upload-pack: fix a sparse '0 as NULL pointer' warning
[git] / t / t5512-ls-remote.sh
1 #!/bin/sh
2
3 test_description='git ls-remote'
4
5 . ./test-lib.sh
6
7 generate_references () {
8         for ref
9         do
10                 oid=$(git rev-parse "$ref") &&
11                 printf '%s\t%s\n' "$oid" "$ref" || return 1
12         done
13 }
14
15 test_expect_success setup '
16         >file &&
17         git add file &&
18         test_tick &&
19         git commit -m initial &&
20         git tag mark &&
21         git tag mark1.1 &&
22         git tag mark1.2 &&
23         git tag mark1.10 &&
24         git show-ref --tags -d >expected.tag.raw &&
25         sed -e "s/ /    /" expected.tag.raw >expected.tag &&
26         generate_references HEAD >expected.all &&
27         git show-ref -d >refs &&
28         sed -e "s/ /    /" refs >>expected.all &&
29
30         git remote add self "$(pwd)/.git"
31 '
32
33 test_expect_success 'ls-remote --tags .git' '
34         git ls-remote --tags .git >actual &&
35         test_cmp expected.tag actual
36 '
37
38 test_expect_success 'ls-remote .git' '
39         git ls-remote .git >actual &&
40         test_cmp expected.all actual
41 '
42
43 test_expect_success 'ls-remote --tags self' '
44         git ls-remote --tags self >actual &&
45         test_cmp expected.tag actual
46 '
47
48 test_expect_success 'ls-remote self' '
49         git ls-remote self >actual &&
50         test_cmp expected.all actual
51 '
52
53 test_expect_success 'ls-remote --sort="version:refname" --tags self' '
54         generate_references \
55                 refs/tags/mark \
56                 refs/tags/mark1.1 \
57                 refs/tags/mark1.2 \
58                 refs/tags/mark1.10 >expect &&
59         git ls-remote --sort="version:refname" --tags self >actual &&
60         test_cmp expect actual
61 '
62
63 test_expect_success 'ls-remote --sort="-version:refname" --tags self' '
64         generate_references \
65                 refs/tags/mark1.10 \
66                 refs/tags/mark1.2 \
67                 refs/tags/mark1.1 \
68                 refs/tags/mark >expect &&
69         git ls-remote --sort="-version:refname" --tags self >actual &&
70         test_cmp expect actual
71 '
72
73 test_expect_success 'ls-remote --sort="-refname" --tags self' '
74         generate_references \
75                 refs/tags/mark1.2 \
76                 refs/tags/mark1.10 \
77                 refs/tags/mark1.1 \
78                 refs/tags/mark >expect &&
79         git ls-remote --sort="-refname" --tags self >actual &&
80         test_cmp expect actual
81 '
82
83 test_expect_success 'dies when no remote specified and no default remotes found' '
84         test_must_fail git ls-remote
85 '
86
87 test_expect_success 'use "origin" when no remote specified' '
88         URL="$(pwd)/.git" &&
89         echo "From $URL" >exp_err &&
90
91         git remote add origin "$URL" &&
92         git ls-remote 2>actual_err >actual &&
93
94         test_cmp exp_err actual_err &&
95         test_cmp expected.all actual
96 '
97
98 test_expect_success 'suppress "From <url>" with -q' '
99         git ls-remote -q 2>actual_err &&
100         ! test_cmp exp_err actual_err
101 '
102
103 test_expect_success 'use branch.<name>.remote if possible' '
104         #
105         # Test that we are indeed using branch.<name>.remote, not "origin", even
106         # though the "origin" remote has been set.
107         #
108
109         # setup a new remote to differentiate from "origin"
110         git clone . other.git &&
111         (
112                 cd other.git &&
113                 echo "$(git rev-parse HEAD)     HEAD" &&
114                 git show-ref    | sed -e "s/ /  /"
115         ) >exp &&
116
117         URL="other.git" &&
118         echo "From $URL" >exp_err &&
119
120         git remote add other $URL &&
121         git config branch.master.remote other &&
122
123         git ls-remote 2>actual_err >actual &&
124         test_cmp exp_err actual_err &&
125         test_cmp exp actual
126 '
127
128 test_expect_success 'confuses pattern as remote when no remote specified' '
129         if test_have_prereq MINGW
130         then
131                 # Windows does not like asterisks in pathname
132                 does_not_exist=master
133         else
134                 does_not_exist="refs*master"
135         fi &&
136         cat >exp <<-EOF &&
137         fatal: '\''$does_not_exist'\'' does not appear to be a git repository
138         fatal: Could not read from remote repository.
139
140         Please make sure you have the correct access rights
141         and the repository exists.
142         EOF
143         #
144         # Do not expect "git ls-remote <pattern>" to work; ls-remote needs
145         # <remote> if you want to feed <pattern>, just like you cannot say
146         # fetch <branch>.
147         # We could just as easily have used "master"; the "*" emphasizes its
148         # role as a pattern.
149         test_must_fail git ls-remote "$does_not_exist" >actual 2>&1 &&
150         test_i18ncmp exp actual
151 '
152
153 test_expect_success 'die with non-2 for wrong repository even with --exit-code' '
154         {
155                 git ls-remote --exit-code ./no-such-repository
156                 status=$?
157         } &&
158         test $status != 2 && test $status != 0
159 '
160
161 test_expect_success 'Report success even when nothing matches' '
162         git ls-remote other.git "refs/nsn/*" >actual &&
163         test_must_be_empty actual
164 '
165
166 test_expect_success 'Report no-match with --exit-code' '
167         test_expect_code 2 git ls-remote --exit-code other.git "refs/nsn/*" >actual &&
168         test_must_be_empty actual
169 '
170
171 test_expect_success 'Report match with --exit-code' '
172         git ls-remote --exit-code other.git "refs/tags/*" >actual &&
173         git ls-remote . tags/mark* >expect &&
174         test_cmp expect actual
175 '
176
177 test_expect_success 'set up some extra tags for ref hiding' '
178         git tag magic/one &&
179         git tag magic/two
180 '
181
182 for configsection in transfer uploadpack
183 do
184         test_expect_success "Hide some refs with $configsection.hiderefs" '
185                 test_config $configsection.hiderefs refs/tags &&
186                 git ls-remote . >actual &&
187                 test_unconfig $configsection.hiderefs &&
188                 git ls-remote . >expect.raw &&
189                 sed -e "/       refs\/tags\//d" expect.raw >expect &&
190                 test_cmp expect actual
191         '
192
193         test_expect_success "Override hiding of $configsection.hiderefs" '
194                 test_when_finished "test_unconfig $configsection.hiderefs" &&
195                 git config --add $configsection.hiderefs refs/tags &&
196                 git config --add $configsection.hiderefs "!refs/tags/magic" &&
197                 git config --add $configsection.hiderefs refs/tags/magic/one &&
198                 git ls-remote . >actual &&
199                 grep refs/tags/magic/two actual &&
200                 ! grep refs/tags/magic/one actual
201         '
202
203 done
204
205 test_expect_success 'overrides work between mixed transfer/upload-pack hideRefs' '
206         test_config uploadpack.hiderefs refs/tags &&
207         test_config transfer.hiderefs "!refs/tags/magic" &&
208         git ls-remote . >actual &&
209         grep refs/tags/magic actual
210 '
211
212 test_expect_success 'protocol v2 supports hiderefs' '
213         test_config uploadpack.hiderefs refs/tags &&
214         git -c protocol.version=2 ls-remote . >actual &&
215         ! grep refs/tags actual
216 '
217
218 test_expect_success 'ls-remote --symref' '
219         git fetch origin &&
220         echo "ref: refs/heads/master    HEAD" >expect &&
221         generate_references \
222                 HEAD \
223                 refs/heads/master >>expect &&
224         oid=$(git rev-parse HEAD) &&
225         echo "$oid      refs/remotes/origin/HEAD" >>expect &&
226         generate_references \
227                 refs/remotes/origin/master \
228                 refs/tags/mark \
229                 refs/tags/mark1.1 \
230                 refs/tags/mark1.10 \
231                 refs/tags/mark1.2 >>expect &&
232         # Protocol v2 supports sending symrefs for refs other than HEAD, so use
233         # protocol v0 here.
234         GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref >actual &&
235         test_cmp expect actual
236 '
237
238 test_expect_success 'ls-remote with filtered symref (refname)' '
239         rev=$(git rev-parse HEAD) &&
240         cat >expect <<-EOF &&
241         ref: refs/heads/master  HEAD
242         $rev    HEAD
243         EOF
244         # Protocol v2 supports sending symrefs for refs other than HEAD, so use
245         # protocol v0 here.
246         GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref . HEAD >actual &&
247         test_cmp expect actual
248 '
249
250 test_expect_failure 'ls-remote with filtered symref (--heads)' '
251         git symbolic-ref refs/heads/foo refs/tags/mark &&
252         cat >expect <<-EOF &&
253         ref: refs/tags/mark     refs/heads/foo
254         $rev    refs/heads/foo
255         $rev    refs/heads/master
256         EOF
257         # Protocol v2 supports sending symrefs for refs other than HEAD, so use
258         # protocol v0 here.
259         GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref --heads . >actual &&
260         test_cmp expect actual
261 '
262
263 test_expect_success 'ls-remote --symref omits filtered-out matches' '
264         cat >expect <<-EOF &&
265         $rev    refs/heads/foo
266         $rev    refs/heads/master
267         EOF
268         # Protocol v2 supports sending symrefs for refs other than HEAD, so use
269         # protocol v0 here.
270         GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref --heads . >actual &&
271         test_cmp expect actual &&
272         GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref . "refs/heads/*" >actual &&
273         test_cmp expect actual
274 '
275
276 test_lazy_prereq GIT_DAEMON '
277         test_bool_env GIT_TEST_GIT_DAEMON true
278 '
279
280 # This test spawns a daemon, so run it only if the user would be OK with
281 # testing with git-daemon.
282 test_expect_success PIPE,JGIT,GIT_DAEMON 'indicate no refs in standards-compliant empty remote' '
283         test_set_port JGIT_DAEMON_PORT &&
284         JGIT_DAEMON_PID= &&
285         git init --bare empty.git &&
286         >empty.git/git-daemon-export-ok &&
287         mkfifo jgit_daemon_output &&
288         {
289                 jgit daemon --port="$JGIT_DAEMON_PORT" . >jgit_daemon_output &
290                 JGIT_DAEMON_PID=$!
291         } &&
292         test_when_finished kill "$JGIT_DAEMON_PID" &&
293         {
294                 read line &&
295                 case $line in
296                 Exporting*)
297                         ;;
298                 *)
299                         echo "Expected: Exporting" &&
300                         false;;
301                 esac &&
302                 read line &&
303                 case $line in
304                 "Listening on"*)
305                         ;;
306                 *)
307                         echo "Expected: Listening on" &&
308                         false;;
309                 esac
310         } <jgit_daemon_output &&
311         # --exit-code asks the command to exit with 2 when no
312         # matching refs are found.
313         test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git
314 '
315
316 test_expect_success 'ls-remote works outside repository' '
317         # It is important for this repo to be inside the nongit
318         # area, as we want a repo name that does not include
319         # slashes (because those inhibit some of our configuration
320         # lookups).
321         nongit git init --bare dst.git &&
322         nongit git ls-remote dst.git
323 '
324
325 test_expect_success 'ls-remote --sort fails gracefully outside repository' '
326         # Use a sort key that requires access to the referenced objects.
327         nongit test_must_fail git ls-remote --sort=authordate "$TRASH_DIRECTORY" 2>err &&
328         test_i18ngrep "^fatal: not a git repository, but the field '\''authordate'\'' requires access to object data" err
329 '
330
331 test_expect_success 'ls-remote patterns work with all protocol versions' '
332         git for-each-ref --format="%(objectname)        %(refname)" \
333                 refs/heads/master refs/remotes/origin/master >expect &&
334         git -c protocol.version=1 ls-remote . master >actual.v1 &&
335         test_cmp expect actual.v1 &&
336         git -c protocol.version=2 ls-remote . master >actual.v2 &&
337         test_cmp expect actual.v2
338 '
339
340 test_expect_success 'ls-remote prefixes work with all protocol versions' '
341         git for-each-ref --format="%(objectname)        %(refname)" \
342                 refs/heads/ refs/tags/ >expect &&
343         git -c protocol.version=1 ls-remote --heads --tags . >actual.v1 &&
344         test_cmp expect actual.v1 &&
345         git -c protocol.version=2 ls-remote --heads --tags . >actual.v2 &&
346         test_cmp expect actual.v2
347 '
348
349 test_done