summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 83ba2d2..6e45c1b 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 6a68900..7d716d5 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 d6dd646..21565c3 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 4ffbe9b..62f52f4 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 0329e40..f21fd93 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 7287779..664453f 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 1c61d9d..aea9124 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);
}