Skip to content

Commit d5c4595

Browse files
authored
Merge pull request #11690 from DeterminateSystems/non-contiguous-tarballs
Handle tarballs where directory entries are not contiguous
2 parents b11c331 + a7b9877 commit d5c4595

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

src/libfetchers/git-utils.cc

+17-1
Original file line numberDiff line numberDiff line change
@@ -977,8 +977,24 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink
977977

978978
void pushBuilder(std::string name)
979979
{
980+
const git_tree_entry * entry;
981+
Tree prevTree = nullptr;
982+
983+
if (!pendingDirs.empty() &&
984+
(entry = git_treebuilder_get(pendingDirs.back().builder.get(), name.c_str())))
985+
{
986+
/* Clone a tree that we've already finished. This happens
987+
if a tarball has directory entries that are not
988+
contiguous. */
989+
if (git_tree_entry_type(entry) != GIT_OBJECT_TREE)
990+
throw Error("parent of '%s' is not a directory", name);
991+
992+
if (git_tree_entry_to_object((git_object * *) (git_tree * *) Setter(prevTree), *repo, entry))
993+
throw Error("looking up parent of '%s': %s", name, git_error_last()->message);
994+
}
995+
980996
git_treebuilder * b;
981-
if (git_treebuilder_new(&b, *repo, nullptr))
997+
if (git_treebuilder_new(&b, *repo, prevTree.get()))
982998
throw Error("creating a tree builder: %s", git_error_last()->message);
983999
pendingDirs.push_back({ .name = std::move(name), .builder = TreeBuilder(b) });
9841000
};

tests/functional/tarball.sh

+14
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,17 @@ chmod +x "$TEST_ROOT/tar_root/foo"
9797
tar cvf "$TEST_ROOT/tar.tar" -C "$TEST_ROOT/tar_root" .
9898
path="$(nix flake prefetch --refresh --json "tarball+file://$TEST_ROOT/tar.tar" | jq -r .storePath)"
9999
[[ $(cat "$path/foo") = bar ]]
100+
101+
# Test a tarball with non-contiguous directory entries.
102+
rm -rf "$TEST_ROOT/tar_root"
103+
mkdir -p "$TEST_ROOT/tar_root/a/b"
104+
echo foo > "$TEST_ROOT/tar_root/a/b/foo"
105+
echo bla > "$TEST_ROOT/tar_root/bla"
106+
tar cvf "$TEST_ROOT/tar.tar" -C "$TEST_ROOT/tar_root" .
107+
echo abc > "$TEST_ROOT/tar_root/bla"
108+
echo xyzzy > "$TEST_ROOT/tar_root/a/b/xyzzy"
109+
tar rvf "$TEST_ROOT/tar.tar" -C "$TEST_ROOT/tar_root" ./a/b/xyzzy ./bla
110+
path="$(nix flake prefetch --refresh --json "tarball+file://$TEST_ROOT/tar.tar" | jq -r .storePath)"
111+
[[ $(cat "$path/a/b/xyzzy") = xyzzy ]]
112+
[[ $(cat "$path/a/b/foo") = foo ]]
113+
[[ $(cat "$path/bla") = abc ]]

0 commit comments

Comments
 (0)