#!/bin/sh # The snapshot page hands a branch back as an archive. One function below # registers the same checks for every tar based format, and each format # needs the same compressor cgit pipes through on the server, so one missing # tool skips that format on both grounds at once. zip follows at the end, # since unzip shares no flags with the rest. test_description='Verify snapshot' . ./setup.sh # Registers the checks for one tar based format. Takes the archive suffix, # the content type the response must carry, the compressor to unpack with and # the name of the prerequisite guarding the checks. test_tar_snapshot() { ext=$1 type=$2 tool=$3 prereq=$4 if command -v "$tool" >/dev/null 2>&1 then test_set_prereq $prereq else say "Skipping $ext validation tests: $tool not found" fi test_expect_success $prereq "get foo/snapshot/master.$ext" " cgit_url 'foo/snapshot/master.$ext' >tmp " test_expect_success $prereq "check $ext response headers" " head -n 1 tmp | grep 'Status: 200 OK' && head -n 2 tmp | grep '^Content-Type: $type\$' && head -n 3 tmp | grep 'Content-Disposition: inline; filename=.master.$ext.' " test_expect_success $prereq "verify $ext format" " strip_headers master.$ext && '$tool' -t 'master.$ext' " test_expect_success $prereq "untar $ext and verify the content" " rm -rf master && '$tool' -dc 'master.$ext' | tar -xf - && ls master/ >output && test_line_count = 5 output && grep '^5\$' master/file-5 && test_line_count = 1 master/file-5 " } # The uncompressed tar comes straight out of git's archive writer, so tar # itself both proves the format and unpacks it. test_expect_success 'get foo/snapshot/master.tar' ' cgit_url "foo/snapshot/master.tar" >tmp ' test_expect_success 'check tar response headers' ' head -n 1 tmp | grep "Status: 200 OK" && head -n 2 tmp | grep "^Content-Type: application/x-tar$" && head -n 3 tmp | grep "Content-Disposition: inline; filename=.master.tar." ' test_expect_success 'untar and verify the content' ' strip_headers master.tar && rm -rf master && tar -xf master.tar && ls master/ >output && test_line_count = 5 output && grep "^5$" master/file-5 && test_line_count = 1 master/file-5 ' test_tar_snapshot tar.gz application/gzip gzip GZIP test_tar_snapshot tar.bz2 application/x-bzip2 bzip2 BZIP2 test_tar_snapshot tar.lz application/x-lzip lzip LZIP test_tar_snapshot tar.xz application/x-xz xz XZ test_tar_snapshot tar.zst application/zstd zstd ZSTD if command -v unzip >/dev/null 2>&1 then test_set_prereq UNZIP else say 'Skipping zip validation tests: unzip not found' fi test_expect_success 'get foo/snapshot/master.zip' ' cgit_url "foo/snapshot/master.zip" >tmp ' test_expect_success 'check zip response headers' ' head -n 1 tmp | grep "Status: 200 OK" && head -n 2 tmp | grep "^Content-Type: application/zip$" && head -n 3 tmp | grep "Content-Disposition: inline; filename=.master.zip." ' test_expect_success 'strip off the header lines' ' strip_headers master.zip ' test_expect_success UNZIP 'verify zip format' ' unzip -t master.zip ' test_expect_success UNZIP 'unzip and verify the content' ' rm -rf master && unzip master.zip && ls master/ >output && test_line_count = 5 output && grep "^5$" master/file-5 && test_line_count = 1 master/file-5 ' # A tag named v1.0 sheds its v in the snapshot name unless dropping it would # merge two tags. The first tag below stays a loose ref on purpose, because on # a case-insensitive filesystem a ref lookup for V1.0 finds the loose v1.0 # file, and deciding by lookups called every fresh tag ambiguous and kept its # v until git happened to pack the refs. test_expect_success 'set up a repo with a versioned tag' ' mkrepo repos/vtags 2 && git -C repos/vtags update-ref refs/tags/v1.0 HEAD && { echo "virtual-root=/" && echo "cache-size=0" && echo "snapshots=tar.gz" && echo "repo.url=vtags" && echo "repo.path=$PWD/repos/vtags/.git" } >vtagsrc ' test_expect_success 'a loose v tag still sheds its v in the snapshot name' ' CGIT_CONFIG="$PWD/vtagsrc" QUERY_STRING="url=vtags/refs/" cgit >tmp && grep "vtags-1.0.tar.gz" tmp && ! grep "vtags-v1.0.tar.gz" tmp ' # The second tag goes in only after the first is packed, since two loose files # differing in case alone cannot coexist on a case-insensitive filesystem. test_expect_success 'a real case collision keeps the v on both tags' ' git -C repos/vtags pack-refs --all && git -C repos/vtags update-ref refs/tags/V1.0 HEAD~1 && CGIT_CONFIG="$PWD/vtagsrc" QUERY_STRING="url=vtags/refs/" cgit >tmp && grep "vtags-v1.0.tar.gz" tmp && grep "vtags-V1.0.tar.gz" tmp && ! grep "vtags-1.0.tar.gz" tmp ' # A name that is all suffix names no revision, and an empty snapshot-prefix # gives the members no leading directory rather than a leading slash. test_expect_success 'a snapshot name with nothing before its suffix is refused' ' git -C repos/vtags branch v HEAD && sed "s/^snapshots=tar.gz$/snapshots=tar/" vtagsrc >vtagstarrc && CGIT_CONFIG="$PWD/vtagstarrc" QUERY_STRING="url=vtags/snapshot/.tar" cgit >tmp && grep "^Status: 404" tmp ' test_expect_success 'an empty snapshot-prefix puts no slash ahead of the members' ' { cat vtagstarrc && echo "repo.snapshot-prefix=" } >noprefixrc && CGIT_CONFIG="$PWD/noprefixrc" QUERY_STRING="url=vtags/snapshot/vtags.tar&id=master" cgit >tmp && strip_headers noprefix.tar && tar -tf noprefix.tar >members && grep "^file-1$" members && ! grep "^/" members ' # A server may run cgit with no PATH at all, and the compressor is then looked # for on the default path execvp searches. test_expect_success GZIP 'a compressed snapshot is made without a PATH' ' sed "s/^cache-size=.*/cache-size=0/" cgitrc >nopathrc && cgit_bin=$(command -v cgit) && ( unset PATH && CGIT_CONFIG="$PWD/nopathrc" QUERY_STRING="url=foo/snapshot/master.tar.gz" "$cgit_bin" >tmp ) && grep "^Status: 200" tmp && strip_headers nopath.tar.gz && gzip -t nopath.tar.gz ' # A link offers the snapshot of a tag, and the name on it has to lead back to # that tag even when a branch is spelled like the tag's stem. test_expect_success 'a snapshot name leads to the tag ahead of a branch' ' git -C repos/vtags update-ref refs/heads/1.0 $(git -C repos/vtags commit-tree -m shadow HEAD^{tree}) && CGIT_CONFIG="$PWD/vtagsrc" QUERY_STRING="url=vtags/snapshot/vtags-1.0.tar.gz" cgit >tmp && strip_headers tag.tar.gz && test "$(gzip -dc tag.tar.gz | git -C repos/vtags get-tar-commit-id)" = "$(git -C repos/vtags rev-parse refs/tags/v1.0^{commit})" ' test_done