diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index e832b1fd0..f45a4b3b3 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -15,6 +15,7 @@ namespace Composer\Command; use Composer\Installer; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Output\OutputInterface; /** @@ -28,6 +29,7 @@ class UpdateCommand extends Command ->setName('update') ->setDescription('Updates your dependencies to the latest version, and updates the composer.lock file.') ->setDefinition(array( + new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be updated, if not provided all packages are.'), new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'), new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of dev-require packages.'), @@ -58,6 +60,7 @@ EOT ->setDevMode($input->getOption('dev')) ->setRunScripts(!$input->getOption('no-scripts')) ->setUpdate(true) + ->setUpdateWhitelist($input->getArgument('packages')) ; return $install->run() ? 0 : 1; diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index f4f6777b3..77542284e 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -89,6 +89,7 @@ class Installer protected $verbose = false; protected $update = false; protected $runScripts = true; + protected $updateWhitelist = null; /** * @var array @@ -275,8 +276,13 @@ class Installer // fix the version of all installed packages (+ platform) that are not // in the current local repo to prevent rogue updates (e.g. non-dev // updating when in dev) + // + // if the updateWhitelist is enabled, packages not in it are also fixed + // to their currently installed version foreach ($installedRepo->getPackages() as $package) { - if ($package->getRepository() === $localRepo) { + if ($package->getRepository() === $localRepo + && (!$this->updateWhitelist || in_array($package->getName(), $this->updateWhitelist)) + ) { continue; } @@ -331,6 +337,11 @@ class Installer } else { // force update to latest on update if ($this->update) { + // skip package is the whitelist is enabled and it is not in it + if ($this->updateWhitelist && !in_array($package->getName(), $this->updateWhitelist)) { + continue; + } + $newPackage = $this->repositoryManager->findPackage($package->getName(), $package->getVersion()); if ($newPackage && $newPackage->getSourceReference() !== $package->getSourceReference()) { $operations[] = new UpdateOperation($package, $newPackage); @@ -551,4 +562,18 @@ class Installer return $this; } + + /** + * restrict the update operation to a few packages, all other packages + * that are already installed will be kept at their current version + * + * @param array $packages + * @return Installer + */ + public function setUpdateWhitelist(array $packages) + { + $this->updateWhitelist = array_map('strtolower', $packages); + + return $this; + } }