]>
Commit | Line | Data |
---|---|---|
c0192df6 JK |
1 | #!/bin/sh |
2 | # Copyright (c) 2020, Jacob Keller. | |
3 | ||
4 | test_description='"git fetch" with negative refspecs. | |
5 | ||
6 | ' | |
7 | ||
028cb644 | 8 | GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main |
334afbc7 JS |
9 | export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME |
10 | ||
c0192df6 JK |
11 | . ./test-lib.sh |
12 | ||
13 | test_expect_success setup ' | |
14 | echo >file original && | |
15 | git add file && | |
16 | git commit -a -m original | |
17 | ' | |
18 | ||
19 | test_expect_success "clone and setup child repos" ' | |
20 | git clone . one && | |
21 | ( | |
22 | cd one && | |
23 | echo >file updated by one && | |
24 | git commit -a -m "updated by one" && | |
25 | git switch -c alternate && | |
26 | echo >file updated again by one && | |
27 | git commit -a -m "updated by one again" && | |
028cb644 | 28 | git switch main |
c0192df6 JK |
29 | ) && |
30 | git clone . two && | |
31 | ( | |
32 | cd two && | |
028cb644 | 33 | git config branch.main.remote one && |
c0192df6 JK |
34 | git config remote.one.url ../one/.git/ && |
35 | git config remote.one.fetch +refs/heads/*:refs/remotes/one/* && | |
36 | git config --add remote.one.fetch ^refs/heads/alternate | |
37 | ) && | |
38 | git clone . three | |
39 | ' | |
40 | ||
41 | test_expect_success "fetch one" ' | |
42 | echo >file updated by origin && | |
43 | git commit -a -m "updated by origin" && | |
44 | ( | |
45 | cd two && | |
46 | test_must_fail git rev-parse --verify refs/remotes/one/alternate && | |
47 | git fetch one && | |
48 | test_must_fail git rev-parse --verify refs/remotes/one/alternate && | |
028cb644 JS |
49 | git rev-parse --verify refs/remotes/one/main && |
50 | mine=$(git rev-parse refs/remotes/one/main) && | |
51 | his=$(cd ../one && git rev-parse refs/heads/main) && | |
c0192df6 JK |
52 | test "z$mine" = "z$his" |
53 | ) | |
54 | ' | |
55 | ||
56 | test_expect_success "fetch with negative refspec on commandline" ' | |
57 | echo >file updated by origin again && | |
58 | git commit -a -m "updated by origin again" && | |
59 | ( | |
60 | cd three && | |
61 | alternate_in_one=$(cd ../one && git rev-parse refs/heads/alternate) && | |
62 | echo $alternate_in_one >expect && | |
028cb644 | 63 | git fetch ../one/.git refs/heads/*:refs/remotes/one/* ^refs/heads/main && |
c0192df6 JK |
64 | cut -f -1 .git/FETCH_HEAD >actual && |
65 | test_cmp expect actual | |
66 | ) | |
67 | ' | |
68 | ||
69 | test_expect_success "fetch with negative sha1 refspec fails" ' | |
70 | echo >file updated by origin yet again && | |
71 | git commit -a -m "updated by origin yet again" && | |
72 | ( | |
73 | cd three && | |
028cb644 JS |
74 | main_in_one=$(cd ../one && git rev-parse refs/heads/main) && |
75 | test_must_fail git fetch ../one/.git refs/heads/*:refs/remotes/one/* ^$main_in_one | |
c0192df6 JK |
76 | ) |
77 | ' | |
78 | ||
79 | test_expect_success "fetch with negative pattern refspec" ' | |
80 | echo >file updated by origin once more && | |
81 | git commit -a -m "updated by origin once more" && | |
82 | ( | |
83 | cd three && | |
84 | alternate_in_one=$(cd ../one && git rev-parse refs/heads/alternate) && | |
85 | echo $alternate_in_one >expect && | |
86 | git fetch ../one/.git refs/heads/*:refs/remotes/one/* ^refs/heads/m* && | |
87 | cut -f -1 .git/FETCH_HEAD >actual && | |
88 | test_cmp expect actual | |
89 | ) | |
90 | ' | |
91 | ||
92 | test_expect_success "fetch with negative pattern refspec does not expand prefix" ' | |
93 | echo >file updated by origin another time && | |
94 | git commit -a -m "updated by origin another time" && | |
95 | ( | |
96 | cd three && | |
97 | alternate_in_one=$(cd ../one && git rev-parse refs/heads/alternate) && | |
028cb644 | 98 | main_in_one=$(cd ../one && git rev-parse refs/heads/main) && |
c0192df6 | 99 | echo $alternate_in_one >expect && |
028cb644 JS |
100 | echo $main_in_one >>expect && |
101 | git fetch ../one/.git refs/heads/*:refs/remotes/one/* ^main && | |
c0192df6 JK |
102 | cut -f -1 .git/FETCH_HEAD >actual && |
103 | test_cmp expect actual | |
104 | ) | |
105 | ' | |
106 | ||
107 | test_expect_success "fetch with negative refspec avoids duplicate conflict" ' | |
c0192df6 JK |
108 | ( |
109 | cd one && | |
110 | git branch dups/a && | |
111 | git branch dups/b && | |
112 | git branch dups/c && | |
113 | git branch other/a && | |
114 | git rev-parse --verify refs/heads/other/a >../expect && | |
115 | git rev-parse --verify refs/heads/dups/b >>../expect && | |
116 | git rev-parse --verify refs/heads/dups/c >>../expect | |
117 | ) && | |
118 | ( | |
119 | cd three && | |
120 | git fetch ../one/.git ^refs/heads/dups/a refs/heads/dups/*:refs/dups/* refs/heads/other/a:refs/dups/a && | |
121 | git rev-parse --verify refs/dups/a >../actual && | |
122 | git rev-parse --verify refs/dups/b >>../actual && | |
123 | git rev-parse --verify refs/dups/c >>../actual | |
124 | ) && | |
125 | test_cmp expect actual | |
126 | ' | |
127 | ||
128 | test_expect_success "push --prune with negative refspec" ' | |
129 | ( | |
130 | cd two && | |
131 | git branch prune/a && | |
132 | git branch prune/b && | |
133 | git branch prune/c && | |
134 | git push ../three refs/heads/prune/* && | |
135 | git branch -d prune/a && | |
136 | git branch -d prune/b && | |
137 | git push --prune ../three refs/heads/prune/* ^refs/heads/prune/b | |
138 | ) && | |
139 | ( | |
140 | cd three && | |
141 | test_write_lines b c >expect && | |
142 | git for-each-ref --format="%(refname:lstrip=3)" refs/heads/prune/ >actual && | |
143 | test_cmp expect actual | |
144 | ) | |
145 | ' | |
146 | ||
147 | test_expect_success "push --prune with negative refspec apply to the destination" ' | |
148 | ( | |
149 | cd two && | |
150 | git branch ours/a && | |
151 | git branch ours/b && | |
152 | git branch ours/c && | |
153 | git push ../three refs/heads/ours/*:refs/heads/theirs/* && | |
154 | git branch -d ours/a && | |
155 | git branch -d ours/b && | |
156 | git push --prune ../three refs/heads/ours/*:refs/heads/theirs/* ^refs/heads/theirs/b | |
157 | ) && | |
158 | ( | |
159 | cd three && | |
160 | test_write_lines b c >expect && | |
161 | git for-each-ref --format="%(refname:lstrip=3)" refs/heads/theirs/ >actual && | |
162 | test_cmp expect actual | |
163 | ) | |
164 | ' | |
165 | ||
166 | test_expect_success "fetch --prune with negative refspec" ' | |
167 | ( | |
168 | cd two && | |
169 | git branch fetch/a && | |
170 | git branch fetch/b && | |
171 | git branch fetch/c | |
172 | ) && | |
173 | ( | |
174 | cd three && | |
175 | git fetch ../two/.git refs/heads/fetch/*:refs/heads/copied/* | |
176 | ) && | |
177 | ( | |
178 | cd two && | |
179 | git branch -d fetch/a && | |
180 | git branch -d fetch/b | |
181 | ) && | |
182 | ( | |
183 | cd three && | |
184 | test_write_lines b c >expect && | |
185 | git fetch -v ../two/.git --prune refs/heads/fetch/*:refs/heads/copied/* ^refs/heads/fetch/b && | |
186 | git for-each-ref --format="%(refname:lstrip=3)" refs/heads/copied/ >actual && | |
187 | test_cmp expect actual | |
188 | ) | |
189 | ' | |
190 | ||
18f9c988 NK |
191 | test_expect_success "push with matching : and negative refspec" ' |
192 | # Manually handle cleanup, since test_config is not | |
193 | # prepared to take arbitrary options like --add | |
194 | test_when_finished "test_unconfig -C two remote.one.push" && | |
195 | ||
196 | # For convenience, we use "master" to refer to the name of | |
197 | # the branch created by default in the following. | |
198 | # | |
199 | # Repositories two and one have branches other than "master" | |
200 | # but they have no overlap---"master" is the only one that | |
201 | # is shared between them. And the master branch at two is | |
202 | # behind the master branch at one by one commit. | |
203 | git -C two config --add remote.one.push : && | |
204 | ||
205 | # A matching push tries to update master, fails due to non-ff | |
206 | test_must_fail git -C two push one && | |
207 | ||
208 | # "master" may actually not be "master"---find it out. | |
209 | current=$(git symbolic-ref HEAD) && | |
210 | ||
211 | # If master is in negative refspec, then the command will not attempt | |
212 | # to push and succeed. | |
213 | git -C two config --add remote.one.push "^$current" && | |
214 | ||
215 | # With "master" excluded, this push is a no-op. Nothing gets | |
216 | # pushed and it succeeds. | |
217 | git -C two push -v one | |
218 | ' | |
219 | ||
220 | test_expect_success "push with matching +: and negative refspec" ' | |
221 | test_when_finished "test_unconfig -C two remote.one.push" && | |
222 | ||
223 | # The same set-up as above, whose side-effect was a no-op. | |
224 | git -C two config --add remote.one.push +: && | |
225 | ||
226 | # The push refuses to update the "master" branch that is checked | |
227 | # out in the "one" repository, even when it is forced with +: | |
228 | test_must_fail git -C two push one && | |
229 | ||
230 | # "master" may actually not be "master"---find it out. | |
231 | current=$(git symbolic-ref HEAD) && | |
232 | ||
233 | # If master is in negative refspec, then the command will not attempt | |
234 | # to push and succeed | |
235 | git -C two config --add remote.one.push "^$current" && | |
236 | ||
237 | # With "master" excluded, this push is a no-op. Nothing gets | |
238 | # pushed and it succeeds. | |
239 | git -C two push -v one | |
240 | ' | |
241 | ||
2e03115d DS |
242 | test_expect_success '--prefetch correctly modifies refspecs' ' |
243 | git -C one config --unset-all remote.origin.fetch && | |
244 | git -C one config --add remote.origin.fetch ^refs/heads/bogus/ignore && | |
245 | git -C one config --add remote.origin.fetch "refs/tags/*:refs/tags/*" && | |
246 | git -C one config --add remote.origin.fetch "refs/heads/bogus/*:bogus/*" && | |
247 | ||
248 | git tag -a -m never never-fetch-tag HEAD && | |
249 | ||
250 | git branch bogus/fetched HEAD~1 && | |
251 | git branch bogus/ignore HEAD && | |
252 | ||
253 | git -C one fetch --prefetch --no-tags && | |
254 | test_must_fail git -C one rev-parse never-fetch-tag && | |
255 | git -C one rev-parse refs/prefetch/bogus/fetched && | |
256 | test_must_fail git -C one rev-parse refs/prefetch/bogus/ignore && | |
257 | ||
258 | # correctly handle when refspec set becomes empty | |
259 | # after removing the refs/tags/* refspec. | |
260 | git -C one config --unset-all remote.origin.fetch && | |
261 | git -C one config --add remote.origin.fetch "refs/tags/*:refs/tags/*" && | |
262 | ||
263 | git -C one fetch --prefetch --no-tags && | |
264 | test_must_fail git -C one rev-parse never-fetch-tag && | |
265 | ||
266 | # The refspec for refs that are not fully qualified | |
267 | # are filtered multiple times. | |
268 | git -C one rev-parse refs/prefetch/bogus/fetched && | |
269 | test_must_fail git -C one rev-parse refs/prefetch/bogus/ignore | |
270 | ' | |
271 | ||
272 | test_expect_success '--prefetch succeeds when refspec becomes empty' ' | |
273 | git checkout bogus/fetched && | |
274 | test_commit extra && | |
275 | ||
276 | git -C one config --unset-all remote.origin.fetch && | |
277 | git -C one config --unset branch.main.remote && | |
278 | git -C one config remote.origin.fetch "+refs/tags/extra" && | |
279 | git -C one config remote.origin.skipfetchall true && | |
280 | git -C one config remote.origin.tagopt "--no-tags" && | |
281 | ||
282 | git -C one fetch --prefetch | |
283 | ' | |
284 | ||
c0192df6 | 285 | test_done |