From be3e4fc84b2cca3e06bb52d6031c5ca4ff12a8a9 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Mar 2020 09:20:40 +0100 Subject: [PATCH] Result cache - use file hashes instead of modified times --- .github/workflows/build.yml | 2 +- .../ResultCache/ResultCacheManager.php | 36 +++++++++---------- tests/e2e/ResultCacheEndToEndTest.php | 6 +++- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e9ca781a81..6280a7a494 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -308,7 +308,7 @@ jobs: uses: actions/cache@v1 with: path: ./tmp - key: "result-cache-v1" + key: "result-cache-v2" - name: "PHPStan with result cache" run: | diff --git a/src/Analyser/ResultCache/ResultCacheManager.php b/src/Analyser/ResultCache/ResultCacheManager.php index d18c4151c7..426fae14d8 100644 --- a/src/Analyser/ResultCache/ResultCacheManager.php +++ b/src/Analyser/ResultCache/ResultCacheManager.php @@ -7,12 +7,11 @@ use PHPStan\File\FileReader; use function array_fill_keys; use function array_key_exists; -use function filemtime; class ResultCacheManager { - private const CACHE_VERSION = 'v1'; + private const CACHE_VERSION = 'v2-hashes'; /** @var string */ private $cacheFilePath; @@ -32,6 +31,9 @@ class ResultCacheManager /** @var string */ private $usedLevel; + /** @var array */ + private $fileHashes = []; + /** * @param string $cacheFilePath * @param string[] $allCustomConfigFiles @@ -113,15 +115,12 @@ public function restore(array $allAnalysedFiles, bool $debug): ResultCache unset($deletedFiles[$analysedFile]); $analysedFileData = $invertedDependencies[$analysedFile]; - $cachedModifiedTime = $analysedFileData['modifiedTime']; + $cachedFileHash = $analysedFileData['fileHash']; $dependentFiles = $analysedFileData['dependentFiles']; $invertedDependenciesToReturn[$analysedFile] = $dependentFiles; - $currentModifiedTime = filemtime($analysedFile); - if ($currentModifiedTime === false) { - $currentModifiedTime = time(); - } + $currentFileHash = $this->getFileHash($analysedFile); - if ($cachedModifiedTime === $currentModifiedTime) { + if ($cachedFileHash === $currentFileHash) { continue; } @@ -293,12 +292,8 @@ private function save( foreach ($dependencies as $file => $fileDependencies) { foreach ($fileDependencies as $fileDep) { if (!array_key_exists($fileDep, $invertedDependencies)) { - $modifiedTime = filemtime($fileDep); - if ($modifiedTime === false) { - $modifiedTime = time(); - } $invertedDependencies[$fileDep] = [ - 'modifiedTime' => $modifiedTime, + 'fileHash' => $this->getFileHash($fileDep), 'dependentFiles' => [], ]; unset($filesNoOneIsDependingOn[$fileDep]); @@ -316,12 +311,8 @@ private function save( continue; } - $modifiedTime = filemtime($file); - if ($modifiedTime === false) { - $modifiedTime = time(); - } $invertedDependencies[$file] = [ - 'modifiedTime' => $modifiedTime, + 'fileHash' => $this->getFileHash($file), 'dependentFiles' => [], ]; } @@ -385,10 +376,17 @@ private function getConfigFiles(): array private function getFileHash(string $path): string { + if (array_key_exists($path, $this->fileHashes)) { + return $this->fileHashes[$path]; + } + $contents = FileReader::read($path); $contents = str_replace("\r\n", "\n", $contents); - return sha1($contents); + $hash = sha1($contents); + $this->fileHashes[$path] = $hash; + + return $hash; } private function getPhpStanVersion(): string diff --git a/tests/e2e/ResultCacheEndToEndTest.php b/tests/e2e/ResultCacheEndToEndTest.php index ea782786c9..83c9880884 100644 --- a/tests/e2e/ResultCacheEndToEndTest.php +++ b/tests/e2e/ResultCacheEndToEndTest.php @@ -42,7 +42,11 @@ public function testResultCache(): void $lexerCode = str_replace('@param string $code', '', $lexerCode); $lexerCode = str_replace('public function startLexing($code', 'public function startLexing(\\PhpParser\\Node\\Expr\\MethodCall $code', $lexerCode); file_put_contents($lexerPath, $lexerCode); - touch(__DIR__ . '/PHP-Parser/lib/PhpParser/ErrorHandler.php'); + + $errorHandlerPath = __DIR__ . '/PHP-Parser/lib/PhpParser/ErrorHandler.php'; + $errorHandlerContents = FileReader::read($errorHandlerPath); + $errorHandlerContents .= "\n\n"; + file_put_contents($errorHandlerPath, $errorHandlerContents); $bootstrapPath = __DIR__ . '/PHP-Parser/lib/bootstrap.php'; $originalBootstrapContents = FileReader::read($bootstrapPath);