diff --git a/src/Composer/Command/DiagnoseCommand.php b/src/Composer/Command/DiagnoseCommand.php index 8fcd2f895..f6b5a7d94 100644 --- a/src/Composer/Command/DiagnoseCommand.php +++ b/src/Composer/Command/DiagnoseCommand.php @@ -22,7 +22,8 @@ use Composer\Util\ConfigValidator; use Composer\Util\ProcessExecutor; use Composer\Util\RemoteFilesystem; use Composer\Util\StreamContextFactory; -use Composer\Util\Keys; +use Composer\SelfUpdate\Keys; +use Composer\SelfUpdate\Versions; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -141,7 +142,7 @@ EOT $this->outputResult($this->checkPubKeys($config)); $io->write('Checking composer version: ', false); - $this->outputResult($this->checkVersion()); + $this->outputResult($this->checkVersion($config)); } return $this->failures; @@ -364,13 +365,13 @@ EOT return $errors ?: true; } - private function checkVersion() + private function checkVersion($config) { - $protocol = extension_loaded('openssl') ? 'https' : 'http'; - $latest = trim($this->rfs->getContents('getcomposer.org', $protocol . '://getcomposer.org/version', false)); + $versionsUtil = new Versions($config, $this->rfs); + $latest = $versionsUtil->getLatest(); - if (Composer::VERSION !== $latest && Composer::VERSION !== '@package_version@') { - return 'You are not running the latest version, run `composer self-update` to update'; + if (Composer::VERSION !== $latest['version'] && Composer::VERSION !== '@package_version@') { + return 'You are not running the latest '.$versionsUtil->getChannel().' version, run `composer self-update` to update ('.Composer::VERSION.' => '.$latest['version'].')'; } return true; diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index a5590164f..c128c6013 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -16,7 +16,8 @@ use Composer\Composer; use Composer\Factory; use Composer\Config; use Composer\Util\Filesystem; -use Composer\Util\Keys; +use Composer\SelfUpdate\Keys; +use Composer\SelfUpdate\Versions; use Composer\IO\IOInterface; use Composer\Downloader\FilesystemException; use Symfony\Component\Console\Input\InputInterface; @@ -47,6 +48,9 @@ class SelfUpdateCommand extends BaseCommand new InputArgument('version', InputArgument::OPTIONAL, 'The version to update to'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('update-keys', null, InputOption::VALUE_NONE, 'Prompt user for a key update'), + new InputOption('stable', null, InputOption::VALUE_NONE, 'Force an update to the stable channel'), + new InputOption('preview', null, InputOption::VALUE_NONE, 'Force an update to the preview channel'), + new InputOption('snapshot', null, InputOption::VALUE_NONE, 'Force an update to the snapshot channel'), )) ->setHelp(<<self-update command checks getcomposer.org for newer @@ -72,6 +76,15 @@ EOT $io = $this->getIO(); $remoteFilesystem = Factory::createRemoteFilesystem($io, $config); + $versionsUtil = new Versions($config, $remoteFilesystem); + + // switch channel if requested + foreach (array('stable', 'preview', 'snapshot') as $channel) { + if ($input->getOption($channel)) { + $versionsUtil->setChannel($channel); + } + } + $cacheDir = $config->get('cache-dir'); $rollbackDir = $config->get('data-dir'); $home = $config->get('home'); @@ -93,7 +106,8 @@ EOT return $this->rollback($output, $rollbackDir, $localFilename); } - $latestVersion = trim($remoteFilesystem->getContents(self::HOMEPAGE, $baseUrl. '/version', false)); + $latest = $versionsUtil->getLatest(); + $latestVersion = $latest['version']; $updateVersion = $input->getArgument('version') ?: $latestVersion; if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) { diff --git a/src/Composer/Util/Keys.php b/src/Composer/SelfUpdate/Keys.php similarity index 96% rename from src/Composer/Util/Keys.php rename to src/Composer/SelfUpdate/Keys.php index 4afa204cd..a8f02e3e2 100644 --- a/src/Composer/Util/Keys.php +++ b/src/Composer/SelfUpdate/Keys.php @@ -10,7 +10,7 @@ * file that was distributed with this source code. */ -namespace Composer\Util; +namespace Composer\SelfUpdate; /** * @author Jordi Boggiano diff --git a/src/Composer/SelfUpdate/Versions.php b/src/Composer/SelfUpdate/Versions.php new file mode 100644 index 000000000..b619bda16 --- /dev/null +++ b/src/Composer/SelfUpdate/Versions.php @@ -0,0 +1,75 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\SelfUpdate; + +use Composer\Util\RemoteFilesystem; +use Composer\Config; +use Composer\Json\JsonFile; + +/** + * @author Jordi Boggiano + */ +class Versions +{ + private $rfs; + private $config; + private $channel; + + public function __construct(Config $config, RemoteFilesystem $rfs) + { + $this->rfs = $rfs; + $this->config = $config; + } + + public function getChannel() + { + if ($this->channel) { + return $this->channel; + } + + $channelFile = $this->config->get('home').'/update-channel'; + if (file_exists($channelFile)) { + $channel = trim(file_get_contents($channelFile)); + if (in_array($channel, array('stable', 'preview', 'snapshot'), true)) { + return $this->channel = $channel; + } + } + + return $this->channel = 'stable'; + } + + public function setChannel($channel) + { + if (!in_array($channel, array('stable', 'preview', 'snapshot'), true)) { + throw new \InvalidArgumentException('Invalid channel '.$channel.', must be one of: stable, preview, snapshot'); + } + + $channelFile = $this->config->get('home').'/update-channel'; + $this->channel = $channel; + file_put_contents($channelFile, $channel.PHP_EOL); + } + + public function getLatest() + { + $protocol = extension_loaded('openssl') ? 'https' : 'http'; + $versions = JsonFile::parseJson($this->rfs->getContents('getcomposer.org', $protocol . '://getcomposer.org/versions', false)); + + foreach ($versions[$this->getChannel()] as $version) { + if ($version['min-php'] <= PHP_VERSION_ID) { + return $version; + } + } + + throw new \LogicException('There is no version of Composer available for your PHP version ('.PHP_VERSION.')'); + } +}