@ -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) {