diff --git a/src/Command/RunCommand.php b/src/Command/RunCommand.php index baa2e91b..d4311246 100644 --- a/src/Command/RunCommand.php +++ b/src/Command/RunCommand.php @@ -179,8 +179,9 @@ private function analyze(InputInterface $input, Config $config, Broker $broker): $broker->subscribe($report = new ResultAccumulator($config->getFilesToShow(), $config->getMinScoreToShow())); $broker->subscribe($processFactory = $this->getProcessFactory($config)); $broker->notify(new BeforeAnalysisEvent()); - $filesFinder = (new FileFinder($config->getFileExtensions(), $config->getFilesToIgnore())) - ->getPhpFiles($this->getDirectoriesToScan($input, $config)); + $basePath = $this->getBasePath($input, $config); + $filesFinder = (new FileFinder($config->getFileExtensions(), $config->getFilesToIgnore(), $basePath)) + ->getPhpFiles($config->getDirectoriesToScan()); $this->processHandlerFactory->getProcessHandler($config, $broker)->process($filesFinder, $processFactory); $broker->notify(new AfterAnalysisEvent($report)); @@ -190,20 +191,13 @@ private function analyze(InputInterface $input, Config $config, Broker $broker): /** * @param InputInterface $input Input. * @param Config $config The configuration object. - * @return array Array of absolute paths. + * @return string The base path. */ - private function getDirectoriesToScan(InputInterface $input, Config $config): array + private function getBasePath(InputInterface $input, Config $config): string { - $basePath = [] === $input->getArgument('paths') + return [] === $input->getArgument('paths') ? $config->getDirPath() : \getcwd(); - $paths = []; - - foreach ($config->getDirectoriesToScan() as $path) { - $paths[] = FileHelper::toAbsolutePath($path, $basePath); - } - - return $paths; } /** diff --git a/src/File/FileFinder.php b/src/File/FileFinder.php index 139d682e..336bef8f 100644 --- a/src/File/FileFinder.php +++ b/src/File/FileFinder.php @@ -29,18 +29,27 @@ class FileFinder */ private $filters; + /** + * The base path. + * + * @var string + */ + private $basePath; + /** * Class constructor. * * @param array $fileExtensions List of file extensions to look for. * @param array $filesToIgnore List of files to ignore. + * @param string $basePath The base path. */ - public function __construct(array $fileExtensions, array $filesToIgnore) + public function __construct(array $fileExtensions, array $filesToIgnore, string $basePath) { $this->fileExtensions = $fileExtensions; $this->filters = \array_map(function (string $fileToIgnore): string { return $this->patternToRegex($fileToIgnore); }, $filesToIgnore); + $this->basePath = $basePath; } /** @@ -53,7 +62,9 @@ public function __construct(array $fileExtensions, array $filesToIgnore) public function getPhpFiles(array $paths): Generator { foreach ($paths as $path) { - yield from $this->getPhpFilesFromPath($path); + $absolutePath = FileHelper::toAbsolutePath($path, $this->basePath); + + yield from $this->getPhpFilesFromPath($absolutePath); } } @@ -69,7 +80,7 @@ private function getPhpFilesFromPath(string $path): Generator if (\is_file($path)) { $file = new SplFileInfo($path); - yield new File($file->getRealPath(), $file->getPathName()); + yield new File($file->getRealPath(), $this->getDisplayPath($file)); return; } @@ -80,10 +91,19 @@ private function getPhpFilesFromPath(string $path): Generator } foreach ($this->findPhpFiles($path) as $file) { - yield new File($file->getRealPath(), $file->getPathName()); + yield new File($file->getRealPath(), $this->getDisplayPath($file)); } } + /** + * @param SplFileInfo $file The file object. + * @return string The file path to display. + */ + private function getDisplayPath(SplFileInfo $file): string + { + return FileHelper::toRelativePath($file->getPathName(), $this->basePath); + } + /** * Recursively finds all PHP files in a given directory. * diff --git a/src/File/FileHelper.php b/src/File/FileHelper.php index e06abbba..c40ca003 100644 --- a/src/File/FileHelper.php +++ b/src/File/FileHelper.php @@ -5,6 +5,7 @@ namespace Churn\File; use InvalidArgumentException; +use Symfony\Component\Filesystem\Exception\InvalidArgumentException as FilesystemException; use Symfony\Component\Filesystem\Filesystem; /** @@ -25,6 +26,22 @@ public static function toAbsolutePath(string $path, string $basePath): string : $basePath . '/' . $path; } + /** + * @param string $path The absolute path of an item. + * @param string $basePath The absolute base path. + * @return string The relative path of the given item. + */ + public static function toRelativePath(string $path, string $basePath): string + { + try { + $relativePath = (new Filesystem())->makePathRelative($path, $basePath); + + return \rtrim($relativePath, '/\\'); + } catch (FilesystemException $e) { + return $path; + } + } + /** * Check whether the path is writable and create the missing folders if needed. * diff --git a/tests/EndToEnd/FossilTest.php b/tests/EndToEnd/FossilTest.php index c0fc7406..7601024e 100644 --- a/tests/EndToEnd/FossilTest.php +++ b/tests/EndToEnd/FossilTest.php @@ -43,12 +43,12 @@ public function it_works_with_fossil() ( (__ ) _ ( )(__)( ) / ) ((___))___/ ) _ ( )___/ \___)(_) (_)(______)(_)\_)(_)\_) (__) (_) (_)(__) -+-------------------+---------------+------------+-------+ -| File | Times Changed | Complexity | Score | -+-------------------+---------------+------------+-------+ -| /tmp/test/Foo.php | 2 | 1 | 1 | -| /tmp/test/Bar.php | 1 | 1 | 0.5 | -+-------------------+---------------+------------+-------+ ++---------+---------------+------------+-------+ +| File | Times Changed | Complexity | Score | ++---------+---------------+------------+-------+ +| Foo.php | 2 | 1 | 1 | +| Bar.php | 1 | 1 | 0.5 | ++---------+---------------+------------+-------+ "; $this->assertEquals(0, $exitCode); diff --git a/tests/EndToEnd/MercurialTest.php b/tests/EndToEnd/MercurialTest.php index 6b947c29..0162945c 100644 --- a/tests/EndToEnd/MercurialTest.php +++ b/tests/EndToEnd/MercurialTest.php @@ -43,12 +43,12 @@ public function it_works_with_mercurial() ( (__ ) _ ( )(__)( ) / ) ((___))___/ ) _ ( )___/ \___)(_) (_)(______)(_)\_)(_)\_) (__) (_) (_)(__) -+-------------------+---------------+------------+-------+ -| File | Times Changed | Complexity | Score | -+-------------------+---------------+------------+-------+ -| /tmp/test/Foo.php | 2 | 1 | 1 | -| /tmp/test/Bar.php | 1 | 1 | 0.5 | -+-------------------+---------------+------------+-------+ ++---------+---------------+------------+-------+ +| File | Times Changed | Complexity | Score | ++---------+---------------+------------+-------+ +| Foo.php | 2 | 1 | 1 | +| Bar.php | 1 | 1 | 0.5 | ++---------+---------------+------------+-------+ "; $this->assertEquals(0, $exitCode); diff --git a/tests/EndToEnd/SubversionTest.php b/tests/EndToEnd/SubversionTest.php index c86b6004..3434d14d 100644 --- a/tests/EndToEnd/SubversionTest.php +++ b/tests/EndToEnd/SubversionTest.php @@ -43,12 +43,12 @@ public function it_works_with_subversion() ( (__ ) _ ( )(__)( ) / ) ((___))___/ ) _ ( )___/ \___)(_) (_)(______)(_)\_)(_)\_) (__) (_) (_)(__) -+-------------------+---------------+------------+-------+ -| File | Times Changed | Complexity | Score | -+-------------------+---------------+------------+-------+ -| /tmp/test/Foo.php | 2 | 1 | 1 | -| /tmp/test/Bar.php | 1 | 1 | 0.5 | -+-------------------+---------------+------------+-------+ ++---------+---------------+------------+-------+ +| File | Times Changed | Complexity | Score | ++---------+---------------+------------+-------+ +| Foo.php | 2 | 1 | 1 | +| Bar.php | 1 | 1 | 0.5 | ++---------+---------------+------------+-------+ "; $this->assertEquals(0, $exitCode); diff --git a/tests/Integration/File/FileFinderTest.php b/tests/Integration/File/FileFinderTest.php index 58d01d44..765b9ad5 100644 --- a/tests/Integration/File/FileFinderTest.php +++ b/tests/Integration/File/FileFinderTest.php @@ -35,6 +35,6 @@ public function setUp() { parent::setup(); - $this->fileFinder = new FileFinder(['php'], []); + $this->fileFinder = new FileFinder(['php'], [], __DIR__); } } diff --git a/tests/Unit/File/FileFinderTest.php b/tests/Unit/File/FileFinderTest.php index bcd05f01..41d2ddf3 100644 --- a/tests/Unit/File/FileFinderTest.php +++ b/tests/Unit/File/FileFinderTest.php @@ -17,7 +17,7 @@ class FileFinderTest extends BaseTestCase public function setup() { - $this->fileFinder = new FileFinder(['php'], []); + $this->fileFinder = new FileFinder(['php'], [], __DIR__); } /** @test */ @@ -53,53 +53,53 @@ public function it_does_not_throw_with_non_existing_path() /** @test */ public function it_ignores_files_specified_to_ignore_in_the_config() { - $fileFinder = new FileFinder(['php'], ['Assets/Baz.php']); + $fileFinder = new FileFinder(['php'], ['Assets/Baz.php'], __DIR__); $this->assertCount(2, iterator_to_array($fileFinder->getPhpFiles([__DIR__ . '/../Assets']), false)); } /** @test */ public function it_ignores_everything_within_a_folder() { - $fileFinder = new FileFinder(['php'], ['Assets2/DeepAssets/*']); + $fileFinder = new FileFinder(['php'], ['Assets2/DeepAssets/*'], __DIR__); $this->assertCount(1, iterator_to_array($fileFinder->getPhpFiles([__DIR__ . '/../Assets2']), false)); - $fileFinder = new FileFinder(['php', 'inc'], ['Assets2/DeepAssets/*']); + $fileFinder = new FileFinder(['php', 'inc'], ['Assets2/DeepAssets/*'], __DIR__); $this->assertCount(2, iterator_to_array($fileFinder->getPhpFiles([__DIR__ . '/../Assets2']), false)); } /** @test */ public function it_ignores_everything_starts_with_a_string() { - $fileFinder = new FileFinder(['php'], ['Assets2/F*']); + $fileFinder = new FileFinder(['php'], ['Assets2/F*'], __DIR__); $this->assertCount(3, iterator_to_array($fileFinder->getPhpFiles([__DIR__ . '/../Assets2']), false)); - $fileFinder = new FileFinder(['php'], ['Assets2/DeepAssets/Deep*']); + $fileFinder = new FileFinder(['php'], ['Assets2/DeepAssets/Deep*'], __DIR__); $this->assertCount(2, iterator_to_array($fileFinder->getPhpFiles([__DIR__ . '/../Assets2']), false)); - $fileFinder = new FileFinder(['php'], ['Assets2/DeepAssets/Dif*']); + $fileFinder = new FileFinder(['php'], ['Assets2/DeepAssets/Dif*'], __DIR__); $this->assertCount(3, iterator_to_array($fileFinder->getPhpFiles([__DIR__ . '/../Assets2']), false)); } /** @test */ public function it_ignores_multiple_matching_patterns_in_multiple_folders() { - $fileFinder = new FileFinder(['php'], ['Assets2/F*', 'Assets/B*']); + $fileFinder = new FileFinder(['php'], ['Assets2/F*', 'Assets/B*'], __DIR__); $this->assertCount(4, iterator_to_array($fileFinder->getPhpFiles([__DIR__ . '/../Assets', __DIR__ . '/../Assets2']), false)); - $fileFinder = new FileFinder(['php', 'inc'], ['Assets2/DeepAssets/De*', 'Assets/B*']); + $fileFinder = new FileFinder(['php', 'inc'], ['Assets2/DeepAssets/De*', 'Assets/B*'], __DIR__); $this->assertCount(5, iterator_to_array($fileFinder->getPhpFiles([__DIR__ . '/../Assets', __DIR__ . '/../Assets2']), false)); - $fileFinder = new FileFinder(['php', 'inc'], ['Assets2/DeepAssets/Di*', 'Assets2/DeepAssets/De*', 'Assets2/F*']); + $fileFinder = new FileFinder(['php', 'inc'], ['Assets2/DeepAssets/Di*', 'Assets2/DeepAssets/De*', 'Assets2/F*'], __DIR__); $this->assertCount(1, iterator_to_array($fileFinder->getPhpFiles([__DIR__ . '/../Assets2']), false)); - $fileFinder = new FileFinder(['php', 'inc'], ['Assets2/*.php']); + $fileFinder = new FileFinder(['php', 'inc'], ['Assets2/*.php'], __DIR__); $this->assertCount(1, iterator_to_array($fileFinder->getPhpFiles([__DIR__ . '/../Assets2']), false)); } /** @test */ public function it_uses_extensions_specified_in_the_config() { - $fileFinder = new FileFinder(['php', 'inc'], []); + $fileFinder = new FileFinder(['php', 'inc'], [], __DIR__); $this->assertCount(4, iterator_to_array($fileFinder->getPhpFiles([__DIR__ . '/../Assets']), false)); } } diff --git a/tests/Unit/File/FileHelperTest.php b/tests/Unit/File/FileHelperTest.php index 52aead89..bf996005 100644 --- a/tests/Unit/File/FileHelperTest.php +++ b/tests/Unit/File/FileHelperTest.php @@ -12,20 +12,42 @@ class FileHelperTest extends BaseTestCase /** * @test - * @dataProvider provide_paths + * @dataProvider provide_absolute_paths */ public function it_can_return_absolute_path(string $path, string $confPath, string $expectedPath): void { $this->assertEquals($expectedPath, FileHelper::toAbsolutePath($path, $confPath)); } - public function provide_paths(): iterable + public function provide_absolute_paths(): iterable { yield ['/tmp', '/path', '/tmp']; yield ['foo', '/path', '/path/foo']; + yield ['foo', 'C:\\path', 'C:\\path/foo']; yield ['C:\\foo', '/path', 'C:\\foo']; yield ['d:\\foo', '/path', 'd:\\foo']; yield ['E:/foo', '/path', 'E:/foo']; yield ['f:/foo', '/path', 'f:/foo']; } + + /** + * @test + * @dataProvider provide_relative_paths + */ + public function it_can_return_relative_path(string $path, string $confPath, string $expectedPath): void + { + $this->assertEquals($expectedPath, FileHelper::toRelativePath($path, $confPath)); + } + + public function provide_relative_paths(): iterable + { + yield ['/tmp/file.php', '/tmp', 'file.php']; + yield ['/tmp/file.php', '/tmp/', 'file.php']; + yield ['file.php', '/tmp', 'file.php']; + yield ['C:/foo/file.php', 'C:/foo', 'file.php']; + + if ('\\' === \DIRECTORY_SEPARATOR) { + yield ['C:\\foo\\file.php', 'C:\\foo\\', 'file.php']; + } + } }