diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index a6a5dc4f7..127676d81 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -13,6 +13,7 @@ namespace Composer\Command; use Composer\Composer; +use Composer\DependencyResolver\Request; use Composer\Installer; use Composer\IO\IOInterface; use Composer\Plugin\CommandEvent; @@ -145,6 +146,13 @@ EOT $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative'); $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader'); + $updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED; + if ($input->getOption('with-all-dependencies')) { + $updateAllowTransitiveDependencies = Request::UPDATE_TRANSITIVE_ROOT_DEPENDENCIES; + } elseif ($input->getOption('with-dependencies')) { + $updateAllowTransitiveDependencies = Request::UPDATE_TRANSITIVE_DEPENDENCIES; + } + $install ->setDryRun($input->getOption('dry-run')) ->setVerbose($input->getOption('verbose')) @@ -158,9 +166,8 @@ EOT ->setApcuAutoloader($apcu) ->setUpdate(true) ->setUpdateMirrors($updateMirrors) - ->setUpdateWhitelist($packages) - ->setWhitelistTransitiveDependencies($input->getOption('with-dependencies')) - ->setWhitelistAllDependencies($input->getOption('with-all-dependencies')) + ->setUpdateAllowList($packages) + ->setUpdateAllowTransitiveDependencies($updateAllowTransitiveDependencies) ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs')) ->setPreferStable($input->getOption('prefer-stable')) ->setPreferLowest($input->getOption('prefer-lowest')) diff --git a/src/Composer/DependencyResolver/PoolBuilder.php b/src/Composer/DependencyResolver/PoolBuilder.php index 7c17ba7ee..2037a0a9d 100644 --- a/src/Composer/DependencyResolver/PoolBuilder.php +++ b/src/Composer/DependencyResolver/PoolBuilder.php @@ -12,6 +12,7 @@ namespace Composer\DependencyResolver; +use Composer\IO\IOInterface; use Composer\Package\AliasPackage; use Composer\Package\BasePackage; use Composer\Package\Package; @@ -36,32 +37,41 @@ class PoolBuilder private $rootAliases; private $rootReferences; private $eventDispatcher; + private $io; private $aliasMap = array(); private $nameConstraints = array(); private $loadedNames = array(); private $packages = array(); private $unacceptableFixedPackages = array(); + private $updateAllowList = array(); + private $skippedLoad = array(); + private $updateAllowWarned = array(); - private $unfixList = array(); - - public function __construct(array $acceptableStabilities, array $stabilityFlags, array $rootAliases, array $rootReferences, EventDispatcher $eventDispatcher = null) + public function __construct(array $acceptableStabilities, array $stabilityFlags, array $rootAliases, array $rootReferences, EventDispatcher $eventDispatcher = null, IOInterface $io = null) { $this->acceptableStabilities = $acceptableStabilities; $this->stabilityFlags = $stabilityFlags; $this->rootAliases = $rootAliases; $this->rootReferences = $rootReferences; $this->eventDispatcher = $eventDispatcher; + $this->io = $io; } public function buildPool(array $repositories, Request $request) { if ($request->getUpdateAllowList()) { - $this->unfixList = $request->getUpdateAllowList(); + $this->updateAllowList = $request->getUpdateAllowList(); + $this->warnAboutNonMatchingUpdateAllowList($request); foreach ($request->getLockedRepository()->getPackages() as $lockedPackage) { - if (!$this->isUpdateable($lockedPackage)) { + if (!$this->isUpdateAllowed($lockedPackage)) { $request->fixPackage($lockedPackage); + // remember which packages we skipped loading remote content for in this partial update + $this->skippedLoad[$lockedPackage->getName()] = true; + foreach ($lockedPackage->getReplaces() as $link) { + $this->skippedLoad[$link->getTarget()] = true; + } } } } @@ -85,7 +95,7 @@ class PoolBuilder || $package->getRepository() instanceof PlatformRepository || StabilityFilter::isPackageAcceptable($this->acceptableStabilities, $this->stabilityFlags, $package->getNames(), $package->getStability()) ) { - $loadNames += $this->loadPackage($request, $package); + $loadNames += $this->loadPackage($request, $package, false); } else { $this->unacceptableFixedPackages[] = $package; } @@ -94,6 +104,7 @@ class PoolBuilder foreach ($request->getRequires() as $packageName => $constraint) { // fixed packages have already been added, so if a root require needs one of them, no need to do anything if (isset($this->loadedNames[$packageName])) { + $this->rootRequireNotUpdated[$packageName] = true; continue; } @@ -120,7 +131,6 @@ class PoolBuilder if ($repository instanceof PlatformRepository || $repository === $request->getLockedRepository()) { continue; } - $result = $repository->loadPackages($loadNames, $this->acceptableStabilities, $this->stabilityFlags); foreach ($result['namesFound'] as $name) { @@ -189,7 +199,7 @@ class PoolBuilder return $pool; } - private function loadPackage(Request $request, PackageInterface $package) + private function loadPackage(Request $request, PackageInterface $package, $propagateUpdate = true) { $index = count($this->packages); $this->packages[] = $package; @@ -205,6 +215,7 @@ class PoolBuilder // apply to if (isset($this->rootReferences[$name])) { // do not modify the references on already locked packages + // TODO what about unfix on allow update? if (!$request->isFixedPackage($package)) { $package->setSourceDistReferences($this->rootReferences[$name]); } @@ -229,9 +240,16 @@ class PoolBuilder $require = $link->getTarget(); if (!isset($this->loadedNames[$require])) { $loadNames[$require] = null; - } - if (isset($request->getUpdateAllowList()[$package->getName()])) { - + // if this is a partial update with transitive dependencies we need to unfix the package we now know is a + // dependency of another package which we are trying to update, and then attempt to load it again + } elseif ($propagateUpdate && $request->getUpdateAllowTransitiveDependencies() && isset($this->skippedLoad[$require])) { + if ($request->getUpdateAllowTransitiveRootDependencies() || !$this->isRootRequire($request, $require)) { + $this->unfixPackage($request, $require); + $loadNames[$require] = null; + } elseif (!$request->getUpdateAllowTransitiveRootDependencies() && $this->isRootRequire($request, $require) && !isset($this->updateAllowWarned[$require]) && $this->io) { + $this->updateAllowWarned[$require] = true; + $this->io->writeError('Dependency "'.$require.'" is also a root requirement. Package has not been listed as an update argument, so keeping locked at old version. Use --with-all-dependencies to include root dependencies.'); + } } $linkConstraint = $link->getConstraint(); @@ -252,114 +270,23 @@ class PoolBuilder } /** - * Adds all dependencies of the update whitelist to the whitelist, too. + * Checks if a particular name is required directly in the request * - * Packages which are listed as requirements in the root package will be - * skipped including their dependencies, unless they are listed in the - * update whitelist themselves or $whitelistAllDependencies is true. - * - * @param RepositoryInterface $lockRepo Use the locked repo - * As we want the most accurate package list to work with, and installed - * repo might be empty but locked repo will always be current. - * @param array $rootRequires An array of links to packages in require of the root package - * @param array $rootDevRequires An array of links to packages in require-dev of the root package + * @return bool */ - private function whitelistUpdateDependencies($lockRepo, array $rootRequires, array $rootDevRequires) + private function isRootRequire(Request $request, $name) { - $rootRequires = array_merge($rootRequires, $rootDevRequires); - - $skipPackages = array(); - if (!$this->whitelistAllDependencies) { - foreach ($rootRequires as $require) { - $skipPackages[$require->getTarget()] = true; - } - } - - $installedRepo = new InstalledRepository(array($lockRepo)); - - $seen = array(); - - $rootRequiredPackageNames = array_keys($rootRequires); - - foreach ($this->updateWhitelist as $packageName => $void) { - $packageQueue = new \SplQueue; - $nameMatchesRequiredPackage = false; - - $depPackages = $installedRepo->findPackagesWithReplacersAndProviders($packageName); - $matchesByPattern = array(); - - // check if the name is a glob pattern that did not match directly - if (empty($depPackages)) { - // add any installed package matching the whitelisted name/pattern - $whitelistPatternSearchRegexp = BasePackage::packageNameToRegexp($packageName, '^%s$'); - foreach ($lockRepo->search($whitelistPatternSearchRegexp) as $installedPackage) { - $matchesByPattern[] = $installedRepo->findPackages($installedPackage['name']); - } - - // add root requirements which match the whitelisted name/pattern - $whitelistPatternRegexp = BasePackage::packageNameToRegexp($packageName); - foreach ($rootRequiredPackageNames as $rootRequiredPackageName) { - if (preg_match($whitelistPatternRegexp, $rootRequiredPackageName)) { - $nameMatchesRequiredPackage = true; - break; - } - } - } - - if (!empty($matchesByPattern)) { - $depPackages = array_merge($depPackages, call_user_func_array('array_merge', $matchesByPattern)); - } - - if (count($depPackages) == 0 && !$nameMatchesRequiredPackage) { - $this->io->writeError('Package "' . $packageName . '" listed for update is not installed. Ignoring.'); - } - - foreach ($depPackages as $depPackage) { - $packageQueue->enqueue($depPackage); - } - - while (!$packageQueue->isEmpty()) { - $package = $packageQueue->dequeue(); - if (isset($seen[spl_object_hash($package)])) { - continue; - } - - $seen[spl_object_hash($package)] = true; - $this->updateWhitelist[$package->getName()] = true; - - if (!$this->whitelistTransitiveDependencies && !$this->whitelistAllDependencies) { - continue; - } - - $requires = $package->getRequires(); - - foreach ($requires as $require) { - $requirePackages = $installedRepo->findPackagesWithReplacersAndProviders($require->getTarget()); - - foreach ($requirePackages as $requirePackage) { - if (isset($this->updateWhitelist[$requirePackage->getName()])) { - continue; - } - - if (isset($skipPackages[$requirePackage->getName()]) && !preg_match(BasePackage::packageNameToRegexp($packageName), $requirePackage->getName())) { - $this->io->writeError('Dependency "' . $requirePackage->getName() . '" is also a root requirement, but is not explicitly whitelisted. Ignoring.'); - continue; - } - - $packageQueue->enqueue($requirePackage); - } - } - } - } + $rootRequires = $request->getRequires(); + return isset($rootRequires[$name]); } /** - * @param PackageInterface $package + * Checks whether the update allow list allows this package in the lock file to be updated * @return bool */ - private function isUpdateable(PackageInterface $package) + private function isUpdateAllowed(PackageInterface $package) { - foreach ($this->unfixList as $pattern => $void) { + foreach ($this->updateAllowList as $pattern => $void) { $patternRegexp = BasePackage::packageNameToRegexp($pattern); if (preg_match($patternRegexp, $package->getName())) { return true; @@ -368,5 +295,42 @@ class PoolBuilder return false; } + + private function warnAboutNonMatchingUpdateAllowList(Request $request) + { + if ($this->io) { + foreach ($this->updateAllowList as $pattern => $void) { + foreach ($request->getLockedRepository()->getPackages() as $package) { + $patternRegexp = BasePackage::packageNameToRegexp($pattern); + if (preg_match($patternRegexp, $package->getName())) { + continue 2; + } + } + if (strpos($pattern, '*') !== false) { + $this->io->writeError('Pattern "' . $pattern . '" listed for update does not match any locked packages.'); + } else { + $this->io->writeError('Package "' . $pattern . '" listed for update is not locked.'); + } + } + } + } + + /** + * Reverts the decision to use a fixed package from lock file if a partial update with transitive dependencies + * found that this package actually needs to be updated + */ + private function unfixPackage(Request $request, $name) + { + // remove locked package by this name which was already initialized + foreach ($this->packages as $i => $loadedPackage) { + if ($loadedPackage->getName() === $name && $loadedPackage->getRepository() === $request->getLockedRepository()) { + $request->unfixPackage($loadedPackage); + unset($this->packages[$i]); + } + } + + unset($this->skippedLoad[$name]); + unset($this->loadedNames[$name]); + } } diff --git a/src/Composer/DependencyResolver/Request.php b/src/Composer/DependencyResolver/Request.php index 2e6cbfb57..c5787b54f 100644 --- a/src/Composer/DependencyResolver/Request.php +++ b/src/Composer/DependencyResolver/Request.php @@ -23,13 +23,16 @@ use Composer\Semver\Constraint\ConstraintInterface; */ class Request { + const UPDATE_ONLY_LISTED = 0; + const UPDATE_TRANSITIVE_DEPENDENCIES = 1; + const UPDATE_TRANSITIVE_ROOT_DEPENDENCIES = 2; + protected $lockedRepository; protected $requires = array(); protected $fixedPackages = array(); protected $unlockables = array(); protected $updateAllowList = array(); protected $updateAllowTransitiveDependencies = false; - protected $updateAllowTransitiveRootDependencies = false; public function __construct(LockArrayRepository $lockedRepository = null) { @@ -52,15 +55,20 @@ class Request $this->fixedPackages[spl_object_hash($package)] = $package; if (!$lockable) { - $this->unlockables[] = $package; + $this->unlockables[spl_object_hash($package)] = $package; } } - public function setUpdateAllowList($updateAllowList, $updateAllowTransitiveDependencies, $updateAllowTransitiveRootDependencies) + public function unfixPackage(PackageInterface $package) + { + unset($this->fixedPackages[spl_object_hash($package)]); + unset($this->unlockables[spl_object_hash($package)]); + } + + public function setUpdateAllowList($updateAllowList, $updateAllowTransitiveDependencies) { $this->updateAllowList = $updateAllowList; $this->updateAllowTransitiveDependencies = $updateAllowTransitiveDependencies; - $this->updateAllowTransitiveRootDependencies = $updateAllowTransitiveRootDependencies; } public function getUpdateAllowList() @@ -68,6 +76,16 @@ class Request return $this->updateAllowList; } + public function getUpdateAllowTransitiveDependencies() + { + return $this->updateAllowTransitiveDependencies !== self::UPDATE_ONLY_LISTED; + } + + public function getUpdateAllowTransitiveRootDependencies() + { + return $this->updateAllowTransitiveDependencies === self::UPDATE_TRANSITIVE_ROOT_DEPENDENCIES; + } + public function getRequires() { return $this->requires; diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 0187420ff..f1d833b1e 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -142,9 +142,8 @@ class Installer * @var array|null */ protected $updateMirrors = false; - protected $updateWhitelist = null; - protected $whitelistTransitiveDependencies = false; - protected $whitelistAllDependencies = false; + protected $updateAllowList = null; + protected $updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED; /** * @var SuggestedPackagesReporter @@ -199,8 +198,8 @@ class Installer gc_collect_cycles(); gc_disable(); - if ($this->updateWhitelist && $this->updateMirrors) { - throw new \RuntimeException("The installer options updateMirrors and updateWhitelist are mutually exclusive."); + if ($this->updateAllowList && $this->updateMirrors) { + throw new \RuntimeException("The installer options updateMirrors and updateAllowList are mutually exclusive."); } // Force update if there is no lock file present @@ -352,16 +351,11 @@ class Installer $lockedRepository = $this->locker->getLockedRepository(true); } - if ($this->updateWhitelist) { + if ($this->updateAllowList) { if (!$lockedRepository) { $this->io->writeError('Cannot update only a partial set of packages without a lock file present.', true, IOInterface::QUIET); return 1; - }/* - $this->whitelistUpdateDependencies( - $lockedRepository, - $this->package->getRequires(), - $this->package->getDevRequires() - );*/ + } } $this->io->writeError('Loading composer repositories with package information'); @@ -395,11 +389,11 @@ class Installer } // pass the allow list into the request, so the pool builder can apply it - if ($this->updateWhitelist) { - $request->setUpdateAllowList($this->updateWhitelist, $this->whitelistTransitiveDependencies, $this->whitelistAllDependencies); + if ($this->updateAllowList) { + $request->setUpdateAllowList($this->updateAllowList, $this->updateAllowTransitiveDependencies); } - $pool = $repositorySet->createPool($request, $this->eventDispatcher); + $pool = $repositorySet->createPool($request, $this->eventDispatcher, $this->io); // solve dependencies $solver = new Solver($policy, $pool, $this->io, $repositorySet); @@ -618,7 +612,7 @@ class Installer $request->requireName($link->getTarget(), $link->getConstraint()); } - $pool = $repositorySet->createPool($request, $this->eventDispatcher); + $pool = $repositorySet->createPool($request, $this->eventDispatcher, $this->io); // solve dependencies $solver = new Solver($policy, $pool, $this->io, $repositorySet); @@ -1138,41 +1132,29 @@ class Installer * @param array $packages * @return Installer */ - public function setUpdateWhitelist(array $packages) + public function setUpdateAllowList(array $packages) { - $this->updateWhitelist = array_flip(array_map('strtolower', $packages)); + $this->updateAllowList = array_flip(array_map('strtolower', $packages)); return $this; } /** - * Should dependencies of whitelisted packages (but not direct dependencies) be updated? + * Should dependencies of packages marked for update be updated? * - * This will NOT whitelist any dependencies that are also directly defined - * in the root package. + * Depending on the chosen constant this will either only update the directly named packages, all transitive + * dependencies which are not root requirement or all transitive dependencies including root requirements * - * @param bool $updateTransitiveDependencies + * @param int $updateAllowTransitiveDependencies One of the UPDATE_ constants on the Request class * @return Installer */ - public function setWhitelistTransitiveDependencies($updateTransitiveDependencies = true) + public function setUpdateAllowTransitiveDependencies($updateAllowTransitiveDependencies) { - $this->whitelistTransitiveDependencies = (bool) $updateTransitiveDependencies; + if (!in_array($updateAllowTransitiveDependencies, array(Request::UPDATE_ONLY_LISTED, Request::UPDATE_TRANSITIVE_DEPENDENCIES, Request::UPDATE_TRANSITIVE_ROOT_DEPENDENCIES), true)) { + throw new \RuntimeException("Invalid value for updateAllowTransitiveDependencies supplied"); + } - return $this; - } - - /** - * Should all dependencies of whitelisted packages be updated recursively? - * - * This will whitelist any dependencies of the whitelisted packages, including - * those defined in the root package. - * - * @param bool $updateAllDependencies - * @return Installer - */ - public function setWhitelistAllDependencies($updateAllDependencies = true) - { - $this->whitelistAllDependencies = (bool) $updateAllDependencies; + $this->updateAllowTransitiveDependencies = $updateAllowTransitiveDependencies; return $this; } diff --git a/src/Composer/Repository/RepositorySet.php b/src/Composer/Repository/RepositorySet.php index a2efbdc67..7e5d6437d 100644 --- a/src/Composer/Repository/RepositorySet.php +++ b/src/Composer/Repository/RepositorySet.php @@ -16,6 +16,7 @@ use Composer\DependencyResolver\Pool; use Composer\DependencyResolver\PoolBuilder; use Composer\DependencyResolver\Request; use Composer\EventDispatcher\EventDispatcher; +use Composer\IO\IOInterface; use Composer\Package\BasePackage; use Composer\Package\Version\VersionParser; use Composer\Repository\CompositeRepository; @@ -185,9 +186,9 @@ class RepositorySet * * @return Pool */ - public function createPool(Request $request, EventDispatcher $eventDispatcher = null) + public function createPool(Request $request, EventDispatcher $eventDispatcher = null, IOInterface $io = null) { - $poolBuilder = new PoolBuilder($this->acceptableStabilities, $this->stabilityFlags, $this->rootAliases, $this->rootReferences, $eventDispatcher); + $poolBuilder = new PoolBuilder($this->acceptableStabilities, $this->stabilityFlags, $this->rootAliases, $this->rootReferences, $eventDispatcher, $io); foreach ($this->repositories as $repo) { if (($repo instanceof InstalledRepositoryInterface || $repo instanceof InstalledRepository) && !$this->allowInstalledRepositories) { diff --git a/tests/Composer/Test/Fixtures/installer/github-issues-4795.test b/tests/Composer/Test/Fixtures/installer/github-issues-4795.test index 8e5d17dfe..dc722c379 100644 --- a/tests/Composer/Test/Fixtures/installer/github-issues-4795.test +++ b/tests/Composer/Test/Fixtures/installer/github-issues-4795.test @@ -14,7 +14,7 @@ dependency of one the requirements that is whitelisted for update. { "name": "a/a", "version": "1.0.0" }, { "name": "a/a", "version": "1.1.0" }, { "name": "b/b", "version": "1.0.0", "require": { "a/a": "~1.0" } }, - { "name": "b/b", "version": "1.1.0", "require": { "a/b": "~1.1" } } + { "name": "b/b", "version": "1.1.0", "require": { "a/a": "~1.1" } } ] } ], @@ -49,9 +49,9 @@ dependency of one the requirements that is whitelisted for update. update b/b --with-dependencies --EXPECT-OUTPUT-- -Dependency "a/a" is also a root requirement, but is not explicitly whitelisted. Ignoring. Loading composer repositories with package information Updating dependencies +Dependency "a/a" is also a root requirement. Package has not been listed as an update argument, so keeping locked at old version. Use --with-all-dependencies to include root dependencies. Nothing to modify in lock file Writing lock file Installing dependencies from lock file (including require-dev) diff --git a/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-root-dependencies.test b/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-root-dependencies.test index 02f544577..55a07b118 100644 --- a/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-root-dependencies.test +++ b/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-root-dependencies.test @@ -70,7 +70,7 @@ Update with a package whitelist only updates those packages and their dependenci "platform-dev": [] } --RUN-- -update whitelisted/pkg-* --with-dependencies +update whitelisted/pkg-* foobar --with-dependencies --EXPECT-- Upgrading dependency/pkg (1.0.0 => 1.1.0) Upgrading whitelisted/pkg-component2 (1.0.0 => 1.1.0) diff --git a/tests/Composer/Test/Fixtures/installer/update-whitelist-warns-non-existing-patterns.test b/tests/Composer/Test/Fixtures/installer/update-whitelist-warns-non-existing-patterns.test new file mode 100644 index 000000000..d4d258112 --- /dev/null +++ b/tests/Composer/Test/Fixtures/installer/update-whitelist-warns-non-existing-patterns.test @@ -0,0 +1,58 @@ +--TEST-- +Verify that partial updates warn about using patterns in the argument which have no matches +--COMPOSER-- +{ + "repositories": [ + { + "type": "package", + "package": [ + { "name": "a/a", "version": "1.0.0" }, + { "name": "b/b", "version": "1.0.0" }, + { "name": "b/b", "version": "1.1.0" } + ] + } + ], + "require": { + "a/a": "~1.0", + "b/b": "~1.0" + } +} + +--INSTALLED-- +[ + { "name": "a/a", "version": "1.0.0" }, + { "name": "b/b", "version": "1.0.0" } +] + +--LOCK-- +{ + "packages": [ + { "name": "a/a", "version": "1.0.0" }, + { "name": "b/b", "version": "1.0.0" } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} +--RUN-- +update b/b foo/bar baz/* --with-dependencies + +--EXPECT-OUTPUT-- +Loading composer repositories with package information +Updating dependencies +Package "foo/bar" listed for update is not locked. +Pattern "baz/*" listed for update does not match any locked packages. +Lock file operations: 0 installs, 1 update, 0 removals + - Upgrading b/b (1.0.0 => 1.1.0) +Writing lock file +Installing dependencies from lock file (including require-dev) +Package operations: 0 installs, 1 update, 0 removals +Generating autoload files + +--EXPECT-- +Upgrading b/b (1.0.0 => 1.1.0) diff --git a/tests/Composer/Test/InstallerTest.php b/tests/Composer/Test/InstallerTest.php index 71a955748..d032dcc27 100644 --- a/tests/Composer/Test/InstallerTest.php +++ b/tests/Composer/Test/InstallerTest.php @@ -12,6 +12,7 @@ namespace Composer\Test; +use Composer\DependencyResolver\Request; use Composer\Installer; use Composer\Console\Application; use Composer\IO\BufferIO; @@ -279,14 +280,20 @@ class InstallerTest extends TestCase $updateMirrors = $input->getOption('lock') || count($filteredPackages) != count($packages); $packages = $filteredPackages; + $updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED; + if ($input->getOption('with-all-dependencies')) { + $updateAllowTransitiveDependencies = Request::UPDATE_TRANSITIVE_ROOT_DEPENDENCIES; + } elseif ($input->getOption('with-dependencies')) { + $updateAllowTransitiveDependencies = Request::UPDATE_TRANSITIVE_DEPENDENCIES; + } + $installer ->setDevMode(!$input->getOption('no-dev')) ->setUpdate(true) ->setDryRun($input->getOption('dry-run')) ->setUpdateMirrors($updateMirrors) - ->setUpdateWhitelist($packages) - ->setWhitelistTransitiveDependencies($input->getOption('with-dependencies')) - ->setWhitelistAllDependencies($input->getOption('with-all-dependencies')) + ->setUpdateAllowList($packages) + ->setUpdateAllowTransitiveDependencies($updateAllowTransitiveDependencies) ->setPreferStable($input->getOption('prefer-stable')) ->setPreferLowest($input->getOption('prefer-lowest')) ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'));