XXX bare repos probably not worth supporting.. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- cache.h | 1 + environment.c | 19 ++++++++++++++++-- setup.c | 62 +++++++++++++++++++++++++++++++++++++++-------------------- trace.c | 1 + 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/cache.h b/cache.h index f85ee70..4c09223 100644 --- a/cache.h +++ b/cache.h @@ -406,6 +406,7 @@ extern char *get_object_directory(void); extern char *get_index_file(void); extern char *get_graft_file(void); extern int set_git_dir(const char *path); +extern int set_git_dir_super(const char *path, const char *super); extern const char *get_git_namespace(void); extern const char *strip_namespace(const char *namespaced_ref); extern const char *get_git_work_tree(void); diff --git a/environment.c b/environment.c index d5ae7a3..8152c7e 100644 --- a/environment.c +++ b/environment.c @@ -125,13 +125,17 @@ static char *expand_namespace(const char *raw_namespace) static void setup_git_env(void) { const char *gitfile; + char *super; git_dir = getenv(GIT_DIR_ENVIRONMENT); if (!git_dir) git_dir = DEFAULT_GIT_DIR_ENVIRONMENT; - gitfile = read_gitfile(git_dir); + gitfile = read_gitfile_super(git_dir, &super); git_dir = xstrdup(gitfile ? gitfile : git_dir); - git_super_dir = getenv(GIT_SUPER_DIR_ENVIRONMENT); + if (super) + git_super_dir = xstrdup(super); + else + git_super_dir = getenv(GIT_SUPER_DIR_ENVIRONMENT); git_object_dir = getenv(DB_ENVIRONMENT); if (!git_object_dir) { git_object_dir = xmalloc(strlen(git_dir) + 9); @@ -280,6 +284,17 @@ int set_git_dir(const char *path) return 0; } +int set_git_dir_super(const char *path, const char *super) +{ + if (super != path && + setenv(GIT_SUPER_DIR_ENVIRONMENT, super, 1)) + return error("Could not set GIT_SUPER_DIR to '%s'", super); + if (setenv(GIT_DIR_ENVIRONMENT, path, 1)) + return error("Could not set GIT_DIR to '%s'", path); + setup_git_env(); + return 0; +} + const char *get_log_output_encoding(void) { return git_log_output_encoding ? git_log_output_encoding diff --git a/setup.c b/setup.c index dfe9d08..f22381e 100644 --- a/setup.c +++ b/setup.c @@ -255,7 +255,8 @@ void setup_work_tree(void) if (getenv(GIT_WORK_TREE_ENVIRONMENT)) setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1); - set_git_dir(remove_leading_path(git_dir, work_tree)); + set_git_dir_super(remove_leading_path(git_dir, work_tree), + get_git_super_dir()); initialized = 1; } @@ -368,24 +369,28 @@ const char *read_gitfile(const char *path) static const char *setup_explicit_git_dir(const char *gitdirenv, + const char *super_, char *cwd, int len, int *nongit_ok) { const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT); const char *worktree; - char *gitfile; + char *gitfile, *super = (char *)super_; int offset; if (PATH_MAX - 40 < strlen(gitdirenv)) die("'$%s' too big", GIT_DIR_ENVIRONMENT); - gitfile = (char*)read_gitfile(gitdirenv); + gitfile = (char*)read_gitfile_super(gitdirenv, !super ? &super : NULL); if (gitfile) { gitfile = xstrdup(gitfile); gitdirenv = gitfile; - } + if (!super) + super = gitfile; + } else if (!super) + super = (char *)gitdirenv; - if (!is_git_directory(gitdirenv)) { + if (!is_git_directory_super(gitdirenv, super)) { if (nongit_ok) { *nongit_ok = 1; goto done_null; @@ -393,7 +398,7 @@ static const char *setup_explicit_git_dir(const char *gitdirenv, die("Not a git repository: '%s'", gitdirenv); } - if (check_repository_format_gently(gitdirenv, nongit_ok)) + if (check_repository_format_gently(super, nongit_ok)) goto done_null; /* #3, #7, #11, #15, #19, #23, #27, #31 (see t1510) */ @@ -404,7 +409,7 @@ static const char *setup_explicit_git_dir(const char *gitdirenv, die("core.bare and core.worktree do not make sense"); /* #18, #26 */ - set_git_dir(gitdirenv); + set_git_dir_super(gitdirenv, super); goto done_null; } else if (git_work_tree_cfg) { /* #6, #14 */ @@ -425,7 +430,7 @@ static const char *setup_explicit_git_dir(const char *gitdirenv, } else if (!git_env_bool(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, 1)) { /* #16d */ - set_git_dir(gitdirenv); + set_git_dir_super(gitdirenv, super); goto done_null; } else /* #2, #10 */ @@ -436,34 +441,39 @@ static const char *setup_explicit_git_dir(const char *gitdirenv, /* both get_git_work_tree() and cwd are already normalized */ if (!strcmp(cwd, worktree)) { /* cwd == worktree */ - set_git_dir(gitdirenv); + set_git_dir_super(gitdirenv, super); goto done_null; } offset = dir_inside_of(cwd, worktree); if (offset >= 0) { /* cwd inside worktree? */ - set_git_dir(real_path(gitdirenv)); + set_git_dir_super(real_path(gitdirenv), super); if (chdir(worktree)) die_errno("Could not chdir to '%s'", worktree); cwd[len++] = '/'; cwd[len] = '\0'; free(gitfile); + if (super != gitdirenv && super != super_) + free(super); return cwd + offset; } /* cwd outside worktree */ - set_git_dir(gitdirenv); + set_git_dir_super(gitdirenv, super); done_null: free(gitfile); + if (super != gitdirenv && super != super_) + free(super); return NULL; } static const char *setup_discovered_git_dir(const char *gitdir, + const char *super, char *cwd, int offset, int len, int *nongit_ok) { - if (check_repository_format_gently(gitdir, nongit_ok)) + if (check_repository_format_gently(super, nongit_ok)) return NULL; /* --work-tree is set without --git-dir; use discovered one */ @@ -472,7 +482,7 @@ static const char *setup_discovered_git_dir(const char *gitdir, gitdir = xstrdup(real_path(gitdir)); if (chdir(cwd)) die_errno("Could not come back to cwd"); - return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok); + return setup_explicit_git_dir(gitdir, super, cwd, len, nongit_ok); } /* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */ @@ -486,7 +496,7 @@ static const char *setup_discovered_git_dir(const char *gitdir, /* #0, #1, #5, #8, #9, #12, #13 */ set_git_work_tree("."); if (strcmp(gitdir, DEFAULT_GIT_DIR_ENVIRONMENT)) - set_git_dir(gitdir); + set_git_dir_super(gitdir, super); inside_git_dir = 0; inside_work_tree = 1; if (offset == len) @@ -516,7 +526,7 @@ static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongi gitdir = offset == len ? "." : xmemdupz(cwd, offset); if (chdir(cwd)) die_errno("Could not come back to cwd"); - return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok); + return setup_explicit_git_dir(gitdir, NULL, cwd, len, nongit_ok); } inside_git_dir = 1; @@ -596,7 +606,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok) struct string_list ceiling_dirs = STRING_LIST_INIT_DUP; static char cwd[PATH_MAX + 1]; const char *gitdirenv, *ret; - char *gitfile; + char *gitfile, *super; int len, offset, offset_parent, ceil_offset = -1; dev_t current_device = 0; int one_filesystem = 1; @@ -620,7 +630,9 @@ static const char *setup_git_directory_gently_1(int *nongit_ok) */ gitdirenv = getenv(GIT_DIR_ENVIRONMENT); if (gitdirenv) - return setup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok); + return setup_explicit_git_dir(gitdirenv, + getenv(GIT_SUPER_DIR_ENVIRONMENT), + cwd, len, nongit_ok); if (env_ceiling_dirs) { int empty_entry_found = 0; @@ -650,21 +662,29 @@ static const char *setup_git_directory_gently_1(int *nongit_ok) if (one_filesystem) current_device = get_device_or_die(".", NULL, 0); for (;;) { - gitfile = (char*)read_gitfile(DEFAULT_GIT_DIR_ENVIRONMENT); - if (gitfile) + gitfile = (char*)read_gitfile_super(DEFAULT_GIT_DIR_ENVIRONMENT, + &super); + if (gitfile) { gitdirenv = gitfile = xstrdup(gitfile); - else { + if (!super) + super = gitfile; + } else { if (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT)) gitdirenv = DEFAULT_GIT_DIR_ENVIRONMENT; + super = (char *)gitdirenv; } if (gitdirenv) { - ret = setup_discovered_git_dir(gitdirenv, + ret = setup_discovered_git_dir(gitdirenv, super, cwd, offset, len, nongit_ok); + if (super != gitdirenv) + free(super); free(gitfile); return ret; } + if (super != gitdirenv) + free(super); free(gitfile); if (is_git_directory(".")) diff --git a/trace.c b/trace.c index 3d744d1..53d800b 100644 --- a/trace.c +++ b/trace.c @@ -173,6 +173,7 @@ void trace_repo_setup(const char *prefix) prefix = "(null)"; trace_printf_key(key, "setup: git_dir: %s\n", quote_crnl(get_git_dir())); + trace_printf_key(key, "setup: git_super_dir: %s\n", quote_crnl(get_git_super_dir())); trace_printf_key(key, "setup: worktree: %s\n", quote_crnl(git_work_tree)); trace_printf_key(key, "setup: cwd: %s\n", quote_crnl(cwd)); trace_printf_key(key, "setup: prefix: %s\n", quote_crnl(prefix)); -- 1.8.5.1.77.g42c48fa -- 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