diff options
author | Junio C Hamano <gitster@pobox.com> | 2023-06-23 02:29:05 +0300 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2023-06-23 02:29:06 +0300 |
commit | d9f9f6b358c4d8aad492bc4995be0926048a6248 (patch) | |
tree | 62cf18a137ffecb83675d7d5dda4f2f43d33253d | |
parent | f2ffc7418685f75e43e2919426276141fd62c656 (diff) | |
parent | 9c7d1b057ff36ee4190621d46e9fe3c83377aea7 (diff) |
Merge branch 'ds/disable-replace-refs'
Introduce a mechanism to disable replace refs globally and per
repository.
* ds/disable-replace-refs:
repository: create read_replace_refs setting
replace-objects: create wrapper around setting
repository: create disable_replace_refs()
-rw-r--r-- | builtin/cat-file.c | 2 | ||||
-rw-r--r-- | builtin/commit-graph.c | 2 | ||||
-rw-r--r-- | builtin/fsck.c | 2 | ||||
-rw-r--r-- | builtin/index-pack.c | 2 | ||||
-rw-r--r-- | builtin/pack-objects.c | 2 | ||||
-rw-r--r-- | builtin/prune.c | 2 | ||||
-rw-r--r-- | builtin/replace.c | 2 | ||||
-rw-r--r-- | builtin/unpack-objects.c | 2 | ||||
-rw-r--r-- | builtin/upload-pack.c | 2 | ||||
-rw-r--r-- | commit-graph.c | 4 | ||||
-rw-r--r-- | config.c | 5 | ||||
-rw-r--r-- | environment.c | 3 | ||||
-rw-r--r-- | git.c | 2 | ||||
-rw-r--r-- | log-tree.c | 2 | ||||
-rw-r--r-- | replace-object.c | 28 | ||||
-rw-r--r-- | replace-object.h | 30 | ||||
-rw-r--r-- | repo-settings.c | 1 | ||||
-rw-r--r-- | repository.h | 9 | ||||
-rwxr-xr-x | t/t7814-grep-recurse-submodules.sh | 40 |
19 files changed, 111 insertions, 31 deletions
diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 0bafc14e6c..27f070267a 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -805,7 +805,7 @@ static int batch_objects(struct batch_options *opt) if (repo_has_promisor_remote(the_repository)) warning("This repository uses promisor remotes. Some objects may not be loaded."); - read_replace_refs = 0; + disable_replace_refs(); cb.opt = opt; cb.expand = &data; diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index a3d00fa232..dd732b3534 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -324,7 +324,7 @@ int cmd_commit_graph(int argc, const char **argv, const char *prefix) git_config(git_default_config, NULL); - read_replace_refs = 0; + disable_replace_refs(); save_commit_buffer = 0; argc = parse_options(argc, argv, prefix, options, diff --git a/builtin/fsck.c b/builtin/fsck.c index dcc165bf0c..d9aa4db828 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -929,7 +929,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) fetch_if_missing = 0; errors_found = 0; - read_replace_refs = 0; + disable_replace_refs(); save_commit_buffer = 0; argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0); diff --git a/builtin/index-pack.c b/builtin/index-pack.c index bb67e16655..d0d8067510 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1752,7 +1752,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) if (argc == 2 && !strcmp(argv[1], "-h")) usage(index_pack_usage); - read_replace_refs = 0; + disable_replace_refs(); fsck_options.walk = mark_link; reset_pack_idx_option(&opts); diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 9cfc8801f9..3af2d84f58 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -4284,7 +4284,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) if (DFS_NUM_STATES > (1 << OE_DFS_STATE_BITS)) BUG("too many dfs states, increase OE_DFS_STATE_BITS"); - read_replace_refs = 0; + disable_replace_refs(); sparse = git_env_bool("GIT_TEST_PACK_SPARSE", -1); if (the_repository->gitdir) { diff --git a/builtin/prune.c b/builtin/prune.c index 5dc9b20720..2877201737 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -164,7 +164,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix) expire = TIME_MAX; save_commit_buffer = 0; - read_replace_refs = 0; + disable_replace_refs(); repo_init_revisions(the_repository, &revs, prefix); argc = parse_options(argc, argv, prefix, options, prune_usage, 0); diff --git a/builtin/replace.c b/builtin/replace.c index 981f189443..abff800276 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -566,7 +566,7 @@ int cmd_replace(int argc, const char **argv, const char *prefix) OPT_END() }; - read_replace_refs = 0; + disable_replace_refs(); git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, options, git_replace_usage, 0); diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 2c52c3a741..0b4fe803cc 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -609,7 +609,7 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix UNUSED) int i; struct object_id oid; - read_replace_refs = 0; + disable_replace_refs(); git_config(git_default_config, NULL); diff --git a/builtin/upload-pack.c b/builtin/upload-pack.c index beb9dd0861..81d2008e01 100644 --- a/builtin/upload-pack.c +++ b/builtin/upload-pack.c @@ -36,7 +36,7 @@ int cmd_upload_pack(int argc, const char **argv, const char *prefix) }; packet_trace_identity("upload-pack"); - read_replace_refs = 0; + disable_replace_refs(); argc = parse_options(argc, argv, prefix, options, upload_pack_usage, 0); diff --git a/commit-graph.c b/commit-graph.c index 843bdb458d..fd0ff8c7b8 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -204,14 +204,12 @@ static struct commit_graph *alloc_commit_graph(void) return g; } -extern int read_replace_refs; - static int commit_graph_compatible(struct repository *r) { if (!r->gitdir) return 0; - if (read_replace_refs) { + if (replace_refs_enabled(r)) { prepare_replace_object(r); if (hashmap_get_size(&r->objects->replace_map->map)) return 0; @@ -1841,11 +1841,6 @@ static int git_default_core_config(const char *var, const char *value, void *cb) return 0; } - if (!strcmp(var, "core.usereplacerefs")) { - read_replace_refs = git_config_bool(var, value); - return 0; - } - /* Add other config variables here and to Documentation/config.txt. */ return platform_core_config(var, value, cb); } diff --git a/environment.c b/environment.c index 6bd001efbd..d449f9719b 100644 --- a/environment.c +++ b/environment.c @@ -62,7 +62,6 @@ const char *editor_program; const char *askpass_program; const char *excludes_file; enum auto_crlf auto_crlf = AUTO_CRLF_FALSE; -int read_replace_refs = 1; enum eol core_eol = EOL_UNSET; int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN; char *check_roundtrip_encoding = "SHIFT-JIS"; @@ -183,7 +182,7 @@ void setup_git_env(const char *git_dir) strvec_clear(&to_free); if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT)) - read_replace_refs = 0; + 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/"); @@ -186,7 +186,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) if (envchanged) *envchanged = 1; } else if (!strcmp(cmd, "--no-replace-objects")) { - read_replace_refs = 0; + disable_replace_refs(); setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1); if (envchanged) *envchanged = 1; diff --git a/log-tree.c b/log-tree.c index f4b22a60cc..48468087af 100644 --- a/log-tree.c +++ b/log-tree.c @@ -156,7 +156,7 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid, if (starts_with(refname, git_replace_ref_base)) { struct object_id original_oid; - if (!read_replace_refs) + if (!replace_refs_enabled(the_repository)) return 0; if (get_oid_hex(refname + strlen(git_replace_ref_base), &original_oid)) { diff --git a/replace-object.c b/replace-object.c index e98825d585..ae2d55b014 100644 --- a/replace-object.c +++ b/replace-object.c @@ -64,7 +64,7 @@ void prepare_replace_object(struct repository *r) * replacement object's name (replaced recursively, if necessary). * The return value is either oid or a pointer to a * permanently-allocated value. This function always respects replace - * references, regardless of the value of read_replace_refs. + * references, regardless of the value of r->settings.read_replace_refs. */ const struct object_id *do_lookup_replace_object(struct repository *r, const struct object_id *oid) @@ -84,3 +84,29 @@ const struct object_id *do_lookup_replace_object(struct repository *r, } die(_("replace depth too high for object %s"), oid_to_hex(oid)); } + +/* + * This indicator determines whether replace references should be + * respected process-wide, regardless of which repository is being + * using at the time. + */ +static int read_replace_refs = 1; + +void disable_replace_refs(void) +{ + read_replace_refs = 0; +} + +int replace_refs_enabled(struct repository *r) +{ + if (!read_replace_refs) + return 0; + + if (r->gitdir) { + prepare_repo_settings(r); + return r->settings.read_replace_refs; + } + + /* repository has no objects or refs. */ + return 0; +} diff --git a/replace-object.h b/replace-object.h index 500482b02b..ba478eb30c 100644 --- a/replace-object.h +++ b/replace-object.h @@ -5,14 +5,6 @@ #include "repository.h" #include "object-store.h" -/* - * Do replace refs need to be checked this run? This variable is - * initialized to true unless --no-replace-object is used or - * $GIT_NO_REPLACE_OBJECTS is set, but is set to false by some - * commands that do not want replace references to be active. - */ -extern int read_replace_refs; - struct replace_object { struct oidmap_entry original; struct object_id replacement; @@ -28,6 +20,18 @@ const struct object_id *do_lookup_replace_object(struct repository *r, const struct object_id *oid); /* + * Some commands disable replace-refs unconditionally, and otherwise each + * repository could alter the core.useReplaceRefs config value. + * + * Return 1 if and only if all of the following are true: + * + * a. disable_replace_refs() has not been called. + * b. GIT_NO_REPLACE_OBJECTS is unset or zero. + * c. the given repository does not have core.useReplaceRefs=false. + */ +int replace_refs_enabled(struct repository *r); + +/* * If object sha1 should be replaced, return the replacement object's * name (replaced recursively, if necessary). The return value is * either sha1 or a pointer to a permanently-allocated value. When @@ -41,11 +45,19 @@ const struct object_id *do_lookup_replace_object(struct repository *r, static inline const struct object_id *lookup_replace_object(struct repository *r, const struct object_id *oid) { - if (!read_replace_refs || + if (!replace_refs_enabled(r) || (r->objects->replace_map_initialized && r->objects->replace_map->map.tablesize == 0)) return oid; return do_lookup_replace_object(r, oid); } +/* + * Some commands override config and environment settings for using + * replace references. Use this method to disable the setting and ensure + * those other settings will not override this choice. This applies + * globally to all in-process repositories. + */ +void disable_replace_refs(void); + #endif /* REPLACE_OBJECT_H */ diff --git a/repo-settings.c b/repo-settings.c index 7b566d729d..525f69c0c7 100644 --- a/repo-settings.c +++ b/repo-settings.c @@ -67,6 +67,7 @@ void prepare_repo_settings(struct repository *r) repo_cfg_bool(r, "pack.usebitmapboundarytraversal", &r->settings.pack_use_bitmap_boundary_traversal, r->settings.pack_use_bitmap_boundary_traversal); + repo_cfg_bool(r, "core.usereplacerefs", &r->settings.read_replace_refs, 1); /* * The GIT_TEST_MULTI_PACK_INDEX variable is special in that diff --git a/repository.h b/repository.h index 586086783f..af294deb8c 100644 --- a/repository.h +++ b/repository.h @@ -39,6 +39,15 @@ struct repo_settings { int pack_read_reverse_index; int pack_use_bitmap_boundary_traversal; + /* + * Does this repository have core.useReplaceRefs=true (on by + * default)? This provides a repository-scoped version of this + * config, though it could be disabled process-wide via some Git + * builtins or the --no-replace-objects option. See + * replace_refs_enabled() for more details. + */ + int read_replace_refs; + struct fsmonitor_settings *fsmonitor; /* lazily loaded */ int index_version; diff --git a/t/t7814-grep-recurse-submodules.sh b/t/t7814-grep-recurse-submodules.sh index 8143817b19..d37c83b464 100755 --- a/t/t7814-grep-recurse-submodules.sh +++ b/t/t7814-grep-recurse-submodules.sh @@ -594,4 +594,44 @@ test_expect_success 'grep partially-cloned submodule' ' ) ' +test_expect_success 'check scope of core.useReplaceRefs' ' + git init base && + git init base/sub && + + echo A >base/a && + echo B >base/b && + echo C >base/sub/c && + echo D >base/sub/d && + + git -C base/sub add c d && + git -C base/sub commit -m "Add files" && + + git -C base submodule add ./sub && + git -C base add a b sub && + git -C base commit -m "Add files and submodule" && + + A=$(git -C base rev-parse HEAD:a) && + B=$(git -C base rev-parse HEAD:b) && + C=$(git -C base/sub rev-parse HEAD:c) && + D=$(git -C base/sub rev-parse HEAD:d) && + + git -C base replace $A $B && + git -C base/sub replace $C $D && + + test_must_fail git -C base grep --cached --recurse-submodules A && + test_must_fail git -C base grep --cached --recurse-submodules C && + + git -C base config core.useReplaceRefs false && + git -C base grep --recurse-submodules A && + test_must_fail git -C base grep --cached --recurse-submodules C && + + git -C base/sub config core.useReplaceRefs false && + git -C base grep --cached --recurse-submodules A && + git -C base grep --cached --recurse-submodules C && + + git -C base config --unset core.useReplaceRefs && + test_must_fail git -C base grep --cached --recurse-submodules A && + git -C base grep --cached --recurse-submodules C +' + test_done |