Compare commits
3 Commits
relative-p
...
getflake-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
490cb842cc | ||
|
|
6992698ac5 | ||
|
|
9868310d6f |
6
doc/manual/rl-next/getflake-path.md
Normal file
6
doc/manual/rl-next/getflake-path.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
synopsis: "`builtins.getFlake` now supports path values"
|
||||
prs: [15290]
|
||||
---
|
||||
|
||||
`builtins.getFlake` now accepts path values in addition to flakerefs, allowing you to write `builtins.getFlake ./subflake` instead of having to use ugly workarounds to construct a pure flakeref.
|
||||
@@ -35,35 +35,39 @@ namespace nix::flake::primops {
|
||||
PrimOp getFlake(const Settings & settings)
|
||||
{
|
||||
auto prim_getFlake = [&settings](EvalState & state, const PosIdx pos, Value ** args, Value & v) {
|
||||
std::string flakeRefS(
|
||||
state.forceStringNoCtx(*args[0], pos, "while evaluating the argument passed to builtins.getFlake"));
|
||||
auto flakeRef = nix::parseFlakeRef(state.fetchSettings, flakeRefS, {}, true);
|
||||
if (state.settings.pureEval && !flakeRef.input.isLocked(state.fetchSettings))
|
||||
throw Error(
|
||||
"cannot call 'getFlake' on unlocked flake reference '%s', at %s (use --impure to override)",
|
||||
flakeRefS,
|
||||
state.positions[pos]);
|
||||
state.forceValue(*args[0], pos);
|
||||
|
||||
callFlake(
|
||||
state,
|
||||
lockFlake(
|
||||
settings,
|
||||
state,
|
||||
flakeRef,
|
||||
LockFlags{
|
||||
.updateLockFile = false,
|
||||
.writeLockFile = false,
|
||||
.useRegistries = !state.settings.pureEval && settings.useRegistries,
|
||||
.allowUnlocked = !state.settings.pureEval,
|
||||
}),
|
||||
v);
|
||||
LockFlags lockFlags{
|
||||
.updateLockFile = false,
|
||||
.writeLockFile = false,
|
||||
.useRegistries = !state.settings.pureEval && settings.useRegistries,
|
||||
.allowUnlocked = !state.settings.pureEval,
|
||||
};
|
||||
|
||||
if (args[0]->type() == nPath) {
|
||||
auto path = state.realisePath(pos, *args[0]);
|
||||
callFlake(state, lockFlake(settings, state, path, lockFlags), v);
|
||||
} else {
|
||||
NixStringContext context;
|
||||
std::string flakeRefS(
|
||||
state.forceStringNoCtx(*args[0], pos, "while evaluating the argument passed to builtins.getFlake"));
|
||||
|
||||
auto flakeRef = nix::parseFlakeRef(state.fetchSettings, flakeRefS, {}, true);
|
||||
if (state.settings.pureEval && !flakeRef.input.isLocked(state.fetchSettings))
|
||||
throw Error(
|
||||
"cannot call 'getFlake' on unlocked flake reference '%s', at %s (use --impure to override)",
|
||||
flakeRefS,
|
||||
state.positions[pos]);
|
||||
|
||||
callFlake(state, lockFlake(settings, state, flakeRef, lockFlags), v);
|
||||
}
|
||||
};
|
||||
|
||||
return PrimOp{
|
||||
.name = "__getFlake",
|
||||
.args = {"args"},
|
||||
.doc = R"(
|
||||
Fetch a flake from a flake reference, and return its output attributes and some metadata. For example:
|
||||
Fetch a flake from a flake reference or a path, and return its output attributes and some metadata. For example:
|
||||
|
||||
```nix
|
||||
(builtins.getFlake "nix/55bc52401966fbffa525c574c14f67b00bc4fb3a").packages.x86_64-linux.nix
|
||||
|
||||
@@ -416,10 +416,8 @@ static LockFile readLockFile(const fetchers::Settings & fetchSettings, const Sou
|
||||
: LockFile();
|
||||
}
|
||||
|
||||
/* Compute an in-memory lock file for the specified top-level flake,
|
||||
and optionally write it to file, if the flake is writable. */
|
||||
LockedFlake
|
||||
lockFlake(const Settings & settings, EvalState & state, const FlakeRef & topRef, const LockFlags & lockFlags)
|
||||
LockedFlake lockFlake(
|
||||
const Settings & settings, EvalState & state, const FlakeRef & topRef, const LockFlags & lockFlags, Flake flake)
|
||||
{
|
||||
experimentalFeatureSettings.require(Xp::Flakes);
|
||||
|
||||
@@ -427,8 +425,6 @@ lockFlake(const Settings & settings, EvalState & state, const FlakeRef & topRef,
|
||||
auto useRegistriesTop = useRegistries ? fetchers::UseRegistries::All : fetchers::UseRegistries::No;
|
||||
auto useRegistriesInputs = useRegistries ? fetchers::UseRegistries::Limited : fetchers::UseRegistries::No;
|
||||
|
||||
auto flake = getFlake(state, topRef, useRegistriesTop, {});
|
||||
|
||||
if (lockFlags.applyNixConfig) {
|
||||
flake.config.apply(settings);
|
||||
state.store->setOptions();
|
||||
@@ -908,6 +904,22 @@ lockFlake(const Settings & settings, EvalState & state, const FlakeRef & topRef,
|
||||
}
|
||||
}
|
||||
|
||||
LockedFlake
|
||||
lockFlake(const Settings & settings, EvalState & state, const FlakeRef & topRef, const LockFlags & lockFlags)
|
||||
{
|
||||
auto useRegistries = lockFlags.useRegistries.value_or(settings.useRegistries);
|
||||
auto useRegistriesTop = useRegistries ? fetchers::UseRegistries::All : fetchers::UseRegistries::No;
|
||||
return lockFlake(settings, state, topRef, lockFlags, getFlake(state, topRef, useRegistriesTop, {}));
|
||||
}
|
||||
|
||||
LockedFlake
|
||||
lockFlake(const Settings & settings, EvalState & state, const SourcePath & flakeDir, const LockFlags & lockFlags)
|
||||
{
|
||||
/* We need a fake flakeref to put in the `Flake` struct, but it's not used for anything. */
|
||||
auto fakeRef = parseFlakeRef(state.fetchSettings, "flake:get-flake");
|
||||
return lockFlake(settings, state, fakeRef, lockFlags, readFlake(state, fakeRef, fakeRef, fakeRef, flakeDir, {}));
|
||||
}
|
||||
|
||||
static ref<SourceAccessor> makeInternalFS()
|
||||
{
|
||||
auto internalFS = make_ref<MemorySourceAccessor>(MemorySourceAccessor{});
|
||||
|
||||
@@ -214,9 +214,16 @@ struct LockFlags
|
||||
std::set<NonEmptyInputAttrPath> inputUpdates;
|
||||
};
|
||||
|
||||
/*
|
||||
* Compute an in-memory lock file for the specified top-level flake, and optionally write it to file, if the flake is
|
||||
* writable.
|
||||
*/
|
||||
LockedFlake
|
||||
lockFlake(const Settings & settings, EvalState & state, const FlakeRef & flakeRef, const LockFlags & lockFlags);
|
||||
|
||||
LockedFlake
|
||||
lockFlake(const Settings & settings, EvalState & state, const SourcePath & flakeDir, const LockFlags & lockFlags);
|
||||
|
||||
void callFlake(EvalState & state, const LockedFlake & lockedFlake, Value & v);
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,6 +32,8 @@ writeSimpleFlake() {
|
||||
baseName = builtins.baseNameOf ./.;
|
||||
|
||||
root = ./.;
|
||||
|
||||
number = 123;
|
||||
};
|
||||
}
|
||||
EOF
|
||||
|
||||
26
tests/functional/flakes/get-flake.sh
Normal file
26
tests/functional/flakes/get-flake.sh
Normal file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
source ./common.sh
|
||||
|
||||
createFlake1
|
||||
|
||||
mkdir -p "$flake1Dir/subflake"
|
||||
cat > "$flake1Dir/subflake/flake.nix" <<EOF
|
||||
{
|
||||
outputs = { self }:
|
||||
let
|
||||
# Bad, legacy way of getting a flake from an input.
|
||||
parentFlake = builtins.getFlake (builtins.flakeRefToString { type = "path"; path = self.sourceInfo.outPath; narHash = self.narHash; });
|
||||
# Better way using a path value.
|
||||
parentFlake2 = builtins.getFlake ./..;
|
||||
in {
|
||||
x = parentFlake.number;
|
||||
y = parentFlake2.number;
|
||||
};
|
||||
}
|
||||
EOF
|
||||
git -C "$flake1Dir" add subflake/flake.nix
|
||||
|
||||
[[ $(nix eval "$flake1Dir/subflake#x") = 123 ]]
|
||||
|
||||
[[ $(nix eval "$flake1Dir/subflake#y") = 123 ]]
|
||||
@@ -34,6 +34,7 @@ suites += {
|
||||
'source-paths.sh',
|
||||
'old-lockfiles.sh',
|
||||
'trace-ifd.sh',
|
||||
'get-flake.sh',
|
||||
],
|
||||
'workdir' : meson.current_source_dir(),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user