function Installer::doInstall
@phpstan-return self::ERROR_*
Parameters
bool $alreadySolved Whether the function is called as part of an update command or independently:
Return value
int exit code
2 calls to Installer::doInstall()
- Installer::doUpdate in vendor/
composer/ composer/ src/ Composer/ Installer.php - @phpstan-return self::ERROR_*
- Installer::run in vendor/
composer/ composer/ src/ Composer/ Installer.php - Run installation (or update)
File
-
vendor/
composer/ composer/ src/ Composer/ Installer.php, line 714
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 doInstall(InstalledRepositoryInterface $localRepo, bool $alreadySolved = false) : int {
if ($this->config
->get('lock')) {
$this->io
->writeError('<info>Installing dependencies from lock file' . ($this->devMode ? ' (including require-dev)' : '') . '</info>');
}
$lockedRepository = $this->locker
->getLockedRepository($this->devMode);
// verify that the lock file works with the current platform repository
// we can skip this part if we're doing this as the second step after an update
if (!$alreadySolved) {
$this->io
->writeError('<info>Verifying lock file contents can be installed on current platform.</info>');
$platformRepo = $this->createPlatformRepo(false);
// creating repository set
$policy = $this->createPolicy(false);
// use aliases from lock file only, so empty root aliases here
$repositorySet = $this->createRepositorySet(false, $platformRepo, [], $lockedRepository);
$repositorySet->addRepository($lockedRepository);
// creating requirements request
$request = $this->createRequest($this->fixedRootPackage, $platformRepo, $lockedRepository);
if (!$this->locker
->isFresh()) {
$this->io
->writeError('<warning>Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. It is recommended that you run `composer update` or `composer update <package name>`.</warning>', true, IOInterface::QUIET);
}
$missingRequirementInfo = $this->locker
->getMissingRequirementInfo($this->package, $this->devMode);
if ($missingRequirementInfo !== []) {
$this->io
->writeError($missingRequirementInfo);
if (!$this->config
->get('allow-missing-requirements')) {
return self::ERROR_LOCK_FILE_INVALID;
}
}
foreach ($lockedRepository->getPackages() as $package) {
$request->fixLockedPackage($package);
}
$rootRequires = $this->package
->getRequires();
if ($this->devMode) {
$rootRequires = array_merge($rootRequires, $this->package
->getDevRequires());
}
foreach ($rootRequires as $link) {
if (PlatformRepository::isPlatformPackage($link->getTarget())) {
$request->requireName($link->getTarget(), $link->getConstraint());
}
}
foreach ($this->locker
->getPlatformRequirements($this->devMode) as $link) {
if (!isset($rootRequires[$link->getTarget()])) {
$request->requireName($link->getTarget(), $link->getConstraint());
}
}
unset($rootRequires, $link);
$pool = $repositorySet->createPool($request, $this->io, $this->eventDispatcher, null, $this->ignoredTypes, $this->allowedTypes);
// solve dependencies
$solver = new Solver($policy, $pool, $this->io);
try {
$lockTransaction = $solver->solve($request, $this->platformRequirementFilter);
$solver = null;
// installing the locked packages on this platform resulted in lock modifying operations, there wasn't a conflict, but the lock file as-is seems to not work on this system
if (0 !== count($lockTransaction->getOperations())) {
$this->io
->writeError('<error>Your lock file cannot be installed on this system without changes. Please run composer update.</error>', true, IOInterface::QUIET);
return self::ERROR_LOCK_FILE_INVALID;
}
} catch (SolverProblemsException $e) {
$err = 'Your lock file does not contain a compatible set of packages. Please run composer update.';
$prettyProblem = $e->getPrettyString($repositorySet, $request, $pool, $this->io
->isVerbose());
$this->io
->writeError('<error>' . $err . '</error>', true, IOInterface::QUIET);
$this->io
->writeError($prettyProblem);
$ghe = new GithubActionError($this->io);
$ghe->emit($err . "\n" . $prettyProblem);
return max(self::ERROR_GENERIC_FAILURE, $e->getCode());
}
}
// TODO in how far do we need to do anything here to ensure dev packages being updated to latest in lock without version change are treated correctly?
$localRepoTransaction = new LocalRepoTransaction($lockedRepository, $localRepo);
$this->eventDispatcher
->dispatchInstallerEvent(InstallerEvents::PRE_OPERATIONS_EXEC, $this->devMode, $this->executeOperations, $localRepoTransaction);
$installs = $updates = $uninstalls = [];
foreach ($localRepoTransaction->getOperations() as $operation) {
if ($operation instanceof InstallOperation) {
$installs[] = $operation->getPackage()
->getPrettyName() . ':' . $operation->getPackage()
->getFullPrettyVersion();
}
elseif ($operation instanceof UpdateOperation) {
$updates[] = $operation->getTargetPackage()
->getPrettyName() . ':' . $operation->getTargetPackage()
->getFullPrettyVersion();
}
elseif ($operation instanceof UninstallOperation) {
$uninstalls[] = $operation->getPackage()
->getPrettyName();
}
}
if ($installs === [] && $updates === [] && $uninstalls === []) {
$this->io
->writeError('Nothing to install, update or remove');
}
else {
$this->io
->writeError(sprintf("<info>Package operations: %d install%s, %d update%s, %d removal%s</info>", count($installs), 1 === count($installs) ? '' : 's', count($updates), 1 === count($updates) ? '' : 's', count($uninstalls), 1 === count($uninstalls) ? '' : 's'));
if ($installs) {
$this->io
->writeError("Installs: " . implode(', ', $installs), true, IOInterface::VERBOSE);
}
if ($updates) {
$this->io
->writeError("Updates: " . implode(', ', $updates), true, IOInterface::VERBOSE);
}
if ($uninstalls) {
$this->io
->writeError("Removals: " . implode(', ', $uninstalls), true, IOInterface::VERBOSE);
}
}
if ($this->executeOperations) {
$localRepo->setDevPackageNames($this->locker
->getDevPackageNames());
$this->installationManager
->execute($localRepo, $localRepoTransaction->getOperations(), $this->devMode, $this->runScripts, $this->downloadOnly);
// see https://github.com/composer/composer/issues/2764
if (count($localRepoTransaction->getOperations()) > 0) {
$vendorDir = $this->config
->get('vendor-dir');
if (is_dir($vendorDir)) {
// suppress errors as this fails sometimes on OSX for no apparent reason
// see https://github.com/composer/composer/issues/4070#issuecomment-129792748
@touch($vendorDir);
}
}
}
else {
foreach ($localRepoTransaction->getOperations() as $operation) {
// output op, but alias op only in debug verbosity
if (false === strpos($operation->getOperationType(), 'Alias') || $this->io
->isDebug()) {
$this->io
->writeError(' - ' . $operation->show(false));
}
}
}
return 0;
}