From c0562611c525bb3c564b79c345fc7e4f9e799e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 8 Jun 2014 16:37:10 +0700 Subject: git potty: restore environments after alias expansion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 4ad8332 (t0001: test git init when run via an alias - 2010-11-26) noted breakages when running init via alias. The problem is for alias to be used, $GIT_DIR must be searched, but 'init' and 'clone' are not happy with that. So we start a new process like an external command, with clean environment in this case. Env variables that are set by command line (e.g. "git --git-dir=.. ") are kept. This should also fix autocorrecting a command typo to "init" because it's the same problem: aliases are read, then "init" is unhappy with $GIT_DIR already set up because of that. Reminded-by: David Turner Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/git.c b/git.c index 9efd1a3..8a19974 100644 --- a/git.c +++ b/git.c @@ -20,6 +20,43 @@ const char git_more_info_string[] = static struct startup_info git_startup_info; static int use_pager = -1; +static char orig_cwd[PATH_MAX]; +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 saved_environment; + +static void save_env(void) +{ + int i; + if (saved_environment) + return; + saved_environment = 1; + if (!getcwd(orig_cwd, sizeof(orig_cwd))) + die_errno("cannot getcwd"); + for (i = 0; i < ARRAY_SIZE(env_names); i++) { + orig_env[i] = getenv(env_names[i]); + if (orig_env[i]) + orig_env[i] = xstrdup(orig_env[i]); + } +} + +static void restore_env(void) +{ + int i; + if (*orig_cwd && chdir(orig_cwd)) + die_errno("could not move to %s", orig_cwd); + for (i = 0; i < ARRAY_SIZE(env_names); i++) { + if (orig_env[i]) + setenv(env_names[i], orig_env[i], 1); + else + unsetenv(env_names[i]); + } +} static void commit_pager_choice(void) { switch (use_pager) { @@ -272,6 +309,7 @@ static int handle_alias(int *argcp, const char ***argv) * RUN_SETUP for reading from the configuration file. */ #define NEED_WORK_TREE (1<<3) +#define NO_SETUP (1<<4) struct cmd_struct { const char *cmd; @@ -352,7 +390,7 @@ static struct cmd_struct commands[] = { { "cherry", cmd_cherry, RUN_SETUP }, { "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE }, { "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE }, - { "clone", cmd_clone }, + { "clone", cmd_clone, NO_SETUP }, { "column", cmd_column, RUN_SETUP_GENTLY }, { "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE }, { "commit-tree", cmd_commit_tree, RUN_SETUP }, @@ -378,8 +416,8 @@ static struct cmd_struct commands[] = { { "hash-object", cmd_hash_object }, { "help", cmd_help }, { "index-pack", cmd_index_pack, RUN_SETUP_GENTLY }, - { "init", cmd_init_db }, - { "init-db", cmd_init_db }, + { "init", cmd_init_db, NO_SETUP }, + { "init-db", cmd_init_db, NO_SETUP }, { "log", cmd_log, RUN_SETUP }, { "ls-files", cmd_ls_files, RUN_SETUP }, { "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY }, @@ -484,6 +522,10 @@ static void handle_builtin(int argc, const char **argv) struct cmd_struct *p = commands+i; if (strcmp(p->cmd, cmd)) continue; + if (saved_environment && (p->option & NO_SETUP)) { + restore_env(); + break; + } exit(run_builtin(p, argc, argv)); } } @@ -539,7 +581,10 @@ static int run_argv(int *argcp, const char ***argv) * of overriding "git log" with "git show" by having * alias.log = show */ - if (done_alias || !handle_alias(argcp, argv)) + if (done_alias) + break; + save_env(); + if (!handle_alias(argcp, argv)) break; done_alias = 1; } diff --git a/t/t0001-init.sh b/t/t0001-init.sh index bbc9cb6..b8c0fff 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -56,7 +56,7 @@ test_expect_success 'plain through aliased command, outside any git repo' ' check_config plain-aliased/.git false unset ' -test_expect_failure 'plain nested through aliased command' ' +test_expect_success 'plain nested through aliased command' ' ( git init plain-ancestor-aliased && cd plain-ancestor-aliased && @@ -68,7 +68,7 @@ test_expect_failure 'plain nested through aliased command' ' check_config plain-ancestor-aliased/plain-nested/.git false unset ' -test_expect_failure 'plain nested in bare through aliased command' ' +test_expect_success 'plain nested in bare through aliased command' ' ( git init --bare bare-ancestor-aliased.git && cd bare-ancestor-aliased.git && -- cgit v0.10.2-6-g49f6