From 1830f5f967c1726d07104fb9b65e8ae84aac287c Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Mon, 29 Sep 2025 23:16:28 +0300 Subject: [PATCH] libutil: Create empty directory at the root for makeEmptySourceAccessor This is my SNAFU. Accidentally broken in 02c9ac445ff527a7b4c5105d20d9ab401117dcee. There's very dubious behavior for 'builtins.readDir /.': { outputs = { ... }: { lib.a = builtins.readDir /.; }; } nix eval /tmp/test-flake#lib.a Starting from 2.27 this now returns an empty set. This really isn't supposed to happen, but this change in the semantics of makeEmptySourceAccessor accidentally changed the behavior of this. --- src/libutil/memory-source-accessor.cc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/libutil/memory-source-accessor.cc b/src/libutil/memory-source-accessor.cc index caff5b56a..a9ffb7746 100644 --- a/src/libutil/memory-source-accessor.cc +++ b/src/libutil/memory-source-accessor.cc @@ -208,11 +208,16 @@ void MemorySink::createSymlink(const CanonPath & path, const std::string & targe ref makeEmptySourceAccessor() { - static auto empty = make_ref().cast(); - /* Don't forget to clear the display prefix, as the default constructed - SourceAccessor has the «unknown» prefix. Since this accessor is supposed - to mimic an empty root directory the prefix needs to be empty. */ - empty->setPathDisplay(""); + static auto empty = []() { + auto empty = make_ref(); + MemorySink sink{*empty}; + sink.createDirectory(CanonPath::root); + /* Don't forget to clear the display prefix, as the default constructed + SourceAccessor has the «unknown» prefix. Since this accessor is supposed + to mimic an empty root directory the prefix needs to be empty. */ + empty->setPathDisplay(""); + return empty.cast(); + }(); return empty; }