Эх сурвалжийг харах

Refactoring selection of the "recommended" version (e.g ~1.2) and adding some tests

This also modifies the behavior slightly (from a recommendation by seldaek) to always
propose the minor version of the recommendation (e.g. ~1.2 instead of ~1.2.1).
Ryan Weaver 10 жил өмнө
parent
commit
895e62e859

+ 1 - 12
src/Composer/Command/InitCommand.php

@@ -557,17 +557,6 @@ EOT
             ));
         }
 
-        $version = $package->getPrettyVersion();
-        if (!$package->isDev()) {
-            // remove the v prefix if there is one
-            if (substr($version, 0, 1) == 'v') {
-                $version = substr($version, 1);
-            }
-
-            // 2.1.0 -> ~2.1.0, 2.0-beta.1 -> ~2.0-beta.1
-            $version = '~'.$version;
-        }
-
-        return $version;
+        return $versionSelector->findRecommendedRequireVersion($package);
     }
 }

+ 42 - 0
src/Composer/Package/Version/VersionSelector.php

@@ -60,6 +60,48 @@ class VersionSelector
         return $package;
     }
 
+    /**
+     * Given a concrete version, this returns a ~ constraint (when possible)
+     * that should be used, for example, in composer.json.
+     *
+     * For example:
+     *  * 1.2.1         -> ~1.2
+     *  * 1.2           -> ~1.2
+     *  * v3.2.1        -> ~3.2
+     *  * 2.0-beta.1    -> ~2.0-beta.1
+     *  * dev-master    -> dev-master    (dev versions are untouched)
+     *
+     * @param PackageInterface $package
+     * @return string
+     */
+    public function findRecommendedRequireVersion(PackageInterface $package)
+    {
+        $version = $package->getPrettyVersion();
+        if (!$package->isDev()) {
+            // remove the v prefix if there is one
+            if (substr($version, 0, 1) == 'v') {
+                $version = substr($version, 1);
+            }
+
+            // for stable packages only, we try to transform 2.1.1 to 2.1
+            // this allows you to upgrade through minor versions
+            if ($package->getStability() == 'stable') {
+                $semanticVersionParts = explode('.', $version);
+                // check to see if we have a normal 1.2.6 semantic version
+                if (count($semanticVersionParts) == 3) {
+                    // remove the last part (i.e. the patch version number)
+                    unset($semanticVersionParts[2]);
+                    $version = implode('.', $semanticVersionParts);
+                }
+            }
+
+            // 2.1 -> ~2.1
+            $version = '~'.$version;
+        }
+
+        return $version;
+    }
+
     private function getParser()
     {
         if ($this->parser === null) {

+ 44 - 0
tests/Composer/Test/Package/Version/VersionSelectorTest.php

@@ -54,6 +54,50 @@ class VersionSelectorTest extends \PHPUnit_Framework_TestCase
         $this->assertFalse($best, 'No versions are available returns false');
     }
 
+    /**
+     * @dataProvider getRecommendedRequireVersionPackages
+     */
+    public function testFindRecommendedRequireVersion($prettyVersion, $isDev, $stability, $expectedVersion)
+    {
+        $pool = $this->createMockPool();
+        $versionSelector = new VersionSelector($pool);
+
+        $package = $this->getMock('\Composer\Package\PackageInterface');
+        $package->expects($this->any())
+            ->method('getPrettyVersion')
+            ->will($this->returnValue($prettyVersion));
+        $package->expects($this->any())
+            ->method('isDev')
+            ->will($this->returnValue($isDev));
+        $package->expects($this->any())
+            ->method('getStability')
+            ->will($this->returnValue($stability));
+
+        $recommended = $versionSelector->findRecommendedRequireVersion($package);
+
+        // assert that the recommended version is what we expect
+        $this->assertEquals($expectedVersion, $recommended);
+    }
+
+    public function getRecommendedRequireVersionPackages()
+    {
+        return array(
+            // real version, is dev package, stability, expected recommendation
+            array('1.2.1', false, 'stable', '~1.2'),
+            array('1.2', false, 'stable', '~1.2'),
+            array('v1.2.1', false, 'stable', '~1.2'),
+            array('3.1.2-pl2', false, 'stable', '~3.1'),
+            array('3.1.2-patch', false, 'stable', '~3.1'),
+            // for non-stable versions, we add ~, but don't try the (1.2.1 -> 1.2) transformation
+            array('2.0-beta.1', false, 'beta', '~2.0-beta.1'),
+            array('3.1.2-alpha5', false, 'alpha', '~3.1.2-alpha5'),
+            array('3.0-RC2', false, 'RC', '~3.0-RC2'),
+            // dev packages are not touched at all
+            array('dev-master', true, 'dev', 'dev-master'),
+            array('3.1.2-dev', true, 'dev', '3.1.2-dev'),
+        );
+    }
+
     private function createMockPackage($version)
     {
         $package = $this->getMock('\Composer\Package\PackageInterface');