libutil: close file handle in async NAR parser

This bit us while upgrading Hydra[1]: when all the data was read into
the hashing sink while receinving NAR contents, the hash was never
created which lead to a test failing because file size was correct, but
the hash was std::nullopt.

[1] https://git.lix.systems/lix-project/hydra/src/commit/7a0dae579b53b4b96a829263b160c6dc9f42ce75/src/hydra-queue-runner/nar-extractor.cc#L70-L73

Change-Id: Ie71b5f1f17c926a2ab95fb2aabf23c7a575ff70b
This commit is contained in:
Maximilian Bosch
2025-06-21 13:52:43 +02:00
parent 3a6414760e
commit 242a228124
2 changed files with 15 additions and 2 deletions
+1
View File
@@ -708,6 +708,7 @@ struct AsyncParser
file->receiveContents({buf.data(), n});
left -= n;
}
file->close();
} else if (auto sl = std::get_if<Parser::Symlink>(&*i)) {
target.createSymlink(name, sl->target);
} else if (auto d = std::get_if<Parser::Directory>(&*i)) {
+14 -2
View File
@@ -248,6 +248,7 @@ namespace parseAsync {
{
bool executable;
uint64_t size;
bool closed;
std::string contents;
operator nar::Entry() const
{
@@ -292,7 +293,10 @@ namespace parseAsync {
file.contents += data;
}
void close() override {}
void close() override
{
file.closed = true;
}
};
explicit ReconstructVisitor(std::map<std::string, Entry> & parent) : parent(parent) {}
@@ -306,7 +310,8 @@ namespace parseAsync {
box_ptr<FileHandle>
createRegularFile(const std::string & name, uint64_t size, bool executable) override
{
auto & file = std::get<File>(parent.emplace(name, File{executable, size}).first->second);
auto & file =
std::get<File>(parent.emplace(name, File{executable, size, false}).first->second);
return make_box_ptr<FileReader>(file);
}
@@ -331,6 +336,13 @@ TEST_P(NarTest, parseAsync)
auto entries = entriesFn()();
parseDump(rv, source).wait(ws).value();
for (auto & [i, val] : contents) {
if (auto f = std::get_if<parseAsync::File>(&val)) {
ASSERT_TRUE(f->closed);
}
}
auto parsed = parseAsync::Directory::toNar(contents.at(""));
while (true) {
auto e = entries.next();