diff --git a/src/Composer/Repository/Vcs/GitLabDriver.php b/src/Composer/Repository/Vcs/GitLabDriver.php index aea5a253f..49ca44423 100644 --- a/src/Composer/Repository/Vcs/GitLabDriver.php +++ b/src/Composer/Repository/Vcs/GitLabDriver.php @@ -280,17 +280,20 @@ class GitLabDriver extends VcsDriver { $resource = $this->getApiUrl().'/repository/'.$type; - $data = JsonFile::parseJson($this->getContents($resource), $resource); + do { + $data = JsonFile::parseJson($this->getContents($resource), $resource); - $references = array(); + $references = array(); - foreach ($data as $datum) { - $references[$datum['name']] = $datum['commit']['id']; + foreach ($data as $datum) { + $references[$datum['name']] = $datum['commit']['id']; - // Keep the last commit date of a reference to avoid - // unnecessary API call when retrieving the composer file. - $this->commits[$datum['commit']['id']] = $datum['commit']; - } + // Keep the last commit date of a reference to avoid + // unnecessary API call when retrieving the composer file. + $this->commits[$datum['commit']['id']] = $datum['commit']; + } + $resource = $this->getNextPage(); + } while ($resource); return $references; } @@ -444,6 +447,21 @@ class GitLabDriver extends VcsDriver return true; } + protected function getNextPage() + { + $headers = $this->remoteFilesystem->getLastHeaders(); + foreach ($headers as $header) { + if (substr($header, 0, 5) === 'Link:') { + $links = explode(',', substr($header, 5)); + foreach ($links as $link) { + if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) { + return $match[1]; + } + } + } + } + } + /** * @param array $configuredDomains * @param string $guessedDomain diff --git a/tests/Composer/Test/Repository/Vcs/GitLabDriverTest.php b/tests/Composer/Test/Repository/Vcs/GitLabDriverTest.php index c663f929d..c5d1c8357 100644 --- a/tests/Composer/Test/Repository/Vcs/GitLabDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/GitLabDriverTest.php @@ -216,6 +216,9 @@ JSON; ->willReturn($tagData) ->shouldBeCalledTimes(1) ; + $this->remoteFilesystem->getLastHeaders() + ->willReturn(array()); + $driver->setRemoteFilesystem($this->remoteFilesystem->reveal()); $expected = array( @@ -227,6 +230,58 @@ JSON; $this->assertEquals($expected, $driver->getTags(), 'Tags are cached'); } + public function testGetPaginatedRefs() { + $driver = $this->testInitialize('https://gitlab.com/mygroup/myproject', 'https://gitlab.com/api/v4/projects/mygroup%2Fmyproject'); + + $apiUrl = 'https://gitlab.com/api/v4/projects/mygroup%2Fmyproject/repository/branches'; + + // @link http://doc.gitlab.com/ce/api/repositories.html#list-project-repository-branches + $branchData = <<remoteFilesystem + ->getContents('gitlab.com', $apiUrl, false, array()) + ->willReturn($branchData) + ->shouldBeCalledTimes(1) + ; + + $this->remoteFilesystem + ->getContents('gitlab.com', "http://gitlab.com/api/v4/projects/mygroup%2Fmyproject/repository/tags?id=mygroup%2Fmyproject&page=2&per_page=20", false, array()) + ->willReturn($branchData) + ->shouldBeCalledTimes(1) + ; + + $this->remoteFilesystem->getLastHeaders() + ->willReturn(array('Link: ; rel="next", ; rel="first", ; rel="last"'), array('Link: ; rel="prev", ; rel="first", ; rel="last"')) + ->shouldBeCalledTimes(2); + + $driver->setRemoteFilesystem($this->remoteFilesystem->reveal()); + + $expected = array( + 'mymaster' => '97eda36b5c1dd953a3792865c222d4e85e5f302e', + 'staging' => '502cffe49f136443f2059803f2e7192d1ac066cd', + ); + + $this->assertEquals($expected, $driver->getBranches()); + $this->assertEquals($expected, $driver->getBranches(), 'Branches are cached'); + + } public function testGetBranches() { $driver = $this->testInitialize('https://gitlab.com/mygroup/myproject', 'https://gitlab.com/api/v4/projects/mygroup%2Fmyproject'); @@ -258,6 +313,9 @@ JSON; ->willReturn($branchData) ->shouldBeCalledTimes(1) ; + $this->remoteFilesystem->getLastHeaders() + ->willReturn(array()); + $driver->setRemoteFilesystem($this->remoteFilesystem->reveal()); $expected = array(