diff --git a/packages/fractor/src/Application/FractorRunner.php b/packages/fractor/src/Application/FractorRunner.php index 64194fbf..5ae73ca0 100644 --- a/packages/fractor/src/Application/FractorRunner.php +++ b/packages/fractor/src/Application/FractorRunner.php @@ -46,7 +46,7 @@ public function __construct( public function run(Configuration $configuration): ProcessResult { - $filePaths = $this->fileFinder->findFiles($configuration->getPaths(), $configuration->getFileExtensions()); + $filePaths = $this->fileFinder->findFilesInPaths($configuration->getPaths(), $configuration); // no files found if ($filePaths === []) { diff --git a/packages/fractor/src/Configuration/ConfigurationFactory.php b/packages/fractor/src/Configuration/ConfigurationFactory.php index 3848c06d..43764650 100644 --- a/packages/fractor/src/Configuration/ConfigurationFactory.php +++ b/packages/fractor/src/Configuration/ConfigurationFactory.php @@ -23,6 +23,7 @@ public function __construct( public function createFromInput(InputInterface $input): Configuration { $dryRun = (bool) $input->getOption(Option::DRY_RUN); + $shouldClearCache = (bool) $input->getOption(Option::CLEAR_CACHE); $outputFormat = (string) $input->getOption(Option::OUTPUT_FORMAT); $showProgressBar = $this->shouldShowProgressBar($input, $outputFormat); @@ -47,6 +48,7 @@ public function createFromInput(InputInterface $input): Configuration return new Configuration( $dryRun, $showProgressBar, + $shouldClearCache, $outputFormat, $fileExtensions, $paths, @@ -68,7 +70,7 @@ public function createForTests(array $paths): Configuration $fileExtensions = $this->allowedFileExtensionsResolver->resolve(); - return new Configuration(false, true, ConsoleOutputFormatter::NAME, $fileExtensions, $paths); + return new Configuration(false, true, false, ConsoleOutputFormatter::NAME, $fileExtensions, $paths); } private function shouldShowProgressBar(InputInterface $input, string $outputFormat): bool diff --git a/packages/fractor/src/Configuration/ValueObject/Configuration.php b/packages/fractor/src/Configuration/ValueObject/Configuration.php index 36d55487..705b99c0 100644 --- a/packages/fractor/src/Configuration/ValueObject/Configuration.php +++ b/packages/fractor/src/Configuration/ValueObject/Configuration.php @@ -19,6 +19,7 @@ public function __construct( private bool $dryRun = false, private bool $showProgressBar = true, + private bool $shouldClearCache = false, private string $outputFormat = ConsoleOutputFormatter::NAME, private array $fileExtensions = [], private array $paths = [], @@ -41,6 +42,11 @@ public function shouldShowProgressBar(): bool return $this->showProgressBar; } + public function shouldClearCache(): bool + { + return $this->shouldClearCache; + } + public function getOutputFormat(): string { return $this->outputFormat; diff --git a/packages/fractor/src/Console/Command/ProcessCommand.php b/packages/fractor/src/Console/Command/ProcessCommand.php index 58433caa..0fede897 100644 --- a/packages/fractor/src/Console/Command/ProcessCommand.php +++ b/packages/fractor/src/Console/Command/ProcessCommand.php @@ -5,7 +5,6 @@ namespace a9f\Fractor\Console\Command; use a9f\Fractor\Application\FractorRunner; -use a9f\Fractor\Caching\Detector\ChangedFilesDetector; use a9f\Fractor\ChangesReporting\Output\ConsoleOutputFormatter; use a9f\Fractor\Configuration\ConfigInitializer; use a9f\Fractor\Configuration\ConfigurationFactory; @@ -32,7 +31,6 @@ public function __construct( private readonly FractorRunner $runner, private readonly ConfigurationFactory $configurationFactory, private readonly OutputFormatterCollector $outputFormatterCollector, - private readonly ChangedFilesDetector $changedFilesDetector, private readonly ConfigInitializer $configInitializer, private readonly MemoryLimiter $memoryLimiter, private readonly ConfigurationRuleFilter $configurationRuleFilter @@ -130,11 +128,6 @@ protected function initialize(InputInterface $input, OutputInterface $output): v if (! $application instanceof FractorApplication) { throw new ShouldNotHappenException(); } - // clear cache - $optionClearCache = (bool) $input->getOption(Option::CLEAR_CACHE); - if ($optionClearCache) { - $this->changedFilesDetector->clear(); - } } /** diff --git a/packages/fractor/src/FileSystem/FilesFinder.php b/packages/fractor/src/FileSystem/FilesFinder.php index 62a5dbfc..3fc2bfcb 100644 --- a/packages/fractor/src/FileSystem/FilesFinder.php +++ b/packages/fractor/src/FileSystem/FilesFinder.php @@ -4,30 +4,33 @@ namespace a9f\Fractor\FileSystem; +use a9f\Fractor\Caching\Detector\ChangedFilesDetector; use a9f\Fractor\Caching\UnchangedFilesFilter; +use a9f\Fractor\Configuration\ValueObject\Configuration; use Symfony\Component\Finder\Finder; use Webmozart\Assert\Assert; final readonly class FilesFinder { public function __construct( - private WildcardResolver $wildcardResolver, + private FilesystemTweaker $filesystemTweaker, private FileAndDirectoryFilter $fileAndDirectoryFilter, private PathSkipper $pathSkipper, - private UnchangedFilesFilter $unchangedFilesFilter + private UnchangedFilesFilter $unchangedFilesFilter, + private ChangedFilesDetector $changedFilesDetector, ) { } /** - * @param list $source + * @param string[] $source * @param string[] $suffixes * @return string[] */ - public function findFiles(array $source, array $suffixes, bool $sortByName = true): array + public function findInDirectoriesAndFiles(array $source, array $suffixes, bool $sortByName = true): array { Assert::allStringNotEmpty($source, 'Please provide some paths'); - $filesAndDirectories = $this->wildcardResolver->resolveAllWildcards($source); + $filesAndDirectories = $this->filesystemTweaker->resolveWithFnmatch($source); $files = $this->fileAndDirectoryFilter->filterFiles($filesAndDirectories); @@ -51,6 +54,19 @@ public function findFiles(array $source, array $suffixes, bool $sortByName = tru return $this->unchangedFilesFilter->filterFilePaths($filePaths); } + /** + * @param string[] $paths + * @return string[] + */ + public function findFilesInPaths(array $paths, Configuration $configuration): array + { + if ($configuration->shouldClearCache()) { + $this->changedFilesDetector->clear(); + } + + return $this->findInDirectoriesAndFiles($paths, $configuration->getFileExtensions(), true); + } + /** * @param string[] $directories * @param string[] $suffixes diff --git a/packages/fractor/src/FileSystem/FilesystemTweaker.php b/packages/fractor/src/FileSystem/FilesystemTweaker.php new file mode 100644 index 00000000..9f88c8e7 --- /dev/null +++ b/packages/fractor/src/FileSystem/FilesystemTweaker.php @@ -0,0 +1,60 @@ +foundInGlob($path); + $absolutePathsFound = $this->appendPaths($foundPaths, $absolutePathsFound); + } else { + $absolutePathsFound = $this->appendPaths([$path], $absolutePathsFound); + } + } + + return $absolutePathsFound; + } + + /** + * @param string[] $foundPaths + * @param string[] $absolutePathsFound + * @return string[] + */ + private function appendPaths(array $foundPaths, array $absolutePathsFound): array + { + foreach ($foundPaths as $foundPath) { + $foundPath = realpath($foundPath); + + if ($foundPath === false) { + continue; + } + + $absolutePathsFound[] = $foundPath; + } + + return $absolutePathsFound; + } + + /** + * @return string[] + */ + private function foundInGlob(string $path): array + { + /** @var string[] $paths */ + $paths = (array) glob($path); + + return array_filter($paths, file_exists(...)); + } +} diff --git a/packages/fractor/src/FileSystem/WildcardResolver.php b/packages/fractor/src/FileSystem/WildcardResolver.php deleted file mode 100644 index 894492f7..00000000 --- a/packages/fractor/src/FileSystem/WildcardResolver.php +++ /dev/null @@ -1,40 +0,0 @@ -foundInGlob($path); - $absolutePathsFound = [...$absolutePathsFound, ...$foundPaths]; - } else { - $absolutePathsFound[] = $path; - } - } - - return $absolutePathsFound; - } - - /** - * @return string[] - */ - private function foundInGlob(string $path): array - { - /** @var string[] $paths */ - $paths = (array) glob($path); - - return array_filter($paths, file_exists(...)); - } -} diff --git a/packages/fractor/tests/FileSystem/FilesFinder/FilesFinderTest.php b/packages/fractor/tests/FileSystem/FilesFinder/FilesFinderTest.php index ec36eff9..98ef98be 100644 --- a/packages/fractor/tests/FileSystem/FilesFinder/FilesFinderTest.php +++ b/packages/fractor/tests/FileSystem/FilesFinder/FilesFinderTest.php @@ -21,33 +21,42 @@ protected function setUp(): void #[Test] public function findAllNonEmptyFilesInGivenDirectories(): void { - self::assertCount(4, $this->subject->findFiles([__DIR__ . '/Fixtures/Source'], [])); + self::assertCount(4, $this->subject->findInDirectoriesAndFiles([__DIR__ . '/Fixtures/Source'], [])); } #[Test] public function findAllNonEmptyFilesInGivenDirectoriesWithGivenExtensions(): void { - self::assertCount(2, $this->subject->findFiles([__DIR__ . '/Fixtures/Source'], ['txt', 'json'])); + self::assertCount( + 2, + $this->subject->findInDirectoriesAndFiles([__DIR__ . '/Fixtures/Source'], ['txt', 'json']) + ); } #[Test] public function withFollowingBrokenSymlinks(): void { - $foundFiles = $this->subject->findFiles([__DIR__ . '/Fixtures/SourceWithBrokenSymlinks'], []); + $foundFiles = $this->subject->findInDirectoriesAndFiles([__DIR__ . '/Fixtures/SourceWithBrokenSymlinks'], []); self::assertCount(0, $foundFiles); } #[Test] public function directoriesWithGlobPattern(): void { - $foundDirectories = $this->subject->findFiles([__DIR__ . '/Fixtures/SourceWithSubFolders/folder*/*'], []); + $foundDirectories = $this->subject->findInDirectoriesAndFiles( + [__DIR__ . '/Fixtures/SourceWithSubFolders/folder*/*'], + [] + ); self::assertCount(2, $foundDirectories); } #[Test] public function filesWithGlobPattern(): void { - $foundFiles = $this->subject->findFiles([__DIR__ . '/Fixtures/SourceWithSubFolders/**/foo.txt'], ['txt']); + $foundFiles = $this->subject->findInDirectoriesAndFiles( + [__DIR__ . '/Fixtures/SourceWithSubFolders/**/foo.txt'], + ['txt'] + ); self::assertCount(2, $foundFiles); /** @var string $foundFile */