Merge branch 'jc/calloc-fix'
[git] / t / t5545-push-options.sh
1 #!/bin/sh
2
3 test_description='pushing to a repository using push options'
4
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
7
8 . ./test-lib.sh
9
10 mk_repo_pair () {
11         rm -rf workbench upstream &&
12         test_create_repo upstream &&
13         test_create_repo workbench &&
14         (
15                 cd upstream &&
16                 git config receive.denyCurrentBranch warn &&
17                 mkdir -p .git/hooks &&
18                 cat >.git/hooks/pre-receive <<-'EOF' &&
19                 #!/bin/sh
20                 if test -n "$GIT_PUSH_OPTION_COUNT"; then
21                         i=0
22                         >hooks/pre-receive.push_options
23                         while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"; do
24                                 eval "value=\$GIT_PUSH_OPTION_$i"
25                                 echo $value >>hooks/pre-receive.push_options
26                                 i=$((i + 1))
27                         done
28                 fi
29                 EOF
30                 chmod u+x .git/hooks/pre-receive
31
32                 cat >.git/hooks/post-receive <<-'EOF' &&
33                 #!/bin/sh
34                 if test -n "$GIT_PUSH_OPTION_COUNT"; then
35                         i=0
36                         >hooks/post-receive.push_options
37                         while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"; do
38                                 eval "value=\$GIT_PUSH_OPTION_$i"
39                                 echo $value >>hooks/post-receive.push_options
40                                 i=$((i + 1))
41                         done
42                 fi
43                 EOF
44                 chmod u+x .git/hooks/post-receive
45         ) &&
46         (
47                 cd workbench &&
48                 git remote add up ../upstream
49         )
50 }
51
52 # Compare the ref ($1) in upstream with a ref value from workbench ($2)
53 # i.e. test_refs second HEAD@{2}
54 test_refs () {
55         test $# = 2 &&
56         git -C upstream rev-parse --verify "$1" >expect &&
57         git -C workbench rev-parse --verify "$2" >actual &&
58         test_cmp expect actual
59 }
60
61 test_expect_success 'one push option works for a single branch' '
62         mk_repo_pair &&
63         git -C upstream config receive.advertisePushOptions true &&
64         (
65                 cd workbench &&
66                 test_commit one &&
67                 git push --mirror up &&
68                 test_commit two &&
69                 git push --push-option=asdf up main
70         ) &&
71         test_refs main main &&
72         echo "asdf" >expect &&
73         test_cmp expect upstream/.git/hooks/pre-receive.push_options &&
74         test_cmp expect upstream/.git/hooks/post-receive.push_options
75 '
76
77 test_expect_success 'push option denied by remote' '
78         mk_repo_pair &&
79         git -C upstream config receive.advertisePushOptions false &&
80         (
81                 cd workbench &&
82                 test_commit one &&
83                 git push --mirror up &&
84                 test_commit two &&
85                 test_must_fail git push --push-option=asdf up main
86         ) &&
87         test_refs main HEAD@{1}
88 '
89
90 test_expect_success 'two push options work' '
91         mk_repo_pair &&
92         git -C upstream config receive.advertisePushOptions true &&
93         (
94                 cd workbench &&
95                 test_commit one &&
96                 git push --mirror up &&
97                 test_commit two &&
98                 git push --push-option=asdf --push-option="more structured text" up main
99         ) &&
100         test_refs main main &&
101         printf "asdf\nmore structured text\n" >expect &&
102         test_cmp expect upstream/.git/hooks/pre-receive.push_options &&
103         test_cmp expect upstream/.git/hooks/post-receive.push_options
104 '
105
106 test_expect_success 'push options and submodules' '
107         test_when_finished "rm -rf parent" &&
108         test_when_finished "rm -rf parent_upstream" &&
109         mk_repo_pair &&
110         git -C upstream config receive.advertisePushOptions true &&
111         cp -r upstream parent_upstream &&
112         test_commit -C upstream one &&
113
114         test_create_repo parent &&
115         git -C parent remote add up ../parent_upstream &&
116         test_commit -C parent one &&
117         git -C parent push --mirror up &&
118
119         git -C parent submodule add ../upstream workbench &&
120         git -C parent/workbench remote add up ../../upstream &&
121         git -C parent commit -m "add submodule" &&
122
123         test_commit -C parent/workbench two &&
124         git -C parent add workbench &&
125         git -C parent commit -m "update workbench" &&
126
127         git -C parent push \
128                 --push-option=asdf --push-option="more structured text" \
129                 --recurse-submodules=on-demand up main &&
130
131         git -C upstream rev-parse --verify main >expect &&
132         git -C parent/workbench rev-parse --verify main >actual &&
133         test_cmp expect actual &&
134
135         git -C parent_upstream rev-parse --verify main >expect &&
136         git -C parent rev-parse --verify main >actual &&
137         test_cmp expect actual &&
138
139         printf "asdf\nmore structured text\n" >expect &&
140         test_cmp expect upstream/.git/hooks/pre-receive.push_options &&
141         test_cmp expect upstream/.git/hooks/post-receive.push_options &&
142         test_cmp expect parent_upstream/.git/hooks/pre-receive.push_options &&
143         test_cmp expect parent_upstream/.git/hooks/post-receive.push_options
144 '
145
146 test_expect_success 'default push option' '
147         mk_repo_pair &&
148         git -C upstream config receive.advertisePushOptions true &&
149         (
150                 cd workbench &&
151                 test_commit one &&
152                 git push --mirror up &&
153                 test_commit two &&
154                 git -c push.pushOption=default push up main
155         ) &&
156         test_refs main main &&
157         echo "default" >expect &&
158         test_cmp expect upstream/.git/hooks/pre-receive.push_options &&
159         test_cmp expect upstream/.git/hooks/post-receive.push_options
160 '
161
162 test_expect_success 'two default push options' '
163         mk_repo_pair &&
164         git -C upstream config receive.advertisePushOptions true &&
165         (
166                 cd workbench &&
167                 test_commit one &&
168                 git push --mirror up &&
169                 test_commit two &&
170                 git -c push.pushOption=default1 -c push.pushOption=default2 push up main
171         ) &&
172         test_refs main main &&
173         printf "default1\ndefault2\n" >expect &&
174         test_cmp expect upstream/.git/hooks/pre-receive.push_options &&
175         test_cmp expect upstream/.git/hooks/post-receive.push_options
176 '
177
178 test_expect_success 'push option from command line overrides from-config push option' '
179         mk_repo_pair &&
180         git -C upstream config receive.advertisePushOptions true &&
181         (
182                 cd workbench &&
183                 test_commit one &&
184                 git push --mirror up &&
185                 test_commit two &&
186                 git -c push.pushOption=default push --push-option=manual up main
187         ) &&
188         test_refs main main &&
189         echo "manual" >expect &&
190         test_cmp expect upstream/.git/hooks/pre-receive.push_options &&
191         test_cmp expect upstream/.git/hooks/post-receive.push_options
192 '
193
194 test_expect_success 'empty value of push.pushOption in config clears the list' '
195         mk_repo_pair &&
196         git -C upstream config receive.advertisePushOptions true &&
197         (
198                 cd workbench &&
199                 test_commit one &&
200                 git push --mirror up &&
201                 test_commit two &&
202                 git -c push.pushOption=default1 -c push.pushOption= -c push.pushOption=default2 push up main
203         ) &&
204         test_refs main main &&
205         echo "default2" >expect &&
206         test_cmp expect upstream/.git/hooks/pre-receive.push_options &&
207         test_cmp expect upstream/.git/hooks/post-receive.push_options
208 '
209
210 test_expect_success 'invalid push option in config' '
211         mk_repo_pair &&
212         git -C upstream config receive.advertisePushOptions true &&
213         (
214                 cd workbench &&
215                 test_commit one &&
216                 git push --mirror up &&
217                 test_commit two &&
218                 test_must_fail git -c push.pushOption push up main
219         ) &&
220         test_refs main HEAD@{1}
221 '
222
223 test_expect_success 'push options keep quoted characters intact (direct)' '
224         mk_repo_pair &&
225         git -C upstream config receive.advertisePushOptions true &&
226         test_commit -C workbench one &&
227         git -C workbench push --push-option="\"embedded quotes\"" up main &&
228         echo "\"embedded quotes\"" >expect &&
229         test_cmp expect upstream/.git/hooks/pre-receive.push_options
230 '
231
232 . "$TEST_DIRECTORY"/lib-httpd.sh
233 start_httpd
234
235 # set up http repository for fetching/pushing, with push options config
236 # bool set to $1
237 mk_http_pair () {
238         test_when_finished "rm -rf test_http_clone" &&
239         test_when_finished 'rm -rf "$HTTPD_DOCUMENT_ROOT_PATH"/upstream.git' &&
240         mk_repo_pair &&
241         git -C upstream config receive.advertisePushOptions "$1" &&
242         git -C upstream config http.receivepack true &&
243         cp -R upstream/.git "$HTTPD_DOCUMENT_ROOT_PATH"/upstream.git &&
244         git clone "$HTTPD_URL"/smart/upstream test_http_clone
245 }
246
247 test_expect_success 'push option denied properly by http server' '
248         mk_http_pair false &&
249         test_commit -C test_http_clone one &&
250         test_must_fail git -C test_http_clone push --push-option=asdf origin main 2>actual &&
251         test_i18ngrep "the receiving end does not support push options" actual &&
252         git -C test_http_clone push origin main
253 '
254
255 test_expect_success 'push options work properly across http' '
256         mk_http_pair true &&
257
258         test_commit -C test_http_clone one &&
259         git -C test_http_clone push origin main &&
260         git -C "$HTTPD_DOCUMENT_ROOT_PATH"/upstream.git rev-parse --verify main >expect &&
261         git -C test_http_clone rev-parse --verify main >actual &&
262         test_cmp expect actual &&
263
264         test_commit -C test_http_clone two &&
265         git -C test_http_clone push --push-option=asdf --push-option="more structured text" origin main &&
266         printf "asdf\nmore structured text\n" >expect &&
267         test_cmp expect "$HTTPD_DOCUMENT_ROOT_PATH"/upstream.git/hooks/pre-receive.push_options &&
268         test_cmp expect "$HTTPD_DOCUMENT_ROOT_PATH"/upstream.git/hooks/post-receive.push_options &&
269
270         git -C "$HTTPD_DOCUMENT_ROOT_PATH"/upstream.git rev-parse --verify main >expect &&
271         git -C test_http_clone rev-parse --verify main >actual &&
272         test_cmp expect actual
273 '
274
275 test_expect_success 'push options keep quoted characters intact (http)' '
276         mk_http_pair true &&
277
278         test_commit -C test_http_clone one &&
279         git -C test_http_clone push --push-option="\"embedded quotes\"" origin main &&
280         echo "\"embedded quotes\"" >expect &&
281         test_cmp expect "$HTTPD_DOCUMENT_ROOT_PATH"/upstream.git/hooks/pre-receive.push_options
282 '
283
284 # DO NOT add non-httpd-specific tests here, because the last part of this
285 # test script is only executed when httpd is available and enabled.
286
287 test_done