aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/primops/fetchTree.cc
diff options
context:
space:
mode:
authorRobert Hensing <robert@roberthensing.nl>2022-02-27 15:25:22 +0100
committerRobert Hensing <robert@roberthensing.nl>2022-02-28 21:37:49 +0100
commit158280d8e9b9d7fbf1ccee9cef829081859810e6 (patch)
tree5ca43557e36b46a2c595d26a9e059fd84a5bbb45 /src/libexpr/primops/fetchTree.cc
parent1c985428c4783568bcfb4692c6ce816eb5c5c31d (diff)
fetchTree: Do not re-fetch paths already present
Diffstat (limited to 'src/libexpr/primops/fetchTree.cc')
-rw-r--r--src/libexpr/primops/fetchTree.cc28
1 files changed, 24 insertions, 4 deletions
diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc
index f3e3e70d8..ea416d2d9 100644
--- a/src/libexpr/primops/fetchTree.cc
+++ b/src/libexpr/primops/fetchTree.cc
@@ -185,6 +185,13 @@ static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, V
// FIXME: document
static RegisterPrimOp primop_fetchTree("fetchTree", 1, prim_fetchTree);
+static void setStorePath(EvalState &state, const StorePath &storePath, Value &v) {
+ state.allowPath(storePath);
+
+ auto path = state.store->printStorePath(storePath);
+ v.mkString(path, PathSet({path}));
+}
+
static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
const std::string & who, bool unpack, std::string name)
{
@@ -203,6 +210,8 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
url = state.forceStringNoCtx(*attr.value, *attr.pos);
else if (n == "sha256")
expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256);
+ else if (n == "narHash")
+ expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256);
else if (n == "name")
name = state.forceStringNoCtx(*attr.value, *attr.pos);
else
@@ -230,6 +239,20 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
if (evalSettings.pureEval && !expectedHash)
throw Error("in pure evaluation mode, '%s' requires a 'sha256' argument", who);
+ // early exit if pinned and already in the store
+ if (expectedHash && expectedHash->type == htSHA256) {
+ auto expectedPath =
+ unpack
+ ? state.store->makeFixedOutputPath(FileIngestionMethod::Recursive, *expectedHash, name, {})
+ : state.store->makeFixedOutputPath(FileIngestionMethod::Flat, *expectedHash, name, {});
+
+ auto validPaths = state.store->queryValidPaths({expectedPath}, NoSubstitute);
+ if (!validPaths.empty()) {
+ setStorePath(state, expectedPath, v);
+ return;
+ }
+ }
+
auto storePath =
unpack
? fetchers::downloadTarball(state.store, *url, name, (bool) expectedHash).first.storePath
@@ -244,10 +267,7 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
*url, expectedHash->to_string(Base32, true), hash.to_string(Base32, true));
}
- state.allowPath(storePath);
-
- auto path = state.store->printStorePath(storePath);
- v.mkString(path, PathSet({path}));
+ setStorePath(state, storePath, v);
}
static void prim_fetchurl(EvalState & state, const Pos & pos, Value * * args, Value & v)