Browse Source

Add prefer-stable flag to pick stable package over unstable ones when possible

Jordi Boggiano 12 years ago
parent
commit
b0297ef67a

+ 4 - 0
res/composer-schema.json

@@ -221,6 +221,10 @@
             "type": ["string"],
             "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable."
         },
+        "prefer-stable": {
+            "type": ["boolean"],
+            "description": "If set to true, stable packages will be prefered to dev packages when possible, even if the minimum-stability allows unstable packages."
+        },
         "bin": {
             "type": ["array"],
             "description": "A set of files that should be treated as binaries and symlinked into bin-dir (from config).",

+ 13 - 0
src/Composer/DependencyResolver/DefaultPolicy.php

@@ -14,15 +14,28 @@ namespace Composer\DependencyResolver;
 
 use Composer\Package\PackageInterface;
 use Composer\Package\AliasPackage;
+use Composer\Package\BasePackage;
 use Composer\Package\LinkConstraint\VersionConstraint;
 
 /**
  * @author Nils Adermann <naderman@naderman.de>
+ * @author Jordi Boggiano <j.boggiano@seld.be>
  */
 class DefaultPolicy implements PolicyInterface
 {
+    private $preferStable;
+
+    public function __construct($preferStable = false)
+    {
+        $this->preferStable = $preferStable;
+    }
+
     public function versionCompare(PackageInterface $a, PackageInterface $b, $operator)
     {
+        if ($this->preferStable && ($stabA = $a->getStability()) !== ($stabB = $b->getStability())) {
+            return BasePackage::$stabilities[$stabA] < BasePackage::$stabilities[$stabB];
+        }
+
         $constraint = new VersionConstraint($operator, $b->getVersion());
         $version = new VersionConstraint('==', $a->getVersion());
 

+ 7 - 2
src/Composer/Installer.php

@@ -234,7 +234,7 @@ class Installer
 
                 // split dev and non-dev requirements by checking what would be removed if we update without the dev requirements
                 if ($this->devMode && $this->package->getDevRequires()) {
-                    $policy = new DefaultPolicy();
+                    $policy = $this->createPolicy();
                     $pool = $this->createPool();
                     $pool->addRepository($installedRepo, $aliases);
 
@@ -308,7 +308,7 @@ class Installer
         $this->io->write('<info>Loading composer repositories with package information</info>');
 
         // creating repository pool
-        $policy = new DefaultPolicy();
+        $policy = $this->createPolicy();
         $pool = $this->createPool();
         $pool->addRepository($installedRepo, $aliases);
         if ($installFromLock) {
@@ -513,6 +513,11 @@ class Installer
         return new Pool($minimumStability, $stabilityFlags);
     }
 
+    private function createPolicy()
+    {
+        return new DefaultPolicy($this->package->getPreferStable());
+    }
+
     private function createRequest(Pool $pool, RootPackageInterface $rootPackage, PlatformRepository $platformRepo)
     {
         $request = new Request($pool);

+ 4 - 0
src/Composer/Package/Loader/RootPackageLoader.php

@@ -91,6 +91,10 @@ class RootPackageLoader extends ArrayLoader
             $package->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
         }
 
+        if (isset($config['prefer-stable'])) {
+            $package->setPreferStable((bool) $config['prefer-stable']);
+        }
+
         $repos = Factory::createDefaultRepositories(null, $this->config, $this->manager);
         foreach ($repos as $repo) {
             $this->manager->addRepository($repo);

+ 19 - 0
src/Composer/Package/RootPackage.php

@@ -20,6 +20,7 @@ namespace Composer\Package;
 class RootPackage extends CompletePackage implements RootPackageInterface
 {
     protected $minimumStability = 'stable';
+    protected $preferStable = false;
     protected $stabilityFlags = array();
     protected $references = array();
 
@@ -59,6 +60,24 @@ class RootPackage extends CompletePackage implements RootPackageInterface
         return $this->stabilityFlags;
     }
 
+    /**
+     * Set the preferStable
+     *
+     * @param bool $preferStable
+     */
+    public function setPreferStable($preferStable)
+    {
+        $this->preferStable = $preferStable;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function getPreferStable()
+    {
+        return $this->preferStable;
+    }
+
     /**
      * Set the references
      *

+ 29 - 0
tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php

@@ -65,6 +65,35 @@ class DefaultPolicyTest extends TestCase
         $this->assertEquals($expected, $selected);
     }
 
+    public function testSelectNewestPicksLatest()
+    {
+        $this->repo->addPackage($packageA1 = $this->getPackage('A', '1.0.0'));
+        $this->repo->addPackage($packageA2 = $this->getPackage('A', '1.0.1-alpha'));
+        $this->pool->addRepository($this->repo);
+
+        $literals = array($packageA1->getId(), $packageA2->getId());
+        $expected = array($packageA2->getId());
+
+        $selected = $this->policy->selectPreferedPackages($this->pool, array(), $literals);
+
+        $this->assertEquals($expected, $selected);
+    }
+
+    public function testSelectNewestPicksLatestStableWithPreferStable()
+    {
+        $this->repo->addPackage($packageA1 = $this->getPackage('A', '1.0.0'));
+        $this->repo->addPackage($packageA2 = $this->getPackage('A', '1.0.1-alpha'));
+        $this->pool->addRepository($this->repo);
+
+        $literals = array($packageA1->getId(), $packageA2->getId());
+        $expected = array($packageA1->getId());
+
+        $policy = new DefaultPolicy(true);
+        $selected = $policy->selectPreferedPackages($this->pool, array(), $literals);
+
+        $this->assertEquals($expected, $selected);
+    }
+
     public function testSelectNewestOverInstalled()
     {
         $this->repo->addPackage($packageA = $this->getPackage('A', '2.0'));