From 5261a5fa03892f7f25aadff5d74678d5f76a4bed Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Tue, 18 Aug 2015 14:58:18 +0100 Subject: [PATCH] Move version guessing in `VersionGuesser` class --- src/Composer/Factory.php | 4 +- .../Package/Loader/RootPackageLoader.php | 197 ++--------------- .../Package/Version/VersionGuesser.php | 201 +++++++++++++++++ .../Package/Loader/RootPackageLoaderTest.php | 203 +++--------------- .../Package/Version/VersionGuesserTest.php | 158 ++++++++++++++ 5 files changed, 416 insertions(+), 347 deletions(-) create mode 100644 src/Composer/Package/Version/VersionGuesser.php create mode 100644 tests/Composer/Test/Package/Version/VersionGuesserTest.php diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 4fabbe455..1da6c30da 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -16,6 +16,7 @@ use Composer\Config\JsonConfigSource; use Composer\Json\JsonFile; use Composer\IO\IOInterface; use Composer\Package\Archiver; +use Composer\Package\Version\VersionGuesser; use Composer\Repository\RepositoryManager; use Composer\Repository\WritableRepositoryInterface; use Composer\Util\ProcessExecutor; @@ -264,7 +265,8 @@ class Factory // load package $parser = new VersionParser; - $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, new ProcessExecutor($io)); + $guesser = new VersionGuesser(new ProcessExecutor($io), $parser); + $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser); $package = $loader->load($localConfig); $composer->setPackage($package); diff --git a/src/Composer/Package/Loader/RootPackageLoader.php b/src/Composer/Package/Loader/RootPackageLoader.php index 9c7c436bc..3043a18c5 100644 --- a/src/Composer/Package/Loader/RootPackageLoader.php +++ b/src/Composer/Package/Loader/RootPackageLoader.php @@ -16,13 +16,10 @@ use Composer\Package\BasePackage; use Composer\Package\AliasPackage; use Composer\Config; use Composer\Factory; +use Composer\Package\Version\VersionGuesser; use Composer\Package\Version\VersionParser; use Composer\Repository\RepositoryManager; -use Composer\Repository\Vcs\HgDriver; -use Composer\IO\NullIO; use Composer\Util\ProcessExecutor; -use Composer\Util\Git as GitUtil; -use Composer\Util\Svn as SvnUtil; /** * ArrayLoader built for the sole purpose of loading the root package @@ -33,16 +30,28 @@ use Composer\Util\Svn as SvnUtil; */ class RootPackageLoader extends ArrayLoader { + /** + * @var RepositoryManager + */ private $manager; - private $config; - private $process; - public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, ProcessExecutor $process = null) + /** + * @var Config + */ + private $config; + + /** + * @var VersionGuesser + */ + private $versionGuesser; + + public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, VersionGuesser $versionGuesser = null) { + parent::__construct($parser); + $this->manager = $manager; $this->config = $config; - $this->process = $process ?: new ProcessExecutor(); - parent::__construct($parser); + $this->versionGuesser = $versionGuesser ?: new VersionGuesser(new ProcessExecutor(), $this->versionParser); } public function load(array $config, $class = 'Composer\Package\RootPackage') @@ -56,7 +65,7 @@ class RootPackageLoader extends ArrayLoader if (getenv('COMPOSER_ROOT_VERSION')) { $version = getenv('COMPOSER_ROOT_VERSION'); } else { - $version = $this->guessVersion($config); + $version = $this->versionGuesser->guessVersion($this->config, $config); } if (!$version) { @@ -176,172 +185,4 @@ class RootPackageLoader extends ArrayLoader return $references; } - - private function guessVersion(array $config) - { - if (function_exists('proc_open')) { - $version = $this->guessGitVersion($config); - if (null !== $version) { - return $version; - } - - $version = $this->guessHgVersion($config); - if (null !== $version) { - return $version; - } - - return $this->guessSvnVersion($config); - } - } - - private function guessGitVersion(array $config) - { - GitUtil::cleanEnv(); - - // try to fetch current version from git tags - if (0 === $this->process->execute('git describe --exact-match --tags', $output)) { - try { - return $this->versionParser->normalize(trim($output)); - } catch (\Exception $e) { - } - } - - // try to fetch current version from git branch - if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output)) { - $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 ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) { - if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) { - $branches[] = $match[1]; - } - } - } - - if (!$isFeatureBranch) { - return $version; - } - - // try to find the best (nearest) version branch to assume this feature's version - $version = $this->guessFeatureVersion($config, $version, $branches, 'git rev-list %candidate%..%branch%'); - - return $version; - } - } - - private function guessHgVersion(array $config) - { - // try to fetch current version from hg branch - if (0 === $this->process->execute('hg branch', $output)) { - $branch = trim($output); - $version = $this->versionParser->normalizeBranch($branch); - $isFeatureBranch = 0 === strpos($version, 'dev-'); - - if ('9999999-dev' === $version) { - $version = 'dev-'.$branch; - } - - if (!$isFeatureBranch) { - return $version; - } - - // re-use the HgDriver to fetch branches (this properly includes bookmarks) - $config = array('url' => getcwd()); - $driver = new HgDriver($config, new NullIO(), $this->config, $this->process); - $branches = array_keys($driver->getBranches()); - - // try to find the best (nearest) version branch to assume this feature's version - $version = $this->guessFeatureVersion($config, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"'); - - return $version; - } - } - - private function guessFeatureVersion(array $config, $version, array $branches, $scmCmdline) - { - // ignore feature branches if they have no branch-alias or self.version is used - // and find the branch they came from to use as a version instead - if ((isset($config['extra']['branch-alias']) && !isset($config['extra']['branch-alias'][$version])) - || strpos(json_encode($config), '"self.version"') - ) { - $branch = preg_replace('{^dev-}', '', $version); - $length = PHP_INT_MAX; - - $nonFeatureBranches = ''; - if (!empty($config['non-feature-branches'])) { - $nonFeatureBranches = implode('|', $config['non-feature-branches']); - } - - foreach ($branches as $candidate) { - // return directly, if branch is configured to be non-feature branch - if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) { - return $version; - } - - // do not compare against other feature branches - if ($candidate === $branch || !preg_match('{^(master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) { - continue; - } - - $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline); - if (0 !== $this->process->execute($cmdLine, $output)) { - continue; - } - - if (strlen($output) < $length) { - $length = strlen($output); - $version = $this->versionParser->normalizeBranch($candidate); - if ('9999999-dev' === $version) { - $version = 'dev-'.$match[1]; - } - } - } - } - - return $version; - } - - private function guessSvnVersion(array $config) - { - SvnUtil::cleanEnv(); - - // try to fetch current version from svn - if (0 === $this->process->execute('svn info --xml', $output)) { - $trunkPath = isset($config['trunk-path']) ? preg_quote($config['trunk-path'], '#') : 'trunk'; - $branchesPath = isset($config['branches-path']) ? preg_quote($config['branches-path'], '#') : 'branches'; - $tagsPath = isset($config['tags-path']) ? preg_quote($config['tags-path'], '#') : 'tags'; - - $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]; - } - - return $version; - } - - return $this->versionParser->normalize(trim($matches[1])); - } - } - } } diff --git a/src/Composer/Package/Version/VersionGuesser.php b/src/Composer/Package/Version/VersionGuesser.php new file mode 100644 index 000000000..98cf216c8 --- /dev/null +++ b/src/Composer/Package/Version/VersionGuesser.php @@ -0,0 +1,201 @@ +process = $process; + $this->versionParser = $versionParser; + } + + public function guessVersion(Config $config, array $packageConfig) + { + if (function_exists('proc_open')) { + $version = $this->guessGitVersion($packageConfig); + if (null !== $version) { + return $version; + } + + $version = $this->guessHgVersion($config, $packageConfig); + if (null !== $version) { + return $version; + } + + return $this->guessSvnVersion($packageConfig); + } + } + + private function guessGitVersion(array $config) + { + GitUtil::cleanEnv(); + + // try to fetch current version from git tags + if (0 === $this->process->execute('git describe --exact-match --tags', $output)) { + try { + return $this->versionParser->normalize(trim($output)); + } catch (\Exception $e) { + } + } + + // try to fetch current version from git branch + if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output)) { + $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 ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) { + if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) { + $branches[] = $match[1]; + } + } + } + + if (!$isFeatureBranch) { + return $version; + } + + // try to find the best (nearest) version branch to assume this feature's version + $version = $this->guessFeatureVersion($config, $version, $branches, 'git rev-list %candidate%..%branch%'); + + return $version; + } + } + + private function guessHgVersion(Config $config, array $packageConfig) + { + // try to fetch current version from hg branch + if (0 === $this->process->execute('hg branch', $output)) { + $branch = trim($output); + $version = $this->versionParser->normalizeBranch($branch); + $isFeatureBranch = 0 === strpos($version, 'dev-'); + + if ('9999999-dev' === $version) { + $version = 'dev-'.$branch; + } + + if (!$isFeatureBranch) { + return $version; + } + + // re-use the HgDriver to fetch branches (this properly includes bookmarks) + $packageConfig = array('url' => getcwd()); + $driver = new HgDriver($packageConfig, new NullIO(), $config, $this->process); + $branches = array_keys($driver->getBranches()); + + // try to find the best (nearest) version branch to assume this feature's version + $version = $this->guessFeatureVersion($config, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"'); + + return $version; + } + } + + private function guessFeatureVersion(array $config, $version, array $branches, $scmCmdline) + { + // ignore feature branches if they have no branch-alias or self.version is used + // and find the branch they came from to use as a version instead + if ((isset($config['extra']['branch-alias']) && !isset($config['extra']['branch-alias'][$version])) + || strpos(json_encode($config), '"self.version"') + ) { + $branch = preg_replace('{^dev-}', '', $version); + $length = PHP_INT_MAX; + + $nonFeatureBranches = ''; + if (!empty($config['non-feature-branches'])) { + $nonFeatureBranches = implode('|', $config['non-feature-branches']); + } + + foreach ($branches as $candidate) { + // return directly, if branch is configured to be non-feature branch + if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) { + return $version; + } + + // do not compare against other feature branches + if ($candidate === $branch || !preg_match('{^(master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) { + continue; + } + + $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline); + if (0 !== $this->process->execute($cmdLine, $output)) { + continue; + } + + if (strlen($output) < $length) { + $length = strlen($output); + $version = $this->versionParser->normalizeBranch($candidate); + if ('9999999-dev' === $version) { + $version = 'dev-'.$match[1]; + } + } + } + } + + return $version; + } + + private function guessSvnVersion(array $config) + { + SvnUtil::cleanEnv(); + + // try to fetch current version from svn + if (0 === $this->process->execute('svn info --xml', $output)) { + $trunkPath = isset($config['trunk-path']) ? preg_quote($config['trunk-path'], '#') : 'trunk'; + $branchesPath = isset($config['branches-path']) ? preg_quote($config['branches-path'], '#') : 'branches'; + $tagsPath = isset($config['tags-path']) ? preg_quote($config['tags-path'], '#') : 'tags'; + + $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]; + } + + return $version; + } + + return $this->versionParser->normalize(trim($matches[1])); + } + } + } +} diff --git a/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php b/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php index 2a4d9ccf6..77139f928 100644 --- a/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php +++ b/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php @@ -15,175 +15,11 @@ namespace Composer\Test\Package\Loader; use Composer\Config; use Composer\Package\Loader\RootPackageLoader; use Composer\Package\BasePackage; +use Composer\Package\Version\VersionGuesser; +use Composer\Package\Version\VersionParser; class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase { - public function testDetachedHeadBecomesDevHash() - { - if (!function_exists('proc_open')) { - $this->markTestSkipped('proc_open() is not available'); - } - - $commitHash = '03a15d220da53c52eddd5f32ffca64a7b3801bea'; - - $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') - ->disableOriginalConstructor() - ->getMock() - ; - - $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) { - $self->assertEquals('git branch --no-color --no-abbrev -v', $command); - $output = "* (no branch) $commitHash Commit message\n"; - - return 0; - }) - ; - - $config = new Config; - $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $executor); - $package = $loader->load(array()); - - $this->assertEquals("dev-$commitHash", $package->getVersion()); - } - - public function testTagBecomesVersion() - { - if (!function_exists('proc_open')) { - $this->markTestSkipped('proc_open() is not available'); - } - - $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') - ->disableOriginalConstructor() - ->getMock() - ; - - $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') - ->setMethods(array('execute')) - ->disableArgumentCloning() - ->disableOriginalConstructor() - ->getMock() - ; - - $self = $this; - - $executor - ->expects($this->at(0)) - ->method('execute') - ->willReturnCallback(function ($command, &$output) use ($self) { - $self->assertEquals('git describe --exact-match --tags', $command); - $output = "v2.0.5-alpha2"; - - return 0; - }) - ; - - $config = new Config; - $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $executor); - $package = $loader->load(array()); - - $this->assertEquals("2.0.5.0-alpha2", $package->getVersion()); - } - - public function testInvalidTagBecomesVersion() - { - if (!function_exists('proc_open')) { - $this->markTestSkipped('proc_open() is not available'); - } - - $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') - ->disableOriginalConstructor() - ->getMock() - ; - - $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') - ->setMethods(array('execute')) - ->disableArgumentCloning() - ->disableOriginalConstructor() - ->getMock() - ; - - $self = $this; - - $executor - ->expects($this->at(0)) - ->method('execute') - ->willReturnCallback(function ($command, &$output) use ($self) { - $self->assertEquals('git describe --exact-match --tags', $command); - $output = "foo-bar"; - - return 0; - }) - ; - - $executor - ->expects($this->at(1)) - ->method('execute') - ->willReturnCallback(function ($command, &$output) use ($self) { - $self->assertEquals('git branch --no-color --no-abbrev -v', $command); - $output = "* foo 03a15d220da53c52eddd5f32ffca64a7b3801bea Commit message\n"; - - return 0; - }) - ; - - $config = new Config; - $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $executor); - $package = $loader->load(array()); - - $this->assertEquals("dev-foo", $package->getVersion()); - } - - public function testNoVersionIsVisibleInPrettyVersion() - { - $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') - ->disableOriginalConstructor() - ->getMock() - ; - - $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') - ->setMethods(array('execute')) - ->disableArgumentCloning() - ->disableOriginalConstructor() - ->getMock() - ; - - $executor - ->expects($this->any()) - ->method('execute') - ->willReturn(null) - ; - - $config = new Config; - $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $executor); - $package = $loader->load(array()); - - $this->assertEquals("1.0.0.0", $package->getVersion()); - $this->assertEquals("No version set (parsed as 1.0.0)", $package->getPrettyVersion()); - } - protected function loadPackage($data) { $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') @@ -218,6 +54,37 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase ), $package->getStabilityFlags()); } + public function testNoVersionIsVisibleInPrettyVersion() + { + $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') + ->disableOriginalConstructor() + ->getMock() + ; + + $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') + ->setMethods(array('execute')) + ->disableArgumentCloning() + ->disableOriginalConstructor() + ->getMock() + ; + + $executor + ->expects($this->any()) + ->method('execute') + ->willReturn(null) + ; + + $config = new Config; + $config->merge(array('repositories' => array('packagist' => false))); + $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($executor, new VersionParser())); + $package = $loader->load(array()); + + $this->assertEquals("1.0.0.0", $package->getVersion()); + $this->assertEquals("No version set (parsed as 1.0.0)", $package->getPrettyVersion()); + } + + + public function testFeatureBranchPrettyVersion() { if (!function_exists('proc_open')) { @@ -272,7 +139,7 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $executor); + $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($executor, new VersionParser())); $package = $loader->load(array('require' => array('foo/bar' => 'self.version'))); $this->assertEquals("dev-master", $package->getPrettyVersion()); @@ -321,7 +188,7 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $executor); + $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($executor, new VersionParser())); $package = $loader->load(array('require' => array('foo/bar' => 'self.version'), "non-feature-branches" => array("latest-.*"))); $this->assertEquals("dev-latest-production", $package->getPrettyVersion()); diff --git a/tests/Composer/Test/Package/Version/VersionGuesserTest.php b/tests/Composer/Test/Package/Version/VersionGuesserTest.php new file mode 100644 index 000000000..7891d1062 --- /dev/null +++ b/tests/Composer/Test/Package/Version/VersionGuesserTest.php @@ -0,0 +1,158 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Test\Package\Version; + +use Composer\Config; +use Composer\Package\Loader\RootPackageLoader; +use Composer\Package\Version\VersionGuesser; +use Composer\Package\Version\VersionParser; + +class VersionGuesserTest extends \PHPUnit_Framework_TestCase +{ + public function testDetachedHeadBecomesDevHash() + { + if (!function_exists('proc_open')) { + $this->markTestSkipped('proc_open() is not available'); + } + + $commitHash = '03a15d220da53c52eddd5f32ffca64a7b3801bea'; + + $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') + ->disableOriginalConstructor() + ->getMock() + ; + + $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) { + $self->assertEquals('git branch --no-color --no-abbrev -v', $command); + $output = "* (no branch) $commitHash Commit message\n"; + + return 0; + }) + ; + + $config = new Config; + $config->merge(array('repositories' => array('packagist' => false))); + $guesser = new VersionGuesser($executor, new VersionParser()); + $version = $guesser->guessVersion($config, []); + + $this->assertEquals("dev-$commitHash", $version); + } + + public function testTagBecomesVersion() + { + if (!function_exists('proc_open')) { + $this->markTestSkipped('proc_open() is not available'); + } + + $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') + ->disableOriginalConstructor() + ->getMock() + ; + + $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') + ->setMethods(array('execute')) + ->disableArgumentCloning() + ->disableOriginalConstructor() + ->getMock() + ; + + $self = $this; + + $executor + ->expects($this->at(0)) + ->method('execute') + ->willReturnCallback(function ($command, &$output) use ($self) { + $self->assertEquals('git describe --exact-match --tags', $command); + $output = "v2.0.5-alpha2"; + + return 0; + }) + ; + + $config = new Config; + $config->merge(array('repositories' => array('packagist' => false))); + $guesser = new VersionGuesser($executor, new VersionParser()); + $version = $guesser->guessVersion($config, []); + + $this->assertEquals("2.0.5.0-alpha2", $version); + } + + public function testInvalidTagBecomesVersion() + { + if (!function_exists('proc_open')) { + $this->markTestSkipped('proc_open() is not available'); + } + + $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') + ->disableOriginalConstructor() + ->getMock() + ; + + $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') + ->setMethods(array('execute')) + ->disableArgumentCloning() + ->disableOriginalConstructor() + ->getMock() + ; + + $self = $this; + + $executor + ->expects($this->at(0)) + ->method('execute') + ->willReturnCallback(function ($command, &$output) use ($self) { + $self->assertEquals('git describe --exact-match --tags', $command); + $output = "foo-bar"; + + return 0; + }) + ; + + $executor + ->expects($this->at(1)) + ->method('execute') + ->willReturnCallback(function ($command, &$output) use ($self) { + $self->assertEquals('git branch --no-color --no-abbrev -v', $command); + $output = "* foo 03a15d220da53c52eddd5f32ffca64a7b3801bea Commit message\n"; + + return 0; + }) + ; + + $config = new Config; + $config->merge(array('repositories' => array('packagist' => false))); + $guesser = new VersionGuesser($executor, new VersionParser()); + $version = $guesser->guessVersion($config, []); + + $this->assertEquals("dev-foo", $version); + } +}