Merge branch 'ps/transactional-update-ref-stdin'
[git] / t / t5543-atomic-push.sh
1 #!/bin/sh
2
3 test_description='pushing to a repository using the atomic push option'
4
5 . ./test-lib.sh
6
7 mk_repo_pair () {
8         rm -rf workbench upstream &&
9         test_create_repo upstream &&
10         test_create_repo workbench &&
11         (
12                 cd upstream &&
13                 git config receive.denyCurrentBranch warn
14         ) &&
15         (
16                 cd workbench &&
17                 git remote add up ../upstream
18         )
19 }
20
21 # Compare the ref ($1) in upstream with a ref value from workbench ($2)
22 # i.e. test_refs second HEAD@{2}
23 test_refs () {
24         test $# = 2 &&
25         git -C upstream rev-parse --verify "$1" >expect &&
26         git -C workbench rev-parse --verify "$2" >actual &&
27         test_cmp expect actual
28 }
29
30 fmt_status_report () {
31         sed -n \
32                 -e "/^To / { s/   */ /g; p; }" \
33                 -e "/^ ! / { s/   */ /g; p; }"
34 }
35
36 test_expect_success 'atomic push works for a single branch' '
37         mk_repo_pair &&
38         (
39                 cd workbench &&
40                 test_commit one &&
41                 git push --mirror up &&
42                 test_commit two &&
43                 git push --atomic up master
44         ) &&
45         test_refs master master
46 '
47
48 test_expect_success 'atomic push works for two branches' '
49         mk_repo_pair &&
50         (
51                 cd workbench &&
52                 test_commit one &&
53                 git branch second &&
54                 git push --mirror up &&
55                 test_commit two &&
56                 git checkout second &&
57                 test_commit three &&
58                 git push --atomic up master second
59         ) &&
60         test_refs master master &&
61         test_refs second second
62 '
63
64 test_expect_success 'atomic push works in combination with --mirror' '
65         mk_repo_pair &&
66         (
67                 cd workbench &&
68                 test_commit one &&
69                 git checkout -b second &&
70                 test_commit two &&
71                 git push --atomic --mirror up
72         ) &&
73         test_refs master master &&
74         test_refs second second
75 '
76
77 test_expect_success 'atomic push works in combination with --force' '
78         mk_repo_pair &&
79         (
80                 cd workbench &&
81                 test_commit one &&
82                 git branch second master &&
83                 test_commit two_a &&
84                 git checkout second &&
85                 test_commit two_b &&
86                 test_commit three_b &&
87                 test_commit four &&
88                 git push --mirror up &&
89                 # The actual test is below
90                 git checkout master &&
91                 test_commit three_a &&
92                 git checkout second &&
93                 git reset --hard HEAD^ &&
94                 git push --force --atomic up master second
95         ) &&
96         test_refs master master &&
97         test_refs second second
98 '
99
100 # set up two branches where master can be pushed but second can not
101 # (non-fast-forward). Since second can not be pushed the whole operation
102 # will fail and leave master untouched.
103 test_expect_success 'atomic push fails if one branch fails' '
104         mk_repo_pair &&
105         (
106                 cd workbench &&
107                 test_commit one &&
108                 git checkout -b second master &&
109                 test_commit two &&
110                 test_commit three &&
111                 test_commit four &&
112                 git push --mirror up &&
113                 git reset --hard HEAD~2 &&
114                 test_commit five &&
115                 git checkout master &&
116                 test_commit six &&
117                 test_must_fail git push --atomic --all up
118         ) &&
119         test_refs master HEAD@{7} &&
120         test_refs second HEAD@{4}
121 '
122
123 test_expect_success 'atomic push fails if one tag fails remotely' '
124         # prepare the repo
125         mk_repo_pair &&
126         (
127                 cd workbench &&
128                 test_commit one &&
129                 git checkout -b second master &&
130                 test_commit two &&
131                 git push --mirror up
132         ) &&
133         # a third party modifies the server side:
134         (
135                 cd upstream &&
136                 git checkout second &&
137                 git tag test_tag second
138         ) &&
139         # see if we can now push both branches.
140         (
141                 cd workbench &&
142                 git checkout master &&
143                 test_commit three &&
144                 git checkout second &&
145                 test_commit four &&
146                 git tag test_tag &&
147                 test_must_fail git push --tags --atomic up master second
148         ) &&
149         test_refs master HEAD@{3} &&
150         test_refs second HEAD@{1}
151 '
152
153 test_expect_success 'atomic push obeys update hook preventing a branch to be pushed' '
154         mk_repo_pair &&
155         (
156                 cd workbench &&
157                 test_commit one &&
158                 git checkout -b second master &&
159                 test_commit two &&
160                 git push --mirror up
161         ) &&
162         (
163                 cd upstream &&
164                 HOOKDIR="$(git rev-parse --git-dir)/hooks" &&
165                 HOOK="$HOOKDIR/update" &&
166                 mkdir -p "$HOOKDIR" &&
167                 write_script "$HOOK" <<-\EOF
168                         # only allow update to master from now on
169                         test "$1" = "refs/heads/master"
170                 EOF
171         ) &&
172         (
173                 cd workbench &&
174                 git checkout master &&
175                 test_commit three &&
176                 git checkout second &&
177                 test_commit four &&
178                 test_must_fail git push --atomic up master second
179         ) &&
180         test_refs master HEAD@{3} &&
181         test_refs second HEAD@{1}
182 '
183
184 test_expect_success 'atomic push is not advertised if configured' '
185         mk_repo_pair &&
186         (
187                 cd upstream &&
188                 git config receive.advertiseatomic 0
189         ) &&
190         (
191                 cd workbench &&
192                 test_commit one &&
193                 git push --mirror up &&
194                 test_commit two &&
195                 test_must_fail git push --atomic up master
196         ) &&
197         test_refs master HEAD@{1}
198 '
199
200 # References in upstream : master(1) one(1) foo(1)
201 # References in workbench: master(2)        foo(1) two(2) bar(2)
202 # Atomic push            : master(2)               two(2) bar(2)
203 test_expect_success 'atomic push reports (reject by update hook)' '
204         mk_repo_pair &&
205         (
206                 cd workbench &&
207                 test_commit one &&
208                 git branch foo &&
209                 git push up master one foo &&
210                 git tag -d one
211         ) &&
212         (
213                 mkdir -p upstream/.git/hooks &&
214                 cat >upstream/.git/hooks/update <<-EOF &&
215                 #!/bin/sh
216
217                 if test "\$1" = "refs/heads/bar"
218                 then
219                         echo >&2 "Pusing to branch bar is prohibited"
220                         exit 1
221                 fi
222                 EOF
223                 chmod a+x upstream/.git/hooks/update
224         ) &&
225         (
226                 cd workbench &&
227                 test_commit two &&
228                 git branch bar
229         ) &&
230         test_must_fail git -C workbench \
231                 push --atomic up master two bar >out 2>&1 &&
232         fmt_status_report <out >actual &&
233         cat >expect <<-EOF &&
234         To ../upstream
235          ! [remote rejected] master -> master (atomic push failure)
236          ! [remote rejected] two -> two (atomic push failure)
237          ! [remote rejected] bar -> bar (hook declined)
238         EOF
239         test_cmp expect actual
240 '
241
242 # References in upstream : master(1) one(1) foo(1)
243 # References in workbench: master(2)        foo(1) two(2) bar(2)
244 test_expect_success 'atomic push reports (mirror, but reject by update hook)' '
245         (
246                 cd workbench &&
247                 git remote remove up &&
248                 git remote add up ../upstream
249         ) &&
250         test_must_fail git -C workbench \
251                 push --atomic --mirror up >out 2>&1 &&
252         fmt_status_report <out >actual &&
253         cat >expect <<-EOF &&
254         To ../upstream
255          ! [remote rejected] master -> master (atomic push failure)
256          ! [remote rejected] one (atomic push failure)
257          ! [remote rejected] bar -> bar (hook declined)
258          ! [remote rejected] two -> two (atomic push failure)
259         EOF
260         test_cmp expect actual
261 '
262
263 # References in upstream : master(2) one(1) foo(1)
264 # References in workbench: master(1)        foo(1) two(2) bar(2)
265 test_expect_success 'atomic push reports (reject by non-ff)' '
266         rm upstream/.git/hooks/update &&
267         (
268                 cd workbench &&
269                 git push up master &&
270                 git reset --hard HEAD^
271         ) &&
272         test_must_fail git -C workbench \
273                 push --atomic up master foo bar >out 2>&1 &&
274         fmt_status_report <out >actual &&
275         cat >expect <<-EOF &&
276         To ../upstream
277          ! [rejected] master -> master (non-fast-forward)
278          ! [rejected] bar -> bar (atomic push failed)
279         EOF
280         test_cmp expect actual
281 '
282
283 test_done