1
0
Fork 0

Fix gitlab driver issues not asking for auth when token is missing, and not falling back properly to git driver

pull/6093/merge
Jordi Boggiano 2017-03-08 10:26:08 +01:00
parent daff57189f
commit f200343cf2
3 changed files with 91 additions and 5 deletions

View File

@ -212,7 +212,8 @@ class GitHubDriver extends VcsDriver
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getChangeDate($identifier) { public function getChangeDate($identifier)
{
if ($this->gitDriver) { if ($this->gitDriver) {
return $this->gitDriver->getChangeDate($identifier); return $this->gitDriver->getChangeDate($identifier);
} }

View File

@ -59,6 +59,13 @@ class GitLabDriver extends VcsDriver
*/ */
protected $gitDriver; protected $gitDriver;
/**
* Defaults to true unless we can make sure it is public
*
* @var bool defines whether the repo is private or not
*/
private $isPrivate = true;
const URL_REGEX = '#^(?:(?P<scheme>https?)://(?P<domain>.+?)/|git@(?P<domain2>[^:]+):)(?P<owner>[^/]+)/(?P<repo>[^/]+?)(?:\.git|/)?$#'; const URL_REGEX = '#^(?:(?P<scheme>https?)://(?P<domain>.+?)/|git@(?P<domain2>[^:]+):)(?P<owner>[^/]+)/(?P<repo>[^/]+?)(?:\.git|/)?$#';
/** /**
@ -100,6 +107,10 @@ class GitLabDriver extends VcsDriver
*/ */
public function getFileContent($file, $identifier) public function getFileContent($file, $identifier)
{ {
if ($this->gitDriver) {
return $this->gitDriver->getFileContent($file, $identifier);
}
// Convert the root identifier to a cachable commit id // Convert the root identifier to a cachable commit id
if (!preg_match('{[a-f0-9]{40}}i', $identifier)) { if (!preg_match('{[a-f0-9]{40}}i', $identifier)) {
$branches = $this->getBranches(); $branches = $this->getBranches();
@ -127,6 +138,10 @@ class GitLabDriver extends VcsDriver
*/ */
public function getChangeDate($identifier) public function getChangeDate($identifier)
{ {
if ($this->gitDriver) {
return $this->gitDriver->getChangeDate($identifier);
}
if (isset($this->commits[$identifier])) { if (isset($this->commits[$identifier])) {
return new \DateTime($this->commits[$identifier]['committed_date']); return new \DateTime($this->commits[$identifier]['committed_date']);
} }
@ -140,7 +155,7 @@ class GitLabDriver extends VcsDriver
*/ */
public function getRepositoryUrl() public function getRepositoryUrl()
{ {
return $this->project['public'] ? $this->project['http_url_to_repo'] : $this->project['ssh_url_to_repo']; return $this->isPrivate ? $this->project['ssh_url_to_repo'] : $this->project['http_url_to_repo'];
} }
/** /**
@ -148,6 +163,10 @@ class GitLabDriver extends VcsDriver
*/ */
public function getUrl() public function getUrl()
{ {
if ($this->gitDriver) {
return $this->gitDriver->getUrl();
}
return $this->project['web_url']; return $this->project['web_url'];
} }
@ -166,6 +185,10 @@ class GitLabDriver extends VcsDriver
*/ */
public function getSource($identifier) public function getSource($identifier)
{ {
if ($this->gitDriver) {
return $this->gitDriver->getSource($identifier);
}
return array('type' => 'git', 'url' => $this->getRepositoryUrl(), 'reference' => $identifier); return array('type' => 'git', 'url' => $this->getRepositoryUrl(), 'reference' => $identifier);
} }
@ -174,6 +197,10 @@ class GitLabDriver extends VcsDriver
*/ */
public function getRootIdentifier() public function getRootIdentifier()
{ {
if ($this->gitDriver) {
return $this->gitDriver->getRootIdentifier();
}
return $this->project['default_branch']; return $this->project['default_branch'];
} }
@ -182,6 +209,10 @@ class GitLabDriver extends VcsDriver
*/ */
public function getBranches() public function getBranches()
{ {
if ($this->gitDriver) {
return $this->gitDriver->getBranches();
}
if (!$this->branches) { if (!$this->branches) {
$this->branches = $this->getReferences('branches'); $this->branches = $this->getReferences('branches');
} }
@ -194,6 +225,10 @@ class GitLabDriver extends VcsDriver
*/ */
public function getTags() public function getTags()
{ {
if ($this->gitDriver) {
return $this->gitDriver->getTags();
}
if (!$this->tags) { if (!$this->tags) {
$this->tags = $this->getReferences('tags'); $this->tags = $this->getReferences('tags');
} }
@ -257,21 +292,28 @@ class GitLabDriver extends VcsDriver
// we need to fetch the default branch from the api // we need to fetch the default branch from the api
$resource = $this->getApiUrl(); $resource = $this->getApiUrl();
$this->project = JsonFile::parseJson($this->getContents($resource, true), $resource); $this->project = JsonFile::parseJson($this->getContents($resource, true), $resource);
$this->isPrivate = !$this->project['public'];
} }
protected function attemptCloneFallback() protected function attemptCloneFallback()
{ {
try { try {
if ($this->isPrivate === false) {
$url = $this->generatePublicUrl();
} else {
$url = $this->generateSshUrl();
}
// If this repository may be private and we // If this repository may be private and we
// cannot ask for authentication credentials (because we // cannot ask for authentication credentials (because we
// are not interactive) then we fallback to GitDriver. // are not interactive) then we fallback to GitDriver.
$this->setupGitDriver($this->generateSshUrl()); $this->setupGitDriver($url);
return; return;
} catch (\RuntimeException $e) { } catch (\RuntimeException $e) {
$this->gitDriver = null; $this->gitDriver = null;
$this->io->writeError('<error>Failed to clone the '.$this->generateSshUrl().' repository, try running in interactive mode so that you can enter your credentials</error>'); $this->io->writeError('<error>Failed to clone the '.$url.' repository, try running in interactive mode so that you can enter your credentials</error>');
throw $e; throw $e;
} }
} }
@ -286,6 +328,11 @@ class GitLabDriver extends VcsDriver
return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git'; return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git';
} }
protected function generatePublicUrl()
{
return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
}
protected function setupGitDriver($url) protected function setupGitDriver($url)
{ {
$this->gitDriver = new GitDriver( $this->gitDriver = new GitDriver(
@ -304,7 +351,22 @@ class GitLabDriver extends VcsDriver
protected function getContents($url, $fetchingRepoData = false) protected function getContents($url, $fetchingRepoData = false)
{ {
try { try {
return parent::getContents($url); $res = parent::getContents($url);
if ($fetchingRepoData) {
$json = JsonFile::parseJson($res, $url);
// force auth as the unauthenticated version of the API is broken
if (!isset($json['default_branch'])) {
if (!empty($json['id'])) {
$this->isPrivate = false;
}
throw new TransportException('GitLab API seems to not be authenticated as it did not return a default_branch', 401);
}
}
return $res;
} catch (TransportException $e) { } catch (TransportException $e) {
$gitLabUtil = new GitLab($this->io, $this->config, $this->process, $this->remoteFilesystem); $gitLabUtil = new GitLab($this->io, $this->config, $this->process, $this->remoteFilesystem);

View File

@ -293,8 +293,31 @@ JSON;
$url = 'https://mycompany.com/gitlab/mygroup/my-pro.ject'; $url = 'https://mycompany.com/gitlab/mygroup/my-pro.ject';
$apiUrl = 'https://mycompany.com/gitlab/api/v3/projects/mygroup%2Fmy-pro%2Eject'; $apiUrl = 'https://mycompany.com/gitlab/api/v3/projects/mygroup%2Fmy-pro%2Eject';
$projectData = <<<JSON
{
"id": 17,
"default_branch": "mymaster",
"public": false,
"http_url_to_repo": "https://gitlab.com/mygroup/my-pro.ject",
"ssh_url_to_repo": "git@gitlab.com:mygroup/my-pro.ject.git",
"last_activity_at": "2014-12-01T09:17:51.000+01:00",
"name": "My Project",
"name_with_namespace": "My Group / My Project",
"path": "myproject",
"path_with_namespace": "mygroup/my-pro.ject",
"web_url": "https://gitlab.com/mygroup/my-pro.ject"
}
JSON;
$this->remoteFilesystem
->getContents('mycompany.com/gitlab', $apiUrl, false)
->willReturn($projectData)
->shouldBeCalledTimes(1)
;
$driver = new GitLabDriver(array('url' => $url), $this->io->reveal(), $this->config, $this->process->reveal(), $this->remoteFilesystem->reveal()); $driver = new GitLabDriver(array('url' => $url), $this->io->reveal(), $this->config, $this->process->reveal(), $this->remoteFilesystem->reveal());
$driver->initialize(); $driver->initialize();
$this->assertEquals($apiUrl, $driver->getApiUrl(), 'API URL is derived from the repository URL'); $this->assertEquals($apiUrl, $driver->getApiUrl(), 'API URL is derived from the repository URL');
} }
} }