From 0ac7d82e740f11dd7aadf07957e574336c423d84 Mon Sep 17 00:00:00 2001 From: Jerry Radwick Date: Thu, 26 Dec 2024 20:49:50 -0500 Subject: [PATCH] Remove prefix from --drall-verbose and --drall-debug --- README.md | 8 +- src/Command/ExecCommand.php | 79 +++++------- src/Drall.php | 26 ++-- src/Model/RawCommand.php | 39 ------ test/Integration/Command/ExecCommandTest.php | 120 ++++++++++++------- test/Unit/DrallTest.php | 8 +- 6 files changed, 126 insertions(+), 154 deletions(-) delete mode 100644 src/Model/RawCommand.php diff --git a/README.md b/README.md index bfd512f..07e1c46 100644 --- a/README.md +++ b/README.md @@ -344,13 +344,13 @@ drall exec --drall-filter="leo||ralph" core:status For more on using filter expressions, refer to the documentation on [consolidation/filter-via-dot-access-data](https://github.com/consolidation/filter-via-dot-access-data). -### --drall-verbose +### --verbose -Whether Drall should display verbose output. +Display verbose output. -### --drall-debug +### --debug -Whether Drall should display debugging output. +Display debug-level output. ## Auto-detect sites diff --git a/src/Command/ExecCommand.php b/src/Command/ExecCommand.php index 5d19bce..6e81d03 100644 --- a/src/Command/ExecCommand.php +++ b/src/Command/ExecCommand.php @@ -11,7 +11,6 @@ use Drall\Drall; use Drall\Model\EnvironmentId; use Drall\Model\Placeholder; -use Drall\Model\RawCommand; use Drall\Trait\SignalAwareTrait; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputArgument; @@ -91,41 +90,10 @@ protected function configure() { $this->ignoreValidationErrors(); } - /** - * Sets an array to be treated as $argv, mostly for testing. - * - * The $argv array contains: - * - Script name as the first parameter, i.e. drall. - * - The Drall command as the second parameter, e.g. exec. - * - Options for the Drall command, e.g. --drall-group=bluish. - * - The Drush command and its arguments, e.g. pmu devel - * - Options for the Drush command, e.g. --fields=site. - * - * @code - * $command->setArgv([ - * '/opt/drall/bin/drall', - * 'exec', - * '--drall-group=bluish', - * 'core:status', - * '--fields=site', - * ]); - * @endcode - * - * @param array $argv - * An array matching the $argv array format. - * - * @return self - * The command. - */ - public function setArgv(array $argv): self { - $this->argv = $argv; - return $this; - } - protected function execute(InputInterface $input, OutputInterface $output): int { $this->preExecute($input, $output); - $command = $this->getCommand(); + $command = $this->getCommand($input); $group = $this->getDrallGroup($input); $filter = $this->getDrallFilter($input); @@ -235,22 +203,35 @@ function ($value) use ($command, $placeholder, $output, $progressBar, &$exitCode return $exitCode; } - protected function getCommand(): RawCommand { - // Symfony Console only recognizes options that are defined in the - // ::configure() method. Since our goal is to catch all arguments and - // options and send them to drush, we do it ourselves using $argv. - // - // @todo Is there a way to catch all options from $input? - $command = RawCommand::fromArgv($this->argv); - - if (!str_contains($command, 'drush')) { - return $command; - } + /** + * Extracts the command to be executed by Drall. + * + * All drall-specific components are removed from the command. + * + * @param \Symfony\Component\Console\Input\InputInterface $input + * Console input. + * + * @return string + * The command without Drall elements. + * + * @example + * Input: /path/to/drall exec --verbose -- drush st --fields=site + * Output: drush st --fields=site + */ + protected function getCommand(InputInterface $input): string { + // @todo Force -- for clarity if options are present. + // @todo Throw an error if --drall-* options are present. + // Everything after the first "--" is treated as an argument. All such + // arguments are treated as parts of the command to be executed. + $command = implode(' ', $input->getArguments()['cmd']); + $this->logger->debug("Command: {command}", ['command' => $command]); - // Inject --uri=@@dir for Drush commands without placeholders. - if (!Placeholder::search($command)) { - $sCommand = preg_replace('/\b(drush) /', 'drush --uri=@@dir ', $command, -1); - $command = new RawCommand($sCommand); + if ( + str_contains($command, 'drush') && + !Placeholder::search($command) + ) { + // Inject --uri=@@dir for Drush commands without placeholders. + $command = preg_replace('/\b(drush) /', 'drush --uri=@@dir ', $command, -1); $this->logger->debug('Injected --uri parameter for Drush command.'); } @@ -284,7 +265,7 @@ protected function getWorkerCount(InputInterface $input): int { /** * Get unique placeholder from a command. */ - private function getUniquePlaceholder(RawCommand $command): ?Placeholder { + private function getUniquePlaceholder(string $command): ?Placeholder { if (!$placeholders = Placeholder::search($command)) { $this->logger->error('The command contains no placeholders. Please run it directly without Drall.'); return NULL; diff --git a/src/Drall.php b/src/Drall.php index 4e04b78..b046b77 100644 --- a/src/Drall.php +++ b/src/Drall.php @@ -42,15 +42,25 @@ public function __construct() { protected function configureIO(InputInterface $input, OutputInterface $output): void { parent::configureIO($input, $output); - if ($input->hasParameterOption('--drall-debug', TRUE)) { + if ($input->hasParameterOption('--debug', TRUE)) { $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); } - elseif ($input->hasParameterOption('--drall-verbose', TRUE)) { + elseif ($input->hasParameterOption('--verbose', TRUE)) { $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); } else { $output->setVerbosity(OutputInterface::VERBOSITY_NORMAL); } + + // The parent::configureIO sets verbosity in a SHELL_VERBOSITY. This causes + // other Symfony Console apps to become verbose, for example, Drush. To + // prevent such behavior, we force the SHELL_VERBOSITY to be normal. + $shellVerbosity = 0; + if (\function_exists('putenv')) { + @putenv("SHELL_VERBOSITY=$shellVerbosity"); + } + $_ENV['SHELL_VERBOSITY'] = $shellVerbosity; + $_SERVER['SHELL_VERBOSITY'] = $shellVerbosity; } protected function getDefaultInputDefinition(): InputDefinition { @@ -58,18 +68,12 @@ protected function getDefaultInputDefinition(): InputDefinition { // Remove unneeded options. $options = $definition->getOptions(); - unset($options['verbose'], $options['quiet']); + unset($options['quiet']); $definition->setOptions($options); $definition->addOption(new InputOption( - 'drall-verbose', - NULL, - InputOption::VALUE_NONE, - 'Display verbose output for Drall.' - )); - $definition->addOption(new InputOption( - 'drall-debug', - NULL, + 'debug', + 'd', InputOption::VALUE_NONE, 'Display debugging output for Drall.' )); diff --git a/src/Model/RawCommand.php b/src/Model/RawCommand.php deleted file mode 100644 index a05cdaa..0000000 --- a/src/Model/RawCommand.php +++ /dev/null @@ -1,39 +0,0 @@ -command = $command; - } - - public function __toString() { - return $this->command; - } - - /** - * Extracts a Drall sub-command from $argv, ignoring parts that are only for Drall. - * - * @param array $argv - * An $argv array. - * - * @return self - * The command without Drall elements. - * - * @example - * Input: ['/path/to/drall', 'exs', 'drush', '--drall-option=foo', 'st', '--fields=site'] - * Output: 'drush st --fields=site' - */ - public static function fromArgv(array $argv): self { - // Ignore the script name and the word "exec". - $parts = array_slice($argv, 2); - // Ignore options with --drall namespace. - $parts = array_filter($parts, fn($w) => !str_starts_with($w, '--drall-')); - - return new RawCommand(implode(' ', $parts)); - } - -} diff --git a/test/Integration/Command/ExecCommandTest.php b/test/Integration/Command/ExecCommandTest.php index 58f1585..0a076e0 100644 --- a/test/Integration/Command/ExecCommandTest.php +++ b/test/Integration/Command/ExecCommandTest.php @@ -11,12 +11,38 @@ */ class ExecCommandTest extends TestCase { + /** + * @testdox Detects commands correctly. + */ + public function testCommandDetection() { + $process = Process::fromShellCommandline( + 'drall exec --debug --drall-no-execute drush st', + static::PATH_DRUPAL, + ); + $process->run(); + $this->assertEquals(<<getOutput()); + } + /** * @testdox With no Drupal installation. */ public function testWithNoDrupal(): void { $process = Process::fromShellCommandline( - 'drall exec ./vendor/bin/drush --uri=@@dir core:status', + 'drall exec -- ./vendor/bin/drush --uri=@@dir core:status', static::PATH_NO_DRUPAL, ); $process->run(); @@ -35,7 +61,7 @@ public function testWithNoDrupal(): void { */ public function testWithEmptyDrupal(): void { $process = Process::fromShellCommandline( - 'drall exec ./vendor/bin/drush --uri=@@dir core:status', + 'drall exec -- ./vendor/bin/drush --uri=@@dir core:status', static::PATH_EMPTY_DRUPAL, ); $process->run(); @@ -50,9 +76,9 @@ public function testWithEmptyDrupal(): void { } /** - * @testdox With no placeholders. + * @testdox Raises error for non-Drush command with no placeholders. */ - public function testWithNoPlaceholders(): void { + public function testNonDrushWithNoPlaceholders(): void { $process = Process::fromShellCommandline('drall exec foo', static::PATH_DRUPAL); $process->run(); $this->assertOutputEquals( @@ -83,21 +109,21 @@ public function testWorkingDirectory(): void { */ public function testDrushWithUriPlaceholder(): void { $process = Process::fromShellCommandline( - 'drall exec ./vendor/bin/drush --uri=@@dir core:status --fields=site', + 'drall exec -- ./vendor/bin/drush --uri=@@dir core:status --field=site', static::PATH_DRUPAL, ); $process->run(); $this->assertOutputEquals(<<getOutput()); } @@ -107,45 +133,45 @@ public function testDrushWithUriPlaceholder(): void { */ public function testDrushWithSitePlaceholder(): void { $process = Process::fromShellCommandline( - 'drall exec ./vendor/bin/drush @@site.local core:status --fields=site', + 'drall exec ./vendor/bin/drush -- @@site.local core:status --field=site', static::PATH_DRUPAL, ); $process->run(); $this->assertOutputEquals(<<getOutput()); } /** - * @testdox With no placeholders. + * @testdox Injects --uri for Drush command with no placeholders. */ public function testDrushWithNoPlaceholders(): void { $process = Process::fromShellCommandline( - 'drall exec ./vendor/bin/drush core:status --fields=site', + 'drall exec -- ./vendor/bin/drush core:status --field=site', static::PATH_DRUPAL, ); $process->run(); $this->assertOutputEquals(<<getOutput()); } @@ -270,7 +296,7 @@ public function testWithDirPlaceholder(): void { */ public function testWithFilter(): void { $process = Process::fromShellCommandline( - 'drall exec --drall-filter=leo ./vendor/bin/drush st --field=site', + 'drall exec --drall-filter=leo -- ./vendor/bin/drush st --field=site', static::PATH_DRUPAL, ); $process->run(); @@ -282,15 +308,16 @@ public function testWithFilter(): void { } /** - * @testdox With @@dir placeholder and --drall-debug. + * @testdox With @@dir placeholder and --debug. */ public function testWithDirPlaceholderAndDebug(): void { $process = Process::fromShellCommandline( - 'drall exec --drall-debug ls web/sites/@@dir/settings.php', + 'drall exec --debug ls web/sites/@@dir/settings.php', static::PATH_DRUPAL, ); $process->run(); $this->assertOutputEquals(<<run(); @@ -333,7 +360,7 @@ public function testWithGroup(): void { */ public function testWithGroupEnvVar(): void { $process = Process::fromShellCommandline( - 'drall exec ./vendor/bin/drush st --field=site', + 'drall exec -- ./vendor/bin/drush st --field=site', static::PATH_DRUPAL, ['DRALL_GROUP' => 'bluish'], ); @@ -352,7 +379,7 @@ public function testWithGroupEnvVar(): void { */ public function testWithSitePlaceholder(): void { $process = Process::fromShellCommandline( - 'drall exec ./vendor/bin/drush @@site.local core:status --fields=site', + 'drall exec ./vendor/bin/drush -- @@site.local core:status --fields=site', static::PATH_DRUPAL, ); $process->run(); @@ -372,15 +399,16 @@ public function testWithSitePlaceholder(): void { } /** - * @testdox With @@site placeholder and --drall-debug. + * @testdox With @@site placeholder and --debug. */ public function testWithSitePlaceholderDebug(): void { $process = Process::fromShellCommandline( - 'drall exec --drall-debug ./vendor/bin/drush @@site.local st --fields=site', + 'drall exec --debug -- ./vendor/bin/drush @@site.local st --fields=site', static::PATH_DRUPAL, ); $process->run(); $this->assertOutputEquals(<<run(); $this->assertOutputEquals(<<getOutput()); } @@ -423,7 +451,7 @@ public function testWithSitePlaceholderAndGroup(): void { */ public function testCatchStdErrOutput(): void { $process = Process::fromShellCommandline( - 'drall exec --drall-filter=default ./vendor/bin/drush --verbose version', + 'drall exec --drall-filter=default -- ./vendor/bin/drush --verbose version', static::PATH_DRUPAL, ); $process->run(); @@ -446,7 +474,7 @@ public function testCatchStdErrOutput(): void { */ public function testWithProgressBarVisible(): void { $process = Process::fromShellCommandline( - 'drall exec ./vendor/bin/drush st --field=site 2>&1', + 'drall exec -- ./vendor/bin/drush st --field=site 2>&1', static::PATH_DRUPAL, ['DRALL_ENVIRONMENT' => 'unknown'], ); @@ -472,7 +500,7 @@ public function testWithProgressBarVisible(): void { */ public function testWithProgressBarHidden(): void { $process = Process::fromShellCommandline( - 'drall exec --drall-no-progress ./vendor/bin/drush st --field=site 2>&1', + 'drall exec --drall-no-progress -- ./vendor/bin/drush st --field=site 2>&1', static::PATH_DRUPAL, // The progress bar is always hidden in the "test" environment to avoid // repeating --no-progress in all commands. Thus, for this test, @@ -516,25 +544,25 @@ public function testWithNoExecute(): void { } /** - * @testdox With --drall-no-execute --drall-verbose. + * @testdox With --drall-no-execute --verbose. */ public function testWithNoExecuteVerbose(): void { $process = Process::fromShellCommandline( - 'drall exec --drall-no-execute --drall-verbose drush core:status', + 'drall exec --drall-no-execute --verbose -- drush st', static::PATH_DRUPAL, ); $process->run(); $this->assertOutputEquals(<<getOutput()); } @@ -544,7 +572,7 @@ public function testWithNoExecuteVerbose(): void { */ public function testWithWorkers(): void { $process = Process::fromShellCommandline( - 'drall ex --drall-workers=2 --drall-verbose drush --uri=@@dir core:status --fields=site', + 'drall ex --drall-workers=2 --verbose -- drush --uri=@@dir core:status --fields=site', static::PATH_DRUPAL, ); $process->run(); @@ -562,7 +590,7 @@ public function testWithWorkers(): void { */ public function testWorkerLimit(): void { $process = Process::fromShellCommandline( - 'drall ex --drall-workers=17 --drall-verbose drush --uri=@@dir st --fields=site', + 'drall ex --drall-workers=17 --verbose -- drush --uri=@@dir st --fields=site', static::PATH_DRUPAL, ); $process->run(); diff --git a/test/Unit/DrallTest.php b/test/Unit/DrallTest.php index c068bfc..a616cba 100644 --- a/test/Unit/DrallTest.php +++ b/test/Unit/DrallTest.php @@ -22,9 +22,7 @@ public function testDefaultInputOptions() { $options = $app->getDefinition()->getOptions(); $this->assertArrayNotHasKey('quiet', $options); - $this->assertArrayNotHasKey('verbose', $options); - $this->assertArrayHasKey('drall-verbose', $options); - $this->assertArrayHasKey('drall-debug', $options); + $this->assertArrayHasKey('debug', $options); } public function testOptionVerbosityNormal() { @@ -35,13 +33,13 @@ public function testOptionVerbosityNormal() { public function testOptionVerbosityVerbose() { $tester = new ApplicationTester(new Drall()); - $tester->run(['command' => 'version', '--drall-verbose' => TRUE]); + $tester->run(['command' => 'version', '--verbose' => TRUE]); $this->assertEquals(OutputInterface::VERBOSITY_VERY_VERBOSE, $tester->getOutput()->getVerbosity()); } public function testOptionVerbosityDebug() { $tester = new ApplicationTester(new Drall()); - $tester->run(['command' => 'version', '--drall-debug' => TRUE]); + $tester->run(['command' => 'version', '--debug' => TRUE]); $this->assertEquals(OutputInterface::VERBOSITY_DEBUG, $tester->getOutput()->getVerbosity()); }