Browse Source

#4828 Using version guesser to pull out the commit has for git repositories. The return value is now an array with version and commit values.

Sash 9 years ago
parent
commit
f6899e5c38

+ 11 - 1
src/Composer/Package/Loader/RootPackageLoader.php

@@ -71,8 +71,11 @@ class RootPackageLoader extends ArrayLoader
             // override with env var if available
             if (getenv('COMPOSER_ROOT_VERSION')) {
                 $version = getenv('COMPOSER_ROOT_VERSION');
+                $commit = null;
             } else {
-                $version = $this->versionGuesser->guessVersion($config, $cwd ?: getcwd());
+                $versionData =  $this->versionGuesser->guessVersion($config, $cwd ?: getcwd());
+                $version = $versionData['version'];
+                $commit = $versionData['commit'];
             }
 
             if (!$version) {
@@ -81,6 +84,13 @@ class RootPackageLoader extends ArrayLoader
             }
 
             $config['version'] = $version;
+            if($commit){
+                $config['source'] = array(
+                    'type' => '',
+                    'url' => '',
+                    'reference' => $commit
+                );
+            }
         }
 
         $realPackage = $package = parent::load($config, $class);

+ 54 - 39
src/Composer/Package/Version/VersionGuesser.php

@@ -44,9 +44,9 @@ class VersionGuesser
     private $versionParser;
 
     /**
-     * @param Config          $config
+     * @param Config $config
      * @param ProcessExecutor $process
-     * @param VersionParser   $versionParser
+     * @param VersionParser $versionParser
      */
     public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser)
     {
@@ -56,20 +56,22 @@ class VersionGuesser
     }
 
     /**
-     * @param array  $packageConfig
-     * @param string $path          Path to guess into
+     * @param array $packageConfig
+     * @param string $path Path to guess into
+     *
+     * @return array versionData, 'version' and 'commit' keys
      */
     public function guessVersion(array $packageConfig, $path)
     {
         if (function_exists('proc_open')) {
-            $version = $this->guessGitVersion($packageConfig, $path);
-            if (null !== $version) {
-                return $version;
+            $versionData = $this->guessGitVersion($packageConfig, $path);
+            if (null !== $versionData) {
+                return $versionData;
             }
 
-            $version = $this->guessHgVersion($packageConfig, $path);
-            if (null !== $version) {
-                return $version;
+            $versionData = $this->guessHgVersion($packageConfig, $path);
+            if (null !== $versionData) {
+                return $versionData;
             }
 
             return $this->guessSvnVersion($packageConfig, $path);
@@ -79,34 +81,34 @@ class VersionGuesser
     private function guessGitVersion(array $packageConfig, $path)
     {
         GitUtil::cleanEnv();
-
-        // try to fetch current version from git tags
-        if (0 === $this->process->execute('git describe --exact-match --tags', $output, $path)) {
-            try {
-                return $this->versionParser->normalize(trim($output));
-            } catch (\Exception $e) {
-            }
-        }
+        $version = null;
+        $commit = null;
+        $version = $this->versionFromGitTags($path);
 
         // try to fetch current version from git branch
         if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output, $path)) {
             $branches = array();
             $isFeatureBranch = false;
-            $version = null;
 
             // find current branch and collect all branch names
             foreach ($this->process->splitLines($output) as $branch) {
                 if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
-                    if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ') {
-                        $version = 'dev-'.$match[2];
-                        $isFeatureBranch = true;
-                    } else {
-                        $version = $this->versionParser->normalizeBranch($match[1]);
-                        $isFeatureBranch = 0 === strpos($version, 'dev-');
-                        if ('9999999-dev' === $version) {
-                            $version = 'dev-'.$match[1];
+                    if (!$version) {
+                        if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ') {
+                            $version = 'dev-' . $match[2];
+                            $isFeatureBranch = true;
+                        } else {
+                            $version = $this->versionParser->normalizeBranch($match[1]);
+                            $isFeatureBranch = 0 === strpos($version, 'dev-');
+                            if ('9999999-dev' === $version) {
+                                $version = 'dev-' . $match[1];
+                            }
                         }
                     }
+
+                    if ($match[2]) {
+                        $commit = $match[2];
+                    }
                 }
 
                 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
@@ -116,15 +118,26 @@ class VersionGuesser
                 }
             }
 
-            if (!$isFeatureBranch) {
-                return $version;
+            if ($isFeatureBranch) {
+                // try to find the best (nearest) version branch to assume this feature's version
+                $version = $this->guessFeatureVersion($packageConfig, $version, $branches, 'git rev-list %candidate%..%branch%', $path);
             }
+        }
 
-            // try to find the best (nearest) version branch to assume this feature's version
-            $version = $this->guessFeatureVersion($packageConfig, $version, $branches, 'git rev-list %candidate%..%branch%', $path);
+        return array('version' => $version, 'commit' => $commit);
+    }
+
+    private function versionFromGitTags($path)
+    {
+        // try to fetch current version from git tags
+        if (0 === $this->process->execute('git describe --exact-match --tags', $output, $path)) {
+            try {
+                return $this->versionParser->normalize(trim($output));
+            } catch (\Exception $e) {
+            }
 
-            return $version;
         }
+        return null;
     }
 
     private function guessHgVersion(array $packageConfig, $path)
@@ -136,7 +149,7 @@ class VersionGuesser
             $isFeatureBranch = 0 === strpos($version, 'dev-');
 
             if ('9999999-dev' === $version) {
-                $version = 'dev-'.$branch;
+                $version = 'dev-' . $branch;
             }
 
             if (!$isFeatureBranch) {
@@ -150,7 +163,7 @@ class VersionGuesser
             // try to find the best (nearest) version branch to assume this feature's version
             $version = $this->guessFeatureVersion($packageConfig, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"', $path);
 
-            return $version;
+            return array('version' => $version, 'commit' => '');
         }
     }
 
@@ -189,7 +202,7 @@ class VersionGuesser
                     $length = strlen($output);
                     $version = $this->versionParser->normalizeBranch($candidate);
                     if ('9999999-dev' === $version) {
-                        $version = 'dev-'.$match[1];
+                        $version = 'dev-' . $match[1];
                     }
                 }
             }
@@ -208,21 +221,23 @@ class VersionGuesser
             $branchesPath = isset($packageConfig['branches-path']) ? preg_quote($packageConfig['branches-path'], '#') : 'branches';
             $tagsPath = isset($packageConfig['tags-path']) ? preg_quote($packageConfig['tags-path'], '#') : 'tags';
 
-            $urlPattern = '#<url>.*/('.$trunkPath.'|('.$branchesPath.'|'. $tagsPath .')/(.*))</url>#';
+            $urlPattern = '#<url>.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))</url>#';
 
             if (preg_match($urlPattern, $output, $matches)) {
                 if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) {
                     // we are in a branches path
                     $version = $this->versionParser->normalizeBranch($matches[3]);
                     if ('9999999-dev' === $version) {
-                        $version = 'dev-'.$matches[3];
+                        $version = 'dev-' . $matches[3];
                     }
 
-                    return $version;
+                    return array('version' => $version, 'commit' => '');
                 }
 
-                return $this->versionParser->normalize(trim($matches[1]));
+                $version = $this->versionParser->normalize(trim($matches[1]));
+                return array('version' => $version, 'commit' => '');
             }
         }
     }
+
 }

+ 1 - 1
src/Composer/Repository/PathRepository.php

@@ -129,7 +129,7 @@ class PathRepository extends ArrayRepository implements ConfigurableRepositoryIn
             );
 
             if (!isset($package['version'])) {
-                $package['version'] = $this->versionGuesser->guessVersion($package, $path) ?: 'dev-master';
+                $package['version'] = $this->versionGuesser->guessVersion($package, $path)['version'] ?: 'dev-master';
             }
 
             $output = '';

+ 44 - 3
tests/Composer/Test/Package/Version/VersionGuesserTest.php

@@ -25,6 +25,47 @@ class VersionGuesserTest extends \PHPUnit_Framework_TestCase
         }
     }
 
+    public function testGuessVersionReturnsData()
+    {
+        $commitHash = '03a15d220da53c52eddd5f32ffca64a7b3801bea';
+        $anotherCommitHash = '03a15d220da53c52eddd5f32ffca64a7b3801bea';
+
+        $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor')
+            ->setMethods(array('execute'))
+            ->disableArgumentCloning()
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $executor
+            ->expects($this->at(0))
+            ->method('execute')
+            ->with('git describe --exact-match --tags')
+            ->willReturn(1)
+        ;
+
+        $self = $this;
+
+        $executor
+            ->expects($this->at(1))
+            ->method('execute')
+            ->willReturnCallback(function ($command, &$output) use ($self, $commitHash, $anotherCommitHash) {
+                $self->assertEquals('git branch --no-color --no-abbrev -v', $command);
+                $output = "* master $commitHash Commit message\n(no branch) $anotherCommitHash Commit message\n";
+
+                return 0;
+            })
+        ;
+
+        $config = new Config;
+        $config->merge(array('repositories' => array('packagist' => false)));
+        $guesser = new VersionGuesser($config, $executor, new VersionParser());
+        $versionArray = $guesser->guessVersion(array(), 'dummy/path');
+
+        $this->assertEquals("dev-master", $versionArray['version']);
+        $this->assertEquals($commitHash, $versionArray['commit']);
+    }
+
     public function testDetachedHeadBecomesDevHash()
     {
         $commitHash = '03a15d220da53c52eddd5f32ffca64a7b3801bea';
@@ -59,7 +100,7 @@ class VersionGuesserTest extends \PHPUnit_Framework_TestCase
         $config = new Config;
         $config->merge(array('repositories' => array('packagist' => false)));
         $guesser = new VersionGuesser($config, $executor, new VersionParser());
-        $version = $guesser->guessVersion(array(), 'dummy/path');
+        $version = $guesser->guessVersion(array(), 'dummy/path')['version'];
 
         $this->assertEquals("dev-$commitHash", $version);
     }
@@ -89,7 +130,7 @@ class VersionGuesserTest extends \PHPUnit_Framework_TestCase
         $config = new Config;
         $config->merge(array('repositories' => array('packagist' => false)));
         $guesser = new VersionGuesser($config, $executor, new VersionParser());
-        $version = $guesser->guessVersion(array(), 'dummy/path');
+        $version = $guesser->guessVersion(array(), 'dummy/path')['version'];
 
         $this->assertEquals("2.0.5.0-alpha2", $version);
     }
@@ -130,7 +171,7 @@ class VersionGuesserTest extends \PHPUnit_Framework_TestCase
         $config = new Config;
         $config->merge(array('repositories' => array('packagist' => false)));
         $guesser = new VersionGuesser($config, $executor, new VersionParser());
-        $version = $guesser->guessVersion(array(), 'dummy/path');
+        $version = $guesser->guessVersion(array(), 'dummy/path')['version'];
 
         $this->assertEquals("dev-foo", $version);
     }