diff --git a/src/Composer/Package/Loader/RootPackageLoader.php b/src/Composer/Package/Loader/RootPackageLoader.php index 565ff39c4..df46f784c 100644 --- a/src/Composer/Package/Loader/RootPackageLoader.php +++ b/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); diff --git a/src/Composer/Package/Version/VersionGuesser.php b/src/Composer/Package/Version/VersionGuesser.php index 4dd0be511..69cd69dfb 100644 --- a/src/Composer/Package/Version/VersionGuesser.php +++ b/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 = '#.*/('.$trunkPath.'|('.$branchesPath.'|'. $tagsPath .')/(.*))#'; + $urlPattern = '#.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))#'; 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' => ''); } } } + } diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index 487f06030..8d4e9919d 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/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 = ''; diff --git a/tests/Composer/Test/Package/Version/VersionGuesserTest.php b/tests/Composer/Test/Package/Version/VersionGuesserTest.php index 84da8d2e9..02b99e971 100644 --- a/tests/Composer/Test/Package/Version/VersionGuesserTest.php +++ b/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); }