1
0
mirror of https://github.com/php/pie.git synced 2026-03-23 23:12:17 +01:00

Add basic ability to pie install non-interactively

This commit is contained in:
James Titcumb
2025-09-11 15:03:27 +01:00
parent 8288fd6ed6
commit 4add071f86
2 changed files with 70 additions and 27 deletions

View File

@@ -51,14 +51,15 @@ use const PHP_VERSION;
/** @internal This is not public API for PIE, so should not be depended upon unless you accept the risk of BC breaks */
final class CommandHelper
{
public const ARG_REQUESTED_PACKAGE_AND_VERSION = 'requested-package-and-version';
public const OPTION_WITH_PHP_CONFIG = 'with-php-config';
public const OPTION_WITH_PHP_PATH = 'with-php-path';
public const OPTION_WITH_PHPIZE_PATH = 'with-phpize-path';
public const OPTION_WORKING_DIRECTORY = 'working-dir';
private const OPTION_MAKE_PARALLEL_JOBS = 'make-parallel-jobs';
private const OPTION_SKIP_ENABLE_EXTENSION = 'skip-enable-extension';
private const OPTION_FORCE = 'force';
public const ARG_REQUESTED_PACKAGE_AND_VERSION = 'requested-package-and-version';
public const OPTION_WITH_PHP_CONFIG = 'with-php-config';
public const OPTION_WITH_PHP_PATH = 'with-php-path';
public const OPTION_WITH_PHPIZE_PATH = 'with-phpize-path';
public const OPTION_WORKING_DIRECTORY = 'working-dir';
public const OPTION_ALLOW_NON_INTERACTIVE_PROJECT_INSTALL = 'allow-non-interactive-project-install';
private const OPTION_MAKE_PARALLEL_JOBS = 'make-parallel-jobs';
private const OPTION_SKIP_ENABLE_EXTENSION = 'skip-enable-extension';
private const OPTION_FORCE = 'force';
/** @psalm-suppress UnusedConstructor */
private function __construct()
@@ -125,6 +126,13 @@ final class CommandHelper
self::configurePhpConfigOptions($command);
$command->addOption(
self::OPTION_ALLOW_NON_INTERACTIVE_PROJECT_INSTALL,
null,
InputOption::VALUE_NONE,
'When installing a PHP project, allow non-interactive project installations. Only used in certain contexts.',
);
/**
* Allows additional options for the `./configure` command to be passed here.
* Note, this means you probably need to call {@see self::validateInput()} to validate the input manually...

View File

@@ -17,6 +17,7 @@ use Php\Pie\Installing\InstallForPhpProject\DetermineExtensionsRequired;
use Php\Pie\Installing\InstallForPhpProject\FindMatchingPackages;
use Php\Pie\Installing\InstallForPhpProject\InstallPiePackageFromPath;
use Php\Pie\Installing\InstallForPhpProject\InstallSelectedPackage;
use Php\Pie\Platform;
use Php\Pie\Platform\InstalledPiePackages;
use Php\Pie\Util\Emoji;
use Psr\Container\ContainerInterface;
@@ -24,6 +25,7 @@ use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\OutputInterface;
@@ -123,6 +125,17 @@ final class InstallExtensionsForProjectCommand extends Command
return $exit;
}
$allowNonInteractive = $input->hasOption(CommandHelper::OPTION_ALLOW_NON_INTERACTIVE_PROJECT_INSTALL) && $input->getOption(CommandHelper::OPTION_ALLOW_NON_INTERACTIVE_PROJECT_INSTALL);
if (! Platform::isInteractive() && ! $allowNonInteractive) {
$output->writeln(sprintf(
'<warning>Aborting! You are not running in interactive mode, and --%s was not specified.</warning>',
CommandHelper::OPTION_ALLOW_NON_INTERACTIVE_PROJECT_INSTALL,
));
// @todo more details
return Command::FAILURE;
}
$targetPlatform = CommandHelper::determineTargetPlatformFromInputs($input, $output);
$output->writeln(sprintf(
@@ -221,37 +234,59 @@ final class InstallExtensionsForProjectCommand extends Command
return;
}
$choiceQuestion = new ChoiceQuestion(
"\nThe following packages may be suitable, which would you like to install: ",
array_merge(
['None'],
array_map(
static function (array $match): string {
return sprintf('%s: %s', $match['name'], $match['description'] ?? 'no description available');
},
$matches,
),
),
0,
);
$selectedPackageAnswer = (string) $helper->ask($input, $output, $choiceQuestion);
if ($selectedPackageAnswer === 'None') {
$output->writeln('Okay I won\'t install anything for ' . $extension->name());
if (! Platform::isInteractive() && count($matches) > 1) {
$anyErrorsHappened = true;
// @todo Figure out if there is a way to improve this, safely
$output->writeln(sprintf(
"<warning>Multiple packages were found for %s:</warning>\n %s\n\n<warning>This means you cannot `pie install` this project interactively for now.</warning>",
$extension->nameWithExtPrefix(),
implode("\n ", array_column($matches, 'name')),
));
return;
}
if (Platform::isInteractive()) {
$choiceQuestion = new ChoiceQuestion(
"\nThe following packages may be suitable, which would you like to install: ",
array_merge(
['None'],
array_map(
static function (array $match): string {
return sprintf('%s: %s', $match['name'], $match['description'] ?? 'no description available');
},
$matches,
),
),
0,
);
$selectedPackageAnswer = (string) $helper->ask($input, $output, $choiceQuestion);
if ($selectedPackageAnswer === 'None') {
$output->writeln('Okay I won\'t install anything for ' . $extension->name());
$anyErrorsHappened = true;
return;
}
$selectedPackageName = substr($selectedPackageAnswer, 0, (int) strpos($selectedPackageAnswer, ':'));
} else {
$selectedPackageName = $matches[0]['name'];
}
$requestInstallConstraint = '';
if ($linkRequiresConstraint !== '*') {
$requestInstallConstraint = ':' . $linkRequiresConstraint;
}
try {
$output->writeln(
sprintf('Invoking pie install of %s%s', $selectedPackageName, $requestInstallConstraint),
OutputInterface::VERBOSITY_VERBOSE,
);
$this->installSelectedPackage->withPieCli(
substr($selectedPackageAnswer, 0, (int) strpos($selectedPackageAnswer, ':')) . $requestInstallConstraint,
$selectedPackageName . $requestInstallConstraint,
$input,
$output,
);