diff --git a/doc/usage.rst b/doc/usage.rst index 7e9c00ea783..37437b0d7a8 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -2,6 +2,9 @@ Usage ===== +The ``fix`` command +------------------- + The ``fix`` command tries to fix as much coding standards problems as possible on a given file or files in a given directory and its subdirectories: @@ -121,6 +124,35 @@ fixed but without actually modifying them: By using ``--using-cache`` option with ``yes`` or ``no`` you can set if the caching mechanism should be used. +The ``list-files`` command +-------------------------- + +The ``list-files`` command will list all files which need fixing. + +.. code-block:: console + + $ php php-cs-fixer.phar list-files + +The ``--config`` option can be used, like in the ``fix`` command, to tell from which path a config file should be loaded. + +.. code-block:: console + + $ php php-cs-fixer.phar list-files --config=.php-cs-fixer.dist.php + +The output is build in a form that its easy to use in combination with ``xargs`` command in a linux pipe. +This can be useful e.g. in situations where the caching might mechanism not available (CI, Docker) and distributing +fixing across several processes might speedup the process. + +Note: You need to pass the config to the ``fix`` command, in order to make it work with several files being passed by ``list-files``. + +.. code-block:: console + + $ php php-cs-fixer.phar list-files --config=.php-cs-fixer.dist.php | xargs -n 10 -P 8 php php-cs-fixer.phar fix --config=.php-cs-fixer.dist.php --path-mode intersection -v + +* `-n` defines how many files a single subprocess process +* `-P` defines how many subprocesses the shell is allowed to spawn for parallel processing (usually similar to the number of CPUs your system has) + + Rule descriptions ----------------- diff --git a/src/Console/Application.php b/src/Console/Application.php index c1154430b8b..b5b7f8e56cd 100644 --- a/src/Console/Application.php +++ b/src/Console/Application.php @@ -15,6 +15,7 @@ use PhpCsFixer\Console\Command\DescribeCommand; use PhpCsFixer\Console\Command\FixCommand; use PhpCsFixer\Console\Command\HelpCommand; +use PhpCsFixer\Console\Command\ListFilesCommand; use PhpCsFixer\Console\Command\SelfUpdateCommand; use PhpCsFixer\Console\SelfUpdate\GithubClient; use PhpCsFixer\Console\SelfUpdate\NewVersionChecker; @@ -52,8 +53,10 @@ public function __construct() $this->toolInfo = new ToolInfo(); + // in alphabetical order $this->add(new DescribeCommand()); $this->add(new FixCommand($this->toolInfo)); + $this->add(new ListFilesCommand($this->toolInfo)); $this->add(new SelfUpdateCommand( new NewVersionChecker(new GithubClient()), $this->toolInfo, diff --git a/src/Console/Command/ListFilesCommand.php b/src/Console/Command/ListFilesCommand.php new file mode 100644 index 00000000000..4913ed18864 --- /dev/null +++ b/src/Console/Command/ListFilesCommand.php @@ -0,0 +1,96 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Command; + +use PhpCsFixer\Config; +use PhpCsFixer\ConfigInterface; +use PhpCsFixer\Console\ConfigurationResolver; +use PhpCsFixer\ToolInfoInterface; +use SplFileInfo; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Markus Staab + * + * @internal + */ +final class ListFilesCommand extends Command +{ + protected static $defaultName = 'list-files'; + + /** + * @var ConfigInterface + */ + private $defaultConfig; + + /** + * @var ToolInfoInterface + */ + private $toolInfo; + + public function __construct(ToolInfoInterface $toolInfo) + { + parent::__construct(); + + $this->defaultConfig = new Config(); + $this->toolInfo = $toolInfo; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition( + [ + new InputOption('config', '', InputOption::VALUE_REQUIRED, 'The path to a .php-cs-fixer.php file.'), + ] + ) + ->setDescription('List all files being fixed by the given config.') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $passedConfig = $input->getOption('config'); + $cwd = getcwd(); + + $resolver = new ConfigurationResolver( + $this->defaultConfig, + [ + 'config' => $passedConfig, + ], + getcwd(), + $this->toolInfo + ); + + $finder = $resolver->getFinder(); + + /** @var SplFileInfo $file */ + foreach ($finder as $file) { + if ($file->isFile()) { + $relativePath = str_replace($cwd, '.', $file->getRealPath()); + // unify directory separators across operating system + $relativePath = str_replace('/', \DIRECTORY_SEPARATOR, $relativePath); + + $output->writeln(escapeshellarg($relativePath)); + } + } + + return 0; + } +} diff --git a/tests/Console/Command/ListFilesCommandTest.php b/tests/Console/Command/ListFilesCommandTest.php new file mode 100644 index 00000000000..3b7f713949f --- /dev/null +++ b/tests/Console/Command/ListFilesCommandTest.php @@ -0,0 +1,56 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Console\Command; + +use PhpCsFixer\Console\Application; +use PhpCsFixer\Console\Command\ListFilesCommand; +use PhpCsFixer\Tests\TestCase; +use PhpCsFixer\ToolInfo; +use Symfony\Component\Console\Tester\CommandTester; + +/** + * @internal + * + * @covers \PhpCsFixer\Console\Command\ListFilesCommand + */ +final class ListFilesCommandTest extends TestCase +{ + public function testListWithConfig() + { + $commandTester = $this->doTestExecute([ + '--config' => __DIR__.'/../../Fixtures/ListFilesTest/.php-cs-fixer.php', + ]); + + $expectedPath = './tests/Fixtures/ListFilesTest/needs-fixing/needs-fixing.php'; + // make the test also work on windows + $expectedPath = str_replace('/', \DIRECTORY_SEPARATOR, $expectedPath); + + static::assertSame(escapeshellarg($expectedPath).PHP_EOL, $commandTester->getDisplay()); + } + + /** + * @return CommandTester + */ + private function doTestExecute(array $arguments) + { + $application = new Application(); + $application->add(new ListFilesCommand(new ToolInfo())); + + $command = $application->find('list-files'); + $commandTester = new CommandTester($command); + + $commandTester->execute($arguments); + + return $commandTester; + } +} diff --git a/tests/Fixtures/ListFilesTest/.php-cs-fixer.php b/tests/Fixtures/ListFilesTest/.php-cs-fixer.php new file mode 100644 index 00000000000..60058c0fb71 --- /dev/null +++ b/tests/Fixtures/ListFilesTest/.php-cs-fixer.php @@ -0,0 +1,20 @@ +in([ + __DIR__.'/needs-fixing/', + ]) + ->exclude([ + __DIR__.'/excluded/', + ]) +; + +$config = new PhpCsFixer\Config(); +return $config + ->setUsingCache(false) + ->setRules([ + '@Symfony' => true, + ]) + ->setRiskyAllowed(true) + ->setFinder($finder) + ; diff --git a/tests/Fixtures/ListFilesTest/excluded/needs-fixing.php b/tests/Fixtures/ListFilesTest/excluded/needs-fixing.php new file mode 100644 index 00000000000..b26f1e37b13 --- /dev/null +++ b/tests/Fixtures/ListFilesTest/excluded/needs-fixing.php @@ -0,0 +1,8 @@ +