aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/primops/fetchTree.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr/primops/fetchTree.cc')
-rw-r--r--src/libexpr/primops/fetchTree.cc69
1 files changed, 49 insertions, 20 deletions
diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc
index f9dfb1164..a1ad0a7b9 100644
--- a/src/libexpr/primops/fetchTree.cc
+++ b/src/libexpr/primops/fetchTree.cc
@@ -13,31 +13,36 @@ namespace nix {
void emitTreeAttrs(
EvalState & state,
const fetchers::Tree & tree,
- std::shared_ptr<const fetchers::Input> input,
+ const fetchers::Input & input,
Value & v)
{
+ assert(input.isImmutable());
+
state.mkAttrs(v, 8);
auto storePath = state.store->printStorePath(tree.storePath);
mkString(*state.allocAttr(v, state.sOutPath), storePath, PathSet({storePath}));
- assert(tree.info.narHash);
+ // FIXME: support arbitrary input attributes.
+
+ auto narHash = input.getNarHash();
+ assert(narHash);
mkString(*state.allocAttr(v, state.symbols.create("narHash")),
- tree.info.narHash.to_string(SRI));
+ narHash->to_string(SRI));
- if (input->getRev()) {
- mkString(*state.allocAttr(v, state.symbols.create("rev")), input->getRev()->gitRev());
- mkString(*state.allocAttr(v, state.symbols.create("shortRev")), input->getRev()->gitShortRev());
+ if (auto rev = input.getRev()) {
+ mkString(*state.allocAttr(v, state.symbols.create("rev")), rev->gitRev());
+ mkString(*state.allocAttr(v, state.symbols.create("shortRev")), rev->gitShortRev());
}
- if (tree.info.revCount)
- mkInt(*state.allocAttr(v, state.symbols.create("revCount")), *tree.info.revCount);
+ if (auto revCount = input.getRevCount())
+ mkInt(*state.allocAttr(v, state.symbols.create("revCount")), *revCount);
- if (tree.info.lastModified) {
- mkInt(*state.allocAttr(v, state.symbols.create("lastModified")), *tree.info.lastModified);
+ if (auto lastModified = input.getLastModified()) {
+ mkInt(*state.allocAttr(v, state.symbols.create("lastModified")), *lastModified);
mkString(*state.allocAttr(v, state.symbols.create("lastModifiedDate")),
- fmt("%s", std::put_time(std::gmtime(&*tree.info.lastModified), "%Y%m%d%H%M%S")));
+ fmt("%s", std::put_time(std::gmtime(&*lastModified), "%Y%m%d%H%M%S")));
}
v.attrs->sort();
@@ -47,7 +52,7 @@ static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, V
{
settings.requireExperimentalFeature("flakes");
- std::shared_ptr<const fetchers::Input> input;
+ fetchers::Input input;
PathSet context;
state.forceValue(*args[0]);
@@ -62,7 +67,7 @@ static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, V
if (attr.value->type == tString)
attrs.emplace(attr.name, attr.value->string.s);
else if (attr.value->type == tBool)
- attrs.emplace(attr.name, attr.value->boolean);
+ attrs.emplace(attr.name, fetchers::Explicit<bool>{attr.value->boolean});
else if (attr.value->type == tInt)
attrs.emplace(attr.name, attr.value->integer);
else
@@ -73,18 +78,42 @@ static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, V
if (!attrs.count("type"))
throw Error("attribute 'type' is missing in call to 'fetchTree', at %s", pos);
- input = fetchers::inputFromAttrs(attrs);
+ input = fetchers::Input::fromAttrs(std::move(attrs));
} else
- input = fetchers::inputFromURL(state.coerceToString(pos, *args[0], context, false, false));
+ input = fetchers::Input::fromURL(state.coerceToString(pos, *args[0], context, false, false));
- if (!evalSettings.pureEval && !input->isDirect())
+ if (!evalSettings.pureEval && !input.isDirect())
input = lookupInRegistries(state.store, input).first;
- if (evalSettings.pureEval && !input->isImmutable())
+ if (evalSettings.pureEval && !input.isImmutable())
throw Error("in pure evaluation mode, 'fetchTree' requires an immutable input, at %s", pos);
- // FIXME: use fetchOrSubstituteTree
- auto [tree, input2] = input->fetchTree(state.store);
+ /* The tree may already be in the Nix store, or it could be
+ substituted (which is often faster than fetching from the
+ original source). So check that. */
+ if (input.hasAllInfo()) {
+ auto storePath = input.computeStorePath(*state.store);
+
+ try {
+ state.store->ensurePath(storePath);
+
+ debug("using substituted/cached input '%s' in '%s'",
+ input.to_string(), state.store->printStorePath(storePath));
+
+ auto actualPath = state.store->toRealPath(storePath);
+
+ if (state.allowedPaths)
+ state.allowedPaths->insert(actualPath);
+
+ emitTreeAttrs(state, fetchers::Tree { .actualPath = actualPath, .storePath = std::move(storePath) }, input, v);
+
+ return;
+ } catch (Error & e) {
+ debug("substitution of input '%s' failed: %s", input.to_string(), e.what());
+ }
+ }
+
+ auto [tree, input2] = input.fetch(state.store);
if (state.allowedPaths)
state.allowedPaths->insert(tree.actualPath);
@@ -137,7 +166,7 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
auto storePath =
unpack
- ? fetchers::downloadTarball(state.store, *url, name, (bool) expectedHash).storePath
+ ? fetchers::downloadTarball(state.store, *url, name, (bool) expectedHash).first.storePath
: fetchers::downloadFile(state.store, *url, name, (bool) expectedHash).storePath;
auto path = state.store->toRealPath(storePath);