33test_description=' test fetching bundles with --bundle-uri'
44
55. ./test-lib.sh
6+ . " $TEST_DIRECTORY " /lib-bundle.sh
67
78test_expect_success ' fail to clone from non-existent file' '
89 test_when_finished rm -rf test &&
@@ -19,10 +20,39 @@ test_expect_success 'fail to clone from non-bundle file' '
1920
2021test_expect_success ' create bundle' '
2122 git init clone-from &&
22- git -C clone-from checkout -b topic &&
23- test_commit -C clone-from A &&
24- test_commit -C clone-from B &&
25- git -C clone-from bundle create B.bundle topic
23+ (
24+ cd clone-from &&
25+ git checkout -b topic &&
26+
27+ test_commit A &&
28+ git bundle create A.bundle topic &&
29+
30+ test_commit B &&
31+ git bundle create B.bundle topic &&
32+
33+ # Create a bundle with reference pointing to non-existent object.
34+ commit_a=$(git rev-parse A) &&
35+ commit_b=$(git rev-parse B) &&
36+ sed -e "/^$/q" -e "s/$commit_a /$commit_b /" \
37+ <A.bundle >bad-header.bundle &&
38+ convert_bundle_to_pack \
39+ <A.bundle >>bad-header.bundle &&
40+
41+ tree_b=$(git rev-parse B^{tree}) &&
42+ cat >data <<-EOF &&
43+ tree $tree_b
44+ parent $commit_b
45+ author A U Thor
46+ committer A U Thor
47+
48+ commit: this is a commit with bad emails
49+
50+ EOF
51+ bad_commit=$(git hash-object --literally -t commit -w --stdin <data) &&
52+ git branch bad $bad_commit &&
53+ git bundle create bad-object.bundle bad &&
54+ git update-ref -d refs/heads/bad
55+ )
2656'
2757
2858test_expect_success ' clone with path bundle' '
@@ -33,6 +63,33 @@ test_expect_success 'clone with path bundle' '
3363 test_cmp expect actual
3464'
3565
66+ test_expect_success ' clone with bundle that has bad header' '
67+ # Write bundle ref fails, but clone can still proceed.
68+ git clone --bundle-uri="clone-from/bad-header.bundle" \
69+ clone-from clone-bad-header 2>err &&
70+ commit_b=$(git -C clone-from rev-parse B) &&
71+ test_grep "trying to write ref ' \' ' refs/bundles/topic' \' ' with nonexistent object $commit_b" err &&
72+ git -C clone-bad-header for-each-ref --format="%(refname)" >refs &&
73+ test_grep ! "refs/bundles/" refs
74+ '
75+
76+ test_expect_success ' clone with bundle that has bad object' '
77+ # Unbundle succeeds if no fsckObjects configured.
78+ git clone --bundle-uri="clone-from/bad-object.bundle" \
79+ clone-from clone-bad-object-no-fsck &&
80+ git -C clone-bad-object-no-fsck for-each-ref --format="%(refname)" >refs &&
81+ grep "refs/bundles/" refs >actual &&
82+ test_write_lines refs/bundles/bad >expect &&
83+ test_cmp expect actual &&
84+
85+ # Unbundle fails with fsckObjects set true, but clone can still proceed.
86+ git -c fetch.fsckObjects=true clone --bundle-uri="clone-from/bad-object.bundle" \
87+ clone-from clone-bad-object-fsck 2>err &&
88+ test_grep "missingEmail" err &&
89+ git -C clone-bad-object-fsck for-each-ref --format="%(refname)" >refs &&
90+ test_grep ! "refs/bundles/" refs
91+ '
92+
3693test_expect_success ' clone with path bundle and non-default hash' '
3794 test_when_finished "rm -rf clone-path-non-default-hash" &&
3895 GIT_DEFAULT_HASH=sha256 git clone --bundle-uri="clone-from/B.bundle" \
@@ -259,6 +316,128 @@ test_expect_success 'clone bundle list (file, any mode, all failures)' '
259316 ! grep "refs/bundles/" refs
260317'
261318
319+ test_expect_success ' negotiation: bundle with part of wanted commits' '
320+ test_when_finished "rm -f trace*.txt" &&
321+ GIT_TRACE_PACKET="$(pwd)/trace-packet.txt" \
322+ git clone --no-local --bundle-uri="clone-from/A.bundle" \
323+ clone-from nego-bundle-part &&
324+ git -C nego-bundle-part for-each-ref --format="%(refname)" >refs &&
325+ grep "refs/bundles/" refs >actual &&
326+ test_write_lines refs/bundles/topic >expect &&
327+ test_cmp expect actual &&
328+ # Ensure that refs/bundles/topic are sent as "have".
329+ tip=$(git -C clone-from rev-parse A) &&
330+ test_grep "clone> have $tip" trace-packet.txt
331+ '
332+
333+ test_expect_success ' negotiation: bundle with all wanted commits' '
334+ test_when_finished "rm -f trace*.txt" &&
335+ GIT_TRACE_PACKET="$(pwd)/trace-packet.txt" \
336+ git clone --no-local --single-branch --branch=topic --no-tags \
337+ --bundle-uri="clone-from/B.bundle" \
338+ clone-from nego-bundle-all &&
339+ git -C nego-bundle-all for-each-ref --format="%(refname)" >refs &&
340+ grep "refs/bundles/" refs >actual &&
341+ test_write_lines refs/bundles/topic >expect &&
342+ test_cmp expect actual &&
343+ # We already have all needed commits so no "want" needed.
344+ test_grep ! "clone> want " trace-packet.txt
345+ '
346+
347+ test_expect_success ' negotiation: bundle list (no heuristic)' '
348+ test_when_finished "rm -f trace*.txt" &&
349+ cat >bundle-list <<-EOF &&
350+ [bundle]
351+ version = 1
352+ mode = all
353+
354+ [bundle "bundle-1"]
355+ uri = file://$(pwd)/clone-from/bundle-1.bundle
356+
357+ [bundle "bundle-2"]
358+ uri = file://$(pwd)/clone-from/bundle-2.bundle
359+ EOF
360+
361+ GIT_TRACE_PACKET="$(pwd)/trace-packet.txt" \
362+ git clone --no-local --bundle-uri="file://$(pwd)/bundle-list" \
363+ clone-from nego-bundle-list-no-heuristic &&
364+
365+ git -C nego-bundle-list-no-heuristic for-each-ref --format="%(refname)" >refs &&
366+ grep "refs/bundles/" refs >actual &&
367+ cat >expect <<-\EOF &&
368+ refs/bundles/base
369+ refs/bundles/left
370+ EOF
371+ test_cmp expect actual &&
372+ tip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/left) &&
373+ test_grep "clone> have $tip" trace-packet.txt
374+ '
375+
376+ test_expect_success ' negotiation: bundle list (creationToken)' '
377+ test_when_finished "rm -f trace*.txt" &&
378+ cat >bundle-list <<-EOF &&
379+ [bundle]
380+ version = 1
381+ mode = all
382+ heuristic = creationToken
383+
384+ [bundle "bundle-1"]
385+ uri = file://$(pwd)/clone-from/bundle-1.bundle
386+ creationToken = 1
387+
388+ [bundle "bundle-2"]
389+ uri = file://$(pwd)/clone-from/bundle-2.bundle
390+ creationToken = 2
391+ EOF
392+
393+ GIT_TRACE_PACKET="$(pwd)/trace-packet.txt" \
394+ git clone --no-local --bundle-uri="file://$(pwd)/bundle-list" \
395+ clone-from nego-bundle-list-heuristic &&
396+
397+ git -C nego-bundle-list-heuristic for-each-ref --format="%(refname)" >refs &&
398+ grep "refs/bundles/" refs >actual &&
399+ cat >expect <<-\EOF &&
400+ refs/bundles/base
401+ refs/bundles/left
402+ EOF
403+ test_cmp expect actual &&
404+ tip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/left) &&
405+ test_grep "clone> have $tip" trace-packet.txt
406+ '
407+
408+ test_expect_success ' negotiation: bundle list with all wanted commits' '
409+ test_when_finished "rm -f trace*.txt" &&
410+ cat >bundle-list <<-EOF &&
411+ [bundle]
412+ version = 1
413+ mode = all
414+ heuristic = creationToken
415+
416+ [bundle "bundle-1"]
417+ uri = file://$(pwd)/clone-from/bundle-1.bundle
418+ creationToken = 1
419+
420+ [bundle "bundle-2"]
421+ uri = file://$(pwd)/clone-from/bundle-2.bundle
422+ creationToken = 2
423+ EOF
424+
425+ GIT_TRACE_PACKET="$(pwd)/trace-packet.txt" \
426+ git clone --no-local --single-branch --branch=left --no-tags \
427+ --bundle-uri="file://$(pwd)/bundle-list" \
428+ clone-from nego-bundle-list-all &&
429+
430+ git -C nego-bundle-list-all for-each-ref --format="%(refname)" >refs &&
431+ grep "refs/bundles/" refs >actual &&
432+ cat >expect <<-\EOF &&
433+ refs/bundles/base
434+ refs/bundles/left
435+ EOF
436+ test_cmp expect actual &&
437+ # We already have all needed commits so no "want" needed.
438+ test_grep ! "clone> want " trace-packet.txt
439+ '
440+
262441# ########################################################################
263442# HTTP tests begin here
264443
0 commit comments