Browse Source

Basic handling of stability flags

Jordi Boggiano 13 years ago
parent
commit
ef28f3b067

+ 25 - 18
src/Composer/DependencyResolver/Pool.php

@@ -12,6 +12,7 @@
 
 namespace Composer\DependencyResolver;
 
+use Composer\Package\BasePackage;
 use Composer\Package\LinkConstraint\LinkConstraintInterface;
 use Composer\Repository\RepositoryInterface;
 use Composer\Repository\CompositeRepository;
@@ -30,18 +31,13 @@ class Pool
     protected $packages = array();
     protected $packageByName = array();
     protected $acceptableStabilities;
+    protected $stabilityFlags;
 
-    public function __construct($minimumStability = 'dev')
+    public function __construct($minimumStability = 'dev', array $stabilityFlags = array())
     {
-        $stabilities = array(
-            'stable',
-            'RC',
-            'beta',
-            'alpha',
-            'dev',
-        );
-
+        $stabilities = BasePackage::$stabilities;
         $this->acceptableStabilities = array_flip(array_splice($stabilities, 0, array_search($minimumStability, $stabilities) + 1));
+        $this->stabilityFlags = $stabilityFlags;
     }
 
     /**
@@ -57,20 +53,31 @@ class Pool
             $repos = array($repo);
         }
 
+        $id = count($this->packages) + 1;
         foreach ($repos as $repo) {
             $this->repositories[] = $repo;
 
             $exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface;
             foreach ($repo->getPackages() as $package) {
-                if (!$exempt && !isset($this->acceptableStabilities[$package->getStability()])) {
-                    continue;
-                }
-
-                $package->setId(count($this->packages) + 1);
-                $this->packages[] = $package;
-
-                foreach ($package->getNames() as $name) {
-                    $this->packageByName[$name][] = $package;
+                $name = $package->getName();
+                $stability = $package->getStability();
+                if (
+                    // always allow exempt repos
+                    $exempt
+                    // allow if package matches the global stability requirement and has no exception
+                    || (!isset($this->stabilityFlags[$name])
+                        && isset($this->acceptableStabilities[$stability]))
+                    // allow if package matches the package-specific stability flag
+                    || (isset($this->stabilityFlags[$name])
+                        && array_search($stability, BasePackage::$stabilities) <= $this->stabilityFlags[$name]
+                    )
+                ) {
+                    $package->setId($id++);
+                    $this->packages[] = $package;
+
+                    foreach ($package->getNames() as $name) {
+                        $this->packageByName[$name][] = $package;
+                    }
                 }
             }
         }

+ 1 - 1
src/Composer/Installer.php

@@ -207,7 +207,7 @@ class Installer
         }
 
         // creating repository pool
-        $pool = new Pool($this->package->getMinimumStability());
+        $pool = new Pool($this->package->getMinimumStability(), $this->package->getStabilityFlags());
         $pool->addRepository($installedRepo);
         foreach ($this->repositoryManager->getRepositories() as $repository) {
             $pool->addRepository($repository);

+ 47 - 14
src/Composer/Package/Loader/RootPackageLoader.php

@@ -12,6 +12,7 @@
 
 namespace Composer\Package\Loader;
 
+use Composer\Package\BasePackage;
 use Composer\Package\Version\VersionParser;
 use Composer\Repository\RepositoryManager;
 use Composer\Util\ProcessExecutor;
@@ -60,24 +61,22 @@ class RootPackageLoader extends ArrayLoader
 
         $package = parent::load($config);
 
+        $aliases = array();
+        $stabilityFlags = array();
         if (isset($config['require'])) {
-            $aliases = array();
-            foreach ($config['require'] as $reqName => $reqVersion) {
-                if (preg_match('{^([^,\s]+) +as +([^,\s]+)$}', $reqVersion, $match)) {
-                    $aliases[] = array(
-                        'package' => strtolower($reqName),
-                        'version' => $this->versionParser->normalize($match[1]),
-                        'alias' => $match[2],
-                        'alias_normalized' => $this->versionParser->normalize($match[2]),
-                    );
-                }
-            }
-
-            $package->setAliases($aliases);
+            $aliases = $this->extractAliases($config['require'], $aliases);
+            $stabilityFlags = $this->extractStabilityFlags($config['require'], $stabilityFlags);
         }
+        if (isset($config['require-dev'])) {
+            $aliases = $this->extractAliases($config['require-dev'], $aliases);
+            $stabilityFlags = $this->extractStabilityFlags($config['require-dev'], $stabilityFlags);
+        }
+
+        $package->setAliases($aliases);
+        $package->setStabilityFlags($stabilityFlags);
 
         if (isset($config['minimum-stability'])) {
-            $package->setMinimumStability($config['minimum-stability']);
+            $package->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
         }
 
         if (isset($config['repositories'])) {
@@ -99,4 +98,38 @@ class RootPackageLoader extends ArrayLoader
 
         return $package;
     }
+
+    private function extractAliases(array $requires, array $aliases)
+    {
+        foreach ($requires as $reqName => $reqVersion) {
+            if (preg_match('{^([^,\s]+) +as +([^,\s]+)$}', $reqVersion, $match)) {
+                $aliases[] = array(
+                    'package' => strtolower($reqName),
+                    'version' => $this->versionParser->normalize($match[1]),
+                    'alias' => $match[2],
+                    'alias_normalized' => $this->versionParser->normalize($match[2]),
+                );
+            }
+        }
+
+        return $aliases;
+    }
+
+    private function extractStabilityFlags(array $requires, array $stabilityFlags)
+    {
+        $stabilities = BasePackage::$stabilities;
+        foreach ($requires as $reqName => $reqVersion) {
+            if (preg_match('{^[^,\s]*?@('.implode('|', $stabilities).')$}i', $reqVersion, $match)) {
+                $name = strtolower($reqName);
+                $stability = array_search(VersionParser::normalizeStability($match[1]), $stabilities);
+
+                if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
+                    continue;
+                }
+                $stabilityFlags[$name] = $stability;
+            }
+        }
+
+        return $stabilityFlags;
+    }
 }

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

@@ -49,6 +49,7 @@ class MemoryPackage extends BasePackage
     protected $dev;
 
     protected $minimumStability = 'dev';
+    protected $stabilityFlags = array();
 
     protected $requires = array();
     protected $conflicts = array();
@@ -617,6 +618,24 @@ class MemoryPackage extends BasePackage
         return $this->minimumStability;
     }
 
+    /**
+     * Set the stabilityFlags
+     *
+     * @param array $stabilityFlags
+     */
+    public function setStabilityFlags(array $stabilityFlags)
+    {
+        $this->stabilityFlags = $stabilityFlags;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function getStabilityFlags()
+    {
+        return $this->stabilityFlags;
+    }
+
     /**
      * Set the autoload mapping
      *

+ 12 - 0
src/Composer/Package/Version/VersionParser.php

@@ -12,6 +12,7 @@
 
 namespace Composer\Package\Version;
 
+use Composer\Package\BasePackage;
 use Composer\Package\LinkConstraint\MultiConstraint;
 use Composer\Package\LinkConstraint\VersionConstraint;
 
@@ -48,6 +49,13 @@ class VersionParser
         return 'stable';
     }
 
+    static public function normalizeStability($stability)
+    {
+        $stability = strtolower($stability);
+
+        return $stability === 'rc' ? 'RC' : $stability;
+    }
+
     /**
      * Normalizes a version string to be able to perform comparisons on it
      *
@@ -143,6 +151,10 @@ class VersionParser
      */
     public function parseConstraints($constraints)
     {
+        if (preg_match('{^([^,\s]*?)@('.implode('|', BasePackage::$stabilities).')$}i', $constraints, $match)) {
+            $constraints = empty($match[1]) ? '*' : $match[1];
+        }
+
         $constraints = preg_split('{\s*,\s*}', trim($constraints));
 
         if (count($constraints) > 1) {

+ 6 - 0
tests/Composer/Test/Package/Version/VersionParserTest.php

@@ -106,6 +106,12 @@ class VersionParserTest extends \PHPUnit_Framework_TestCase
         );
     }
 
+    public function testParseConstraintsIgnoresStabilityFlag()
+    {
+        $parser = new VersionParser;
+        $this->assertSame((string) new VersionConstraint('=', '1.0.0.0'), (string) $parser->parseConstraints('1.0@dev'));
+    }
+
     /**
      * @dataProvider simpleConstraints
      */