1
0
Fork 0

Merge pull request #9519 from Seldaek/lock-update-with-new-req

Fix mirror updates when adding new reqs and dev-reqs are present
pull/9532/head
Nils Adermann 2020-11-26 13:29:00 +01:00 committed by GitHub
commit 01887a2488
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 104 additions and 34 deletions

View File

@ -24,6 +24,7 @@ use Composer\DependencyResolver\Pool;
use Composer\DependencyResolver\Request;
use Composer\DependencyResolver\Solver;
use Composer\DependencyResolver\SolverProblemsException;
use Composer\DependencyResolver\PolicyInterface;
use Composer\Downloader\DownloadManager;
use Composer\EventDispatcher\EventDispatcher;
use Composer\Installer\InstallationManager;
@ -52,6 +53,7 @@ use Composer\Repository\RootPackageRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\RepositoryManager;
use Composer\Repository\LockArrayRepository;
use Composer\Script\ScriptEvents;
/**
@ -365,12 +367,10 @@ class Installer
// doing a full update
}
if ($this->updateAllowList) {
if (!$lockedRepository) {
$this->io->writeError('<error>Cannot update only a partial set of packages without a lock file present.</error>', true, IOInterface::QUIET);
if (($this->updateAllowList || $this->updateMirrors) && !$lockedRepository) {
$this->io->writeError('<error>Cannot update ' . ($this->updateMirrors ? 'lock file information' : 'only a partial set of packages') . ' without a lock file present. Run `composer update` to generate a lock file.</error>', true, IOInterface::QUIET);
return 1;
}
return 1;
}
$this->io->writeError('<info>Loading composer repositories with package information</info>');
@ -387,22 +387,7 @@ class Installer
}
$request = $this->createRequest($this->fixedRootPackage, $platformRepo, $lockedRepository);
// if we're updating mirrors we want to keep exactly the same versions installed which are in the lock file, but we want current remote metadata
if ($this->updateMirrors && $lockedRepository) {
foreach ($lockedRepository->getPackages() as $lockedPackage) {
// exclude alias packages here as for root aliases, both alias and aliased are
// present in the lock repo and we only want to require the aliased version
if (!$lockedPackage instanceof AliasPackage) {
$request->requireName($lockedPackage->getName(), new Constraint('==', $lockedPackage->getVersion()));
}
}
} else {
$links = array_merge($this->package->getRequires(), $this->package->getDevRequires());
foreach ($links as $link) {
$request->requireName($link->getTarget(), $link->getConstraint());
}
}
$this->requirePackagesForUpdate($request, $lockedRepository, true);
// pass the allow list into the request, so the pool builder can apply it
if ($this->updateAllowList) {
@ -442,7 +427,7 @@ class Installer
$this->io->writeError('Nothing to modify in lock file');
}
$exitCode = $this->extractDevPackages($lockTransaction, $platformRepo, $aliases, $policy);
$exitCode = $this->extractDevPackages($lockTransaction, $platformRepo, $aliases, $policy, $lockedRepository);
if ($exitCode !== 0) {
return $exitCode;
}
@ -555,7 +540,7 @@ class Installer
* Run the solver a second time on top of the existing update result with only the current result set in the pool
* and see what packages would get removed if we only had the non-dev packages in the solver request
*/
protected function extractDevPackages(LockTransaction $lockTransaction, $platformRepo, $aliases, $policy)
protected function extractDevPackages(LockTransaction $lockTransaction, PlatformRepository $platformRepo, array $aliases, PolicyInterface $policy, LockArrayRepository $lockedRepository = null)
{
if (!$this->package->getDevRequires()) {
return 0;
@ -572,11 +557,7 @@ class Installer
$repositorySet->addRepository($resultRepo);
$request = $this->createRequest($this->fixedRootPackage, $platformRepo);
$links = $this->package->getRequires();
foreach ($links as $link) {
$request->requireName($link->getTarget(), $link->getConstraint());
}
$this->requirePackagesForUpdate($request, $lockedRepository, false);
$pool = $repositorySet->createPoolWithAllPackages();
@ -815,12 +796,9 @@ class Installer
}
/**
* @param RootPackageInterface $rootPackage
* @param PlatformRepository $platformRepo
* @param RepositoryInterface|null $lockedRepository
* @return Request
*/
private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo, $lockedRepository = null)
private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo, LockArrayRepository $lockedRepository = null)
{
$request = new Request($lockedRepository);
@ -851,6 +829,33 @@ class Installer
return $request;
}
private function requirePackagesForUpdate(Request $request, LockArrayRepository $lockedRepository = null, $includeDevRequires = true)
{
// if we're updating mirrors we want to keep exactly the same versions installed which are in the lock file, but we want current remote metadata
if ($this->updateMirrors) {
$excludedPackages = array();
if (!$includeDevRequires) {
$excludedPackages = array_flip($this->locker->getDevPackageNames());
}
foreach ($lockedRepository->getPackages() as $lockedPackage) {
// exclude alias packages here as for root aliases, both alias and aliased are
// present in the lock repo and we only want to require the aliased version
if (!$lockedPackage instanceof AliasPackage && !isset($excludedPackages[$lockedPackage->getName()])) {
$request->requireName($lockedPackage->getName(), new Constraint('==', $lockedPackage->getVersion()));
}
}
} else {
$links = $this->package->getRequires();
if ($includeDevRequires) {
$links = array_merge($links, $this->package->getDevRequires());
}
foreach ($links as $link) {
$request->requireName($link->getTarget(), $link->getConstraint());
}
}
}
/**
* @param bool $forUpdate
* @return array
@ -870,7 +875,7 @@ class Installer
* @param array $links
* @return array
*/
private function extractPlatformRequirements($links)
private function extractPlatformRequirements(array $links)
{
$platformReqs = array();
foreach ($links as $link) {

View File

@ -31,7 +31,7 @@ Partial update without lock file should error
--RUN--
update b/unstable
--EXPECT-OUTPUT--
Cannot update only a partial set of packages without a lock file present.
Cannot update only a partial set of packages without a lock file present. Run `composer update` to generate a lock file.
--EXPECT-EXIT-CODE--
1
--EXPECT--

View File

@ -0,0 +1,65 @@
--TEST--
Update mirrors with a new root require which is not yet in lock should simply ignore it
--COMPOSER--
{
"repositories": [
{
"type": "package",
"package": [
{"name": "a/a", "version": "1.0.0"},
{"name": "a/a", "version": "1.1.0"},
{"name": "b/b", "version": "1.0.0"},
{"name": "b/b", "version": "1.1.0"},
{"name": "new/req", "version": "1.0.0"},
{"name": "new/req", "version": "1.1.0"}
]
}
],
"require": {
"a/a": "1.*",
"new/req": "1.*"
},
"require-dev": {
"b/b": "1.*"
}
}
--INSTALLED--
[
{"name": "a/a", "version": "1.0.0"},
{"name": "b/b", "version": "1.0.0"}
]
--LOCK--
{
"packages": [
{"name": "a/a", "version": "1.0.0", "type": "library"}
],
"packages-dev": [
{"name": "b/b", "version": "1.0.0", "type": "library"}
],
"aliases": [],
"minimum-stability": "dev",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}
--RUN--
update mirrors
--EXPECT-LOCK--
{
"packages": [
{"name": "a/a", "version": "1.0.0", "type": "library"}
],
"packages-dev": [
{"name": "b/b", "version": "1.0.0", "type": "library"}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}
--EXPECT--