diff --git a/src/libfetchers/filtering-source-accessor.cc b/src/libfetchers/filtering-source-accessor.cc index 29f0be3080e..8ad13b33416 100644 --- a/src/libfetchers/filtering-source-accessor.cc +++ b/src/libfetchers/filtering-source-accessor.cc @@ -61,6 +61,11 @@ std::pair> FilteringSourceAccessor::getFin return next->getFingerprint(prefix / path); } +void FilteringSourceAccessor::invalidateCache(const CanonPath & path) +{ + next->invalidateCache(prefix / path); +} + void FilteringSourceAccessor::checkAccess(const CanonPath & path) { if (!isAllowed(path)) diff --git a/src/libfetchers/include/nix/fetchers/filtering-source-accessor.hh b/src/libfetchers/include/nix/fetchers/filtering-source-accessor.hh index 396a184fe72..ed3fc56f676 100644 --- a/src/libfetchers/include/nix/fetchers/filtering-source-accessor.hh +++ b/src/libfetchers/include/nix/fetchers/filtering-source-accessor.hh @@ -52,6 +52,8 @@ struct FilteringSourceAccessor : SourceAccessor std::pair> getFingerprint(const CanonPath & path) override; + void invalidateCache(const CanonPath & path) override; + /** * Call `makeNotAllowedError` to throw a `RestrictedPathError` * exception if `isAllowed()` returns `false` for `path`. diff --git a/src/libflake/flake.cc b/src/libflake/flake.cc index be3b667d2da..9dab20c5c10 100644 --- a/src/libflake/flake.cc +++ b/src/libflake/flake.cc @@ -876,6 +876,8 @@ lockFlake(const Settings & settings, EvalState & state, const FlakeRef & topRef, CanonPath((topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock"), newLockFileS, commitMessage); + + flake.lockFilePath().invalidateCache(); } /* Rewriting the lockfile changed the top-level diff --git a/src/libutil/include/nix/util/posix-source-accessor.hh b/src/libutil/include/nix/util/posix-source-accessor.hh index c3733119bff..7ff7ee9fdee 100644 --- a/src/libutil/include/nix/util/posix-source-accessor.hh +++ b/src/libutil/include/nix/util/posix-source-accessor.hh @@ -80,6 +80,8 @@ public: return trackLastModified ? std::optional{mtime} : std::nullopt; } + void invalidateCache(const CanonPath & path) override; + private: /** diff --git a/src/libutil/include/nix/util/source-accessor.hh b/src/libutil/include/nix/util/source-accessor.hh index ee09b182b7b..e1de9ece7f3 100644 --- a/src/libutil/include/nix/util/source-accessor.hh +++ b/src/libutil/include/nix/util/source-accessor.hh @@ -213,6 +213,11 @@ struct SourceAccessor : std::enable_shared_from_this { return std::nullopt; } + + /** + * Invalidate any cached value the accessor may have for the specified path. + */ + virtual void invalidateCache(const CanonPath & path) {} }; /** diff --git a/src/libutil/include/nix/util/source-path.hh b/src/libutil/include/nix/util/source-path.hh index 08f9fe580b0..4597de1ff46 100644 --- a/src/libutil/include/nix/util/source-path.hh +++ b/src/libutil/include/nix/util/source-path.hh @@ -114,6 +114,11 @@ struct SourcePath return {accessor, accessor->resolveSymlinks(path, mode)}; } + void invalidateCache() const + { + accessor->invalidateCache(path); + } + friend class std::hash; }; diff --git a/src/libutil/mounted-source-accessor.cc b/src/libutil/mounted-source-accessor.cc index 4122fc78c12..73ad5c9a94a 100644 --- a/src/libutil/mounted-source-accessor.cc +++ b/src/libutil/mounted-source-accessor.cc @@ -99,6 +99,12 @@ struct MountedSourceAccessorImpl : MountedSourceAccessor auto [accessor, subpath] = resolve(path); return accessor->getFingerprint(subpath); } + + void invalidateCache(const CanonPath & path) override + { + auto [accessor, subpath] = resolve(path); + accessor->invalidateCache(subpath); + } }; ref makeMountedSourceAccessor(std::map> mounts) diff --git a/src/libutil/posix-source-accessor.cc b/src/libutil/posix-source-accessor.cc index ccb9c89d94e..86f28def0d4 100644 --- a/src/libutil/posix-source-accessor.cc +++ b/src/libutil/posix-source-accessor.cc @@ -85,11 +85,11 @@ bool PosixSourceAccessor::pathExists(const CanonPath & path) return nix::pathExists(makeAbsPath(path).string()); } +using Cache = boost::concurrent_flat_map>; +static Cache cache; + std::optional PosixSourceAccessor::cachedLstat(const CanonPath & path) { - using Cache = boost::concurrent_flat_map>; - static Cache cache; - // Note: we convert std::filesystem::path to Path because the // former is not hashable on libc++. Path absPath = makeAbsPath(path).string(); @@ -106,6 +106,11 @@ std::optional PosixSourceAccessor::cachedLstat(const CanonPath & path return st; } +void PosixSourceAccessor::invalidateCache(const CanonPath & path) +{ + cache.erase(makeAbsPath(path).string()); +} + std::optional PosixSourceAccessor::maybeLstat(const CanonPath & path) { if (auto parent = path.parent()) diff --git a/src/libutil/union-source-accessor.cc b/src/libutil/union-source-accessor.cc index d19400303e2..dfe81f635cd 100644 --- a/src/libutil/union-source-accessor.cc +++ b/src/libutil/union-source-accessor.cc @@ -90,6 +90,12 @@ struct UnionSourceAccessor : SourceAccessor } return {path, std::nullopt}; } + + void invalidateCache(const CanonPath & path) override + { + for (auto & accessor : accessors) + accessor->invalidateCache(path); + } }; ref makeUnionSourceAccessor(std::vector> && accessors)