Merge branch 'ph/stash-rerere'
[git] / t / t5541-http-push.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 LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5541'}
16 . "$TEST_DIRECTORY"/lib-httpd.sh
17 . "$TEST_DIRECTORY"/lib-terminal.sh
18 start_httpd
19
20 test_expect_success 'setup remote repository' '
21         cd "$ROOT_PATH" &&
22         mkdir test_repo &&
23         cd test_repo &&
24         git init &&
25         : >path1 &&
26         git add path1 &&
27         test_tick &&
28         git commit -m initial &&
29         cd - &&
30         git clone --bare test_repo test_repo.git &&
31         cd test_repo.git &&
32         git config http.receivepack true &&
33         git config core.logallrefupdates true &&
34         ORIG_HEAD=$(git rev-parse --verify HEAD) &&
35         cd - &&
36         mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH"
37 '
38
39 cat >exp <<EOF
40 GET  /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
41 POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200
42 EOF
43 test_expect_success 'no empty path components' '
44         # In the URL, add a trailing slash, and see if git appends yet another
45         # slash.
46         cd "$ROOT_PATH" &&
47         git clone $HTTPD_URL/smart/test_repo.git/ test_repo_clone &&
48
49         sed -e "
50                 s/^.* \"//
51                 s/\"//
52                 s/ [1-9][0-9]*\$//
53                 s/^GET /GET  /
54         " >act <"$HTTPD_ROOT_PATH"/access.log &&
55
56         # Clear the log, so that it does not affect the "used receive-pack
57         # service" test which reads the log too.
58         #
59         # We do this before the actual comparison to ensure the log is cleared.
60         echo > "$HTTPD_ROOT_PATH"/access.log &&
61
62         test_cmp exp act
63 '
64
65 test_expect_success 'clone remote repository' '
66         rm -rf test_repo_clone &&
67         git clone $HTTPD_URL/smart/test_repo.git test_repo_clone &&
68         (
69                 cd test_repo_clone && git config push.default matching
70         )
71 '
72
73 test_expect_success 'push to remote repository (standard)' '
74         cd "$ROOT_PATH"/test_repo_clone &&
75         : >path2 &&
76         git add path2 &&
77         test_tick &&
78         git commit -m path2 &&
79         HEAD=$(git rev-parse --verify HEAD) &&
80         GIT_CURL_VERBOSE=1 git push -v -v 2>err &&
81         ! grep "Expect: 100-continue" err &&
82         grep "POST git-receive-pack ([0-9]* bytes)" err &&
83         (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
84          test $HEAD = $(git rev-parse --verify HEAD))
85 '
86
87 test_expect_success 'push already up-to-date' '
88         git push
89 '
90
91 test_expect_success 'create and delete remote branch' '
92         cd "$ROOT_PATH"/test_repo_clone &&
93         git checkout -b dev &&
94         : >path3 &&
95         git add path3 &&
96         test_tick &&
97         git commit -m dev &&
98         git push origin dev &&
99         git push origin :dev &&
100         test_must_fail git show-ref --verify refs/remotes/origin/dev
101 '
102
103 cat >"$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update" <<EOF
104 #!/bin/sh
105 exit 1
106 EOF
107 chmod a+x "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update"
108
109 cat >exp <<EOF
110 remote: error: hook declined to update refs/heads/dev2
111 To http://127.0.0.1:$LIB_HTTPD_PORT/smart/test_repo.git
112  ! [remote rejected] dev2 -> dev2 (hook declined)
113 error: failed to push some refs to 'http://127.0.0.1:$LIB_HTTPD_PORT/smart/test_repo.git'
114 EOF
115
116 test_expect_success 'rejected update prints status' '
117         cd "$ROOT_PATH"/test_repo_clone &&
118         git checkout -b dev2 &&
119         : >path4 &&
120         git add path4 &&
121         test_tick &&
122         git commit -m dev2 &&
123         test_must_fail git push origin dev2 2>act &&
124         sed -e "/^remote: /s/ *$//" <act >cmp &&
125         test_cmp exp cmp
126 '
127 rm -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update"
128
129 cat >exp <<EOF
130
131 GET  /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
132 POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200
133 GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
134 POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
135 GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
136 GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
137 POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
138 GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
139 POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
140 GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
141 POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
142 EOF
143 test_expect_success 'used receive-pack service' '
144         sed -e "
145                 s/^.* \"//
146                 s/\"//
147                 s/ [1-9][0-9]*\$//
148                 s/^GET /GET  /
149         " >act <"$HTTPD_ROOT_PATH"/access.log &&
150         test_cmp exp act
151 '
152
153 test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
154         "$ROOT_PATH"/test_repo_clone master
155
156 test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper' '
157         # create a dissimilarly-named remote ref so that git is unable to match the
158         # two refs (viz. local, remote) unless an explicit refspec is provided.
159         git push origin master:retsam
160
161         echo "change changed" > path2 &&
162         git commit -a -m path2 --amend &&
163
164         # push master too; this ensures there is at least one '"'push'"' command to
165         # the remote helper and triggers interaction with the helper.
166         test_must_fail git push -v origin +master master:retsam >output 2>&1'
167
168 test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper: remote output' '
169         grep "^ + [a-f0-9]*\.\.\.[a-f0-9]* *master -> master (forced update)$" output &&
170         grep "^ ! \[rejected\] *master -> retsam (non-fast-forward)$" output
171 '
172
173 test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper: our output' '
174         test_i18ngrep "Updates were rejected because" \
175                 output
176 '
177
178 test_expect_success 'push (chunked)' '
179         git checkout master &&
180         test_commit commit path3 &&
181         HEAD=$(git rev-parse --verify HEAD) &&
182         git config http.postbuffer 4 &&
183         test_when_finished "git config --unset http.postbuffer" &&
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 stop_httpd
273 test_done