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 <johannes.schindelin@gmx.de> Reviewed-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
3f9c5dfb71
commit
a9bcf6586d
28
alias.c
28
alias.c
@ -1,14 +1,28 @@
|
||||
#include "cache.h"
|
||||
|
||||
struct config_alias_data {
|
||||
const char *alias;
|
||||
char *v;
|
||||
};
|
||||
|
||||
static int config_alias_cb(const char *key, const char *value, void *d)
|
||||
{
|
||||
struct config_alias_data *data = d;
|
||||
const char *p;
|
||||
|
||||
if (skip_prefix(key, "alias.", &p) && !strcmp(p, data->alias))
|
||||
return git_config_string((const char **)&data->v, key, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *alias_lookup(const char *alias)
|
||||
{
|
||||
char *v = NULL;
|
||||
struct strbuf key = STRBUF_INIT;
|
||||
strbuf_addf(&key, "alias.%s", alias);
|
||||
if (git_config_key_is_valid(key.buf))
|
||||
git_config_get_string(key.buf, &v);
|
||||
strbuf_release(&key);
|
||||
return v;
|
||||
struct config_alias_data data = { alias, NULL };
|
||||
|
||||
read_early_config(config_alias_cb, &data);
|
||||
|
||||
return data.v;
|
||||
}
|
||||
|
||||
#define SPLIT_CMDLINE_BAD_ENDING 1
|
||||
|
55
git.c
55
git.c
@ -16,50 +16,6 @@ const char git_more_info_string[] =
|
||||
"to read about a specific subcommand or concept.");
|
||||
|
||||
static int use_pager = -1;
|
||||
static char *orig_cwd;
|
||||
static const char *env_names[] = {
|
||||
GIT_DIR_ENVIRONMENT,
|
||||
GIT_WORK_TREE_ENVIRONMENT,
|
||||
GIT_IMPLICIT_WORK_TREE_ENVIRONMENT,
|
||||
GIT_PREFIX_ENVIRONMENT
|
||||
};
|
||||
static char *orig_env[4];
|
||||
static int save_restore_env_balance;
|
||||
|
||||
static void save_env_before_alias(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(save_restore_env_balance == 0);
|
||||
save_restore_env_balance = 1;
|
||||
orig_cwd = xgetcwd();
|
||||
for (i = 0; i < ARRAY_SIZE(env_names); i++) {
|
||||
orig_env[i] = getenv(env_names[i]);
|
||||
orig_env[i] = xstrdup_or_null(orig_env[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void restore_env(int external_alias)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(save_restore_env_balance == 1);
|
||||
save_restore_env_balance = 0;
|
||||
if (!external_alias && orig_cwd && chdir(orig_cwd))
|
||||
die_errno("could not move to %s", orig_cwd);
|
||||
free(orig_cwd);
|
||||
for (i = 0; i < ARRAY_SIZE(env_names); i++) {
|
||||
if (external_alias &&
|
||||
!strcmp(env_names[i], GIT_PREFIX_ENVIRONMENT))
|
||||
continue;
|
||||
if (orig_env[i]) {
|
||||
setenv(env_names[i], orig_env[i], 1);
|
||||
free(orig_env[i]);
|
||||
} else {
|
||||
unsetenv(env_names[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void commit_pager_choice(void) {
|
||||
switch (use_pager) {
|
||||
@ -250,19 +206,18 @@ static int handle_alias(int *argcp, const char ***argv)
|
||||
const char **new_argv;
|
||||
const char *alias_command;
|
||||
char *alias_string;
|
||||
int unused_nongit;
|
||||
|
||||
save_env_before_alias();
|
||||
setup_git_directory_gently(&unused_nongit);
|
||||
|
||||
alias_command = (*argv)[0];
|
||||
alias_string = alias_lookup(alias_command);
|
||||
if (alias_string) {
|
||||
if (alias_string[0] == '!') {
|
||||
struct child_process child = CHILD_PROCESS_INIT;
|
||||
int nongit_ok;
|
||||
|
||||
/* Aliases expect GIT_PREFIX, GIT_DIR etc to be set */
|
||||
setup_git_directory_gently(&nongit_ok);
|
||||
|
||||
commit_pager_choice();
|
||||
restore_env(1);
|
||||
|
||||
child.use_shell = 1;
|
||||
argv_array_push(&child.args, alias_string + 1);
|
||||
@ -308,8 +263,6 @@ static int handle_alias(int *argcp, const char ***argv)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
restore_env(0);
|
||||
|
||||
errno = saved_errno;
|
||||
|
||||
return ret;
|
||||
|
@ -391,7 +391,7 @@ test_expect_success TTY 'core.pager in repo config works and retains cwd' '
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_failure TTY 'core.pager is found via alias in subdirectory' '
|
||||
test_expect_success TTY 'core.pager is found via alias in subdirectory' '
|
||||
sane_unset GIT_PAGER &&
|
||||
test_config core.pager "cat >via-alias" &&
|
||||
(
|
||||
|
Loading…
Reference in New Issue
Block a user