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'));