Merge branch 'jt/fetch-tips-in-partial-clone'
authorJunio C Hamano <gitster@pobox.com>
Fri, 19 Oct 2018 04:34:04 +0000 (13:34 +0900)
committerJunio C Hamano <gitster@pobox.com>
Fri, 19 Oct 2018 04:34:04 +0000 (13:34 +0900)
"git fetch $repo $object" in a partial clone did not correctly
fetch the asked-for object that is referenced by an object in
promisor packfile, which has been fixed.

* jt/fetch-tips-in-partial-clone:
  fetch: in partial clone, check presence of targets
  connected: document connectivity in partial clones

builtin/fetch.c
connected.h
t/t5616-partial-clone.sh

index 0696abf..6ce882c 100644 (file)
@@ -931,10 +931,11 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
  * everything we are going to fetch already exists and is connected
  * locally.
  */
-static int quickfetch(struct ref *ref_map)
+static int check_exist_and_connected(struct ref *ref_map)
 {
        struct ref *rm = ref_map;
        struct check_connected_options opt = CHECK_CONNECTED_INIT;
+       struct ref *r;
 
        /*
         * If we are deepening a shallow clone we already have these
@@ -945,13 +946,23 @@ static int quickfetch(struct ref *ref_map)
         */
        if (deepen)
                return -1;
+
+       /*
+        * check_connected() allows objects to merely be promised, but
+        * we need all direct targets to exist.
+        */
+       for (r = rm; r; r = r->next) {
+               if (!has_object_file(&r->old_oid))
+                       return -1;
+       }
+
        opt.quiet = 1;
        return check_connected(iterate_ref_map, &rm, &opt);
 }
 
 static int fetch_refs(struct transport *transport, struct ref *ref_map)
 {
-       int ret = quickfetch(ref_map);
+       int ret = check_exist_and_connected(ref_map);
        if (ret)
                ret = transport_fetch_refs(transport, ref_map);
        if (!ret)
index e4c9618..8d5a6b3 100644 (file)
@@ -51,9 +51,9 @@ struct check_connected_options {
 #define CHECK_CONNECTED_INIT { 0 }
 
 /*
- * Make sure that our object store has all the commits necessary to
- * connect the ancestry chain to some of our existing refs, and all
- * the trees and blobs that these commits use.
+ * Make sure that all given objects and all objects reachable from them
+ * either exist in our object store or (if the repository is a partial
+ * clone) are promised to be available.
  *
  * Return 0 if Ok, non zero otherwise (i.e. some missing objects)
  *
index 6ff6146..6391437 100755 (executable)
@@ -182,6 +182,23 @@ test_expect_success 'partial clone fetches blobs pointed to by refs even if norm
        git -C dst fsck
 '
 
+test_expect_success 'fetch what is specified on CLI even if already promised' '
+       rm -rf src dst.git &&
+       git init src &&
+       test_commit -C src foo &&
+       test_config -C src uploadpack.allowfilter 1 &&
+       test_config -C src uploadpack.allowanysha1inwant 1 &&
+
+       git hash-object --stdin <src/foo.t >blob &&
+
+       git clone --bare --filter=blob:none "file://$(pwd)/src" dst.git &&
+       git -C dst.git rev-list --objects --quiet --missing=print HEAD >missing_before &&
+       grep "?$(cat blob)" missing_before &&
+       git -C dst.git fetch origin $(cat blob) &&
+       git -C dst.git rev-list --objects --quiet --missing=print HEAD >missing_after &&
+       ! grep "?$(cat blob)" missing_after
+'
+
 . "$TEST_DIRECTORY"/lib-httpd.sh
 start_httpd