git potty: restore environments after alias expansion
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 <dturner@twopensource.com> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Nguyễn Thái Ngọc Duy committed
Jun 8, 2014 at 16:37 UTC
c0562611c525bb3c564b79c345fc7e4f9e799e54
2 files changed
+51
-6
git.c
+49
-4
@@ -20,6 +20,43 @@ const char git_more_info_string[] =
20
21
static struct startup_info git_startup_info;
22
static int use_pager = -1;
23
+static char orig_cwd[PATH_MAX];
24
+static const char *env_names[] = {
25
+ GIT_DIR_ENVIRONMENT,
26
+ GIT_WORK_TREE_ENVIRONMENT,
27
+ GIT_IMPLICIT_WORK_TREE_ENVIRONMENT,
28
+ GIT_PREFIX_ENVIRONMENT
29
+};
30
+static char *orig_env[4];
31
+static int saved_environment;
32
+
33
+static void save_env(void)
34
+{
35
+ int i;
36
+ if (saved_environment)
37
+ return;
38
+ saved_environment = 1;
39
+ if (!getcwd(orig_cwd, sizeof(orig_cwd)))
40
+ die_errno("cannot getcwd");
41
+ for (i = 0; i < ARRAY_SIZE(env_names); i++) {
42
+ orig_env[i] = getenv(env_names[i]);
43
+ if (orig_env[i])
44
+ orig_env[i] = xstrdup(orig_env[i]);
45
+ }
46
+}
47
+
48
+static void restore_env(void)
49
+{
50
+ int i;
51
+ if (*orig_cwd && chdir(orig_cwd))
52
+ die_errno("could not move to %s", orig_cwd);
53
+ for (i = 0; i < ARRAY_SIZE(env_names); i++) {
54
+ if (orig_env[i])
55
+ setenv(env_names[i], orig_env[i], 1);
56
+ else
57
+ unsetenv(env_names[i]);
58
+ }
59
+}
60
61
static void commit_pager_choice(void) {
62
switch (use_pager) {
@@ -272,6 +309,7 @@ static int handle_alias(int *argcp, const char ***argv)
309
* RUN_SETUP for reading from the configuration file.
310
*/
311
#define NEED_WORK_TREE (1<<3)
312
+#define NO_SETUP (1<<4)
313
314
struct cmd_struct {
315
const char *cmd;
@@ -352,7 +390,7 @@ static struct cmd_struct commands[] = {
390
{ "cherry", cmd_cherry, RUN_SETUP },
391
{ "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },
392
{ "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE },
355
- { "clone", cmd_clone },
393
+ { "clone", cmd_clone, NO_SETUP },
394
{ "column", cmd_column, RUN_SETUP_GENTLY },
395
{ "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE },
396
{ "commit-tree", cmd_commit_tree, RUN_SETUP },
@@ -378,8 +416,8 @@ static struct cmd_struct commands[] = {
416
{ "hash-object", cmd_hash_object },
417
{ "help", cmd_help },
418
{ "index-pack", cmd_index_pack, RUN_SETUP_GENTLY },
381
- { "init", cmd_init_db },
382
- { "init-db", cmd_init_db },
419
+ { "init", cmd_init_db, NO_SETUP },
420
+ { "init-db", cmd_init_db, NO_SETUP },
421
{ "log", cmd_log, RUN_SETUP },
422
{ "ls-files", cmd_ls_files, RUN_SETUP },
423
{ "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
@@ -484,6 +522,10 @@ static void handle_builtin(int argc, const char **argv)
522
struct cmd_struct *p = commands+i;
523
if (strcmp(p->cmd, cmd))
524
continue;
525
+ if (saved_environment && (p->option & NO_SETUP)) {
526
+ restore_env();
527
+ break;
528
+ }
529
exit(run_builtin(p, argc, argv));
530
}
531
}
@@ -539,7 +581,10 @@ static int run_argv(int *argcp, const char ***argv)
581
* of overriding "git log" with "git show" by having
582
* alias.log = show
583
*/
542
- if (done_alias || !handle_alias(argcp, argv))
584
+ if (done_alias)
585
+ break;
586
+ save_env();
587
+ if (!handle_alias(argcp, argv))
588
break;
589
done_alias = 1;
590
}
t/t0001-init.sh
+2
-2
@@ -56,7 +56,7 @@ test_expect_success 'plain through aliased command, outside any git repo' '
56
check_config plain-aliased/.git false unset
57
'
58
59
-test_expect_failure 'plain nested through aliased command' '
59
+test_expect_success 'plain nested through aliased command' '
60
(
61
git init plain-ancestor-aliased &&
62
cd plain-ancestor-aliased &&
@@ -68,7 +68,7 @@ test_expect_failure 'plain nested through aliased command' '
68
check_config plain-ancestor-aliased/plain-nested/.git false unset
69
'
70
71
-test_expect_failure 'plain nested in bare through aliased command' '
71
+test_expect_success 'plain nested in bare through aliased command' '
72
(
73
git init --bare bare-ancestor-aliased.git &&
74
cd bare-ancestor-aliased.git &&