1#!/bin/sh
2
3test_description='git remote porcelain-ish'
4
5. ./test-lib.sh
6
7setup_repository () {
8 mkdir "$1" && (
9 cd "$1" &&
10 git init &&
11 >file &&
12 git add file &&
13 test_tick &&
14 git commit -m "Initial" &&
15 git checkout -b side &&
16 >elif &&
17 git add elif &&
18 test_tick &&
19 git commit -m "Second" &&
20 git checkout master
21 )
22}
23
24tokens_match () {
25 echo "$1" | tr ' ' '\012' | sort | sed -e '/^$/d' >expect &&
26 echo "$2" | tr ' ' '\012' | sort | sed -e '/^$/d' >actual &&
27 test_cmp expect actual
28}
29
30check_remote_track () {
31 actual=$(git remote show "$1" | sed -e '1,/Tracked/d') &&
32 shift &&
33 tokens_match "$*" "$actual"
34}
35
36check_tracking_branch () {
37 f="" &&
38 r=$(git for-each-ref "--format=%(refname)" |
39 sed -ne "s|^refs/remotes/$1/||p") &&
40 shift &&
41 tokens_match "$*" "$r"
42}
43
44test_expect_success setup '
45
46 setup_repository one &&
47 setup_repository two &&
48 (
49 cd two && git branch another
50 ) &&
51 git clone one test
52
53'
54
55test_expect_success 'remote information for the origin' '
56(
57 cd test &&
58 tokens_match origin "$(git remote)" &&
59 check_remote_track origin master side &&
60 check_tracking_branch origin HEAD master side
61)
62'
63
64test_expect_success 'add another remote' '
65(
66 cd test &&
67 git remote add -f second ../two &&
68 tokens_match "origin second" "$(git remote)" &&
69 check_remote_track origin master side &&
70 check_remote_track second master side another &&
71 check_tracking_branch second master side another &&
72 git for-each-ref "--format=%(refname)" refs/remotes |
73 sed -e "/^refs\/remotes\/origin\//d" \
74 -e "/^refs\/remotes\/second\//d" >actual &&
75 >expect &&
76 test_cmp expect actual
77)
78'
79
80test_expect_success 'remote forces tracking branches' '
81(
82 cd test &&
83 case `git config remote.second.fetch` in
84 +*) true ;;
85 *) false ;;
86 esac
87)
88'
89
90test_expect_success 'remove remote' '
91(
92 cd test &&
93 git symbolic-ref refs/remotes/second/HEAD refs/remotes/second/master &&
94 git remote rm second
95)
96'
97
98test_expect_success 'remove remote' '
99(
100 cd test &&
101 tokens_match origin "$(git remote)" &&
102 check_remote_track origin master side &&
103 git for-each-ref "--format=%(refname)" refs/remotes |
104 sed -e "/^refs\/remotes\/origin\//d" >actual &&
105 >expect &&
106 test_cmp expect actual
107)
108'
109
110test_expect_success 'remove remote protects non-remote branches' '
111(
112 cd test &&
113 (cat >expect1 <<EOF
114Note: A non-remote branch was not removed; to delete it, use:
115 git branch -d master
116EOF
117 cat >expect2 <<EOF
118Note: Non-remote branches were not removed; to delete them, use:
119 git branch -d foobranch
120 git branch -d master
121EOF
122) &&
123 git tag footag
124 git config --add remote.oops.fetch "+refs/*:refs/*" &&
125 git remote rm oops 2>actual1 &&
126 git branch foobranch &&
127 git config --add remote.oops.fetch "+refs/*:refs/*" &&
128 git remote rm oops 2>actual2 &&
129 git branch -d foobranch &&
130 git tag -d footag &&
131 test_cmp expect1 actual1 &&
132 test_cmp expect2 actual2
133)
134'
135
136cat > test/expect << EOF
137* remote origin
138 URL: $(pwd)/one
139 Remote branch merged with 'git pull' while on branch master
140 master
141 New remote branch (next fetch will store in remotes/origin)
142 master
143 Tracked remote branches
144 side
145 master
146 Local branches pushed with 'git push'
147 master:upstream
148 +refs/tags/lastbackup
149EOF
150
151test_expect_success 'show' '
152 (cd test &&
153 git config --add remote.origin.fetch \
154 refs/heads/master:refs/heads/upstream &&
155 git fetch &&
156 git branch -d -r origin/master &&
157 (cd ../one &&
158 echo 1 > file &&
159 test_tick &&
160 git commit -m update file) &&
161 git config remote.origin.push \
162 refs/heads/master:refs/heads/upstream &&
163 git config --add remote.origin.push \
164 +refs/tags/lastbackup &&
165 git remote show origin > output &&
166 test_cmp expect output)
167'
168
169cat > test/expect << EOF
170* remote origin
171 URL: $(pwd)/one
172 Remote branch merged with 'git pull' while on branch master
173 master
174 Tracked remote branches
175 master
176 side
177 Local branches pushed with 'git push'
178 master:upstream
179 +refs/tags/lastbackup
180EOF
181
182test_expect_success 'show -n' '
183 (mv one one.unreachable &&
184 cd test &&
185 git remote show -n origin > output &&
186 mv ../one.unreachable ../one &&
187 test_cmp expect output)
188'
189
190test_expect_success 'prune' '
191 (cd one &&
192 git branch -m side side2) &&
193 (cd test &&
194 git fetch origin &&
195 git remote prune origin &&
196 git rev-parse refs/remotes/origin/side2 &&
197 test_must_fail git rev-parse refs/remotes/origin/side)
198'
199
200cat > test/expect << EOF
201Pruning origin
202URL: $(pwd)/one
203 * [would prune] origin/side2
204EOF
205
206test_expect_success 'prune --dry-run' '
207 (cd one &&
208 git branch -m side2 side) &&
209 (cd test &&
210 git remote prune --dry-run origin > output &&
211 git rev-parse refs/remotes/origin/side2 &&
212 test_must_fail git rev-parse refs/remotes/origin/side &&
213 (cd ../one &&
214 git branch -m side side2) &&
215 test_cmp expect output)
216'
217
218test_expect_success 'add --mirror && prune' '
219 (mkdir mirror &&
220 cd mirror &&
221 git init --bare &&
222 git remote add --mirror -f origin ../one) &&
223 (cd one &&
224 git branch -m side2 side) &&
225 (cd mirror &&
226 git rev-parse --verify refs/heads/side2 &&
227 test_must_fail git rev-parse --verify refs/heads/side &&
228 git fetch origin &&
229 git remote prune origin &&
230 test_must_fail git rev-parse --verify refs/heads/side2 &&
231 git rev-parse --verify refs/heads/side)
232'
233
234test_expect_success 'add alt && prune' '
235 (mkdir alttst &&
236 cd alttst &&
237 git init &&
238 git remote add -f origin ../one &&
239 git config remote.alt.url ../one &&
240 git config remote.alt.fetch "+refs/heads/*:refs/remotes/origin/*") &&
241 (cd one &&
242 git branch -m side side2) &&
243 (cd alttst &&
244 git rev-parse --verify refs/remotes/origin/side &&
245 test_must_fail git rev-parse --verify refs/remotes/origin/side2 &&
246 git fetch alt &&
247 git remote prune alt &&
248 test_must_fail git rev-parse --verify refs/remotes/origin/side &&
249 git rev-parse --verify refs/remotes/origin/side2)
250'
251
252cat > one/expect << EOF
253 apis/master
254 apis/side
255 drosophila/another
256 drosophila/master
257 drosophila/side
258EOF
259
260test_expect_success 'update' '
261
262 (cd one &&
263 git remote add drosophila ../two &&
264 git remote add apis ../mirror &&
265 git remote update &&
266 git branch -r > output &&
267 test_cmp expect output)
268
269'
270
271cat > one/expect << EOF
272 drosophila/another
273 drosophila/master
274 drosophila/side
275 manduca/master
276 manduca/side
277 megaloprepus/master
278 megaloprepus/side
279EOF
280
281test_expect_success 'update with arguments' '
282
283 (cd one &&
284 for b in $(git branch -r)
285 do
286 git branch -r -d $b || break
287 done &&
288 git remote add manduca ../mirror &&
289 git remote add megaloprepus ../mirror &&
290 git config remotes.phobaeticus "drosophila megaloprepus" &&
291 git config remotes.titanus manduca &&
292 git remote update phobaeticus titanus &&
293 git branch -r > output &&
294 test_cmp expect output)
295
296'
297
298cat > one/expect << EOF
299 apis/master
300 apis/side
301 manduca/master
302 manduca/side
303 megaloprepus/master
304 megaloprepus/side
305EOF
306
307test_expect_success 'update default' '
308
309 (cd one &&
310 for b in $(git branch -r)
311 do
312 git branch -r -d $b || break
313 done &&
314 git config remote.drosophila.skipDefaultUpdate true &&
315 git remote update default &&
316 git branch -r > output &&
317 test_cmp expect output)
318
319'
320
321cat > one/expect << EOF
322 drosophila/another
323 drosophila/master
324 drosophila/side
325EOF
326
327test_expect_success 'update default (overridden, with funny whitespace)' '
328
329 (cd one &&
330 for b in $(git branch -r)
331 do
332 git branch -r -d $b || break
333 done &&
334 git config remotes.default "$(printf "\t drosophila \n")" &&
335 git remote update default &&
336 git branch -r > output &&
337 test_cmp expect output)
338
339'
340
341test_expect_success '"remote show" does not show symbolic refs' '
342
343 git clone one three &&
344 (cd three &&
345 git remote show origin > output &&
346 ! grep HEAD < output &&
347 ! grep -i stale < output)
348
349'
350
351test_expect_success 'reject adding remote with an invalid name' '
352
353 test_must_fail git remote add some:url desired-name
354
355'
356
357# The first three test if the tracking branches are properly renamed,
358# the last two ones check if the config is updated.
359
360test_expect_success 'rename a remote' '
361
362 git clone one four &&
363 (cd four &&
364 git remote rename origin upstream &&
365 rmdir .git/refs/remotes/origin &&
366 test "$(git symbolic-ref refs/remotes/upstream/HEAD)" = "refs/remotes/upstream/master" &&
367 test "$(git rev-parse upstream/master)" = "$(git rev-parse master)" &&
368 test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*" &&
369 test "$(git config branch.master.remote)" = "upstream")
370
371'
372
373cat > remotes_origin << EOF
374URL: $(pwd)/one
375Push: refs/heads/master:refs/heads/upstream
376Pull: refs/heads/master:refs/heads/origin
377EOF
378
379test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' '
380 git clone one five &&
381 origin_url=$(pwd)/one &&
382 (cd five &&
383 git remote rm origin &&
384 mkdir -p .git/remotes &&
385 cat ../remotes_origin > .git/remotes/origin &&
386 git remote rename origin origin &&
387 ! test -f .git/remotes/origin &&
388 test "$(git config remote.origin.url)" = "$origin_url" &&
389 test "$(git config remote.origin.push)" = "refs/heads/master:refs/heads/upstream" &&
390 test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
391'
392
393test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' '
394 git clone one six &&
395 origin_url=$(pwd)/one &&
396 (cd six &&
397 git remote rm origin &&
398 echo "$origin_url" > .git/branches/origin &&
399 git remote rename origin origin &&
400 ! test -f .git/branches/origin &&
401 test "$(git config remote.origin.url)" = "$origin_url" &&
402 test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
403'
404
405test_expect_success 'remote prune to cause a dangling symref' '
406 git clone one seven &&
407 (
408 cd one &&
409 git checkout side2 &&
410 git branch -D master
411 ) &&
412 (
413 cd seven &&
414 git remote prune origin
415 ) 2>err &&
416 grep "has become dangling" err &&
417
418 : And the dangling symref will not cause other annoying errors
419 (
420 cd seven &&
421 git branch -a
422 ) 2>err &&
423 ! grep "points nowhere" err
424 (
425 cd seven &&
426 test_must_fail git branch nomore origin
427 ) 2>err &&
428 grep "dangling symref" err
429'
430
431test_done
432