Sync with 'maint'
[alt-git.git] / t / t5533-push-cas.sh
blob6365d99777ead268ccd589d6990b07fd9c4ec33c
1 #!/bin/sh
3 test_description='compare & swap push force/delete safety'
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
8 TEST_PASSES_SANITIZE_LEAK=true
9 . ./test-lib.sh
11 setup_srcdst_basic () {
12 rm -fr src dst &&
13 git clone --no-local . src &&
14 git clone --no-local src dst &&
16 cd src && git checkout HEAD^0
20 # For tests with "--force-if-includes".
21 setup_src_dup_dst () {
22 rm -fr src dup dst &&
23 git init --bare dst &&
24 git clone --no-local dst src &&
25 git clone --no-local dst dup
27 cd src &&
28 test_commit A &&
29 test_commit B &&
30 test_commit C &&
31 git push origin
32 ) &&
34 cd dup &&
35 git fetch &&
36 git merge origin/main &&
37 git switch -c branch main~2 &&
38 test_commit D &&
39 test_commit E &&
40 git push origin --all
41 ) &&
43 cd src &&
44 git switch main &&
45 git fetch --all &&
46 git branch branch --track origin/branch &&
47 git rebase origin/main
48 ) &&
50 cd dup &&
51 git switch main &&
52 test_commit F &&
53 test_commit G &&
54 git switch branch &&
55 test_commit H &&
56 git push origin --all
60 test_expect_success setup '
61 # create template repository
62 test_commit A &&
63 test_commit B &&
64 test_commit C
67 test_expect_success 'push to update (protected)' '
68 setup_srcdst_basic &&
70 cd dst &&
71 test_commit D &&
72 test_must_fail git push --force-with-lease=main:main origin main 2>err &&
73 grep "stale info" err
74 ) &&
75 git ls-remote . refs/heads/main >expect &&
76 git ls-remote src refs/heads/main >actual &&
77 test_cmp expect actual
80 test_expect_success 'push to update (protected, forced)' '
81 setup_srcdst_basic &&
83 cd dst &&
84 test_commit D &&
85 git push --force --force-with-lease=main:main origin main 2>err &&
86 grep "forced update" err
87 ) &&
88 git ls-remote dst refs/heads/main >expect &&
89 git ls-remote src refs/heads/main >actual &&
90 test_cmp expect actual
93 test_expect_success 'push to update (protected, tracking)' '
94 setup_srcdst_basic &&
96 cd src &&
97 git checkout main &&
98 test_commit D &&
99 git checkout HEAD^0
100 ) &&
101 git ls-remote src refs/heads/main >expect &&
103 cd dst &&
104 test_commit E &&
105 git ls-remote . refs/remotes/origin/main >expect &&
106 test_must_fail git push --force-with-lease=main origin main &&
107 git ls-remote . refs/remotes/origin/main >actual &&
108 test_cmp expect actual
109 ) &&
110 git ls-remote src refs/heads/main >actual &&
111 test_cmp expect actual
114 test_expect_success 'push to update (protected, tracking, forced)' '
115 setup_srcdst_basic &&
117 cd src &&
118 git checkout main &&
119 test_commit D &&
120 git checkout HEAD^0
121 ) &&
123 cd dst &&
124 test_commit E &&
125 git ls-remote . refs/remotes/origin/main >expect &&
126 git push --force --force-with-lease=main origin main
127 ) &&
128 git ls-remote dst refs/heads/main >expect &&
129 git ls-remote src refs/heads/main >actual &&
130 test_cmp expect actual
133 test_expect_success 'push to update (allowed)' '
134 setup_srcdst_basic &&
136 cd dst &&
137 test_commit D &&
138 git push --force-with-lease=main:main^ origin main
139 ) &&
140 git ls-remote dst refs/heads/main >expect &&
141 git ls-remote src refs/heads/main >actual &&
142 test_cmp expect actual
145 test_expect_success 'push to update (allowed, tracking)' '
146 setup_srcdst_basic &&
148 cd dst &&
149 test_commit D &&
150 git push --force-with-lease=main origin main 2>err &&
151 ! grep "forced update" err
152 ) &&
153 git ls-remote dst refs/heads/main >expect &&
154 git ls-remote src refs/heads/main >actual &&
155 test_cmp expect actual
158 test_expect_success 'push to update (allowed even though no-ff)' '
159 setup_srcdst_basic &&
161 cd dst &&
162 git reset --hard HEAD^ &&
163 test_commit D &&
164 git push --force-with-lease=main origin main 2>err &&
165 grep "forced update" err
166 ) &&
167 git ls-remote dst refs/heads/main >expect &&
168 git ls-remote src refs/heads/main >actual &&
169 test_cmp expect actual
172 test_expect_success 'push to delete (protected)' '
173 setup_srcdst_basic &&
174 git ls-remote src refs/heads/main >expect &&
176 cd dst &&
177 test_must_fail git push --force-with-lease=main:main^ origin :main
178 ) &&
179 git ls-remote src refs/heads/main >actual &&
180 test_cmp expect actual
183 test_expect_success 'push to delete (protected, forced)' '
184 setup_srcdst_basic &&
186 cd dst &&
187 git push --force --force-with-lease=main:main^ origin :main
188 ) &&
189 git ls-remote src refs/heads/main >actual &&
190 test_must_be_empty actual
193 test_expect_success 'push to delete (allowed)' '
194 setup_srcdst_basic &&
196 cd dst &&
197 git push --force-with-lease=main origin :main 2>err &&
198 grep deleted err
199 ) &&
200 git ls-remote src refs/heads/main >actual &&
201 test_must_be_empty actual
204 test_expect_success 'cover everything with default force-with-lease (protected)' '
205 setup_srcdst_basic &&
207 cd src &&
208 git branch nain main^
209 ) &&
210 git ls-remote src refs/heads/\* >expect &&
212 cd dst &&
213 test_must_fail git push --force-with-lease origin main main:nain
214 ) &&
215 git ls-remote src refs/heads/\* >actual &&
216 test_cmp expect actual
219 test_expect_success 'cover everything with default force-with-lease (allowed)' '
220 setup_srcdst_basic &&
222 cd src &&
223 git branch nain main^
224 ) &&
226 cd dst &&
227 git fetch &&
228 git push --force-with-lease origin main main:nain
229 ) &&
230 git ls-remote dst refs/heads/main |
231 sed -e "s/main/nain/" >expect &&
232 git ls-remote src refs/heads/nain >actual &&
233 test_cmp expect actual
236 test_expect_success 'new branch covered by force-with-lease' '
237 setup_srcdst_basic &&
239 cd dst &&
240 git branch branch main &&
241 git push --force-with-lease=branch origin branch
242 ) &&
243 git ls-remote dst refs/heads/branch >expect &&
244 git ls-remote src refs/heads/branch >actual &&
245 test_cmp expect actual
248 test_expect_success 'new branch covered by force-with-lease (explicit)' '
249 setup_srcdst_basic &&
251 cd dst &&
252 git branch branch main &&
253 git push --force-with-lease=branch: origin branch
254 ) &&
255 git ls-remote dst refs/heads/branch >expect &&
256 git ls-remote src refs/heads/branch >actual &&
257 test_cmp expect actual
260 test_expect_success 'new branch already exists' '
261 setup_srcdst_basic &&
263 cd src &&
264 git checkout -b branch main &&
265 test_commit F
266 ) &&
268 cd dst &&
269 git branch branch main &&
270 test_must_fail git push --force-with-lease=branch: origin branch
274 test_expect_success 'background updates of REMOTE can be mitigated with a non-updated REMOTE-push' '
275 rm -rf src dst &&
276 git init --bare src.bare &&
277 test_when_finished "rm -rf src.bare" &&
278 git clone --no-local src.bare dst &&
279 test_when_finished "rm -rf dst" &&
281 cd dst &&
282 test_commit G &&
283 git remote add origin-push ../src.bare &&
284 git push origin-push main:main
285 ) &&
286 git clone --no-local src.bare dst2 &&
287 test_when_finished "rm -rf dst2" &&
289 cd dst2 &&
290 test_commit H &&
291 git push
292 ) &&
294 cd dst &&
295 test_commit I &&
296 git fetch origin &&
297 test_must_fail git push --force-with-lease origin-push &&
298 git fetch origin-push &&
299 git push --force-with-lease origin-push
303 test_expect_success 'background updates to remote can be mitigated with "--force-if-includes"' '
304 setup_src_dup_dst &&
305 test_when_finished "rm -fr dst src dup" &&
306 git ls-remote dst refs/heads/main >expect.main &&
307 git ls-remote dst refs/heads/branch >expect.branch &&
309 cd src &&
310 git switch branch &&
311 test_commit I &&
312 git switch main &&
313 test_commit J &&
314 git fetch --all &&
315 test_must_fail git push --force-with-lease --force-if-includes --all
316 ) &&
317 git ls-remote dst refs/heads/main >actual.main &&
318 git ls-remote dst refs/heads/branch >actual.branch &&
319 test_cmp expect.main actual.main &&
320 test_cmp expect.branch actual.branch
323 test_expect_success 'background updates to remote can be mitigated with "push.useForceIfIncludes"' '
324 setup_src_dup_dst &&
325 test_when_finished "rm -fr dst src dup" &&
326 git ls-remote dst refs/heads/main >expect.main &&
328 cd src &&
329 git switch branch &&
330 test_commit I &&
331 git switch main &&
332 test_commit J &&
333 git fetch --all &&
334 git config --local push.useForceIfIncludes true &&
335 test_must_fail git push --force-with-lease=main origin main
336 ) &&
337 git ls-remote dst refs/heads/main >actual.main &&
338 test_cmp expect.main actual.main
341 test_expect_success '"--force-if-includes" should be disabled for --force-with-lease="<refname>:<expect>"' '
342 setup_src_dup_dst &&
343 test_when_finished "rm -fr dst src dup" &&
344 git ls-remote dst refs/heads/main >expect.main &&
346 cd src &&
347 git switch branch &&
348 test_commit I &&
349 git switch main &&
350 test_commit J &&
351 remote_head="$(git rev-parse refs/remotes/origin/main)" &&
352 git fetch --all &&
353 test_must_fail git push --force-if-includes --force-with-lease="main:$remote_head" 2>err &&
354 grep "stale info" err
355 ) &&
356 git ls-remote dst refs/heads/main >actual.main &&
357 test_cmp expect.main actual.main
360 test_expect_success '"--force-if-includes" should allow forced update after a rebase ("pull --rebase")' '
361 setup_src_dup_dst &&
362 test_when_finished "rm -fr dst src dup" &&
364 cd src &&
365 git switch branch &&
366 test_commit I &&
367 git switch main &&
368 test_commit J &&
369 git pull --rebase origin main &&
370 git push --force-if-includes --force-with-lease="main"
374 test_expect_success '"--force-if-includes" should allow forced update after a rebase ("pull --rebase", local rebase)' '
375 setup_src_dup_dst &&
376 test_when_finished "rm -fr dst src dup" &&
378 cd src &&
379 git switch branch &&
380 test_commit I &&
381 git switch main &&
382 test_commit J &&
383 git pull --rebase origin main &&
384 git rebase --onto HEAD~4 HEAD~1 &&
385 git push --force-if-includes --force-with-lease="main"
389 test_expect_success '"--force-if-includes" should allow deletes' '
390 setup_src_dup_dst &&
391 test_when_finished "rm -fr dst src dup" &&
393 cd src &&
394 git switch branch &&
395 git pull --rebase origin branch &&
396 git push --force-if-includes --force-with-lease="branch" origin :branch
400 test_done