libexpr: reformat stuff we'll change soon

mainly to keep the next diff smaller. it'll be large enough as is.

Change-Id: Ib8a34520f03539cbf6aa2f0e66cbed05fe1225eb
This commit is contained in:
eldritch horrors
2025-10-05 16:22:35 +02:00
parent db35aa753b
commit 28c4431c69
18 changed files with 581 additions and 249 deletions
+6 -2
View File
@@ -1291,7 +1291,9 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
attrs2["type"] = "strings";
XMLOpenElement m(xml, "meta", attrs2);
for (auto elem : v->listItems()) {
if (elem->type() != nString) continue;
if (elem->type() != nString) {
continue;
}
XMLAttrs attrs3;
attrs3["value"] = elem->str();
xml.writeEmptyElement("string", attrs3);
@@ -1302,7 +1304,9 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
Bindings & attrs = *v->attrs();
for (auto &i : attrs) {
const Attr & a(*attrs.get(i.name));
if(a.value->type() != nString) continue;
if (a.value->type() != nString) {
continue;
}
XMLAttrs attrs3;
attrs3["type"] = globals.state->symbols[i.name];
attrs3["value"] = a.value->str();
+18 -13
View File
@@ -1019,21 +1019,26 @@ Value * NixRepl::replOverlays()
evalSettings.pureEval.setDefault(prevPureEval);
if (!replInit->isLambda()) {
evaluator.errors.make<TypeError>(
"Expected `repl-overlays` entry %s to be a lambda but found %s: %s",
path,
showType(*replInit),
ValuePrinter(state, *replInit, errorPrintOptions)
)
.debugThrow();
evaluator.errors
.make<TypeError>(
"Expected `repl-overlays` entry %s to be a lambda but found %s: %s",
path,
showType(*replInit),
ValuePrinter(state, *replInit, errorPrintOptions)
)
.debugThrow();
}
if (auto attrs = dynamic_cast<AttrsPattern *>(replInit->lambda().fun->pattern.get()); attrs && !attrs->ellipsis) {
evaluator.errors.make<TypeError>(
"Expected first argument of %1% to have %2% to allow future versions of Lix to add additional attributes to the argument",
"repl-overlays",
"..."
)
if (auto attrs = dynamic_cast<AttrsPattern *>(replInit->lambda().fun->pattern.get());
attrs && !attrs->ellipsis)
{
evaluator.errors
.make<TypeError>(
"Expected first argument of %1% to have %2% to allow future versions of Lix to "
"add additional attributes to the argument",
"repl-overlays",
"..."
)
.atPos(replInit->lambda().fun->pos)
.debugThrow();
}
+1 -2
View File
@@ -24,8 +24,7 @@ struct Attr
Symbol name;
PosIdx pos;
Value * value;
Attr(Symbol name, Value * value, PosIdx pos = noPos)
: name(name), pos(pos), value(value) { };
Attr(Symbol name, Value * value, PosIdx pos = noPos) : name(name), pos(pos), value(value) {}
Attr() { };
bool operator < (const Attr & a) const
{
+9 -4
View File
@@ -520,7 +520,8 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(EvalState & state, const st
}
return make_ref<AttrCursor>(
root, std::make_pair(shared_from_this(), name), attr->value, std::move(cachedValue2));
root, std::make_pair(shared_from_this(), name), attr->value, std::move(cachedValue2)
);
}
ref<AttrCursor> AttrCursor::getAttr(EvalState & state, const std::string & name)
@@ -683,11 +684,15 @@ std::vector<std::string> AttrCursor::getListOfStrings(EvalState & state)
std::vector<std::string> res;
for (auto & elem : v.listItems())
res.push_back(std::string(state.forceStringNoCtx(*elem, noPos, "while evaluating an attribute for caching")));
for (auto & elem : v.listItems()) {
res.push_back(std::string(
state.forceStringNoCtx(*elem, noPos, "while evaluating an attribute for caching")
));
}
if (root->db)
if (root->db) {
cachedValue = {root->db->setListOfStrings(getKey(), res), res};
}
return res;
}
+49 -18
View File
@@ -577,8 +577,9 @@ void EvalBuiltins::addConstant(const std::string & name, const Value & v2, Const
We might know the type of a thunk in advance, so be allowed
to just write it down in that case. */
if (auto gotType = v->type(true); gotType != nThunk)
if (auto gotType = v->type(true); gotType != nThunk) {
assert(info.type == gotType);
}
/* Install value the base environment. */
staticEnv->vars.insert_or_assign(symbols.create(name), baseEnvDispl);
@@ -671,8 +672,9 @@ void printWithBindings(const SymbolTable & st, const Env & env)
{
if (env.values[0]->type() == nAttrs) {
std::set<std::string_view> bindings;
for (const auto & attr : *env.values[0]->attrs())
for (const auto & attr : *env.values[0]->attrs()) {
bindings.emplace(st[attr.name]);
}
std::cout << "with: ";
std::cout << ANSI_MAGENTA;
@@ -857,7 +859,9 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
{
for (auto l = var.level; l; --l, env = env->up) ;
if (!var.fromWith) return env->values[var.displ];
if (!var.fromWith) {
return env->values[var.displ];
}
// This early exit defeats the `maybeThunk` optimization for variables from `with`,
// The added complexity of handling this appears to be similarly in cost, or
@@ -866,7 +870,11 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
auto * fromWith = var.fromWith;
while (1) {
forceAttrs(*env->values[0], fromWith->pos, "while evaluating the first subexpression of a with expression");
forceAttrs(
*env->values[0],
fromWith->pos,
"while evaluating the first subexpression of a with expression"
);
auto j = env->values[0]->attrs()->get(var.name);
if (j) {
if (ctx.stats.countCalls) ctx.stats.attrSelects[j->pos]++;
@@ -984,11 +992,13 @@ Value * ExprVar::maybeThunk(EvalState & state, Env & env)
Value * v = state.lookupVar(&env, *this, true);
/* The value might not be initialised in the environment yet.
In that case, ignore it. */
if (v) { state.ctx.stats.nrAvoided++; return v; }
if (v) {
state.ctx.stats.nrAvoided++;
return v;
}
return Expr::maybeThunk(state, env);
}
Value * ExprLiteral::maybeThunk(EvalState & state, Env & env)
{
state.ctx.stats.nrAvoided++;
@@ -1976,7 +1986,9 @@ void EvalState::concatLists(
forceList(*lists[n], pos, errorCtx);
auto l = lists[n]->listSize();
len += l;
if (l) nonEmpty = lists[n];
if (l) {
nonEmpty = lists[n];
}
}
if (nonEmpty && len == nonEmpty->listSize()) {
@@ -1989,8 +2001,9 @@ void EvalState::concatLists(
auto out = list->elems;
for (size_t n = 0, pos = 0; n < nrLists; ++n) {
auto l = lists[n]->listSize();
if (l)
if (l) {
memcpy(out + pos, lists[n]->listElems(), l * sizeof(Value *));
}
pos += l;
}
}
@@ -2171,8 +2184,9 @@ void EvalState::forceValueDeep(Value & v)
}
else if (v.isList()) {
for (auto v2 : v.listItems())
for (auto v2 : v.listItems()) {
recurse(*v2);
}
}
};
@@ -2322,7 +2336,9 @@ bool EvalState::isDerivation(Value & v)
return false;
}
forceValue(*i->value, i->pos);
if (i->value->type() != nString) return false;
if (i->value->type() != nString) {
return false;
}
return i->value->str() == "derivation";
}
@@ -2389,8 +2405,9 @@ BackedStringView EvalState::coerceToString(
.withTrace(pos, errorCtx)
.debugThrow();
}
return coerceToString(pos, *i->value, context, errorCtx,
mode, copyToStore, canonicalizePath);
return coerceToString(
pos, *i->value, context, errorCtx, mode, copyToStore, canonicalizePath
);
}
if (v.type() == nExternal) {
@@ -2426,9 +2443,15 @@ BackedStringView EvalState::coerceToString(
std::string result;
for (auto [n, v2] : enumerate(v.listItems())) {
try {
result += *coerceToString(pos, *v2, context,
"while evaluating one element of the list",
mode, copyToStore, canonicalizePath);
result += *coerceToString(
pos,
*v2,
context,
"while evaluating one element of the list",
mode,
copyToStore,
canonicalizePath
);
} catch (Error & e) {
e.addTrace(ctx.positions[pos], errorCtx);
throw;
@@ -2436,7 +2459,9 @@ BackedStringView EvalState::coerceToString(
if (n < v.listSize() - 1
/* !!! not quite correct */
&& (!v2->isList() || v2->listSize() != 0))
{
result += " ";
}
}
return result;
}
@@ -2597,8 +2622,11 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v
case nList:
if (v1.listSize() != v2.listSize()) return false;
for (size_t n = 0; n < v1.listSize(); ++n)
if (!eqValues(*v1.listElems()[n], *v2.listElems()[n], pos, errorCtx)) return false;
for (size_t n = 0; n < v1.listSize(); ++n) {
if (!eqValues(*v1.listElems()[n], *v2.listElems()[n], pos, errorCtx)) {
return false;
}
}
return true;
case nAttrs: {
@@ -2617,8 +2645,11 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v
/* Otherwise, compare the attributes one by one. */
Bindings::iterator i, j;
for (i = v1.attrs()->begin(), j = v2.attrs()->begin(); i != v1.attrs()->end(); ++i, ++j)
if (i->name != j->name || !eqValues(*i->value, *j->value, pos, errorCtx))
{
if (i->name != j->name || !eqValues(*i->value, *j->value, pos, errorCtx)) {
return false;
}
}
return true;
}
+56 -25
View File
@@ -371,7 +371,10 @@ static Flake getFlake(
expectType(state, nFunction, *outputs->value, outputs->pos);
if (outputs->value->isLambda()) {
if (auto pattern = dynamic_cast<AttrsPattern *>(outputs->value->lambda().fun->pattern.get()); pattern) {
if (auto pattern =
dynamic_cast<AttrsPattern *>(outputs->value->lambda().fun->pattern.get());
pattern)
{
for (auto & formal : pattern->formals) {
if (formal.name != state.ctx.s.self)
flake.inputs.emplace(
@@ -394,37 +397,62 @@ static Flake getFlake(
for (auto & setting : *nixConfig->value->attrs()) {
forceTrivialValue(state, *setting.value, setting.pos);
if (setting.value->type() == nString)
if (setting.value->type() == nString) {
flake.config.settings.emplace(
state.ctx.symbols[setting.name],
std::string(state.forceStringNoCtx(*setting.value, setting.pos, "")));
else if (setting.value->type() == nPath) {
std::string(state.forceStringNoCtx(*setting.value, setting.pos, ""))
);
} else if (setting.value->type() == nPath) {
NixStringContext emptyContext = {};
flake.config.settings.emplace(
state.ctx.symbols[setting.name],
state.coerceToString(setting.pos, *setting.value, emptyContext, "", StringCoercionMode::Strict, true, true) .toOwned());
}
else if (setting.value->type() == nInt)
state
.coerceToString(
setting.pos,
*setting.value,
emptyContext,
"",
StringCoercionMode::Strict,
true,
true
)
.toOwned()
);
} else if (setting.value->type() == nInt) {
flake.config.settings.emplace(
state.ctx.symbols[setting.name],
state.forceInt(*setting.value, setting.pos, "").value);
else if (setting.value->type() == nBool)
state.forceInt(*setting.value, setting.pos, "").value
);
} else if (setting.value->type() == nBool) {
flake.config.settings.emplace(
state.ctx.symbols[setting.name],
Explicit<bool> { state.forceBool(*setting.value, setting.pos, "") });
else if (setting.value->type() == nList) {
Explicit<bool>{state.forceBool(*setting.value, setting.pos, "")}
);
} else if (setting.value->type() == nList) {
std::vector<std::string> ss;
for (auto elem : setting.value->listItems()) {
if (elem->type() != nString)
state.ctx.errors.make<TypeError>("list element in flake configuration setting '%s' is %s while a string is expected",
state.ctx.symbols[setting.name], showType(*setting.value)).debugThrow();
if (elem->type() != nString) {
state.ctx.errors
.make<TypeError>(
"list element in flake configuration setting '%s' is %s while a "
"string is expected",
state.ctx.symbols[setting.name],
showType(*setting.value)
)
.debugThrow();
}
ss.emplace_back(state.forceStringNoCtx(*elem, setting.pos, ""));
}
flake.config.settings.emplace(state.ctx.symbols[setting.name], ss);
} else {
state.ctx.errors
.make<TypeError>(
"flake configuration setting '%s' is %s",
state.ctx.symbols[setting.name],
showType(*setting.value)
)
.debugThrow();
}
else
state.ctx.errors.make<TypeError>("flake configuration setting '%s' is %s",
state.ctx.symbols[setting.name], showType(*setting.value)).debugThrow();
}
}
@@ -927,7 +955,8 @@ void callFlake(EvalState & state,
lockedFlake.flake.lockedRef.input,
*vRootSrc,
false,
lockedFlake.flake.forceDirty);
lockedFlake.flake.forceDirty
);
vRootSubdir->mkString(lockedFlake.flake.lockedRef.subdir);
@@ -1008,14 +1037,16 @@ void prim_flakeRefToString(
} else if (t == nBool) {
attrs.emplace(state.ctx.symbols[attr.name], Explicit<bool>{attr.value->boolean()});
} else if (t == nString) {
attrs.emplace(state.ctx.symbols[attr.name],
std::string(attr.value->str()));
attrs.emplace(state.ctx.symbols[attr.name], std::string(attr.value->str()));
} else {
state.ctx.errors.make<EvalError>(
"flake reference attribute sets may only contain integers, Booleans, "
"and strings, but attribute '%s' is %s",
state.ctx.symbols[attr.name],
showType(*attr.value)).debugThrow();
state.ctx.errors
.make<EvalError>(
"flake reference attribute sets may only contain integers, Booleans, "
"and strings, but attribute '%s' is %s",
state.ctx.symbols[attr.name],
showType(*attr.value)
)
.debugThrow();
}
}
auto flakeRef = FlakeRef::fromAttrs(attrs);
+22 -29
View File
@@ -68,7 +68,9 @@ std::string DrvInfo::queryName(EvalState & state)
if (!i) {
state.ctx.errors.make<TypeError>("derivation name missing").debugThrow();
}
name = state.forceStringNoCtx(*i->value, noPos, "while evaluating the 'name' attribute of a derivation");
name = state.forceStringNoCtx(
*i->value, noPos, "while evaluating the 'name' attribute of a derivation"
);
}
return name;
}
@@ -156,9 +158,7 @@ void DrvInfo::fillOutputs(EvalState & state, bool withPaths)
// NOTE(Qyriad): I don't think there is any codepath that can cause this to error.
state.forceList(
*outputs->value,
outputs->pos,
"while evaluating the 'outputs' attribute of a derivation"
*outputs->value, outputs->pos, "while evaluating the 'outputs' attribute of a derivation"
);
for (auto [idx, elem] : enumerate(outputs->value->listItems())) {
@@ -168,11 +168,7 @@ void DrvInfo::fillOutputs(EvalState & state, bool withPaths)
// it is only possible by overriding a derivation attrset already created by
// one of those with `//` to introduce the failing `outputs` entry.
auto errMsg = fmt("while evaluating output %d of a derivation", idx);
std::string_view outputName = state.forceStringNoCtx(
*elem,
outputs->pos,
errMsg
);
std::string_view outputName = state.forceStringNoCtx(*elem, outputs->pos, errMsg);
if (withPaths) {
// Find the attr with this output's name...
@@ -196,12 +192,8 @@ void DrvInfo::fillOutputs(EvalState & state, bool withPaths)
NixStringContext context;
// And idk what could possibly cause this one to error
// that wouldn't error before here.
auto storePath = state.coerceToStorePath(
outPath->pos,
*outPath->value,
context,
errMsg
);
auto storePath =
state.coerceToStorePath(outPath->pos, *outPath->value, context, errMsg);
this->outputs.emplace(outputName, storePath);
} else {
this->outputs.emplace(outputName, std::nullopt);
@@ -254,11 +246,12 @@ DrvInfo::Outputs DrvInfo::queryOutputs(EvalState & state, bool withPaths, bool o
if (!outTI->isList()) throw Error(errMsg + "expected a list but got %s", Uncolored(showType(outTI->type())));
Outputs result;
for (auto elem : outTI->listItems()) {
if (elem->type() != nString)
if (elem->type() != nString) {
throw Error(
errMsg + "element is %s where a string was expected",
Uncolored(showType(elem->type()))
);
}
auto out = outputs.find(std::string(elem->str()));
if (out == outputs.end()) {
throw Error(errMsg + "output '%s' does not exist", elem->str());
@@ -310,8 +303,11 @@ bool DrvInfo::checkMeta(EvalState & state, Value & v)
{
state.forceValue(v, noPos);
if (v.type() == nList) {
for (auto elem : v.listItems())
if (!checkMeta(state, *elem)) return false;
for (auto elem : v.listItems()) {
if (!checkMeta(state, *elem)) {
return false;
}
}
return true;
}
else if (v.type() == nAttrs) {
@@ -319,8 +315,11 @@ bool DrvInfo::checkMeta(EvalState & state, Value & v)
if (i) {
return false;
}
for (auto & i : *v.attrs())
if (!checkMeta(state, *i.value)) return false;
for (auto & i : *v.attrs()) {
if (!checkMeta(state, *i.value)) {
return false;
}
}
return true;
}
else return v.type() == nInt || v.type() == nBool || v.type() == nString ||
@@ -467,17 +466,11 @@ static void getDerivations(EvalState & state, Value & vIn, PosIdx pos,
// and can cause spurious duplicate detections due to v being on the stack.
for (auto [n, elem] : enumerate(v.listItems())) {
std::string joinedAttrPath = addToPath(pathPrefix, fmt("%d", n));
bool shouldRecurse = getDerivation(state, *elem, joinedAttrPath, drvs, ignoreAssertionFailures);
bool shouldRecurse =
getDerivation(state, *elem, joinedAttrPath, drvs, ignoreAssertionFailures);
if (shouldRecurse) {
getDerivations(
state,
*elem,
pos,
joinedAttrPath,
autoArgs,
drvs,
done,
ignoreAssertionFailures
state, *elem, pos, joinedAttrPath, autoArgs, drvs, done, ignoreAssertionFailures
);
}
}
+4 -2
View File
@@ -49,7 +49,8 @@ class JSONSax : nlohmann::json_sax<JSON> {
parent->value(state).mkAttrs(attrs2.alreadySorted());
return std::move(parent);
}
void add(EvalState & state) override {
void add(EvalState & state) override
{
attrs.insert_or_assign(_key, value(state));
v = nullptr;
}
@@ -71,7 +72,8 @@ class JSONSax : nlohmann::json_sax<JSON> {
}
return std::move(parent);
}
void add(EvalState & state) override {
void add(EvalState & state) override
{
values.push_back(*v);
v = nullptr;
}
+208 -60
View File
@@ -303,15 +303,31 @@ void prim_exec(EvalState & state, Value * * args, Value & v)
if (count == 0)
state.ctx.errors.make<EvalError>("at least one argument to 'exec' required").debugThrow();
NixStringContext context;
auto program = state.coerceToString(noPos, *elems[0], context,
"while evaluating the first element of the argument passed to builtins.exec",
StringCoercionMode::Strict, false).toOwned();
auto program =
state
.coerceToString(
noPos,
*elems[0],
context,
"while evaluating the first element of the argument passed to builtins.exec",
StringCoercionMode::Strict,
false
)
.toOwned();
Strings commandArgs;
for (size_t i = 1; i < count; ++i) {
commandArgs.push_back(
state.coerceToString(noPos, *elems[i], context,
"while evaluating an element of the argument passed to builtins.exec",
StringCoercionMode::Strict, false).toOwned());
state
.coerceToString(
noPos,
*elems[i],
context,
"while evaluating an element of the argument passed to builtins.exec",
StringCoercionMode::Strict,
false
)
.toOwned()
);
}
try {
auto _ = state.realiseContext(context); // FIXME: Handle CA derivations
@@ -530,11 +546,16 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v)
"in the attrset passed as argument to builtins.genericClosure"
);
state.forceList(*startSet->value, noPos, "while evaluating the 'startSet' attribute passed as argument to builtins.genericClosure");
state.forceList(
*startSet->value,
noPos,
"while evaluating the 'startSet' attribute passed as argument to builtins.genericClosure"
);
UnsafeValueList workSet;
for (auto elem : startSet->value->listItems())
for (auto elem : startSet->value->listItems()) {
workSet.push_back(elem);
}
if (startSet->value->listSize() == 0) {
v = *startSet->value;
@@ -548,7 +569,11 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v)
args[0]->attrs(),
"in the attrset passed as argument to builtins.genericClosure"
);
state.forceFunction(*op->value, noPos, "while evaluating the 'operator' attribute passed as argument to builtins.genericClosure");
state.forceFunction(
*op->value,
noPos,
"while evaluating the 'operator' attribute passed as argument to builtins.genericClosure"
);
/* Construct the closure by applying the operator to elements of
`workSet', adding the result to `workSet', continuing until
@@ -572,7 +597,9 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v)
);
state.forceValue(*key->value, noPos);
if (!doneKeys.insert(key->value).second) continue;
if (!doneKeys.insert(key->value).second) {
continue;
}
res.push_back(e);
/* Call the `operator' function with `e' as argument. */
@@ -782,9 +809,15 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
std::string drvName;
try {
drvName = state.forceStringNoCtx(*nameAttr->value, noPos, "while evaluating the `name` attribute passed to builtins.derivationStrict");
drvName = state.forceStringNoCtx(
*nameAttr->value,
noPos,
"while evaluating the `name` attribute passed to builtins.derivationStrict"
);
} catch (Error & e) {
e.addTrace(state.ctx.positions[nameAttr->pos], "while evaluating the derivation attribute 'name'");
e.addTrace(
state.ctx.positions[nameAttr->pos], "while evaluating the derivation attribute 'name'"
);
throw;
}
@@ -901,34 +934,48 @@ drvName, Bindings * attrs, Value & v)
if (ignoreNulls) {
state.forceValue(*i->value, noPos);
if (i->value->type() == nNull) continue;
if (i->value->type() == nNull) {
continue;
}
}
if (i->name == state.ctx.s.contentAddressed && state.forceBool(*i->value, noPos, context_below)) {
if (i->name == state.ctx.s.contentAddressed
&& state.forceBool(*i->value, noPos, context_below))
{
state.ctx.errors.make<EvalError>("ca derivations are not supported in Lix")
.debugThrow();
}
else if (i->name == state.ctx.s.impure && state.forceBool(*i->value, noPos, context_below)) {
else if (i->name == state.ctx.s.impure
&& state.forceBool(*i->value, noPos, context_below))
{
state.ctx.errors.make<EvalError>("impure derivations are not supported in Lix")
.debugThrow();
}
/* The `args' attribute is special: it supplies the
command-line arguments to the builder. */
else if (i->name == state.ctx.s.args) {
else if (i->name == state.ctx.s.args)
{
state.forceList(*i->value, noPos, context_below);
for (auto elem : i->value->listItems()) {
auto s = state.coerceToString(noPos, *elem, context,
"while evaluating an element of the argument list",
StringCoercionMode::ToString).toOwned();
auto s = state
.coerceToString(
noPos,
*elem,
context,
"while evaluating an element of the argument list",
StringCoercionMode::ToString
)
.toOwned();
drv.args.push_back(s);
}
}
/* All other attributes are passed to the builder through
the environment. */
else {
else
{
if (jsonObject) {
@@ -951,8 +998,9 @@ drvName, Bindings * attrs, Value & v)
/* Require outputs to be a list of strings. */
state.forceList(*i->value, noPos, context_below);
Strings ss;
for (auto elem : i->value->listItems())
for (auto elem : i->value->listItems()) {
ss.emplace_back(state.forceStringNoCtx(*elem, noPos, context_below));
}
handleOutputs(ss);
}
@@ -1000,17 +1048,26 @@ drvName, Bindings * attrs, Value & v)
);
} else {
auto s = state.coerceToString(noPos, *i->value, context, context_below, StringCoercionMode::ToString).toOwned();
auto s = state
.coerceToString(
noPos,
*i->value,
context,
context_below,
StringCoercionMode::ToString
)
.toOwned();
drv.env.emplace(key, s);
if (i->name == state.ctx.s.builder) drv.builder = std::move(s);
else if (i->name == state.ctx.s.system) drv.platform = std::move(s);
if (i->name == state.ctx.s.builder) {
drv.builder = std::move(s);
} else if (i->name == state.ctx.s.system)
drv.platform = std::move(s);
else if (i->name == state.ctx.s.outputHash) outputHash = std::move(s);
else if (i->name == state.ctx.s.outputHashAlgo) outputHashAlgo = std::move(s);
else if (i->name == state.ctx.s.outputHashMode) handleHashMode(s);
else if (i->name == state.ctx.s.outputs)
handleOutputs(tokenizeString<Strings>(s));
}
}
} catch (Error & e) {
@@ -1325,7 +1382,9 @@ static void prim_findFile(EvalState & state, Value * * args, Value & v)
SearchPath searchPath;
for (auto v2 : args[0]->listItems()) {
state.forceAttrs(*v2, noPos, "while evaluating an element of the list passed to builtins.findFile");
state.forceAttrs(
*v2, noPos, "while evaluating an element of the list passed to builtins.findFile"
);
std::string prefix;
auto i = v2->attrs()->get(state.ctx.s.prefix);
@@ -1341,9 +1400,17 @@ static void prim_findFile(EvalState & state, Value * * args, Value & v)
i = getAttr(state, state.ctx.s.path, v2->attrs(), "in an element of the __nixPath");
NixStringContext context;
auto path = state.coerceToString(noPos, *i->value, context,
"while evaluating the `path` attribute of an element of the list passed to builtins.findFile",
StringCoercionMode::Strict, false).toOwned();
auto path = state
.coerceToString(
noPos,
*i->value,
context,
"while evaluating the `path` attribute of an element of the list "
"passed to builtins.findFile",
StringCoercionMode::Strict,
false
)
.toOwned();
try {
auto rewrites = state.realiseContext(context);
@@ -1627,21 +1694,48 @@ static void prim_path(EvalState & state, Value * * args, Value & v)
for (auto & attr : *args[0]->attrs()) {
auto & n = state.ctx.symbols[attr.name];
if (n == "path")
path.emplace(state.coerceToPath(attr.pos, *attr.value, context, "while evaluating the 'path' attribute passed to 'builtins.path'"));
else if (attr.name == state.ctx.s.name)
name = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `name` attribute passed to builtins.path");
else if (n == "filter")
state.forceFunction(*(filterFun = attr.value), attr.pos, "while evaluating the `filter` parameter passed to builtins.path");
else if (n == "recursive")
method = FileIngestionMethod { state.forceBool(*attr.value, attr.pos, "while evaluating the `recursive` attribute passed to builtins.path") };
else if (n == "sha256")
expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `sha256` attribute passed to builtins.path"), HashType::SHA256);
else
state.ctx.errors.make<EvalError>(
"unsupported argument '%1%' to 'addPath'",
state.ctx.symbols[attr.name]
).atPos(attr.pos).debugThrow();
if (n == "path") {
path.emplace(state.coerceToPath(
attr.pos,
*attr.value,
context,
"while evaluating the 'path' attribute passed to 'builtins.path'"
));
} else if (attr.name == state.ctx.s.name) {
name = state.forceStringNoCtx(
*attr.value,
attr.pos,
"while evaluating the `name` attribute passed to builtins.path"
);
} else if (n == "filter") {
state.forceFunction(
*(filterFun = attr.value),
attr.pos,
"while evaluating the `filter` parameter passed to builtins.path"
);
} else if (n == "recursive") {
method = FileIngestionMethod{state.forceBool(
*attr.value,
attr.pos,
"while evaluating the `recursive` attribute passed to builtins.path"
)};
} else if (n == "sha256") {
expectedHash = newHashAllowEmpty(
state.forceStringNoCtx(
*attr.value,
attr.pos,
"while evaluating the `sha256` attribute passed to builtins.path"
),
HashType::SHA256
);
} else {
state.ctx.errors
.make<EvalError>(
"unsupported argument '%1%' to 'addPath'", state.ctx.symbols[attr.name]
)
.atPos(attr.pos)
.debugThrow();
}
}
if (!path)
state.ctx.errors.make<EvalError>(
@@ -1804,7 +1898,11 @@ static void prim_removeAttrs(EvalState & state, Value * * args, Value & v)
boost::container::small_vector<Attr, 64> names;
names.reserve(args[1]->listSize());
for (auto elem : args[1]->listItems()) {
state.forceStringNoCtx(*elem, noPos, "while evaluating the values of the second argument passed to builtins.removeAttrs");
state.forceStringNoCtx(
*elem,
noPos,
"while evaluating the values of the second argument passed to builtins.removeAttrs"
);
names.emplace_back(state.ctx.symbols.create(elem->str()), nullptr);
}
std::sort(names.begin(), names.end());
@@ -1834,11 +1932,18 @@ static void prim_listToAttrs(EvalState & state, Value * * args, Value & v)
std::set<Symbol> seen;
for (auto v2 : args[0]->listItems()) {
state.forceAttrs(*v2, noPos, "while evaluating an element of the list passed to builtins.listToAttrs");
state.forceAttrs(
*v2, noPos, "while evaluating an element of the list passed to builtins.listToAttrs"
);
auto j = getAttr(state, state.ctx.s.name, v2->attrs(), "in a {name=...; value=...;} pair");
auto name = state.forceStringNoCtx(*j->value, j->pos, "while evaluating the `name` attribute of an element of the list passed to builtins.listToAttrs");
auto name = state.forceStringNoCtx(
*j->value,
j->pos,
"while evaluating the `name` attribute of an element of the list passed to "
"builtins.listToAttrs"
);
auto sym = state.ctx.symbols.create(name);
if (seen.insert(sym).second) {
@@ -1928,7 +2033,11 @@ static void prim_catAttrs(EvalState & state, Value * * args, Value & v)
size_t found = 0;
for (auto v2 : args[1]->listItems()) {
state.forceAttrs(*v2, noPos, "while evaluating an element in the list passed as second argument to builtins.catAttrs");
state.forceAttrs(
*v2,
noPos,
"while evaluating an element in the list passed as second argument to builtins.catAttrs"
);
auto i = v2->attrs()->get(attrName);
if (i) {
res[found++] = i->value;
@@ -1999,9 +2108,15 @@ static void prim_zipAttrsWith(EvalState & state, Value * * args, Value & v)
for (unsigned int n = 0; n < listSize; ++n) {
Value * vElem = listElems[n];
state.forceAttrs(*vElem, noPos, "while evaluating a value of the list passed as second argument to builtins.zipAttrsWith");
for (auto & attr : *vElem->attrs())
state.forceAttrs(
*vElem,
noPos,
"while evaluating a value of the list passed as second argument to "
"builtins.zipAttrsWith"
);
for (auto & attr : *vElem->attrs()) {
attrsSeen[attr.name].first++;
}
}
auto attrs = state.ctx.buildBindings(attrsSeen.size());
@@ -2148,11 +2263,18 @@ static void prim_elem(EvalState & state, Value * * args, Value & v)
{
bool res = false;
state.forceList(*args[1], noPos, "while evaluating the second argument passed to builtins.elem");
for (auto elem : args[1]->listItems())
if (state.eqValues(*args[0], *elem, noPos, "while searching for the presence of the given element in the list")) {
for (auto elem : args[1]->listItems()) {
if (state.eqValues(
*args[0],
*elem,
noPos,
"while searching for the presence of the given element in the list"
))
{
res = true;
break;
}
}
v.mkBool(res);
}
@@ -2160,7 +2282,13 @@ static void prim_elem(EvalState & state, Value * * args, Value & v)
static void prim_concatLists(EvalState & state, Value * * args, Value & v)
{
state.forceList(*args[0], noPos, "while evaluating the first argument passed to builtins.concatLists");
state.concatLists(v, args[0]->listSize(), args[0]->listElems(), noPos, "while evaluating a value of the list passed to builtins.concatLists");
state.concatLists(
v,
args[0]->listSize(),
args[0]->listElems(),
noPos,
"while evaluating a value of the list passed to builtins.concatLists"
);
}
/* Return the length of a list. This is an O(1) time operation. */
@@ -2392,8 +2520,9 @@ static void prim_concatMap(EvalState & state, Value * * args, Value & v)
auto out = result->elems;
for (unsigned int n = 0, pos = 0; n < nrLists; ++n) {
auto l = lists[n].listSize();
if (l)
if (l) {
memcpy(out + pos, lists[n].listElems(), l * sizeof(Value *));
}
pos += l;
}
}
@@ -2716,8 +2845,9 @@ void prim_split(EvalState & state, Value * * args, Value & v)
}
// Add a string for non-matched suffix characters.
if (idx == 2 * len)
if (idx == 2 * len) {
(result->elems[idx++] = state.ctx.mem.allocValue())->mkString(match.suffix().str());
}
}
assert(idx == 2 * len + 1);
@@ -2740,7 +2870,13 @@ static void prim_concatStringsSep(EvalState & state, Value * * args, Value & v)
for (auto elem : args[1]->listItems()) {
if (first) first = false; else res += sep;
res += *state.coerceToString(noPos, *elem, context, "while evaluating one element of the list of strings to concat passed to builtins.concatStringsSep");
res += *state.coerceToString(
noPos,
*elem,
context,
"while evaluating one element of the list of strings to concat passed to "
"builtins.concatStringsSep"
);
}
v.mkString(res, context);
@@ -2757,8 +2893,13 @@ static void prim_replaceStrings(EvalState & state, Value * * args, Value & v)
std::vector<std::string> from;
from.reserve(args[0]->listSize());
for (auto elem : args[0]->listItems())
from.emplace_back(state.forceString(*elem, noPos, "while evaluating one of the strings to replace passed to builtins.replaceStrings"));
for (auto elem : args[0]->listItems()) {
from.emplace_back(state.forceString(
*elem,
noPos,
"while evaluating one of the strings to replace passed to builtins.replaceStrings"
));
}
std::unordered_map<size_t, std::string> cache;
auto to = args[1]->listItems();
@@ -2779,10 +2920,17 @@ static void prim_replaceStrings(EvalState & state, Value * * args, Value & v)
auto v = cache.find(j_index);
if (v == cache.end()) {
NixStringContext ctx;
auto ts = state.forceString(**j, ctx, noPos, "while evaluating one of the replacement strings passed to builtins.replaceStrings");
auto ts = state.forceString(
**j,
ctx,
noPos,
"while evaluating one of the replacement strings passed to "
"builtins.replaceStrings"
);
v = (cache.emplace(j_index, ts)).first;
for (auto& path : ctx)
for (auto & path : ctx) {
context.insert(path);
}
}
res += v->second;
if (i->empty()) {
+1 -2
View File
@@ -142,8 +142,7 @@ void prim_fetchClosure(EvalState & state, Value * * args, Value & v)
}
else if (attrName == "fromStore")
fromStoreUrl = state.forceStringNoCtx(*attr.value, attr.pos,
attrHint());
fromStoreUrl = state.forceStringNoCtx(*attr.value, attr.pos, attrHint());
else if (attrName == "inputAddressed")
inputAddressedMaybe = state.forceBool(*attr.value, attr.pos, attrHint());
+32 -9
View File
@@ -20,22 +20,45 @@ static void prim_fetchMercurial(EvalState & state, Value * * args, Value & v)
for (auto & attr : *args[0]->attrs()) {
std::string_view n(state.ctx.symbols[attr.name]);
if (n == "url")
url = state.coerceToString(attr.pos, *attr.value, context,
"while evaluating the `url` attribute passed to builtins.fetchMercurial",
StringCoercionMode::Strict, false).toOwned();
url = state
.coerceToString(
attr.pos,
*attr.value,
context,
"while evaluating the `url` attribute passed to "
"builtins.fetchMercurial",
StringCoercionMode::Strict,
false
)
.toOwned();
else if (n == "rev") {
// Ugly: unlike fetchGit, here the "rev" attribute can
// be both a revision or a branch/tag name.
auto value = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `rev` attribute passed to builtins.fetchMercurial");
if (std::regex_match(value.begin(), value.end(), revRegex))
auto value = state.forceStringNoCtx(
*attr.value,
attr.pos,
"while evaluating the `rev` attribute passed to builtins.fetchMercurial"
);
if (std::regex_match(value.begin(), value.end(), revRegex)) {
rev = Hash::parseAny(value, HashType::SHA1);
else
} else
ref = value;
}
else if (n == "name")
name = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `name` attribute passed to builtins.fetchMercurial");
else
state.ctx.errors.make<EvalError>("unsupported argument '%s' to 'fetchMercurial'", state.ctx.symbols[attr.name]).atPos(attr.pos).debugThrow();
name = state.forceStringNoCtx(
*attr.value,
attr.pos,
"while evaluating the `name` attribute passed to builtins.fetchMercurial"
);
else {
state.ctx.errors
.make<EvalError>(
"unsupported argument '%s' to 'fetchMercurial'",
state.ctx.symbols[attr.name]
)
.atPos(attr.pos)
.debugThrow();
}
}
if (url.empty())
+50 -19
View File
@@ -127,11 +127,16 @@ static void fetchTree(
state.ctx.errors.make<EvalError>(
"unexpected attribute 'type'"
).atPos(pos).debugThrow();
type = state.forceStringNoCtx(*aType->value, aType->pos, "while evaluating the `type` attribute passed to builtins.fetchTree");
} else if (!type)
state.ctx.errors.make<EvalError>(
"attribute 'type' is missing in call to 'fetchTree'"
).atPos(pos).debugThrow();
type = state.forceStringNoCtx(
*aType->value,
aType->pos,
"while evaluating the `type` attribute passed to builtins.fetchTree"
);
} else if (!type) {
state.ctx.errors.make<EvalError>("attribute 'type' is missing in call to 'fetchTree'")
.atPos(pos)
.debugThrow();
}
attrs.emplace("type", type.value());
@@ -139,17 +144,21 @@ static void fetchTree(
if (attr.name == state.ctx.s.type) continue;
state.forceValue(*attr.value, attr.pos);
if (attr.value->type() == nPath || attr.value->type() == nString) {
auto s = state.coerceToString(attr.pos, *attr.value, context, "", StringCoercionMode::Strict, false).toOwned();
auto s =
state
.coerceToString(
attr.pos, *attr.value, context, "", StringCoercionMode::Strict, false
)
.toOwned();
attrs.emplace(state.ctx.symbols[attr.name],
state.ctx.symbols[attr.name] == "url"
? type == "git"
? fixURIForGit(s, state)
: fixURI(s, state)
: s);
}
else if (attr.value->type() == nBool)
} else if (attr.value->type() == nBool) {
attrs.emplace(state.ctx.symbols[attr.name], Explicit<bool>{attr.value->boolean()});
else if (attr.value->type() == nInt) {
} else if (attr.value->type() == nInt) {
auto intValue = attr.value->integer().value;
if (intValue < 0) {
@@ -158,9 +167,16 @@ static void fetchTree(
unsigned long asUnsigned = intValue;
attrs.emplace(state.ctx.symbols[attr.name], asUnsigned);
} else
state.ctx.errors.make<TypeError>("fetchTree argument '%s' is %s while a string, Boolean or integer is expected",
state.ctx.symbols[attr.name], showType(*attr.value)).debugThrow();
} else {
state.ctx.errors
.make<TypeError>(
"fetchTree argument '%s' is %s while a string, Boolean or integer is "
"expected",
state.ctx.symbols[attr.name],
showType(*attr.value)
)
.debugThrow();
}
}
if (!params.allowNameArgument)
@@ -224,14 +240,29 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
for (auto & attr : *args[0]->attrs()) {
std::string_view n(state.ctx.symbols[attr.name]);
if (n == "url")
url = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the url we should fetch");
else if (n == "sha256")
expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the sha256 of the content we should fetch"), HashType::SHA256);
else if (n == "name")
name = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the name of the content we should fetch");
else
url = state.forceStringNoCtx(
*attr.value, attr.pos, "while evaluating the url we should fetch"
);
else if (n == "sha256") {
expectedHash = newHashAllowEmpty(
state.forceStringNoCtx(
*attr.value,
attr.pos,
"while evaluating the sha256 of the content we should fetch"
),
HashType::SHA256
);
} else if (n == "name")
name = state.forceStringNoCtx(
*attr.value,
attr.pos,
"while evaluating the name of the content we should fetch"
);
else {
state.ctx.errors.make<EvalError>("unsupported argument '%s' to '%s'", n, who)
.atPos(pos).debugThrow();
.atPos(pos)
.debugThrow();
}
}
if (!url)
+6 -3
View File
@@ -60,10 +60,13 @@ JSON printValueAsJSON(EvalState & state, bool strict,
for (auto & j : names) {
const Attr & a(*v.attrs()->get(state.ctx.symbols.create(j)));
try {
out[j] = printValueAsJSON(state, strict, *a.value, a.pos, context, copyToStore);
out[j] =
printValueAsJSON(state, strict, *a.value, a.pos, context, copyToStore);
} catch (Error & e) {
e.addTrace(state.ctx.positions[a.pos],
HintFmt("while evaluating attribute '%1%'", j));
e.addTrace(
state.ctx.positions[a.pos],
HintFmt("while evaluating attribute '%1%'", j)
);
throw;
}
}
+11 -6
View File
@@ -43,8 +43,7 @@ static void showAttrs(EvalState & state, bool strict, bool location,
if (location && a.pos) posToXML(state, xmlAttrs, state.ctx.positions[a.pos]);
XMLOpenElement _(doc, "attr", xmlAttrs);
printValueAsXML(state, strict, location,
*a.value, doc, context, drvsSeen, a.pos);
printValueAsXML(state, strict, location, *a.value, doc, context, drvsSeen, a.pos);
}
}
@@ -90,14 +89,19 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
Path drvPath;
a = v.attrs()->get(state.ctx.s.drvPath);
if (a) {
if (strict) state.forceValue(*a->value, a->pos);
if (a->value->type() == nString)
if (strict) {
state.forceValue(*a->value, a->pos);
}
if (a->value->type() == nString) {
xmlAttrs["drvPath"] = drvPath = a->value->str();
}
}
a = v.attrs()->get(state.ctx.s.outPath);
if (a) {
if (strict) state.forceValue(*a->value, a->pos);
if (strict) {
state.forceValue(*a->value, a->pos);
}
if (a->value->type() == nString) {
xmlAttrs["outPath"] = a->value->str();
}
@@ -120,8 +124,9 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
case nList: {
XMLOpenElement _(doc, "list");
for (auto v2 : v.listItems())
for (auto v2 : v.listItems()) {
printValueAsXML(state, strict, location, *v2, doc, context, drvsSeen, pos);
}
break;
}
+66 -32
View File
@@ -192,12 +192,14 @@ static void enumerateOutputs(
/* Hack: ensure that hydraJobs is evaluated before anything
else. This way we can disable IFD for hydraJobs and then enable
it for other outputs. */
if (auto attr = aOutputs->value->attrs()->get(sHydraJobs))
if (auto attr = aOutputs->value->attrs()->get(sHydraJobs)) {
callback(state.ctx.symbols[attr->name], *attr->value, attr->pos);
}
for (auto & attr : *aOutputs->value->attrs()) {
if (attr.name != sHydraJobs)
if (attr.name != sHydraJobs) {
callback(state.ctx.symbols[attr.name], *attr.value, attr.pos);
}
}
}
@@ -506,8 +508,9 @@ struct CmdFlakeCheck : FlakeCommand
Activity act(*logger, lvlInfo, actUnknown,
fmt("checking Hydra job '%s'", attrPath2));
checkDerivation(attrPath2, *attr.value, attr.pos);
} else
} else {
checkHydraJobs(attrPath2, *attr.value, attr.pos);
}
}
} catch (Error & e) {
@@ -625,9 +628,15 @@ struct CmdFlakeCheck : FlakeCommand
state->forceAttrs(*attr.value, attr.pos, "");
for (auto & attr2 : *attr.value->attrs()) {
auto drvPath = checkDerivation(
fmt("%s.%s.%s", name, attr_name, evaluator->symbols[attr2.name]),
*attr2.value, attr2.pos);
if (drvPath && attr_name == evalSettings.getCurrentSystem()) {
fmt("%s.%s.%s",
name,
attr_name,
evaluator->symbols[attr2.name]),
*attr2.value,
attr2.pos
);
if (drvPath && attr_name == evalSettings.getCurrentSystem())
{
drvPaths.push_back(DerivedPath::Built {
.drvPath = makeConstantStorePath(*drvPath),
.outputs = OutputsSpec::All { },
@@ -645,9 +654,7 @@ struct CmdFlakeCheck : FlakeCommand
const auto & attr_name = evaluator->symbols[attr.name];
checkSystemName(attr_name, attr.pos);
if (checkSystemType(attr_name, attr.pos)) {
checkApp(
fmt("%s.%s", name, attr_name),
*attr.value, attr.pos);
checkApp(fmt("%s.%s", name, attr_name), *attr.value, attr.pos);
};
}
}
@@ -660,10 +667,16 @@ struct CmdFlakeCheck : FlakeCommand
checkSystemName(attr_name, attr.pos);
if (checkSystemType(attr_name, attr.pos)) {
state->forceAttrs(*attr.value, attr.pos, "");
for (auto & attr2 : *attr.value->attrs())
for (auto & attr2 : *attr.value->attrs()) {
checkDerivation(
fmt("%s.%s.%s", name, attr_name, evaluator->symbols[attr2.name]),
*attr2.value, attr2.pos);
fmt("%s.%s.%s",
name,
attr_name,
evaluator->symbols[attr2.name]),
*attr2.value,
attr2.pos
);
}
};
}
}
@@ -676,10 +689,16 @@ struct CmdFlakeCheck : FlakeCommand
checkSystemName(attr_name, attr.pos);
if (checkSystemType(attr_name, attr.pos)) {
state->forceAttrs(*attr.value, attr.pos, "");
for (auto & attr2 : *attr.value->attrs())
for (auto & attr2 : *attr.value->attrs()) {
checkApp(
fmt("%s.%s.%s", name, attr_name, evaluator->symbols[attr2.name]),
*attr2.value, attr2.pos);
fmt("%s.%s.%s",
name,
attr_name,
evaluator->symbols[attr2.name]),
*attr2.value,
attr2.pos
);
}
};
}
}
@@ -692,8 +711,8 @@ struct CmdFlakeCheck : FlakeCommand
checkSystemName(attr_name, attr.pos);
if (checkSystemType(attr_name, attr.pos)) {
checkDerivation(
fmt("%s.%s", name, attr_name),
*attr.value, attr.pos);
fmt("%s.%s", name, attr_name), *attr.value, attr.pos
);
};
}
}
@@ -705,9 +724,7 @@ struct CmdFlakeCheck : FlakeCommand
const auto & attr_name = evaluator->symbols[attr.name];
checkSystemName(attr_name, attr.pos);
if (checkSystemType(attr_name, attr.pos) ) {
checkApp(
fmt("%s.%s", name, attr_name),
*attr.value, attr.pos);
checkApp(fmt("%s.%s", name, attr_name), *attr.value, attr.pos);
};
}
}
@@ -731,8 +748,11 @@ struct CmdFlakeCheck : FlakeCommand
{
state->forceAttrs(vOutput, pos, "");
for (auto & attr : *vOutput.attrs())
checkOverlay(fmt("%s.%s", name, evaluator->symbols[attr.name]),
*attr.value, attr.pos);
checkOverlay(
fmt("%s.%s", name, evaluator->symbols[attr.name]),
*attr.value,
attr.pos
);
}
else if (name == "nixosModule")
@@ -744,16 +764,22 @@ struct CmdFlakeCheck : FlakeCommand
{
state->forceAttrs(vOutput, pos, "");
for (auto & attr : *vOutput.attrs())
checkModule(fmt("%s.%s", name, evaluator->symbols[attr.name]),
*attr.value, attr.pos);
checkModule(
fmt("%s.%s", name, evaluator->symbols[attr.name]),
*attr.value,
attr.pos
);
}
else if (name == "nixosConfigurations")
{
state->forceAttrs(vOutput, pos, "");
for (auto & attr : *vOutput.attrs())
checkNixOSConfiguration(fmt("%s.%s", name, evaluator->symbols[attr.name]),
*attr.value, attr.pos);
checkNixOSConfiguration(
fmt("%s.%s", name, evaluator->symbols[attr.name]),
*attr.value,
attr.pos
);
}
else if (name == "hydraJobs")
@@ -770,8 +796,11 @@ struct CmdFlakeCheck : FlakeCommand
{
state->forceAttrs(vOutput, pos, "");
for (auto & attr : *vOutput.attrs())
checkTemplate(fmt("%s.%s", name, evaluator->symbols[attr.name]),
*attr.value, attr.pos);
checkTemplate(
fmt("%s.%s", name, evaluator->symbols[attr.name]),
*attr.value,
attr.pos
);
}
else if (name == "defaultBundler")
@@ -782,8 +811,8 @@ struct CmdFlakeCheck : FlakeCommand
checkSystemName(attr_name, attr.pos);
if (checkSystemType(attr_name, attr.pos)) {
checkBundler(
fmt("%s.%s", name, attr_name),
*attr.value, attr.pos);
fmt("%s.%s", name, attr_name), *attr.value, attr.pos
);
};
}
}
@@ -798,8 +827,13 @@ struct CmdFlakeCheck : FlakeCommand
state->forceAttrs(*attr.value, attr.pos, "");
for (auto & attr2 : *attr.value->attrs()) {
checkBundler(
fmt("%s.%s.%s", name, attr_name, evaluator->symbols[attr2.name]),
*attr2.value, attr2.pos);
fmt("%s.%s.%s",
name,
attr_name,
evaluator->symbols[attr2.name]),
*attr2.value,
attr2.pos
);
}
};
}
+8 -3
View File
@@ -377,7 +377,8 @@ static void showHelp(AsyncIoRoot & aio, std::vector<std::string> subcommand, Nix
if (!attr)
throw UsageError("`nix` has no subcommand '%s'", concatStringsSep("", subcommand));
auto markdown = state->forceString(*attr->value, noPos, "while evaluating the lowdown help text");
auto markdown =
state->forceString(*attr->value, noPos, "while evaluating the lowdown help text");
RunPager pager;
std::cout << renderMarkdownToTerminal(markdown) << "\n";
@@ -530,9 +531,13 @@ void mainWrapped(AsyncIoRoot & aio, int argc, char * * argv)
auto builtins = state.builtins.env.values[0]->attrs();
for (auto & builtin : *builtins) {
auto b = JSON::object();
if (!builtin.value->isPrimOp()) continue;
if (!builtin.value->isPrimOp()) {
continue;
}
auto primOp = builtin.value->primOp();
if (!primOp->doc) continue;
if (!primOp->doc) {
continue;
}
b["arity"] = primOp->arity;
b["args"] = primOp->args;
b["doc"] = trim(stripIndentation(primOp->doc));
+21 -6
View File
@@ -41,10 +41,13 @@ std::string resolveMirrorUrl(EvalState & state, const std::string & url)
}
state.forceList(*mirrorList->value, noPos, "while evaluating one mirror configuration");
if (mirrorList->value->listSize() < 1)
if (mirrorList->value->listSize() < 1) {
throw Error("mirror URL '%s' did not expand to anything", url);
}
std::string mirror(state.forceString(*mirrorList->value->listElems()[0], noPos, "while evaluating the first available mirror"));
std::string mirror(state.forceString(
*mirrorList->value->listElems()[0], noPos, "while evaluating the first available mirror"
));
return mirror + (mirror.ends_with("/") ? "" : "/") + s.substr(p + 1);
}
@@ -215,22 +218,34 @@ static int main_nix_prefetch_url(AsyncIoRoot & aio, std::string programName, Str
if (!attr)
throw Error("attribute 'urls' missing");
state->forceList(*attr->value, noPos, "while evaluating the urls to prefetch");
if (attr->value->listSize() < 1)
if (attr->value->listSize() < 1) {
throw Error("'urls' list is empty");
url = state->forceString(*attr->value->listElems()[0], noPos, "while evaluating the first url from the urls list");
}
url = state->forceString(
*attr->value->listElems()[0],
noPos,
"while evaluating the first url from the urls list"
);
/* Extract the hash mode. */
auto attr2 = v.attrs()->get(evaluator->symbols.create("outputHashMode"));
if (!attr2)
printInfo("warning: this does not look like a fetchurl call");
else
unpack = state->forceString(*attr2->value, noPos, "while evaluating the outputHashMode of the source to prefetch") == "recursive";
unpack = state->forceString(
*attr2->value,
noPos,
"while evaluating the outputHashMode of the source to prefetch"
)
== "recursive";
/* Extract the name. */
if (!name) {
auto attr3 = v.attrs()->get(evaluator->symbols.create("name"));
if (!attr3)
name = state->forceString(*attr3->value, noPos, "while evaluating the name of the source to prefetch");
name = state->forceString(
*attr3->value, noPos, "while evaluating the name of the source to prefetch"
);
}
}
+13 -14
View File
@@ -467,14 +467,14 @@ TEST_F(ValuePrintingTests, ansiColorsError)
auto & e = evaluator.parseExprFromString("{ a = throw \"uh oh!\"; }", {CanonPath::root});
state.eval(e, vError);
test(*vError.attrs()->begin()->value,
ANSI_RED
"«error: uh oh!»"
ANSI_NORMAL,
PrintOptions {
.ansiColors = true,
.force = true,
});
test(
*vError.attrs()->begin()->value,
ANSI_RED "«error: uh oh!»" ANSI_NORMAL,
PrintOptions{
.ansiColors = true,
.force = true,
}
);
}
TEST_F(ValuePrintingTests, ansiColorsDerivationError)
@@ -518,12 +518,11 @@ TEST_F(ValuePrintingTests, ansiColorsAssert)
state.eval(e, v);
ASSERT_EQ(v.type(), nAttrs);
test(*v.attrs()->begin()->value,
ANSI_RED "«error: assertion failed»" ANSI_NORMAL,
PrintOptions {
.ansiColors = true,
.force = true
});
test(
*v.attrs()->begin()->value,
ANSI_RED "«error: assertion failed»" ANSI_NORMAL,
PrintOptions{.ansiColors = true, .force = true}
);
}
TEST_F(ValuePrintingTests, ansiColorsList)