diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index decb8e0bf..366cb40b4 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -560,14 +560,11 @@ ref openEvalCache( EvalState & state, std::shared_ptr lockedFlake) { - auto fingerprint = lockedFlake->getFingerprint(); + auto fingerprint = lockedFlake->getFingerprint(state.store); return make_ref( - #if 0 evalSettings.useEvalCache && evalSettings.pureEval - ? std::optional { std::cref(fingerprint) } - : - #endif - std::nullopt, + ? fingerprint + : std::nullopt, state, [&state, lockedFlake]() { diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc index 335574adb..99c498be7 100644 --- a/src/libexpr/flake/flake.cc +++ b/src/libexpr/flake/flake.cc @@ -772,19 +772,17 @@ static RegisterPrimOp r2({ } -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(htSHA256, - fmt("%s;%s;%d;%d;%s", - "FIXME", - //flake.sourceInfo->storePath.to_string(), - flake.lockedRef.subdir, - flake.lockedRef.input.getRevCount().value_or(0), - flake.lockedRef.input.getLastModified().value_or(0), - lockFile)); + return hashString(htSHA256, 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 8e30e741d..6b44f9a9c 100644 --- a/src/libexpr/flake/flake.hh +++ b/src/libexpr/flake/flake.hh @@ -79,7 +79,7 @@ struct LockedFlake Flake flake; LockFile lockFile; - Fingerprint getFingerprint() const; + std::optional getFingerprint(ref store) const; }; struct LockFlags diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index 954b25070..f1d64c992 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -289,6 +289,14 @@ std::optional Input::getLastModified() const return {}; } +std::optional Input::getFingerprint(ref store) const +{ + if (auto rev = getRev()) + return rev->gitRev(); + assert(scheme); + return scheme->getFingerprint(store, *this); +} + ParsedURL InputScheme::toURL(const Input & input) { throw Error("don't know how to convert input '%s' to a URL", attrsToJSON(input.attrs)); diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh index e8c897d4f..ccba68dc9 100644 --- a/src/libfetchers/fetchers.hh +++ b/src/libfetchers/fetchers.hh @@ -104,6 +104,10 @@ public: std::optional getRevCount() const; std::optional getLastModified() const; + // For locked inputs, returns a string that uniquely specifies the + // content of the input (typically a commit hash or content hash). + std::optional getFingerprint(ref store) const; + private: void checkLocked(Store & store, const StorePath & storePath, Input & input) const; @@ -156,6 +160,9 @@ struct InputScheme virtual bool isRelative(const Input & input) const { return false; } + + virtual std::optional getFingerprint(ref store, const Input & input) const + { return std::nullopt; } }; void registerInputScheme(std::shared_ptr && fetcher); diff --git a/src/libfetchers/path.cc b/src/libfetchers/path.cc index 2706e8e91..1236ecf7e 100644 --- a/src/libfetchers/path.cc +++ b/src/libfetchers/path.cc @@ -86,13 +86,14 @@ struct PathInputScheme : InputScheme // nothing to do } - CanonPath getAbsPath(ref store, const Input & input) + CanonPath getAbsPath(ref store, const Input & input) const { auto path = getStrAttr(input.attrs, "path"); if (path[0] == '/') return CanonPath(path); + // FIXME: remove this? if (!input.parent) throw Error("cannot fetch input '%s' because it uses a relative path", input.to_string()); @@ -145,6 +146,19 @@ struct PathInputScheme : InputScheme input2.attrs.emplace("path", (std::string) absPath.abs()); return {makeFSInputAccessor(absPath), std::move(input2)}; } + + std::optional getFingerprint(ref store, const Input & input) const override + { + /* If this path is in the Nix store, we can consider it + locked, so just use the path as its fingerprint. Maybe we + should restrict this to CA paths but that's not + super-important. */ + auto path = getAbsPath(store, input); + if (store->isInStore(path.abs())) + return path.abs(); + return std::nullopt; + } + }; static auto rPathInputScheme = OnStartup([] { registerInputScheme(std::make_unique()); });