summaryrefslogtreecommitdiff
path: root/repository.c
diff options
context:
space:
mode:
Diffstat (limited to 'repository.c')
-rw-r--r--repository.c165
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,