diff --git a/src/Composer/Repository/Vcs/GitBitbucketDriver.php b/src/Composer/Repository/Vcs/GitBitbucketDriver.php new file mode 100644 index 000000000..1ac4f85f3 --- /dev/null +++ b/src/Composer/Repository/Vcs/GitBitbucketDriver.php @@ -0,0 +1,163 @@ + + * 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\Json\JsonFile; + +/** + * @author Per Bernhardt + */ +class GitBitbucketDriver implements VcsDriverInterface +{ + protected $url; + protected $owner; + protected $repository; + protected $tags; + protected $branches; + protected $rootIdentifier; + protected $infoCache = array(); + + public function __construct($url) + { + $this->url = $url; + preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)\.git$#', $url, $match); + $this->owner = $match[1]; + $this->repository = $match[2]; + } + + /** + * {@inheritDoc} + */ + public function initialize() + { + } + + /** + * {@inheritDoc} + */ + public function getRootIdentifier() + { + if (null === $this->rootIdentifier) { + $repoData = json_decode(file_get_contents('https://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository), true); + $this->rootIdentifier = $repoData['main_branch'] ?: 'master'; + } + + return $this->rootIdentifier; + } + + /** + * {@inheritDoc} + */ + public function getUrl() + { + return $this->url; + } + + /** + * {@inheritDoc} + */ + public function getSource($identifier) + { + $label = array_search($identifier, $this->getTags()) ?: $identifier; + + return array('type' => 'git', 'url' => $this->getUrl(), 'reference' => $label); + } + + /** + * {@inheritDoc} + */ + public function getDist($identifier) + { + $label = array_search($identifier, $this->getTags()) ?: $identifier; + $url = 'https://bitbucket.org/'.$this->owner.'/'.$this->repository.'/get/'.$label.'.zip'; + + return array('type' => 'zip', 'url' => $url, 'reference' => $label, 'shasum' => ''); + } + + /** + * {@inheritDoc} + */ + public function getComposerInformation($identifier) + { + if (!isset($this->infoCache[$identifier])) { + $composer = @file_get_contents('https://bitbucket.org/'.$this->owner.'/'.$this->repository.'/raw/'.$identifier.'/composer.json'); + if (!$composer) { + throw new \UnexpectedValueException('Failed to retrieve composer information for identifier '.$identifier.' in '.$this->getUrl()); + } + + $composer = JsonFile::parseJson($composer); + + if (!isset($composer['time'])) { + $changeset = json_decode(file_get_contents('https://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/changesets/'.$identifier), true); + $composer['time'] = $changeset['timestamp']; + } + $this->infoCache[$identifier] = $composer; + } + + return $this->infoCache[$identifier]; + } + + /** + * {@inheritDoc} + */ + public function getTags() + { + if (null === $this->tags) { + $tagsData = json_decode(file_get_contents('https://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags'), true); + $this->tags = array(); + foreach ($tagsData as $tag => $data) { + $this->tags[$tag] = $data['raw_node']; + } + } + + return $this->tags; + } + + /** + * {@inheritDoc} + */ + public function getBranches() + { + if (null === $this->branches) { + $branchData = json_decode(file_get_contents('https://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/branches'), true); + $this->branches = array(); + foreach ($branchData as $branch => $data) { + $this->branches[$branch] = $data['raw_node']; + } + } + + return $this->branches; + } + + /** + * {@inheritDoc} + */ + public function hasComposerFile($identifier) + { + try { + $this->getComposerInformation($identifier); + return true; + } catch (\Exception $e) { + } + + return false; + } + + /** + * {@inheritDoc} + */ + public static function supports($url, $deep = false) + { + return preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)\.git$#', $url, $match); + } +} diff --git a/src/Composer/Repository/Vcs/HgBitbucketDriver.php b/src/Composer/Repository/Vcs/HgBitbucketDriver.php new file mode 100644 index 000000000..9c1c82b3b --- /dev/null +++ b/src/Composer/Repository/Vcs/HgBitbucketDriver.php @@ -0,0 +1,164 @@ + + * 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\Json\JsonFile; + +/** + * @author Per Bernhardt + */ +class HgBitbucketDriver implements VcsDriverInterface +{ + protected $url; + protected $owner; + protected $repository; + protected $tags; + protected $branches; + protected $rootIdentifier; + protected $infoCache = array(); + + public function __construct($url) + { + $this->url = $url; + preg_match('#^https://bitbucket\.org/([^/]+)/([^/]+)/?$#', $url, $match); + $this->owner = $match[1]; + $this->repository = $match[2]; + } + + /** + * {@inheritDoc} + */ + public function initialize() + { + } + + /** + * {@inheritDoc} + */ + public function getRootIdentifier() + { + if (null === $this->rootIdentifier) { + $repoData = json_decode(file_get_contents('https://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags'), true); + $this->rootIdentifier = $repoData['tip']['raw_node']; + } + + return $this->rootIdentifier; + } + + /** + * {@inheritDoc} + */ + public function getUrl() + { + return $this->url; + } + + /** + * {@inheritDoc} + */ + public function getSource($identifier) + { + $label = array_search($identifier, $this->getTags()) ?: $identifier; + + return array('type' => 'hg', 'url' => $this->getUrl(), 'reference' => $label); + } + + /** + * {@inheritDoc} + */ + public function getDist($identifier) + { + $label = array_search($identifier, $this->getTags()) ?: $identifier; + $url = 'https://bitbucket.org/'.$this->owner.'/'.$this->repository.'/get/'.$label.'.zip'; + + return array('type' => 'zip', 'url' => $url, 'reference' => $label, 'shasum' => ''); + } + + /** + * {@inheritDoc} + */ + public function getComposerInformation($identifier) + { + if (!isset($this->infoCache[$identifier])) { + $composer = @file_get_contents('https://bitbucket.org/'.$this->owner.'/'.$this->repository.'/raw/'.$identifier.'/composer.json'); + if (!$composer) { + throw new \UnexpectedValueException('Failed to retrieve composer information for identifier '.$identifier.' in '.$this->getUrl()); + } + + $composer = JsonFile::parseJson($composer); + + if (!isset($composer['time'])) { + $changeset = json_decode(file_get_contents('https://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/changesets/'.$identifier), true); + $composer['time'] = $changeset['timestamp']; + } + $this->infoCache[$identifier] = $composer; + } + + return $this->infoCache[$identifier]; + } + + /** + * {@inheritDoc} + */ + public function getTags() + { + if (null === $this->tags) { + $tagsData = json_decode(file_get_contents('https://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags'), true); + $this->tags = array(); + foreach ($tagsData as $tag => $data) { + $this->tags[$tag] = $data['raw_node']; + } + unset($this->tags['tip']); + } + + return $this->tags; + } + + /** + * {@inheritDoc} + */ + public function getBranches() + { + if (null === $this->branches) { + $branchData = json_decode(file_get_contents('https://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/branches'), true); + $this->branches = array(); + foreach ($branchData as $branch => $data) { + $this->branches[$branch] = $data['raw_node']; + } + } + + return $this->branches; + } + + /** + * {@inheritDoc} + */ + public function hasComposerFile($identifier) + { + try { + $this->getComposerInformation($identifier); + return true; + } catch (\Exception $e) { + } + + return false; + } + + /** + * {@inheritDoc} + */ + public static function supports($url, $deep = false) + { + return preg_match('#^https://bitbucket\.org/([^/]+)/([^/]+)/?$#', $url, $match); + } +}