diff --git a/src/Composer/Package/Version/VersionGuesser.php b/src/Composer/Package/Version/VersionGuesser.php index f8e43fb88..060bf26dd 100644 --- a/src/Composer/Package/Version/VersionGuesser.php +++ b/src/Composer/Package/Version/VersionGuesser.php @@ -88,8 +88,7 @@ class VersionGuesser private function postprocess(array $versionData) { - // make sure that e.g. dev-1.5 gets converted to 1.5.x-dev - if ('dev-' !== substr($versionData['version'], 0, 4)) { + if ('-dev' === substr($versionData['version'], -4)) { $versionData['pretty_version'] = preg_replace('{(\.9{7})+}', '.x', $versionData['version']); } diff --git a/src/Composer/Repository/Vcs/GitLabDriver.php b/src/Composer/Repository/Vcs/GitLabDriver.php index b883eefea..fb2b7437e 100644 --- a/src/Composer/Repository/Vcs/GitLabDriver.php +++ b/src/Composer/Repository/Vcs/GitLabDriver.php @@ -66,7 +66,12 @@ class GitLabDriver extends VcsDriver */ private $isPrivate = true; - const URL_REGEX = '#^(?:(?Phttps?)://(?P.+?)/|git@(?P[^:]+):)(?P.+)/(?P[^/]+?)(?:\.git|/)?$#'; + /** + * @var int port number + */ + protected $portNumber; + + const URL_REGEX = '#^(?:(?Phttps?)://(?P.+?)(?::(?P[0-9]+))?/|git@(?P[^:]+):)(?P.+)/(?P[^/]+?)(?:\.git|/)?$#'; /** * Extracts information from the repository url. @@ -90,6 +95,12 @@ class GitLabDriver extends VcsDriver : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? 'http' : 'https') ; $this->originUrl = $this->determineOrigin($configuredDomains, $guessedDomain, $urlParts); + + if (!empty($match['port']) && true === is_numeric($match['port'])) { + // If it is an HTTP based URL, and it has a port + $this->portNumber = (int) $match['port']; + } + $this->namespace = implode('/', $urlParts); $this->repository = preg_replace('#(\.git)$#', '', $match['repo']); @@ -248,7 +259,9 @@ class GitLabDriver extends VcsDriver */ public function getApiUrl() { - return $this->scheme.'://'.$this->originUrl.'/api/v4/projects/'.$this->urlEncodeAll($this->namespace).'%2F'.$this->urlEncodeAll($this->repository); + $domainName = $this->originUrl; + $portNumber = (true === is_numeric($this->portNumber)) ? sprintf(':%s', $this->portNumber) : ''; + return $this->scheme.'://'.$domainName.$portNumber.'/api/v4/projects/'.$this->urlEncodeAll($this->namespace).'%2F'.$this->urlEncodeAll($this->repository); } /** @@ -436,6 +449,7 @@ class GitLabDriver extends VcsDriver */ public static function supports(IOInterface $io, Config $config, $url, $deep = false) { + if (!preg_match(self::URL_REGEX, $url, $match)) { return false; } diff --git a/tests/Composer/Test/Package/Version/VersionGuesserTest.php b/tests/Composer/Test/Package/Version/VersionGuesserTest.php index 615ed728b..d8db7e599 100644 --- a/tests/Composer/Test/Package/Version/VersionGuesserTest.php +++ b/tests/Composer/Test/Package/Version/VersionGuesserTest.php @@ -384,6 +384,48 @@ class VersionGuesserTest extends TestCase $this->assertEquals("2.0.5.0-alpha2", $versionData['version']); } + public function testTagBecomesPrettyVersion() + { + $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 branch --no-color --no-abbrev -v', $command); + $output = "* (HEAD detached at 1.0.0) c006f0c12bbbf197b5c071ffb1c0e9812bb14a4d Commit message\n"; + + return 0; + }) + ; + + $executor + ->expects($this->at(1)) + ->method('execute') + ->willReturnCallback(function ($command, &$output) use ($self) { + $self->assertEquals('git describe --exact-match --tags', $command); + $output = '1.0.0'; + + return 0; + }) + ; + + $config = new Config; + $config->merge(array('repositories' => array('packagist' => false))); + $guesser = new VersionGuesser($config, $executor, new VersionParser()); + $versionData = $guesser->guessVersion(array(), 'dummy/path'); + + $this->assertEquals('1.0.0.0', $versionData['version']); + $this->assertEquals('1.0.0', $versionData['pretty_version']); + } + public function testInvalidTagBecomesVersion() { $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') diff --git a/tests/Composer/Test/Repository/Vcs/GitLabDriverTest.php b/tests/Composer/Test/Repository/Vcs/GitLabDriverTest.php index 25634138f..081425005 100644 --- a/tests/Composer/Test/Repository/Vcs/GitLabDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/GitLabDriverTest.php @@ -38,6 +38,7 @@ class GitLabDriverTest extends TestCase 'home' => $this->home, 'gitlab-domains' => array( 'mycompany.com/gitlab', + 'gitlab.mycompany.com', 'othercompany.com/nested/gitlab', 'gitlab.com', ), @@ -180,6 +181,45 @@ JSON; return $driver; } + /** + * Also support repositories over HTTP (TLS) and has a port number. + * + * @group gitlabHttpPort + */ + public function testInitializeWithPortNumber() + { + $domain = 'gitlab.mycompany.com'; + $port = '5443'; + $namespace = 'mygroup/myproject'; + $url = sprintf('https://%1$s:%2$s/%3$s', $domain, $port, $namespace); + $apiUrl = sprintf('https://%1$s:%2$s/api/v4/projects/%3$s', $domain, $port, urlencode($namespace)); + + // An incomplete single project API response payload. + // @link http://doc.gitlab.com/ce/api/projects.html#get-single-project + $projectData = <<<'JSON' +{ + "default_branch": "1.0.x", + "http_url_to_repo": "https://%1$s:%2$s/%3$s.git", + "path": "myproject", + "path_with_namespace": "%3$s", + "web_url": "https://%1$s:%2$s/%3$s" +} +JSON; + + $this->remoteFilesystem + ->getContents($domain, $apiUrl, false, array()) + ->willReturn(sprintf($projectData, $domain, $port, $namespace)) + ->shouldBeCalledTimes(1); + + $driver = new GitLabDriver(array('url' => $url), $this->io->reveal(), $this->config, $this->process->reveal(), $this->remoteFilesystem->reveal()); + $driver->initialize(); + + $this->assertEquals($apiUrl, $driver->getApiUrl(), 'API URL is derived from the repository URL'); + $this->assertEquals('1.0.x', $driver->getRootIdentifier(), 'Root identifier is the default branch in GitLab'); + $this->assertEquals($url.'.git', $driver->getRepositoryUrl(), 'The repository URL is the SSH one by default'); + $this->assertEquals($url, $driver->getUrl()); + } + public function testGetDist() { $driver = $this->testInitialize('https://gitlab.com/mygroup/myproject', 'https://gitlab.com/api/v4/projects/mygroup%2Fmyproject'); @@ -380,6 +420,7 @@ JSON; } /** + * @group gitlabHttpPort * @dataProvider dataForTestSupports */ public function testSupports($url, $expected) @@ -391,10 +432,14 @@ JSON; { return array( array('http://gitlab.com/foo/bar', true), + array('http://gitlab.mycompany.com:5443/foo/bar', true), array('http://gitlab.com/foo/bar/', true), + array('http://gitlab.com/foo/bar/', true), + array('http://gitlab.com/foo/bar.git', true), array('http://gitlab.com/foo/bar.git', true), array('http://gitlab.com/foo/bar.baz.git', true), array('https://gitlab.com/foo/bar', extension_loaded('openssl')), // Platform requirement + array('https://gitlab.mycompany.com:5443/foo/bar', extension_loaded('openssl')), // Platform requirement array('git@gitlab.com:foo/bar.git', extension_loaded('openssl')), array('git@example.com:foo/bar.git', false), array('http://example.com/foo/bar', false),