The 19th batch
[git.git] / t / t5548-push-porcelain.sh
blobecb3877aa4bf1b25942598ef5f1628d91c9bfbd5
1 #!/bin/sh
3 # Copyright (c) 2020 Jiang Xin
5 test_description='Test git push porcelain output'
7 TEST_PASSES_SANITIZE_LEAK=true
8 . ./test-lib.sh
10 # Create commits in <repo> and assign each commit's oid to shell variables
11 # given in the arguments (A, B, and C). E.g.:
13 # create_commits_in <repo> A B C
15 # NOTE: Never calling this function from a subshell since variable
16 # assignments will disappear when subshell exits.
17 create_commits_in () {
18 repo="$1" && test -d "$repo" ||
19 error "Repository $repo does not exist."
20 shift &&
21 while test $# -gt 0
23 name=$1 &&
24 shift &&
25 test_commit -C "$repo" --no-tag "$name" &&
26 eval $name=$(git -C "$repo" rev-parse HEAD)
27 done
30 get_abbrev_oid () {
31 oid=$1 &&
32 suffix=${oid#???????} &&
33 oid=${oid%$suffix} &&
34 if test -n "$oid"
35 then
36 echo "$oid"
37 else
38 echo "undefined-oid"
42 # Format the output of git-push, git-show-ref and other commands to make a
43 # user-friendly and stable text. We can easily prepare the expect text
44 # without having to worry about future changes of the commit ID and spaces
45 # of the output.
46 make_user_friendly_and_stable_output () {
47 sed \
48 -e "s/$(get_abbrev_oid $A)[0-9a-f]*/<COMMIT-A>/g" \
49 -e "s/$(get_abbrev_oid $B)[0-9a-f]*/<COMMIT-B>/g" \
50 -e "s/$ZERO_OID/<ZERO-OID>/g" \
51 -e "s#To $URL_PREFIX/upstream.git#To <URL/of/upstream.git>#"
54 format_and_save_expect () {
55 sed -e 's/^> //' -e 's/Z$//' >expect
58 setup_upstream_and_workbench () {
59 # Upstream after setup : main(B) foo(A) bar(A) baz(A)
60 # Workbench after setup : main(A)
61 test_expect_success "setup upstream repository and workbench" '
62 rm -rf upstream.git workbench &&
63 git init --bare upstream.git &&
64 git init workbench &&
65 create_commits_in workbench A B &&
67 cd workbench &&
68 # Try to make a stable fixed width for abbreviated commit ID,
69 # this fixed-width oid will be replaced with "<OID>".
70 git config core.abbrev 7 &&
71 git remote add origin ../upstream.git &&
72 git update-ref refs/heads/main $A &&
73 git push origin \
74 $B:refs/heads/main \
75 $A:refs/heads/foo \
76 $A:refs/heads/bar \
77 $A:refs/heads/baz
78 ) &&
79 git -C "workbench" config advice.pushUpdateRejected false &&
80 upstream=upstream.git
84 run_git_push_porcelain_output_test() {
85 case $1 in
86 http)
87 PROTOCOL="HTTP protocol"
88 URL_PREFIX="http://.*"
90 file)
91 PROTOCOL="builtin protocol"
92 URL_PREFIX="\.\."
94 esac
96 # Refs of upstream : main(B) foo(A) bar(A) baz(A)
97 # Refs of workbench: main(A) baz(A) next(A)
98 # git-push : main(A) NULL (B) baz(A) next(A)
99 test_expect_success "porcelain output of successful git-push ($PROTOCOL)" '
101 cd workbench &&
102 git update-ref refs/heads/main $A &&
103 git update-ref refs/heads/baz $A &&
104 git update-ref refs/heads/next $A &&
105 git push --porcelain --force origin \
106 main \
107 :refs/heads/foo \
108 $B:bar \
109 baz \
110 next
111 ) >out &&
112 make_user_friendly_and_stable_output <out >actual &&
113 format_and_save_expect <<-EOF &&
114 > To <URL/of/upstream.git>
115 > = refs/heads/baz:refs/heads/baz [up to date]
116 > <COMMIT-B>:refs/heads/bar <COMMIT-A>..<COMMIT-B>
117 > - :refs/heads/foo [deleted]
118 > + refs/heads/main:refs/heads/main <COMMIT-B>...<COMMIT-A> (forced update)
119 > * refs/heads/next:refs/heads/next [new branch]
120 > Done
122 test_cmp expect actual &&
124 git -C "$upstream" show-ref >out &&
125 make_user_friendly_and_stable_output <out >actual &&
126 cat >expect <<-EOF &&
127 <COMMIT-B> refs/heads/bar
128 <COMMIT-A> refs/heads/baz
129 <COMMIT-A> refs/heads/main
130 <COMMIT-A> refs/heads/next
132 test_cmp expect actual
135 # Refs of upstream : main(A) bar(B) baz(A) next(A)
136 # Refs of workbench: main(B) bar(A) baz(A) next(A)
137 # git-push : main(B) bar(A) NULL next(A)
138 test_expect_success "atomic push failed ($PROTOCOL)" '
140 cd workbench &&
141 git update-ref refs/heads/main $B &&
142 git update-ref refs/heads/bar $A &&
143 test_must_fail git push --atomic --porcelain origin \
144 main \
145 bar \
146 :baz \
147 next
148 ) >out &&
149 make_user_friendly_and_stable_output <out >actual &&
150 format_and_save_expect <<-EOF &&
151 To <URL/of/upstream.git>
152 > = refs/heads/next:refs/heads/next [up to date]
153 > ! refs/heads/bar:refs/heads/bar [rejected] (non-fast-forward)
154 > ! (delete):refs/heads/baz [rejected] (atomic push failed)
155 > ! refs/heads/main:refs/heads/main [rejected] (atomic push failed)
156 Done
158 test_cmp expect actual &&
160 git -C "$upstream" show-ref >out &&
161 make_user_friendly_and_stable_output <out >actual &&
162 cat >expect <<-EOF &&
163 <COMMIT-B> refs/heads/bar
164 <COMMIT-A> refs/heads/baz
165 <COMMIT-A> refs/heads/main
166 <COMMIT-A> refs/heads/next
168 test_cmp expect actual
171 test_expect_success "prepare pre-receive hook ($PROTOCOL)" '
172 test_hook --setup -C "$upstream" pre-receive <<-EOF
173 exit 1
177 # Refs of upstream : main(A) bar(B) baz(A) next(A)
178 # Refs of workbench: main(B) bar(A) baz(A) next(A)
179 # git-push : main(B) bar(A) NULL next(A)
180 test_expect_success "pre-receive hook declined ($PROTOCOL)" '
182 cd workbench &&
183 git update-ref refs/heads/main $B &&
184 git update-ref refs/heads/bar $A &&
185 test_must_fail git push --porcelain --force origin \
186 main \
187 bar \
188 :baz \
189 next
190 ) >out &&
191 make_user_friendly_and_stable_output <out >actual &&
192 format_and_save_expect <<-EOF &&
193 To <URL/of/upstream.git>
194 > = refs/heads/next:refs/heads/next [up to date]
195 > ! refs/heads/bar:refs/heads/bar [remote rejected] (pre-receive hook declined)
196 > ! :refs/heads/baz [remote rejected] (pre-receive hook declined)
197 > ! refs/heads/main:refs/heads/main [remote rejected] (pre-receive hook declined)
198 Done
200 test_cmp expect actual &&
202 git -C "$upstream" show-ref >out &&
203 make_user_friendly_and_stable_output <out >actual &&
204 cat >expect <<-EOF &&
205 <COMMIT-B> refs/heads/bar
206 <COMMIT-A> refs/heads/baz
207 <COMMIT-A> refs/heads/main
208 <COMMIT-A> refs/heads/next
210 test_cmp expect actual
213 test_expect_success "remove pre-receive hook ($PROTOCOL)" '
214 rm "$upstream/hooks/pre-receive"
217 # Refs of upstream : main(A) bar(B) baz(A) next(A)
218 # Refs of workbench: main(B) bar(A) baz(A) next(A)
219 # git-push : main(B) bar(A) NULL next(A)
220 test_expect_success "non-fastforward push ($PROTOCOL)" '
222 cd workbench &&
223 test_must_fail git push --porcelain origin \
224 main \
225 bar \
226 :baz \
227 next
228 ) >out &&
229 make_user_friendly_and_stable_output <out >actual &&
230 format_and_save_expect <<-EOF &&
231 To <URL/of/upstream.git>
232 > = refs/heads/next:refs/heads/next [up to date]
233 > - :refs/heads/baz [deleted]
234 > refs/heads/main:refs/heads/main <COMMIT-A>..<COMMIT-B>
235 > ! refs/heads/bar:refs/heads/bar [rejected] (non-fast-forward)
236 Done
238 test_cmp expect actual &&
240 git -C "$upstream" show-ref >out &&
241 make_user_friendly_and_stable_output <out >actual &&
242 cat >expect <<-EOF &&
243 <COMMIT-B> refs/heads/bar
244 <COMMIT-B> refs/heads/main
245 <COMMIT-A> refs/heads/next
247 test_cmp expect actual
251 # Initialize the upstream repository and local workbench.
252 setup_upstream_and_workbench
254 # Run git-push porcelain test on builtin protocol
255 run_git_push_porcelain_output_test file
257 ROOT_PATH="$PWD"
258 . "$TEST_DIRECTORY"/lib-gpg.sh
259 . "$TEST_DIRECTORY"/lib-httpd.sh
260 . "$TEST_DIRECTORY"/lib-terminal.sh
261 start_httpd
263 # Re-initialize the upstream repository and local workbench.
264 setup_upstream_and_workbench
266 test_expect_success "setup for http" '
267 git -C upstream.git config http.receivepack true &&
268 upstream="$HTTPD_DOCUMENT_ROOT_PATH/upstream.git" &&
269 mv upstream.git "$upstream" &&
271 git -C workbench remote set-url origin $HTTPD_URL/smart/upstream.git
274 setup_askpass_helper
276 # Run git-push porcelain test on HTTP protocol
277 run_git_push_porcelain_output_test http
279 test_done