tests: mark tests relying on the current default for `init.defaultBranch`
[git] / t / t5510-fetch.sh
1 #!/bin/sh
2 # Copyright (c) 2006, Junio C Hamano.
3
4 test_description='Per branch config variables affects "git fetch".
5
6 '
7
8 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
9 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
10
11 . ./test-lib.sh
12
13 D=$(pwd)
14
15 test_bundle_object_count () {
16         git verify-pack -v "$1" >verify.out &&
17         test "$2" = $(grep "^$OID_REGEX " verify.out | wc -l)
18 }
19
20 convert_bundle_to_pack () {
21         while read x && test -n "$x"
22         do
23                 :;
24         done
25         cat
26 }
27
28 test_expect_success setup '
29         echo >file original &&
30         git add file &&
31         git commit -a -m original'
32
33 test_expect_success "clone and setup child repos" '
34         git clone . one &&
35         (
36                 cd one &&
37                 echo >file updated by one &&
38                 git commit -a -m "updated by one"
39         ) &&
40         git clone . two &&
41         (
42                 cd two &&
43                 git config branch.master.remote one &&
44                 git config remote.one.url ../one/.git/ &&
45                 git config remote.one.fetch refs/heads/master:refs/heads/one
46         ) &&
47         git clone . three &&
48         (
49                 cd three &&
50                 git config branch.master.remote two &&
51                 git config branch.master.merge refs/heads/one &&
52                 mkdir -p .git/remotes &&
53                 {
54                         echo "URL: ../two/.git/"
55                         echo "Pull: refs/heads/master:refs/heads/two"
56                         echo "Pull: refs/heads/one:refs/heads/one"
57                 } >.git/remotes/two
58         ) &&
59         git clone . bundle &&
60         git clone . seven
61 '
62
63 test_expect_success "fetch test" '
64         cd "$D" &&
65         echo >file updated by origin &&
66         git commit -a -m "updated by origin" &&
67         cd two &&
68         git fetch &&
69         git rev-parse --verify refs/heads/one &&
70         mine=$(git rev-parse refs/heads/one) &&
71         his=$(cd ../one && git rev-parse refs/heads/master) &&
72         test "z$mine" = "z$his"
73 '
74
75 test_expect_success "fetch test for-merge" '
76         cd "$D" &&
77         cd three &&
78         git fetch &&
79         git rev-parse --verify refs/heads/two &&
80         git rev-parse --verify refs/heads/one &&
81         master_in_two=$(cd ../two && git rev-parse master) &&
82         one_in_two=$(cd ../two && git rev-parse one) &&
83         {
84                 echo "$one_in_two       "
85                 echo "$master_in_two    not-for-merge"
86         } >expected &&
87         cut -f -2 .git/FETCH_HEAD >actual &&
88         test_cmp expected actual'
89
90 test_expect_success 'fetch --prune on its own works as expected' '
91         cd "$D" &&
92         git clone . prune &&
93         cd prune &&
94         git update-ref refs/remotes/origin/extrabranch master &&
95
96         git fetch --prune origin &&
97         test_must_fail git rev-parse origin/extrabranch
98 '
99
100 test_expect_success 'fetch --prune with a branch name keeps branches' '
101         cd "$D" &&
102         git clone . prune-branch &&
103         cd prune-branch &&
104         git update-ref refs/remotes/origin/extrabranch master &&
105
106         git fetch --prune origin master &&
107         git rev-parse origin/extrabranch
108 '
109
110 test_expect_success 'fetch --prune with a namespace keeps other namespaces' '
111         cd "$D" &&
112         git clone . prune-namespace &&
113         cd prune-namespace &&
114
115         git fetch --prune origin refs/heads/a/*:refs/remotes/origin/a/* &&
116         git rev-parse origin/master
117 '
118
119 test_expect_success 'fetch --prune handles overlapping refspecs' '
120         cd "$D" &&
121         git update-ref refs/pull/42/head master &&
122         git clone . prune-overlapping &&
123         cd prune-overlapping &&
124         git config --add remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
125
126         git fetch --prune origin &&
127         git rev-parse origin/master &&
128         git rev-parse origin/pr/42 &&
129
130         git config --unset-all remote.origin.fetch &&
131         git config remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
132         git config --add remote.origin.fetch refs/heads/*:refs/remotes/origin/* &&
133
134         git fetch --prune origin &&
135         git rev-parse origin/master &&
136         git rev-parse origin/pr/42
137 '
138
139 test_expect_success 'fetch --prune --tags prunes branches but not tags' '
140         cd "$D" &&
141         git clone . prune-tags &&
142         cd prune-tags &&
143         git tag sometag master &&
144         # Create what looks like a remote-tracking branch from an earlier
145         # fetch that has since been deleted from the remote:
146         git update-ref refs/remotes/origin/fake-remote master &&
147
148         git fetch --prune --tags origin &&
149         git rev-parse origin/master &&
150         test_must_fail git rev-parse origin/fake-remote &&
151         git rev-parse sometag
152 '
153
154 test_expect_success 'fetch --prune --tags with branch does not prune other things' '
155         cd "$D" &&
156         git clone . prune-tags-branch &&
157         cd prune-tags-branch &&
158         git tag sometag master &&
159         git update-ref refs/remotes/origin/extrabranch master &&
160
161         git fetch --prune --tags origin master &&
162         git rev-parse origin/extrabranch &&
163         git rev-parse sometag
164 '
165
166 test_expect_success 'fetch --prune --tags with refspec prunes based on refspec' '
167         cd "$D" &&
168         git clone . prune-tags-refspec &&
169         cd prune-tags-refspec &&
170         git tag sometag master &&
171         git update-ref refs/remotes/origin/foo/otherbranch master &&
172         git update-ref refs/remotes/origin/extrabranch master &&
173
174         git fetch --prune --tags origin refs/heads/foo/*:refs/remotes/origin/foo/* &&
175         test_must_fail git rev-parse refs/remotes/origin/foo/otherbranch &&
176         git rev-parse origin/extrabranch &&
177         git rev-parse sometag
178 '
179
180 test_expect_success '--refmap="" ignores configured refspec' '
181         cd "$TRASH_DIRECTORY" &&
182         git clone "$D" remote-refs &&
183         git -C remote-refs rev-parse remotes/origin/master >old &&
184         git -C remote-refs update-ref refs/remotes/origin/master master~1 &&
185         git -C remote-refs rev-parse remotes/origin/master >new &&
186         git -C remote-refs fetch --refmap= origin "+refs/heads/*:refs/hidden/origin/*" &&
187         git -C remote-refs rev-parse remotes/origin/master >actual &&
188         test_cmp new actual &&
189         git -C remote-refs fetch origin &&
190         git -C remote-refs rev-parse remotes/origin/master >actual &&
191         test_cmp old actual
192 '
193
194 test_expect_success '--refmap="" and --prune' '
195         git -C remote-refs update-ref refs/remotes/origin/foo/otherbranch master &&
196         git -C remote-refs update-ref refs/hidden/foo/otherbranch master &&
197         git -C remote-refs fetch --prune --refmap="" origin +refs/heads/*:refs/hidden/* &&
198         git -C remote-refs rev-parse remotes/origin/foo/otherbranch &&
199         test_must_fail git -C remote-refs rev-parse refs/hidden/foo/otherbranch &&
200         git -C remote-refs fetch --prune origin &&
201         test_must_fail git -C remote-refs rev-parse remotes/origin/foo/otherbranch
202 '
203
204 test_expect_success 'fetch tags when there is no tags' '
205
206     cd "$D" &&
207
208     mkdir notags &&
209     cd notags &&
210     git init &&
211
212     git fetch -t ..
213
214 '
215
216 test_expect_success 'fetch following tags' '
217
218         cd "$D" &&
219         git tag -a -m "annotated" anno HEAD &&
220         git tag light HEAD &&
221
222         mkdir four &&
223         cd four &&
224         git init &&
225
226         git fetch .. :track &&
227         git show-ref --verify refs/tags/anno &&
228         git show-ref --verify refs/tags/light
229
230 '
231
232 test_expect_success 'fetch uses remote ref names to describe new refs' '
233         cd "$D" &&
234         git init descriptive &&
235         (
236                 cd descriptive &&
237                 git config remote.o.url .. &&
238                 git config remote.o.fetch "refs/heads/*:refs/crazyheads/*" &&
239                 git config --add remote.o.fetch "refs/others/*:refs/heads/*" &&
240                 git fetch o
241         ) &&
242         git tag -a -m "Descriptive tag" descriptive-tag &&
243         git branch descriptive-branch &&
244         git checkout descriptive-branch &&
245         echo "Nuts" >crazy &&
246         git add crazy &&
247         git commit -a -m "descriptive commit" &&
248         git update-ref refs/others/crazy HEAD &&
249         (
250                 cd descriptive &&
251                 git fetch o 2>actual &&
252                 test_i18ngrep "new branch.* -> refs/crazyheads/descriptive-branch$" actual &&
253                 test_i18ngrep "new tag.* -> descriptive-tag$" actual &&
254                 test_i18ngrep "new ref.* -> crazy$" actual
255         ) &&
256         git checkout master
257 '
258
259 test_expect_success 'fetch must not resolve short tag name' '
260
261         cd "$D" &&
262
263         mkdir five &&
264         cd five &&
265         git init &&
266
267         test_must_fail git fetch .. anno:five
268
269 '
270
271 test_expect_success 'fetch can now resolve short remote name' '
272
273         cd "$D" &&
274         git update-ref refs/remotes/six/HEAD HEAD &&
275
276         mkdir six &&
277         cd six &&
278         git init &&
279
280         git fetch .. six:six
281 '
282
283 test_expect_success 'create bundle 1' '
284         cd "$D" &&
285         echo >file updated again by origin &&
286         git commit -a -m "tip" &&
287         git bundle create --version=3 bundle1 master^..master
288 '
289
290 test_expect_success 'header of bundle looks right' '
291         cat >expect <<-EOF &&
292         # v3 git bundle
293         @object-format=$(test_oid algo)
294         -OID updated by origin
295         OID refs/heads/master
296
297         EOF
298         sed -e "s/$OID_REGEX/OID/g" -e "5q" "$D"/bundle1 >actual &&
299         test_cmp expect actual
300 '
301
302 test_expect_success 'create bundle 2' '
303         cd "$D" &&
304         git bundle create bundle2 master~2..master
305 '
306
307 test_expect_success 'unbundle 1' '
308         cd "$D/bundle" &&
309         git checkout -b some-branch &&
310         test_must_fail git fetch "$D/bundle1" master:master
311 '
312
313
314 test_expect_success 'bundle 1 has only 3 files ' '
315         cd "$D" &&
316         convert_bundle_to_pack <bundle1 >bundle.pack &&
317         git index-pack bundle.pack &&
318         test_bundle_object_count bundle.pack 3
319 '
320
321 test_expect_success 'unbundle 2' '
322         cd "$D/bundle" &&
323         git fetch ../bundle2 master:master &&
324         test "tip" = "$(git log -1 --pretty=oneline master | cut -d" " -f2)"
325 '
326
327 test_expect_success 'bundle does not prerequisite objects' '
328         cd "$D" &&
329         touch file2 &&
330         git add file2 &&
331         git commit -m add.file2 file2 &&
332         git bundle create bundle3 -1 HEAD &&
333         convert_bundle_to_pack <bundle3 >bundle.pack &&
334         git index-pack bundle.pack &&
335         test_bundle_object_count bundle.pack 3
336 '
337
338 test_expect_success 'bundle should be able to create a full history' '
339
340         cd "$D" &&
341         git tag -a -m "1.0" v1.0 master &&
342         git bundle create bundle4 v1.0
343
344 '
345
346 test_expect_success 'fetch with a non-applying branch.<name>.merge' '
347         git config branch.master.remote yeti &&
348         git config branch.master.merge refs/heads/bigfoot &&
349         git config remote.blub.url one &&
350         git config remote.blub.fetch "refs/heads/*:refs/remotes/one/*" &&
351         git fetch blub
352 '
353
354 # URL supplied to fetch does not match the url of the configured branch's remote
355 test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [1]' '
356         one_head=$(cd one && git rev-parse HEAD) &&
357         this_head=$(git rev-parse HEAD) &&
358         git update-ref -d FETCH_HEAD &&
359         git fetch one &&
360         test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
361         test $this_head = "$(git rev-parse --verify HEAD)"
362 '
363
364 # URL supplied to fetch matches the url of the configured branch's remote and
365 # the merge spec matches the branch the remote HEAD points to
366 test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [2]' '
367         one_ref=$(cd one && git symbolic-ref HEAD) &&
368         git config branch.master.remote blub &&
369         git config branch.master.merge "$one_ref" &&
370         git update-ref -d FETCH_HEAD &&
371         git fetch one &&
372         test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
373         test $this_head = "$(git rev-parse --verify HEAD)"
374 '
375
376 # URL supplied to fetch matches the url of the configured branch's remote, but
377 # the merge spec does not match the branch the remote HEAD points to
378 test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [3]' '
379         git config branch.master.merge "${one_ref}_not" &&
380         git update-ref -d FETCH_HEAD &&
381         git fetch one &&
382         test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
383         test $this_head = "$(git rev-parse --verify HEAD)"
384 '
385
386 # the strange name is: a\!'b
387 test_expect_success 'quoting of a strangely named repo' '
388         test_must_fail git fetch "a\\!'\''b" > result 2>&1 &&
389         grep "fatal: '\''a\\\\!'\''b'\''" result
390 '
391
392 test_expect_success 'bundle should record HEAD correctly' '
393
394         cd "$D" &&
395         git bundle create bundle5 HEAD master &&
396         git bundle list-heads bundle5 >actual &&
397         for h in HEAD refs/heads/master
398         do
399                 echo "$(git rev-parse --verify $h) $h"
400         done >expect &&
401         test_cmp expect actual
402
403 '
404
405 test_expect_success 'mark initial state of origin/master' '
406         (
407                 cd three &&
408                 git tag base-origin-master refs/remotes/origin/master
409         )
410 '
411
412 test_expect_success 'explicit fetch should update tracking' '
413
414         cd "$D" &&
415         git branch -f side &&
416         (
417                 cd three &&
418                 git update-ref refs/remotes/origin/master base-origin-master &&
419                 o=$(git rev-parse --verify refs/remotes/origin/master) &&
420                 git fetch origin master &&
421                 n=$(git rev-parse --verify refs/remotes/origin/master) &&
422                 test "$o" != "$n" &&
423                 test_must_fail git rev-parse --verify refs/remotes/origin/side
424         )
425 '
426
427 test_expect_success 'explicit pull should update tracking' '
428
429         cd "$D" &&
430         git branch -f side &&
431         (
432                 cd three &&
433                 git update-ref refs/remotes/origin/master base-origin-master &&
434                 o=$(git rev-parse --verify refs/remotes/origin/master) &&
435                 git pull origin master &&
436                 n=$(git rev-parse --verify refs/remotes/origin/master) &&
437                 test "$o" != "$n" &&
438                 test_must_fail git rev-parse --verify refs/remotes/origin/side
439         )
440 '
441
442 test_expect_success 'explicit --refmap is allowed only with command-line refspec' '
443         cd "$D" &&
444         (
445                 cd three &&
446                 test_must_fail git fetch --refmap="*:refs/remotes/none/*"
447         )
448 '
449
450 test_expect_success 'explicit --refmap option overrides remote.*.fetch' '
451         cd "$D" &&
452         git branch -f side &&
453         (
454                 cd three &&
455                 git update-ref refs/remotes/origin/master base-origin-master &&
456                 o=$(git rev-parse --verify refs/remotes/origin/master) &&
457                 git fetch --refmap="refs/heads/*:refs/remotes/other/*" origin master &&
458                 n=$(git rev-parse --verify refs/remotes/origin/master) &&
459                 test "$o" = "$n" &&
460                 test_must_fail git rev-parse --verify refs/remotes/origin/side &&
461                 git rev-parse --verify refs/remotes/other/master
462         )
463 '
464
465 test_expect_success 'explicitly empty --refmap option disables remote.*.fetch' '
466         cd "$D" &&
467         git branch -f side &&
468         (
469                 cd three &&
470                 git update-ref refs/remotes/origin/master base-origin-master &&
471                 o=$(git rev-parse --verify refs/remotes/origin/master) &&
472                 git fetch --refmap="" origin master &&
473                 n=$(git rev-parse --verify refs/remotes/origin/master) &&
474                 test "$o" = "$n" &&
475                 test_must_fail git rev-parse --verify refs/remotes/origin/side
476         )
477 '
478
479 test_expect_success 'configured fetch updates tracking' '
480
481         cd "$D" &&
482         git branch -f side &&
483         (
484                 cd three &&
485                 git update-ref refs/remotes/origin/master base-origin-master &&
486                 o=$(git rev-parse --verify refs/remotes/origin/master) &&
487                 git fetch origin &&
488                 n=$(git rev-parse --verify refs/remotes/origin/master) &&
489                 test "$o" != "$n" &&
490                 git rev-parse --verify refs/remotes/origin/side
491         )
492 '
493
494 test_expect_success 'non-matching refspecs do not confuse tracking update' '
495         cd "$D" &&
496         git update-ref refs/odd/location HEAD &&
497         (
498                 cd three &&
499                 git update-ref refs/remotes/origin/master base-origin-master &&
500                 git config --add remote.origin.fetch \
501                         refs/odd/location:refs/remotes/origin/odd &&
502                 o=$(git rev-parse --verify refs/remotes/origin/master) &&
503                 git fetch origin master &&
504                 n=$(git rev-parse --verify refs/remotes/origin/master) &&
505                 test "$o" != "$n" &&
506                 test_must_fail git rev-parse --verify refs/remotes/origin/odd
507         )
508 '
509
510 test_expect_success 'pushing nonexistent branch by mistake should not segv' '
511
512         cd "$D" &&
513         test_must_fail git push seven no:no
514
515 '
516
517 test_expect_success 'auto tag following fetches minimum' '
518
519         cd "$D" &&
520         git clone .git follow &&
521         git checkout HEAD^0 &&
522         (
523                 for i in 1 2 3 4 5 6 7
524                 do
525                         echo $i >>file &&
526                         git commit -m $i -a &&
527                         git tag -a -m $i excess-$i || exit 1
528                 done
529         ) &&
530         git checkout master &&
531         (
532                 cd follow &&
533                 git fetch
534         )
535 '
536
537 test_expect_success 'refuse to fetch into the current branch' '
538
539         test_must_fail git fetch . side:master
540
541 '
542
543 test_expect_success 'fetch into the current branch with --update-head-ok' '
544
545         git fetch --update-head-ok . side:master
546
547 '
548
549 test_expect_success 'fetch --dry-run does not touch FETCH_HEAD, but still prints what would be written' '
550         rm -f .git/FETCH_HEAD err &&
551         git fetch --dry-run . 2>err &&
552         ! test -f .git/FETCH_HEAD &&
553         grep FETCH_HEAD err
554 '
555
556 test_expect_success '--no-write-fetch-head does not touch FETCH_HEAD, and does not print what would be written' '
557         rm -f .git/FETCH_HEAD err &&
558         git fetch --no-write-fetch-head . 2>err &&
559         ! test -f .git/FETCH_HEAD &&
560         ! grep FETCH_HEAD err
561 '
562
563 test_expect_success '--write-fetch-head gets defeated by --dry-run' '
564         rm -f .git/FETCH_HEAD &&
565         git fetch --dry-run --write-fetch-head . &&
566         ! test -f .git/FETCH_HEAD
567 '
568
569 test_expect_success "should be able to fetch with duplicate refspecs" '
570         mkdir dups &&
571         (
572                 cd dups &&
573                 git init &&
574                 git config branch.master.remote three &&
575                 git config remote.three.url ../three/.git &&
576                 git config remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
577                 git config --add remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
578                 git fetch three
579         )
580 '
581
582 test_expect_success 'LHS of refspec follows ref disambiguation rules' '
583         mkdir lhs-ambiguous &&
584         (
585                 cd lhs-ambiguous &&
586                 git init server &&
587                 test_commit -C server unwanted &&
588                 test_commit -C server wanted &&
589
590                 git init client &&
591
592                 # Check a name coming after "refs" alphabetically ...
593                 git -C server update-ref refs/heads/s wanted &&
594                 git -C server update-ref refs/heads/refs/heads/s unwanted &&
595                 git -C client fetch ../server +refs/heads/s:refs/heads/checkthis &&
596                 git -C server rev-parse wanted >expect &&
597                 git -C client rev-parse checkthis >actual &&
598                 test_cmp expect actual &&
599
600                 # ... and one before.
601                 git -C server update-ref refs/heads/q wanted &&
602                 git -C server update-ref refs/heads/refs/heads/q unwanted &&
603                 git -C client fetch ../server +refs/heads/q:refs/heads/checkthis &&
604                 git -C server rev-parse wanted >expect &&
605                 git -C client rev-parse checkthis >actual &&
606                 test_cmp expect actual &&
607
608                 # Tags are preferred over branches like refs/{heads,tags}/*
609                 git -C server update-ref refs/tags/t wanted &&
610                 git -C server update-ref refs/heads/t unwanted &&
611                 git -C client fetch ../server +t:refs/heads/checkthis &&
612                 git -C server rev-parse wanted >expect &&
613                 git -C client rev-parse checkthis >actual
614         )
615 '
616
617 test_expect_success 'fetch.writeCommitGraph' '
618         git clone three write &&
619         (
620                 cd three &&
621                 test_commit new
622         ) &&
623         (
624                 cd write &&
625                 git -c fetch.writeCommitGraph fetch origin &&
626                 test_path_is_file .git/objects/info/commit-graphs/commit-graph-chain
627         )
628 '
629
630 test_expect_success 'fetch.writeCommitGraph with submodules' '
631         git clone dups super &&
632         (
633                 cd super &&
634                 git submodule add "file://$TRASH_DIRECTORY/three" &&
635                 git commit -m "add submodule"
636         ) &&
637         git clone "super" super-clone &&
638         (
639                 cd super-clone &&
640                 rm -rf .git/objects/info &&
641                 git -c fetch.writeCommitGraph=true fetch origin &&
642                 test_path_is_file .git/objects/info/commit-graphs/commit-graph-chain
643         )
644 '
645
646 # configured prune tests
647
648 set_config_tristate () {
649         # var=$1 val=$2
650         case "$2" in
651         unset)
652                 test_unconfig "$1"
653                 ;;
654         *)
655                 git config "$1" "$2"
656                 key=$(echo $1 | sed -e 's/^remote\.origin/fetch/')
657                 git_fetch_c="$git_fetch_c -c $key=$2"
658                 ;;
659         esac
660 }
661
662 test_configured_prune () {
663         test_configured_prune_type "$@" "name"
664         test_configured_prune_type "$@" "link"
665 }
666
667 test_configured_prune_type () {
668         fetch_prune=$1
669         remote_origin_prune=$2
670         fetch_prune_tags=$3
671         remote_origin_prune_tags=$4
672         expected_branch=$5
673         expected_tag=$6
674         cmdline=$7
675         mode=$8
676
677         if test -z "$cmdline_setup"
678         then
679                 test_expect_success 'setup cmdline_setup variable for subsequent test' '
680                         remote_url="file://$(git -C one config remote.origin.url)" &&
681                         remote_fetch="$(git -C one config remote.origin.fetch)" &&
682                         cmdline_setup="\"$remote_url\" \"$remote_fetch\""
683                 '
684         fi
685
686         if test "$mode" = 'link'
687         then
688                 new_cmdline=""
689
690                 if test "$cmdline" = ""
691                 then
692                         new_cmdline=$cmdline_setup
693                 else
694                         new_cmdline=$(printf "%s" "$cmdline" | perl -pe 's[origin(?!/)]["'"$remote_url"'"]g')
695                 fi
696
697                 if test "$fetch_prune_tags" = 'true' ||
698                    test "$remote_origin_prune_tags" = 'true'
699                 then
700                         if ! printf '%s' "$cmdline\n" | grep -q refs/remotes/origin/
701                         then
702                                 new_cmdline="$new_cmdline refs/tags/*:refs/tags/*"
703                         fi
704                 fi
705
706                 cmdline="$new_cmdline"
707         fi
708
709         test_expect_success "$mode prune fetch.prune=$1 remote.origin.prune=$2 fetch.pruneTags=$3 remote.origin.pruneTags=$4${7:+ $7}; branch:$5 tag:$6" '
710                 # make sure a newbranch is there in . and also in one
711                 git branch -f newbranch &&
712                 git tag -f newtag &&
713                 (
714                         cd one &&
715                         test_unconfig fetch.prune &&
716                         test_unconfig fetch.pruneTags &&
717                         test_unconfig remote.origin.prune &&
718                         test_unconfig remote.origin.pruneTags &&
719                         git fetch '"$cmdline_setup"' &&
720                         git rev-parse --verify refs/remotes/origin/newbranch &&
721                         git rev-parse --verify refs/tags/newtag
722                 ) &&
723
724                 # now remove them
725                 git branch -d newbranch &&
726                 git tag -d newtag &&
727
728                 # then test
729                 (
730                         cd one &&
731                         git_fetch_c="" &&
732                         set_config_tristate fetch.prune $fetch_prune &&
733                         set_config_tristate fetch.pruneTags $fetch_prune_tags &&
734                         set_config_tristate remote.origin.prune $remote_origin_prune &&
735                         set_config_tristate remote.origin.pruneTags $remote_origin_prune_tags &&
736
737                         if test "$mode" != "link"
738                         then
739                                 git_fetch_c=""
740                         fi &&
741                         git$git_fetch_c fetch '"$cmdline"' &&
742                         case "$expected_branch" in
743                         pruned)
744                                 test_must_fail git rev-parse --verify refs/remotes/origin/newbranch
745                                 ;;
746                         kept)
747                                 git rev-parse --verify refs/remotes/origin/newbranch
748                                 ;;
749                         esac &&
750                         case "$expected_tag" in
751                         pruned)
752                                 test_must_fail git rev-parse --verify refs/tags/newtag
753                                 ;;
754                         kept)
755                                 git rev-parse --verify refs/tags/newtag
756                                 ;;
757                         esac
758                 )
759         '
760 }
761
762 # $1 config: fetch.prune
763 # $2 config: remote.<name>.prune
764 # $3 config: fetch.pruneTags
765 # $4 config: remote.<name>.pruneTags
766 # $5 expect: branch to be pruned?
767 # $6 expect: tag to be pruned?
768 # $7 git-fetch $cmdline:
769 #
770 #                     $1    $2    $3    $4    $5     $6     $7
771 test_configured_prune unset unset unset unset kept   kept   ""
772 test_configured_prune unset unset unset unset kept   kept   "--no-prune"
773 test_configured_prune unset unset unset unset pruned kept   "--prune"
774 test_configured_prune unset unset unset unset kept   pruned \
775         "--prune origin refs/tags/*:refs/tags/*"
776 test_configured_prune unset unset unset unset pruned pruned \
777         "--prune origin refs/tags/*:refs/tags/* +refs/heads/*:refs/remotes/origin/*"
778
779 test_configured_prune false unset unset unset kept   kept   ""
780 test_configured_prune false unset unset unset kept   kept   "--no-prune"
781 test_configured_prune false unset unset unset pruned kept   "--prune"
782
783 test_configured_prune true  unset unset unset pruned kept   ""
784 test_configured_prune true  unset unset unset pruned kept   "--prune"
785 test_configured_prune true  unset unset unset kept   kept   "--no-prune"
786
787 test_configured_prune unset false unset unset kept   kept   ""
788 test_configured_prune unset false unset unset kept   kept   "--no-prune"
789 test_configured_prune unset false unset unset pruned kept   "--prune"
790
791 test_configured_prune false false unset unset kept   kept   ""
792 test_configured_prune false false unset unset kept   kept   "--no-prune"
793 test_configured_prune false false unset unset pruned kept   "--prune"
794 test_configured_prune false false unset unset kept   pruned \
795         "--prune origin refs/tags/*:refs/tags/*"
796 test_configured_prune false false unset unset pruned pruned \
797         "--prune origin refs/tags/*:refs/tags/* +refs/heads/*:refs/remotes/origin/*"
798
799 test_configured_prune true  false unset unset kept   kept   ""
800 test_configured_prune true  false unset unset pruned kept   "--prune"
801 test_configured_prune true  false unset unset kept   kept   "--no-prune"
802
803 test_configured_prune unset true  unset unset pruned kept   ""
804 test_configured_prune unset true  unset unset kept   kept   "--no-prune"
805 test_configured_prune unset true  unset unset pruned kept   "--prune"
806
807 test_configured_prune false true  unset unset pruned kept   ""
808 test_configured_prune false true  unset unset kept   kept   "--no-prune"
809 test_configured_prune false true  unset unset pruned kept   "--prune"
810
811 test_configured_prune true  true  unset unset pruned kept   ""
812 test_configured_prune true  true  unset unset pruned kept   "--prune"
813 test_configured_prune true  true  unset unset kept   kept   "--no-prune"
814 test_configured_prune true  true  unset unset kept   pruned \
815         "--prune origin refs/tags/*:refs/tags/*"
816 test_configured_prune true  true  unset unset pruned pruned \
817         "--prune origin refs/tags/*:refs/tags/* +refs/heads/*:refs/remotes/origin/*"
818
819 # --prune-tags on its own does nothing, needs --prune as well, same
820 # for fetch.pruneTags without fetch.prune
821 test_configured_prune unset unset unset unset kept kept     "--prune-tags"
822 test_configured_prune unset unset true unset  kept kept     ""
823 test_configured_prune unset unset unset true  kept kept     ""
824
825 # These will prune the tags
826 test_configured_prune unset unset unset unset pruned pruned "--prune --prune-tags"
827 test_configured_prune true  unset true  unset pruned pruned ""
828 test_configured_prune unset true  unset true  pruned pruned ""
829
830 # remote.<name>.pruneTags overrides fetch.pruneTags, just like
831 # remote.<name>.prune overrides fetch.prune if set.
832 test_configured_prune true  unset true unset pruned pruned  ""
833 test_configured_prune false true  false true  pruned pruned ""
834 test_configured_prune true  false true  false kept   kept   ""
835
836 # When --prune-tags is supplied it's ignored if an explicit refspec is
837 # given, same for the configuration options.
838 test_configured_prune unset unset unset unset pruned kept \
839         "--prune --prune-tags origin +refs/heads/*:refs/remotes/origin/*"
840 test_configured_prune unset unset true  unset pruned kept \
841         "--prune origin +refs/heads/*:refs/remotes/origin/*"
842 test_configured_prune unset unset unset true pruned  kept \
843         "--prune origin +refs/heads/*:refs/remotes/origin/*"
844
845 # Pruning that also takes place if a file:// url replaces a named
846 # remote. However, because there's no implicit
847 # +refs/heads/*:refs/remotes/origin/* refspec and supplying it on the
848 # command-line negates --prune-tags, the branches will not be pruned.
849 test_configured_prune_type unset unset unset unset kept   kept   "origin --prune-tags" "name"
850 test_configured_prune_type unset unset unset unset kept   kept   "origin --prune-tags" "link"
851 test_configured_prune_type unset unset unset unset pruned pruned "origin --prune --prune-tags" "name"
852 test_configured_prune_type unset unset unset unset kept   pruned "origin --prune --prune-tags" "link"
853 test_configured_prune_type unset unset unset unset pruned pruned "--prune --prune-tags origin" "name"
854 test_configured_prune_type unset unset unset unset kept   pruned "--prune --prune-tags origin" "link"
855 test_configured_prune_type unset unset true  unset pruned pruned "--prune origin" "name"
856 test_configured_prune_type unset unset true  unset kept   pruned "--prune origin" "link"
857 test_configured_prune_type unset unset unset true  pruned pruned "--prune origin" "name"
858 test_configured_prune_type unset unset unset true  kept   pruned "--prune origin" "link"
859 test_configured_prune_type true  unset true  unset pruned pruned "origin" "name"
860 test_configured_prune_type true  unset true  unset kept   pruned "origin" "link"
861 test_configured_prune_type unset  true true  unset pruned pruned "origin" "name"
862 test_configured_prune_type unset  true true  unset kept   pruned "origin" "link"
863 test_configured_prune_type unset  true unset true  pruned pruned "origin" "name"
864 test_configured_prune_type unset  true unset true  kept   pruned "origin" "link"
865
866 # When all remote.origin.fetch settings are deleted a --prune
867 # --prune-tags still implicitly supplies refs/tags/*:refs/tags/* so
868 # tags, but not tracking branches, will be deleted.
869 test_expect_success 'remove remote.origin.fetch "one"' '
870         (
871                 cd one &&
872                 git config --unset-all remote.origin.fetch
873         )
874 '
875 test_configured_prune_type unset unset unset unset kept pruned "origin --prune --prune-tags" "name"
876 test_configured_prune_type unset unset unset unset kept pruned "origin --prune --prune-tags" "link"
877
878 test_expect_success 'all boundary commits are excluded' '
879         test_commit base &&
880         test_commit oneside &&
881         git checkout HEAD^ &&
882         test_commit otherside &&
883         git checkout master &&
884         test_tick &&
885         git merge otherside &&
886         ad=$(git log --no-walk --format=%ad HEAD) &&
887         git bundle create twoside-boundary.bdl master --since="$ad" &&
888         convert_bundle_to_pack <twoside-boundary.bdl >twoside-boundary.pack &&
889         pack=$(git index-pack --fix-thin --stdin <twoside-boundary.pack) &&
890         test_bundle_object_count .git/objects/pack/pack-${pack##pack    }.pack 3
891 '
892
893 test_expect_success 'fetch --prune prints the remotes url' '
894         git branch goodbye &&
895         git clone . only-prunes &&
896         git branch -D goodbye &&
897         (
898                 cd only-prunes &&
899                 git fetch --prune origin 2>&1 | head -n1 >../actual
900         ) &&
901         echo "From ${D}/." >expect &&
902         test_i18ncmp expect actual
903 '
904
905 test_expect_success 'branchname D/F conflict resolved by --prune' '
906         git branch dir/file &&
907         git clone . prune-df-conflict &&
908         git branch -D dir/file &&
909         git branch dir &&
910         (
911                 cd prune-df-conflict &&
912                 git fetch --prune &&
913                 git rev-parse origin/dir >../actual
914         ) &&
915         git rev-parse dir >expect &&
916         test_cmp expect actual
917 '
918
919 test_expect_success 'fetching a one-level ref works' '
920         test_commit extra &&
921         git reset --hard HEAD^ &&
922         git update-ref refs/foo extra &&
923         git init one-level &&
924         (
925                 cd one-level &&
926                 git fetch .. HEAD refs/foo
927         )
928 '
929
930 test_expect_success 'fetching with auto-gc does not lock up' '
931         write_script askyesno <<-\EOF &&
932         echo "$*" &&
933         false
934         EOF
935         git clone "file://$D" auto-gc &&
936         test_commit test2 &&
937         (
938                 cd auto-gc &&
939                 git config fetch.unpackLimit 1 &&
940                 git config gc.autoPackLimit 1 &&
941                 git config gc.autoDetach false &&
942                 GIT_ASK_YESNO="$D/askyesno" git fetch --verbose >fetch.out 2>&1 &&
943                 test_i18ngrep "Auto packing the repository" fetch.out &&
944                 ! grep "Should I try again" fetch.out
945         )
946 '
947
948 test_expect_success PREPARE_FOR_MAIN_BRANCH,C_LOCALE_OUTPUT 'fetch aligned output' '
949         git clone . full-output &&
950         test_commit looooooooooooong-tag &&
951         (
952                 cd full-output &&
953                 git -c fetch.output=full fetch origin >actual 2>&1 &&
954                 grep -e "->" actual | cut -c 22- >../actual
955         ) &&
956         cat >expect <<-\EOF &&
957         main                 -> origin/main
958         looooooooooooong-tag -> looooooooooooong-tag
959         EOF
960         test_cmp expect actual
961 '
962
963 test_expect_success PREPARE_FOR_MAIN_BRANCH,C_LOCALE_OUTPUT 'fetch compact output' '
964         git clone . compact &&
965         test_commit extraaa &&
966         (
967                 cd compact &&
968                 git -c fetch.output=compact fetch origin >actual 2>&1 &&
969                 grep -e "->" actual | cut -c 22- >../actual
970         ) &&
971         cat >expect <<-\EOF &&
972         main       -> origin/*
973         extraaa    -> *
974         EOF
975         test_cmp expect actual
976 '
977
978 test_expect_success '--no-show-forced-updates' '
979         mkdir forced-updates &&
980         (
981                 cd forced-updates &&
982                 git init &&
983                 test_commit 1 &&
984                 test_commit 2
985         ) &&
986         git clone forced-updates forced-update-clone &&
987         git clone forced-updates no-forced-update-clone &&
988         git -C forced-updates reset --hard HEAD~1 &&
989         (
990                 cd forced-update-clone &&
991                 git fetch --show-forced-updates origin 2>output &&
992                 test_i18ngrep "(forced update)" output
993         ) &&
994         (
995                 cd no-forced-update-clone &&
996                 git fetch --no-show-forced-updates origin 2>output &&
997                 test_i18ngrep ! "(forced update)" output
998         )
999 '
1000
1001 setup_negotiation_tip () {
1002         SERVER="$1"
1003         URL="$2"
1004         USE_PROTOCOL_V2="$3"
1005
1006         rm -rf "$SERVER" client trace &&
1007         git init "$SERVER" &&
1008         test_commit -C "$SERVER" alpha_1 &&
1009         test_commit -C "$SERVER" alpha_2 &&
1010         git -C "$SERVER" checkout --orphan beta &&
1011         test_commit -C "$SERVER" beta_1 &&
1012         test_commit -C "$SERVER" beta_2 &&
1013
1014         git clone "$URL" client &&
1015
1016         if test "$USE_PROTOCOL_V2" -eq 1
1017         then
1018                 git -C "$SERVER" config protocol.version 2 &&
1019                 git -C client config protocol.version 2
1020         fi &&
1021
1022         test_commit -C "$SERVER" beta_s &&
1023         git -C "$SERVER" checkout master &&
1024         test_commit -C "$SERVER" alpha_s &&
1025         git -C "$SERVER" tag -d alpha_1 alpha_2 beta_1 beta_2
1026 }
1027
1028 check_negotiation_tip () {
1029         # Ensure that {alpha,beta}_1 are sent as "have", but not {alpha_beta}_2
1030         ALPHA_1=$(git -C client rev-parse alpha_1) &&
1031         grep "fetch> have $ALPHA_1" trace &&
1032         BETA_1=$(git -C client rev-parse beta_1) &&
1033         grep "fetch> have $BETA_1" trace &&
1034         ALPHA_2=$(git -C client rev-parse alpha_2) &&
1035         ! grep "fetch> have $ALPHA_2" trace &&
1036         BETA_2=$(git -C client rev-parse beta_2) &&
1037         ! grep "fetch> have $BETA_2" trace
1038 }
1039
1040 test_expect_success '--negotiation-tip limits "have" lines sent' '
1041         setup_negotiation_tip server server 0 &&
1042         GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1043                 --negotiation-tip=alpha_1 --negotiation-tip=beta_1 \
1044                 origin alpha_s beta_s &&
1045         check_negotiation_tip
1046 '
1047
1048 test_expect_success '--negotiation-tip understands globs' '
1049         setup_negotiation_tip server server 0 &&
1050         GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1051                 --negotiation-tip=*_1 \
1052                 origin alpha_s beta_s &&
1053         check_negotiation_tip
1054 '
1055
1056 test_expect_success '--negotiation-tip understands abbreviated SHA-1' '
1057         setup_negotiation_tip server server 0 &&
1058         GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1059                 --negotiation-tip=$(git -C client rev-parse --short alpha_1) \
1060                 --negotiation-tip=$(git -C client rev-parse --short beta_1) \
1061                 origin alpha_s beta_s &&
1062         check_negotiation_tip
1063 '
1064
1065 . "$TEST_DIRECTORY"/lib-httpd.sh
1066 start_httpd
1067
1068 test_expect_success '--negotiation-tip limits "have" lines sent with HTTP protocol v2' '
1069         setup_negotiation_tip "$HTTPD_DOCUMENT_ROOT_PATH/server" \
1070                 "$HTTPD_URL/smart/server" 1 &&
1071         GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1072                 --negotiation-tip=alpha_1 --negotiation-tip=beta_1 \
1073                 origin alpha_s beta_s &&
1074         check_negotiation_tip
1075 '
1076
1077 # DO NOT add non-httpd-specific tests here, because the last part of this
1078 # test script is only executed when httpd is available and enabled.
1079
1080 test_done