diff --git a/src/nix/prefetch.cc b/src/nix/prefetch.cc index 5e890f3c8..55b8498ef 100644 --- a/src/nix/prefetch.cc +++ b/src/nix/prefetch.cc @@ -114,14 +114,15 @@ std::tuple prefetchFile( createDirs(unpacked); unpackTarfile(tmpFile.string(), unpacked); + auto entries = std::filesystem::directory_iterator{unpacked}; /* If the archive unpacks to a single file/directory, then use that as the top-level. */ - auto entries = std::filesystem::directory_iterator{unpacked}; - auto file_count = std::distance(entries, std::filesystem::directory_iterator{}); - if (file_count == 1) - tmpFile = entries->path(); - else + tmpFile = entries->path(); + unsigned fileCount = std::distance(entries, std::filesystem::directory_iterator{}); + if (fileCount != 1) { + /* otherwise, use the directory itself */ tmpFile = unpacked; + } } Activity act(*logger, lvlChatty, actUnknown, diff --git a/tests/functional/tarball.sh b/tests/functional/tarball.sh index a2824cd12..f999b7a10 100755 --- a/tests/functional/tarball.sh +++ b/tests/functional/tarball.sh @@ -54,6 +54,18 @@ test_tarball() { # with the content-addressing (! nix-instantiate --eval -E "fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; name = \"foo\"; }") + store_path=$(nix store prefetch-file --json "file://$tarball" | jq -r .storePath) + if ! cmp -s "$store_path" "$tarball"; then + echo "prefetched tarball differs from original: $store_path vs $tarball" >&2 + exit 1 + fi + store_path2=$(nix store prefetch-file --json --unpack "file://$tarball" | jq -r .storePath) + diff_output=$(diff -r "$store_path2" "$tarroot") + if [ -n "$diff_output" ]; then + echo "prefetched tarball differs from original: $store_path2 vs $tarroot" >&2 + echo "$diff_output" + exit 1 + fi } test_tarball '' cat