@@ -40,6 +40,30 @@ write_command () {
4040 fi
4141}
4242
43+ # Write a complete fetch command to stdout, suitable for use with `test-tool
44+ # pkt-line`. "want-ref", "want", and "have" lines are read from stdin.
45+ #
46+ # Examples:
47+ #
48+ # write_fetch_command <<-EOF
49+ # want-ref refs/heads/main
50+ # have $(git rev-parse a)
51+ # EOF
52+ #
53+ # write_fetch_command <<-EOF
54+ # want $(git rev-parse b)
55+ # have $(git rev-parse a)
56+ # EOF
57+ #
58+ write_fetch_command () {
59+ write_command fetch &&
60+ echo " 0001" &&
61+ echo " no-progress" &&
62+ cat &&
63+ echo " done" &&
64+ echo " 0000"
65+ }
66+
4367# c(o/foo) d(o/bar)
4468# \ /
4569# b e(baz) f(main)
@@ -77,15 +101,11 @@ test_expect_success 'config controls ref-in-want advertisement' '
77101'
78102
79103test_expect_success ' invalid want-ref line' '
80- test-tool pkt-line pack >in <<-EOF &&
81- $(write_command fetch)
82- 0001
83- no-progress
104+ write_fetch_command >pkt <<-EOF &&
84105 want-ref refs/heads/non-existent
85- done
86- 0000
87106 EOF
88107
108+ test-tool pkt-line pack <pkt >in &&
89109 test_must_fail test-tool serve-v2 --stateless-rpc 2>out <in &&
90110 grep "unknown ref" out
91111'
@@ -97,16 +117,11 @@ test_expect_success 'basic want-ref' '
97117 EOF
98118 git rev-parse f >expected_commits &&
99119
100- oid=$(git rev-parse a) &&
101- test-tool pkt-line pack >in <<-EOF &&
102- $(write_command fetch)
103- 0001
104- no-progress
120+ write_fetch_command >pkt <<-EOF &&
105121 want-ref refs/heads/main
106- have $oid
107- done
108- 0000
122+ have $(git rev-parse a)
109123 EOF
124+ test-tool pkt-line pack <pkt >in &&
110125
111126 test-tool serve-v2 --stateless-rpc >out <in &&
112127 check_output
@@ -121,17 +136,12 @@ test_expect_success 'multiple want-ref lines' '
121136 EOF
122137 git rev-parse c d >expected_commits &&
123138
124- oid=$(git rev-parse b) &&
125- test-tool pkt-line pack >in <<-EOF &&
126- $(write_command fetch)
127- 0001
128- no-progress
139+ write_fetch_command >pkt <<-EOF &&
129140 want-ref refs/heads/o/foo
130141 want-ref refs/heads/o/bar
131- have $oid
132- done
133- 0000
142+ have $(git rev-parse b)
134143 EOF
144+ test-tool pkt-line pack <pkt >in &&
135145
136146 test-tool serve-v2 --stateless-rpc >out <in &&
137147 check_output
@@ -144,16 +154,12 @@ test_expect_success 'mix want and want-ref' '
144154 EOF
145155 git rev-parse e f >expected_commits &&
146156
147- test-tool pkt-line pack >in <<-EOF &&
148- $(write_command fetch)
149- 0001
150- no-progress
157+ write_fetch_command >pkt <<-EOF &&
151158 want-ref refs/heads/main
152159 want $(git rev-parse e)
153160 have $(git rev-parse a)
154- done
155- 0000
156161 EOF
162+ test-tool pkt-line pack <pkt >in &&
157163
158164 test-tool serve-v2 --stateless-rpc >out <in &&
159165 check_output
@@ -166,16 +172,11 @@ test_expect_success 'want-ref with ref we already have commit for' '
166172 EOF
167173 >expected_commits &&
168174
169- oid=$(git rev-parse c) &&
170- test-tool pkt-line pack >in <<-EOF &&
171- $(write_command fetch)
172- 0001
173- no-progress
175+ write_fetch_command >pkt <<-EOF &&
174176 want-ref refs/heads/o/foo
175- have $oid
176- done
177- 0000
177+ have $(git rev-parse c)
178178 EOF
179+ test-tool pkt-line pack <pkt >in &&
179180
180181 test-tool serve-v2 --stateless-rpc >out <in &&
181182 check_output
@@ -298,6 +299,141 @@ test_expect_success 'fetching with wildcard that matches multiple refs' '
298299 grep "want-ref refs/heads/o/bar" log
299300'
300301
302+ REPO=" $( pwd) /repo-ns"
303+
304+ test_expect_success ' setup namespaced repo' '
305+ (
306+ git init -b main "$REPO" &&
307+ cd "$REPO" &&
308+ test_commit a &&
309+ test_commit b &&
310+ git checkout a &&
311+ test_commit c &&
312+ git checkout a &&
313+ test_commit d &&
314+ git update-ref refs/heads/ns-no b &&
315+ git update-ref refs/namespaces/ns/refs/heads/ns-yes c &&
316+ git update-ref refs/namespaces/ns/refs/heads/hidden d
317+ ) &&
318+ git -C "$REPO" config uploadpack.allowRefInWant true
319+ '
320+
321+ test_expect_success ' with namespace: want-ref is considered relative to namespace' '
322+ wanted_ref=refs/heads/ns-yes &&
323+
324+ oid=$(git -C "$REPO" rev-parse "refs/namespaces/ns/$wanted_ref") &&
325+ cat >expected_refs <<-EOF &&
326+ $oid $wanted_ref
327+ EOF
328+ cat >expected_commits <<-EOF &&
329+ $oid
330+ $(git -C "$REPO" rev-parse a)
331+ EOF
332+
333+ write_fetch_command >pkt <<-EOF &&
334+ want-ref $wanted_ref
335+ EOF
336+ test-tool pkt-line pack <pkt >in &&
337+
338+ GIT_NAMESPACE=ns test-tool -C "$REPO" serve-v2 --stateless-rpc >out <in &&
339+ check_output
340+ '
341+
342+ test_expect_success ' with namespace: want-ref outside namespace is unknown' '
343+ wanted_ref=refs/heads/ns-no &&
344+
345+ write_fetch_command >pkt <<-EOF &&
346+ want-ref $wanted_ref
347+ EOF
348+ test-tool pkt-line pack <pkt >in &&
349+
350+ test_must_fail env GIT_NAMESPACE=ns \
351+ test-tool -C "$REPO" serve-v2 --stateless-rpc >out <in &&
352+ grep "unknown ref" out
353+ '
354+
355+ # Cross-check refs/heads/ns-no indeed exists
356+ test_expect_success ' without namespace: want-ref outside namespace succeeds' '
357+ wanted_ref=refs/heads/ns-no &&
358+
359+ oid=$(git -C "$REPO" rev-parse $wanted_ref) &&
360+ cat >expected_refs <<-EOF &&
361+ $oid $wanted_ref
362+ EOF
363+ cat >expected_commits <<-EOF &&
364+ $oid
365+ $(git -C "$REPO" rev-parse a)
366+ EOF
367+
368+ write_fetch_command >pkt <<-EOF &&
369+ want-ref $wanted_ref
370+ EOF
371+ test-tool pkt-line pack <pkt >in &&
372+
373+ test-tool -C "$REPO" serve-v2 --stateless-rpc >out <in &&
374+ check_output
375+ '
376+
377+ test_expect_success ' with namespace: hideRefs is matched, relative to namespace' '
378+ wanted_ref=refs/heads/hidden &&
379+ git -C "$REPO" config transfer.hideRefs $wanted_ref &&
380+
381+ write_fetch_command >pkt <<-EOF &&
382+ want-ref $wanted_ref
383+ EOF
384+ test-tool pkt-line pack <pkt >in &&
385+
386+ test_must_fail env GIT_NAMESPACE=ns \
387+ test-tool -C "$REPO" serve-v2 --stateless-rpc >out <in &&
388+ grep "unknown ref" out
389+ '
390+
391+ # Cross-check refs/heads/hidden indeed exists
392+ test_expect_success ' with namespace: want-ref succeeds if hideRefs is removed' '
393+ wanted_ref=refs/heads/hidden &&
394+ git -C "$REPO" config --unset transfer.hideRefs $wanted_ref &&
395+
396+ oid=$(git -C "$REPO" rev-parse "refs/namespaces/ns/$wanted_ref") &&
397+ cat >expected_refs <<-EOF &&
398+ $oid $wanted_ref
399+ EOF
400+ cat >expected_commits <<-EOF &&
401+ $oid
402+ $(git -C "$REPO" rev-parse a)
403+ EOF
404+
405+ write_fetch_command >pkt <<-EOF &&
406+ want-ref $wanted_ref
407+ EOF
408+ test-tool pkt-line pack <pkt >in &&
409+
410+ GIT_NAMESPACE=ns test-tool -C "$REPO" serve-v2 --stateless-rpc >out <in &&
411+ check_output
412+ '
413+
414+ test_expect_success ' without namespace: relative hideRefs does not match' '
415+ wanted_ref=refs/namespaces/ns/refs/heads/hidden &&
416+ git -C "$REPO" config transfer.hideRefs refs/heads/hidden &&
417+
418+ oid=$(git -C "$REPO" rev-parse $wanted_ref) &&
419+ cat >expected_refs <<-EOF &&
420+ $oid $wanted_ref
421+ EOF
422+ cat >expected_commits <<-EOF &&
423+ $oid
424+ $(git -C "$REPO" rev-parse a)
425+ EOF
426+
427+ write_fetch_command >pkt <<-EOF &&
428+ want-ref $wanted_ref
429+ EOF
430+ test-tool pkt-line pack <pkt >in &&
431+
432+ test-tool -C "$REPO" serve-v2 --stateless-rpc >out <in &&
433+ check_output
434+ '
435+
436+
301437. " $TEST_DIRECTORY " /lib-httpd.sh
302438start_httpd
303439
0 commit comments