1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-29 21:50:58 +01:00

Merge remote-tracking branch 'origin/master' into lazy-trees

This commit is contained in:
Eelco Dolstra 2022-05-09 11:26:39 +02:00
commit 30ca717558
175 changed files with 4032 additions and 1936 deletions

View file

@ -72,7 +72,7 @@ static std::tuple<fetchers::Tree, FlakeRef, FlakeRef> fetchOrSubstituteTree(
return {std::move(tree), resolvedRef, lockedRef};
}
static void forceTrivialValue(EvalState & state, Value & value, const Pos & pos)
static void forceTrivialValue(EvalState & state, Value & value, const PosIdx pos)
{
if (value.isThunk() && value.isTrivial())
state.forceValue(value, pos);
@ -80,18 +80,18 @@ static void forceTrivialValue(EvalState & state, Value & value, const Pos & pos)
static void expectType(EvalState & state, ValueType type,
Value & value, const Pos & pos)
Value & value, const PosIdx pos)
{
forceTrivialValue(state, value, pos);
if (value.type() != type)
throw Error("expected %s but got %s at %s",
showType(type), showType(value.type()), pos);
showType(type), showType(value.type()), state.positions[pos]);
}
static std::map<FlakeId, FlakeInput> parseFlakeInputs(
EvalState & state,
Value * value,
const Pos & pos,
const PosIdx pos,
const std::optional<Path> & baseDir,
const InputPath & lockRootPath);
@ -99,7 +99,7 @@ static FlakeInput parseFlakeInput(
EvalState & state,
const std::string & inputName,
Value * value,
const Pos & pos,
const PosIdx pos,
const std::optional<Path> & baseDir,
const InputPath & lockRootPath)
{
@ -118,37 +118,39 @@ static FlakeInput parseFlakeInput(
for (nix::Attr attr : *(value->attrs)) {
try {
if (attr.name == sUrl) {
expectType(state, nString, *attr.value, *attr.pos);
expectType(state, nString, *attr.value, attr.pos);
url = attr.value->string.s;
attrs.emplace("url", *url);
} else if (attr.name == sFlake) {
expectType(state, nBool, *attr.value, *attr.pos);
expectType(state, nBool, *attr.value, attr.pos);
input.isFlake = attr.value->boolean;
} else if (attr.name == sInputs) {
input.overrides = parseFlakeInputs(state, attr.value, *attr.pos, baseDir, lockRootPath);
input.overrides = parseFlakeInputs(state, attr.value, attr.pos, baseDir, lockRootPath);
} else if (attr.name == sFollows) {
expectType(state, nString, *attr.value, *attr.pos);
expectType(state, nString, *attr.value, attr.pos);
auto follows(parseInputPath(attr.value->string.s));
follows.insert(follows.begin(), lockRootPath.begin(), lockRootPath.end());
input.follows = follows;
} else {
switch (attr.value->type()) {
case nString:
attrs.emplace(attr.name, attr.value->string.s);
attrs.emplace(state.symbols[attr.name], attr.value->string.s);
break;
case nBool:
attrs.emplace(attr.name, Explicit<bool> { attr.value->boolean });
attrs.emplace(state.symbols[attr.name], Explicit<bool> { attr.value->boolean });
break;
case nInt:
attrs.emplace(attr.name, (long unsigned int)attr.value->integer);
attrs.emplace(state.symbols[attr.name], (long unsigned int)attr.value->integer);
break;
default:
throw TypeError("flake input attribute '%s' is %s while a string, Boolean, or integer is expected",
attr.name, showType(*attr.value));
state.symbols[attr.name], showType(*attr.value));
}
}
} catch (Error & e) {
e.addTrace(*attr.pos, hintfmt("in flake attribute '%s'", attr.name));
e.addTrace(
state.positions[attr.pos],
hintfmt("in flake attribute '%s'", state.symbols[attr.name]));
throw;
}
}
@ -157,13 +159,13 @@ static FlakeInput parseFlakeInput(
try {
input.ref = FlakeRef::fromAttrs(attrs);
} catch (Error & e) {
e.addTrace(pos, hintfmt("in flake input"));
e.addTrace(state.positions[pos], hintfmt("in flake input"));
throw;
}
else {
attrs.erase("url");
if (!attrs.empty())
throw Error("unexpected flake input attribute '%s', at %s", attrs.begin()->first, pos);
throw Error("unexpected flake input attribute '%s', at %s", attrs.begin()->first, state.positions[pos]);
if (url)
input.ref = parseFlakeRef(*url, baseDir, true, input.isFlake);
}
@ -177,7 +179,7 @@ static FlakeInput parseFlakeInput(
static std::map<FlakeId, FlakeInput> parseFlakeInputs(
EvalState & state,
Value * value,
const Pos & pos,
const PosIdx pos,
const std::optional<Path> & baseDir,
const InputPath & lockRootPath)
{
@ -186,11 +188,11 @@ static std::map<FlakeId, FlakeInput> parseFlakeInputs(
expectType(state, nAttrs, *value, pos);
for (nix::Attr & inputAttr : *(*value).attrs) {
inputs.emplace(inputAttr.name,
inputs.emplace(state.symbols[inputAttr.name],
parseFlakeInput(state,
inputAttr.name,
state.symbols[inputAttr.name],
inputAttr.value,
*inputAttr.pos,
inputAttr.pos,
baseDir,
lockRootPath));
}
@ -213,37 +215,37 @@ static Flake readFlake(
Value vInfo;
state.evalFile(flakePath, vInfo, true);
expectType(state, nAttrs, vInfo, Pos(foFile, state.symbols.create(flakePath.to_string()), 0, 0));
expectType(state, nAttrs, vInfo, state.positions.add({flakePath.to_string(), foFile}, 0, 0));
Flake flake {
// FIXME
.originalRef = lockedRef,
.resolvedRef = lockedRef,
.lockedRef = lockedRef,
.accessor = ptr(&accessor),
.accessor = &accessor,
.flakePath = dirOf(flakePath.path),
};
if (auto description = vInfo.attrs->get(state.sDescription)) {
expectType(state, nString, *description->value, *description->pos);
expectType(state, nString, *description->value, description->pos);
flake.description = description->value->string.s;
}
auto sInputs = state.symbols.create("inputs");
if (auto inputs = vInfo.attrs->get(sInputs))
flake.inputs = parseFlakeInputs(state, inputs->value, *inputs->pos, flakeDir, lockRootPath);
flake.inputs = parseFlakeInputs(state, inputs->value, inputs->pos, flakeDir, lockRootPath);
auto sOutputs = state.symbols.create("outputs");
if (auto outputs = vInfo.attrs->get(sOutputs)) {
expectType(state, nFunction, *outputs->value, *outputs->pos);
expectType(state, nFunction, *outputs->value, outputs->pos);
if (outputs->value->isLambda() && outputs->value->lambda.fun->hasFormals()) {
for (auto & formal : outputs->value->lambda.fun->formals->formals) {
if (formal.name != state.sSelf)
flake.inputs.emplace(formal.name, FlakeInput {
.ref = parseFlakeRef(formal.name)
flake.inputs.emplace(state.symbols[formal.name], FlakeInput {
.ref = parseFlakeRef(state.symbols[formal.name])
});
}
}
@ -254,35 +256,41 @@ static Flake readFlake(
auto sNixConfig = state.symbols.create("nixConfig");
if (auto nixConfig = vInfo.attrs->get(sNixConfig)) {
expectType(state, nAttrs, *nixConfig->value, *nixConfig->pos);
expectType(state, nAttrs, *nixConfig->value, nixConfig->pos);
for (auto & setting : *nixConfig->value->attrs) {
forceTrivialValue(state, *setting.value, *setting.pos);
forceTrivialValue(state, *setting.value, setting.pos);
if (setting.value->type() == nString)
flake.config.settings.insert({setting.name, std::string(state.forceStringNoCtx(*setting.value, *setting.pos))});
flake.config.settings.emplace(
state.symbols[setting.name],
std::string(state.forceStringNoCtx(*setting.value, setting.pos)));
else if (setting.value->type() == nPath) {
PathSet emptyContext = {};
flake.config.settings.emplace(
setting.name,
state.coerceToString(*setting.pos, *setting.value, emptyContext, false, true, true) .toOwned());
state.symbols[setting.name],
state.coerceToString(setting.pos, *setting.value, emptyContext, false, true, true) .toOwned());
}
else if (setting.value->type() == nInt)
flake.config.settings.insert({setting.name, state.forceInt(*setting.value, *setting.pos)});
flake.config.settings.emplace(
state.symbols[setting.name],
state.forceInt(*setting.value, setting.pos));
else if (setting.value->type() == nBool)
flake.config.settings.insert({setting.name, Explicit<bool> { state.forceBool(*setting.value, *setting.pos) }});
flake.config.settings.emplace(
state.symbols[setting.name],
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)
throw TypeError("list element in flake configuration setting '%s' is %s while a string is expected",
setting.name, showType(*setting.value));
ss.emplace_back(state.forceStringNoCtx(*elem, *setting.pos));
state.symbols[setting.name], showType(*setting.value));
ss.emplace_back(state.forceStringNoCtx(*elem, setting.pos));
}
flake.config.settings.insert({setting.name, ss});
flake.config.settings.emplace(state.symbols[setting.name], ss);
}
else
throw TypeError("flake configuration setting '%s' is %s",
setting.name, showType(*setting.value));
state.symbols[setting.name], showType(*setting.value));
}
}
@ -292,7 +300,7 @@ static Flake readFlake(
attr.name != sOutputs &&
attr.name != sNixConfig)
throw Error("flake '%s' has an unsupported attribute '%s', at %s",
lockedRef, attr.name, *attr.pos);
lockedRef, state.symbols[attr.name], state.positions[attr.pos]);
}
return flake;
@ -723,12 +731,12 @@ void callFlake(EvalState & state,
state.callFunction(*vTmp2, *vRootSubdir, vRes, noPos);
}
static void prim_getFlake(EvalState & state, const Pos & pos, Value * * args, Value & v)
static void prim_getFlake(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
std::string flakeRefS(state.forceStringNoCtx(*args[0], pos));
auto flakeRef = parseFlakeRef(flakeRefS, {}, true);
if (evalSettings.pureEval && !flakeRef.input.isLocked())
throw Error("cannot call 'getFlake' on unlocked flake reference '%s', at %s (use --impure to override)", flakeRefS, pos);
throw Error("cannot call 'getFlake' on unlocked flake reference '%s', at %s (use --impure to override)", flakeRefS, state.positions[pos]);
callFlake(state,
lockFlake(state, flakeRef,