Skip to content

Commit 8fa8a4f

Browse files
committed
Merge branch 'jt/partial-clone-fsck-connectivity'
Partial clone support of "git clone" has been updated to correctly validate the objects it receives from the other side. The server side has been corrected to send objects that are directly requested, even if they may match the filtering criteria (e.g. when doing a "lazy blob" partial clone). * jt/partial-clone-fsck-connectivity: clone: check connectivity even if clone is partial upload-pack: send refs' objects despite "filter"
2 parents 7633ff4 + a7e67c1 commit 8fa8a4f

File tree

8 files changed

+91
-7
lines changed

8 files changed

+91
-7
lines changed

Documentation/technical/pack-protocol.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,9 @@ information is sent back to the client in the next step.
284284
The client can optionally request that pack-objects omit various
285285
objects from the packfile using one of several filtering techniques.
286286
These are intended for use with partial clone and partial fetch
287-
operations. See `rev-list` for possible "filter-spec" values.
287+
operations. An object that does not meet a filter-spec value is
288+
omitted unless explicitly requested in a 'want' line. See `rev-list`
289+
for possible filter-spec values.
288290

289291
Once all the 'want's and 'shallow's (and optional 'deepen') are
290292
transferred, clients MUST send a flush-pkt, to tell the server side

builtin/clone.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1202,7 +1202,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
12021202

12031203
update_remote_refs(refs, mapped_refs, remote_head_points_at,
12041204
branch_top.buf, reflog_msg.buf, transport,
1205-
!is_local && !filter_options.choice);
1205+
!is_local);
12061206

12071207
update_head(our_head_points_at, remote_head, reflog_msg.buf);
12081208

list-objects.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ static void process_blob(struct rev_info *revs,
4848

4949
pathlen = path->len;
5050
strbuf_addstr(path, name);
51-
if (filter_fn)
51+
if (!(obj->flags & USER_GIVEN) && filter_fn)
5252
r = filter_fn(LOFS_BLOB, obj,
5353
path->buf, &path->buf[pathlen],
5454
filter_data);
@@ -133,7 +133,7 @@ static void process_tree(struct rev_info *revs,
133133
}
134134

135135
strbuf_addstr(base, name);
136-
if (filter_fn)
136+
if (!(obj->flags & USER_GIVEN) && filter_fn)
137137
r = filter_fn(LOFS_BEGIN_TREE, obj,
138138
base->buf, &base->buf[baselen],
139139
filter_data);
@@ -172,7 +172,7 @@ static void process_tree(struct rev_info *revs,
172172
cb_data, filter_fn, filter_data);
173173
}
174174

175-
if (filter_fn) {
175+
if (!(obj->flags & USER_GIVEN) && filter_fn) {
176176
r = filter_fn(LOFS_END_TREE, obj,
177177
base->buf, &base->buf[baselen],
178178
filter_data);

object.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ struct object_array {
5353

5454
/*
5555
* object flag allocation:
56-
* revision.h: 0---------10 26
56+
* revision.h: 0---------10 2526
5757
* fetch-pack.c: 0----5
5858
* walker.c: 0-2
5959
* upload-pack.c: 4 11----------------19

revision.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ static void add_pending_object_with_path(struct rev_info *revs,
175175
strbuf_release(&buf);
176176
return; /* do not add the commit itself */
177177
}
178+
obj->flags |= USER_GIVEN;
178179
add_object_array_with_path(obj, name, &revs->pending, mode, path);
179180
}
180181

revision.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@
2020
#define SYMMETRIC_LEFT (1u<<8)
2121
#define PATCHSAME (1u<<9)
2222
#define BOTTOM (1u<<10)
23+
#define USER_GIVEN (1u<<25) /* given directly by the user */
2324
#define TRACK_LINEAR (1u<<26)
24-
#define ALL_REV_FLAGS (((1u<<11)-1) | TRACK_LINEAR)
25+
#define ALL_REV_FLAGS (((1u<<11)-1) | USER_GIVEN | TRACK_LINEAR)
2526

2627
#define DECORATE_SHORT_REFS 1
2728
#define DECORATE_FULL_REFS 2

t/t5317-pack-objects-filter-objects.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,22 @@ test_expect_success 'verify blob:limit=1k' '
160160
test_cmp observed expected
161161
'
162162

163+
test_expect_success 'verify explicitly specifying oversized blob in input' '
164+
git -C r2 ls-files -s large.1000 large.10000 \
165+
| awk -f print_2.awk \
166+
| sort >expected &&
167+
git -C r2 pack-objects --rev --stdout --filter=blob:limit=1k >filter.pack <<-EOF &&
168+
HEAD
169+
$(git -C r2 rev-parse HEAD:large.10000)
170+
EOF
171+
git -C r2 index-pack ../filter.pack &&
172+
git -C r2 verify-pack -v ../filter.pack \
173+
| grep blob \
174+
| awk -f print_1.awk \
175+
| sort >observed &&
176+
test_cmp observed expected
177+
'
178+
163179
test_expect_success 'verify blob:limit=1m' '
164180
git -C r2 ls-files -s large.1000 large.10000 \
165181
| awk -f print_2.awk \

t/t5616-partial-clone.sh

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,68 @@ test_expect_success 'partial clone with transfer.fsckobjects=1 uses index-pack -
154154
grep "git index-pack.*--fsck-objects" trace
155155
'
156156

157+
test_expect_success 'partial clone fetches blobs pointed to by refs even if normally filtered out' '
158+
rm -rf src dst &&
159+
git init src &&
160+
test_commit -C src x &&
161+
test_config -C src uploadpack.allowfilter 1 &&
162+
test_config -C src uploadpack.allowanysha1inwant 1 &&
163+
164+
# Create a tag pointing to a blob.
165+
BLOB=$(echo blob-contents | git -C src hash-object --stdin -w) &&
166+
git -C src tag myblob "$BLOB" &&
167+
168+
git clone --filter="blob:none" "file://$(pwd)/src" dst 2>err &&
169+
! grep "does not point to a valid object" err &&
170+
git -C dst fsck
171+
'
172+
173+
. "$TEST_DIRECTORY"/lib-httpd.sh
174+
start_httpd
175+
176+
# Converts bytes into a form suitable for inclusion in a sed command. For
177+
# example, "printf 'ab\r\n' | hex_unpack" results in '\x61\x62\x0d\x0a'.
178+
sed_escape () {
179+
perl -e '$/ = undef; $input = <>; print unpack("H2" x length($input), $input)' |
180+
sed 's/\(..\)/\\x\1/g'
181+
}
182+
183+
test_expect_success 'upon cloning, check that all refs point to objects' '
184+
SERVER="$HTTPD_DOCUMENT_ROOT_PATH/server" &&
185+
rm -rf "$SERVER" repo &&
186+
test_create_repo "$SERVER" &&
187+
test_commit -C "$SERVER" foo &&
188+
test_config -C "$SERVER" uploadpack.allowfilter 1 &&
189+
test_config -C "$SERVER" uploadpack.allowanysha1inwant 1 &&
190+
191+
# Create a tag pointing to a blob.
192+
BLOB=$(echo blob-contents | git -C "$SERVER" hash-object --stdin -w) &&
193+
git -C "$SERVER" tag myblob "$BLOB" &&
194+
195+
# Craft a packfile not including that blob.
196+
git -C "$SERVER" rev-parse HEAD |
197+
git -C "$SERVER" pack-objects --stdout >incomplete.pack &&
198+
199+
# Replace the existing packfile with the crafted one. The protocol
200+
# requires that the packfile be sent in sideband 1, hence the extra
201+
# \x01 byte at the beginning.
202+
printf "1,/packfile/!c %04x\\\\x01%s0000" \
203+
"$(($(wc -c <incomplete.pack) + 5))" \
204+
"$(sed_escape <incomplete.pack)" \
205+
>"$HTTPD_ROOT_PATH/one-time-sed" &&
206+
207+
# Use protocol v2 because the sed command looks for the "packfile"
208+
# section header.
209+
test_config -C "$SERVER" protocol.version 2 &&
210+
test_must_fail git -c protocol.version=2 clone \
211+
--filter=blob:none $HTTPD_URL/one_time_sed/server repo 2>err &&
212+
213+
grep "did not send all necessary objects" err &&
214+
215+
# Ensure that the one-time-sed script was used.
216+
! test -e "$HTTPD_ROOT_PATH/one-time-sed"
217+
'
218+
219+
stop_httpd
220+
157221
test_done

0 commit comments

Comments
 (0)