diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index d87d7b9b1..6db9bf9a1 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -443,10 +443,10 @@ ref openEvalCache( EvalState & state, std::shared_ptr lockedFlake) { - auto fingerprint = lockedFlake->getFingerprint(); + auto fingerprint = lockedFlake->getFingerprint(state.store); return make_ref( evalSettings.useEvalCache && evalSettings.pureEval - ? std::optional { std::cref(fingerprint) } + ? fingerprint : std::nullopt, state, [&state, lockedFlake]() diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc index fd9341504..4a69bb381 100644 --- a/src/libexpr/flake/flake.cc +++ b/src/libexpr/flake/flake.cc @@ -926,18 +926,17 @@ static RegisterPrimOp r4({ } -Fingerprint LockedFlake::getFingerprint() const +std::optional LockedFlake::getFingerprint(ref store) const { + if (lockFile.isUnlocked()) return std::nullopt; + + auto fingerprint = flake.lockedRef.input.getFingerprint(store); + if (!fingerprint) return std::nullopt; + // FIXME: as an optimization, if the flake contains a lock file // and we haven't changed it, then it's sufficient to use // flake.sourceInfo.storePath for the fingerprint. - return hashString(HashAlgorithm::SHA256, - fmt("%s;%s;%d;%d;%s", - flake.path.to_string(), - flake.lockedRef.subdir, - flake.lockedRef.input.getRevCount().value_or(0), - flake.lockedRef.input.getLastModified().value_or(0), - lockFile)); + return hashString(HashAlgorithm::SHA256, fmt("%s;%s;%s", *fingerprint, flake.lockedRef.subdir, lockFile)); } Flake::~Flake() { } diff --git a/src/libexpr/flake/flake.hh b/src/libexpr/flake/flake.hh index 48907813f..1ba085f0f 100644 --- a/src/libexpr/flake/flake.hh +++ b/src/libexpr/flake/flake.hh @@ -119,7 +119,7 @@ struct LockedFlake */ std::map, SourcePath> nodePaths; - Fingerprint getFingerprint() const; + std::optional getFingerprint(ref store) const; }; struct LockFlags diff --git a/src/libfetchers/path.cc b/src/libfetchers/path.cc index 276fd1b36..8231492e8 100644 --- a/src/libfetchers/path.cc +++ b/src/libfetchers/path.cc @@ -147,6 +147,20 @@ struct PathInputScheme : InputScheme return {std::move(*storePath), input}; } + std::optional getFingerprint(ref store, const Input & input) const override + { + /* If this path is in the Nix store, use the hash of the + store object and the subpath. */ + auto path = getAbsPath(input); + try { + auto [storePath, subPath] = store->toStorePath(path.abs()); + auto info = store->queryPathInfo(storePath); + return fmt("path:%s:%s", info->narHash.to_string(HashFormat::Base16, false), subPath); + } catch (Error &) { + return std::nullopt; + } + } + std::optional experimentalFeature() const override { return Xp::Flakes;