diff --git a/src/Composer/Command/RemoveCommand.php b/src/Composer/Command/RemoveCommand.php index 048baace0..ec6f64308 100644 --- a/src/Composer/Command/RemoveCommand.php +++ b/src/Composer/Command/RemoveCommand.php @@ -131,7 +131,7 @@ EOT ->setApcuAutoloader($apcu) ->setUpdate(true) ->setUpdateWhitelist($packages) - ->setWhitelistDependencies(!$input->getOption('no-update-with-dependencies')) + ->setIndirectWhitelistDependencies(!$input->getOption('no-update-with-dependencies')) ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs')) ->setRunScripts(!$input->getOption('no-scripts')) ; diff --git a/src/Composer/Command/RequireCommand.php b/src/Composer/Command/RequireCommand.php index 354c661ad..012ed354a 100644 --- a/src/Composer/Command/RequireCommand.php +++ b/src/Composer/Command/RequireCommand.php @@ -169,7 +169,8 @@ EOT ->setApcuAutoloader($apcu) ->setUpdate(true) ->setUpdateWhitelist(array_keys($requirements)) - ->setWhitelistDependencies($input->getOption('update-with-dependencies')) + ->setIndirectWhitelistDependencies($input->getOption('update-with-dependencies')) + ->setAllWhitelistDependencies($input->getOption('update-with-all-dependencies')) ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs')) ->setPreferStable($input->getOption('prefer-stable')) ->setPreferLowest($input->getOption('prefer-lowest')) diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index 9444f6f77..ac047c41a 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -48,7 +48,8 @@ class UpdateCommand extends BaseCommand new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'), - new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also all dependencies of whitelisted packages to the whitelist.'), + new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also dependencies of whitelisted packages to the whitelist, if those dependencies are not defined in root package.'), + new InputOption('with-all-dependencies', null, InputOption::VALUE_NONE, 'Add also all dependencies of whitelisted packages to the whitelist.'), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'), new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'), @@ -145,7 +146,8 @@ EOT ->setApcuAutoloader($apcu) ->setUpdate(true) ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $packages) - ->setWhitelistDependencies($input->getOption('with-dependencies')) + ->setIndirectWhitelistDependencies($input->getOption('with-dependencies')) + ->setAllWhitelistDependencies($input->getOption('with-all-dependencies')) ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs')) ->setPreferStable($input->getOption('prefer-stable')) ->setPreferLowest($input->getOption('prefer-lowest')) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 55ec51baf..932b220e2 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -126,6 +126,7 @@ class Installer */ protected $updateWhitelist = null; protected $whitelistDependencies = false; + protected $whitelistAllDependencies = false; /** * @var SuggestedPackagesReporter @@ -1351,7 +1352,7 @@ class Installer $seen[$package->getId()] = true; $this->updateWhitelist[$package->getName()] = true; - if (!$this->whitelistDependencies) { + if (!$this->whitelistDependencies && !$this->whitelistAllDependencies) { continue; } @@ -1361,7 +1362,7 @@ class Installer $requirePackages = $pool->whatProvides($require->getTarget()); foreach ($requirePackages as $requirePackage) { - if (isset($this->updateWhitelist[$requirePackage->getName()])) { + if (!$this->whitelistAllDependencies && isset($this->updateWhitelist[$requirePackage->getName()])) { continue; } @@ -1652,18 +1653,37 @@ class Installer } /** - * Should dependencies of whitelisted packages be updated recursively? + * Should indirect dependencies of whitelisted packages be updated? + * + * This will NOT whitelist any dependencies that are also directly defined + * in the root package. * * @param bool $updateDependencies * @return Installer */ - public function setWhitelistDependencies($updateDependencies = true) + public function setIndirectWhitelistDependencies($updateDependencies = true) { $this->whitelistDependencies = (bool) $updateDependencies; return $this; } + /** + * Should all dependencies of whitelisted packages be updated recursively? + * + * This will NOT whitelist any dependencies that are also defined in the + * root package. + * + * @param bool $updateAllDependencies + * @return Installer + */ + public function setAllWhitelistDependencies($updateAllDependencies = true) + { + $this->whitelistAllDependencies = (bool) $updateAllDependencies; + + return $this; + } + /** * Should packages be preferred in a stable version when updating? * diff --git a/tests/Composer/Test/Fixtures/installer/update-with-all-dependencies.test b/tests/Composer/Test/Fixtures/installer/update-with-all-dependencies.test new file mode 100644 index 000000000..7e2573f9c --- /dev/null +++ b/tests/Composer/Test/Fixtures/installer/update-with-all-dependencies.test @@ -0,0 +1,44 @@ +--TEST-- + +See Github issue #6661 ( github.com/composer/composer/issues/6661 ). + +When `with-all-dependencies` is used, Composer\Installer::whitelistUpdateDependencies should update all whitelisted dependencies, even if the dependency is a root requirement. + +--COMPOSER-- +{ + "repositories": [ + { + "type": "package", + "package": [ + { "name": "a", "version": "1.0.0" }, + { "name": "a", "version": "1.1.0" }, + { "name": "b", "version": "1.0.0", "require": { "a": "~1.0" } }, + { "name": "b", "version": "1.1.0", "require": { "a": "~1.1" } } + ] + } + ], + "require": { + "a": "~1.0", + "b": "~1.0" + } +} + +--INSTALLED-- +[ + { "name": "a", "version": "1.0.0" }, + { "name": "b", "version": "1.0.0", "require": { "a": "~1.0" } } +] + +--RUN-- +update b --with-all-dependencies + +--EXPECT-OUTPUT-- +Loading composer repositories with package information +Updating dependencies (including require-dev) +Package operations: 0 installs, 2 updates, 0 removals +Writing lock file +Generating autoload files + +--EXPECT-- +Updating a (1.0.0) to a (1.1.0) +Updating b (1.0.0) to b (1.1.0) \ No newline at end of file diff --git a/tests/Composer/Test/InstallerTest.php b/tests/Composer/Test/InstallerTest.php index adac21714..d6c0734a5 100644 --- a/tests/Composer/Test/InstallerTest.php +++ b/tests/Composer/Test/InstallerTest.php @@ -224,7 +224,8 @@ class InstallerTest extends TestCase ->setUpdate(true) ->setDryRun($input->getOption('dry-run')) ->setUpdateWhitelist($input->getArgument('packages')) - ->setWhitelistDependencies($input->getOption('with-dependencies')) + ->setIndirectWhitelistDependencies($input->getOption('with-dependencies')) + ->setAllWhitelistDependencies($input->getOption('with-all-dependencies')) ->setPreferStable($input->getOption('prefer-stable')) ->setPreferLowest($input->getOption('prefer-lowest')) ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'));