ソースを参照

Merge pull request #5064 from Seldaek/update-channels

Add update channels support to self-update and diagnose
Jordi Boggiano 9 年 前
コミット
95c263284a

+ 8 - 7
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 '<comment>You are not running the latest version, run `composer self-update` to update</comment>';
+        if (Composer::VERSION !== $latest['version'] && Composer::VERSION !== '@package_version@') {
+            return '<comment>You are not running the latest '.$versionsUtil->getChannel().' version, run `composer self-update` to update ('.Composer::VERSION.' => '.$latest['version'].')</comment>';
         }
 
         return true;

+ 16 - 2
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(<<<EOT
 The <info>self-update</info> 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) {

+ 1 - 1
src/Composer/Util/Keys.php → 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 <j.boggiano@seld.be>

+ 75 - 0
src/Composer/SelfUpdate/Versions.php

@@ -0,0 +1,75 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * 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 <j.boggiano@seld.be>
+ */
+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.')');
+    }
+}