Partial updates should remove all unused dependencies
Instead of marking locked packages as fixed, we change the pool builder to load only the locked version and treat it like a fixed package, but removing the actual request fix, makes the solver treat it as a regular optional dependency. As a consequence locked packages may be removed on a partial update of another package, but they cannot be updated.pull/9223/head
parent
d8490ee38f
commit
73e24ea9fb
|
@ -62,6 +62,7 @@ class LockTransaction extends Transaction
|
|||
|
||||
if ($literal > 0) {
|
||||
$package = $pool->literalToPackage($literal);
|
||||
|
||||
$this->resultPackages['all'][] = $package;
|
||||
if (!isset($this->unlockableMap[$package->id])) {
|
||||
$this->resultPackages['non-dev'][] = $package;
|
||||
|
|
|
@ -123,13 +123,16 @@ class PoolBuilder
|
|||
|
||||
public function buildPool(array $repositories, Request $request)
|
||||
{
|
||||
$singleVersionPackages = $request->getFixedPackages();
|
||||
|
||||
if ($request->getUpdateAllowList()) {
|
||||
$this->updateAllowList = $request->getUpdateAllowList();
|
||||
$this->warnAboutNonMatchingUpdateAllowList($request);
|
||||
|
||||
foreach ($request->getLockedRepository()->getPackages() as $lockedPackage) {
|
||||
if (!$this->isUpdateAllowed($lockedPackage)) {
|
||||
$request->fixPackage($lockedPackage);
|
||||
//$request->fixPackage($lockedPackage);
|
||||
$singleVersionPackages[] = $lockedPackage;
|
||||
$lockedName = $lockedPackage->getName();
|
||||
// remember which packages we skipped loading remote content for in this partial update
|
||||
$this->skippedLoad[$lockedName] = $lockedName;
|
||||
|
@ -140,7 +143,7 @@ class PoolBuilder
|
|||
}
|
||||
}
|
||||
|
||||
foreach ($request->getFixedPackages() as $package) {
|
||||
foreach ($singleVersionPackages as $package) {
|
||||
// using MatchAllConstraint here because fixed packages do not need to retrigger
|
||||
// loading any packages
|
||||
$this->loadedPackages[$package->getName()] = new MatchAllConstraint();
|
||||
|
@ -345,7 +348,7 @@ class PoolBuilder
|
|||
// apply to
|
||||
if (isset($this->rootReferences[$name])) {
|
||||
// do not modify the references on already locked packages
|
||||
if (!$request->isFixedPackage($package)) {
|
||||
if ($request->getLockedRepository() !== $package->getRepository() && !$request->isFixedPackage($package)) {
|
||||
$package->setSourceDistReferences($this->rootReferences[$name]);
|
||||
}
|
||||
}
|
||||
|
@ -473,7 +476,7 @@ class PoolBuilder
|
|||
foreach ($request->getLockedRepository()->getPackages() as $lockedPackage) {
|
||||
if (!($lockedPackage instanceof AliasPackage) && $lockedPackage->getName() === $name) {
|
||||
if (false !== $index = array_search($lockedPackage, $this->packages, true)) {
|
||||
$request->unfixPackage($lockedPackage);
|
||||
//$request->unfixPackage($lockedPackage);
|
||||
$this->removeLoadedPackage($request, $lockedPackage, $index);
|
||||
}
|
||||
}
|
||||
|
@ -496,7 +499,7 @@ class PoolBuilder
|
|||
unset($this->packages[$index]);
|
||||
if (isset($this->aliasMap[spl_object_hash($package)])) {
|
||||
foreach ($this->aliasMap[spl_object_hash($package)] as $aliasIndex => $aliasPackage) {
|
||||
$request->unfixPackage($aliasPackage);
|
||||
//$request->unfixPackage($aliasPackage);
|
||||
unset($this->packages[$aliasIndex]);
|
||||
}
|
||||
unset($this->aliasMap[spl_object_hash($package)]);
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
--TEST--
|
||||
Removing a package deletes unused dependencies and does not update other dependencies
|
||||
--COMPOSER--
|
||||
{
|
||||
"repositories": [
|
||||
{
|
||||
"type": "package",
|
||||
"package": [
|
||||
{ "name": "root/a", "version": "1.0.0", "require": { "dep/c": "*", "dep/d": "*"} },
|
||||
{ "name": "remove/b", "version": "1.0.0", "require": { "dep/c": "*", "dep/e": "*"} },
|
||||
{ "name": "dep/c", "version": "1.0.0" },
|
||||
{ "name": "dep/c", "version": "1.2.0" },
|
||||
{ "name": "dep/d", "version": "1.0.0" },
|
||||
{ "name": "dep/d", "version": "1.2.0" },
|
||||
{ "name": "dep/e", "version": "1.0.0" },
|
||||
{ "name": "unrelated/f", "version": "1.0.0" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"root/a": "*"
|
||||
}
|
||||
}
|
||||
--LOCK--
|
||||
{
|
||||
"packages": [
|
||||
{ "name": "root/a", "version": "1.0.0", "require": { "dep/c": "*", "dep/d": "*"} },
|
||||
{ "name": "remove/b", "version": "1.0.0", "require": { "dep/c": "*", "dep/e": "*"} },
|
||||
{ "name": "dep/c", "version": "1.0.0" },
|
||||
{ "name": "dep/d", "version": "1.0.0" },
|
||||
{ "name": "dep/e", "version": "1.0.0" },
|
||||
{ "name": "unrelated/f", "version": "1.0.0" }
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false
|
||||
}
|
||||
--RUN--
|
||||
update remove/b
|
||||
--EXPECT--
|
||||
Installing dep/d (1.0.0)
|
||||
Installing dep/c (1.0.0)
|
||||
Installing root/a (1.0.0)
|
|
@ -0,0 +1,39 @@
|
|||
--TEST--
|
||||
Removing a package has no effect if another package would require an update in order to find a correct set of dependencies without the removed package
|
||||
--COMPOSER--
|
||||
{
|
||||
"repositories": [
|
||||
{
|
||||
"type": "package",
|
||||
"package": [
|
||||
{ "name": "root/a", "version": "1.0.0", "require": { "remove/b": "*", "dep/c": "*"} },
|
||||
{ "name": "remove/b", "version": "1.0.0", "require": { "dep/c": "*"} },
|
||||
{ "name": "dep/c", "version": "1.0.0" },
|
||||
{ "name": "dep/c", "version": "1.2.0", "replace": { "remove/b": "1.0.0"} }
|
||||
]
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"root/a": "*"
|
||||
}
|
||||
}
|
||||
--LOCK--
|
||||
{
|
||||
"packages": [
|
||||
{ "name": "root/a", "version": "1.0.0", "require": { "remove/b": "*", "dep/c": "*"} },
|
||||
{ "name": "remove/b", "version": "1.0.0", "require": { "dep/c": "*"} },
|
||||
{ "name": "dep/c", "version": "1.0.0" }
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false
|
||||
}
|
||||
--RUN--
|
||||
update remove/b
|
||||
--EXPECT--
|
||||
Installing dep/c (1.0.0)
|
||||
Installing remove/b (1.0.0)
|
||||
Installing root/a (1.0.0)
|
Loading…
Reference in New Issue