From f4bafc412fac79ce07c89f8d3ab9bd1c32f7b9cd Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 21 Mar 2022 11:31:01 +0100 Subject: [PATCH] Add builtins.fetchClosure This allows closures to be imported at evaluation time, without requiring the user to configure substituters. E.g. builtins.fetchClosure { storePath = /nix/store/f89g6yi63m1ywfxj96whv5sxsm74w5ka-python3.9-sqlparse-0.4.2; from = "https://cache.ngi0.nixos.org"; } --- src/libexpr/primops/fetchClosure.cc | 62 +++++++++++++++++++++++++++++ src/libexpr/primops/fetchTree.cc | 4 +- 2 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 src/libexpr/primops/fetchClosure.cc diff --git a/src/libexpr/primops/fetchClosure.cc b/src/libexpr/primops/fetchClosure.cc new file mode 100644 index 000000000..4bcc716db --- /dev/null +++ b/src/libexpr/primops/fetchClosure.cc @@ -0,0 +1,62 @@ +#include "primops.hh" +#include "store-api.hh" + +namespace nix { + +static void prim_fetchClosure(EvalState & state, const Pos & pos, Value * * args, Value & v) +{ + state.forceAttrs(*args[0], pos); + + std::optional storePath; + std::optional from; + + for (auto & attr : *args[0]->attrs) { + if (attr.name == "storePath") { + PathSet context; + storePath = state.coerceToStorePath(*attr.pos, *attr.value, context); + } + + else if (attr.name == "from") + from = state.forceStringNoCtx(*attr.value, *attr.pos); + + else + throw Error({ + .msg = hintfmt("attribute '%s' isn't supported in call to 'fetchClosure'", attr.name), + .errPos = pos + }); + } + + if (!storePath) + throw Error({ + .msg = hintfmt("attribute '%s' is missing in call to 'fetchClosure'", "storePath"), + .errPos = pos + }); + + if (!from) + throw Error({ + .msg = hintfmt("attribute '%s' is missing in call to 'fetchClosure'", "from"), + .errPos = pos + }); + + // FIXME: only allow some "trusted" store types (like BinaryCacheStore). + auto srcStore = openStore(*from); + + copyClosure(*srcStore, *state.store, RealisedPath::Set { *storePath }); + + auto storePathS = state.store->printStorePath(*storePath); + + v.mkString(storePathS, {storePathS}); + + // FIXME: in pure mode, require a CA path or a NAR hash of the + // top-level path. +} + +static RegisterPrimOp primop_fetchClosure({ + .name = "__fetchClosure", + .args = {"args"}, + .doc = R"( + )", + .fun = prim_fetchClosure, +}); + +} diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index 9c2da2178..42c98e312 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -145,7 +145,7 @@ static void fetchTree( if (!params.allowNameArgument) if (auto nameIter = attrs.find("name"); nameIter != attrs.end()) throw Error({ - .msg = hintfmt("attribute 'name' isn’t supported in call to 'fetchTree'"), + .msg = hintfmt("attribute 'name' isn't supported in call to 'fetchTree'"), .errPos = pos }); @@ -329,7 +329,7 @@ static RegisterPrimOp primop_fetchTarball({ .fun = prim_fetchTarball, }); -static void prim_fetchGit(EvalState &state, const Pos &pos, Value **args, Value &v) +static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Value & v) { fetchTree(state, pos, args, v, "git", FetchTreeParams { .emptyRevFallback = true, .allowNameArgument = true }); }