Merge branch 'jc/commit-hook-authorship' into maint
[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 . ./test-lib.sh
9
10 D=`pwd`
11
12 test_bundle_object_count () {
13         git verify-pack -v "$1" >verify.out &&
14         test "$2" = $(grep '^[0-9a-f]\{40\} ' verify.out | wc -l)
15 }
16
17 convert_bundle_to_pack () {
18         while read x && test -n "$x"
19         do
20                 :;
21         done
22         cat
23 }
24
25 test_expect_success setup '
26         echo >file original &&
27         git add file &&
28         git commit -a -m original'
29
30 test_expect_success "clone and setup child repos" '
31         git clone . one &&
32         (
33                 cd one &&
34                 echo >file updated by one &&
35                 git commit -a -m "updated by one"
36         ) &&
37         git clone . two &&
38         (
39                 cd two &&
40                 git config branch.master.remote one &&
41                 git config remote.one.url ../one/.git/ &&
42                 git config remote.one.fetch refs/heads/master:refs/heads/one
43         ) &&
44         git clone . three &&
45         (
46                 cd three &&
47                 git config branch.master.remote two &&
48                 git config branch.master.merge refs/heads/one &&
49                 mkdir -p .git/remotes &&
50                 {
51                         echo "URL: ../two/.git/"
52                         echo "Pull: refs/heads/master:refs/heads/two"
53                         echo "Pull: refs/heads/one:refs/heads/one"
54                 } >.git/remotes/two
55         ) &&
56         git clone . bundle &&
57         git clone . seven
58 '
59
60 test_expect_success "fetch test" '
61         cd "$D" &&
62         echo >file updated by origin &&
63         git commit -a -m "updated by origin" &&
64         cd two &&
65         git fetch &&
66         test -f .git/refs/heads/one &&
67         mine=`git rev-parse refs/heads/one` &&
68         his=`cd ../one && git rev-parse refs/heads/master` &&
69         test "z$mine" = "z$his"
70 '
71
72 test_expect_success "fetch test for-merge" '
73         cd "$D" &&
74         cd three &&
75         git fetch &&
76         test -f .git/refs/heads/two &&
77         test -f .git/refs/heads/one &&
78         master_in_two=`cd ../two && git rev-parse master` &&
79         one_in_two=`cd ../two && git rev-parse one` &&
80         {
81                 echo "$one_in_two       "
82                 echo "$master_in_two    not-for-merge"
83         } >expected &&
84         cut -f -2 .git/FETCH_HEAD >actual &&
85         test_cmp expected actual'
86
87 test_expect_success 'fetch --prune on its own works as expected' '
88         cd "$D" &&
89         git clone . prune &&
90         cd prune &&
91         git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
92
93         git fetch --prune origin &&
94         test_must_fail git rev-parse origin/extrabranch
95 '
96
97 test_expect_success 'fetch --prune with a branch name keeps branches' '
98         cd "$D" &&
99         git clone . prune-branch &&
100         cd prune-branch &&
101         git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
102
103         git fetch --prune origin master &&
104         git rev-parse origin/extrabranch
105 '
106
107 test_expect_success 'fetch --prune with a namespace keeps other namespaces' '
108         cd "$D" &&
109         git clone . prune-namespace &&
110         cd prune-namespace &&
111
112         git fetch --prune origin refs/heads/a/*:refs/remotes/origin/a/* &&
113         git rev-parse origin/master
114 '
115
116 test_expect_success 'fetch --prune --tags does not delete the remote-tracking branches' '
117         cd "$D" &&
118         git clone . prune-tags &&
119         cd prune-tags &&
120         git fetch origin refs/heads/master:refs/tags/sometag &&
121
122         git fetch --prune --tags origin &&
123         git rev-parse origin/master &&
124         test_must_fail git rev-parse somebranch
125 '
126
127 test_expect_success 'fetch --prune --tags with branch does not delete other remote-tracking branches' '
128         cd "$D" &&
129         git clone . prune-tags-branch &&
130         cd prune-tags-branch &&
131         git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
132
133         git fetch --prune --tags origin master &&
134         git rev-parse origin/extrabranch
135 '
136
137 test_expect_success 'fetch tags when there is no tags' '
138
139     cd "$D" &&
140
141     mkdir notags &&
142     cd notags &&
143     git init &&
144
145     git fetch -t ..
146
147 '
148
149 test_expect_success 'fetch following tags' '
150
151         cd "$D" &&
152         git tag -a -m 'annotated' anno HEAD &&
153         git tag light HEAD &&
154
155         mkdir four &&
156         cd four &&
157         git init &&
158
159         git fetch .. :track &&
160         git show-ref --verify refs/tags/anno &&
161         git show-ref --verify refs/tags/light
162
163 '
164
165 test_expect_success 'fetch must not resolve short tag name' '
166
167         cd "$D" &&
168
169         mkdir five &&
170         cd five &&
171         git init &&
172
173         test_must_fail git fetch .. anno:five
174
175 '
176
177 test_expect_success 'fetch can now resolve short remote name' '
178
179         cd "$D" &&
180         git update-ref refs/remotes/six/HEAD HEAD &&
181
182         mkdir six &&
183         cd six &&
184         git init &&
185
186         git fetch .. six:six
187 '
188
189 test_expect_success 'create bundle 1' '
190         cd "$D" &&
191         echo >file updated again by origin &&
192         git commit -a -m "tip" &&
193         git bundle create bundle1 master^..master
194 '
195
196 test_expect_success 'header of bundle looks right' '
197         head -n 1 "$D"/bundle1 | grep "^#" &&
198         head -n 2 "$D"/bundle1 | grep "^-[0-9a-f]\{40\} " &&
199         head -n 3 "$D"/bundle1 | grep "^[0-9a-f]\{40\} " &&
200         head -n 4 "$D"/bundle1 | grep "^$"
201 '
202
203 test_expect_success 'create bundle 2' '
204         cd "$D" &&
205         git bundle create bundle2 master~2..master
206 '
207
208 test_expect_success 'unbundle 1' '
209         cd "$D/bundle" &&
210         git checkout -b some-branch &&
211         test_must_fail git fetch "$D/bundle1" master:master
212 '
213
214
215 test_expect_success 'bundle 1 has only 3 files ' '
216         cd "$D" &&
217         convert_bundle_to_pack <bundle1 >bundle.pack &&
218         git index-pack bundle.pack &&
219         test_bundle_object_count bundle.pack 3
220 '
221
222 test_expect_success 'unbundle 2' '
223         cd "$D/bundle" &&
224         git fetch ../bundle2 master:master &&
225         test "tip" = "$(git log -1 --pretty=oneline master | cut -b42-)"
226 '
227
228 test_expect_success 'bundle does not prerequisite objects' '
229         cd "$D" &&
230         touch file2 &&
231         git add file2 &&
232         git commit -m add.file2 file2 &&
233         git bundle create bundle3 -1 HEAD &&
234         convert_bundle_to_pack <bundle3 >bundle.pack &&
235         git index-pack bundle.pack &&
236         test_bundle_object_count bundle.pack 3
237 '
238
239 test_expect_success 'bundle should be able to create a full history' '
240
241         cd "$D" &&
242         git tag -a -m '1.0' v1.0 master &&
243         git bundle create bundle4 v1.0
244
245 '
246
247 ! rsync --help > /dev/null 2> /dev/null &&
248 say 'Skipping rsync tests because rsync was not found' || {
249 test_expect_success 'fetch via rsync' '
250         git pack-refs &&
251         mkdir rsynced &&
252         (cd rsynced &&
253          git init --bare &&
254          git fetch "rsync:$(pwd)/../.git" master:refs/heads/master &&
255          git gc --prune &&
256          test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
257          git fsck --full)
258 '
259
260 test_expect_success 'push via rsync' '
261         mkdir rsynced2 &&
262         (cd rsynced2 &&
263          git init) &&
264         (cd rsynced &&
265          git push "rsync:$(pwd)/../rsynced2/.git" master) &&
266         (cd rsynced2 &&
267          git gc --prune &&
268          test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
269          git fsck --full)
270 '
271
272 test_expect_success 'push via rsync' '
273         mkdir rsynced3 &&
274         (cd rsynced3 &&
275          git init) &&
276         git push --all "rsync:$(pwd)/rsynced3/.git" &&
277         (cd rsynced3 &&
278          test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
279          git fsck --full)
280 '
281 }
282
283 test_expect_success 'fetch with a non-applying branch.<name>.merge' '
284         git config branch.master.remote yeti &&
285         git config branch.master.merge refs/heads/bigfoot &&
286         git config remote.blub.url one &&
287         git config remote.blub.fetch "refs/heads/*:refs/remotes/one/*" &&
288         git fetch blub
289 '
290
291 # URL supplied to fetch does not match the url of the configured branch's remote
292 test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [1]' '
293         one_head=$(cd one && git rev-parse HEAD) &&
294         this_head=$(git rev-parse HEAD) &&
295         git update-ref -d FETCH_HEAD &&
296         git fetch one &&
297         test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
298         test $this_head = "$(git rev-parse --verify HEAD)"
299 '
300
301 # URL supplied to fetch matches the url of the configured branch's remote and
302 # the merge spec matches the branch the remote HEAD points to
303 test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [2]' '
304         one_ref=$(cd one && git symbolic-ref HEAD) &&
305         git config branch.master.remote blub &&
306         git config branch.master.merge "$one_ref" &&
307         git update-ref -d FETCH_HEAD &&
308         git fetch one &&
309         test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
310         test $this_head = "$(git rev-parse --verify HEAD)"
311 '
312
313 # URL supplied to fetch matches the url of the configured branch's remote, but
314 # the merge spec does not match the branch the remote HEAD points to
315 test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [3]' '
316         git config branch.master.merge "${one_ref}_not" &&
317         git update-ref -d FETCH_HEAD &&
318         git fetch one &&
319         test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
320         test $this_head = "$(git rev-parse --verify HEAD)"
321 '
322
323 # the strange name is: a\!'b
324 test_expect_success 'quoting of a strangely named repo' '
325         test_must_fail git fetch "a\\!'\''b" > result 2>&1 &&
326         cat result &&
327         grep "fatal: '\''a\\\\!'\''b'\''" result
328 '
329
330 test_expect_success 'bundle should record HEAD correctly' '
331
332         cd "$D" &&
333         git bundle create bundle5 HEAD master &&
334         git bundle list-heads bundle5 >actual &&
335         for h in HEAD refs/heads/master
336         do
337                 echo "$(git rev-parse --verify $h) $h"
338         done >expect &&
339         test_cmp expect actual
340
341 '
342
343 test_expect_success 'explicit fetch should not update tracking' '
344
345         cd "$D" &&
346         git branch -f side &&
347         (
348                 cd three &&
349                 o=$(git rev-parse --verify refs/remotes/origin/master) &&
350                 git fetch origin master &&
351                 n=$(git rev-parse --verify refs/remotes/origin/master) &&
352                 test "$o" = "$n" &&
353                 test_must_fail git rev-parse --verify refs/remotes/origin/side
354         )
355 '
356
357 test_expect_success 'explicit pull should not update tracking' '
358
359         cd "$D" &&
360         git branch -f side &&
361         (
362                 cd three &&
363                 o=$(git rev-parse --verify refs/remotes/origin/master) &&
364                 git pull origin master &&
365                 n=$(git rev-parse --verify refs/remotes/origin/master) &&
366                 test "$o" = "$n" &&
367                 test_must_fail git rev-parse --verify refs/remotes/origin/side
368         )
369 '
370
371 test_expect_success 'configured fetch updates tracking' '
372
373         cd "$D" &&
374         git branch -f side &&
375         (
376                 cd three &&
377                 o=$(git rev-parse --verify refs/remotes/origin/master) &&
378                 git fetch origin &&
379                 n=$(git rev-parse --verify refs/remotes/origin/master) &&
380                 test "$o" != "$n" &&
381                 git rev-parse --verify refs/remotes/origin/side
382         )
383 '
384
385 test_expect_success 'pushing nonexistent branch by mistake should not segv' '
386
387         cd "$D" &&
388         test_must_fail git push seven no:no
389
390 '
391
392 test_expect_success 'auto tag following fetches minimum' '
393
394         cd "$D" &&
395         git clone .git follow &&
396         git checkout HEAD^0 &&
397         (
398                 for i in 1 2 3 4 5 6 7
399                 do
400                         echo $i >>file &&
401                         git commit -m $i -a &&
402                         git tag -a -m $i excess-$i || exit 1
403                 done
404         ) &&
405         git checkout master &&
406         (
407                 cd follow &&
408                 git fetch
409         )
410 '
411
412 test_expect_success 'refuse to fetch into the current branch' '
413
414         test_must_fail git fetch . side:master
415
416 '
417
418 test_expect_success 'fetch into the current branch with --update-head-ok' '
419
420         git fetch --update-head-ok . side:master
421
422 '
423
424 test_expect_success 'fetch --dry-run' '
425
426         rm -f .git/FETCH_HEAD &&
427         git fetch --dry-run . &&
428         ! test -f .git/FETCH_HEAD
429 '
430
431 test_expect_success "should be able to fetch with duplicate refspecs" '
432         mkdir dups &&
433         (
434                 cd dups &&
435                 git init &&
436                 git config branch.master.remote three &&
437                 git config remote.three.url ../three/.git &&
438                 git config remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
439                 git config --add remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
440                 git fetch three
441         )
442 '
443
444 test_expect_success 'all boundary commits are excluded' '
445         test_commit base &&
446         test_commit oneside &&
447         git checkout HEAD^ &&
448         test_commit otherside &&
449         git checkout master &&
450         test_tick &&
451         git merge otherside &&
452         ad=$(git log --no-walk --format=%ad HEAD) &&
453         git bundle create twoside-boundary.bdl master --since="$ad" &&
454         convert_bundle_to_pack <twoside-boundary.bdl >twoside-boundary.pack &&
455         pack=$(git index-pack --fix-thin --stdin <twoside-boundary.pack) &&
456         test_bundle_object_count .git/objects/pack/pack-${pack##pack    }.pack 3
457 '
458
459 test_done