aboutsummaryrefslogtreecommitdiffstats
path: root/setup.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2025-12-05 14:49:58 +0900
committerJunio C Hamano <gitster@pobox.com>2025-12-05 14:49:58 +0900
commit9d442ce2e21fc02332378c6026b011bb5ced1856 (patch)
treed2074c0ead08d882f8cd824584d0b2814c3b5a4b /setup.c
parent1b40ddc1a5e2eecd54802c3c6c3c940b0306542a (diff)
parentac65c70663b092e823b0d3de1c1cfdee0a4fbc8e (diff)
downloadgit-9d442ce2e21fc02332378c6026b011bb5ced1856.tar.gz
Merge branch 'ps/object-source-management'
Code refactoring around object database sources. * ps/object-source-management: odb: handle recreation of quarantine directories odb: handle changing a repository's commondir chdir-notify: add function to unregister listeners odb: handle initialization of sources in `odb_new()` http-push: stop setting up `the_repository` for each reference t/helper: stop setting up `the_repository` repeatedly builtin/index-pack: fix deferred fsck outside repos oidset: introduce `oidset_equal()` odb: move logic to disable ref updates into repo odb: refactor `odb_clear()` to `odb_free()` odb: adopt logic to close object databases setup: convert `set_git_dir()` to have file scope path: move `enter_repo()` into "setup.c"
Diffstat (limited to 'setup.c')
-rw-r--r--setup.c214
1 files changed, 148 insertions, 66 deletions
diff --git a/setup.c b/setup.c
index cf47441b7b..3a6a048620 100644
--- a/setup.c
+++ b/setup.c
@@ -22,7 +22,6 @@
#include "chdir-notify.h"
#include "path.h"
#include "quote.h"
-#include "tmp-objdir.h"
#include "trace.h"
#include "trace2.h"
#include "worktree.h"
@@ -1002,6 +1001,83 @@ cleanup_return:
return error_code ? NULL : 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_internal(path, skip_initializing_odb);
+}
+
+static void update_relative_gitdir(const char *name UNUSED,
+ const char *old_cwd,
+ const char *new_cwd,
+ void *data UNUSED)
+{
+ char *path = reparent_relative_path(old_cwd, new_cwd,
+ repo_get_git_dir(the_repository));
+ trace_printf_key(&trace_setup_key,
+ "setup: move $GIT_DIR to '%s'",
+ path);
+ set_git_dir_1(path, true);
+ free(path);
+}
+
+static void set_git_dir(const char *path, int make_realpath)
+{
+ struct strbuf realpath = STRBUF_INIT;
+
+ if (make_realpath) {
+ strbuf_realpath(&realpath, path, 1);
+ path = realpath.buf;
+ }
+
+ set_git_dir_1(path, false);
+ if (!is_absolute_path(path))
+ chdir_notify_register(NULL, update_relative_gitdir, NULL);
+
+ strbuf_release(&realpath);
+}
+
static const char *setup_explicit_git_dir(const char *gitdirenv,
struct strbuf *cwd,
struct repository_format *repo_fmt,
@@ -1628,79 +1704,85 @@ 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 = 1;
- }
-
- 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;
-}
-
-static void set_git_dir_1(const char *path)
+const char *enter_repo(const char *path, unsigned flags)
{
- xsetenv(GIT_DIR_ENVIRONMENT, path, 1);
- setup_git_env(path);
-}
+ static struct strbuf validated_path = STRBUF_INIT;
+ static struct strbuf used_path = STRBUF_INIT;
-static void update_relative_gitdir(const char *name UNUSED,
- const char *old_cwd,
- const char *new_cwd,
- void *data UNUSED)
-{
- char *path = reparent_relative_path(old_cwd, new_cwd,
- repo_get_git_dir(the_repository));
- struct tmp_objdir *tmp_objdir = tmp_objdir_unapply_primary_odb();
+ if (!path)
+ return NULL;
- trace_printf_key(&trace_setup_key,
- "setup: move $GIT_DIR to '%s'",
- path);
- set_git_dir_1(path);
- if (tmp_objdir)
- tmp_objdir_reapply_primary_odb(tmp_objdir, old_cwd, new_cwd);
- free(path);
-}
+ if (!(flags & ENTER_REPO_STRICT)) {
+ static const char *suffix[] = {
+ "/.git", "", ".git/.git", ".git", NULL,
+ };
+ const char *gitfile;
+ int len = strlen(path);
+ int i;
+ while ((1 < len) && (path[len-1] == '/'))
+ len--;
-void set_git_dir(const char *path, int make_realpath)
-{
- struct strbuf realpath = STRBUF_INIT;
+ /*
+ * We can handle arbitrary-sized buffers, but this remains as a
+ * sanity check on untrusted input.
+ */
+ if (PATH_MAX <= len)
+ return NULL;
- if (make_realpath) {
- strbuf_realpath(&realpath, path, 1);
- path = realpath.buf;
+ strbuf_reset(&used_path);
+ strbuf_reset(&validated_path);
+ strbuf_add(&used_path, path, len);
+ strbuf_add(&validated_path, path, len);
+
+ if (used_path.buf[0] == '~') {
+ char *newpath = interpolate_path(used_path.buf, 0);
+ if (!newpath)
+ return NULL;
+ strbuf_attach(&used_path, newpath, strlen(newpath),
+ strlen(newpath));
+ }
+ for (i = 0; suffix[i]; i++) {
+ struct stat st;
+ size_t baselen = used_path.len;
+ strbuf_addstr(&used_path, suffix[i]);
+ if (!stat(used_path.buf, &st) &&
+ (S_ISREG(st.st_mode) ||
+ (S_ISDIR(st.st_mode) && is_git_directory(used_path.buf)))) {
+ strbuf_addstr(&validated_path, suffix[i]);
+ break;
+ }
+ strbuf_setlen(&used_path, baselen);
+ }
+ if (!suffix[i])
+ return NULL;
+ gitfile = read_gitfile(used_path.buf);
+ if (!(flags & ENTER_REPO_ANY_OWNER_OK))
+ die_upon_dubious_ownership(gitfile, NULL, used_path.buf);
+ if (gitfile) {
+ strbuf_reset(&used_path);
+ strbuf_addstr(&used_path, gitfile);
+ }
+ if (chdir(used_path.buf))
+ return NULL;
+ path = validated_path.buf;
+ }
+ else {
+ const char *gitfile = read_gitfile(path);
+ if (!(flags & ENTER_REPO_ANY_OWNER_OK))
+ die_upon_dubious_ownership(gitfile, NULL, path);
+ if (gitfile)
+ path = gitfile;
+ if (chdir(path))
+ return NULL;
}
- set_git_dir_1(path);
- if (!is_absolute_path(path))
- chdir_notify_register(NULL, update_relative_gitdir, NULL);
+ if (is_git_directory(".")) {
+ set_git_dir(".", 0);
+ check_repository_format(NULL);
+ return path;
+ }
- strbuf_release(&realpath);
+ return NULL;
}
static int git_work_tree_initialized;