1
0
Fork 0

Merge pull request #10280 from Seldaek/pool_builder_replace

Fix unlocking of replacers when a replaced package is unlocked
pull/10307/head
Jordi Boggiano 2021-11-23 16:45:26 +01:00 committed by GitHub
commit c0156e1b89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 543 additions and 27 deletions

View File

@ -99,7 +99,7 @@ class PoolBuilder
private $unacceptableFixedOrLockedPackages = array(); private $unacceptableFixedOrLockedPackages = array();
/** @var string[] */ /** @var string[] */
private $updateAllowList = array(); private $updateAllowList = array();
/** @var array<string, string> */ /** @var array<string, array<PackageInterface>> */
private $skippedLoad = array(); private $skippedLoad = array();
/** /**
@ -156,11 +156,10 @@ class PoolBuilder
foreach ($request->getLockedRepository()->getPackages() as $lockedPackage) { foreach ($request->getLockedRepository()->getPackages() as $lockedPackage) {
if (!$this->isUpdateAllowed($lockedPackage)) { if (!$this->isUpdateAllowed($lockedPackage)) {
$request->lockPackage($lockedPackage); $request->lockPackage($lockedPackage);
$lockedName = $lockedPackage->getName(); $this->skippedLoad[$lockedPackage->getName()][] = $lockedPackage;
// remember which packages we skipped loading remote content for in this partial update // remember which packages we skipped loading remote content for in this partial update
$this->skippedLoad[$lockedName] = $lockedName;
foreach ($lockedPackage->getReplaces() as $link) { foreach ($lockedPackage->getReplaces() as $link) {
$this->skippedLoad[$link->getTarget()] = $lockedName; $this->skippedLoad[$link->getTarget()][] = $lockedPackage;
} }
} }
} }
@ -422,12 +421,18 @@ class PoolBuilder
// looking at a package which needs to be updated we need to unlock the package we now know is a // looking at a package which needs to be updated we need to unlock the package we now know is a
// dependency of another package which we are trying to update, and then attempt to load it again // dependency of another package which we are trying to update, and then attempt to load it again
if ($propagateUpdate && $request->getUpdateAllowTransitiveDependencies()) { if ($propagateUpdate && $request->getUpdateAllowTransitiveDependencies()) {
if ($request->getUpdateAllowTransitiveRootDependencies() || !$this->isRootRequire($request, $this->skippedLoad[$require])) { $skippedRootRequires = $this->getSkippedRootRequires($request, $require);
if ($request->getUpdateAllowTransitiveRootDependencies() || !$skippedRootRequires) {
$this->unlockPackage($request, $require); $this->unlockPackage($request, $require);
$this->markPackageNameForLoading($request, $require, $linkConstraint); $this->markPackageNameForLoading($request, $require, $linkConstraint);
} elseif (!isset($this->updateAllowWarned[$this->skippedLoad[$require]])) { } else {
$this->updateAllowWarned[$this->skippedLoad[$require]] = true; foreach ($skippedRootRequires as $rootRequire) {
$this->io->writeError('<warning>Dependency "'.$this->skippedLoad[$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 (-W) to include root dependencies.</warning>'); if (!isset($this->updateAllowWarned[$rootRequire])) {
$this->updateAllowWarned[$rootRequire] = true;
$this->io->writeError('<warning>Dependency '.$rootRequire.' is also a root requirement. Package has not been listed as an update argument, so keeping locked at old version. Use --with-all-dependencies (-W) to include root dependencies.</warning>');
}
}
} }
} }
} else { } else {
@ -441,12 +446,18 @@ class PoolBuilder
foreach ($package->getReplaces() as $link) { foreach ($package->getReplaces() as $link) {
$replace = $link->getTarget(); $replace = $link->getTarget();
if (isset($this->loadedPackages[$replace], $this->skippedLoad[$replace])) { if (isset($this->loadedPackages[$replace], $this->skippedLoad[$replace])) {
if ($request->getUpdateAllowTransitiveRootDependencies() || !$this->isRootRequire($request, $this->skippedLoad[$replace])) { $skippedRootRequires = $this->getSkippedRootRequires($request, $replace);
if ($request->getUpdateAllowTransitiveRootDependencies() || !$skippedRootRequires) {
$this->unlockPackage($request, $replace); $this->unlockPackage($request, $replace);
$this->markPackageNameForLoading($request, $replace, $link->getConstraint()); $this->markPackageNameForLoading($request, $replace, $link->getConstraint());
} elseif ($this->isRootRequire($request, $replace) && !isset($this->updateAllowWarned[$replace])) { } else {
$this->updateAllowWarned[$replace] = true; foreach ($skippedRootRequires as $rootRequire) {
$this->io->writeError('<warning>Dependency "'.$replace.'" is also a root requirement. Package has not been listed as an update argument, so keeping locked at old version. Use --with-all-dependencies (-W) to include root dependencies.</warning>'); if (!isset($this->updateAllowWarned[$rootRequire])) {
$this->updateAllowWarned[$rootRequire] = true;
$this->io->writeError('<warning>Dependency '.$rootRequire.' is also a root requirement. Package has not been listed as an update argument, so keeping locked at old version. Use --with-all-dependencies (-W) to include root dependencies.</warning>');
}
}
} }
} }
} }
@ -466,6 +477,48 @@ class PoolBuilder
return isset($rootRequires[$name]); return isset($rootRequires[$name]);
} }
/**
* @param string $name
* @return string[]
*/
private function getSkippedRootRequires(Request $request, $name)
{
if (!isset($this->skippedLoad[$name])) {
return array();
}
$rootRequires = $request->getRequires();
$matches = array();
if (isset($rootRequires[$name])) {
return array_map(function (PackageInterface $package) use ($name) {
if ($name !== $package->getName()) {
return $package->getName() .' (via replace of '.$name.')';
}
return $package->getName();
}, $this->skippedLoad[$name]);
}
foreach ($this->skippedLoad[$name] as $packageOrReplacer) {
if (isset($rootRequires[$packageOrReplacer->getName()])) {
$matches[] = $packageOrReplacer->getName();
}
foreach ($packageOrReplacer->getReplaces() as $link) {
if (isset($rootRequires[$link->getTarget()])) {
if ($name !== $packageOrReplacer->getName()) {
$matches[] = $packageOrReplacer->getName() .' (via replace of '.$name.')';
} else {
$matches[] = $packageOrReplacer->getName();
}
break;
}
}
}
return $matches;
}
/** /**
* Checks whether the update allow list allows this package in the lock file to be updated * Checks whether the update allow list allows this package in the lock file to be updated
* *
@ -529,13 +582,26 @@ class PoolBuilder
*/ */
private function unlockPackage(Request $request, $name) private function unlockPackage(Request $request, $name)
{ {
if ( foreach ($this->skippedLoad[$name] as $packageOrReplacer) {
// if we unfixed a replaced package name, we also need to unfix the replacer itself // if we unfixed a replaced package name, we also need to unfix the replacer itself
$this->skippedLoad[$name] !== $name
// as long as it was not unfixed yet // as long as it was not unfixed yet
&& isset($this->skippedLoad[$this->skippedLoad[$name]]) if ($packageOrReplacer->getName() !== $name && isset($this->skippedLoad[$packageOrReplacer->getName()])) {
) { $replacerName = $packageOrReplacer->getName();
$this->unlockPackage($request, $this->skippedLoad[$name]); if ($request->getUpdateAllowTransitiveRootDependencies() || (!$this->isRootRequire($request, $name) && !$this->isRootRequire($request, $replacerName))) {
$this->unlockPackage($request, $replacerName);
if ($this->isRootRequire($request, $replacerName)) {
$this->markPackageNameForLoading($request, $replacerName, new MatchAllConstraint);
} else {
foreach ($this->packages as $loadedPackage) {
$requires = $loadedPackage->getRequires();
if (isset($requires[$replacerName])) {
$this->markPackageNameForLoading($request, $replacerName, $requires[$replacerName]->getConstraint());
}
}
}
}
}
} }
unset($this->skippedLoad[$name], $this->loadedPackages[$name], $this->maxExtendedReqs[$name]); unset($this->skippedLoad[$name], $this->loadedPackages[$name], $this->maxExtendedReqs[$name]);
@ -551,11 +617,14 @@ class PoolBuilder
// also loaded, as they were previously ignored because the locked (now unlocked) package already // also loaded, as they were previously ignored because the locked (now unlocked) package already
// satisfied their requirements // satisfied their requirements
foreach ($request->getFixedOrLockedPackages() as $fixedOrLockedPackage) { foreach ($request->getFixedOrLockedPackages() as $fixedOrLockedPackage) {
if ($fixedOrLockedPackage !== $lockedPackage && isset($this->skippedLoad[$fixedOrLockedPackage->getName()])) { if ($fixedOrLockedPackage === $lockedPackage) {
foreach ($fixedOrLockedPackage->getRequires() as $requireLink) { continue;
if ($requireLink->getTarget() === $lockedPackage->getName()) {
$this->markPackageNameForLoading($request, $lockedPackage->getName(), $requireLink->getConstraint());
} }
if (isset($this->skippedLoad[$fixedOrLockedPackage->getName()])) {
$requires = $fixedOrLockedPackage->getRequires();
if (isset($requires[$lockedPackage->getName()])) {
$this->markPackageNameForLoading($request, $lockedPackage->getName(), $requires[$lockedPackage->getName()]->getConstraint());
} }
} }
} }

View File

@ -1,5 +1,5 @@
--TEST-- --TEST--
Check that replacers from additional repositories are loaded when doing a partial update Check that replacers from additional repositories are loaded when doing a partial update allowing all transitive deps
--REQUEST-- --REQUEST--
{ {
@ -15,7 +15,7 @@ Check that replacers from additional repositories are loaded when doing a partia
"allowList": [ "allowList": [
"indirect/replacer" "indirect/replacer"
], ],
"allowTransitiveDepsNoRootRequire": true "allowTransitiveDeps": true
} }
--FIXED-- --FIXED--

View File

@ -0,0 +1,102 @@
--TEST--
Partially updating with deps a root requirement which depends on packages should load all available versions for the path repo packages' dependencies.
--REQUEST--
{
"require": {
"root/update": "*",
"root-required/replacer": "*",
"replacer/pkg": "*",
"root/noupdate": "*"
},
"locked": [
{
"name": "replacer/pkg",
"version": "1.0.0",
"require": {
"root-required/replacer-replaced": "1.*",
"transitive/dep-of-replacer": "1.*",
"transitive/replacer-replaced": "1.*"
},
"replace": {
"replaced/pkg": "1.0.0"
}
},
{
"name": "pkg/with-replaced-deps",
"version": "1.0.0",
"require": {
"transitive/dep": "1.*",
"root-required/replacer-replaced": "1.*",
"transitive/replacer-replaced": "1.*"
}
},
{"name": "root/update", "version": "1.0.1", "require": {"pkg/with-replaced-deps": ">=1.0.1", "replaced/pkg": "*"}},
{"name": "root/noupdate", "version": "1.0.1", "require": {"transitive/replacer": "^2"}},
{"name": "transitive/dep", "version": "1.0.0"},
{"name": "root-required/replacer", "version": "1.0.0", "replace": {"root-required/replacer-replaced": "1.0.0"}},
{"name": "transitive/dep-of-replacer", "version": "1.0.0"},
{"name": "transitive/replacer", "version": "1.0.0", "replace": {"transitive/replacer-replaced": "1.0.0"}}
],
"allowList": [
"root/update"
],
"allowTransitiveDeps": true
}
--FIXED--
[
]
--PACKAGE-REPOS--
[
[
{
"name": "replacer/pkg",
"version": "2.0.0",
"require": {
"root-required/replacer-replaced": ">=1.0.3",
"transitive/dep-of-replacer": "2.*",
"transitive/replacer-replaced": "2.*"
},
"replace": {
"replaced/pkg": "2.0.0"
}
},
{
"name": "pkg/with-replaced-deps",
"version": "2.0.0",
"require": {
"transitive/dep": "2.*",
"root-required/replacer-replaced": "2.*",
"transitive/replacer-replaced": ">=1.0.3"
}
},
{"name": "root/update", "version": "1.0.4", "require": {"pkg/with-replaced-deps": ">=1.0.1", "replaced/pkg": "*"}},
{"name": "root/noupdate", "version": "1.0.1", "require": {"transitive/replacer": "^2"}},
{"name": "transitive/dep", "version": "1.0.0"},
{"name": "transitive/dep", "version": "2.0.2"},
{"name": "root-required/replacer", "version": "1.0.0", "replace": {"root-required/replacer-replaced": "1.0.0"}},
{"name": "root-required/replacer", "version": "1.0.3", "replace": {"root-required/replacer-replaced": "1.0.3"}},
{"name": "root-required/replacer", "version": "2.0.4", "replace": {"root-required/replacer-replaced": "2.0.4"}},
{"name": "transitive/dep-of-replacer", "version": "1.0.0"},
{"name": "transitive/dep-of-replacer", "version": "2.0.2"},
{"name": "transitive/replacer", "version": "1.0.0", "replace": {"transitive/replacer-replaced": "1.0.0"}},
{"name": "transitive/replacer", "version": "1.0.3", "replace": {"transitive/replacer-replaced": "1.0.3"}},
{"name": "transitive/replacer", "version": "2.0.4", "replace": {"transitive/replacer-replaced": "2.0.4"}}
]
]
--EXPECT--
[
"root/noupdate-1.0.1.0 (locked)",
"root/update-1.0.4.0",
"replacer/pkg-2.0.0.0",
"pkg/with-replaced-deps-2.0.0.0",
"transitive/dep-2.0.2.0",
"root-required/replacer-1.0.0.0",
"root-required/replacer-1.0.3.0",
"root-required/replacer-2.0.4.0",
"transitive/dep-of-replacer-2.0.2.0",
"transitive/replacer-2.0.4.0"
]

View File

@ -0,0 +1,87 @@
--TEST--
Check that replacers/providers which replace/provide a root requirement do not get unlocked
--REQUEST--
{
"require": {
"base/package": "^1.0",
"base/package2": "^1.0",
"indirect/replacer": "^1.0"
},
"locked": [
{"name": "shared/dep", "version": "1.2.0", "id": 1},
{"name": "shared/dep2", "version": "1.2.0", "id": 2},
{"name": "indirect/replacer", "version": "1.2.0", "require": {"replacer/package": "^1.2", "provider/package": "^1.2"}, "id": 3},
{"name": "replacer/package", "version": "1.2.0", "require": {"shared/dep": "^1.1"}, "replace": {"base/package": "1.2.0"}, "id": 4},
{"name": "provider/package", "version": "1.2.0", "require": {"shared/dep2": "^1.1"}, "provide": {"base/package2": "1.2.0"}, "id": 5}
],
"allowList": [
"indirect/replacer"
],
"allowTransitiveDepsNoRootRequire": true
}
--FIXED--
[
]
--PACKAGE-REPOS--
[
[
{
"name": "base/package",
"version": "1.0.0",
"require": {
"shared/dep": "^1.2"
}
},
{
"name": "base/package2",
"version": "1.0.0",
"require": {
"shared/dep2": "^1.2"
}
},
{
"name": "shared/dep",
"version": "1.0.0"
},
{
"name": "shared/dep",
"version": "1.2.0"
},
{
"name": "shared/dep2",
"version": "1.0.0"
},
{
"name": "shared/dep2",
"version": "1.2.0"
},
{
"name": "indirect/replacer",
"version": "1.2.0",
"require": {
"replacer/package": "^1.2"
}
},
{
"name": "indirect/replacer",
"version": "1.0.0",
"require": {
"replacer/package": "^1.0"
}
}
]
]
--EXPECT--
[
1,
4,
5,
"base/package2-1.0.0.0",
"indirect/replacer-1.2.0.0",
"indirect/replacer-1.0.0.0",
"shared/dep2-1.2.0.0"
]

View File

@ -50,7 +50,7 @@ update b/b --with-dependencies
--EXPECT-OUTPUT-- --EXPECT-OUTPUT--
Loading composer repositories with package information Loading composer repositories with package information
<warning>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 (-W) to include root dependencies.</warning> <warning>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 (-W) to include root dependencies.</warning>
Updating dependencies Updating dependencies
Nothing to modify in lock file Nothing to modify in lock file
Writing lock file Writing lock file

View File

@ -0,0 +1,65 @@
--TEST--
Ensure a partial update of a dependency does NOT update dependencies which provide its requirements.
--COMPOSER--
{
"repositories": [
{
"type": "package",
"package": [
{"name": "root/req1", "version": "1.0.0", "require": {"virtual/pkg1": "1.*"}},
{"name": "root/req1", "version": "2.0.0", "require": {"virtual/pkg1": "2.*"}},
{"name": "root/req2", "version": "1.0.0", "require": {"dep/pkg1": "1.*", "dep/pkg2": "1.*"}},
{"name": "dep/pkg1", "version": "1.0.0", "provide": {"virtual/pkg1": "1.0.0"}},
{"name": "dep/pkg1", "version": "1.2.0", "provide": {"virtual/pkg1": "2.0.0"}},
{"name": "dep/pkg2", "version": "1.0.0", "provide": {"virtual/pkg1": "1.0.0"}},
{"name": "dep/pkg2", "version": "1.2.0", "provide": {"virtual/pkg1": "2.0.0"}}
]
}
],
"require": {
"root/req1": "*",
"root/req2": "*"
}
}
--LOCK--
{
"packages": [
{"name": "dep/pkg1", "version": "1.0.0", "type": "library", "provide": {"virtual/pkg1": "1.0.0"}},
{"name": "dep/pkg2", "version": "1.0.0", "type": "library", "provide": {"virtual/pkg1": "1.0.0"}},
{"name": "root/req1", "version": "1.0.0", "type": "library", "require": {"virtual/pkg1": "1.*"}},
{"name": "root/req2", "version": "1.0.0", "type": "library", "require": {"dep/pkg1": "1.*", "dep/pkg2": "1.*"}}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}
--RUN--
update root/req1 --with-dependencies
--EXPECT-LOCK--
{
"packages": [
{"name": "dep/pkg1", "version": "1.0.0", "type": "library", "provide": {"virtual/pkg1": "1.0.0"}},
{"name": "dep/pkg2", "version": "1.0.0", "type": "library", "provide": {"virtual/pkg1": "1.0.0"}},
{"name": "root/req1", "version": "1.0.0", "type": "library", "require": {"virtual/pkg1": "1.*"}},
{"name": "root/req2", "version": "1.0.0", "type": "library", "require": {"dep/pkg1": "1.*", "dep/pkg2": "1.*"}}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}
--EXPECT--
Installing dep/pkg1 (1.0.0)
Installing dep/pkg2 (1.0.0)
Installing root/req1 (1.0.0)
Installing root/req2 (1.0.0)

View File

@ -0,0 +1,62 @@
--TEST--
Ensure a partial update of a dependency updates dependencies which replace one of its requirements.
--COMPOSER--
{
"repositories": [
{
"type": "package",
"package": [
{"name": "root/req1", "version": "1.0.0", "require": {"replaced/pkg1": "1.*"}},
{"name": "root/req1", "version": "2.0.0", "require": {"replaced/pkg1": "2.*"}},
{"name": "root/req2", "version": "1.0.0", "require": {"dep/pkg1": "1.*"}},
{"name": "replaced/pkg1", "version": "1.0.0"},
{"name": "replaced/pkg1", "version": "2.0.0"},
{"name": "dep/pkg1", "version": "1.0.0", "replace": {"replaced/pkg1": "1.0.0"}},
{"name": "dep/pkg1", "version": "1.2.0", "replace": {"replaced/pkg1": "2.0.0"}}
]
}
],
"require": {
"root/req1": "*",
"root/req2": "*"
}
}
--LOCK--
{
"packages": [
{"name": "dep/pkg1", "version": "1.0.0", "type": "library", "replace": {"replaced/pkg1": "1.0.0"}},
{"name": "root/req1", "version": "1.0.0", "type": "library", "require": {"replaced/pkg1": "1.*"}},
{"name": "root/req2", "version": "1.0.0", "type": "library", "require": {"dep/pkg1": "1.*"}}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}
--RUN--
update root/req1 --with-dependencies
--EXPECT-LOCK--
{
"packages": [
{"name": "dep/pkg1", "version": "1.2.0", "type": "library", "replace": {"replaced/pkg1": "2.0.0"}},
{"name": "root/req1", "version": "2.0.0", "type": "library", "require": {"replaced/pkg1": "2.*"}},
{"name": "root/req2", "version": "1.0.0", "type": "library", "require": {"dep/pkg1": "1.*"}}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}
--EXPECT--
Installing dep/pkg1 (1.2.0)
Installing root/req1 (2.0.0)
Installing root/req2 (1.0.0)

View File

@ -0,0 +1,131 @@
--TEST--
Ensure that a partial update of a dependency does not conflict if the only way to proceed is using an old locked version.
--COMPOSER--
{
"repositories": [
{
"type": "package",
"package": [
{
"name": "update/pkg1", "version": "1.0.0", "require": {
"dep/pkg2": "*",
"root/pkg3": "*",
"root/provided-pkg4": "*",
"root/replaced-pkg8": "*"
}
},
{
"name": "update/pkg1", "version": "2.0.0", "require": {
"dep/pkg2": "*",
"root/pkg3": "*",
"root/provided-pkg4": "*",
"root/replaced-pkg8": "*"
}
},
{"name": "dep/pkg2", "version": "1.0.0"},
{"name": "dep/pkg2", "version": "2.0.0"},
{"name": "root/pkg3", "version": "1.0.0"},
{"name": "root/pkg3", "version": "2.0.0"},
{"name": "dep/pkg5", "version": "1.0.0", "provide": {"root/provided-pkg4": "1.0.0"}},
{"name": "dep/pkg5", "version": "2.0.0", "provide": {"root/provided-pkg4": "2.0.0"}},
{"name": "dep/pkg6", "version": "1.0.0", "provide": {"root/provided-pkg4": "1.0.0"}},
{"name": "dep/pkg6", "version": "2.0.0", "provide": {"root/provided-pkg4": "2.0.0"}},
{"name": "root/pkg7", "version": "1.0.0", "require": {"dep/pkg5": "*", "dep/pkg6": "*"}},
{"name": "dep/pkg9", "version": "1.0.0", "replace": {"root/replaced-pkg8": "1.0.0"}},
{"name": "dep/pkg9", "version": "2.0.0", "replace": {"root/replaced-pkg8": "2.0.0"}},
{"name": "root/replaced-pkg8", "version": "1.0.0"},
{"name": "root/replaced-pkg8", "version": "2.0.0"},
{"name": "root/pkg10", "version": "1.0.0", "require": {"dep/pkg9": "*"}}
]
}
],
"require": {
"update/pkg1": "*",
"root/pkg3": "*",
"root/provided-pkg4": "*",
"root/pkg7": "*",
"root/replaced-pkg8": "*",
"root/pkg10": "*"
}
}
--LOCK--
{
"packages": [
{
"name": "update/pkg1", "version": "1.0.0", "type": "library", "require": {
"dep/pkg2": "*",
"root/pkg3": "*",
"root/provided-pkg4": "*",
"root/replaced-pkg8": "*"
}
},
{"name": "dep/pkg2", "version": "1.0.0", "type": "library"},
{"name": "root/pkg3", "version": "1.0.0", "type": "library"},
{"name": "dep/pkg5", "version": "1.0.0", "type": "library", "provide": {"root/provided-pkg4": "1.0.0"}},
{"name": "dep/pkg6", "version": "1.0.0", "type": "library", "provide": {"root/provided-pkg4": "1.0.0"}},
{"name": "root/pkg7", "version": "1.0.0", "type": "library", "require": {"dep/pkg5": "*", "dep/pkg6": "*"}},
{"name": "dep/pkg9", "version": "1.0.0", "type": "library", "replace": {"root/replaced-pkg8": "1.0.0"}},
{"name": "root/pkg10", "version": "1.0.0", "type": "library", "require": {"dep/pkg9": "*"}}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}
--RUN--
update update/pkg1 --with-dependencies
--EXPECT-LOCK--
{
"packages": [
{"name": "dep/pkg2", "version": "2.0.0", "type": "library"},
{"name": "dep/pkg5", "version": "1.0.0", "type": "library", "provide": {"root/provided-pkg4": "1.0.0"}},
{"name": "dep/pkg6", "version": "1.0.0", "type": "library", "provide": {"root/provided-pkg4": "1.0.0"}},
{"name": "dep/pkg9", "version": "1.0.0", "type": "library", "replace": {"root/replaced-pkg8": "1.0.0"}},
{"name": "root/pkg10", "version": "1.0.0", "type": "library", "require": {"dep/pkg9": "*"}},
{"name": "root/pkg3", "version": "1.0.0", "type": "library"},
{"name": "root/pkg7", "version": "1.0.0", "type": "library", "require": {"dep/pkg5": "*", "dep/pkg6": "*"}},
{
"name": "update/pkg1", "version": "2.0.0", "type": "library", "require": {
"dep/pkg2": "*",
"root/pkg3": "*",
"root/provided-pkg4": "*",
"root/replaced-pkg8": "*"
}
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}
--EXPECT-OUTPUT--
Loading composer repositories with package information
<warning>Dependency root/pkg3 is also a root requirement. Package has not been listed as an update argument, so keeping locked at old version. Use --with-all-dependencies (-W) to include root dependencies.</warning>
<warning>Dependency dep/pkg9 (via replace of root/replaced-pkg8) is also a root requirement. Package has not been listed as an update argument, so keeping locked at old version. Use --with-all-dependencies (-W) to include root dependencies.</warning>
Updating dependencies
Lock file operations: 0 installs, 2 updates, 0 removals
- Upgrading dep/pkg2 (1.0.0 => 2.0.0)
- Upgrading update/pkg1 (1.0.0 => 2.0.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 8 installs, 0 updates, 0 removals
Generating autoload files
--EXPECT--
Installing dep/pkg9 (1.0.0)
Installing root/pkg10 (1.0.0)
Installing dep/pkg6 (1.0.0)
Installing dep/pkg5 (1.0.0)
Installing root/pkg7 (1.0.0)
Installing root/pkg3 (1.0.0)
Installing dep/pkg2 (2.0.0)
Installing update/pkg1 (2.0.0)

View File

@ -77,12 +77,12 @@
{ {
"location": "Composer\\Test\\InstallerTest::testIntegrationWithRawPool", "location": "Composer\\Test\\InstallerTest::testIntegrationWithRawPool",
"message": "preg_match(): Passing null to parameter #4 ($flags) of type int is deprecated", "message": "preg_match(): Passing null to parameter #4 ($flags) of type int is deprecated",
"count": 1728 "count": 1776
}, },
{ {
"location": "Composer\\Test\\InstallerTest::testIntegrationWithPoolOptimizer", "location": "Composer\\Test\\InstallerTest::testIntegrationWithPoolOptimizer",
"message": "preg_match(): Passing null to parameter #4 ($flags) of type int is deprecated", "message": "preg_match(): Passing null to parameter #4 ($flags) of type int is deprecated",
"count": 1728 "count": 1776
}, },
{ {
"location": "Composer\\Test\\Package\\Archiver\\ArchivableFilesFinderTest::testManualExcludes", "location": "Composer\\Test\\Package\\Archiver\\ArchivableFilesFinderTest::testManualExcludes",