Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/wiki
Submodule wiki updated from f1a8bc to 4782e8
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Changelog

All notable changes to this project will be documented in this file.
Expand All @@ -7,6 +7,10 @@

## [Unreleased]

### Fixed

- Show the DevTools ASCII logo by default on all top-level command executions, while adding a `--no-logo` global option and automatically suppressing the banner for `--json` / `--pretty-json` invocations (including automatic forwarding of `--no-logo` to internal DevTools subprocesses) to avoid banner repetition in orchestrated command queues (#277)

### Added

- Add a configurable DevTools generated artifact workspace through `--workspace-dir` and `FAST_FORWARD_WORKSPACE_DIR`, keeping explicit output/cache command options authoritative (#274)
Expand Down
65 changes: 53 additions & 12 deletions src/Console/DevTools.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,19 @@
*/
final class DevTools extends Application
{
private const array RAW_OUTPUT_COMMANDS = [
'changelog:next-version',
'changelog:show',
];

private const string LOGO = <<<'LOGO'
____ _____ _
| _ \ _____ _|_ _|__ ___ | |___
| | | |/ _ \ \ / / | |/ _ \ / _ \| / __|
| |_| | __/\ V / | | (_) | (_) | \__ \
|____/ \___| \_/ |_|\___/ \___/|_|___/
========================================

LOGO;

/**
Expand Down Expand Up @@ -87,17 +94,6 @@ public function __construct(
$this->setCommandLoader($commandLoader);
}

/**
* Gets the help message for the DevTools application, including the ASCII logo.
*
* @return string
*/
#[Override]
public function getHelp(): string
{
return self::LOGO . "\n\n" . parent::getHelp();
}

/**
* Returns the application-level input definition with DevTools runtime options.
*
Expand Down Expand Up @@ -128,6 +124,12 @@ protected function getDefaultInputDefinition(): InputDefinition
description: 'Store generated DevTools artifacts in the given directory.',
));

$definition->addOption(new InputOption(
name: 'no-logo',
mode: InputOption::VALUE_NONE,
description: 'Hide the startup ASCII logo.',
));

return $definition;
}

Expand All @@ -142,6 +144,12 @@ protected function getDefaultInputDefinition(): InputDefinition
#[Override]
public function doRun(InputInterface $input, OutputInterface $output): int
{
$shouldRenderLogo = $this->shouldRenderLogo($input);

if ($shouldRenderLogo) {
$output->writeln(self::LOGO);
}

try {
$this->workingDirectorySwitcher->switchTo($this->getWorkingDirectoryOption($input));
$this->configureWorkspaceDirectory($input);
Expand All @@ -151,7 +159,7 @@ public function doRun(InputInterface $input, OutputInterface $output): int
return Command::FAILURE;
}

if (! $this->isSelfUpdateCommand($input)) {
if ($shouldRenderLogo && ! $this->isSelfUpdateCommand($input)) {
$this->runAutoUpdateWhenRequested($input, $output);
$this->versionCheckNotifier->notify($output);
}
Expand Down Expand Up @@ -248,6 +256,39 @@ private function isSelfUpdateCommand(InputInterface $input): bool
return \in_array($input->getFirstArgument(), SelfUpdateCommand::getCommandNames(), true);
}

/**
* Whether to show the startup ASCII logo for this invocation.
*
* @param InputInterface $input
*/
private function shouldRenderLogo(InputInterface $input): bool
{
return ! $this->isLogoSuppressedByOptions($input)
&& ! $this->isRawOutputCommand($input);
}

/**
* Detects CLI flags that explicitly suppress logo output.
*
* @param InputInterface $input
*/
private function isLogoSuppressedByOptions(InputInterface $input): bool
{
return (bool) $input->getParameterOption('--no-logo', null, true)
|| (bool) $input->hasParameterOption('--json', true)
|| (bool) $input->hasParameterOption('--pretty-json', true);
}

/**
* Identifies commands that must keep CLI output unprefixed by logos.
*
* @param InputInterface $input
*/
private function isRawOutputCommand(InputInterface $input): bool
{
return \in_array((string) $input->getFirstArgument(), self::RAW_OUTPUT_COMMANDS, true);
}

/**
* Interprets environment values that enable auto-update.
*
Expand Down
46 changes: 46 additions & 0 deletions src/Process/ProcessBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

namespace FastForward\DevTools\Process;

use FastForward\DevTools\Path\DevToolsPathResolver;
use Symfony\Component\Process\Process;

/**
Expand All @@ -31,6 +32,8 @@
*/
final readonly class ProcessBuilder implements ProcessBuilderInterface
{
private const string NO_LOGO_ARGUMENT = '--no-logo';

/**
* Creates a new immutable process builder instance.
*
Expand Down Expand Up @@ -94,10 +97,53 @@ public function getArguments(): array
*/
public function build(string|array $command): Process
{
if (\is_array($command)) {
$command = array_values($command);
}

if (\is_string($command)) {
$command = explode(' ', $command);
}

if ($this->shouldAddLogoSuppressionArgument($command)) {
$command = $this->prependLogoSuppressionArgument($command);
}

return new Process(command: [...$command, ...$this->arguments], timeout: 0);
}

/**
* @param list<string> $command
*/
private function shouldAddLogoSuppressionArgument(array $command): bool
{
if (\in_array(self::NO_LOGO_ARGUMENT, $this->arguments, true)) {
return false;
}

if ([] === $command) {
return false;
}

$binary = str_replace('\\', '/', $command[0]);
$packageBinaryPath = str_replace('\\', '/', DevToolsPathResolver::getBinaryPath());

return $binary === $packageBinaryPath;
}

/**
* @param list<string> $command
*
* @return list<string>
*/
private function prependLogoSuppressionArgument(array $command): array
{
if ([] === $command) {
return $command;
}

$binary = array_shift($command);

return [$binary, self::NO_LOGO_ARGUMENT, ...$command];
}
}
2 changes: 2 additions & 0 deletions tests/Console/Command/DependenciesCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use FastForward\DevTools\Console\Command\DependenciesCommand;
use FastForward\DevTools\Console\Command\Traits\LogsCommandResults;
use FastForward\DevTools\Config\ComposerDependencyAnalyserConfig;
use FastForward\DevTools\Path\DevToolsPathResolver;
use FastForward\DevTools\Process\ProcessBuilder;
use FastForward\DevTools\Process\ProcessBuilderInterface;
use FastForward\DevTools\Process\ProcessQueueInterface;
Expand All @@ -42,6 +43,7 @@
use Symfony\Component\Process\Process;

#[CoversClass(DependenciesCommand::class)]
#[UsesClass(DevToolsPathResolver::class)]
#[UsesClass(ProcessBuilder::class)]
#[UsesTrait(LogsCommandResults::class)]
final class DependenciesCommandTest extends TestCase
Expand Down
2 changes: 2 additions & 0 deletions tests/Console/Command/TestsCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use FastForward\DevTools\Process\ProcessBuilder;
use FastForward\DevTools\Process\ProcessQueueInterface;
use FastForward\DevTools\Path\ManagedWorkspace;
use FastForward\DevTools\Path\DevToolsPathResolver;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\UsesClass;
Expand All @@ -48,6 +49,7 @@

#[CoversClass(TestsCommand::class)]
#[UsesClass(CoverageSummary::class)]
#[UsesClass(DevToolsPathResolver::class)]
#[UsesClass(ProcessBuilder::class)]
#[UsesClass(ManagedWorkspace::class)]
#[UsesTrait(LogsCommandResults::class)]
Expand Down
Loading
Loading