-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcat.cc
More file actions
121 lines (98 loc) · 3.12 KB
/
Copy pathcat.cc
File metadata and controls
121 lines (98 loc) · 3.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include "nix/cmd/command.hh"
#include "nix/store/store-api.hh"
#include "nix/util/archive.hh"
#include "nix/util/nar-accessor.hh"
#include "nix/util/serialise.hh"
#include "nix/util/source-accessor.hh"
#include <nlohmann/json.hpp>
using namespace nix;
struct MixCat : virtual Args
{
void cat(ref<SourceAccessor> accessor, CanonPath path)
{
auto st = accessor->lstat(path);
if (st.type != SourceAccessor::Type::tRegular)
throw Error("path '%1%' is not a regular file", path.abs());
logger->stop();
writeFull(getStandardOutput(), accessor->readFile(path));
}
};
struct CmdCatStore : StoreCommand, MixCat
{
std::string path;
CmdCatStore()
{
expectArgs({.label = "path", .handler = {&path}, .completer = completePath});
}
std::string description() override
{
return "print the contents of a file in the Nix store on stdout";
}
std::string doc() override
{
return
#include "store-cat.md"
;
}
void run(ref<Store> store) override
{
auto [storePath, rest] = store->toStorePath(path);
cat(store->requireStoreObjectAccessor(storePath), CanonPath{rest});
}
};
struct CmdCatNar : StoreCommand, MixCat
{
Path narPath;
std::string path;
CmdCatNar()
{
expectArgs({.label = "nar", .handler = {&narPath}, .completer = completePath});
expectArg("path", &path);
}
std::string description() override
{
return "print the contents of a file inside a NAR file on stdout";
}
std::string doc() override
{
return
#include "nar-cat.md"
;
}
void run(ref<Store> store) override
{
AutoCloseFD fd = toDescriptor(open(narPath.c_str(), O_RDONLY));
if (!fd)
throw SysError("opening NAR file '%s'", narPath);
auto source = FdSource{fd.get()};
struct CatRegularFileSink : NullFileSystemObjectSink
{
CanonPath neededPath = CanonPath::root;
bool found = false;
void createRegularFile(const CanonPath & path, std::function<void(CreateRegularFileSink &)> crf) override
{
struct : CreateRegularFileSink, FdSink
{
void isExecutable() override {}
} crfSink;
crfSink.fd = INVALID_DESCRIPTOR;
if (path == neededPath) {
logger->stop();
crfSink.skipContents = false;
crfSink.fd = getStandardOutput();
found = true;
} else {
crfSink.skipContents = true;
}
crf(crfSink);
}
} sink;
sink.neededPath = CanonPath(path);
/* NOTE: We still parse the whole file to validate that it's a correct NAR. */
parseDump(sink, source);
if (!sink.found)
throw Error("NAR does not contain regular file '%1%'", path);
}
};
static auto rCmdCatStore = registerCommand2<CmdCatStore>({"store", "cat"});
static auto rCmdCatNar = registerCommand2<CmdCatNar>({"nar", "cat"});