Skip to content

Commit 9c7d1b0

Browse files
derrickstoleegitster
authored andcommitted
repository: create read_replace_refs setting
The 'read_replace_refs' global specifies whether or not we should respect the references of the form 'refs/replace/<oid>' to replace which object we look up when asking for '<oid>'. This global has caused issues when it is not initialized properly, such as in b6551fe (merge-tree: load default git config, 2023-05-10). To make this more robust, move its config-based initialization out of git_default_config and into prepare_repo_settings(). This provides a repository-scoped version of the 'read_replace_refs' global. The global still has its purpose: it is disabled process-wide by the GIT_NO_REPLACE_OBJECTS environment variable or by a call to disable_replace_refs() in some specific Git commands. Since we already encapsulated the use of the constant inside replace_refs_enabled(), we can perform the initialization inside that method, if necessary. This solves the problem of forgetting to check the config, as we will check it before returning this value. Due to this encapsulation, the global can move to be static within replace-object.c. There is an interesting behavior change possible here: we now have a repository-scoped understanding of this config value. Thus, if there was a command that recurses into submodules and might follow replace refs, then it would now respect the core.useReplaceRefs config value in each repository. 'git grep --recurse-submodules' is such a command that recurses into submodules in-process. We can demonstrate the granularity of this config value via a test in t7814. Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f117838 commit 9c7d1b0

File tree

7 files changed

+68
-16
lines changed

7 files changed

+68
-16
lines changed

config.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,11 +1838,6 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
18381838
return 0;
18391839
}
18401840

1841-
if (!strcmp(var, "core.usereplacerefs")) {
1842-
read_replace_refs = git_config_bool(var, value);
1843-
return 0;
1844-
}
1845-
18461841
/* Add other config variables here and to Documentation/config.txt. */
18471842
return platform_core_config(var, value, cb);
18481843
}

environment.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ const char *editor_program;
6363
const char *askpass_program;
6464
const char *excludes_file;
6565
enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
66-
int read_replace_refs = 1;
6766
enum eol core_eol = EOL_UNSET;
6867
int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;
6968
char *check_roundtrip_encoding = "SHIFT-JIS";

replace-object.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ void prepare_replace_object(struct repository *r)
6464
* replacement object's name (replaced recursively, if necessary).
6565
* The return value is either oid or a pointer to a
6666
* permanently-allocated value. This function always respects replace
67-
* references, regardless of the value of read_replace_refs.
67+
* references, regardless of the value of r->settings.read_replace_refs.
6868
*/
6969
const struct object_id *do_lookup_replace_object(struct repository *r,
7070
const struct object_id *oid)
@@ -85,12 +85,28 @@ const struct object_id *do_lookup_replace_object(struct repository *r,
8585
die(_("replace depth too high for object %s"), oid_to_hex(oid));
8686
}
8787

88+
/*
89+
* This indicator determines whether replace references should be
90+
* respected process-wide, regardless of which repository is being
91+
* using at the time.
92+
*/
93+
static int read_replace_refs = 1;
94+
8895
void disable_replace_refs(void)
8996
{
9097
read_replace_refs = 0;
9198
}
9299

93100
int replace_refs_enabled(struct repository *r)
94101
{
95-
return read_replace_refs;
102+
if (!read_replace_refs)
103+
return 0;
104+
105+
if (r->gitdir) {
106+
prepare_repo_settings(r);
107+
return r->settings.read_replace_refs;
108+
}
109+
110+
/* repository has no objects or refs. */
111+
return 0;
96112
}

replace-object.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,6 @@
55
#include "repository.h"
66
#include "object-store.h"
77

8-
/*
9-
* Do replace refs need to be checked this run? This variable is
10-
* initialized to true unless --no-replace-object is used or
11-
* $GIT_NO_REPLACE_OBJECTS is set, but is set to false by some
12-
* commands that do not want replace references to be active.
13-
*/
14-
extern int read_replace_refs;
15-
168
struct replace_object {
179
struct oidmap_entry original;
1810
struct object_id replacement;

repo-settings.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ void prepare_repo_settings(struct repository *r)
6767
repo_cfg_bool(r, "pack.usebitmapboundarytraversal",
6868
&r->settings.pack_use_bitmap_boundary_traversal,
6969
r->settings.pack_use_bitmap_boundary_traversal);
70+
repo_cfg_bool(r, "core.usereplacerefs", &r->settings.read_replace_refs, 1);
7071

7172
/*
7273
* The GIT_TEST_MULTI_PACK_INDEX variable is special in that

repository.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@ struct repo_settings {
3939
int pack_read_reverse_index;
4040
int pack_use_bitmap_boundary_traversal;
4141

42+
/*
43+
* Does this repository have core.useReplaceRefs=true (on by
44+
* default)? This provides a repository-scoped version of this
45+
* config, though it could be disabled process-wide via some Git
46+
* builtins or the --no-replace-objects option. See
47+
* replace_refs_enabled() for more details.
48+
*/
49+
int read_replace_refs;
50+
4251
struct fsmonitor_settings *fsmonitor; /* lazily loaded */
4352

4453
int index_version;

t/t7814-grep-recurse-submodules.sh

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,4 +594,44 @@ test_expect_success 'grep partially-cloned submodule' '
594594
)
595595
'
596596

597+
test_expect_success 'check scope of core.useReplaceRefs' '
598+
git init base &&
599+
git init base/sub &&
600+
601+
echo A >base/a &&
602+
echo B >base/b &&
603+
echo C >base/sub/c &&
604+
echo D >base/sub/d &&
605+
606+
git -C base/sub add c d &&
607+
git -C base/sub commit -m "Add files" &&
608+
609+
git -C base submodule add ./sub &&
610+
git -C base add a b sub &&
611+
git -C base commit -m "Add files and submodule" &&
612+
613+
A=$(git -C base rev-parse HEAD:a) &&
614+
B=$(git -C base rev-parse HEAD:b) &&
615+
C=$(git -C base/sub rev-parse HEAD:c) &&
616+
D=$(git -C base/sub rev-parse HEAD:d) &&
617+
618+
git -C base replace $A $B &&
619+
git -C base/sub replace $C $D &&
620+
621+
test_must_fail git -C base grep --cached --recurse-submodules A &&
622+
test_must_fail git -C base grep --cached --recurse-submodules C &&
623+
624+
git -C base config core.useReplaceRefs false &&
625+
git -C base grep --recurse-submodules A &&
626+
test_must_fail git -C base grep --cached --recurse-submodules C &&
627+
628+
git -C base/sub config core.useReplaceRefs false &&
629+
git -C base grep --cached --recurse-submodules A &&
630+
git -C base grep --cached --recurse-submodules C &&
631+
632+
git -C base config --unset core.useReplaceRefs &&
633+
test_must_fail git -C base grep --cached --recurse-submodules A &&
634+
git -C base grep --cached --recurse-submodules C
635+
'
636+
597637
test_done

0 commit comments

Comments
 (0)