diff options
Diffstat (limited to 'repository.c')
-rw-r--r-- | repository.c | 165 |
1 files changed, 126 insertions, 39 deletions
diff --git a/repository.c b/repository.c index 6f7f6f0..2118f56 100644 --- a/repository.c +++ b/repository.c @@ -1,30 +1,51 @@ -/* - * not really _using_ the compat macros, just make sure the_index - * declaration matches the definition in this file. - */ -#define USE_THE_INDEX_COMPATIBILITY_MACROS -#include "cache.h" +#include "git-compat-util.h" +#include "abspath.h" #include "repository.h" -#include "object-store.h" +#include "object-store-ll.h" #include "config.h" #include "object.h" #include "lockfile.h" +#include "path.h" +#include "read-cache-ll.h" +#include "remote.h" +#include "setup.h" +#include "loose.h" #include "submodule-config.h" +#include "sparse-index.h" +#include "trace2.h" +#include "promisor-remote.h" /* The main repository */ static struct repository the_repo; -struct repository *the_repository; -struct index_state the_index; +struct repository *the_repository = &the_repo; -void initialize_the_repository(void) +void initialize_repository(struct repository *repo) { - the_repository = &the_repo; - - the_repo.index = &the_index; - the_repo.objects = raw_object_store_new(); - the_repo.parsed_objects = parsed_object_pool_new(); + repo->objects = raw_object_store_new(); + repo->remote_state = remote_state_new(); + repo->parsed_objects = parsed_object_pool_new(); + ALLOC_ARRAY(repo->index, 1); + index_state_init(repo->index, repo); - repo_set_hash_algo(&the_repo, GIT_HASH_SHA1); + /* + * Unfortunately, we need to keep this hack around for the time being: + * + * - Not setting up the hash algorithm for `the_repository` leads to + * crashes because `the_hash_algo` is a macro that expands to + * `the_repository->hash_algo`. So if Git commands try to access + * `the_hash_algo` without a Git directory we crash. + * + * - Setting up the hash algorithm to be SHA1 by default breaks other + * commands when running with SHA256. + * + * This is another point in case why having global state is a bad idea. + * Eventually, we should remove this hack and stop setting the hash + * algorithm in this function altogether. Instead, it should only ever + * be set via our repository setup procedures. But that requires more + * work. + */ + if (repo == the_repository) + repo_set_hash_algo(repo, GIT_HASH_SHA1); } static void expand_base_dir(char **out, const char *in, @@ -72,12 +93,14 @@ void repo_set_gitdir(struct repository *repo, repo_set_commondir(repo, o->commondir); if (!repo->objects->odb) { - repo->objects->odb = xcalloc(1, sizeof(*repo->objects->odb)); + CALLOC_ARRAY(repo->objects->odb, 1); repo->objects->odb_tail = &repo->objects->odb->next; } expand_base_dir(&repo->objects->odb->path, o->object_dir, repo->commondir, "objects"); + repo->objects->odb->disable_ref_updates = o->disable_ref_updates; + free(repo->objects->alternate_db); repo->objects->alternate_db = xstrdup_or_null(o->alternate_db); expand_base_dir(&repo->graft_file, o->graft_file, @@ -89,10 +112,20 @@ void repo_set_gitdir(struct repository *repo, void repo_set_hash_algo(struct repository *repo, int hash_algo) { repo->hash_algo = &hash_algos[hash_algo]; -#ifndef ENABLE_SHA256 - if (hash_algo != GIT_HASH_SHA1) - die(_("The hash algorithm %s is not supported in this build."), repo->hash_algo->name); -#endif +} + +void repo_set_compat_hash_algo(struct repository *repo, int algo) +{ + if (hash_algo_by_ptr(repo->hash_algo) == algo) + BUG("hash_algo and compat_hash_algo match"); + repo->compat_hash_algo = algo ? &hash_algos[algo] : NULL; + if (repo->compat_hash_algo) + repo_read_loose_object_map(repo); +} + +void repo_set_ref_storage_format(struct repository *repo, unsigned int format) +{ + repo->ref_storage_format = format; } /* @@ -164,8 +197,7 @@ int repo_init(struct repository *repo, struct repository_format format = REPOSITORY_FORMAT_INIT; memset(repo, 0, sizeof(*repo)); - repo->objects = raw_object_store_new(); - repo->parsed_objects = parsed_object_pool_new(); + initialize_repository(repo); if (repo_init_gitdir(repo, gitdir)) goto error; @@ -174,10 +206,20 @@ int repo_init(struct repository *repo, goto error; repo_set_hash_algo(repo, format.hash_algo); + repo_set_compat_hash_algo(repo, format.compat_hash_algo); + repo_set_ref_storage_format(repo, format.ref_storage_format); + repo->repository_format_worktree_config = format.worktree_config; + + /* take ownership of format.partial_clone */ + repo->repository_format_partial_clone = format.partial_clone; + format.partial_clone = NULL; if (worktree) repo_set_worktree(repo, worktree); + if (repo->compat_hash_algo) + repo_read_loose_object_map(repo); + clear_repository_format(&format); return 0; @@ -188,19 +230,15 @@ error: int repo_submodule_init(struct repository *subrepo, struct repository *superproject, - const struct submodule *sub) + const char *path, + const struct object_id *treeish_name) { struct strbuf gitdir = STRBUF_INIT; struct strbuf worktree = STRBUF_INIT; int ret = 0; - if (!sub) { - ret = -1; - goto out; - } - - strbuf_repo_worktree_path(&gitdir, superproject, "%s/.git", sub->path); - strbuf_repo_worktree_path(&worktree, superproject, "%s", sub->path); + strbuf_repo_worktree_path(&gitdir, superproject, "%s/.git", path); + strbuf_repo_worktree_path(&worktree, superproject, "%s", path); if (repo_init(subrepo, gitdir.buf, worktree.buf)) { /* @@ -210,9 +248,15 @@ int repo_submodule_init(struct repository *subrepo, * in the superproject's 'modules' directory. In this case the * submodule would not have a worktree. */ + const struct submodule *sub = + submodule_from_path(superproject, treeish_name, path); + if (!sub) { + ret = -1; + goto out; + } + strbuf_reset(&gitdir); - strbuf_repo_git_path(&gitdir, superproject, - "modules/%s", sub->name); + submodule_name_to_gitdir(&gitdir, superproject, sub->name); if (repo_init(subrepo, gitdir.buf, NULL)) { ret = -1; @@ -223,7 +267,7 @@ int repo_submodule_init(struct repository *subrepo, subrepo->submodule_prefix = xstrfmt("%s%s/", superproject->submodule_prefix ? superproject->submodule_prefix : - "", sub->path); + "", path); out: strbuf_release(&gitdir); @@ -231,6 +275,18 @@ out: return ret; } +static void repo_clear_path_cache(struct repo_path_cache *cache) +{ + FREE_AND_NULL(cache->squash_msg); + FREE_AND_NULL(cache->squash_msg); + FREE_AND_NULL(cache->merge_msg); + FREE_AND_NULL(cache->merge_rr); + FREE_AND_NULL(cache->merge_mode); + FREE_AND_NULL(cache->merge_head); + FREE_AND_NULL(cache->fetch_head); + FREE_AND_NULL(cache->shallow); +} + void repo_clear(struct repository *repo) { FREE_AND_NULL(repo->gitdir); @@ -258,17 +314,48 @@ void repo_clear(struct repository *repo) if (repo->index) { discard_index(repo->index); - if (repo->index != &the_index) - FREE_AND_NULL(repo->index); + FREE_AND_NULL(repo->index); + } + + if (repo->promisor_remote_config) { + promisor_remote_clear(repo->promisor_remote_config); + FREE_AND_NULL(repo->promisor_remote_config); + } + + if (repo->remote_state) { + remote_state_clear(repo->remote_state); + FREE_AND_NULL(repo->remote_state); } + + repo_clear_path_cache(&repo->cached_paths); } int repo_read_index(struct repository *repo) { - if (!repo->index) - repo->index = xcalloc(1, sizeof(*repo->index)); + int res; + + /* Complete the double-reference */ + if (!repo->index) { + ALLOC_ARRAY(repo->index, 1); + index_state_init(repo->index, repo); + } else if (repo->index->repo != repo) { + BUG("repo's index should point back at itself"); + } + + res = read_index_from(repo->index, repo->index_file, repo->gitdir); + + prepare_repo_settings(repo); + if (repo->settings.command_requires_full_index) + ensure_full_index(repo->index); + + /* + * If sparse checkouts are in use, check whether paths with the + * SKIP_WORKTREE attribute are missing from the worktree; if not, + * clear that attribute for that path. + */ + clear_skip_worktree_from_present_files(repo->index); - return read_index_from(repo->index, repo->index_file, repo->gitdir); + return res; } int repo_hold_locked_index(struct repository *repo, |