about summary refs log tree commit
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2018-04-10 16:28:20 +0900
committerJunio C Hamano <gitster@pobox.com>2018-04-10 16:28:20 +0900
commit0873c393c750d32a111ee66ab4ca4d7d21bee0ba (patch)
treea84c74dc4b8084446000913ffe254b33e92dc155
parent62c0fd46a875050e904831a73ef4375ed26cfaf6 (diff)
parent00a3da2a131a3e122df7e053d992fbc1735bf4f9 (diff)
downloadgit-0873c393c750d32a111ee66ab4ca4d7d21bee0ba.tar.gz
Code clean-up for the "repository" abstraction.

* nd/remove-ignore-env-field:
  repository.h: add comment and clarify repo_set_gitdir
  repository: delete ignore_env member
  sha1_file.c: move delayed getenv(altdb) back to setup_git_env()
  repository.c: delete dead functions
  repository.c: move env-related setup code back to environment.c
  repository: initialize the_repository in main()
-rw-r--r--cache.h2
-rw-r--r--common-main.c2
-rw-r--r--environment.c31
-rw-r--r--repository.c92
-rw-r--r--repository.h30
-rw-r--r--setup.c3
-rw-r--r--sha1_file.c6
7 files changed, 101 insertions, 65 deletions
diff --git a/cache.h b/cache.h
index 83ba2d2b03..6e45c1b537 100644
--- a/cache.h
+++ b/cache.h
@@ -459,7 +459,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/common-main.c b/common-main.c
index 6a689007e7..7d716d5a54 100644
--- a/common-main.c
+++ b/common-main.c
@@ -34,6 +34,8 @@ int main(int argc, const char **argv)
 
         git_setup_gettext();
 
+        initialize_the_repository();
+
         attr_start();
 
         git_extract_argv0_path(argv[0]);
diff --git a/environment.c b/environment.c
index d6dd64662c..21565c3c52 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,35 @@ 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);
+        args.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_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 +326,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 4ffbe9bc94..62f52f47fc 100644
--- a/repository.c
+++ b/repository.c
@@ -4,64 +4,68 @@
 #include "submodule-config.h"
 
 /* The main repository */
-static struct repository the_repo = {
-        NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &the_index, &hash_algos[GIT_HASH_SHA1], 0, 0
-};
-struct repository *the_repository = &the_repo;
+static struct repository the_repo;
+struct repository *the_repository;
 
-static char *git_path_from_env(const char *envvar, const char *git_dir,
-                               const char *path, int fromenv)
+void initialize_the_repository(void)
 {
-        if (fromenv) {
-                const char *value = getenv(envvar);
-                if (value)
-                        return xstrdup(value);
-        }
+        the_repository = &the_repo;
 
-        return xstrfmt("%s/%s", git_dir, path);
+        the_repo.index = &the_index;
+        repo_set_hash_algo(&the_repo, GIT_HASH_SHA1);
 }
 
-static int find_common_dir(struct strbuf *sb, const char *gitdir, int fromenv)
+static void expand_base_dir(char **out, const char *in,
+                            const char *base_dir, const char *def_in)
 {
-        if (fromenv) {
-                const char *value = getenv(GIT_COMMON_DIR_ENVIRONMENT);
-                if (value) {
-                        strbuf_addstr(sb, value);
-                        return 1;
-                }
-        }
-
-        return get_common_dir_noenv(sb, gitdir);
+        free(*out);
+        if (in)
+                *out = xstrdup(in);
+        else
+                *out = xstrfmt("%s/%s", base_dir, def_in);
 }
 
-static void repo_setup_env(struct repository *repo)
+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");
+        free(repo->alternate_db);
+        repo->alternate_db = xstrdup_or_null(o->alternate_db);
+        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)
@@ -79,6 +83,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) {
@@ -93,7 +98,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);
@@ -128,13 +133,13 @@ static int read_and_verify_repository_format(struct repository_format *format,
  * Initialize 'repo' based on the provided 'gitdir'.
  * Return 0 upon success and a non-zero value upon failure.
  */
-int repo_init(struct repository *repo, const char *gitdir, const char *worktree)
+static int repo_init(struct repository *repo,
+                     const char *gitdir,
+                     const char *worktree)
 {
         struct repository_format format;
         memset(repo, 0, sizeof(*repo));
 
-        repo->ignore_env = 1;
-
         if (repo_init_gitdir(repo, gitdir))
                 goto error;
 
@@ -210,6 +215,7 @@ void repo_clear(struct repository *repo)
         FREE_AND_NULL(repo->gitdir);
         FREE_AND_NULL(repo->commondir);
         FREE_AND_NULL(repo->objectdir);
+        FREE_AND_NULL(repo->alternate_db);
         FREE_AND_NULL(repo->graft_file);
         FREE_AND_NULL(repo->index_file);
         FREE_AND_NULL(repo->worktree);
diff --git a/repository.h b/repository.h
index 0329e40c7f..f21fd93f72 100644
--- a/repository.h
+++ b/repository.h
@@ -26,6 +26,9 @@ struct repository {
          */
         char *objectdir;
 
+        /* Path to extra alternate object database if not NULL */
+        char *alternate_db;
+
         /*
          * Path to the repository's graft file.
          * Cannot be NULL after initialization.
@@ -72,15 +75,6 @@ struct repository {
         const struct git_hash_algo *hash_algo;
 
         /* Configurations */
-        /*
-         * Bit used during initialization to indicate if repository state (like
-         * the location of the 'objectdir') should be read from the
-         * environment.  By default this bit will be set at the begining of
-         * 'repo_init()' so that all repositories will ignore the environment.
-         * The exception to this is 'the_repository', which doesn't go through
-         * the normal 'repo_init()' process.
-         */
-        unsigned ignore_env:1;
 
         /* Indicate if a repository has a different 'commondir' from 'gitdir' */
         unsigned different_commondir:1;
@@ -88,10 +82,24 @@ struct repository {
 
 extern struct repository *the_repository;
 
-extern void repo_set_gitdir(struct repository *repo, const char *path);
+/*
+ * Define a custom repository layout. Any field can be NULL, which
+ * will default back to the path according to the default layout.
+ */
+struct set_gitdir_args {
+        const char *commondir;
+        const char *object_dir;
+        const char *graft_file;
+        const char *index_file;
+        const char *alternate_db;
+};
+
+extern void repo_set_gitdir(struct repository *repo,
+                            const char *root,
+                            const struct set_gitdir_args *extra_args);
 extern void repo_set_worktree(struct repository *repo, const char *path);
 extern void repo_set_hash_algo(struct repository *repo, int algo);
-extern int repo_init(struct repository *repo, const char *gitdir, const char *worktree);
+extern void initialize_the_repository(void);
 extern int repo_submodule_init(struct repository *submodule,
                                struct repository *superproject,
                                const char *path);
diff --git a/setup.c b/setup.c
index 7287779642..664453fcef 100644
--- a/setup.c
+++ b/setup.c
@@ -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);
diff --git a/sha1_file.c b/sha1_file.c
index 1c61d9d927..aea9124a78 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -668,15 +668,11 @@ int foreach_alt_odb(alt_odb_fn fn, void *cb)
 
 void prepare_alt_odb(void)
 {
-        const char *alt;
-
         if (alt_odb_tail)
                 return;
 
-        alt = getenv(ALTERNATE_DB_ENVIRONMENT);
-
         alt_odb_tail = &alt_odb_list;
-        link_alt_odb_entries(alt, PATH_SEP, NULL, 0);
+        link_alt_odb_entries(the_repository->alternate_db, PATH_SEP, NULL, 0);
 
         read_info_alternates(get_object_directory(), 0);
 }