diff options
Diffstat (limited to 'repository.c')
-rw-r--r-- | repository.c | 147 |
1 files changed, 85 insertions, 62 deletions
diff --git a/repository.c b/repository.c index edca907404..7b02e1dffa 100644 --- a/repository.c +++ b/repository.c @@ -1,65 +1,87 @@ #include "cache.h" #include "repository.h" +#include "object-store.h" #include "config.h" +#include "object.h" #include "submodule-config.h" /* The main repository */ static struct repository the_repo; -struct repository *the_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; + + the_repo.index = &the_index; + the_repo.objects = raw_object_store_new(); + the_repo.parsed_objects = parsed_object_pool_new(); - return xstrfmt("%s/%s", git_dir, path); + 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); - repo->objectdir = git_path_from_env(DB_ENVIRONMENT, repo->commondir, - "objects", !repo->ignore_env); - repo->graft_file = git_path_from_env(GRAFT_ENVIRONMENT, repo->commondir, - "info/grafts", !repo->ignore_env); - 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); /* - * NEEDSWORK: Eventually we want to be able to free gitdir and the rest - * of the environment before reinitializing it again, but we have some - * crazy code paths where we try to set gitdir with the current gitdir - * and we don't want to free gitdir before copying the passed in value. + * 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. */ - repo->gitdir = xstrdup(gitfile ? gitfile : path); + char *old_gitdir = repo->gitdir; + + repo->gitdir = xstrdup(gitfile ? gitfile : root); + free(old_gitdir); - repo_setup_env(repo); + repo_set_commondir(repo, o->commondir); + + if (!repo->objects->odb) { + repo->objects->odb = xcalloc(1, sizeof(*repo->objects->odb)); + repo->objects->odb_tail = &repo->objects->odb->next; + } + expand_base_dir(&repo->objects->odb->path, o->object_dir, + repo->commondir, "objects"); + + free(repo->objects->alternate_db); + repo->objects->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) +{ + repo->hash_algo = &hash_algos[hash_algo]; } /* @@ -72,6 +94,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) { @@ -86,7 +109,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); @@ -121,12 +144,15 @@ 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) +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; + repo->objects = raw_object_store_new(); + repo->parsed_objects = parsed_object_pool_new(); if (repo_init_gitdir(repo, gitdir)) goto error; @@ -134,6 +160,8 @@ int repo_init(struct repository *repo, const char *gitdir, const char *worktree) if (read_and_verify_repository_format(&format, repo->commondir)) goto error; + repo_set_hash_algo(repo, format.hash_algo); + if (worktree) repo_set_worktree(repo, worktree); @@ -158,7 +186,7 @@ int repo_submodule_init(struct repository *submodule, struct strbuf worktree = STRBUF_INIT; int ret = 0; - sub = submodule_from_cache(superproject, null_sha1, path); + sub = submodule_from_path(superproject, &null_oid, path); if (!sub) { ret = -1; goto out; @@ -198,25 +226,22 @@ out: void repo_clear(struct repository *repo) { - free(repo->gitdir); - repo->gitdir = NULL; - free(repo->commondir); - repo->commondir = NULL; - free(repo->objectdir); - repo->objectdir = NULL; - free(repo->graft_file); - repo->graft_file = NULL; - free(repo->index_file); - repo->index_file = NULL; - free(repo->worktree); - repo->worktree = NULL; - free(repo->submodule_prefix); - repo->submodule_prefix = NULL; + FREE_AND_NULL(repo->gitdir); + FREE_AND_NULL(repo->commondir); + FREE_AND_NULL(repo->graft_file); + FREE_AND_NULL(repo->index_file); + FREE_AND_NULL(repo->worktree); + FREE_AND_NULL(repo->submodule_prefix); + + raw_object_store_clear(repo->objects); + FREE_AND_NULL(repo->objects); + + parsed_object_pool_clear(repo->parsed_objects); + FREE_AND_NULL(repo->parsed_objects); if (repo->config) { git_configset_clear(repo->config); - free(repo->config); - repo->config = NULL; + FREE_AND_NULL(repo->config); } if (repo->submodule_cache) { @@ -226,8 +251,8 @@ void repo_clear(struct repository *repo) if (repo->index) { discard_index(repo->index); - free(repo->index); - repo->index = NULL; + if (repo->index != &the_index) + FREE_AND_NULL(repo->index); } } @@ -235,8 +260,6 @@ int repo_read_index(struct repository *repo) { if (!repo->index) repo->index = xcalloc(1, sizeof(*repo->index)); - else - discard_index(repo->index); - return read_index_from(repo->index, repo->index_file); + return read_index_from(repo->index, repo->index_file, repo->gitdir); } |