upload-pack: teach deepen-relative in protocol v2
authorJonathan Tan <jonathantanmy@google.com>
Tue, 18 Dec 2018 21:24:35 +0000 (13:24 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 10 Jan 2019 22:53:49 +0000 (14:53 -0800)
Commit 685fbd3291 ("fetch-pack: perform a fetch using v2", 2018-03-15)
attempted to teach Git deepen-relative in protocol v2 (among other
things), but it didn't work:

(1) fetch-pack.c needs to emit "deepen-relative".
(2) upload-pack.c needs to ensure that the correct deepen_relative
variable is passed to deepen() (there are two - the static variable
and the one in struct upload_pack_data).
(3) Before deepen() computes the list of reachable shallows, it first
needs to mark all "our" refs as OUR_REF. v2 currently does not do
this, because unlike v0, it is not needed otherwise.

Fix all this and include a test demonstrating that it works now. For
(2), the static variable deepen_relative is also eliminated, removing a
source of confusion.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
Reviewed-by: Josh Steadmon <steadmon@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
fetch-pack.c
t/t5702-protocol-v2.sh
upload-pack.c
index 5885623eceb0de359bf8eb45af9370497cbe46b9..577faa6229d073768195dff6bcb0f113e5fbd4be 100644 (file)
@@ -1007,6 +1007,8 @@ static void add_shallow_requests(struct strbuf *req_buf,
                        packet_buf_write(req_buf, "deepen-not %s", s->string);
                }
        }
+       if (args->deepen_relative)
+               packet_buf_write(req_buf, "deepen-relative\n");
 }
 
 static void add_wants(int no_dependents, const struct ref *wants, struct strbuf *req_buf)
index fd164d414dad9cfe02fa435fd88dfe6ba6cfcc7b..a738c0c4ce828718f92d0c4955d9ac2eadfb752e 100755 (executable)
@@ -489,6 +489,35 @@ test_expect_success 'ensure that multiple fetches in same process from a shallow
        grep "fetch< version 2" trace
 '
 
+test_expect_success 'deepen-relative' '
+       rm -rf server client trace &&
+
+       test_create_repo server &&
+       test_commit -C server one &&
+       test_commit -C server two &&
+       test_commit -C server three &&
+       git clone --depth 1 "file://$(pwd)/server" client &&
+       test_commit -C server four &&
+
+       # Sanity check that only "three" is downloaded
+       git -C client log --pretty=tformat:%s master >actual &&
+       echo three >expected &&
+       test_cmp expected actual &&
+
+       GIT_TRACE_PACKET="$(pwd)/trace" git -C client -c protocol.version=2 \
+               fetch --deepen=1 origin &&
+       # Ensure that protocol v2 is used
+       grep "fetch< version 2" trace &&
+
+       git -C client log --pretty=tformat:%s origin/master >actual &&
+       cat >expected <<-\EOF &&
+       four
+       three
+       two
+       EOF
+       test_cmp expected actual
+'
+
 # Test protocol v2 with 'http://' transport
 #
 . "$TEST_DIRECTORY"/lib-httpd.sh
index 5e81f1ff24f141fc5357522cb0745c7ff0aeb189..9df27b55a098135629ef4eccea4cb18aadb7dad3 100644 (file)
@@ -43,7 +43,6 @@
 
 static timestamp_t oldest_have;
 
-static int deepen_relative;
 static int multi_ack;
 static int no_done;
 static int use_thin_pack, use_ofs_delta, use_include_tag;
@@ -662,6 +661,9 @@ static void send_unshallow(const struct object_array *shallows,
        }
 }
 
+static int check_ref(const char *refname_full, const struct object_id *oid,
+                    int flag, void *cb_data);
+
 static void deepen(int depth, int deepen_relative,
                   struct object_array *shallows, struct object_array *want_obj)
 {
@@ -676,6 +678,13 @@ static void deepen(int depth, int deepen_relative,
                struct object_array reachable_shallows = OBJECT_ARRAY_INIT;
                struct commit_list *result;
 
+               /*
+                * Checking for reachable shallows requires that our refs be
+                * marked with OUR_REF.
+                */
+               head_ref_namespaced(check_ref, NULL);
+               for_each_namespaced_ref(check_ref, NULL);
+
                get_reachable_list(shallows, &reachable_shallows);
                result = get_shallow_commits(&reachable_shallows,
                                             depth + 1,
@@ -712,6 +721,7 @@ static void deepen_by_rev_list(int ac, const char **av,
 static int send_shallow_list(int depth, int deepen_rev_list,
                             timestamp_t deepen_since,
                             struct string_list *deepen_not,
+                            int deepen_relative,
                             struct object_array *shallows,
                             struct object_array *want_obj)
 {
@@ -834,6 +844,7 @@ static void receive_needs(struct object_array *want_obj)
        int has_non_tip = 0;
        timestamp_t deepen_since = 0;
        int deepen_rev_list = 0;
+       int deepen_relative = 0;
 
        shallow_nr = 0;
        for (;;) {
@@ -925,7 +936,8 @@ static void receive_needs(struct object_array *want_obj)
                return;
 
        if (send_shallow_list(depth, deepen_rev_list, deepen_since,
-                             &deepen_not, &shallows, want_obj))
+                             &deepen_not, deepen_relative, &shallows,
+                             want_obj))
                packet_flush(1);
        object_array_clear(&shallows);
 }
@@ -1398,6 +1410,7 @@ static void send_shallow_info(struct upload_pack_data *data,
 
        if (!send_shallow_list(data->depth, data->deepen_rev_list,
                               data->deepen_since, &data->deepen_not,
+                              data->deepen_relative,
                               &data->shallows, want_obj) &&
            is_repository_shallow(the_repository))
                deepen(INFINITE_DEPTH, data->deepen_relative, &data->shallows,