Skip to content

Commit a9bcf65

Browse files
dschogitster
authored andcommitted
alias: use the early config machinery to expand aliases
Instead of discovering the .git/ directory, reading the config and then trying to painstakingly reset all the global state if we did not find a matching alias, let's use the early config machinery instead. It may look like unnecessary work to discover the .git/ directory in the early config machinery and then call setup_git_directory_gently() in the case of a shell alias, repeating the very same discovery *again*. However, we have to do this as the early config machinery takes pains *not* to touch any global state, while shell aliases expect a possibly changed working directory and at least the GIT_PREFIX and GIT_DIR variables to be set. This change also fixes a known issue where Git tried to read the pager config from an incorrect path in a subdirectory of a Git worktree if an alias expanded to a shell command. Signed-off-by: Johannes Schindelin <[email protected]> Reviewed-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 3f9c5df commit a9bcf65

File tree

3 files changed

+26
-59
lines changed

3 files changed

+26
-59
lines changed

alias.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,28 @@
11
#include "cache.h"
22

3+
struct config_alias_data {
4+
const char *alias;
5+
char *v;
6+
};
7+
8+
static int config_alias_cb(const char *key, const char *value, void *d)
9+
{
10+
struct config_alias_data *data = d;
11+
const char *p;
12+
13+
if (skip_prefix(key, "alias.", &p) && !strcmp(p, data->alias))
14+
return git_config_string((const char **)&data->v, key, value);
15+
16+
return 0;
17+
}
18+
319
char *alias_lookup(const char *alias)
420
{
5-
char *v = NULL;
6-
struct strbuf key = STRBUF_INIT;
7-
strbuf_addf(&key, "alias.%s", alias);
8-
if (git_config_key_is_valid(key.buf))
9-
git_config_get_string(key.buf, &v);
10-
strbuf_release(&key);
11-
return v;
21+
struct config_alias_data data = { alias, NULL };
22+
23+
read_early_config(config_alias_cb, &data);
24+
25+
return data.v;
1226
}
1327

1428
#define SPLIT_CMDLINE_BAD_ENDING 1

git.c

Lines changed: 4 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -16,50 +16,6 @@ const char git_more_info_string[] =
1616
"to read about a specific subcommand or concept.");
1717

1818
static int use_pager = -1;
19-
static char *orig_cwd;
20-
static const char *env_names[] = {
21-
GIT_DIR_ENVIRONMENT,
22-
GIT_WORK_TREE_ENVIRONMENT,
23-
GIT_IMPLICIT_WORK_TREE_ENVIRONMENT,
24-
GIT_PREFIX_ENVIRONMENT
25-
};
26-
static char *orig_env[4];
27-
static int save_restore_env_balance;
28-
29-
static void save_env_before_alias(void)
30-
{
31-
int i;
32-
33-
assert(save_restore_env_balance == 0);
34-
save_restore_env_balance = 1;
35-
orig_cwd = xgetcwd();
36-
for (i = 0; i < ARRAY_SIZE(env_names); i++) {
37-
orig_env[i] = getenv(env_names[i]);
38-
orig_env[i] = xstrdup_or_null(orig_env[i]);
39-
}
40-
}
41-
42-
static void restore_env(int external_alias)
43-
{
44-
int i;
45-
46-
assert(save_restore_env_balance == 1);
47-
save_restore_env_balance = 0;
48-
if (!external_alias && orig_cwd && chdir(orig_cwd))
49-
die_errno("could not move to %s", orig_cwd);
50-
free(orig_cwd);
51-
for (i = 0; i < ARRAY_SIZE(env_names); i++) {
52-
if (external_alias &&
53-
!strcmp(env_names[i], GIT_PREFIX_ENVIRONMENT))
54-
continue;
55-
if (orig_env[i]) {
56-
setenv(env_names[i], orig_env[i], 1);
57-
free(orig_env[i]);
58-
} else {
59-
unsetenv(env_names[i]);
60-
}
61-
}
62-
}
6319

6420
static void commit_pager_choice(void) {
6521
switch (use_pager) {
@@ -250,19 +206,18 @@ static int handle_alias(int *argcp, const char ***argv)
250206
const char **new_argv;
251207
const char *alias_command;
252208
char *alias_string;
253-
int unused_nongit;
254-
255-
save_env_before_alias();
256-
setup_git_directory_gently(&unused_nongit);
257209

258210
alias_command = (*argv)[0];
259211
alias_string = alias_lookup(alias_command);
260212
if (alias_string) {
261213
if (alias_string[0] == '!') {
262214
struct child_process child = CHILD_PROCESS_INIT;
215+
int nongit_ok;
216+
217+
/* Aliases expect GIT_PREFIX, GIT_DIR etc to be set */
218+
setup_git_directory_gently(&nongit_ok);
263219

264220
commit_pager_choice();
265-
restore_env(1);
266221

267222
child.use_shell = 1;
268223
argv_array_push(&child.args, alias_string + 1);
@@ -308,8 +263,6 @@ static int handle_alias(int *argcp, const char ***argv)
308263
ret = 1;
309264
}
310265

311-
restore_env(0);
312-
313266
errno = saved_errno;
314267

315268
return ret;

t/t7006-pager.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ test_expect_success TTY 'core.pager in repo config works and retains cwd' '
391391
)
392392
'
393393

394-
test_expect_failure TTY 'core.pager is found via alias in subdirectory' '
394+
test_expect_success TTY 'core.pager is found via alias in subdirectory' '
395395
sane_unset GIT_PAGER &&
396396
test_config core.pager "cat >via-alias" &&
397397
(

0 commit comments

Comments
 (0)