diff options
-rw-r--r-- | cache.h | 2 | ||||
-rw-r--r-- | environment.c | 30 | ||||
-rw-r--r-- | repository.c | 58 | ||||
-rw-r--r-- | repository.h | 11 | ||||
-rw-r--r-- | setup.c | 3 |
5 files changed, 79 insertions, 25 deletions
@@ -484,7 +484,7 @@ static inline enum object_type object_type(unsigned int mode) */ extern const char * const local_repo_env[]; -extern void setup_git_env(void); +extern void setup_git_env(const char *git_dir); /* * Returns true iff we have a configured git repository (either via diff --git a/environment.c b/environment.c index de8431e01e..da3f7daa09 100644 --- a/environment.c +++ b/environment.c @@ -13,6 +13,7 @@ #include "refs.h" #include "fmt-merge-msg.h" #include "commit.h" +#include "argv-array.h" int trust_executable_bit = 1; int trust_ctime = 1; @@ -147,10 +148,34 @@ static char *expand_namespace(const char *raw_namespace) return strbuf_detach(&buf, NULL); } -void setup_git_env(void) +/* + * Wrapper of getenv() that returns a strdup value. This value is kept + * in argv to be freed later. + */ +static const char *getenv_safe(struct argv_array *argv, const char *name) +{ + const char *value = getenv(name); + + if (!value) + return NULL; + + argv_array_push(argv, value); + return argv->argv[argv->argc - 1]; +} + +void setup_git_env(const char *git_dir) { const char *shallow_file; const char *replace_ref_base; + struct set_gitdir_args args = { NULL }; + struct argv_array to_free = ARGV_ARRAY_INIT; + + args.commondir = getenv_safe(&to_free, GIT_COMMON_DIR_ENVIRONMENT); + args.object_dir = getenv_safe(&to_free, DB_ENVIRONMENT); + args.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT); + args.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT); + repo_set_gitdir(the_repository, git_dir, &args); + argv_array_clear(&to_free); if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT)) check_replace_refs = 0; @@ -300,8 +325,7 @@ int set_git_dir(const char *path) { if (setenv(GIT_DIR_ENVIRONMENT, path, 1)) return error("Could not set GIT_DIR to '%s'", path); - repo_set_gitdir(the_repository, path); - setup_git_env(); + setup_git_env(path); return 0; } diff --git a/repository.c b/repository.c index 0eddf28fcd..bb53b54b6d 100644 --- a/repository.c +++ b/repository.c @@ -40,34 +40,55 @@ static int find_common_dir(struct strbuf *sb, const char *gitdir, int fromenv) return get_common_dir_noenv(sb, gitdir); } -static void repo_setup_env(struct repository *repo) +static void expand_base_dir(char **out, const char *in, + const char *base_dir, const char *def_in) +{ + free(*out); + if (in) + *out = xstrdup(in); + else + *out = xstrfmt("%s/%s", base_dir, def_in); +} + +static void repo_set_commondir(struct repository *repo, + const char *commondir) { struct strbuf sb = STRBUF_INIT; - repo->different_commondir = find_common_dir(&sb, repo->gitdir, - !repo->ignore_env); free(repo->commondir); + + if (commondir) { + repo->different_commondir = 1; + repo->commondir = xstrdup(commondir); + return; + } + + repo->different_commondir = get_common_dir_noenv(&sb, repo->gitdir); repo->commondir = strbuf_detach(&sb, NULL); - free(repo->objectdir); - repo->objectdir = git_path_from_env(DB_ENVIRONMENT, repo->commondir, - "objects", !repo->ignore_env); - free(repo->graft_file); - repo->graft_file = git_path_from_env(GRAFT_ENVIRONMENT, repo->commondir, - "info/grafts", !repo->ignore_env); - free(repo->index_file); - repo->index_file = git_path_from_env(INDEX_ENVIRONMENT, repo->gitdir, - "index", !repo->ignore_env); } -void repo_set_gitdir(struct repository *repo, const char *path) +void repo_set_gitdir(struct repository *repo, + const char *root, + const struct set_gitdir_args *o) { - const char *gitfile = read_gitfile(path); + const char *gitfile = read_gitfile(root); + /* + * repo->gitdir is saved because the caller could pass "root" + * that also points to repo->gitdir. We want to keep it alive + * until after xstrdup(root). Then we can free it. + */ char *old_gitdir = repo->gitdir; - repo->gitdir = xstrdup(gitfile ? gitfile : path); - repo_setup_env(repo); - + repo->gitdir = xstrdup(gitfile ? gitfile : root); free(old_gitdir); + + repo_set_commondir(repo, o->commondir); + expand_base_dir(&repo->objectdir, o->object_dir, + repo->commondir, "objects"); + expand_base_dir(&repo->graft_file, o->graft_file, + repo->commondir, "info/grafts"); + expand_base_dir(&repo->index_file, o->index_file, + repo->gitdir, "index"); } void repo_set_hash_algo(struct repository *repo, int hash_algo) @@ -85,6 +106,7 @@ static int repo_init_gitdir(struct repository *repo, const char *gitdir) int error = 0; char *abspath = NULL; const char *resolved_gitdir; + struct set_gitdir_args args = { NULL }; abspath = real_pathdup(gitdir, 0); if (!abspath) { @@ -99,7 +121,7 @@ static int repo_init_gitdir(struct repository *repo, const char *gitdir) goto out; } - repo_set_gitdir(repo, resolved_gitdir); + repo_set_gitdir(repo, resolved_gitdir, &args); out: free(abspath); diff --git a/repository.h b/repository.h index 40c1c81bdc..84aeac2825 100644 --- a/repository.h +++ b/repository.h @@ -88,7 +88,16 @@ struct repository { extern struct repository *the_repository; -extern void repo_set_gitdir(struct repository *repo, const char *path); +struct set_gitdir_args { + const char *commondir; + const char *object_dir; + const char *graft_file; + const char *index_file; +}; + +extern void repo_set_gitdir(struct repository *repo, + const char *root, + const struct set_gitdir_args *optional); extern void repo_set_worktree(struct repository *repo, const char *path); extern void repo_set_hash_algo(struct repository *repo, int algo); extern void initialize_the_repository(void); @@ -1116,8 +1116,7 @@ const char *setup_git_directory_gently(int *nongit_ok) const char *gitdir = getenv(GIT_DIR_ENVIRONMENT); if (!gitdir) gitdir = DEFAULT_GIT_DIR_ENVIRONMENT; - repo_set_gitdir(the_repository, gitdir); - setup_git_env(); + setup_git_env(gitdir); } if (startup_info->have_repository) repo_set_hash_algo(the_repository, repo_fmt.hash_algo); |