unset_git_directory() can only clean up things as long as set_git_dir() has not been called because set_git_dir() keeps internal state itself. Even worse, set_git_dir() may override $GIT_DIR env variable. All those are now handled by unset_git_env(). Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- cache.h | 1 + environment.c | 20 ++++++++++++++++++++ git.c | 11 +++++------ setup.c | 2 ++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/cache.h b/cache.h index dd27e11..bd9df24 100644 --- a/cache.h +++ b/cache.h @@ -419,6 +419,7 @@ extern void setup_work_tree(void); extern const char *setup_git_directory_gently(int *); extern const char *setup_git_directory(void); extern void unset_git_directory(const char *prefix); +extern void unset_git_env(); extern const char *prefix_path(const char *prefix, int len, const char *path); extern const char *prefix_filename(const char *prefix, int len, const char *path); extern int check_filename(const char *prefix, const char *name); diff --git a/environment.c b/environment.c index c36c902..6127025 100644 --- a/environment.c +++ b/environment.c @@ -62,6 +62,7 @@ char *git_work_tree_cfg; static char *work_tree; static const char *git_dir; +static const char *original_git_dir; static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file; /* @@ -81,6 +82,20 @@ const char * const local_repo_env[LOCAL_REPO_ENV_SIZE + 1] = { NULL }; +void unset_git_env(void) +{ + git_dir = NULL; + if (original_git_dir) + setenv(GIT_DIR_ENVIRONMENT, original_git_dir, 1); + else + unsetenv(GIT_DIR_ENVIRONMENT); + git_object_dir = NULL; + git_refs_dir = NULL; + git_index_file = NULL; + git_graft_file = NULL; + read_replace_refs = 1; +} + static void setup_git_env(void) { git_dir = getenv(GIT_DIR_ENVIRONMENT); @@ -184,6 +199,11 @@ char *get_graft_file(void) int set_git_dir(const char *path) { + static int original_git_dir_set = 0; + if (!original_git_dir_set) { + original_git_dir = getenv(GIT_DIR_ENVIRONMENT); + original_git_dir_set = 1; + } if (setenv(GIT_DIR_ENVIRONMENT, path, 1)) return error("Could not set GIT_DIR to '%s'", path); setup_git_env(); diff --git a/git.c b/git.c index 746470f..6a40304 100644 --- a/git.c +++ b/git.c @@ -146,14 +146,13 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) static int handle_alias(int *argcp, const char ***argv) { int envchanged = 0, ret = 0, saved_errno = errno; - const char *subdir; int count, option_count; const char **new_argv; const char *alias_command; char *alias_string; int unused_nongit; - subdir = setup_git_directory_gently(&unused_nongit); + setup_git_directory_gently(&unused_nongit); alias_command = (*argv)[0]; alias_string = alias_lookup(alias_command); @@ -210,8 +209,7 @@ static int handle_alias(int *argcp, const char ***argv) ret = 1; } - if (subdir && chdir(subdir)) - die_errno("Cannot change to '%s'", subdir); + unset_git_directory(startup_info->prefix); errno = saved_errno; @@ -240,8 +238,6 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) int status, help; struct stat st; - memset(&git_startup_info, 0, sizeof(git_startup_info)); - startup_info = &git_startup_info; help = argc == 2 && !strcmp(argv[1], "-h"); if (!help) { if (p->option & RUN_SETUP) @@ -486,6 +482,9 @@ int main(int argc, const char **argv) { const char *cmd; + memset(&git_startup_info, 0, sizeof(git_startup_info)); + startup_info = &git_startup_info; + cmd = git_extract_argv0_path(argv[0]); if (!cmd) cmd = "git-help"; diff --git a/setup.c b/setup.c index 2f850ab..3264187 100644 --- a/setup.c +++ b/setup.c @@ -329,6 +329,8 @@ void unset_git_directory(const char *prefix) die("Cannot change to '%s'", prefix); if (startup_info) { + if (startup_info->have_repository) + unset_git_env(); startup_info->prefix = NULL; startup_info->have_repository = 0; } -- 1.7.0.1.384.g6abcaa -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html