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;
}
}