Merge branch 'js/partial-clone-connectivity-check'
authorJunio C Hamano <gitster@pobox.com>
Mon, 13 May 2019 14:50:31 +0000 (23:50 +0900)
committerJunio C Hamano <gitster@pobox.com>
Mon, 13 May 2019 14:50:32 +0000 (23:50 +0900)
During an initial "git clone --depth=..." partial clone, it is
pointless to spend cycles for a large portion of the connectivity
check that enumerates and skips promisor objects (which by
definition is all objects fetched from the other side). This has
been optimized out.

* js/partial-clone-connectivity-check:
t/perf: add perf script for partial clones
clone: do faster object check for partial clones

builtin/clone.c
connected.c
connected.h
t/perf/p5600-partial-clone.sh [new file with mode: 0755]
index 31a47d190a96a4bb7ea47eae28434456226cd8d2..ffdd94e8f66193626e343e4cd0b14bd12d262d0e 100644 (file)
@@ -660,7 +660,8 @@ static void update_remote_refs(const struct ref *refs,
                               const char *branch_top,
                               const char *msg,
                               struct transport *transport,
-                              int check_connectivity)
+                              int check_connectivity,
+                              int check_refs_only)
 {
        const struct ref *rm = mapped_refs;
 
@@ -669,6 +670,7 @@ static void update_remote_refs(const struct ref *refs,
 
                opt.transport = transport;
                opt.progress = transport->progress;
+               opt.check_refs_only = !!check_refs_only;
 
                if (check_connected(iterate_ref_map, &rm, &opt))
                        die(_("remote did not send all necessary objects"));
@@ -1230,7 +1232,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
        update_remote_refs(refs, mapped_refs, remote_head_points_at,
                           branch_top.buf, reflog_msg.buf, transport,
-                          !is_local);
+                          !is_local, filter_options.choice);
 
        update_head(our_head_points_at, remote_head, reflog_msg.buf);
 
index 1bba888eff90a23e586807fd02b274b8e7fac097..1ab481fed69b33b48bd95c282d2c0faff897123c 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "object-store.h"
 #include "run-command.h"
 #include "sigchain.h"
 #include "connected.h"
@@ -49,6 +50,22 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
                strbuf_release(&idx_file);
        }
 
+       if (opt->check_refs_only) {
+               /*
+                * For partial clones, we don't want to have to do a regular
+                * connectivity check because we have to enumerate and exclude
+                * all promisor objects (slow), and then the connectivity check
+                * itself becomes a no-op because in a partial clone every
+                * object is a promisor object. Instead, just make sure we
+                * received the objects pointed to by each wanted ref.
+                */
+               do {
+                       if (!repo_has_object_file(the_repository, &oid))
+                               return 1;
+               } while (!fn(cb_data, &oid));
+               return 0;
+       }
+
        if (opt->shallow_file) {
                argv_array_push(&rev_list.args, "--shallow-file");
                argv_array_push(&rev_list.args, opt->shallow_file);
index 8d5a6b3ad6fe4bb0f9ca0930f8eea82543968306..ce2e7d8f2e535aac72fb317448ad20fb2133429b 100644 (file)
@@ -46,6 +46,14 @@ struct check_connected_options {
         * during a fetch.
         */
        unsigned is_deepening_fetch : 1;
+
+       /*
+        * If non-zero, only check the top-level objects referenced by the
+        * wanted refs (passed in as cb_data). This is useful for partial
+        * clones, where enumerating and excluding all promisor objects is very
+        * slow and the commit-walk itself becomes a no-op.
+        */
+       unsigned check_refs_only : 1;
 };
 
 #define CHECK_CONNECTED_INIT { 0 }
diff --git a/t/perf/p5600-partial-clone.sh b/t/perf/p5600-partial-clone.sh
new file mode 100755 (executable)
index 0000000..3e04bd2
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+test_description='performance of partial clones'
+. ./perf-lib.sh
+
+test_perf_default_repo
+
+test_expect_success 'enable server-side config' '
+       git config uploadpack.allowFilter true &&
+       git config uploadpack.allowAnySHA1InWant true
+'
+
+test_perf 'clone without blobs' '
+       rm -rf bare.git &&
+       git clone --no-local --bare --filter=blob:none . bare.git
+'
+
+test_perf 'checkout of result' '
+       rm -rf worktree &&
+       mkdir -p worktree/.git &&
+       tar -C bare.git -cf - . | tar -C worktree/.git -xf - &&
+       git -C worktree config core.bare false &&
+       git -C worktree checkout -f
+'
+
+test_done