Просмотр исходного кода

#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 10 лет назад
Родитель
Сommit
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);
     }