src/nix/prefetch: fix prefetch containing current directory instead of tarball

When --unpack was used the nix would add the current directory to the
nix store instead of the content of unpacked.
The reason for this is that std::distance already consumes the iterator.
To fix this we re-instantiate the directory iterator in case the
directory only contains a single entry.

(cherry picked from commit 8cea1fbd97)
This commit is contained in:
Jörg Thalheim 2024-07-05 17:26:58 +02:00 committed by github-actions[bot]
parent df877f4522
commit 73f3179954
2 changed files with 18 additions and 5 deletions

View File

@ -113,15 +113,16 @@ std::tuple<StorePath, Hash> prefetchFile(
createDirs(unpacked); createDirs(unpacked);
unpackTarfile(tmpFile.string(), unpacked); unpackTarfile(tmpFile.string(), unpacked);
auto entries = std::filesystem::directory_iterator{unpacked};
/* If the archive unpacks to a single file/directory, then use /* If the archive unpacks to a single file/directory, then use
that as the top-level. */ 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(); tmpFile = entries->path();
else unsigned fileCount = std::distance(entries, std::filesystem::directory_iterator{});
if (fileCount != 1) {
/* otherwise, use the directory itself */
tmpFile = unpacked; tmpFile = unpacked;
} }
}
Activity act(*logger, lvlChatty, actUnknown, Activity act(*logger, lvlChatty, actUnknown,
fmt("adding '%s' to the store", url)); fmt("adding '%s' to the store", url));

View File

@ -54,6 +54,18 @@ test_tarball() {
# with the content-addressing # with the content-addressing
(! nix-instantiate --eval -E "fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; name = \"foo\"; }") (! 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 test_tarball '' cat