refspec: stop depending on `the_repository`

The only remaining user of `the_hash_algo` in "refspec.c" is `refspec_append()`, which needs to know the hash algorithm so that it can parse the appended refspec item. In contrast to the functions adapted in the preceding commit, this function always operates on a `struct refspec`. As that structure is expected to only ever contain refspecs that all use the same hash function it doesn't make sense though to adapt each caller. Instead, adapt the structure itself so that it gets initialized with a hash function and use that hash function to parse new refspec items. Adapt callers accordingly. This removes the final dependency on the global repository variable in "refspec.c", so we can drop `USE_THE_REPOSITORY_VARIABLE`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jul 16, 2026 at 14:38 UTC 01f4b61d0302af16b30b2b5141a53e3a88f9f98a
10 files changed +38 -23
builtin/fast-export.c
+3 -1
@@ -51,7 +51,7 @@ static int show_original_ids;
51 static int mark_tags;
52 static struct string_list extra_refs = STRING_LIST_INIT_DUP;
53 static struct string_list tag_refs = STRING_LIST_INIT_DUP;
54 -static struct refspec refspecs = REFSPEC_INIT_FETCH;
54 +static struct refspec refspecs;
55 static int anonymize;
56 static struct hashmap anonymized_seeds;
57 static struct revision_sources revision_sources;
@@ -1372,6 +1372,8 @@ int cmd_fast_export(int argc,
1372 /* we handle encodings */
1373 repo_config(the_repository, git_default_config, NULL);
1374
1375 + refspec_init_fetch(&refspecs, the_hash_algo);
1376 +
1377 repo_init_revisions(the_repository, &revs, prefix);
1378 init_revision_sources(&revision_sources);
1379 revs.topo_order = 1;
builtin/fetch.c
+4 -2
@@ -96,7 +96,7 @@ static struct string_list deepen_not = STRING_LIST_INIT_NODUP;
96 static struct strbuf default_rla = STRBUF_INIT;
97 static struct transport *gtransport;
98 static struct transport *gsecondary;
99 -static struct refspec refmap = REFSPEC_INIT_FETCH;
99 +static struct refspec refmap;
100 static struct string_list server_options = STRING_LIST_INIT_DUP;
101 static struct string_list negotiation_restrict = STRING_LIST_INIT_NODUP;
102 static struct string_list negotiation_include = STRING_LIST_INIT_NODUP;
@@ -2429,7 +2429,7 @@ static int fetch_one(struct remote *remote, int argc, const char **argv,
2429 const struct fetch_config *config,
2430 struct list_objects_filter_options *filter_options)
2431 {
2432 - struct refspec rs = REFSPEC_INIT_FETCH;
2432 + struct refspec rs = REFSPEC_INIT_FETCH(the_hash_algo);
2433 int i;
2434 int exit_code;
2435 int maybe_prune_tags;
@@ -2631,6 +2631,8 @@ int cmd_fetch(int argc,
2631
2632 filter_options.allow_auto_filter = 1;
2633
2634 + refspec_init_fetch(&refmap, the_hash_algo);
2635 +
2636 packet_trace_identity("fetch");
2637
2638 /* Record the command line for the reflog */
builtin/push.c
+4 -2
@@ -66,7 +66,7 @@ static enum transport_family family;
66
67 static struct push_cas_option cas;
68
69 -static struct refspec rs = REFSPEC_INIT_PUSH;
69 +static struct refspec rs;
70
71 static struct string_list push_options_config = STRING_LIST_INIT_DUP;
72
@@ -749,6 +749,8 @@ int cmd_push(int argc,
749 : &push_options_config);
750 set_push_cert_flags(&flags, push_cert);
751
752 + refspec_init_push(&rs, the_hash_algo);
753 +
754 die_for_incompatible_opt4(deleterefs, "--delete",
755 tags, "--tags",
756 flags & TRANSPORT_PUSH_ALL, "--all/--branches",
@@ -855,7 +857,7 @@ int cmd_push(int argc,
857 }
858
859 refspec_clear(&rs);
858 - rs = (struct refspec) REFSPEC_INIT_PUSH;
860 + rs = (struct refspec) REFSPEC_INIT_PUSH(the_hash_algo);
861
862 if (tags)
863 refspec_append(&rs, "refs/tags/*");
builtin/send-pack.c
+4 -1
@@ -153,7 +153,7 @@ int cmd_send_pack(int argc,
153 const char *prefix,
154 struct repository *repo)
155 {
156 - struct refspec rs = REFSPEC_INIT_PUSH;
156 + struct refspec rs;
157 const char *remote_name = NULL;
158 struct remote *remote = NULL;
159 const char *dest = NULL;
@@ -214,6 +214,9 @@ int cmd_send_pack(int argc,
214
215 repo_config(repo, send_pack_config, NULL);
216 argc = parse_options(argc, argv, prefix, options, send_pack_usage, 0);
217 +
218 + refspec_init_push(&rs, repo->hash_algo);
219 +
220 if (argc > 0) {
221 dest = argv[0];
222 refspec_appendn(&rs, argv + 1, argc - 1);
builtin/submodule--helper.c
+1 -1
@@ -3150,7 +3150,7 @@ static int push_check(int argc, const char **argv, const char *prefix UNUSED,
3150 if (argc > 2) {
3151 int i;
3152 struct ref *local_refs = get_local_heads();
3153 - struct refspec refspec = REFSPEC_INIT_PUSH;
3153 + struct refspec refspec = REFSPEC_INIT_PUSH(the_hash_algo);
3154
3155 refspec_appendn(&refspec, argv + 2, argc - 2);
3156
http-push.c
+1 -1
@@ -1716,7 +1716,7 @@ int cmd_main(int argc, const char **argv)
1716 {
1717 struct transfer_request *request;
1718 struct transfer_request *next_request;
1719 - struct refspec rs = REFSPEC_INIT_PUSH;
1719 + struct refspec rs = REFSPEC_INIT_PUSH(the_hash_algo);
1720 struct remote_lock *ref_lock = NULL;
1721 struct remote_lock *info_ref_lock = NULL;
1722 int delete_branch = 0;
refspec.c
+6 -7
@@ -1,4 +1,3 @@
1 -#define USE_THE_REPOSITORY_VARIABLE
1 #define DISABLE_SIGN_COMPARE_WARNINGS
2
3 #include "git-compat-util.h"
@@ -185,15 +184,15 @@ void refspec_item_clear(struct refspec_item *item)
184 item->exact_sha1 = 0;
185 }
186
188 -void refspec_init_fetch(struct refspec *rs)
187 +void refspec_init_fetch(struct refspec *rs, const struct git_hash_algo *algo)
188 {
190 - struct refspec blank = REFSPEC_INIT_FETCH;
189 + struct refspec blank = REFSPEC_INIT_FETCH(algo);
190 memcpy(rs, &blank, sizeof(*rs));
191 }
192
194 -void refspec_init_push(struct refspec *rs)
193 +void refspec_init_push(struct refspec *rs, const struct git_hash_algo *algo)
194 {
196 - struct refspec blank = REFSPEC_INIT_PUSH;
195 + struct refspec blank = REFSPEC_INIT_PUSH(algo);
196 memcpy(rs, &blank, sizeof(*rs));
197 }
198
@@ -203,9 +202,9 @@ void refspec_append(struct refspec *rs, const char *refspec)
202 int ret;
203
204 if (rs->fetch)
206 - ret = refspec_item_init_fetch(&item, refspec, the_hash_algo);
205 + ret = refspec_item_init_fetch(&item, refspec, rs->hash_algo);
206 else
208 - ret = refspec_item_init_push(&item, refspec, the_hash_algo);
207 + ret = refspec_item_init_push(&item, refspec, rs->hash_algo);
208 if (!ret)
209 die(_("invalid refspec '%s'"), refspec);
210
refspec.h
+12 -5
@@ -49,14 +49,21 @@ struct refspec {
49 int alloc;
50 int nr;
51
52 + const struct git_hash_algo *hash_algo;
53 unsigned fetch : 1;
54 };
55
55 -#define REFSPEC_INIT_FETCH { .fetch = 1 }
56 -#define REFSPEC_INIT_PUSH { .fetch = 0 }
57 -
58 -void refspec_init_fetch(struct refspec *rs);
59 -void refspec_init_push(struct refspec *rs);
56 +#define REFSPEC_INIT_FETCH(algo) { \
57 + .fetch = 1, \
58 + .hash_algo = (algo), \
59 +}
60 +#define REFSPEC_INIT_PUSH(algo) { \
61 + .fetch = 0, \
62 + .hash_algo = (algo), \
63 +}
64 +
65 +void refspec_init_fetch(struct refspec *rs, const struct git_hash_algo *hash_algo);
66 +void refspec_init_push(struct refspec *rs, const struct git_hash_algo *hash_algo);
67 void refspec_clear(struct refspec *rs);
68
69 void refspec_append(struct refspec *rs, const char *refspec);
remote.c
+2 -2
@@ -150,8 +150,8 @@ static struct remote *make_remote(struct remote_state *remote_state,
150 ret->prune = -1; /* unspecified */
151 ret->prune_tags = -1; /* unspecified */
152 ret->name = xstrndup(name, len);
153 - refspec_init_push(&ret->push);
154 - refspec_init_fetch(&ret->fetch);
153 + refspec_init_push(&ret->push, the_hash_algo);
154 + refspec_init_fetch(&ret->fetch, the_hash_algo);
155 string_list_init_dup(&ret->server_options);
156 string_list_init_dup(&ret->negotiation_restrict);
157 string_list_init_dup(&ret->negotiation_include);
transport-helper.c
+1 -1
@@ -162,7 +162,7 @@ static struct child_process *get_helper(struct transport *transport)
162
163 data->helper = helper;
164 data->no_disconnect_req = 0;
165 - refspec_init_fetch(&data->rs);
165 + refspec_init_fetch(&data->rs, the_hash_algo);
166
167 /*
168 * Open the output as FILE* so strbuf_getline_*() family of