diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index d79d22df2..e5550d14e 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -135,8 +135,36 @@ EOT $latest = $versionsUtil->getLatest(); $latestStable = $versionsUtil->getLatest('stable'); + try { + $latestPreview = $versionsUtil->getLatest('preview'); + } catch (\UnexpectedValueException $e) { + $latestPreview = $latestStable; + } $latestVersion = $latest['version']; $updateVersion = $input->getArgument('version') ?: $latestVersion; + $currentMajorVersion = preg_replace('{^(\d+).*}', '$1', Composer::getVersion()); + $updateMajorVersion = preg_replace('{^(\d+).*}', '$1', $updateVersion); + $previewMajorVersion = preg_replace('{^(\d+).*}', '$1', $latestPreview['version']); + + if ($versionsUtil->getChannel() === 'stable' && !$input->getArgument('version')) { + // if requesting stable channel and no specific version, avoid automatically upgrading to the next major + // simply output a warning that the next major stable is available and let users upgrade to it manually + if ($currentMajorVersion < $updateMajorVersion) { + $skippedVersion = $updateVersion; + + $versionsUtil->setChannel($currentMajorVersion); + + $latest = $versionsUtil->getLatest(); + $latestStable = $versionsUtil->getLatest('stable'); + $latestVersion = $latest['version']; + $updateVersion = $latestVersion; + + $io->writeError('A new stable major version of Composer is available ('.$skippedVersion.'), run "composer self-update --'.$updateMajorVersion.'" to update to it. See also https://github.com/composer/composer/releases for changelogs.'); + } elseif ($currentMajorVersion < $previewMajorVersion) { + // promote next major version if available in preview + $io->writeError('A preview release of the next major version of Composer is available ('.$latestPreview['version'].'), run "composer self-update --preview" to give it a try. See also https://github.com/composer/composer/releases for changelogs.'); + } + } if ($requestedChannel && is_numeric($requestedChannel) && substr($latestStable['version'], 0, 1) !== $requestedChannel) { $io->writeError('Warning: You forced the install of '.$latestVersion.' via --'.$requestedChannel.', but '.$latestStable['version'].' is the latest stable version. Updating to it via composer self-update --stable is recommended.'); diff --git a/src/Composer/DependencyResolver/DefaultPolicy.php b/src/Composer/DependencyResolver/DefaultPolicy.php index 235987aa3..4f3bdefa3 100644 --- a/src/Composer/DependencyResolver/DefaultPolicy.php +++ b/src/Composer/DependencyResolver/DefaultPolicy.php @@ -60,7 +60,7 @@ class DefaultPolicy implements PolicyInterface $sortedLiterals = $this->pruneRemoteAliases($pool, $sortedLiterals); } - $selected = \call_user_func_array('array_merge', $packages); + $selected = \call_user_func_array('array_merge', array_values($packages)); // now sort the result across all packages to respect replaces across packages usort($selected, function ($a, $b) use ($policy, $pool, $requiredPackage) { diff --git a/src/Composer/Repository/Vcs/BitbucketDriver.php b/src/Composer/Repository/Vcs/BitbucketDriver.php index 22180b55d..d23b32dd2 100644 --- a/src/Composer/Repository/Vcs/BitbucketDriver.php +++ b/src/Composer/Repository/Vcs/BitbucketDriver.php @@ -120,10 +120,14 @@ abstract class BitbucketDriver extends VcsDriver if (!isset($this->infoCache[$identifier])) { if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) { - return $this->infoCache[$identifier] = JsonFile::parseJson($res); - } + $composer = JsonFile::parseJson($res); + } else { + $composer = $this->getBaseComposerInformation($identifier); - $composer = $this->getBaseComposerInformation($identifier); + if ($this->shouldCache($identifier)) { + $this->cache->write($identifier, json_encode($composer)); + } + } if ($composer) { // specials for bitbucket @@ -174,10 +178,6 @@ abstract class BitbucketDriver extends VcsDriver } $this->infoCache[$identifier] = $composer; - - if ($this->shouldCache($identifier)) { - $this->cache->write($identifier, json_encode($composer)); - } } return $this->infoCache[$identifier]; diff --git a/src/Composer/Repository/Vcs/GitHubDriver.php b/src/Composer/Repository/Vcs/GitHubDriver.php index 0a97123c0..83e353321 100644 --- a/src/Composer/Repository/Vcs/GitHubDriver.php +++ b/src/Composer/Repository/Vcs/GitHubDriver.php @@ -151,10 +151,14 @@ class GitHubDriver extends VcsDriver if (!isset($this->infoCache[$identifier])) { if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) { - return $this->infoCache[$identifier] = JsonFile::parseJson($res); - } + $composer = JsonFile::parseJson($res); + } else { + $composer = $this->getBaseComposerInformation($identifier); - $composer = $this->getBaseComposerInformation($identifier); + if ($this->shouldCache($identifier)) { + $this->cache->write($identifier, json_encode($composer)); + } + } if ($composer) { // specials for github @@ -173,10 +177,6 @@ class GitHubDriver extends VcsDriver } } - if ($this->shouldCache($identifier)) { - $this->cache->write($identifier, json_encode($composer)); - } - $this->infoCache[$identifier] = $composer; } diff --git a/src/Composer/Repository/Vcs/GitLabDriver.php b/src/Composer/Repository/Vcs/GitLabDriver.php index 8f0ed6f0f..22f884d7f 100644 --- a/src/Composer/Repository/Vcs/GitLabDriver.php +++ b/src/Composer/Repository/Vcs/GitLabDriver.php @@ -131,10 +131,14 @@ class GitLabDriver extends VcsDriver if (!isset($this->infoCache[$identifier])) { if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) { - return $this->infoCache[$identifier] = JsonFile::parseJson($res); - } + $composer = JsonFile::parseJson($res); + } else { + $composer = $this->getBaseComposerInformation($identifier); - $composer = $this->getBaseComposerInformation($identifier); + if ($this->shouldCache($identifier)) { + $this->cache->write($identifier, json_encode($composer)); + } + } if ($composer) { // specials for gitlab (this data is only available if authentication is provided) @@ -146,10 +150,6 @@ class GitLabDriver extends VcsDriver } } - if ($this->shouldCache($identifier)) { - $this->cache->write($identifier, json_encode($composer)); - } - $this->infoCache[$identifier] = $composer; } @@ -448,7 +448,7 @@ class GitLabDriver extends VcsDriver if (!$moreThanGuestAccess) { $this->io->writeError('GitLab token with Guest only access detected'); - return $this->attemptCloneFallback(); + return $this->attemptCloneFallback(); } } diff --git a/src/Composer/SelfUpdate/Versions.php b/src/Composer/SelfUpdate/Versions.php index 6d1379d41..21b48d9e5 100644 --- a/src/Composer/SelfUpdate/Versions.php +++ b/src/Composer/SelfUpdate/Versions.php @@ -26,6 +26,7 @@ class Versions private $httpDownloader; private $config; private $channel; + private $versionsData; public function __construct(Config $config, HttpDownloader $httpDownloader) { @@ -63,12 +64,7 @@ class Versions public function getLatest($channel = null) { - if ($this->config->get('disable-tls') === true) { - $protocol = 'http'; - } else { - $protocol = 'https'; - } - $versions = $this->httpDownloader->get($protocol . '://getcomposer.org/versions')->decodeJson(); + $versions = $this->getVersionsData(); foreach ($versions[$channel ?: $this->getChannel()] as $version) { if ($version['min-php'] <= PHP_VERSION_ID) { @@ -76,6 +72,21 @@ class Versions } } - throw new \LogicException('There is no version of Composer available for your PHP version ('.PHP_VERSION.')'); + throw new \UnexpectedValueException('There is no version of Composer available for your PHP version ('.PHP_VERSION.')'); + } + + private function getVersionsData() + { + if (!$this->versionsData) { + if ($this->config->get('disable-tls') === true) { + $protocol = 'http'; + } else { + $protocol = 'https'; + } + + $this->versionsData = $this->httpDownloader->get($protocol . '://getcomposer.org/versions')->decodeJson(); + } + + return $this->versionsData; } }