Skip to content

Commit 64c5596

Browse files
authored
Merge pull request #14273 from fzakaria/fzakaria/issue-13944
Make `nix nar [cat|ls]` lazy
1 parent 27767a6 commit 64c5596

File tree

5 files changed

+50
-29
lines changed

5 files changed

+50
-29
lines changed

src/libstore/include/nix/store/nar-accessor.hh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,12 @@ ref<SourceAccessor> makeNarAccessor(Source & source);
2727
*/
2828
using GetNarBytes = std::function<std::string(uint64_t, uint64_t)>;
2929

30-
ref<SourceAccessor> makeLazyNarAccessor(const std::string & listing, GetNarBytes getNarBytes);
30+
/**
31+
* The canonical GetNarBytes function for a seekable Source.
32+
*/
33+
GetNarBytes seekableGetNarBytes(const Path & path);
34+
35+
ref<SourceAccessor> makeLazyNarAccessor(const nlohmann::json & listing, GetNarBytes getNarBytes);
3136

3237
/**
3338
* Write a JSON representation of the contents of a NAR (except file

src/libstore/nar-accessor.cc

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,14 @@ struct NarAccessor : public SourceAccessor
141141
parseDump(indexer, indexer);
142142
}
143143

144-
NarAccessor(const std::string & listing, GetNarBytes getNarBytes)
144+
NarAccessor(const nlohmann::json & listing, GetNarBytes getNarBytes)
145145
: getNarBytes(getNarBytes)
146146
{
147147
using json = nlohmann::json;
148148

149-
std::function<void(NarMember &, json &)> recurse;
149+
std::function<void(NarMember &, const json &)> recurse;
150150

151-
recurse = [&](NarMember & member, json & v) {
151+
recurse = [&](NarMember & member, const json & v) {
152152
std::string type = v["type"];
153153

154154
if (type == "directory") {
@@ -169,8 +169,7 @@ struct NarAccessor : public SourceAccessor
169169
return;
170170
};
171171

172-
json v = json::parse(listing);
173-
recurse(root, v);
172+
recurse(root, listing);
174173
}
175174

176175
NarMember * find(const CanonPath & path)
@@ -251,11 +250,34 @@ ref<SourceAccessor> makeNarAccessor(Source & source)
251250
return make_ref<NarAccessor>(source);
252251
}
253252

254-
ref<SourceAccessor> makeLazyNarAccessor(const std::string & listing, GetNarBytes getNarBytes)
253+
ref<SourceAccessor> makeLazyNarAccessor(const nlohmann::json & listing, GetNarBytes getNarBytes)
255254
{
256255
return make_ref<NarAccessor>(listing, getNarBytes);
257256
}
258257

258+
GetNarBytes seekableGetNarBytes(const Path & path)
259+
{
260+
return [path](uint64_t offset, uint64_t length) {
261+
AutoCloseFD fd = toDescriptor(open(
262+
path.c_str(),
263+
O_RDONLY
264+
#ifndef _WIN32
265+
| O_CLOEXEC
266+
#endif
267+
));
268+
if (!fd)
269+
throw SysError("opening NAR cache file '%s'", path);
270+
271+
if (lseek(fromDescriptorReadOnly(fd.get()), offset, SEEK_SET) != (off_t) offset)
272+
throw SysError("seeking in '%s'", path);
273+
274+
std::string buf(length, 0);
275+
readFull(fd.get(), buf.data(), length);
276+
277+
return buf;
278+
};
279+
}
280+
259281
using nlohmann::json;
260282

261283
json listNar(ref<SourceAccessor> accessor, const CanonPath & path, bool recurse)

src/libstore/remote-fs-accessor.cc

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -70,26 +70,8 @@ std::shared_ptr<SourceAccessor> RemoteFSAccessor::accessObject(const StorePath &
7070

7171
try {
7272
listing = nix::readFile(makeCacheFile(storePath.hashPart(), "ls"));
73-
74-
auto narAccessor = makeLazyNarAccessor(listing, [cacheFile](uint64_t offset, uint64_t length) {
75-
AutoCloseFD fd = toDescriptor(open(
76-
cacheFile.c_str(),
77-
O_RDONLY
78-
#ifndef _WIN32
79-
| O_CLOEXEC
80-
#endif
81-
));
82-
if (!fd)
83-
throw SysError("opening NAR cache file '%s'", cacheFile);
84-
85-
if (lseek(fromDescriptorReadOnly(fd.get()), offset, SEEK_SET) != (off_t) offset)
86-
throw SysError("seeking in '%s'", cacheFile);
87-
88-
std::string buf(length, 0);
89-
readFull(fd.get(), buf.data(), length);
90-
91-
return buf;
92-
});
73+
auto listingJson = nlohmann::json::parse(listing);
74+
auto narAccessor = makeLazyNarAccessor(listingJson, seekableGetNarBytes(cacheFile));
9375

9476
nars.emplace(storePath.hashPart(), narAccessor);
9577
return narAccessor;

src/nix/cat.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#include "nix/cmd/command.hh"
22
#include "nix/store/store-api.hh"
33
#include "nix/store/nar-accessor.hh"
4+
#include "nix/util/serialise.hh"
5+
#include "nix/util/source-accessor.hh"
6+
7+
#include <nlohmann/json.hpp>
48

59
using namespace nix;
610

@@ -71,7 +75,11 @@ struct CmdCatNar : StoreCommand, MixCat
7175

7276
void run(ref<Store> store) override
7377
{
74-
cat(makeNarAccessor(readFile(narPath)), CanonPath{path});
78+
AutoCloseFD fd = open(narPath.c_str(), O_RDONLY);
79+
auto source = FdSource{fd.get()};
80+
auto narAccessor = makeNarAccessor(source);
81+
auto listing = listNar(narAccessor, CanonPath::root, true);
82+
cat(makeLazyNarAccessor(listing, seekableGetNarBytes(narPath)), CanonPath{path});
7583
}
7684
};
7785

src/nix/ls.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,11 @@ struct CmdLsNar : Command, MixLs
145145

146146
void run() override
147147
{
148-
list(makeNarAccessor(readFile(narPath)), CanonPath{path});
148+
AutoCloseFD fd = open(narPath.c_str(), O_RDONLY);
149+
auto source = FdSource{fd.get()};
150+
auto narAccessor = makeNarAccessor(source);
151+
auto listing = listNar(narAccessor, CanonPath::root, true);
152+
list(makeLazyNarAccessor(listing, seekableGetNarBytes(narPath)), CanonPath{path});
149153
}
150154
};
151155

0 commit comments

Comments
 (0)