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
122
123
124
|
#include "lix/libcmd/command.hh"
#include "lix/libmain/common-args.hh"
#include "lix/libexpr/print-options.hh"
#include "lix/libmain/shared.hh"
#include "lix/libstore/store-api.hh"
#include "lix/libexpr/eval.hh"
#include "lix/libexpr/eval-inline.hh"
#include "lix/libexpr/value-to-json.hh"
#include "eval.hh"
#include "lix/libutil/types.hh"
namespace nix {
struct CmdEval : MixJSON, InstallableCommand, MixReadOnlyOption
{
bool raw = false;
std::optional<std::string> apply;
std::optional<Path> writeTo;
CmdEval() : InstallableCommand()
{
addFlag({
.longName = "raw",
.description = "Print strings without quotes or escaping.",
.handler = {&raw, true},
});
addFlag({
.longName = "apply",
.description = "Apply the function *expr* to each argument.",
.labels = {"expr"},
.handler = {&apply},
});
// `--write-to` was axed because it was not used in-tree, no non-packaging uses out of tree
// could be found, and it was rife with misvehavior including arbitrary file writes as root
// when run a prepared input. we have opted to remove it instead of trying to make it safe.
addFlag({
.longName = "write-to",
.description = "Previously used to write a string or attrset of strings to *path*.",
.labels = {"path"},
.handler = {&writeTo},
.hidden = true,
});
}
std::string description() override
{
return "evaluate a Nix expression";
}
std::string doc() override
{
return
#include "eval.md"
;
}
Category category() override { return catSecondary; }
void run(ref<Store> store, ref<Installable> installable) override
{
if (raw && json)
throw UsageError("--raw and --json are mutually exclusive");
if (writeTo) {
throw UsageError(
"--write-to has been removed because it was insecure and broken, please use "
"structured output formats (e.g. via --json) instead"
);
}
auto const installableValue = InstallableValue::require(installable);
auto evaluator = getEvaluator();
auto state = evaluator->begin(aio());
auto [v, pos] = installableValue->toValue(*state);
NixStringContext context;
if (apply) {
Value vApply = state->eval(evaluator->parseExprFromString(*apply, CanonPath::fromCwd()));
v = state->callFunction(vApply, v, noPos);
}
if (raw) {
logger->pause();
writeFull(
STDOUT_FILENO,
*state->coerceToString(
noPos, v, context, "while generating the eval command output"
)
);
}
else if (json)
{
logger->cout("%s", printValueAsJSON(*state, true, v, pos, context, false));
}
else
{
logger->cout(
"%s",
ValuePrinter(
*state,
v,
PrintOptions{
.force = true,
.derivationPathDepth = 0,
.errors = ErrorPrintBehavior::ThrowTopLevel,
}
)
);
}
}
};
void registerNixEval()
{
registerCommand<CmdEval>("eval");
}
}
|