]> git.ipfire.org Git - thirdparty/git.git/commitdiff
refspec: let callers pass in hash algorithm when parsing items
authorPatrick Steinhardt <ps@pks.im>
Thu, 16 Jul 2026 12:38:03 +0000 (14:38 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 16 Jul 2026 20:58:25 +0000 (13:58 -0700)
When parsing a refspec item we need to know about the hash algorithm
used by the repository so that we can decide whether or not a given
string is an exact object ID. We use `the_hash_algo` for this, which
makes the code implicitly depend on `the_repository`.

Refactor `refspec_item_init_fetch()`, `refspec_item_init_push()` and
`valid_fetch_refspec()` so that callers have to pass in the hash
algorithm explicitly and adapt callers accordingly. For now, all of
the callers simply pass `the_hash_algo`, so there is no change in
behaviour.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/fetch.c
builtin/pull.c
refspec.c
refspec.h
remote.c

index 8e676b79ba1a91390812ae0699611ee64bdf357f..1d4a129039b16e073a460cf2f6ed0ae7a327b1db 100644 (file)
@@ -601,7 +601,8 @@ static struct ref *get_ref_map(struct remote *remote,
                struct refspec_item tag_refspec;
 
                /* also fetch all tags */
-               refspec_item_init_push(&tag_refspec, TAG_REFSPEC);
+               refspec_item_init_push(&tag_refspec, TAG_REFSPEC,
+                                      the_hash_algo);
                get_fetch_map(remote_refs, &tag_refspec, &tail, 0);
                refspec_item_clear(&tag_refspec);
        } else if (tags == TAGS_DEFAULT && *autotags) {
index d49b09114ae7d8ff052e3fa34175f7e90f7dcb4d..db3ee0aab3ed91ea9733b143bf09c0aeac223dfe 100644 (file)
@@ -612,7 +612,7 @@ static const char *get_tracking_branch(const char *remote, const char *refspec)
        const char *spec_src;
        const char *merge_branch;
 
-       if (!refspec_item_init_fetch(&spec, refspec))
+       if (!refspec_item_init_fetch(&spec, refspec, the_hash_algo))
                die(_("invalid refspec '%s'"), refspec);
        spec_src = spec.src;
        if (!*spec_src || !strcmp(spec_src, "HEAD"))
index fb89bce1db23fb83002686ee953d9ce31c3b7fbb..33a6fb8e457887c41f2e1d2130cf8797c73ac55d 100644 (file)
--- a/refspec.c
+++ b/refspec.c
@@ -16,7 +16,8 @@
  * Parses the provided refspec 'refspec' and populates the refspec_item 'item'.
  * Returns 1 if successful and 0 if the refspec is invalid.
  */
-static int parse_refspec(struct refspec_item *item, const char *refspec, int fetch)
+static int parse_refspec(struct refspec_item *item, const char *refspec,
+                        const struct git_hash_algo *algo, int fetch)
 {
        size_t llen;
        int is_glob;
@@ -84,7 +85,7 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet
                 */
                if (!*item->src)
                        return 0; /* negative refspecs must not be empty */
-               else if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))
+               else if (llen == algo->hexsz && !get_oid_hex_algop(item->src, &unused, algo))
                        return 0; /* negative refspecs cannot be exact sha1 */
                else if (!check_refname_format(item->src, flags))
                        ; /* valid looking ref is ok */
@@ -101,7 +102,7 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet
                /* LHS */
                if (!*item->src)
                        ; /* empty is ok; it means "HEAD" */
-               else if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))
+               else if (llen == algo->hexsz && !get_oid_hex_algop(item->src, &unused, algo))
                        item->exact_sha1 = 1; /* ok */
                else if (!check_refname_format(item->src, flags))
                        ; /* valid looking ref is ok */
@@ -154,21 +155,23 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet
 }
 
 static int refspec_item_init(struct refspec_item *item, const char *refspec,
-                            int fetch)
+                            const struct git_hash_algo *algo, int fetch)
 {
        memset(item, 0, sizeof(*item));
        item->raw = xstrdup(refspec);
-       return parse_refspec(item, refspec, fetch);
+       return parse_refspec(item, refspec, algo, fetch);
 }
 
-int refspec_item_init_fetch(struct refspec_item *item, const char *refspec)
+int refspec_item_init_fetch(struct refspec_item *item, const char *refspec,
+                           const struct git_hash_algo *algo)
 {
-       return refspec_item_init(item, refspec, 1);
+       return refspec_item_init(item, refspec, algo, 1);
 }
 
-int refspec_item_init_push(struct refspec_item *item, const char *refspec)
+int refspec_item_init_push(struct refspec_item *item, const char *refspec,
+                          const struct git_hash_algo *algo)
 {
-       return refspec_item_init(item, refspec, 0);
+       return refspec_item_init(item, refspec, algo, 0);
 }
 
 void refspec_item_clear(struct refspec_item *item)
@@ -200,9 +203,9 @@ void refspec_append(struct refspec *rs, const char *refspec)
        int ret;
 
        if (rs->fetch)
-               ret = refspec_item_init_fetch(&item, refspec);
+               ret = refspec_item_init_fetch(&item, refspec, the_hash_algo);
        else
-               ret = refspec_item_init_push(&item, refspec);
+               ret = refspec_item_init_push(&item, refspec, the_hash_algo);
        if (!ret)
                die(_("invalid refspec '%s'"), refspec);
 
@@ -246,10 +249,11 @@ void refspec_clear(struct refspec *rs)
        rs->fetch = 0;
 }
 
-int valid_fetch_refspec(const char *fetch_refspec_str)
+int valid_fetch_refspec(const char *fetch_refspec_str,
+                       const struct git_hash_algo *algo)
 {
        struct refspec_item refspec;
-       int ret = refspec_item_init_fetch(&refspec, fetch_refspec_str);
+       int ret = refspec_item_init_fetch(&refspec, fetch_refspec_str, algo);
        refspec_item_clear(&refspec);
        return ret;
 }
index 832d6f923ce083fd0ab0a47a6ba5b3dd10eb49a6..e482b720a87b867951002464364295afc8c0517d 100644 (file)
--- a/refspec.h
+++ b/refspec.h
@@ -1,6 +1,7 @@
 #ifndef REFSPEC_H
 #define REFSPEC_H
 
+struct git_hash_algo;
 struct string_list;
 struct strvec;
 
@@ -33,8 +34,10 @@ struct refspec_item {
        char *raw;
 };
 
-int refspec_item_init_fetch(struct refspec_item *item, const char *refspec);
-int refspec_item_init_push(struct refspec_item *item, const char *refspec);
+int refspec_item_init_fetch(struct refspec_item *item, const char *refspec,
+                           const struct git_hash_algo *algo);
+int refspec_item_init_push(struct refspec_item *item, const char *refspec,
+                          const struct git_hash_algo *algo);
 void refspec_item_clear(struct refspec_item *item);
 
 /**
@@ -61,7 +64,7 @@ __attribute__((format (printf,2,3)))
 void refspec_appendf(struct refspec *rs, const char *fmt, ...);
 void refspec_appendn(struct refspec *rs, const char **refspecs, int nr);
 
-int valid_fetch_refspec(const char *refspec);
+int valid_fetch_refspec(const char *refspec, const struct git_hash_algo *algo);
 
 /*
  * Determine what <prefix> values to pass to the peer in ref-prefix lines
index e6c52c850cac6308b1236f59782097e032c24fde..b4dff1e5f990fa2cf779d41bbdf27a46077b0c52 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -3039,7 +3039,7 @@ int valid_remote_name(const char *name)
        int result;
        struct strbuf refspec = STRBUF_INIT;
        strbuf_addf(&refspec, "refs/heads/test:refs/remotes/%s/test", name);
-       result = valid_fetch_refspec(refspec.buf);
+       result = valid_fetch_refspec(refspec.buf, the_hash_algo);
        strbuf_release(&refspec);
        return result;
 }