aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--odb.c37
-rw-r--r--odb.h4
-rw-r--r--repository.c13
-rw-r--r--repository.h1
-rw-r--r--setup.c84
5 files changed, 83 insertions, 56 deletions
diff --git a/odb.c b/odb.c
index 88b40c81c0..70665fb7f4 100644
--- a/odb.c
+++ b/odb.c
@@ -1,5 +1,6 @@
#include "git-compat-util.h"
#include "abspath.h"
+#include "chdir-notify.h"
#include "commit-graph.h"
#include "config.h"
#include "dir.h"
@@ -142,9 +143,9 @@ static void read_info_alternates(struct object_database *odb,
const char *relative_base,
int depth);
-struct odb_source *odb_source_new(struct object_database *odb,
- const char *path,
- bool local)
+static struct odb_source *odb_source_new(struct object_database *odb,
+ const char *path,
+ bool local)
{
struct odb_source *source;
@@ -1034,6 +1035,32 @@ int odb_write_object_stream(struct object_database *odb,
return odb_source_loose_write_stream(odb->sources, stream, len, oid);
}
+static void odb_update_commondir(const char *name UNUSED,
+ const char *old_cwd,
+ const char *new_cwd,
+ void *cb_data)
+{
+ struct object_database *odb = cb_data;
+ struct odb_source *source;
+
+ /*
+ * In theory, we only have to do this for the primary object source, as
+ * alternates' paths are always resolved to an absolute path.
+ */
+ for (source = odb->sources; source; source = source->next) {
+ char *path;
+
+ if (is_absolute_path(source->path))
+ continue;
+
+ path = reparent_relative_path(old_cwd, new_cwd,
+ source->path);
+
+ free(source->path);
+ source->path = path;
+ }
+}
+
struct object_database *odb_new(struct repository *repo,
const char *primary_source,
const char *secondary_sources)
@@ -1055,6 +1082,8 @@ struct object_database *odb_new(struct repository *repo,
free(to_free);
+ chdir_notify_register(NULL, odb_update_commondir, o);
+
return o;
}
@@ -1106,6 +1135,8 @@ void odb_free(struct object_database *o)
packfile_store_free(o->packfiles);
string_list_clear(&o->submodule_source_paths, 0);
+ chdir_notify_unregister(NULL, odb_update_commondir, o);
+
free(o);
}
diff --git a/odb.h b/odb.h
index 41b3c03027..014cd9585a 100644
--- a/odb.h
+++ b/odb.h
@@ -78,10 +78,6 @@ struct odb_source {
char *path;
};
-struct odb_source *odb_source_new(struct object_database *odb,
- const char *path,
- bool local);
-
struct packed_git;
struct packfile_store;
struct cached_object_entry;
diff --git a/repository.c b/repository.c
index 5975c8f341..863f24411b 100644
--- a/repository.c
+++ b/repository.c
@@ -165,17 +165,10 @@ void repo_set_gitdir(struct repository *repo,
repo_set_commondir(repo, o->commondir);
- if (!repo->objects) {
+ if (!repo->objects)
repo->objects = odb_new(repo, o->object_dir, o->alternate_db);
- } else {
- char *objects_path = NULL;
- expand_base_dir(&objects_path, o->object_dir,
- repo->commondir, "objects");
- free(repo->objects->sources->path);
- repo->objects->sources->path = objects_path;
- free(repo->objects->alternate_db);
- repo->objects->alternate_db = xstrdup_or_null(o->alternate_db);
- }
+ else if (!o->skip_initializing_odb)
+ BUG("cannot reinitialize an already-initialized object directory");
repo->disable_ref_updates = o->disable_ref_updates;
diff --git a/repository.h b/repository.h
index 614649413b..6063c4b846 100644
--- a/repository.h
+++ b/repository.h
@@ -195,6 +195,7 @@ struct set_gitdir_args {
const char *index_file;
const char *alternate_db;
bool disable_ref_updates;
+ bool skip_initializing_odb;
};
void repo_set_gitdir(struct repository *repo, const char *root,
diff --git a/setup.c b/setup.c
index a752e9fc84..a625f9fbc8 100644
--- a/setup.c
+++ b/setup.c
@@ -1002,10 +1002,51 @@ cleanup_return:
return error_code ? NULL : path;
}
-static void set_git_dir_1(const char *path)
+static void setup_git_env_internal(const char *git_dir,
+ bool skip_initializing_odb)
+{
+ char *git_replace_ref_base;
+ const char *shallow_file;
+ const char *replace_ref_base;
+ struct set_gitdir_args args = { NULL };
+ struct strvec to_free = STRVEC_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);
+ if (getenv(GIT_QUARANTINE_ENVIRONMENT))
+ args.disable_ref_updates = true;
+ args.skip_initializing_odb = skip_initializing_odb;
+
+ repo_set_gitdir(the_repository, git_dir, &args);
+ strvec_clear(&to_free);
+
+ if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
+ disable_replace_refs();
+ replace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);
+ git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base
+ : "refs/replace/");
+ update_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);
+
+ shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
+ if (shallow_file)
+ set_alternate_shallow_file(the_repository, shallow_file, 0);
+
+ if (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0))
+ fetch_if_missing = 0;
+}
+
+void setup_git_env(const char *git_dir)
+{
+ setup_git_env_internal(git_dir, false);
+}
+
+static void set_git_dir_1(const char *path, bool skip_initializing_odb)
{
xsetenv(GIT_DIR_ENVIRONMENT, path, 1);
- setup_git_env(path);
+ setup_git_env_internal(path, skip_initializing_odb);
}
static void update_relative_gitdir(const char *name UNUSED,
@@ -1020,7 +1061,7 @@ static void update_relative_gitdir(const char *name UNUSED,
trace_printf_key(&trace_setup_key,
"setup: move $GIT_DIR to '%s'",
path);
- set_git_dir_1(path);
+ set_git_dir_1(path, true);
if (tmp_objdir)
tmp_objdir_reapply_primary_odb(tmp_objdir, old_cwd, new_cwd);
free(path);
@@ -1035,7 +1076,7 @@ static void set_git_dir(const char *path, int make_realpath)
path = realpath.buf;
}
- set_git_dir_1(path);
+ set_git_dir_1(path, false);
if (!is_absolute_path(path))
chdir_notify_register(NULL, update_relative_gitdir, NULL);
@@ -1668,41 +1709,6 @@ enum discovery_result discover_git_directory_reason(struct strbuf *commondir,
return result;
}
-void setup_git_env(const char *git_dir)
-{
- char *git_replace_ref_base;
- const char *shallow_file;
- const char *replace_ref_base;
- struct set_gitdir_args args = { NULL };
- struct strvec to_free = STRVEC_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);
- if (getenv(GIT_QUARANTINE_ENVIRONMENT)) {
- args.disable_ref_updates = true;
- }
-
- repo_set_gitdir(the_repository, git_dir, &args);
- strvec_clear(&to_free);
-
- if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
- disable_replace_refs();
- replace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);
- git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base
- : "refs/replace/");
- update_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);
-
- shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
- if (shallow_file)
- set_alternate_shallow_file(the_repository, shallow_file, 0);
-
- if (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0))
- fetch_if_missing = 0;
-}
-
const char *enter_repo(const char *path, unsigned flags)
{
static struct strbuf validated_path = STRBUF_INIT;