function Installer::doUpdate
@phpstan-return self::ERROR_*
1 call to Installer::doUpdate()
- Installer::run in vendor/
composer/ composer/ src/ Composer/ Installer.php - Run installation (or update)
File
-
vendor/
composer/ composer/ src/ Composer/ Installer.php, line 454
Class
- Installer
- @author Jordi Boggiano <j.boggiano@seld.be> @author Beau Simensen <beau@dflydev.com> @author Konstantin Kudryashov <ever.zet@gmail.com> @author Nils Adermann <naderman@naderman.de>
Namespace
ComposerCode
protected function doUpdate(InstalledRepositoryInterface $localRepo, bool $doInstall) : int {
$platformRepo = $this->createPlatformRepo(true);
$aliases = $this->getRootAliases(true);
$lockedRepository = null;
try {
if ($this->locker
->isLocked()) {
$lockedRepository = $this->locker
->getLockedRepository(true);
}
} catch (\Seld\JsonLint\ParsingException $e) {
if ($this->updateAllowList !== null || $this->updateMirrors) {
// in case we are doing a partial update or updating mirrors, the lock file is needed so we error
throw $e;
}
// otherwise, ignoring parse errors as the lock file will be regenerated from scratch when
// doing a full update
}
if (($this->updateAllowList !== null || $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 self::ERROR_NO_LOCK_FILE_FOR_PARTIAL_UPDATE;
}
$this->io
->writeError('<info>Loading composer repositories with package information</info>');
// creating repository set
$policy = $this->createPolicy(true, $lockedRepository);
$repositorySet = $this->createRepositorySet(true, $platformRepo, $aliases);
$repositories = $this->repositoryManager
->getRepositories();
foreach ($repositories as $repository) {
$repositorySet->addRepository($repository);
}
if ($lockedRepository) {
$repositorySet->addRepository($lockedRepository);
}
$request = $this->createRequest($this->fixedRootPackage, $platformRepo, $lockedRepository);
$this->requirePackagesForUpdate($request, $lockedRepository, true);
// pass the allow list into the request, so the pool builder can apply it
if ($this->updateAllowList !== null) {
$request->setUpdateAllowList($this->updateAllowList, $this->updateAllowTransitiveDependencies);
}
$pool = $repositorySet->createPool($request, $this->io, $this->eventDispatcher, $this->createPoolOptimizer($policy), $this->ignoredTypes, $this->allowedTypes);
$this->io
->writeError('<info>Updating dependencies</info>');
// solve dependencies
$solver = new Solver($policy, $pool, $this->io);
try {
$lockTransaction = $solver->solve($request, $this->platformRequirementFilter);
$ruleSetSize = $solver->getRuleSetSize();
$solver = null;
} catch (SolverProblemsException $e) {
$err = 'Your requirements could not be resolved to an installable set of packages.';
$prettyProblem = $e->getPrettyString($repositorySet, $request, $pool, $this->io
->isVerbose());
$this->io
->writeError('<error>' . $err . '</error>', true, IOInterface::QUIET);
$this->io
->writeError($prettyProblem);
if (!$this->devMode) {
$this->io
->writeError('<warning>Running update with --no-dev does not mean require-dev is ignored, it just means the packages will not be installed. If dev requirements are blocking the update you have to resolve those problems.</warning>', true, IOInterface::QUIET);
}
$ghe = new GithubActionError($this->io);
$ghe->emit($err . "\n" . $prettyProblem);
return max(self::ERROR_GENERIC_FAILURE, $e->getCode());
}
$this->io
->writeError("Analyzed " . count($pool) . " packages to resolve dependencies", true, IOInterface::VERBOSE);
$this->io
->writeError("Analyzed " . $ruleSetSize . " rules to resolve dependencies", true, IOInterface::VERBOSE);
$pool = null;
if (!$lockTransaction->getOperations()) {
$this->io
->writeError('Nothing to modify in lock file');
}
$exitCode = $this->extractDevPackages($lockTransaction, $platformRepo, $aliases, $policy, $lockedRepository);
if ($exitCode !== 0) {
return $exitCode;
}
\Composer\Semver\CompilingMatcher::clear();
// write lock
$platformReqs = $this->extractPlatformRequirements($this->package
->getRequires());
$platformDevReqs = $this->extractPlatformRequirements($this->package
->getDevRequires());
$installsUpdates = $uninstalls = [];
if ($lockTransaction->getOperations()) {
$installNames = $updateNames = $uninstallNames = [];
foreach ($lockTransaction->getOperations() as $operation) {
if ($operation instanceof InstallOperation) {
$installsUpdates[] = $operation;
$installNames[] = $operation->getPackage()
->getPrettyName() . ':' . $operation->getPackage()
->getFullPrettyVersion();
}
elseif ($operation instanceof UpdateOperation) {
// when mirrors/metadata from a package gets updated we do not want to list it as an
// update in the output as it is only an internal lock file metadata update
if ($this->updateMirrors && $operation->getInitialPackage()
->getName() === $operation->getTargetPackage()
->getName() && $operation->getInitialPackage()
->getVersion() === $operation->getTargetPackage()
->getVersion()) {
continue;
}
$installsUpdates[] = $operation;
$updateNames[] = $operation->getTargetPackage()
->getPrettyName() . ':' . $operation->getTargetPackage()
->getFullPrettyVersion();
}
elseif ($operation instanceof UninstallOperation) {
$uninstalls[] = $operation;
$uninstallNames[] = $operation->getPackage()
->getPrettyName();
}
}
if ($this->config
->get('lock')) {
$this->io
->writeError(sprintf("<info>Lock file operations: %d install%s, %d update%s, %d removal%s</info>", count($installNames), 1 === count($installNames) ? '' : 's', count($updateNames), 1 === count($updateNames) ? '' : 's', count($uninstalls), 1 === count($uninstalls) ? '' : 's'));
if ($installNames) {
$this->io
->writeError("Installs: " . implode(', ', $installNames), true, IOInterface::VERBOSE);
}
if ($updateNames) {
$this->io
->writeError("Updates: " . implode(', ', $updateNames), true, IOInterface::VERBOSE);
}
if ($uninstalls) {
$this->io
->writeError("Removals: " . implode(', ', $uninstallNames), true, IOInterface::VERBOSE);
}
}
}
$sortByName = static function ($a, $b) : int {
if ($a instanceof UpdateOperation) {
$a = $a->getTargetPackage()
->getName();
}
else {
$a = $a->getPackage()
->getName();
}
if ($b instanceof UpdateOperation) {
$b = $b->getTargetPackage()
->getName();
}
else {
$b = $b->getPackage()
->getName();
}
return strcmp($a, $b);
};
usort($uninstalls, $sortByName);
usort($installsUpdates, $sortByName);
foreach (array_merge($uninstalls, $installsUpdates) as $operation) {
// collect suggestions
if ($operation instanceof InstallOperation) {
$this->suggestedPackagesReporter
->addSuggestionsFromPackage($operation->getPackage());
}
// output op if lock file is enabled, but alias op only in debug verbosity
if ($this->config
->get('lock') && (false === strpos($operation->getOperationType(), 'Alias') || $this->io
->isDebug())) {
$sourceRepo = '';
if ($this->io
->isVeryVerbose() && false === strpos($operation->getOperationType(), 'Alias')) {
$operationPkg = $operation instanceof UpdateOperation ? $operation->getTargetPackage() : $operation->getPackage();
if ($operationPkg->getRepository() !== null) {
$sourceRepo = ' from ' . $operationPkg->getRepository()
->getRepoName();
}
}
$this->io
->writeError(' - ' . $operation->show(true) . $sourceRepo);
}
}
$updatedLock = $this->locker
->setLockData($lockTransaction->getNewLockPackages(false, $this->updateMirrors), $lockTransaction->getNewLockPackages(true, $this->updateMirrors), $platformReqs, $platformDevReqs, $lockTransaction->getAliases($aliases), $this->package
->getMinimumStability(), $this->package
->getStabilityFlags(), $this->preferStable || $this->package
->getPreferStable(), $this->preferLowest, $this->config
->get('platform') ?: [], $this->writeLock && $this->executeOperations);
if ($updatedLock && $this->writeLock && $this->executeOperations) {
$this->io
->writeError('<info>Writing lock file</info>');
}
if ($doInstall) {
// TODO ensure lock is used from locker as-is, since it may not have been written to disk in case of executeOperations == false
return $this->doInstall($localRepo, true);
}
return 0;
}