From 84c3743fb14258a39fc9dc7a5269bdd9839b0066 Mon Sep 17 00:00:00 2001 From: Edgaraszs Date: Mon, 28 Jul 2025 22:14:04 +0300 Subject: [PATCH] feat: dirty files check --- src/Command/AnalyseCommand.php | 3 ++ src/Command/ClearResultCacheCommand.php | 1 + src/Command/CommandHelper.php | 9 ++++- src/Command/DiagnoseCommand.php | 1 + src/Command/DirtyFilesHelper.php | 43 +++++++++++++++++++++ src/Command/DumpParametersCommand.php | 1 + src/Command/FixerWorkerCommand.php | 1 + src/Command/WorkerCommand.php | 1 + tests/PHPStan/Command/CommandHelperTest.php | 2 + 9 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/Command/DirtyFilesHelper.php diff --git a/src/Command/AnalyseCommand.php b/src/Command/AnalyseCommand.php index 926aa66408..67a88faf2f 100644 --- a/src/Command/AnalyseCommand.php +++ b/src/Command/AnalyseCommand.php @@ -109,6 +109,7 @@ protected function configure(): void new InputOption('watch', mode: InputOption::VALUE_NONE, description: 'Launch PHPStan Pro'), new InputOption('pro', mode: InputOption::VALUE_NONE, description: 'Launch PHPStan Pro'), new InputOption('fail-without-result-cache', mode: InputOption::VALUE_NONE, description: 'Return non-zero exit code when result cache is not used'), + new InputOption('dirty', mode: InputOption::VALUE_NONE, description: 'Only analyze files that have uncommitted changes'), ]); } @@ -147,6 +148,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $pro = (bool) $input->getOption('watch') || (bool) $input->getOption('pro'); $fix = (bool) $input->getOption('fix'); $failWithoutResultCache = (bool) $input->getOption('fail-without-result-cache'); + $dirty = (bool) $input->getOption('dirty'); /** @var string|false|null $generateBaselineFile */ $generateBaselineFile = $input->getOption('generate-baseline'); @@ -190,6 +192,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $tmpFile, $insteadOfFile, true, + $dirty, ); } catch (InceptionNotSuccessfulException $e) { return 1; diff --git a/src/Command/ClearResultCacheCommand.php b/src/Command/ClearResultCacheCommand.php index 1ca5f60b6e..71bdc7d0bc 100644 --- a/src/Command/ClearResultCacheCommand.php +++ b/src/Command/ClearResultCacheCommand.php @@ -88,6 +88,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int null, null, true, + false, ); } catch (InceptionNotSuccessfulException) { return 1; diff --git a/src/Command/CommandHelper.php b/src/Command/CommandHelper.php index a599a83efa..dc1b4c8dea 100644 --- a/src/Command/CommandHelper.php +++ b/src/Command/CommandHelper.php @@ -95,6 +95,7 @@ public static function begin( ?string $singleReflectionFile, ?string $singleReflectionInsteadOfFile, bool $cleanupContainerCache, + bool $dirty, ): InceptionResult { $stdOutput = new SymfonyOutput($output, new SymfonyStyle(new ErrorsConsoleStyle($input, $output))); @@ -239,7 +240,13 @@ public static function begin( $defaultLevelUsed = true; } - $paths = array_map(static fn (string $path): string => $currentWorkingDirectoryFileHelper->normalizePath($currentWorkingDirectoryFileHelper->absolutizePath($path)), $paths); + if ($dirty) { + $dirtyPathsHelper = new DirtyFilesHelper(); + $paths = array_map(static fn (string $path): string => $currentWorkingDirectoryFileHelper + ->normalizePath($currentWorkingDirectoryFileHelper->absolutizePath($path)), $dirtyPathsHelper->getGitDirtyFiles()); + } else { + $paths = array_map(static fn (string $path): string => $currentWorkingDirectoryFileHelper->normalizePath($currentWorkingDirectoryFileHelper->absolutizePath($path)), $paths); + } $analysedPathsFromConfig = []; $containerFactory = new ContainerFactory($currentWorkingDirectory); diff --git a/src/Command/DiagnoseCommand.php b/src/Command/DiagnoseCommand.php index 03d8d78455..31d61bccd7 100644 --- a/src/Command/DiagnoseCommand.php +++ b/src/Command/DiagnoseCommand.php @@ -87,6 +87,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int null, null, false, + false, ); } catch (InceptionNotSuccessfulException) { return 1; diff --git a/src/Command/DirtyFilesHelper.php b/src/Command/DirtyFilesHelper.php new file mode 100644 index 0000000000..0b8b06b4a2 --- /dev/null +++ b/src/Command/DirtyFilesHelper.php @@ -0,0 +1,43 @@ +&1', $output, $returnVar); + if ($returnVar !== 0) { + return null; + } + + return trim($output[0]); + } + + /** + * @return string[] + */ + public function getGitDirtyFiles(): array + { + $repoPath = $this->getGitRepoRoot(); + if ($repoPath === null) { + return []; + } + + $cmd = 'cd ' . escapeshellarg($repoPath) . ' && git status --porcelain'; + + exec($cmd, $output, $returnVar); + if ($returnVar !== 0) { + return []; + } + + $dirtyFiles = []; + + foreach ($output as $line) { + $filePath = substr($line, 3); + $dirtyFiles[] = $filePath; + } + + return $dirtyFiles; + } +} diff --git a/src/Command/DumpParametersCommand.php b/src/Command/DumpParametersCommand.php index 4ea86d2125..753ca337dd 100644 --- a/src/Command/DumpParametersCommand.php +++ b/src/Command/DumpParametersCommand.php @@ -89,6 +89,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int null, null, false, + false, ); } catch (InceptionNotSuccessfulException) { return 1; diff --git a/src/Command/FixerWorkerCommand.php b/src/Command/FixerWorkerCommand.php index 8701f1045d..54261954a0 100644 --- a/src/Command/FixerWorkerCommand.php +++ b/src/Command/FixerWorkerCommand.php @@ -114,6 +114,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int null, null, false, + false, ); } catch (InceptionNotSuccessfulException) { return 1; diff --git a/src/Command/WorkerCommand.php b/src/Command/WorkerCommand.php index dfef585109..0714ad92e2 100644 --- a/src/Command/WorkerCommand.php +++ b/src/Command/WorkerCommand.php @@ -118,6 +118,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $tmpFile, $insteadOfFile, false, + false, ); } catch (InceptionNotSuccessfulException $e) { return 1; diff --git a/tests/PHPStan/Command/CommandHelperTest.php b/tests/PHPStan/Command/CommandHelperTest.php index 702b5ac4ae..94972d7b4f 100644 --- a/tests/PHPStan/Command/CommandHelperTest.php +++ b/tests/PHPStan/Command/CommandHelperTest.php @@ -128,6 +128,7 @@ public function testBegin( null, null, false, + false, ); if ($expectException) { $this->fail(); @@ -309,6 +310,7 @@ public function testResolveParameters( null, null, false, + false, ); $parameters = $result->getContainer()->getParameters(); foreach ($expectedParameters as $name => $expectedValue) {