1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-25 06:31:14 +02:00

Don't allow __final in fetchTree

It's now only allowed in fetchFinalTree, which is not exposed to users
but only to call-flake.nix.
This commit is contained in:
Eelco Dolstra 2024-11-08 19:27:54 +01:00
parent d90b56d527
commit 4dceca51de
7 changed files with 55 additions and 9 deletions

View file

@ -10,6 +10,9 @@ lockFileStr:
# unlocked trees. # unlocked trees.
overrides: overrides:
# This is `prim_fetchFinalTree`.
fetchTreeFinal:
let let
lockFile = builtins.fromJSON lockFileStr; lockFile = builtins.fromJSON lockFileStr;
@ -45,7 +48,7 @@ let
else else
# FIXME: remove obsolete node.info. # FIXME: remove obsolete node.info.
# Note: lock file entries are always final. # Note: lock file entries are always final.
fetchTree (node.info or {} // removeAttrs node.locked ["dir"] // { __final = true; }); fetchTreeFinal (node.info or {} // removeAttrs node.locked ["dir"]);
subdir = overrides.${key}.dir or node.locked.dir or ""; subdir = overrides.${key}.dir or node.locked.dir or "";

View file

@ -510,9 +510,15 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
Value * v = allocValue(); Value * v = allocValue();
v->mkPrimOp(new PrimOp(primOp)); v->mkPrimOp(new PrimOp(primOp));
staticBaseEnv->vars.emplace_back(envName, baseEnvDispl);
baseEnv.values[baseEnvDispl++] = v; if (primOp.internal)
baseEnv.values[0]->payload.attrs->push_back(Attr(symbols.create(primOp.name), v)); internalPrimOps.emplace(primOp.name, v);
else {
staticBaseEnv->vars.emplace_back(envName, baseEnvDispl);
baseEnv.values[baseEnvDispl++] = v;
baseEnv.values[0]->payload.attrs->push_back(Attr(symbols.create(primOp.name), v));
}
return v; return v;
} }

View file

@ -107,6 +107,11 @@ struct PrimOp
*/ */
std::optional<ExperimentalFeature> experimentalFeature; std::optional<ExperimentalFeature> experimentalFeature;
/**
* If true, this primop is not exposed to the user.
*/
bool internal = false;
/** /**
* Validity check to be performed by functions that introduce primops, * Validity check to be performed by functions that introduce primops,
* such as RegisterPrimOp() and Value::mkPrimOp(). * such as RegisterPrimOp() and Value::mkPrimOp().
@ -591,6 +596,11 @@ public:
*/ */
std::shared_ptr<StaticEnv> staticBaseEnv; // !!! should be private std::shared_ptr<StaticEnv> staticBaseEnv; // !!! should be private
/**
* Internal primops not exposed to the user.
*/
std::unordered_map<std::string, Value *, std::hash<std::string>, std::equal_to<std::string>, traceable_allocator<std::pair<const std::string, Value *>>> internalPrimOps;
/** /**
* Name and documentation about every constant. * Name and documentation about every constant.
* *

View file

@ -78,6 +78,7 @@ struct FetchTreeParams {
bool emptyRevFallback = false; bool emptyRevFallback = false;
bool allowNameArgument = false; bool allowNameArgument = false;
bool isFetchGit = false; bool isFetchGit = false;
bool isFinal = false;
}; };
static void fetchTree( static void fetchTree(
@ -195,6 +196,13 @@ static void fetchTree(
state.checkURI(input.toURLString()); state.checkURI(input.toURLString());
if (params.isFinal) {
input.attrs.insert_or_assign("__final", Explicit<bool>(true));
} else {
if (input.isFinal())
throw Error("input '%s' is not allowed to use the '__final' attribute", input.to_string());
}
auto [storePath, input2] = input.fetchToStore(state.store); auto [storePath, input2] = input.fetchToStore(state.store);
state.allowPath(storePath); state.allowPath(storePath);
@ -431,6 +439,18 @@ static RegisterPrimOp primop_fetchTree({
.experimentalFeature = Xp::FetchTree, .experimentalFeature = Xp::FetchTree,
}); });
void prim_fetchFinalTree(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
fetchTree(state, pos, args, v, {.isFinal = true});
}
static RegisterPrimOp primop_fetchFinalTree({
.name = "fetchFinalTree",
.args = {"input"},
.fun = prim_fetchFinalTree,
.internal = true,
});
static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v, static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v,
const std::string & who, bool unpack, std::string name) const std::string & who, bool unpack, std::string name)
{ {

View file

@ -809,12 +809,14 @@ void callFlake(EvalState & state,
auto vCallFlake = state.allocValue(); auto vCallFlake = state.allocValue();
state.evalFile(state.callFlakeInternal, *vCallFlake); state.evalFile(state.callFlakeInternal, *vCallFlake);
auto vTmp1 = state.allocValue();
auto vLocks = state.allocValue(); auto vLocks = state.allocValue();
vLocks->mkString(lockFileStr); vLocks->mkString(lockFileStr);
state.callFunction(*vCallFlake, *vLocks, *vTmp1, noPos);
state.callFunction(*vTmp1, vOverrides, vRes, noPos); auto vFetchFinalTree = get(state.internalPrimOps, "fetchFinalTree");
assert(vFetchFinalTree);
Value * args[] = {vLocks, &vOverrides, *vFetchFinalTree};
state.callFunction(*vCallFlake, 3, args, vRes, noPos);
} }
void initLib(const Settings & settings) void initLib(const Settings & settings)

View file

@ -234,4 +234,11 @@ void emitTreeAttrs(
bool emptyRevFallback = false, bool emptyRevFallback = false,
bool forceDirty = false); bool forceDirty = false);
/**
* An internal builtin similar to `fetchTree`, except that it
* always treats the input as final (i.e. no attributes can be
* added/removed/changed).
*/
void prim_fetchFinalTree(EvalState & state, const PosIdx pos, Value * * args, Value & v);
} }

View file

@ -159,8 +159,6 @@ can occur in *locked* flake references and are available to Nix code:
for tarball flakes, it's the most recent timestamp of any file for tarball flakes, it's the most recent timestamp of any file
inside the tarball. inside the tarball.
Attributes that start with `__` are internal or experimental and may be removed in future versions.
## Types ## Types
Currently the `type` attribute can be one of the following: Currently the `type` attribute can be one of the following: