Merge remote-tracking branch 'SofHad/update-interactive'
commit
721acf3c93
|
@ -12,13 +12,17 @@
|
||||||
|
|
||||||
namespace Composer\Command;
|
namespace Composer\Command;
|
||||||
|
|
||||||
|
use Composer\Composer;
|
||||||
use Composer\Installer;
|
use Composer\Installer;
|
||||||
use Composer\Plugin\CommandEvent;
|
use Composer\Plugin\CommandEvent;
|
||||||
use Composer\Plugin\PluginEvents;
|
use Composer\Plugin\PluginEvents;
|
||||||
|
use Symfony\Component\Console\Helper\Table;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||||
|
use Symfony\Component\Console\Question\Question;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
@ -51,6 +55,7 @@ class UpdateCommand extends Command
|
||||||
new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
|
new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
|
||||||
new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
|
new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
|
||||||
new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
|
new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
|
||||||
|
new InputOption('interactive', 'i', InputOption::VALUE_NONE, 'interactive interface with autocompletion that can help to select the packages to update.'),
|
||||||
))
|
))
|
||||||
->setHelp(<<<EOT
|
->setHelp(<<<EOT
|
||||||
The <info>update</info> command reads the composer.json file from the
|
The <info>update</info> command reads the composer.json file from the
|
||||||
|
@ -86,6 +91,13 @@ EOT
|
||||||
}
|
}
|
||||||
|
|
||||||
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
|
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
|
||||||
|
|
||||||
|
$packages = $input->getArgument('packages');
|
||||||
|
|
||||||
|
if ($input->getOption('interactive')) {
|
||||||
|
$packages = $this->getPackagesInteractively($input, $output, $composer, $packages);
|
||||||
|
}
|
||||||
|
|
||||||
$composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
|
$composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
|
||||||
|
|
||||||
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
|
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
|
||||||
|
@ -129,7 +141,7 @@ EOT
|
||||||
->setOptimizeAutoloader($optimize)
|
->setOptimizeAutoloader($optimize)
|
||||||
->setClassMapAuthoritative($authoritative)
|
->setClassMapAuthoritative($authoritative)
|
||||||
->setUpdate(true)
|
->setUpdate(true)
|
||||||
->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $input->getArgument('packages'))
|
->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $packages)
|
||||||
->setWhitelistDependencies($input->getOption('with-dependencies'))
|
->setWhitelistDependencies($input->getOption('with-dependencies'))
|
||||||
->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
|
->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
|
||||||
->setPreferStable($input->getOption('prefer-stable'))
|
->setPreferStable($input->getOption('prefer-stable'))
|
||||||
|
@ -142,4 +154,83 @@ EOT
|
||||||
|
|
||||||
return $install->run();
|
return $install->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getPackagesInteractively(InputInterface $input, OutputInterface $output, Composer $composer, $packages)
|
||||||
|
{
|
||||||
|
if (!$input->isInteractive()) {
|
||||||
|
throw new \InvalidArgumentException('--interactive cannot be used in non-interactive terminals.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$packagesMap = $composer->getRepositoryManager()
|
||||||
|
->getLocalRepository()->getPackages();
|
||||||
|
|
||||||
|
$requiredPackageNames = array();
|
||||||
|
foreach (
|
||||||
|
array_merge(
|
||||||
|
$composer->getPackage()->getRequires(),
|
||||||
|
$composer->getPackage()->getDevRequires()
|
||||||
|
) as $require) {
|
||||||
|
$requiredPackageNames[] = $require->getTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
$InstalledPackageNames = array();
|
||||||
|
foreach ($packagesMap as $package) {
|
||||||
|
$InstalledPackageNames[] = $package->getPrettyName();
|
||||||
|
}
|
||||||
|
|
||||||
|
$autocompleterValues = array_unique(
|
||||||
|
array_merge($InstalledPackageNames, $requiredPackageNames)
|
||||||
|
);
|
||||||
|
|
||||||
|
$helper = $this->getHelper('question');
|
||||||
|
$question = new Question(
|
||||||
|
'<comment>Enter package name: </comment>',
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
$packages = is_array($packages) ? $packages : array();
|
||||||
|
$output->writeln('<info>NB: Empty package ends submission.</info>'); // I couldn't find any better for now!
|
||||||
|
|
||||||
|
do {
|
||||||
|
$question->setAutocompleterValues($autocompleterValues);
|
||||||
|
$addedPackage = $helper->ask($input, $output, $question);
|
||||||
|
|
||||||
|
if (!is_string($addedPackage)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_array($addedPackage, $packages)) {
|
||||||
|
$packages[] = $addedPackage;
|
||||||
|
$autocompleterValues = array_diff($autocompleterValues, array($addedPackage));
|
||||||
|
} else {
|
||||||
|
$output->writeln(sprintf('<error>The package "%s" was already added.</error>', $package));
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
$packages = array_filter($packages);
|
||||||
|
if (!$packages) {
|
||||||
|
throw new \InvalidArgumentException('You must enter minimum one package.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = new Table($output);
|
||||||
|
$table->setHeaders(array('Selected packages'));
|
||||||
|
foreach ((array)$packages as $package) {
|
||||||
|
$table->addRow(array($package));
|
||||||
|
}
|
||||||
|
$table->render();
|
||||||
|
|
||||||
|
$continue = new ConfirmationQuestion(
|
||||||
|
sprintf(
|
||||||
|
'<question>Would you like to continue and update the above package%s [yes|no] ?</question><info> (yes) </info>',
|
||||||
|
1 === count($packages) ? '' : 's'
|
||||||
|
),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($helper->ask($input, $output, $continue)) {
|
||||||
|
return $packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \RuntimeException('Installation aborted.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue