#!/bin/sh test_description='upload-pack ref-in-want' . ./test-lib.sh get_actual_refs () { sed -n -e '/wanted-refs/,/0001/{ /wanted-refs/d /0001/d p }' actual_refs } get_actual_commits () { test-tool pkt-line unpack-sideband o.pack && git index-pack o.pack && git verify-pack -v o.idx >objs && sed -n -e 's/\([0-9a-f][0-9a-f]*\) commit .*/\1/p' objs >objs.sed && sort >actual_commits sorted_commits && test_cmp sorted_commits actual_commits } write_command () { echo "command=$1" if test "$(test_oid algo)" != sha1 then echo "object-format=$(test_oid algo)" fi } # Write a complete fetch command to stdout, suitable for use with `test-tool # pkt-line`. "want-ref", "want", and "have" lines are read from stdin. # # Examples: # # write_fetch_command <<-EOF # want-ref refs/heads/main # have $(git rev-parse a) # EOF # # write_fetch_command <<-EOF # want $(git rev-parse b) # have $(git rev-parse a) # EOF # write_fetch_command () { write_command fetch && echo "0001" && echo "no-progress" && cat && echo "done" && echo "0000" } # c(o/foo) d(o/bar) # \ / # b e(baz) f(main) # \__ | __/ # \ | / # a test_expect_success 'setup repository' ' test_commit a && git branch -M main && git checkout -b o/foo && test_commit b && test_commit c && git checkout -b o/bar b && test_commit d && git checkout -b baz a && test_commit e && git checkout main && test_commit f ' test_expect_success 'config controls ref-in-want advertisement' ' test-tool serve-v2 --advertise-capabilities >out && perl -ne "/ref-in-want/ and print" out >out.filter && test_must_be_empty out.filter && git config uploadpack.allowRefInWant false && test-tool serve-v2 --advertise-capabilities >out && perl -ne "/ref-in-want/ and print" out >out.filter && test_must_be_empty out.filter && git config uploadpack.allowRefInWant true && test-tool serve-v2 --advertise-capabilities >out && perl -ne "/ref-in-want/ and print" out >out.filter && test_file_not_empty out.filter ' test_expect_success 'invalid want-ref line' ' write_fetch_command >pkt <<-EOF && want-ref refs/heads/non-existent EOF test-tool pkt-line pack in && test_must_fail test-tool serve-v2 --stateless-rpc 2>out expected_refs <<-EOF && $oid refs/heads/main EOF git rev-parse f >expected_commits && write_fetch_command >pkt <<-EOF && want-ref refs/heads/main have $(git rev-parse a) EOF test-tool pkt-line pack in && test-tool serve-v2 --stateless-rpc >out expected_refs <<-EOF && $oid_c refs/heads/o/foo $oid_d refs/heads/o/bar EOF git rev-parse c d >expected_commits && write_fetch_command >pkt <<-EOF && want-ref refs/heads/o/foo want-ref refs/heads/o/bar have $(git rev-parse b) EOF test-tool pkt-line pack in && test-tool serve-v2 --stateless-rpc >out expected_refs <<-EOF && $oid refs/heads/main EOF git rev-parse e f >expected_commits && write_fetch_command >pkt <<-EOF && want-ref refs/heads/main want $(git rev-parse e) have $(git rev-parse a) EOF test-tool pkt-line pack in && test-tool serve-v2 --stateless-rpc >out expected_refs <<-EOF && $oid refs/heads/o/foo EOF >expected_commits && write_fetch_command >pkt <<-EOF && want-ref refs/heads/o/foo have $(git rev-parse c) EOF test-tool pkt-line pack in && test-tool serve-v2 --stateless-rpc >out expected && git -C local rev-parse refs/heads/actual >actual && test_cmp expected actual && grep "want $oid" log ' test_expect_success 'fetching multiple refs' ' test_when_finished "rm -f log" && rm -rf local && cp -r "$LOCAL_PRISTINE" local && GIT_TRACE_PACKET="$(pwd)/log" git -C local fetch origin main baz && git -C "$REPO" rev-parse "main" "baz" >expected && git -C local rev-parse refs/remotes/origin/main refs/remotes/origin/baz >actual && test_cmp expected actual && grep "want-ref refs/heads/main" log && grep "want-ref refs/heads/baz" log ' test_expect_success 'fetching ref and exact OID' ' test_when_finished "rm -f log" && rm -rf local && cp -r "$LOCAL_PRISTINE" local && oid=$(git -C "$REPO" rev-parse b) && GIT_TRACE_PACKET="$(pwd)/log" git -C local fetch origin \ main "$oid":refs/heads/actual && git -C "$REPO" rev-parse "main" "b" >expected && git -C local rev-parse refs/remotes/origin/main refs/heads/actual >actual && test_cmp expected actual && grep "want $oid" log && grep "want-ref refs/heads/main" log ' test_expect_success 'fetching with wildcard that does not match any refs' ' test_when_finished "rm -f log" && rm -rf local && cp -r "$LOCAL_PRISTINE" local && git -C local fetch origin refs/heads/none*:refs/heads/* >out && test_must_be_empty out ' test_expect_success 'fetching with wildcard that matches multiple refs' ' test_when_finished "rm -f log" && rm -rf local && cp -r "$LOCAL_PRISTINE" local && GIT_TRACE_PACKET="$(pwd)/log" git -C local fetch origin refs/heads/o*:refs/heads/o* && git -C "$REPO" rev-parse "o/foo" "o/bar" >expected && git -C local rev-parse "o/foo" "o/bar" >actual && test_cmp expected actual && grep "want-ref refs/heads/o/foo" log && grep "want-ref refs/heads/o/bar" log ' REPO="$(pwd)/repo-ns" test_expect_success 'setup namespaced repo' ' ( git init -b main "$REPO" && cd "$REPO" && test_commit a && test_commit b && git checkout a && test_commit c && git checkout a && test_commit d && git update-ref refs/heads/ns-no b && git update-ref refs/namespaces/ns/refs/heads/ns-yes c && git update-ref refs/namespaces/ns/refs/heads/hidden d ) && git -C "$REPO" config uploadpack.allowRefInWant true ' test_expect_success 'with namespace: want-ref is considered relative to namespace' ' wanted_ref=refs/heads/ns-yes && oid=$(git -C "$REPO" rev-parse "refs/namespaces/ns/$wanted_ref") && cat >expected_refs <<-EOF && $oid $wanted_ref EOF cat >expected_commits <<-EOF && $oid $(git -C "$REPO" rev-parse a) EOF write_fetch_command >pkt <<-EOF && want-ref $wanted_ref EOF test-tool pkt-line pack in && GIT_NAMESPACE=ns test-tool -C "$REPO" serve-v2 --stateless-rpc >out pkt <<-EOF && want-ref $wanted_ref EOF test-tool pkt-line pack in && test_must_fail env GIT_NAMESPACE=ns \ test-tool -C "$REPO" serve-v2 --stateless-rpc >out expected_refs <<-EOF && $oid $wanted_ref EOF cat >expected_commits <<-EOF && $oid $(git -C "$REPO" rev-parse a) EOF write_fetch_command >pkt <<-EOF && want-ref $wanted_ref EOF test-tool pkt-line pack in && test-tool -C "$REPO" serve-v2 --stateless-rpc >out pkt <<-EOF && want-ref $wanted_ref EOF test-tool pkt-line pack in && test_must_fail env GIT_NAMESPACE=ns \ test-tool -C "$REPO" serve-v2 --stateless-rpc >out