Skip to content

Commit 5b51f0d

Browse files
committed
Merge branch 'js/partial-clone-connectivity-check'
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
2 parents 5b2d1c0 + 1bb10d4 commit 5b51f0d

File tree

4 files changed

+55
-2
lines changed

4 files changed

+55
-2
lines changed

builtin/clone.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,8 @@ static void update_remote_refs(const struct ref *refs,
660660
const char *branch_top,
661661
const char *msg,
662662
struct transport *transport,
663-
int check_connectivity)
663+
int check_connectivity,
664+
int check_refs_only)
664665
{
665666
const struct ref *rm = mapped_refs;
666667

@@ -669,6 +670,7 @@ static void update_remote_refs(const struct ref *refs,
669670

670671
opt.transport = transport;
671672
opt.progress = transport->progress;
673+
opt.check_refs_only = !!check_refs_only;
672674

673675
if (check_connected(iterate_ref_map, &rm, &opt))
674676
die(_("remote did not send all necessary objects"));
@@ -1230,7 +1232,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
12301232

12311233
update_remote_refs(refs, mapped_refs, remote_head_points_at,
12321234
branch_top.buf, reflog_msg.buf, transport,
1233-
!is_local);
1235+
!is_local, filter_options.choice);
12341236

12351237
update_head(our_head_points_at, remote_head, reflog_msg.buf);
12361238

connected.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "cache.h"
2+
#include "object-store.h"
23
#include "run-command.h"
34
#include "sigchain.h"
45
#include "connected.h"
@@ -49,6 +50,22 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
4950
strbuf_release(&idx_file);
5051
}
5152

53+
if (opt->check_refs_only) {
54+
/*
55+
* For partial clones, we don't want to have to do a regular
56+
* connectivity check because we have to enumerate and exclude
57+
* all promisor objects (slow), and then the connectivity check
58+
* itself becomes a no-op because in a partial clone every
59+
* object is a promisor object. Instead, just make sure we
60+
* received the objects pointed to by each wanted ref.
61+
*/
62+
do {
63+
if (!repo_has_object_file(the_repository, &oid))
64+
return 1;
65+
} while (!fn(cb_data, &oid));
66+
return 0;
67+
}
68+
5269
if (opt->shallow_file) {
5370
argv_array_push(&rev_list.args, "--shallow-file");
5471
argv_array_push(&rev_list.args, opt->shallow_file);

connected.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ struct check_connected_options {
4646
* during a fetch.
4747
*/
4848
unsigned is_deepening_fetch : 1;
49+
50+
/*
51+
* If non-zero, only check the top-level objects referenced by the
52+
* wanted refs (passed in as cb_data). This is useful for partial
53+
* clones, where enumerating and excluding all promisor objects is very
54+
* slow and the commit-walk itself becomes a no-op.
55+
*/
56+
unsigned check_refs_only : 1;
4957
};
5058

5159
#define CHECK_CONNECTED_INIT { 0 }

t/perf/p5600-partial-clone.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/sh
2+
3+
test_description='performance of partial clones'
4+
. ./perf-lib.sh
5+
6+
test_perf_default_repo
7+
8+
test_expect_success 'enable server-side config' '
9+
git config uploadpack.allowFilter true &&
10+
git config uploadpack.allowAnySHA1InWant true
11+
'
12+
13+
test_perf 'clone without blobs' '
14+
rm -rf bare.git &&
15+
git clone --no-local --bare --filter=blob:none . bare.git
16+
'
17+
18+
test_perf 'checkout of result' '
19+
rm -rf worktree &&
20+
mkdir -p worktree/.git &&
21+
tar -C bare.git -cf - . | tar -C worktree/.git -xf - &&
22+
git -C worktree config core.bare false &&
23+
git -C worktree checkout -f
24+
'
25+
26+
test_done

0 commit comments

Comments
 (0)