function UpdateCommand::execute
Overrides Command::execute
File
-
vendor/
composer/ composer/ src/ Composer/ Command/ UpdateCommand.php, line 126
Class
- UpdateCommand
- @author Jordi Boggiano <j.boggiano@seld.be> @author Nils Adermann <naderman@naderman.de>
Namespace
Composer\CommandCode
protected function execute(InputInterface $input, OutputInterface $output) : int {
$io = $this->getIO();
if ($input->getOption('dev')) {
$io->writeError('<warning>You are using the deprecated option "--dev". It has no effect and will break in Composer 3.</warning>');
}
if ($input->getOption('no-suggest')) {
$io->writeError('<warning>You are using the deprecated option "--no-suggest". It has no effect and will break in Composer 3.</warning>');
}
$composer = $this->requireComposer();
if (!HttpDownloader::isCurlEnabled()) {
$io->writeError('<warning>Composer is operating significantly slower than normal because you do not have the PHP curl extension enabled.</warning>');
}
$packages = $input->getArgument('packages');
$reqs = $this->formatRequirements($input->getOption('with'));
// extract --with shorthands from the allowlist
if (count($packages) > 0) {
$allowlistPackagesWithRequirements = array_filter($packages, static function ($pkg) : bool {
return Preg::isMatch('{\\S+[ =:]\\S+}', $pkg);
});
foreach ($this->formatRequirements($allowlistPackagesWithRequirements) as $package => $constraint) {
$reqs[$package] = $constraint;
}
// replace the foo/bar:req by foo/bar in the allowlist
foreach ($allowlistPackagesWithRequirements as $package) {
$packageName = Preg::replace('{^([^ =:]+)[ =:].*$}', '$1', $package);
$index = array_search($package, $packages);
$packages[$index] = $packageName;
}
}
$rootPackage = $composer->getPackage();
$rootPackage->setReferences(RootPackageLoader::extractReferences($reqs, $rootPackage->getReferences()));
$rootPackage->setStabilityFlags(RootPackageLoader::extractStabilityFlags($reqs, $rootPackage->getMinimumStability(), $rootPackage->getStabilityFlags()));
$parser = new VersionParser();
$temporaryConstraints = [];
$rootRequirements = array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires());
foreach ($reqs as $package => $constraint) {
$package = strtolower($package);
$parsedConstraint = $parser->parseConstraints($constraint);
$temporaryConstraints[$package] = $parsedConstraint;
if (isset($rootRequirements[$package]) && !Intervals::haveIntersections($parsedConstraint, $rootRequirements[$package]->getConstraint())) {
$io->writeError('<error>The temporary constraint "' . $constraint . '" for "' . $package . '" must be a subset of the constraint in your composer.json (' . $rootRequirements[$package]->getPrettyConstraint() . ')</error>');
$io->write('<info>Run `composer require ' . $package . '` or `composer require ' . $package . ':' . $constraint . '` instead to replace the constraint</info>');
return self::FAILURE;
}
}
if ($input->getOption('patch-only')) {
if (!$composer->getLocker()
->isLocked()) {
throw new \InvalidArgumentException('patch-only can only be used with a lock file present');
}
foreach ($composer->getLocker()
->getLockedRepository(true)
->getCanonicalPackages() as $package) {
if ($package->isDev()) {
continue;
}
if (!Preg::isMatch('{^(\\d+\\.\\d+\\.\\d+)}', $package->getVersion(), $match)) {
continue;
}
$constraint = $parser->parseConstraints('~' . $match[1]);
if (isset($temporaryConstraints[$package->getName()])) {
$temporaryConstraints[$package->getName()] = MultiConstraint::create([
$temporaryConstraints[$package->getName()],
$constraint,
], true);
}
else {
$temporaryConstraints[$package->getName()] = $constraint;
}
}
}
if ($input->getOption('interactive')) {
$packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages);
}
if ($input->getOption('root-reqs')) {
$requires = array_keys($rootPackage->getRequires());
if (!$input->getOption('no-dev')) {
$requires = array_merge($requires, array_keys($rootPackage->getDevRequires()));
}
if (!empty($packages)) {
$packages = array_intersect($packages, $requires);
}
else {
$packages = $requires;
}
}
// the arguments lock/nothing/mirrors are not package names but trigger a mirror update instead
// they are further mutually exclusive with listing actual package names
$filteredPackages = array_filter($packages, static function ($package) : bool {
return !in_array($package, [
'lock',
'nothing',
'mirrors',
], true);
});
$updateMirrors = $input->getOption('lock') || count($filteredPackages) !== count($packages);
$packages = $filteredPackages;
if ($updateMirrors && !empty($packages)) {
$io->writeError('<error>You cannot simultaneously update only a selection of packages and regenerate the lock file metadata.</error>');
return -1;
}
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
$composer->getEventDispatcher()
->dispatch($commandEvent->getName(), $commandEvent);
$composer->getInstallationManager()
->setOutputProgress(!$input->getOption('no-progress'));
$install = Installer::create($io, $composer);
$config = $composer->getConfig();
[
$preferSource,
$preferDist,
] = $this->getPreferredInstallOptions($config, $input);
$optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
$authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
$apcuPrefix = $input->getOption('apcu-autoloader-prefix');
$apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
$updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED;
if ($input->getOption('with-all-dependencies')) {
$updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS;
}
elseif ($input->getOption('with-dependencies')) {
$updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE;
}
$install->setDryRun($input->getOption('dry-run'))
->setVerbose($input->getOption('verbose'))
->setPreferSource($preferSource)
->setPreferDist($preferDist)
->setDevMode(!$input->getOption('no-dev'))
->setDumpAutoloader(!$input->getOption('no-autoloader'))
->setOptimizeAutoloader($optimize)
->setClassMapAuthoritative($authoritative)
->setApcuAutoloader($apcu, $apcuPrefix)
->setUpdate(true)
->setInstall(!$input->getOption('no-install'))
->setUpdateMirrors($updateMirrors)
->setUpdateAllowList($packages)
->setUpdateAllowTransitiveDependencies($updateAllowTransitiveDependencies)
->setPlatformRequirementFilter($this->getPlatformRequirementFilter($input))
->setPreferStable($input->getOption('prefer-stable'))
->setPreferLowest($input->getOption('prefer-lowest'))
->setTemporaryConstraints($temporaryConstraints)
->setAudit(!$input->getOption('no-audit'))
->setAuditFormat($this->getAuditFormat($input))
->setMinimalUpdate($input->getOption('minimal-changes'));
if ($input->getOption('no-plugins')) {
$install->disablePlugins();
}
$result = $install->run();
if ($result === 0) {
$bumpAfterUpdate = $input->getOption('bump-after-update');
if (false === $bumpAfterUpdate) {
$bumpAfterUpdate = $composer->getConfig()
->get('bump-after-update');
}
if (false !== $bumpAfterUpdate) {
$io->writeError('<info>Bumping dependencies</info>');
$bumpCommand = new BumpCommand();
$bumpCommand->setComposer($composer);
$result = $bumpCommand->doBump($io, $bumpAfterUpdate === 'dev', $bumpAfterUpdate === 'no-dev', $input->getOption('dry-run'), $input->getArgument('packages'));
}
}
return $result;
}