diff --git a/src/Composer/Repository/Vcs/BitbucketDriver.php b/src/Composer/Repository/Vcs/BitbucketDriver.php index 8a2e78a98..00401e253 100644 --- a/src/Composer/Repository/Vcs/BitbucketDriver.php +++ b/src/Composer/Repository/Vcs/BitbucketDriver.php @@ -1,5 +1,15 @@ + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Composer\Repository\Vcs; use Composer\Cache; @@ -23,12 +33,13 @@ abstract class BitbucketDriver extends VcsDriver protected $homeUrl = ''; protected $website = ''; protected $cloneHttpsUrl = ''; - protected $cloneSshUrl = ''; /** * @var VcsDriver */ protected $fallbackDriver; + /** @var string|null if set either git or hg */ + protected $vcsType; /** * {@inheritDoc} @@ -55,11 +66,18 @@ abstract class BitbucketDriver extends VcsDriver */ public function getUrl() { + if ($this->fallbackDriver) { + return $this->fallbackDriver->getUrl(); + } + return $this->cloneHttpsUrl; } /** - * @return array + * Attempts to fetch the repository data via the BitBucket API and + * sets some parameters which are used in other methods + * + * @return void */ protected function getRepoData() { @@ -73,6 +91,9 @@ abstract class BitbucketDriver extends VcsDriver ); $repoData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource, true), $resource); + if ($this->fallbackDriver) { + throw new BitbucketFallbackException(); + } $this->parseCloneUrls($repoData['links']['clone']); $this->hasIssues = !empty($repoData['has_issues']); @@ -80,8 +101,7 @@ abstract class BitbucketDriver extends VcsDriver $this->tagsUrl = $repoData['links']['tags']['href']; $this->homeUrl = $repoData['links']['html']['href']; $this->website = $repoData['website']; - - return $repoData; + $this->vcsType = $repoData['scm']; } /** @@ -173,7 +193,7 @@ abstract class BitbucketDriver extends VcsDriver $file ); - return $this->getContents($resource); + return $this->getContentsWithOAuthCredentials($resource); } /** @@ -187,16 +207,32 @@ abstract class BitbucketDriver extends VcsDriver $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/' . $this->owner . '/' . $this->repository . '/changesets/' . $identifier; - $changeset = JsonFile::parseJson($this->getContents($resource), $resource); + $changeset = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource); return new \DateTime($changeset['timestamp']); } + /** + * {@inheritDoc} + */ + public function getSource($identifier) + { + if ($this->fallbackDriver) { + return $this->fallbackDriver->getSource($identifier); + } + + return array('type' => $this->vcsType, 'url' => $this->getUrl(), 'reference' => $identifier); + } + /** * {@inheritDoc} */ public function getDist($identifier) { + if ($this->fallbackDriver) { + return $this->fallbackDriver->getDist($identifier); + } + $url = sprintf( 'https://bitbucket.org/%s/%s/get/%s.zip', $this->owner, @@ -212,6 +248,10 @@ abstract class BitbucketDriver extends VcsDriver */ public function getTags() { + if ($this->fallbackDriver) { + return $this->fallbackDriver->getTags(); + } + if (null === $this->tags) { $this->tags = array(); $resource = sprintf( @@ -236,6 +276,9 @@ abstract class BitbucketDriver extends VcsDriver $resource = $tagsData['next']; } } + if ($this->vcsType === 'hg') { + unset($this->tags['tip']); + } } return $this->tags; @@ -246,6 +289,10 @@ abstract class BitbucketDriver extends VcsDriver */ public function getBranches() { + if ($this->fallbackDriver) { + return $this->fallbackDriver->getBranches(); + } + if (null === $this->branches) { $this->branches = array(); $resource = sprintf( @@ -311,10 +358,7 @@ abstract class BitbucketDriver extends VcsDriver * * @return string */ - protected function generateSshUrl() - { - return $this->cloneSshUrl; - } + abstract protected function generateSshUrl(); protected function attemptCloneFallback() { @@ -331,6 +375,10 @@ abstract class BitbucketDriver extends VcsDriver } } + /** + * @param string $url + * @return void + */ abstract protected function setupFallbackDriver($url); /** @@ -344,13 +392,21 @@ abstract class BitbucketDriver extends VcsDriver // Format: https://(user@)bitbucket.org/{user}/{repo} // Strip username from URL (only present in clone URL's for private repositories) $this->cloneHttpsUrl = preg_replace('/https:\/\/([^@]+@)?/', 'https://', $cloneLink['href']); - } elseif ($cloneLink['name'] === 'ssh') { - // Format: ssh://{git or hg}@bitbucket.org/{user}/{repo} - // Replace for git URL's - $href = preg_replace('/ssh:\/\/git@bitbucket\.org\//', 'git@bitbucket.org:', $cloneLink['href']); - // Replace for hg URL's - $this->cloneSshUrl = str_replace('ssh://', '', $href); } } } + + /** + * @return array|null + */ + protected function getMainBranchData() + { + $resource = sprintf( + 'https://api.bitbucket.org/1.0/repositories/%s/%s/main-branch', + $this->owner, + $this->repository + ); + + return JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource); + } } diff --git a/src/Composer/Repository/Vcs/BitbucketFallbackException.php b/src/Composer/Repository/Vcs/BitbucketFallbackException.php new file mode 100644 index 000000000..063bb4c10 --- /dev/null +++ b/src/Composer/Repository/Vcs/BitbucketFallbackException.php @@ -0,0 +1,17 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Repository\Vcs; + +class BitbucketFallbackException extends \RuntimeException +{ +} diff --git a/src/Composer/Repository/Vcs/GitBitbucketDriver.php b/src/Composer/Repository/Vcs/GitBitbucketDriver.php index d128ad6ab..292ab01b1 100644 --- a/src/Composer/Repository/Vcs/GitBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/GitBitbucketDriver.php @@ -13,13 +13,12 @@ namespace Composer\Repository\Vcs; use Composer\Config; -use Composer\Json\JsonFile; use Composer\IO\IOInterface; /** * @author Per Bernhardt */ -class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface +class GitBitbucketDriver extends BitbucketDriver { /** * {@inheritDoc} @@ -31,75 +30,26 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface } if (null === $this->rootIdentifier) { - $repoData = $this->getRepoData(); + try { + $this->getRepoData(); + } catch (BitbucketFallbackException $e) { + return $this->fallbackDriver->getRootIdentifier(); + } - if ($repoData['scm'] !== 'git') { + if ($this->vcsType !== 'git') { throw new \RuntimeException( $this->url.' does not appear to be a git repository, use '. $this->cloneHttpsUrl.' if this is a mercurial bitbucket repository' ); } - $resource = sprintf( - 'https://api.bitbucket.org/1.0/repositories/%s/%s/main-branch', - $this->owner, - $this->repository - ); - $main_branch_data = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource, true), $resource); + $main_branch_data = $this->getMainBranchData(); $this->rootIdentifier = !empty($main_branch_data['name']) ? $main_branch_data['name'] : 'master'; } return $this->rootIdentifier; } - /** - * {@inheritDoc} - */ - public function getUrl() - { - if ($this->fallbackDriver) { - return $this->fallbackDriver->getUrl(); - } - - return parent::getUrl(); - } - - /** - * {@inheritDoc} - */ - public function getSource($identifier) - { - if ($this->fallbackDriver) { - return $this->fallbackDriver->getSource($identifier); - } - - return array('type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier); - } - - /** - * {@inheritDoc} - */ - public function getTags() - { - if ($this->fallbackDriver) { - return $this->fallbackDriver->getTags(); - } - - return parent::getTags(); - } - - /** - * {@inheritDoc} - */ - public function getBranches() - { - if ($this->fallbackDriver) { - return $this->fallbackDriver->getBranches(); - } - - return parent::getBranches(); - } - /** * {@inheritDoc} */ @@ -119,7 +69,7 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface } /** - * @param string $url + * {@inheritdoc} */ protected function setupFallbackDriver($url) { @@ -132,4 +82,12 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface ); $this->fallbackDriver->initialize(); } + + /** + * {@inheritdoc} + */ + protected function generateSshUrl() + { + return 'git@' . $this->originUrl . ':' . $this->owner.'/'.$this->repository.'.git'; + } } diff --git a/src/Composer/Repository/Vcs/HgBitbucketDriver.php b/src/Composer/Repository/Vcs/HgBitbucketDriver.php index 573259e2e..cf76a5115 100644 --- a/src/Composer/Repository/Vcs/HgBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/HgBitbucketDriver.php @@ -13,7 +13,6 @@ namespace Composer\Repository\Vcs; use Composer\Config; -use Composer\Json\JsonFile; use Composer\IO\IOInterface; /** @@ -26,50 +25,31 @@ class HgBitbucketDriver extends BitbucketDriver */ public function getRootIdentifier() { - if (null === $this->rootIdentifier) { - $repoData = $this->getRepoData(); + if ($this->fallbackDriver) { + return $this->fallbackDriver->getRootIdentifier(); + } - if ($repoData['scm'] !== 'hg') { + if (null === $this->rootIdentifier) { + try { + $this->getRepoData(); + } catch (BitbucketFallbackException $e) { + return $this->fallbackDriver->getRootIdentifier(); + } + + if ($this->vcsType !== 'hg') { throw new \RuntimeException( $this->url.' does not appear to be a mercurial repository, use '. $this->cloneHttpsUrl.' if this is a git bitbucket repository' ); } - $resource = sprintf( - 'https://api.bitbucket.org/1.0/repositories/%s/%s/main-branch', - $this->owner, - $this->repository - ); - $main_branch_data = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource, true), $resource); + $main_branch_data = $this->getMainBranchData(); $this->rootIdentifier = !empty($main_branch_data['name']) ? $main_branch_data['name'] : 'default'; } return $this->rootIdentifier; } - /** - * {@inheritDoc} - */ - public function getSource($identifier) - { - return array('type' => 'hg', 'url' => $this->getUrl(), 'reference' => $identifier); - } - - /** - * {@inheritDoc} - */ - public function getTags() - { - parent::getTags(); - - if (isset($this->tags['tip'])) { - unset($this->tags['tip']); - } - - return $this->tags; - } - /** * {@inheritDoc} */ @@ -88,6 +68,9 @@ class HgBitbucketDriver extends BitbucketDriver return true; } + /** + * {@inheritdoc} + */ protected function setupFallbackDriver($url) { $this->fallbackDriver = new HgDriver( @@ -99,4 +82,12 @@ class HgBitbucketDriver extends BitbucketDriver ); $this->fallbackDriver->initialize(); } + + /** + * {@inheritdoc} + */ + protected function generateSshUrl() + { + return 'ssh://hg@' . $this->originUrl . '/' . $this->owner.'/'.$this->repository; + } }