Skip to content

Commit 3955140

Browse files
kimgitster
authored andcommitted
upload-pack.c: treat want-ref relative to namespace
When 'upload-pack' runs within the context of a git namespace, treat any 'want-ref' lines the client sends as relative to that namespace. Also check if the wanted ref is hidden via 'hideRefs'. If it is hidden, respond with an error as if the ref didn't exist. Helped-by: Jonathan Tan <[email protected]> Signed-off-by: Kim Altintop <[email protected]> Reviewed-by: Jonathan Tan <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent bac01c6 commit 3955140

File tree

2 files changed

+146
-7
lines changed

2 files changed

+146
-7
lines changed

t/t5703-upload-pack-ref-in-want.sh

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,141 @@ test_expect_success 'fetching with wildcard that matches multiple refs' '
299299
grep "want-ref refs/heads/o/bar" log
300300
'
301301

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+
302437
. "$TEST_DIRECTORY"/lib-httpd.sh
303438
start_httpd
304439

upload-pack.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,21 +1417,25 @@ static int parse_want_ref(struct packet_writer *writer, const char *line,
14171417
struct string_list *wanted_refs,
14181418
struct object_array *want_obj)
14191419
{
1420-
const char *arg;
1421-
if (skip_prefix(line, "want-ref ", &arg)) {
1420+
const char *refname_nons;
1421+
if (skip_prefix(line, "want-ref ", &refname_nons)) {
14221422
struct object_id oid;
14231423
struct string_list_item *item;
14241424
struct object *o;
1425+
struct strbuf refname = STRBUF_INIT;
14251426

1426-
if (read_ref(arg, &oid)) {
1427-
packet_writer_error(writer, "unknown ref %s", arg);
1428-
die("unknown ref %s", arg);
1427+
strbuf_addf(&refname, "%s%s", get_git_namespace(), refname_nons);
1428+
if (ref_is_hidden(refname_nons, refname.buf) ||
1429+
read_ref(refname.buf, &oid)) {
1430+
packet_writer_error(writer, "unknown ref %s", refname_nons);
1431+
die("unknown ref %s", refname_nons);
14291432
}
1433+
strbuf_release(&refname);
14301434

1431-
item = string_list_append(wanted_refs, arg);
1435+
item = string_list_append(wanted_refs, refname_nons);
14321436
item->util = oiddup(&oid);
14331437

1434-
o = parse_object_or_die(&oid, arg);
1438+
o = parse_object_or_die(&oid, refname_nons);
14351439
if (!(o->flags & WANTED)) {
14361440
o->flags |= WANTED;
14371441
add_object_array(o, NULL, want_obj);

0 commit comments

Comments
 (0)