aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2022-03-25 14:04:18 +0100
committerEelco Dolstra <edolstra@gmail.com>2022-03-25 14:04:18 +0100
commit86b05ccd54f2e98ac2b5cef3bcecb29ed6ec4fd8 (patch)
tree1bfdc7d899ca7fd8adde25fc30202d3cdb2f8d20
parent55bc52401966fbffa525c574c14f67b00bc4fb3a (diff)
Only provide builtin.{getFlake,fetchClosure} is the corresponding experimental feature is enabled
This allows writing fallback code like if builtins ? fetchClosure then builtins.fetchClose { ... } else builtins.storePath ...
-rw-r--r--doc/manual/src/release-notes/rl-next.md9
-rw-r--r--src/libexpr/eval.cc17
-rw-r--r--src/libexpr/eval.hh6
-rw-r--r--src/libexpr/flake/flake.cc9
-rw-r--r--src/libexpr/primops.cc20
-rw-r--r--src/libexpr/primops.hh2
-rw-r--r--src/libexpr/primops/fetchClosure.cc6
-rw-r--r--src/nix/main.cc1
8 files changed, 31 insertions, 39 deletions
diff --git a/doc/manual/src/release-notes/rl-next.md b/doc/manual/src/release-notes/rl-next.md
index 33eaa8a2c..2ec864ee4 100644
--- a/doc/manual/src/release-notes/rl-next.md
+++ b/doc/manual/src/release-notes/rl-next.md
@@ -5,9 +5,12 @@
* `nix store make-content-addressable` has been renamed to `nix store
make-content-addressed`.
-* New builtin function `builtins.fetchClosure` that copies a closure
- from a binary cache at evaluation time and rewrites it to
- content-addressed form (if it isn't already). Like
+* New experimental builtin function `builtins.fetchClosure` that
+ copies a closure from a binary cache at evaluation time and rewrites
+ it to content-addressed form (if it isn't already). Like
`builtins.storePath`, this allows importing pre-built store paths;
the difference is that it doesn't require the user to configure
binary caches and trusted public keys.
+
+ This function is only available if you enable the experimental
+ feature `fetch-closure`.
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 3ec5ed202..437c7fc53 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -507,23 +507,6 @@ EvalState::~EvalState()
}
-void EvalState::requireExperimentalFeatureOnEvaluation(
- const ExperimentalFeature & feature,
- const std::string_view fName,
- const Pos & pos)
-{
- if (!settings.isExperimentalFeatureEnabled(feature)) {
- throw EvalError({
- .msg = hintfmt(
- "Cannot call '%2%' because experimental Nix feature '%1%' is disabled. You can enable it via '--extra-experimental-features %1%'.",
- feature,
- fName
- ),
- .errPos = pos
- });
- }
-}
-
void EvalState::allowPath(const Path & path)
{
if (allowedPaths)
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 198a62ad2..ab46b448c 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -149,12 +149,6 @@ public:
std::shared_ptr<Store> buildStore = nullptr);
~EvalState();
- void requireExperimentalFeatureOnEvaluation(
- const ExperimentalFeature &,
- const std::string_view fName,
- const Pos & pos
- );
-
void addToSearchPath(const std::string & s);
SearchPath getSearchPath() { return searchPath; }
diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc
index 6a1aca40d..fdcfb18d7 100644
--- a/src/libexpr/flake/flake.cc
+++ b/src/libexpr/flake/flake.cc
@@ -706,8 +706,6 @@ void callFlake(EvalState & state,
static void prim_getFlake(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
- state.requireExperimentalFeatureOnEvaluation(Xp::Flakes, "builtins.getFlake", pos);
-
std::string flakeRefS(state.forceStringNoCtx(*args[0], pos));
auto flakeRef = parseFlakeRef(flakeRefS, {}, true);
if (evalSettings.pureEval && !flakeRef.input.isLocked())
@@ -723,7 +721,12 @@ static void prim_getFlake(EvalState & state, const Pos & pos, Value * * args, Va
v);
}
-static RegisterPrimOp r2("__getFlake", 1, prim_getFlake);
+static RegisterPrimOp r2({
+ .name = "__getFlake",
+ .args = {"args"},
+ .fun = prim_getFlake,
+ .experimentalFeature = Xp::Flakes,
+});
}
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index f5d9aa9ae..f3eb5e925 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -3814,7 +3814,7 @@ RegisterPrimOp::RegisterPrimOp(std::string name, size_t arity, PrimOpFun fun)
.name = name,
.args = {},
.arity = arity,
- .fun = fun
+ .fun = fun,
});
}
@@ -3886,13 +3886,17 @@ void EvalState::createBaseEnv()
if (RegisterPrimOp::primOps)
for (auto & primOp : *RegisterPrimOp::primOps)
- addPrimOp({
- .fun = primOp.fun,
- .arity = std::max(primOp.args.size(), primOp.arity),
- .name = symbols.create(primOp.name),
- .args = primOp.args,
- .doc = primOp.doc,
- });
+ if (!primOp.experimentalFeature
+ || settings.isExperimentalFeatureEnabled(*primOp.experimentalFeature))
+ {
+ addPrimOp({
+ .fun = primOp.fun,
+ .arity = std::max(primOp.args.size(), primOp.arity),
+ .name = symbols.create(primOp.name),
+ .args = primOp.args,
+ .doc = primOp.doc,
+ });
+ }
/* Add a wrapper around the derivation primop that computes the
`drvPath' and `outPath' attributes lazily. */
diff --git a/src/libexpr/primops.hh b/src/libexpr/primops.hh
index 5b16e075f..905bd0366 100644
--- a/src/libexpr/primops.hh
+++ b/src/libexpr/primops.hh
@@ -16,6 +16,7 @@ struct RegisterPrimOp
size_t arity = 0;
const char * doc;
PrimOpFun fun;
+ std::optional<ExperimentalFeature> experimentalFeature;
};
typedef std::vector<Info> PrimOps;
@@ -35,6 +36,7 @@ struct RegisterPrimOp
/* These primops are disabled without enableNativeCode, but plugins
may wish to use them in limited contexts without globally enabling
them. */
+
/* Load a ValueInitializer from a DSO and return whatever it initializes */
void prim_importNative(EvalState & state, const Pos & pos, Value * * args, Value & v);
diff --git a/src/libexpr/primops/fetchClosure.cc b/src/libexpr/primops/fetchClosure.cc
index 47f40ef33..efeb93daf 100644
--- a/src/libexpr/primops/fetchClosure.cc
+++ b/src/libexpr/primops/fetchClosure.cc
@@ -7,8 +7,6 @@ namespace nix {
static void prim_fetchClosure(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
- settings.requireExperimentalFeature(Xp::FetchClosure);
-
state.forceAttrs(*args[0], pos);
std::optional<std::string> fromStoreUrl;
@@ -145,8 +143,12 @@ static RegisterPrimOp primop_fetchClosure({
specifying a binary cache from which the path can be fetched.
Also, requiring a content-addressed final store path avoids the
need for users to configure binary cache public keys.
+
+ This function is only available if you enable the experimental
+ feature `fetch-closure`.
)",
.fun = prim_fetchClosure,
+ .experimentalFeature = Xp::FetchClosure,
});
}
diff --git a/src/nix/main.cc b/src/nix/main.cc
index 9bc6c15fa..6198681e7 100644
--- a/src/nix/main.cc
+++ b/src/nix/main.cc
@@ -289,6 +289,7 @@ void mainWrapped(int argc, char * * argv)
}
if (argc == 2 && std::string(argv[1]) == "__dump-builtins") {
+ settings.experimentalFeatures = {Xp::Flakes, Xp::FetchClosure};
evalSettings.pureEval = false;
EvalState state({}, openStore("dummy://"));
auto res = nlohmann::json::object();