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>
			
			
				maint
			
			
		
							parent
							
								
									e156455ea4
								
							
						
					
					
						commit
						c0562611c5
					
				
							
								
								
									
										53
									
								
								git.c
								
								
								
								
							
							
						
						
									
										53
									
								
								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; | ||||
| 	} | ||||
|  |  | |||
|  | @ -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 && | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Nguyễn Thái Ngọc Duy
						Nguyễn Thái Ngọc Duy