]> git.ipfire.org Git - thirdparty/git.git/blobdiff - upload-pack.c
Merge git-gui into ml/git-gui-exec-path-fix
[thirdparty/git.git] / upload-pack.c
index 0970392b415d3c8baba516dcee120745ad29ef7f..83f3d2651ab3feee758178f86394627ffe4f76b0 100644 (file)
@@ -68,7 +68,7 @@ struct upload_pack_data {
        struct object_array have_obj;
        struct oid_array haves;                                 /* v2 only */
        struct string_list wanted_refs;                         /* v2 only */
-       struct string_list hidden_refs;
+       struct strvec hidden_refs;
 
        struct object_array shallows;
        struct string_list deepen_not;
@@ -126,7 +126,7 @@ static void upload_pack_data_init(struct upload_pack_data *data)
 {
        struct string_list symref = STRING_LIST_INIT_DUP;
        struct string_list wanted_refs = STRING_LIST_INIT_DUP;
-       struct string_list hidden_refs = STRING_LIST_INIT_DUP;
+       struct strvec hidden_refs = STRVEC_INIT;
        struct object_array want_obj = OBJECT_ARRAY_INIT;
        struct object_array have_obj = OBJECT_ARRAY_INIT;
        struct oid_array haves = OID_ARRAY_INIT;
@@ -161,7 +161,7 @@ static void upload_pack_data_clear(struct upload_pack_data *data)
 {
        string_list_clear(&data->symref, 1);
        string_list_clear(&data->wanted_refs, 1);
-       string_list_clear(&data->hidden_refs, 0);
+       strvec_clear(&data->hidden_refs);
        object_array_clear(&data->want_obj);
        object_array_clear(&data->have_obj);
        oid_array_clear(&data->haves);
@@ -601,11 +601,36 @@ static int get_common_commits(struct upload_pack_data *data,
        }
 }
 
+static int allow_hidden_refs(enum allow_uor allow_uor)
+{
+       if ((allow_uor & ALLOW_ANY_SHA1) == ALLOW_ANY_SHA1)
+               return 1;
+       return !(allow_uor & (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1));
+}
+
+static void for_each_namespaced_ref_1(each_ref_fn fn,
+                                     struct upload_pack_data *data)
+{
+       const char **excludes = NULL;
+       /*
+        * If `data->allow_uor` allows fetching hidden refs, we need to
+        * mark all references (including hidden ones), to check in
+        * `is_our_ref()` below.
+        *
+        * Otherwise, we only care about whether each reference's object
+        * has the OUR_REF bit set or not, so do not need to visit
+        * hidden references.
+        */
+       if (allow_hidden_refs(data->allow_uor))
+               excludes = hidden_refs_to_excludes(&data->hidden_refs);
+
+       for_each_namespaced_ref(excludes, fn, data);
+}
+
+
 static int is_our_ref(struct object *o, enum allow_uor allow_uor)
 {
-       int allow_hidden_ref = (allow_uor &
-                               (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1));
-       return o->flags & ((allow_hidden_ref ? HIDDEN_REF : 0) | OUR_REF);
+       return o->flags & ((allow_hidden_refs(allow_uor) ? 0 : HIDDEN_REF) | OUR_REF);
 }
 
 /*
@@ -776,11 +801,12 @@ error:
        for (i = 0; i < data->want_obj.nr; i++) {
                struct object *o = data->want_obj.objects[i].item;
                if (!is_our_ref(o, data->allow_uor)) {
+                       error("git upload-pack: not our ref %s",
+                             oid_to_hex(&o->oid));
                        packet_writer_error(&data->writer,
                                            "upload-pack: not our ref %s",
                                            oid_to_hex(&o->oid));
-                       die("git upload-pack: not our ref %s",
-                           oid_to_hex(&o->oid));
+                       exit(128);
                }
        }
 }
@@ -854,7 +880,7 @@ static void deepen(struct upload_pack_data *data, int depth)
                 * marked with OUR_REF.
                 */
                head_ref_namespaced(check_ref, data);
-               for_each_namespaced_ref(check_ref, data);
+               for_each_namespaced_ref_1(check_ref, data);
 
                get_reachable_list(data, &reachable_shallows);
                result = get_shallow_commits(&reachable_shallows,
@@ -1169,7 +1195,7 @@ static void receive_needs(struct upload_pack_data *data,
 
 /* return non-zero if the ref is hidden, otherwise 0 */
 static int mark_our_ref(const char *refname, const char *refname_full,
-                       const struct object_id *oid, const struct string_list *hidden_refs)
+                       const struct object_id *oid, const struct strvec *hidden_refs)
 {
        struct object *o = lookup_unknown_object(the_repository, oid);
 
@@ -1391,7 +1417,7 @@ void upload_pack(const int advertise_refs, const int stateless_rpc,
                if (advertise_refs)
                        data.no_done = 1;
                head_ref_namespaced(send_ref, &data);
-               for_each_namespaced_ref(send_ref, &data);
+               for_each_namespaced_ref_1(send_ref, &data);
                if (!data.sent_capabilities) {
                        const char *refname = "capabilities^{}";
                        write_v0_ref(&data, refname, refname, null_oid());
@@ -1405,7 +1431,7 @@ void upload_pack(const int advertise_refs, const int stateless_rpc,
                packet_flush(1);
        } else {
                head_ref_namespaced(check_ref, &data);
-               for_each_namespaced_ref(check_ref, &data);
+               for_each_namespaced_ref_1(check_ref, &data);
        }
 
        if (!advertise_refs) {
@@ -1470,7 +1496,7 @@ static int parse_want(struct packet_writer *writer, const char *line,
 
 static int parse_want_ref(struct packet_writer *writer, const char *line,
                          struct string_list *wanted_refs,
-                         struct string_list *hidden_refs,
+                         struct strvec *hidden_refs,
                          struct object_array *want_obj)
 {
        const char *refname_nons;