]> git.ipfire.org Git - thirdparty/git.git/commitdiff
fetch-pack: add refetch
authorRobert Coup <robert@coup.net.nz>
Mon, 28 Mar 2022 14:02:06 +0000 (14:02 +0000)
committerJunio C Hamano <gitster@pobox.com>
Mon, 28 Mar 2022 17:25:52 +0000 (10:25 -0700)
Allow a "refetch" where the contents of the local object store are
ignored and a full fetch is performed, not attempting to find or
negotiate common commits with the remote.

A key use case is to apply a new partial clone blob/tree filter and
refetch all the associated matching content, which would otherwise not
be transferred when the commit objects are already present locally.

Signed-off-by: Robert Coup <robert@coup.net.nz>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
fetch-pack.c
fetch-pack.h

index 87657907e78d428d0add0a3f057390c0b4b4585a..4e1e88eea097dde85dbbe200ed28d2886a5f2dca 100644 (file)
@@ -312,19 +312,21 @@ static int find_common(struct fetch_negotiator *negotiator,
                const char *remote_hex;
                struct object *o;
 
-               /*
-                * If that object is complete (i.e. it is an ancestor of a
-                * local ref), we tell them we have it but do not have to
-                * tell them about its ancestors, which they already know
-                * about.
-                *
-                * We use lookup_object here because we are only
-                * interested in the case we *know* the object is
-                * reachable and we have already scanned it.
-                */
-               if (((o = lookup_object(the_repository, remote)) != NULL) &&
-                               (o->flags & COMPLETE)) {
-                       continue;
+               if (!args->refetch) {
+                       /*
+                       * If that object is complete (i.e. it is an ancestor of a
+                       * local ref), we tell them we have it but do not have to
+                       * tell them about its ancestors, which they already know
+                       * about.
+                       *
+                       * We use lookup_object here because we are only
+                       * interested in the case we *know* the object is
+                       * reachable and we have already scanned it.
+                       */
+                       if (((o = lookup_object(the_repository, remote)) != NULL) &&
+                                       (o->flags & COMPLETE)) {
+                               continue;
+                       }
                }
 
                remote_hex = oid_to_hex(remote);
@@ -692,6 +694,9 @@ static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator,
        int old_save_commit_buffer = save_commit_buffer;
        timestamp_t cutoff = 0;
 
+       if (args->refetch)
+               return;
+
        save_commit_buffer = 0;
 
        trace2_region_enter("fetch-pack", "parse_remote_refs_and_find_cutoff", NULL);
@@ -1028,7 +1033,11 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
        struct fetch_negotiator *negotiator;
 
        negotiator = &negotiator_alloc;
-       fetch_negotiator_init(r, negotiator);
+       if (args->refetch) {
+               fetch_negotiator_init_noop(negotiator);
+       } else {
+               fetch_negotiator_init(r, negotiator);
+       }
 
        sort_ref_list(&ref, ref_compare_name);
        QSORT(sought, nr_sought, cmp_ref_by_name);
@@ -1121,7 +1130,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
 
        mark_complete_and_common_ref(negotiator, args, &ref);
        filter_refs(args, &ref, sought, nr_sought);
-       if (everything_local(args, &ref)) {
+       if (!args->refetch && everything_local(args, &ref)) {
                packet_flush(fd[1]);
                goto all_done;
        }
@@ -1587,7 +1596,10 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
        struct strvec index_pack_args = STRVEC_INIT;
 
        negotiator = &negotiator_alloc;
-       fetch_negotiator_init(r, negotiator);
+       if (args->refetch)
+               fetch_negotiator_init_noop(negotiator);
+       else
+               fetch_negotiator_init(r, negotiator);
 
        packet_reader_init(&reader, fd[0], NULL, 0,
                           PACKET_READ_CHOMP_NEWLINE |
@@ -1613,7 +1625,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
                        /* Filter 'ref' by 'sought' and those that aren't local */
                        mark_complete_and_common_ref(negotiator, args, &ref);
                        filter_refs(args, &ref, sought, nr_sought);
-                       if (everything_local(args, &ref))
+                       if (!args->refetch && everything_local(args, &ref))
                                state = FETCH_DONE;
                        else
                                state = FETCH_SEND_REQUEST;
index 7f94a2a58318099c6fd8e8940ce7926478bc2a4c..8c7752fc8212c7f911f9f462a2b306c48022bc2f 100644 (file)
@@ -42,6 +42,7 @@ struct fetch_pack_args {
        unsigned update_shallow:1;
        unsigned reject_shallow_remote:1;
        unsigned deepen:1;
+       unsigned refetch:1;
 
        /*
         * Indicate that the remote of this request is a promisor remote. The