Merge branch 'rs/export-strbuf-addchars'
[git] / t / t5541-http-push-smart.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at>
4 #
5
6 test_description='test smart pushing over http via http-backend'
7 . ./test-lib.sh
8
9 if test -n "$NO_CURL"; then
10         skip_all='skipping test, git built without http support'
11         test_done
12 fi
13
14 ROOT_PATH="$PWD"
15 . "$TEST_DIRECTORY"/lib-httpd.sh
16 . "$TEST_DIRECTORY"/lib-terminal.sh
17 start_httpd
18
19 test_expect_success 'setup remote repository' '
20         cd "$ROOT_PATH" &&
21         mkdir test_repo &&
22         cd test_repo &&
23         git init &&
24         : >path1 &&
25         git add path1 &&
26         test_tick &&
27         git commit -m initial &&
28         cd - &&
29         git clone --bare test_repo test_repo.git &&
30         cd test_repo.git &&
31         git config http.receivepack true &&
32         git config core.logallrefupdates true &&
33         ORIG_HEAD=$(git rev-parse --verify HEAD) &&
34         cd - &&
35         mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH"
36 '
37
38 setup_askpass_helper
39
40 cat >exp <<EOF
41 GET  /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
42 POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200
43 EOF
44 test_expect_success 'no empty path components' '
45         # In the URL, add a trailing slash, and see if git appends yet another
46         # slash.
47         cd "$ROOT_PATH" &&
48         git clone $HTTPD_URL/smart/test_repo.git/ test_repo_clone &&
49
50         sed -e "
51                 s/^.* \"//
52                 s/\"//
53                 s/ [1-9][0-9]*\$//
54                 s/^GET /GET  /
55         " >act <"$HTTPD_ROOT_PATH"/access.log &&
56
57         # Clear the log, so that it does not affect the "used receive-pack
58         # service" test which reads the log too.
59         #
60         # We do this before the actual comparison to ensure the log is cleared.
61         echo > "$HTTPD_ROOT_PATH"/access.log &&
62
63         test_cmp exp act
64 '
65
66 test_expect_success 'clone remote repository' '
67         rm -rf test_repo_clone &&
68         git clone $HTTPD_URL/smart/test_repo.git test_repo_clone &&
69         (
70                 cd test_repo_clone && git config push.default matching
71         )
72 '
73
74 test_expect_success 'push to remote repository (standard)' '
75         cd "$ROOT_PATH"/test_repo_clone &&
76         : >path2 &&
77         git add path2 &&
78         test_tick &&
79         git commit -m path2 &&
80         HEAD=$(git rev-parse --verify HEAD) &&
81         GIT_CURL_VERBOSE=1 git push -v -v 2>err &&
82         ! grep "Expect: 100-continue" err &&
83         grep "POST git-receive-pack ([0-9]* bytes)" err &&
84         (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
85          test $HEAD = $(git rev-parse --verify HEAD))
86 '
87
88 test_expect_success 'push already up-to-date' '
89         git push
90 '
91
92 test_expect_success 'create and delete remote branch' '
93         cd "$ROOT_PATH"/test_repo_clone &&
94         git checkout -b dev &&
95         : >path3 &&
96         git add path3 &&
97         test_tick &&
98         git commit -m dev &&
99         git push origin dev &&
100         git push origin :dev &&
101         test_must_fail git show-ref --verify refs/remotes/origin/dev
102 '
103
104 cat >"$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update" <<EOF
105 #!/bin/sh
106 exit 1
107 EOF
108 chmod a+x "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update"
109
110 cat >exp <<EOF
111 remote: error: hook declined to update refs/heads/dev2
112 To http://127.0.0.1:$LIB_HTTPD_PORT/smart/test_repo.git
113  ! [remote rejected] dev2 -> dev2 (hook declined)
114 error: failed to push some refs to 'http://127.0.0.1:$LIB_HTTPD_PORT/smart/test_repo.git'
115 EOF
116
117 test_expect_success 'rejected update prints status' '
118         cd "$ROOT_PATH"/test_repo_clone &&
119         git checkout -b dev2 &&
120         : >path4 &&
121         git add path4 &&
122         test_tick &&
123         git commit -m dev2 &&
124         test_must_fail git push origin dev2 2>act &&
125         sed -e "/^remote: /s/ *$//" <act >cmp &&
126         test_cmp exp cmp
127 '
128 rm -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update"
129
130 cat >exp <<EOF
131
132 GET  /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
133 POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200
134 GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
135 POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
136 GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
137 GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
138 POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
139 GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
140 POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
141 GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
142 POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
143 EOF
144 test_expect_success 'used receive-pack service' '
145         sed -e "
146                 s/^.* \"//
147                 s/\"//
148                 s/ [1-9][0-9]*\$//
149                 s/^GET /GET  /
150         " >act <"$HTTPD_ROOT_PATH"/access.log &&
151         test_cmp exp act
152 '
153
154 test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
155         "$ROOT_PATH"/test_repo_clone master             success
156
157 test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper' '
158         # create a dissimilarly-named remote ref so that git is unable to match the
159         # two refs (viz. local, remote) unless an explicit refspec is provided.
160         git push origin master:retsam
161
162         echo "change changed" > path2 &&
163         git commit -a -m path2 --amend &&
164
165         # push master too; this ensures there is at least one '"'push'"' command to
166         # the remote helper and triggers interaction with the helper.
167         test_must_fail git push -v origin +master master:retsam >output 2>&1'
168
169 test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper: remote output' '
170         grep "^ + [a-f0-9]*\.\.\.[a-f0-9]* *master -> master (forced update)$" output &&
171         grep "^ ! \[rejected\] *master -> retsam (non-fast-forward)$" output
172 '
173
174 test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper: our output' '
175         test_i18ngrep "Updates were rejected because" \
176                 output
177 '
178
179 test_expect_success 'push (chunked)' '
180         git checkout master &&
181         test_commit commit path3 &&
182         HEAD=$(git rev-parse --verify HEAD) &&
183         test_config http.postbuffer 4 &&
184         git push -v -v origin $BRANCH 2>err &&
185         grep "POST git-receive-pack (chunked)" err &&
186         (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
187          test $HEAD = $(git rev-parse --verify HEAD))
188 '
189
190 test_expect_success 'push --all can push to empty repo' '
191         d=$HTTPD_DOCUMENT_ROOT_PATH/empty-all.git &&
192         git init --bare "$d" &&
193         git --git-dir="$d" config http.receivepack true &&
194         git push --all "$HTTPD_URL"/smart/empty-all.git
195 '
196
197 test_expect_success 'push --mirror can push to empty repo' '
198         d=$HTTPD_DOCUMENT_ROOT_PATH/empty-mirror.git &&
199         git init --bare "$d" &&
200         git --git-dir="$d" config http.receivepack true &&
201         git push --mirror "$HTTPD_URL"/smart/empty-mirror.git
202 '
203
204 test_expect_success 'push --all to repo with alternates' '
205         s=$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git &&
206         d=$HTTPD_DOCUMENT_ROOT_PATH/alternates-all.git &&
207         git clone --bare --shared "$s" "$d" &&
208         git --git-dir="$d" config http.receivepack true &&
209         git --git-dir="$d" repack -adl &&
210         git push --all "$HTTPD_URL"/smart/alternates-all.git
211 '
212
213 test_expect_success 'push --mirror to repo with alternates' '
214         s=$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git &&
215         d=$HTTPD_DOCUMENT_ROOT_PATH/alternates-mirror.git &&
216         git clone --bare --shared "$s" "$d" &&
217         git --git-dir="$d" config http.receivepack true &&
218         git --git-dir="$d" repack -adl &&
219         git push --mirror "$HTTPD_URL"/smart/alternates-mirror.git
220 '
221
222 test_expect_success TTY 'push shows progress when stderr is a tty' '
223         cd "$ROOT_PATH"/test_repo_clone &&
224         test_commit noisy &&
225         test_terminal git push >output 2>&1 &&
226         grep "^Writing objects" output
227 '
228
229 test_expect_success TTY 'push --quiet silences status and progress' '
230         cd "$ROOT_PATH"/test_repo_clone &&
231         test_commit quiet &&
232         test_terminal git push --quiet >output 2>&1 &&
233         test_cmp /dev/null output
234 '
235
236 test_expect_success TTY 'push --no-progress silences progress but not status' '
237         cd "$ROOT_PATH"/test_repo_clone &&
238         test_commit no-progress &&
239         test_terminal git push --no-progress >output 2>&1 &&
240         grep "^To http" output &&
241         ! grep "^Writing objects"
242 '
243
244 test_expect_success 'push --progress shows progress to non-tty' '
245         cd "$ROOT_PATH"/test_repo_clone &&
246         test_commit progress &&
247         git push --progress >output 2>&1 &&
248         grep "^To http" output &&
249         grep "^Writing objects" output
250 '
251
252 test_expect_success 'http push gives sane defaults to reflog' '
253         cd "$ROOT_PATH"/test_repo_clone &&
254         test_commit reflog-test &&
255         git push "$HTTPD_URL"/smart/test_repo.git &&
256         git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
257                 log -g -1 --format="%gn <%ge>" >actual &&
258         echo "anonymous <anonymous@http.127.0.0.1>" >expect &&
259         test_cmp expect actual
260 '
261
262 test_expect_success 'http push respects GIT_COMMITTER_* in reflog' '
263         cd "$ROOT_PATH"/test_repo_clone &&
264         test_commit custom-reflog-test &&
265         git push "$HTTPD_URL"/smart_custom_env/test_repo.git &&
266         git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
267                 log -g -1 --format="%gn <%ge>" >actual &&
268         echo "Custom User <custom@example.com>" >expect &&
269         test_cmp expect actual
270 '
271
272 test_expect_success 'push over smart http with auth' '
273         cd "$ROOT_PATH/test_repo_clone" &&
274         echo push-auth-test >expect &&
275         test_commit push-auth-test &&
276         set_askpass user@host pass@host &&
277         git push "$HTTPD_URL"/auth/smart/test_repo.git &&
278         git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
279                 log -1 --format=%s >actual &&
280         expect_askpass both user@host &&
281         test_cmp expect actual
282 '
283
284 test_expect_success 'push to auth-only-for-push repo' '
285         cd "$ROOT_PATH/test_repo_clone" &&
286         echo push-half-auth >expect &&
287         test_commit push-half-auth &&
288         set_askpass user@host pass@host &&
289         git push "$HTTPD_URL"/auth-push/smart/test_repo.git &&
290         git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
291                 log -1 --format=%s >actual &&
292         expect_askpass both user@host &&
293         test_cmp expect actual
294 '
295
296 test_expect_success 'create repo without http.receivepack set' '
297         cd "$ROOT_PATH" &&
298         git init half-auth &&
299         (
300                 cd half-auth &&
301                 test_commit one
302         ) &&
303         git clone --bare half-auth "$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git"
304 '
305
306 test_expect_success 'clone via half-auth-complete does not need password' '
307         cd "$ROOT_PATH" &&
308         set_askpass wrong &&
309         git clone "$HTTPD_URL"/half-auth-complete/smart/half-auth.git \
310                 half-auth-clone &&
311         expect_askpass none
312 '
313
314 test_expect_success 'push into half-auth-complete requires password' '
315         cd "$ROOT_PATH/half-auth-clone" &&
316         echo two >expect &&
317         test_commit two &&
318         set_askpass user@host pass@host &&
319         git push "$HTTPD_URL/half-auth-complete/smart/half-auth.git" &&
320         git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git" \
321                 log -1 --format=%s >actual &&
322         expect_askpass both user@host &&
323         test_cmp expect actual
324 '
325
326 run_with_limited_cmdline () {
327         (ulimit -s 128 && "$@")
328 }
329
330 test_lazy_prereq CMDLINE_LIMIT 'run_with_limited_cmdline true'
331
332 test_expect_success CMDLINE_LIMIT 'push 2000 tags over http' '
333         sha1=$(git rev-parse HEAD) &&
334         test_seq 2000 |
335           sort |
336           sed "s|.*|$sha1 refs/tags/really-long-tag-name-&|" \
337           >.git/packed-refs &&
338         run_with_limited_cmdline git push --mirror
339 '
340
341 stop_httpd
342 test_done