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