From f62003e8804165b6331d8c6f130c9ca071ddbdba Mon Sep 17 00:00:00 2001 From: webard Date: Sat, 12 Sep 2026 14:20:50 +0200 Subject: [PATCH] relative path cache --- src/Caching/Detector/ChangedFilesDetector.php | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Caching/Detector/ChangedFilesDetector.php b/src/Caching/Detector/ChangedFilesDetector.php index 385dbffb98c..2698ad39411 100644 --- a/src/Caching/Detector/ChangedFilesDetector.php +++ b/src/Caching/Detector/ChangedFilesDetector.php @@ -8,6 +8,7 @@ use Rector\Caching\Config\FileHashComputer; use Rector\Caching\Enum\CacheKey; use Rector\Configuration\Parameter\SimpleParameterProvider; +use Rector\FileSystem\FilePathHelper; use Rector\Util\FileHasher; /** @@ -28,7 +29,8 @@ final class ChangedFilesDetector public function __construct( private readonly FileHashComputer $fileHashComputer, private readonly Cache $cache, - private readonly FileHasher $fileHasher + private readonly FileHasher $fileHasher, + private readonly FilePathHelper $filePathHelper ) { } @@ -70,7 +72,7 @@ public function hasFileChanged(string $filePath): bool // a scoped (--only) run reuses the full-run cache: a file left clean by all rules stays // clean under a single rule too, and the content is still compared below if ($cachedValue === null && $this->scopeSuffix !== '') { - $unscopedCacheKey = $this->fileHasher->hash($this->resolvePath($filePath)); + $unscopedCacheKey = $this->fileHasher->hash($this->cacheKeyPath($filePath)); $cachedValue = $this->cache->load($unscopedCacheKey, CacheKey::FILE_HASH_KEY); } @@ -117,7 +119,20 @@ private function resolvePath(string $filePath): string private function getFilePathCacheKey(string $filePath): string { - return $this->fileHasher->hash($this->resolvePath($filePath) . $this->scopeSuffix); + return $this->fileHasher->hash($this->cacheKeyPath($filePath) . $this->scopeSuffix); + } + + /** + * The path a cache key is built from: relative to the project, never absolute. + * + * An absolute path ties the whole cache to one location on disk, so the same project + * checked out twice - a git worktree, a CI checkout, a container mount - shares nothing. + * Relative keys let a cache travel with the project. Paths outside the project keep + * their `../` prefix and stay just as stable, because the anchor does not move either. + */ + private function cacheKeyPath(string $filePath): string + { + return $this->filePathHelper->relativePath($this->resolvePath($filePath)); } private function hashFile(string $filePath): string