From 597f834ae998ea80797879f4259e8e6accff4a4b Mon Sep 17 00:00:00 2001 From: Thomas Flori Date: Fri, 11 Nov 2016 09:06:03 +0100 Subject: [PATCH 1/5] add getFileContent function This function is very similar to a part from getComposerInformation - so we can use this function in getComposerInformation too. And because it is almost everywhere the same we can put it to abstract class. By implementing getComposerInformation in abstract class we need to add the getChangeDate to interface too. Only Problem: perforce seems not to support a ChangeDate. For this we use 'now' to have at least something. --- .../Repository/Vcs/BitbucketDriver.php | 184 ++++++++++++++++++ src/Composer/Repository/Vcs/FossilDriver.php | 34 ++-- .../Repository/Vcs/GitBitbucketDriver.php | 155 +++------------ src/Composer/Repository/Vcs/GitDriver.php | 44 ++--- src/Composer/Repository/Vcs/GitHubDriver.php | 98 ++++++---- src/Composer/Repository/Vcs/GitLabDriver.php | 49 ++++- .../Repository/Vcs/HgBitbucketDriver.php | 73 ++----- src/Composer/Repository/Vcs/HgDriver.php | 34 ++-- .../Repository/Vcs/PerforceDriver.php | 16 ++ src/Composer/Repository/Vcs/SvnDriver.php | 59 ++++++ src/Composer/Repository/Vcs/VcsDriver.php | 28 +++ .../Repository/Vcs/VcsDriverInterface.php | 17 ++ src/Composer/Util/Perforce.php | 42 ++++ 13 files changed, 542 insertions(+), 291 deletions(-) create mode 100644 src/Composer/Repository/Vcs/BitbucketDriver.php diff --git a/src/Composer/Repository/Vcs/BitbucketDriver.php b/src/Composer/Repository/Vcs/BitbucketDriver.php new file mode 100644 index 000000000..4e3a55f26 --- /dev/null +++ b/src/Composer/Repository/Vcs/BitbucketDriver.php @@ -0,0 +1,184 @@ +url, $match); + $this->owner = $match[1]; + $this->repository = $match[2]; + $this->originUrl = 'bitbucket.org'; + $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository); + } + + /** + * {@inheritDoc} + */ + public function getComposerInformation($identifier) + { + if ($this->sshDriver) { + return $this->sshDriver->getComposerInformation($identifier); + } + + if (!isset($this->infoCache[$identifier])) { + + $composer = parent::getComposerInformation($identifier); + + // specials for bitbucket + if (!isset($composer['support']['source'])) { + $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier; + + if (array_key_exists($label, $tags = $this->getTags())) { + $hash = $tags[$label]; + } elseif (array_key_exists($label, $branches = $this->getBranches())) { + $hash = $branches[$label]; + } + + if (! isset($hash)) { + $composer['support']['source'] = sprintf('https://%s/%s/%s/src', $this->originUrl, $this->owner, $this->repository); + } else { + $composer['support']['source'] = sprintf( + 'https://%s/%s/%s/src/%s/?at=%s', + $this->originUrl, + $this->owner, + $this->repository, + $hash, + $label + ); + } + } + if (!isset($composer['support']['issues']) && $this->hasIssues) { + $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository); + } + + $this->infoCache[$identifier] = $composer; + } + + return $this->infoCache[$identifier]; + } + + /** + * {@inheritdoc} + */ + public function getFileContent($file, $identifier) { + if ($this->sshDriver) { + return $this->sshDriver->getFileContent($file, $identifier); + } + + if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier . ':' . $file)) { + return $res; + } + + $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/src/'.$identifier.'/' . $file; + $fileData = JsonFile::parseJson($this->getContents($resource), $resource); + if (!is_array($fileData) || ! array_key_exists('data', $fileData)) { + return null; + } + + if (preg_match('{[a-f0-9]{40}}i', $identifier)) { + $this->cache->write($identifier . ':' . $file, $fileData['data']); + } + + return $fileData['data']; + } + + /** + * {@inheritdoc} + */ + public function getChangeDate($identifier) { + if ($this->sshDriver) { + return $this->sshDriver->getChangeDate($identifier); + } + + $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/changesets/'.$identifier; + $changeset = JsonFile::parseJson($this->getContents($resource), $resource); + + return new \DateTime($changeset['timestamp']); + } + + /** + * Get the remote content. + * + * @param string $url The URL of content + * @param bool $fetchingRepoData + * + * @return mixed The result + */ + protected function getContentsWithOAuthCredentials($url, $fetchingRepoData = false) + { + try { + return parent::getContents($url); + } catch (TransportException $e) { + $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process, $this->remoteFilesystem); + + switch ($e->getCode()) { + case 403: + if (!$this->io->hasAuthentication($this->originUrl) && $bitbucketUtil->authorizeOAuth($this->originUrl)) { + return parent::getContents($url); + } + + if (!$this->io->isInteractive() && $fetchingRepoData) { + return $this->attemptCloneFallback(); + } + + throw $e; + + default: + throw $e; + } + } + } + + /** + * Generate an SSH URL + * + * @return string + */ + protected function generateSshUrl() + { + return 'git@' . $this->originUrl . ':' . $this->owner.'/'.$this->repository.'.git'; + } + + protected function attemptCloneFallback() + { + try { + $this->setupSshDriver($this->generateSshUrl()); + + return; + } catch (\RuntimeException $e) { + $this->sshDriver = null; + + $this->io->writeError('Failed to clone the '.$this->generateSshUrl().' repository, try running in interactive mode so that you can enter your Bitbucket OAuth consumer credentials'); + throw $e; + } + } + + abstract protected function setupSshDriver($url); +} diff --git a/src/Composer/Repository/Vcs/FossilDriver.php b/src/Composer/Repository/Vcs/FossilDriver.php index 58fc9eb1b..b992db7ec 100644 --- a/src/Composer/Repository/Vcs/FossilDriver.php +++ b/src/Composer/Repository/Vcs/FossilDriver.php @@ -122,29 +122,27 @@ class FossilDriver extends VcsDriver } /** - * {@inheritDoc} + * {@inheritdoc} */ - public function getComposerInformation($identifier) + public function getFileContent($file, $identifier) { - if (!isset($this->infoCache[$identifier])) { - $command = sprintf('fossil cat -r %s composer.json', ProcessExecutor::escape($identifier)); - $this->process->execute($command, $composer, $this->checkoutDir); - - if (trim($composer) === '') { - return; - } + $command = sprintf('fossil cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file)); + $this->process->execute($command, $content, $this->checkoutDir); - $composer = JsonFile::parseJson(trim($composer), $identifier); - - if (empty($composer['time'])) { - $this->process->execute(sprintf('fossil finfo composer.json | head -n 2 | tail -n 1 | awk \'{print $1}\''), $output, $this->checkoutDir); - $date = new \DateTime(trim($output), new \DateTimeZone('UTC')); - $composer['time'] = $date->format('Y-m-d H:i:s'); - } - $this->infoCache[$identifier] = $composer; + if (!trim($content)) { + return null; } - return $this->infoCache[$identifier]; + return $content; + } + + /** + * {@inheritdoc} + */ + public function getChangeDate($identifier) + { + $this->process->execute(sprintf('fossil finfo composer.json | head -n 2 | tail -n 1 | awk \'{print $1}\''), $output, $this->checkoutDir); + return new \DateTime(trim($output), new \DateTimeZone('UTC')); } /** diff --git a/src/Composer/Repository/Vcs/GitBitbucketDriver.php b/src/Composer/Repository/Vcs/GitBitbucketDriver.php index 72af4183e..03a9fddaf 100644 --- a/src/Composer/Repository/Vcs/GitBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/GitBitbucketDriver.php @@ -22,43 +22,18 @@ use Composer\Util\Bitbucket; /** * @author Per Bernhardt */ -class GitBitbucketDriver extends VcsDriver implements VcsDriverInterface +class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface { - /** - * @var Cache - */ - protected $cache; - protected $owner; - protected $repository; - protected $tags; - protected $branches; - protected $rootIdentifier; - protected $infoCache = array(); - private $hasIssues; - /** - * @var GitDriver - */ - private $gitDriver; - /** - * {@inheritDoc} - */ - public function initialize() - { - preg_match('#^https?://bitbucket\.org/([^/]+)/(.+?)\.git$#', $this->url, $match); - $this->owner = $match[1]; - $this->repository = $match[2]; - $this->originUrl = 'bitbucket.org'; - $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository); - } + /** * {@inheritDoc} */ public function getRootIdentifier() { - if ($this->gitDriver) { - return $this->gitDriver->getRootIdentifier(); + if ($this->sshDriver) { + return $this->sshDriver->getRootIdentifier(); } if (null === $this->rootIdentifier) { @@ -76,8 +51,8 @@ class GitBitbucketDriver extends VcsDriver implements VcsDriverInterface */ public function getUrl() { - if ($this->gitDriver) { - return $this->gitDriver->getUrl(); + if ($this->sshDriver) { + return $this->sshDriver->getUrl(); } return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git'; @@ -88,8 +63,8 @@ class GitBitbucketDriver extends VcsDriver implements VcsDriverInterface */ public function getSource($identifier) { - if ($this->gitDriver) { - return $this->gitDriver->getSource($identifier); + if ($this->sshDriver) { + return $this->sshDriver->getSource($identifier); } return array('type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier); @@ -105,76 +80,14 @@ class GitBitbucketDriver extends VcsDriver implements VcsDriverInterface return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => ''); } - /** - * {@inheritDoc} - */ - public function getComposerInformation($identifier) - { - if ($this->gitDriver) { - return $this->gitDriver->getComposerInformation($identifier); - } - - if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier)) { - $this->infoCache[$identifier] = JsonFile::parseJson($res); - } - - if (!isset($this->infoCache[$identifier])) { - $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/src/'.$identifier.'/composer.json'; - $file = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource); - if (!is_array($file) || ! array_key_exists('data', $file)) { - return array(); - } - - $composer = JsonFile::parseJson($file['data'], $resource); - - if (empty($composer['time'])) { - $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/changesets/'.$identifier; - $changeset = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource); - $composer['time'] = $changeset['timestamp']; - } - if (!isset($composer['support']['source'])) { - $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier; - - if (array_key_exists($label, $tags = $this->getTags())) { - $hash = $tags[$label]; - } elseif (array_key_exists($label, $branches = $this->getBranches())) { - $hash = $branches[$label]; - } - - if (! isset($hash)) { - $composer['support']['source'] = sprintf('https://%s/%s/%s/src', $this->originUrl, $this->owner, $this->repository); - } else { - $composer['support']['source'] = sprintf( - 'https://%s/%s/%s/src/%s/?at=%s', - $this->originUrl, - $this->owner, - $this->repository, - $hash, - $label - ); - } - } - if (!isset($composer['support']['issues']) && $this->hasIssues) { - $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository); - } - - if (preg_match('{[a-f0-9]{40}}i', $identifier)) { - $this->cache->write($identifier, json_encode($composer)); - } - - $this->infoCache[$identifier] = $composer; - } - - return $this->infoCache[$identifier]; - } /** * {@inheritDoc} */ public function getTags() { - if ($this->gitDriver) { - return $this->gitDriver->getTags(); + if ($this->sshDriver) { + return $this->sshDriver->getTags(); } if (null === $this->tags) { @@ -194,8 +107,8 @@ class GitBitbucketDriver extends VcsDriver implements VcsDriverInterface */ public function getBranches() { - if ($this->gitDriver) { - return $this->gitDriver->getBranches(); + if ($this->sshDriver) { + return $this->sshDriver->getBranches(); } if (null === $this->branches) { @@ -228,28 +141,19 @@ class GitBitbucketDriver extends VcsDriver implements VcsDriverInterface return true; } - protected function attemptCloneFallback() - { - try { - $this->setupGitDriver($this->generateSshUrl()); - - return; - } catch (\RuntimeException $e) { - $this->gitDriver = null; - - $this->io->writeError('Failed to clone the '.$this->generateSshUrl().' repository, try running in interactive mode so that you can enter your Bitbucket OAuth consumer credentials'); - throw $e; - } - } - /** - * Generate an SSH URL - * - * @return string + * @param string $url */ - private function generateSshUrl() + protected function setupSshDriver($url) { - return 'git@' . $this->originUrl . ':' . $this->owner.'/'.$this->repository.'.git'; + $this->sshDriver = new GitDriver( + array('url' => $url), + $this->io, + $this->config, + $this->process, + $this->remoteFilesystem + ); + $this->sshDriver->initialize(); } /** @@ -284,19 +188,4 @@ class GitBitbucketDriver extends VcsDriver implements VcsDriverInterface } } } - - /** - * @param string $url - */ - private function setupGitDriver($url) - { - $this->gitDriver = new GitDriver( - array('url' => $url), - $this->io, - $this->config, - $this->process, - $this->remoteFilesystem - ); - $this->gitDriver->initialize(); - } } diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index bacad4d2c..685088c4b 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -120,38 +120,34 @@ class GitDriver extends VcsDriver } /** - * {@inheritDoc} + * {@inheritdoc} */ - public function getComposerInformation($identifier) + public function getFileContent($file, $identifier) { - if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier)) { - $this->infoCache[$identifier] = JsonFile::parseJson($res); + if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier . ':' . $file)) { + return $res; } - if (!isset($this->infoCache[$identifier])) { - $resource = sprintf('%s:composer.json', ProcessExecutor::escape($identifier)); - $this->process->execute(sprintf('git show %s', $resource), $composer, $this->repoDir); - - if (!trim($composer)) { - return; - } - - $composer = JsonFile::parseJson($composer, $resource); - - if (empty($composer['time'])) { - $this->process->execute(sprintf('git log -1 --format=%%at %s', ProcessExecutor::escape($identifier)), $output, $this->repoDir); - $date = new \DateTime('@'.trim($output), new \DateTimeZone('UTC')); - $composer['time'] = $date->format('Y-m-d H:i:s'); - } + $resource = sprintf('%s:%s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file)); + $this->process->execute(sprintf('git show %s', $resource), $content, $this->repoDir); - if (preg_match('{[a-f0-9]{40}}i', $identifier)) { - $this->cache->write($identifier, json_encode($composer)); - } + if (!trim($content)) { + return null; + } - $this->infoCache[$identifier] = $composer; + if (preg_match('{[a-f0-9]{40}}i', $identifier)) { + $this->cache->write($identifier . ':' . $file, $content); } - return $this->infoCache[$identifier]; + return $content; + } + + /** + * {@inheritdoc} + */ + public function getChangeDate($identifier) { + $this->process->execute(sprintf('git log -1 --format=%%at %s', ProcessExecutor::escape($identifier)), $output, $this->repoDir); + return new \DateTime('@'.trim($output), new \DateTimeZone('UTC')); } /** diff --git a/src/Composer/Repository/Vcs/GitHubDriver.php b/src/Composer/Repository/Vcs/GitHubDriver.php index 04d7321f5..04ac5d7cd 100644 --- a/src/Composer/Repository/Vcs/GitHubDriver.php +++ b/src/Composer/Repository/Vcs/GitHubDriver.php @@ -146,57 +146,79 @@ class GitHubDriver extends VcsDriver return $this->gitDriver->getComposerInformation($identifier); } - if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier)) { - $this->infoCache[$identifier] = JsonFile::parseJson($res); - } - if (!isset($this->infoCache[$identifier])) { - $notFoundRetries = 2; - while ($notFoundRetries) { - try { - $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/composer.json?ref='.urlencode($identifier); - $resource = JsonFile::parseJson($this->getContents($resource)); - if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($composer = base64_decode($resource['content']))) { - throw new \RuntimeException('Could not retrieve composer.json for '.$identifier); - } - break; - } catch (TransportException $e) { - if (404 !== $e->getCode()) { - throw $e; - } - // TODO should be removed when possible - // retry fetching if github returns a 404 since they happen randomly - $notFoundRetries--; - $composer = null; - } + $composer = parent::getComposerInformation($identifier); + + // specials for github + if (!isset($composer['support']['source'])) { + $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier; + $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label); + } + if (!isset($composer['support']['issues']) && $this->hasIssues) { + $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository); } - if ($composer) { - $composer = JsonFile::parseJson($composer, $resource); + $this->infoCache[$identifier] = $composer; + } + + return $this->infoCache[$identifier]; + } - if (empty($composer['time'])) { - $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier); - $commit = JsonFile::parseJson($this->getContents($resource), $resource); - $composer['time'] = $commit['commit']['committer']['date']; + /** + * {@inheritdoc} + */ + public function getFileContent($file, $identifier) + { + if ($this->gitDriver) { + return $this->gitDriver->getFileContent($file, $identifier); + } + + if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier . ':' . $file)) { + return $res; + } + + $notFoundRetries = 2; + while ($notFoundRetries) { + try { + + $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier); + $resource = JsonFile::parseJson($this->getContents($resource)); + if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) { + throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier); } - if (!isset($composer['support']['source'])) { - $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier; - $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label); + + if ($content && preg_match('{[a-f0-9]{40}}i', $identifier)) { + $this->cache->write($identifier . ':' . $file, $content); } - if (!isset($composer['support']['issues']) && $this->hasIssues) { - $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository); + + return $content; + } catch (TransportException $e) { + if (404 !== $e->getCode()) { + throw $e; } - } - if ($composer && preg_match('{[a-f0-9]{40}}i', $identifier)) { - $this->cache->write($identifier, json_encode($composer)); + // TODO should be removed when possible + // retry fetching if github returns a 404 since they happen randomly + $notFoundRetries--; + return null; } + } - $this->infoCache[$identifier] = $composer; + return null; + } + + /** + * {@inheritdoc} + */ + public function getChangeDate($identifier) { + if ($this->gitDriver) { + return $this->gitDriver->getChangeDate($identifier); } - return $this->infoCache[$identifier]; + $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier); + $commit = JsonFile::parseJson($this->getContents($resource), $resource); + return new \DateTime($commit['commit']['committer']['date']); } /** diff --git a/src/Composer/Repository/Vcs/GitLabDriver.php b/src/Composer/Repository/Vcs/GitLabDriver.php index ed91056d4..2ad00003a 100644 --- a/src/Composer/Repository/Vcs/GitLabDriver.php +++ b/src/Composer/Repository/Vcs/GitLabDriver.php @@ -33,7 +33,6 @@ class GitLabDriver extends VcsDriver private $repository; private $cache; - private $infoCache = array(); /** * @var array Project data returned by GitLab API @@ -143,6 +142,54 @@ class GitLabDriver extends VcsDriver return $this->infoCache[$identifier] = $composer; } + /** + * {@inheritdoc} + */ + public function getFileContent($file, $identifier) + { + // Convert the root identifier to a cachable commit id + if (!preg_match('{[a-f0-9]{40}}i', $identifier)) { + $branches = $this->getBranches(); + if (isset($branches[$identifier])) { + $identifier = $branches[$identifier]; + } + } + + if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier . ':' . $file)) { + return $res; + } + + $resource = $this->getApiUrl().'/repository/blobs/'.$identifier.'?filepath=' . $file; + + try { + $content = $this->getContents($resource); + } catch (TransportException $e) { + if ($e->getCode() !== 404) { + throw $e; + } + return null; + } + + if (preg_match('{[a-f0-9]{40}}i', $identifier)) { + $this->cache->write($identifier . ':' . $file, $content); + } + + return $content; + } + + /** + * {@inheritdoc} + */ + public function getChangeDate($identifier) + { + if (isset($this->commits[$identifier])) { + return new \DateTime($this->commits[$identifier]['committed_date']); + } + + return new \DateTime(); + } + + /** * {@inheritDoc} */ diff --git a/src/Composer/Repository/Vcs/HgBitbucketDriver.php b/src/Composer/Repository/Vcs/HgBitbucketDriver.php index eb6808601..d2d7cc1be 100644 --- a/src/Composer/Repository/Vcs/HgBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/HgBitbucketDriver.php @@ -20,27 +20,8 @@ use Composer\IO\IOInterface; /** * @author Per Bernhardt */ -class HgBitbucketDriver extends VcsDriver +class HgBitbucketDriver extends BitbucketDriver { - protected $cache; - protected $owner; - protected $repository; - protected $tags; - protected $branches; - protected $rootIdentifier; - protected $infoCache = array(); - - /** - * {@inheritDoc} - */ - public function initialize() - { - preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+)/?$#', $this->url, $match); - $this->owner = $match[1]; - $this->repository = $match[2]; - $this->originUrl = 'bitbucket.org'; - $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository); - } /** * {@inheritDoc} @@ -53,6 +34,7 @@ class HgBitbucketDriver extends VcsDriver if (array() === $repoData || !isset($repoData['tip'])) { throw new \RuntimeException($this->url.' does not appear to be a mercurial repository, use '.$this->url.'.git if this is a git bitbucket repository'); } + $this->hasIssues = !empty($repoData['has_issues']); $this->rootIdentifier = $repoData['tip']['raw_node']; } @@ -85,46 +67,6 @@ class HgBitbucketDriver extends VcsDriver return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => ''); } - /** - * {@inheritDoc} - */ - public function getComposerInformation($identifier) - { - if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier)) { - $this->infoCache[$identifier] = JsonFile::parseJson($res); - } - - if (!isset($this->infoCache[$identifier])) { - $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/'.$this->owner.'/'.$this->repository.'/src/'.$identifier.'/composer.json'; - $repoData = JsonFile::parseJson($this->getContents($resource), $resource); - - // Bitbucket does not send different response codes for found and - // not found files, so we have to check the response structure. - // found: {node: ..., data: ..., size: ..., ...} - // not found: {node: ..., files: [...], directories: [...], ...} - - if (!array_key_exists('data', $repoData)) { - return; - } - - $composer = JsonFile::parseJson($repoData['data'], $resource); - - if (empty($composer['time'])) { - $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/'.$this->owner.'/'.$this->repository.'/changesets/'.$identifier; - $changeset = JsonFile::parseJson($this->getContents($resource), $resource); - $composer['time'] = $changeset['timestamp']; - } - - if (preg_match('{[a-f0-9]{40}}i', $identifier)) { - $this->cache->write($identifier, json_encode($composer)); - } - - $this->infoCache[$identifier] = $composer; - } - - return $this->infoCache[$identifier]; - } - /** * {@inheritDoc} */ @@ -177,4 +119,15 @@ class HgBitbucketDriver extends VcsDriver return true; } + + protected function setupSshDriver($url) { + $this->sshDriver = new HgDriver( + array('url' => $url), + $this->io, + $this->config, + $this->process, + $this->remoteFilesystem + ); + $this->sshDriver->initialize(); + } } diff --git a/src/Composer/Repository/Vcs/HgDriver.php b/src/Composer/Repository/Vcs/HgDriver.php index 4dc103d38..451cec7ff 100644 --- a/src/Composer/Repository/Vcs/HgDriver.php +++ b/src/Composer/Repository/Vcs/HgDriver.php @@ -17,6 +17,7 @@ use Composer\Json\JsonFile; use Composer\Util\ProcessExecutor; use Composer\Util\Filesystem; use Composer\IO\IOInterface; +use Symfony\Component\Process\Process; /** * @author Per Bernhardt @@ -114,28 +115,27 @@ class HgDriver extends VcsDriver } /** - * {@inheritDoc} + * {@inheritdoc} */ - public function getComposerInformation($identifier) + public function getFileContent($file, $identifier) { - if (!isset($this->infoCache[$identifier])) { - $this->process->execute(sprintf('hg cat -r %s composer.json', ProcessExecutor::escape($identifier)), $composer, $this->repoDir); - - if (!trim($composer)) { - return; - } + $resource = sprintf('hg cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file)); + $this->process->execute(sprintf('hg cat -r %s', $resource), $content, $this->repoDir); - $composer = JsonFile::parseJson($composer, $identifier); - - if (empty($composer['time'])) { - $this->process->execute(sprintf('hg log --template "{date|rfc3339date}" -r %s', ProcessExecutor::escape($identifier)), $output, $this->repoDir); - $date = new \DateTime(trim($output), new \DateTimeZone('UTC')); - $composer['time'] = $date->format('Y-m-d H:i:s'); - } - $this->infoCache[$identifier] = $composer; + if (!trim($content)) { + return; } - return $this->infoCache[$identifier]; + return $content; + } + + /** + * {@inheritdoc} + */ + public function getChangeDate($identifier) + { + $this->process->execute(sprintf('hg log --template "{date|rfc3339date}" -r %s', ProcessExecutor::escape($identifier)), $output, $this->repoDir); + return new \DateTime(trim($output), new \DateTimeZone('UTC')); } /** diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 01d4a52d8..744b4264f 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -24,6 +24,7 @@ class PerforceDriver extends VcsDriver { protected $depot; protected $branch; + /** @var Perforce */ protected $perforce; protected $composerInfo; protected $composerInfoIdentifier; @@ -74,6 +75,21 @@ class PerforceDriver extends VcsDriver return $composer_info; } + /** + * {@inheritdoc} + */ + public function getFileContent($file, $identifier) + { + return $this->perforce->getFileContent($file, $identifier); + } + + /** + * {@inheritdoc} + */ + public function getChangeDate($identifier) { + return new \DateTime(); + } + /** * {@inheritDoc} */ diff --git a/src/Composer/Repository/Vcs/SvnDriver.php b/src/Composer/Repository/Vcs/SvnDriver.php index c602ddaa3..bffe23b46 100644 --- a/src/Composer/Repository/Vcs/SvnDriver.php +++ b/src/Composer/Repository/Vcs/SvnDriver.php @@ -166,6 +166,65 @@ class SvnDriver extends VcsDriver return $this->infoCache[$identifier]; } + /** + * @param string $file + * @param string $identifier + */ + public function getFileContent($file, $identifier) + { + $identifier = '/' . trim($identifier, '/') . '/'; + + if ($res = $this->cache->read($identifier . ':' . $file)) { + return $res; + } + + preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match); + if (!empty($match[2])) { + $path = $match[1]; + $rev = $match[2]; + } else { + $path = $identifier; + $rev = ''; + } + + try { + $resource = $path.$file; + $output = $this->execute('svn cat', $this->baseUrl . $resource . $rev); + if (!trim($output)) { + return null; + } + } catch (\RuntimeException $e) { + throw new TransportException($e->getMessage()); + } + + $this->cache->write($identifier . ':' . $file, $output); + + return $output; + } + + /** + * {@inheritdoc} + */ + public function getChangeDate($identifier) { + $identifier = '/' . trim($identifier, '/') . '/'; + + preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match); + if (!empty($match[2])) { + $path = $match[1]; + $rev = $match[2]; + } else { + $path = $identifier; + $rev = ''; + } + + $output = $this->execute('svn info', $this->baseUrl . $path . $rev); + foreach ($this->process->splitLines($output) as $line) { + if ($line && preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) { + return new \DateTime($match[1], new \DateTimeZone('UTC')); + } + } + } + /** * {@inheritDoc} */ diff --git a/src/Composer/Repository/Vcs/VcsDriver.php b/src/Composer/Repository/Vcs/VcsDriver.php index 56f06a580..37e9fc01f 100644 --- a/src/Composer/Repository/Vcs/VcsDriver.php +++ b/src/Composer/Repository/Vcs/VcsDriver.php @@ -16,6 +16,7 @@ use Composer\Downloader\TransportException; use Composer\Config; use Composer\Factory; use Composer\IO\IOInterface; +use Composer\Json\JsonFile; use Composer\Util\ProcessExecutor; use Composer\Util\RemoteFilesystem; use Composer\Util\Filesystem; @@ -41,6 +42,8 @@ abstract class VcsDriver implements VcsDriverInterface protected $process; /** @var RemoteFilesystem */ protected $remoteFilesystem; + /** @var array */ + protected $infoCache = array(); /** * Constructor. @@ -66,6 +69,31 @@ abstract class VcsDriver implements VcsDriverInterface $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config); } + /** + * {@inheritdoc} + */ + public function getComposerInformation($identifier) + { + if (!isset($this->infoCache[$identifier])) { + $composerFileContent = $this->getFileContent('composer.json', $identifier); + + if (!$composerFileContent) { + return null; + } + + $composer = JsonFile::parseJson($composerFileContent, $identifier . ':composer.json'); + + if (empty($composer['time'])) { + $composer['time'] = $this->getChangeDate($identifier)->format('Y-m-d H:i:s'); + } + + $this->infoCache[$identifier] = $composer; + } + + + return $this->infoCache[$identifier]; + } + /** * {@inheritDoc} */ diff --git a/src/Composer/Repository/Vcs/VcsDriverInterface.php b/src/Composer/Repository/Vcs/VcsDriverInterface.php index 307d63ef6..5f77b3161 100644 --- a/src/Composer/Repository/Vcs/VcsDriverInterface.php +++ b/src/Composer/Repository/Vcs/VcsDriverInterface.php @@ -33,6 +33,23 @@ interface VcsDriverInterface */ public function getComposerInformation($identifier); + /** + * Return the content of $file or null if the file does not exist. + * + * @param string $file + * @param string $identifier + * @return string + */ + public function getFileContent($file, $identifier); + + /** + * Get the changedate for $identifier. + * + * @param string $identifier + * @return \DateTime + */ + public function getChangeDate($identifier); + /** * Return the root identifier (trunk, master, default/tip ..) * diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 632238985..86fd472cd 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -407,6 +407,48 @@ class Perforce return $this->getComposerInformationFromLabel($identifier, $index); } + public function getFileContent($file, $identifier) { + $path = $this->getFilePath($file, $identifier); + + $command = $this->generateP4Command(' print ' . $path); + $this->executeCommand($command); + $result = $this->commandResult; + + if (!trim($result)) { + return null; + } + + return $result; + } + + public function getFilePath($file, $identifier) { + $index = strpos($identifier, '@'); + if ($index === false) { + $path = $identifier. '/' . $file; + + return $path; + } else { + $path = substr($identifier, 0, $index) . '/' . $file . substr($identifier, $index); + $command = $this->generateP4Command(' files ' . $path, false); + $this->executeCommand($command); + $result = $this->commandResult; + $index2 = strpos($result, 'no such file(s).'); + if ($index2 === false) { + $index3 = strpos($result, 'change'); + if (!($index3 === false)) { + $phrase = trim(substr($result, $index3)); + $fields = explode(' ', $phrase); + $id = $fields[1]; + $path = substr($identifier, 0, $index) . '/' . $file . '@' . $id; + + return $path; + } + } + } + + return null; + } + public function getComposerInformationFromPath($composerJson) { $command = $this->generateP4Command(' print ' . $composerJson); From 33d026bb06197865b9cb59b6fb594df9c22f013b Mon Sep 17 00:00:00 2001 From: Thomas Flori Date: Sat, 12 Nov 2016 09:33:05 +0100 Subject: [PATCH 2/5] fix code style to be PSR-2 conform I tried to solve all PSR-2 style guide violations in files that I changed. One I could not solve: const can not concatenate in php 5.3. --- .../Repository/Vcs/BitbucketDriver.php | 55 +++++++++++++----- .../Repository/Vcs/GitBitbucketDriver.php | 48 ++++------------ src/Composer/Repository/Vcs/GitDriver.php | 32 ++++++++--- src/Composer/Repository/Vcs/GitLabDriver.php | 56 +++++++++++++++---- .../Repository/Vcs/HgBitbucketDriver.php | 23 ++++++-- src/Composer/Repository/Vcs/HgDriver.php | 38 +++++++++++-- .../Repository/Vcs/PerforceDriver.php | 3 +- src/Composer/Repository/Vcs/SvnDriver.php | 13 ++++- src/Composer/Repository/Vcs/VcsDriver.php | 9 ++- src/Composer/Util/Perforce.php | 10 +++- 10 files changed, 198 insertions(+), 89 deletions(-) diff --git a/src/Composer/Repository/Vcs/BitbucketDriver.php b/src/Composer/Repository/Vcs/BitbucketDriver.php index 4e3a55f26..5afd767cd 100644 --- a/src/Composer/Repository/Vcs/BitbucketDriver.php +++ b/src/Composer/Repository/Vcs/BitbucketDriver.php @@ -1,9 +1,7 @@ owner = $match[1]; $this->repository = $match[2]; $this->originUrl = 'bitbucket.org'; - $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository); + $this->cache = new Cache( + $this->io, + implode('/', array( + $this->config->get('cache-repo-dir'), + $this->originUrl, + $this->owner, + $this->repository + )) + ); } /** @@ -48,12 +54,17 @@ abstract class BitbucketDriver extends VcsDriver } if (!isset($this->infoCache[$identifier])) { - $composer = parent::getComposerInformation($identifier); // specials for bitbucket if (!isset($composer['support']['source'])) { - $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier; + $label = array_search( + $identifier, + $this->getTags() + ) ?: array_search( + $identifier, + $this->getBranches() + ) ?: $identifier; if (array_key_exists($label, $tags = $this->getTags())) { $hash = $tags[$label]; @@ -62,7 +73,12 @@ abstract class BitbucketDriver extends VcsDriver } if (! isset($hash)) { - $composer['support']['source'] = sprintf('https://%s/%s/%s/src', $this->originUrl, $this->owner, $this->repository); + $composer['support']['source'] = sprintf( + 'https://%s/%s/%s/src', + $this->originUrl, + $this->owner, + $this->repository + ); } else { $composer['support']['source'] = sprintf( 'https://%s/%s/%s/src/%s/?at=%s', @@ -75,7 +91,12 @@ abstract class BitbucketDriver extends VcsDriver } } if (!isset($composer['support']['issues']) && $this->hasIssues) { - $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository); + $composer['support']['issues'] = sprintf( + 'https://%s/%s/%s/issues', + $this->originUrl, + $this->owner, + $this->repository + ); } $this->infoCache[$identifier] = $composer; @@ -87,7 +108,8 @@ abstract class BitbucketDriver extends VcsDriver /** * {@inheritdoc} */ - public function getFileContent($file, $identifier) { + public function getFileContent($file, $identifier) + { if ($this->sshDriver) { return $this->sshDriver->getFileContent($file, $identifier); } @@ -96,7 +118,8 @@ abstract class BitbucketDriver extends VcsDriver return $res; } - $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/src/'.$identifier.'/' . $file; + $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/' + . $this->owner . '/' . $this->repository . '/src/' . $identifier . '/' . $file; $fileData = JsonFile::parseJson($this->getContents($resource), $resource); if (!is_array($fileData) || ! array_key_exists('data', $fileData)) { return null; @@ -112,12 +135,14 @@ abstract class BitbucketDriver extends VcsDriver /** * {@inheritdoc} */ - public function getChangeDate($identifier) { + public function getChangeDate($identifier) + { if ($this->sshDriver) { return $this->sshDriver->getChangeDate($identifier); } - $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/changesets/'.$identifier; + $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/' + . $this->owner . '/' . $this->repository . '/changesets/' . $identifier; $changeset = JsonFile::parseJson($this->getContents($resource), $resource); return new \DateTime($changeset['timestamp']); @@ -140,7 +165,8 @@ abstract class BitbucketDriver extends VcsDriver switch ($e->getCode()) { case 403: - if (!$this->io->hasAuthentication($this->originUrl) && $bitbucketUtil->authorizeOAuth($this->originUrl)) { + if (!$this->io->hasAuthentication($this->originUrl) + && $bitbucketUtil->authorizeOAuth($this->originUrl)) { return parent::getContents($url); } @@ -175,7 +201,10 @@ abstract class BitbucketDriver extends VcsDriver } catch (\RuntimeException $e) { $this->sshDriver = null; - $this->io->writeError('Failed to clone the '.$this->generateSshUrl().' repository, try running in interactive mode so that you can enter your Bitbucket OAuth consumer credentials'); + $this->io->writeError( + 'Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode' + . ' so that you can enter your Bitbucket OAuth consumer credentials' + ); throw $e; } } diff --git a/src/Composer/Repository/Vcs/GitBitbucketDriver.php b/src/Composer/Repository/Vcs/GitBitbucketDriver.php index 03a9fddaf..a965d150b 100644 --- a/src/Composer/Repository/Vcs/GitBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/GitBitbucketDriver.php @@ -37,7 +37,8 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface } if (null === $this->rootIdentifier) { - $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository; + $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/' + . $this->owner . '/' . $this->repository; $repoData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource, true), $resource); $this->hasIssues = !empty($repoData['has_issues']); $this->rootIdentifier = !empty($repoData['main_branch']) ? $repoData['main_branch'] : 'master'; @@ -91,7 +92,8 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface } if (null === $this->tags) { - $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags'; + $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/' + . $this->owner . '/' . $this->repository . '/tags'; $tagsData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource); $this->tags = array(); foreach ($tagsData as $tag => $data) { @@ -112,7 +114,8 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface } if (null === $this->branches) { - $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/branches'; + $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/' + . $this->owner . '/' . $this->repository . '/branches'; $branchData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource); $this->branches = array(); foreach ($branchData as $branch => $data) { @@ -133,7 +136,11 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface } if (!extension_loaded('openssl')) { - $io->writeError('Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE); + $io->writeError( + 'Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.', + true, + IOInterface::VERBOSE + ); return false; } @@ -155,37 +162,4 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface ); $this->sshDriver->initialize(); } - - /** - * Get the remote content. - * - * @param string $url The URL of content - * @param bool $fetchingRepoData - * - * @return mixed The result - */ - protected function getContentsWithOAuthCredentials($url, $fetchingRepoData = false) - { - try { - return parent::getContents($url); - } catch (TransportException $e) { - $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process, $this->remoteFilesystem); - - switch ($e->getCode()) { - case 403: - if (!$this->io->hasAuthentication($this->originUrl) && $bitbucketUtil->authorizeOAuth($this->originUrl)) { - return parent::getContents($url); - } - - if (!$this->io->isInteractive() && $fetchingRepoData) { - return $this->attemptCloneFallback(); - } - - throw $e; - - default: - throw $e; - } - } - } } diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index 685088c4b..fdd069aef 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -42,7 +42,8 @@ class GitDriver extends VcsDriver $this->repoDir = $this->url; $cacheUrl = realpath($this->url); } else { - $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/'; + $this->repoDir = $this->config->get('cache-vcs-dir') . '/' + . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/'; GitUtil::cleanEnv(); @@ -50,16 +51,26 @@ class GitDriver extends VcsDriver $fs->ensureDirectoryExists(dirname($this->repoDir)); if (!is_writable(dirname($this->repoDir))) { - throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.dirname($this->repoDir).'" directory is not writable by the current user.'); + throw new \RuntimeException( + 'Can not clone ' . $this->url . ' to access package information. The "' . dirname($this->repoDir) + . '" directory is not writable by the current user.' + ); } if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) { - throw new \InvalidArgumentException('The source URL '.$this->url.' is invalid, ssh URLs should have a port number after ":".'."\n".'Use ssh://git@example.com:22/path or just git@example.com:path if you do not want to provide a password or custom port.'); + throw new \InvalidArgumentException( + 'The source URL ' . $this->url . ' is invalid, ssh URLs should have a port number after ":".' + . "\n" . 'Use ssh://git@example.com:22/path or just git@example.com:path if you do not want' + . ' to provide a password or custom port.' + ); } $gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs); if (!$gitUtil->syncMirror($this->url, $this->repoDir)) { - $this->io->writeError('Failed to update '.$this->url.', package information from this repository may be outdated'); + $this->io->writeError( + 'Failed to update ' . $this->url . ', package information from this repository' + . ' may be outdated' + ); } $cacheUrl = $this->url; @@ -68,7 +79,10 @@ class GitDriver extends VcsDriver $this->getTags(); $this->getBranches(); - $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $cacheUrl)); + $this->cache = new Cache( + $this->io, + $this->config->get('cache-repo-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $cacheUrl) + ); } /** @@ -145,8 +159,12 @@ class GitDriver extends VcsDriver /** * {@inheritdoc} */ - public function getChangeDate($identifier) { - $this->process->execute(sprintf('git log -1 --format=%%at %s', ProcessExecutor::escape($identifier)), $output, $this->repoDir); + public function getChangeDate($identifier) + { + $this->process->execute(sprintf( + 'git log -1 --format=%%at %s', + ProcessExecutor::escape($identifier) + ), $output, $this->repoDir); return new \DateTime('@'.trim($output), new \DateTimeZone('UTC')); } diff --git a/src/Composer/Repository/Vcs/GitLabDriver.php b/src/Composer/Repository/Vcs/GitLabDriver.php index 2ad00003a..775360cf9 100644 --- a/src/Composer/Repository/Vcs/GitLabDriver.php +++ b/src/Composer/Repository/Vcs/GitLabDriver.php @@ -73,15 +73,30 @@ class GitLabDriver extends VcsDriver public function initialize() { if (!preg_match(self::URL_REGEX, $this->url, $match)) { - throw new \InvalidArgumentException('The URL provided is invalid. It must be the HTTP URL of a GitLab project.'); + throw new \InvalidArgumentException( + 'The URL provided is invalid. It must be the HTTP URL of a GitLab project.' + ); } - $this->scheme = !empty($match['scheme']) ? $match['scheme'] : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? 'http' : 'https'); + $this->scheme = !empty($match['scheme']) ? + $match['scheme'] : + (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? + 'http' : + 'https' + ); $this->originUrl = !empty($match['domain']) ? $match['domain'] : $match['domain2']; $this->owner = $match['owner']; $this->repository = preg_replace('#(\.git)$#', '', $match['repo']); - $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository); + $this->cache = new Cache( + $this->io, + implode('/', array( + $this->config->get('cache-repo-dir'), + $this->originUrl, + $this->owner, + $this->repository + )) + ); $this->fetchProject(); } @@ -275,7 +290,8 @@ class GitLabDriver extends VcsDriver */ public function getApiUrl() { - return $this->scheme.'://'.$this->originUrl.'/api/v3/projects/'.$this->urlEncodeAll($this->owner).'%2F'.$this->urlEncodeAll($this->repository); + return $this->scheme . '://' . $this->originUrl . '/api/v3/projects/' + . $this->urlEncodeAll($this->owner) . '%2F' . $this->urlEncodeAll($this->repository); } /** @@ -289,7 +305,9 @@ class GitLabDriver extends VcsDriver $encoded = ''; for ($i = 0; isset($string[$i]); $i++) { $character = $string[$i]; - if (!ctype_alnum($character)) $character = '%' . sprintf('%02X', ord($character)); + if (!ctype_alnum($character)) { + $character = '%' . sprintf('%02X', ord($character)); + } $encoded .= $character; } return $encoded; @@ -338,7 +356,10 @@ class GitLabDriver extends VcsDriver } catch (\RuntimeException $e) { $this->gitDriver = null; - $this->io->writeError('Failed to clone the '.$this->generateSshUrl().' repository, try running in interactive mode so that you can enter your credentials'); + $this->io->writeError( + 'Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode' + . ' so that you can enter your credentials' + ); throw $e; } } @@ -378,7 +399,7 @@ class GitLabDriver extends VcsDriver switch ($e->getCode()) { case 401: case 404: - // try to authorize only if we are fetching the main /repos/foo/bar data, otherwise it must be a real 404 + // try to authorize only if we are fetching the main /repos/foo/bar data, otherwise it must be a 404 if (!$fetchingRepoData) { throw $e; } @@ -390,13 +411,22 @@ class GitLabDriver extends VcsDriver if (!$this->io->isInteractive()) { return $this->attemptCloneFallback(); } - $this->io->writeError('Failed to download ' . $this->owner . '/' . $this->repository . ':' . $e->getMessage() . ''); - $gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, 'Your credentials are required to fetch private repository metadata ('.$this->url.')'); + $this->io->writeError( + 'Failed to download ' . $this->owner . '/' . $this->repository + . ':' . $e->getMessage() . '' + ); + $gitLabUtil->authorizeOAuthInteractively( + $this->scheme, + $this->originUrl, + 'Your credentials are required to fetch private repository metadata (' + . $this->url . ')' + ); return parent::getContents($url); case 403: - if (!$this->io->hasAuthentication($this->originUrl) && $gitLabUtil->authorizeOAuth($this->originUrl)) { + if (!$this->io->hasAuthentication($this->originUrl) && + $gitLabUtil->authorizeOAuth($this->originUrl)) { return parent::getContents($url); } @@ -432,7 +462,11 @@ class GitLabDriver extends VcsDriver } if ('https' === $scheme && !extension_loaded('openssl')) { - $io->writeError('Skipping GitLab driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE); + $io->writeError( + 'Skipping GitLab driver for ' . $url . ' because the OpenSSL PHP extension is missing.', + true, + IOInterface::VERBOSE + ); return false; } diff --git a/src/Composer/Repository/Vcs/HgBitbucketDriver.php b/src/Composer/Repository/Vcs/HgBitbucketDriver.php index d2d7cc1be..dc8d32517 100644 --- a/src/Composer/Repository/Vcs/HgBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/HgBitbucketDriver.php @@ -29,10 +29,14 @@ class HgBitbucketDriver extends BitbucketDriver public function getRootIdentifier() { if (null === $this->rootIdentifier) { - $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags'; + $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/' + . $this->owner . '/' . $this->repository . '/tags'; $repoData = JsonFile::parseJson($this->getContents($resource), $resource); if (array() === $repoData || !isset($repoData['tip'])) { - throw new \RuntimeException($this->url.' does not appear to be a mercurial repository, use '.$this->url.'.git if this is a git bitbucket repository'); + throw new \RuntimeException( + $this->url . ' does not appear to be a mercurial repository, use ' + . $this->url . '.git if this is a git bitbucket repository' + ); } $this->hasIssues = !empty($repoData['has_issues']); $this->rootIdentifier = $repoData['tip']['raw_node']; @@ -73,7 +77,8 @@ class HgBitbucketDriver extends BitbucketDriver public function getTags() { if (null === $this->tags) { - $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags'; + $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/' + . $this->owner . '/' . $this->repository . '/tags'; $tagsData = JsonFile::parseJson($this->getContents($resource), $resource); $this->tags = array(); foreach ($tagsData as $tag => $data) { @@ -91,7 +96,8 @@ class HgBitbucketDriver extends BitbucketDriver public function getBranches() { if (null === $this->branches) { - $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/'.$this->owner.'/'.$this->repository.'/branches'; + $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/' + . $this->owner . '/' . $this->repository . '/branches'; $branchData = JsonFile::parseJson($this->getContents($resource), $resource); $this->branches = array(); foreach ($branchData as $branch => $data) { @@ -112,7 +118,11 @@ class HgBitbucketDriver extends BitbucketDriver } if (!extension_loaded('openssl')) { - $io->writeError('Skipping Bitbucket hg driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE); + $io->writeError( + 'Skipping Bitbucket hg driver for ' . $url . ' because the OpenSSL PHP extension is missing.', + true, + IOInterface::VERBOSE + ); return false; } @@ -120,7 +130,8 @@ class HgBitbucketDriver extends BitbucketDriver return true; } - protected function setupSshDriver($url) { + protected function setupSshDriver($url) + { $this->sshDriver = new HgDriver( array('url' => $url), $this->io, diff --git a/src/Composer/Repository/Vcs/HgDriver.php b/src/Composer/Repository/Vcs/HgDriver.php index 451cec7ff..e347269b0 100644 --- a/src/Composer/Repository/Vcs/HgDriver.php +++ b/src/Composer/Repository/Vcs/HgDriver.php @@ -45,7 +45,10 @@ class HgDriver extends VcsDriver $fs->ensureDirectoryExists($cacheDir); if (!is_writable(dirname($this->repoDir))) { - throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$cacheDir.'" directory is not writable by the current user.'); + throw new \RuntimeException( + 'Can not clone ' . $this->url . ' to access package information. The "' . $cacheDir + . '" directory is not writable by the current user.' + ); } // Ensure we are allowed to use this URL by config @@ -54,20 +57,36 @@ class HgDriver extends VcsDriver // update the repo if it is a valid hg repository if (is_dir($this->repoDir) && 0 === $this->process->execute('hg summary', $output, $this->repoDir)) { if (0 !== $this->process->execute('hg pull', $output, $this->repoDir)) { - $this->io->writeError('Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')'); + $this->io->writeError( + 'Failed to update ' . $this->url . ', package information from this repository may be' + . ' outdated ('.$this->process->getErrorOutput().')' + ); } } else { // clean up directory and do a fresh clone into it $fs->removeDirectory($this->repoDir); - if (0 !== $this->process->execute(sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoDir)), $output, $cacheDir)) { + if (0 !== $this->process->execute( + sprintf( + 'hg clone --noupdate %s %s', + ProcessExecutor::escape($this->url), + ProcessExecutor::escape($this->repoDir) + ), + $output, + $cacheDir + )) { $output = $this->process->getErrorOutput(); if (0 !== $this->process->execute('hg --version', $ignoredOutput)) { - throw new \RuntimeException('Failed to clone '.$this->url.', hg was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput()); + throw new \RuntimeException( + 'Failed to clone ' . $this->url . ', hg was not found, check that it is installed and in' + . ' your PATH env.' . "\n\n" . $this->process->getErrorOutput() + ); } - throw new \RuntimeException('Failed to clone '.$this->url.', could not read packages from it' . "\n\n" .$output); + throw new \RuntimeException( + 'Failed to clone ' . $this->url . ', could not read packages from it' . "\n\n" .$output + ); } } } @@ -134,7 +153,14 @@ class HgDriver extends VcsDriver */ public function getChangeDate($identifier) { - $this->process->execute(sprintf('hg log --template "{date|rfc3339date}" -r %s', ProcessExecutor::escape($identifier)), $output, $this->repoDir); + $this->process->execute( + sprintf( + 'hg log --template "{date|rfc3339date}" -r %s', + ProcessExecutor::escape($identifier) + ), + $output, + $this->repoDir + ); return new \DateTime(trim($output), new \DateTimeZone('UTC')); } diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 744b4264f..2a011106e 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -86,7 +86,8 @@ class PerforceDriver extends VcsDriver /** * {@inheritdoc} */ - public function getChangeDate($identifier) { + public function getChangeDate($identifier) + { return new \DateTime(); } diff --git a/src/Composer/Repository/Vcs/SvnDriver.php b/src/Composer/Repository/Vcs/SvnDriver.php index bffe23b46..5139d02a7 100644 --- a/src/Composer/Repository/Vcs/SvnDriver.php +++ b/src/Composer/Repository/Vcs/SvnDriver.php @@ -77,7 +77,10 @@ class SvnDriver extends VcsDriver $this->baseUrl = substr($this->url, 0, $pos); } - $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl)); + $this->cache = new Cache( + $this->io, + $this->config->get('cache-repo-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl) + ); $this->getBranches(); $this->getTags(); @@ -205,7 +208,8 @@ class SvnDriver extends VcsDriver /** * {@inheritdoc} */ - public function getChangeDate($identifier) { + public function getChangeDate($identifier) + { $identifier = '/' . trim($identifier, '/') . '/'; preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match); @@ -380,7 +384,10 @@ class SvnDriver extends VcsDriver return $this->util->execute($command, $url); } catch (\RuntimeException $e) { if (0 !== $this->process->execute('svn --version', $ignoredOutput)) { - throw new \RuntimeException('Failed to load '.$this->url.', svn was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput()); + throw new \RuntimeException( + 'Failed to load ' . $this->url . ', svn was not found, check that it is installed and in your' + . ' PATH env.' . "\n\n" . $this->process->getErrorOutput() + ); } throw new \RuntimeException( diff --git a/src/Composer/Repository/Vcs/VcsDriver.php b/src/Composer/Repository/Vcs/VcsDriver.php index 37e9fc01f..321afbef5 100644 --- a/src/Composer/Repository/Vcs/VcsDriver.php +++ b/src/Composer/Repository/Vcs/VcsDriver.php @@ -54,8 +54,13 @@ abstract class VcsDriver implements VcsDriverInterface * @param ProcessExecutor $process Process instance, injectable for mocking * @param RemoteFilesystem $remoteFilesystem Remote Filesystem, injectable for mocking */ - final public function __construct(array $repoConfig, IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null) - { + final public function __construct( + array $repoConfig, + IOInterface $io, + Config $config, + ProcessExecutor $process = null, + RemoteFilesystem $remoteFilesystem = null + ) { if (Filesystem::isLocalPath($repoConfig['url'])) { $repoConfig['url'] = Filesystem::getPlatformPath($repoConfig['url']); } diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 86fd472cd..533af98cc 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -304,7 +304,9 @@ class Perforce public function connectClient() { - $p4CreateClientCommand = $this->generateP4Command('client -i < ' . str_replace(" ", "\\ ", $this->getP4ClientSpec())); + $p4CreateClientCommand = $this->generateP4Command( + 'client -i < ' . str_replace(" ", "\\ ", $this->getP4ClientSpec()) + ); $this->executeCommand($p4CreateClientCommand); } @@ -407,7 +409,8 @@ class Perforce return $this->getComposerInformationFromLabel($identifier, $index); } - public function getFileContent($file, $identifier) { + public function getFileContent($file, $identifier) + { $path = $this->getFilePath($file, $identifier); $command = $this->generateP4Command(' print ' . $path); @@ -421,7 +424,8 @@ class Perforce return $result; } - public function getFilePath($file, $identifier) { + public function getFilePath($file, $identifier) + { $index = strpos($identifier, '@'); if ($index === false) { $path = $identifier. '/' . $file; From d70dfd2df303e6112f2adcdaefd6fb1e9daa6d0b Mon Sep 17 00:00:00 2001 From: Thomas Flori Date: Sat, 12 Nov 2016 10:48:19 +0100 Subject: [PATCH 3/5] revert style changes --- .../Repository/Vcs/GitBitbucketDriver.php | 15 ++--- src/Composer/Repository/Vcs/GitDriver.php | 24 ++------ src/Composer/Repository/Vcs/GitLabDriver.php | 56 ++++--------------- .../Repository/Vcs/HgBitbucketDriver.php | 20 ++----- src/Composer/Repository/Vcs/HgDriver.php | 29 ++-------- src/Composer/Repository/Vcs/SvnDriver.php | 10 +--- src/Composer/Repository/Vcs/VcsDriver.php | 9 +-- 7 files changed, 34 insertions(+), 129 deletions(-) diff --git a/src/Composer/Repository/Vcs/GitBitbucketDriver.php b/src/Composer/Repository/Vcs/GitBitbucketDriver.php index a965d150b..9c07fff40 100644 --- a/src/Composer/Repository/Vcs/GitBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/GitBitbucketDriver.php @@ -37,8 +37,7 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface } if (null === $this->rootIdentifier) { - $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/' - . $this->owner . '/' . $this->repository; + $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository; $repoData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource, true), $resource); $this->hasIssues = !empty($repoData['has_issues']); $this->rootIdentifier = !empty($repoData['main_branch']) ? $repoData['main_branch'] : 'master'; @@ -92,8 +91,7 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface } if (null === $this->tags) { - $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/' - . $this->owner . '/' . $this->repository . '/tags'; + $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags'; $tagsData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource); $this->tags = array(); foreach ($tagsData as $tag => $data) { @@ -114,8 +112,7 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface } if (null === $this->branches) { - $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/' - . $this->owner . '/' . $this->repository . '/branches'; + $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/branches'; $branchData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource); $this->branches = array(); foreach ($branchData as $branch => $data) { @@ -136,11 +133,7 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface } if (!extension_loaded('openssl')) { - $io->writeError( - 'Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.', - true, - IOInterface::VERBOSE - ); + $io->writeError('Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE); return false; } diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index fdd069aef..a93447c73 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -42,8 +42,7 @@ class GitDriver extends VcsDriver $this->repoDir = $this->url; $cacheUrl = realpath($this->url); } else { - $this->repoDir = $this->config->get('cache-vcs-dir') . '/' - . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/'; + $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/'; GitUtil::cleanEnv(); @@ -51,26 +50,16 @@ class GitDriver extends VcsDriver $fs->ensureDirectoryExists(dirname($this->repoDir)); if (!is_writable(dirname($this->repoDir))) { - throw new \RuntimeException( - 'Can not clone ' . $this->url . ' to access package information. The "' . dirname($this->repoDir) - . '" directory is not writable by the current user.' - ); + throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.dirname($this->repoDir).'" directory is not writable by the current user.'); } if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) { - throw new \InvalidArgumentException( - 'The source URL ' . $this->url . ' is invalid, ssh URLs should have a port number after ":".' - . "\n" . 'Use ssh://git@example.com:22/path or just git@example.com:path if you do not want' - . ' to provide a password or custom port.' - ); + throw new \InvalidArgumentException('The source URL '.$this->url.' is invalid, ssh URLs should have a port number after ":".'."\n".'Use ssh://git@example.com:22/path or just git@example.com:path if you do not want to provide a password or custom port.'); } $gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs); if (!$gitUtil->syncMirror($this->url, $this->repoDir)) { - $this->io->writeError( - 'Failed to update ' . $this->url . ', package information from this repository' - . ' may be outdated' - ); + $this->io->writeError('Failed to update '.$this->url.', package information from this repository may be outdated'); } $cacheUrl = $this->url; @@ -79,10 +68,7 @@ class GitDriver extends VcsDriver $this->getTags(); $this->getBranches(); - $this->cache = new Cache( - $this->io, - $this->config->get('cache-repo-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $cacheUrl) - ); + $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $cacheUrl)); } /** diff --git a/src/Composer/Repository/Vcs/GitLabDriver.php b/src/Composer/Repository/Vcs/GitLabDriver.php index 775360cf9..2ad00003a 100644 --- a/src/Composer/Repository/Vcs/GitLabDriver.php +++ b/src/Composer/Repository/Vcs/GitLabDriver.php @@ -73,30 +73,15 @@ class GitLabDriver extends VcsDriver public function initialize() { if (!preg_match(self::URL_REGEX, $this->url, $match)) { - throw new \InvalidArgumentException( - 'The URL provided is invalid. It must be the HTTP URL of a GitLab project.' - ); + throw new \InvalidArgumentException('The URL provided is invalid. It must be the HTTP URL of a GitLab project.'); } - $this->scheme = !empty($match['scheme']) ? - $match['scheme'] : - (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? - 'http' : - 'https' - ); + $this->scheme = !empty($match['scheme']) ? $match['scheme'] : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? 'http' : 'https'); $this->originUrl = !empty($match['domain']) ? $match['domain'] : $match['domain2']; $this->owner = $match['owner']; $this->repository = preg_replace('#(\.git)$#', '', $match['repo']); - $this->cache = new Cache( - $this->io, - implode('/', array( - $this->config->get('cache-repo-dir'), - $this->originUrl, - $this->owner, - $this->repository - )) - ); + $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository); $this->fetchProject(); } @@ -290,8 +275,7 @@ class GitLabDriver extends VcsDriver */ public function getApiUrl() { - return $this->scheme . '://' . $this->originUrl . '/api/v3/projects/' - . $this->urlEncodeAll($this->owner) . '%2F' . $this->urlEncodeAll($this->repository); + return $this->scheme.'://'.$this->originUrl.'/api/v3/projects/'.$this->urlEncodeAll($this->owner).'%2F'.$this->urlEncodeAll($this->repository); } /** @@ -305,9 +289,7 @@ class GitLabDriver extends VcsDriver $encoded = ''; for ($i = 0; isset($string[$i]); $i++) { $character = $string[$i]; - if (!ctype_alnum($character)) { - $character = '%' . sprintf('%02X', ord($character)); - } + if (!ctype_alnum($character)) $character = '%' . sprintf('%02X', ord($character)); $encoded .= $character; } return $encoded; @@ -356,10 +338,7 @@ class GitLabDriver extends VcsDriver } catch (\RuntimeException $e) { $this->gitDriver = null; - $this->io->writeError( - 'Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode' - . ' so that you can enter your credentials' - ); + $this->io->writeError('Failed to clone the '.$this->generateSshUrl().' repository, try running in interactive mode so that you can enter your credentials'); throw $e; } } @@ -399,7 +378,7 @@ class GitLabDriver extends VcsDriver switch ($e->getCode()) { case 401: case 404: - // try to authorize only if we are fetching the main /repos/foo/bar data, otherwise it must be a 404 + // try to authorize only if we are fetching the main /repos/foo/bar data, otherwise it must be a real 404 if (!$fetchingRepoData) { throw $e; } @@ -411,22 +390,13 @@ class GitLabDriver extends VcsDriver if (!$this->io->isInteractive()) { return $this->attemptCloneFallback(); } - $this->io->writeError( - 'Failed to download ' . $this->owner . '/' . $this->repository - . ':' . $e->getMessage() . '' - ); - $gitLabUtil->authorizeOAuthInteractively( - $this->scheme, - $this->originUrl, - 'Your credentials are required to fetch private repository metadata (' - . $this->url . ')' - ); + $this->io->writeError('Failed to download ' . $this->owner . '/' . $this->repository . ':' . $e->getMessage() . ''); + $gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, 'Your credentials are required to fetch private repository metadata ('.$this->url.')'); return parent::getContents($url); case 403: - if (!$this->io->hasAuthentication($this->originUrl) && - $gitLabUtil->authorizeOAuth($this->originUrl)) { + if (!$this->io->hasAuthentication($this->originUrl) && $gitLabUtil->authorizeOAuth($this->originUrl)) { return parent::getContents($url); } @@ -462,11 +432,7 @@ class GitLabDriver extends VcsDriver } if ('https' === $scheme && !extension_loaded('openssl')) { - $io->writeError( - 'Skipping GitLab driver for ' . $url . ' because the OpenSSL PHP extension is missing.', - true, - IOInterface::VERBOSE - ); + $io->writeError('Skipping GitLab driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE); return false; } diff --git a/src/Composer/Repository/Vcs/HgBitbucketDriver.php b/src/Composer/Repository/Vcs/HgBitbucketDriver.php index dc8d32517..6edc1364e 100644 --- a/src/Composer/Repository/Vcs/HgBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/HgBitbucketDriver.php @@ -29,14 +29,10 @@ class HgBitbucketDriver extends BitbucketDriver public function getRootIdentifier() { if (null === $this->rootIdentifier) { - $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/' - . $this->owner . '/' . $this->repository . '/tags'; + $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags'; $repoData = JsonFile::parseJson($this->getContents($resource), $resource); if (array() === $repoData || !isset($repoData['tip'])) { - throw new \RuntimeException( - $this->url . ' does not appear to be a mercurial repository, use ' - . $this->url . '.git if this is a git bitbucket repository' - ); + throw new \RuntimeException($this->url.' does not appear to be a mercurial repository, use '.$this->url.'.git if this is a git bitbucket repository'); } $this->hasIssues = !empty($repoData['has_issues']); $this->rootIdentifier = $repoData['tip']['raw_node']; @@ -77,8 +73,7 @@ class HgBitbucketDriver extends BitbucketDriver public function getTags() { if (null === $this->tags) { - $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/' - . $this->owner . '/' . $this->repository . '/tags'; + $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags'; $tagsData = JsonFile::parseJson($this->getContents($resource), $resource); $this->tags = array(); foreach ($tagsData as $tag => $data) { @@ -96,8 +91,7 @@ class HgBitbucketDriver extends BitbucketDriver public function getBranches() { if (null === $this->branches) { - $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/' - . $this->owner . '/' . $this->repository . '/branches'; + $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/'.$this->owner.'/'.$this->repository.'/branches'; $branchData = JsonFile::parseJson($this->getContents($resource), $resource); $this->branches = array(); foreach ($branchData as $branch => $data) { @@ -118,11 +112,7 @@ class HgBitbucketDriver extends BitbucketDriver } if (!extension_loaded('openssl')) { - $io->writeError( - 'Skipping Bitbucket hg driver for ' . $url . ' because the OpenSSL PHP extension is missing.', - true, - IOInterface::VERBOSE - ); + $io->writeError('Skipping Bitbucket hg driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE); return false; } diff --git a/src/Composer/Repository/Vcs/HgDriver.php b/src/Composer/Repository/Vcs/HgDriver.php index e347269b0..bad52bed3 100644 --- a/src/Composer/Repository/Vcs/HgDriver.php +++ b/src/Composer/Repository/Vcs/HgDriver.php @@ -45,10 +45,7 @@ class HgDriver extends VcsDriver $fs->ensureDirectoryExists($cacheDir); if (!is_writable(dirname($this->repoDir))) { - throw new \RuntimeException( - 'Can not clone ' . $this->url . ' to access package information. The "' . $cacheDir - . '" directory is not writable by the current user.' - ); + throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$cacheDir.'" directory is not writable by the current user.'); } // Ensure we are allowed to use this URL by config @@ -57,36 +54,20 @@ class HgDriver extends VcsDriver // update the repo if it is a valid hg repository if (is_dir($this->repoDir) && 0 === $this->process->execute('hg summary', $output, $this->repoDir)) { if (0 !== $this->process->execute('hg pull', $output, $this->repoDir)) { - $this->io->writeError( - 'Failed to update ' . $this->url . ', package information from this repository may be' - . ' outdated ('.$this->process->getErrorOutput().')' - ); + $this->io->writeError('Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')'); } } else { // clean up directory and do a fresh clone into it $fs->removeDirectory($this->repoDir); - if (0 !== $this->process->execute( - sprintf( - 'hg clone --noupdate %s %s', - ProcessExecutor::escape($this->url), - ProcessExecutor::escape($this->repoDir) - ), - $output, - $cacheDir - )) { + if (0 !== $this->process->execute(sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoDir)), $output, $cacheDir)) { $output = $this->process->getErrorOutput(); if (0 !== $this->process->execute('hg --version', $ignoredOutput)) { - throw new \RuntimeException( - 'Failed to clone ' . $this->url . ', hg was not found, check that it is installed and in' - . ' your PATH env.' . "\n\n" . $this->process->getErrorOutput() - ); + throw new \RuntimeException('Failed to clone '.$this->url.', hg was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput()); } - throw new \RuntimeException( - 'Failed to clone ' . $this->url . ', could not read packages from it' . "\n\n" .$output - ); + throw new \RuntimeException('Failed to clone '.$this->url.', could not read packages from it' . "\n\n" .$output); } } } diff --git a/src/Composer/Repository/Vcs/SvnDriver.php b/src/Composer/Repository/Vcs/SvnDriver.php index 5139d02a7..1d3df7909 100644 --- a/src/Composer/Repository/Vcs/SvnDriver.php +++ b/src/Composer/Repository/Vcs/SvnDriver.php @@ -77,10 +77,7 @@ class SvnDriver extends VcsDriver $this->baseUrl = substr($this->url, 0, $pos); } - $this->cache = new Cache( - $this->io, - $this->config->get('cache-repo-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl) - ); + $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl)); $this->getBranches(); $this->getTags(); @@ -384,10 +381,7 @@ class SvnDriver extends VcsDriver return $this->util->execute($command, $url); } catch (\RuntimeException $e) { if (0 !== $this->process->execute('svn --version', $ignoredOutput)) { - throw new \RuntimeException( - 'Failed to load ' . $this->url . ', svn was not found, check that it is installed and in your' - . ' PATH env.' . "\n\n" . $this->process->getErrorOutput() - ); + throw new \RuntimeException('Failed to load '.$this->url.', svn was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput()); } throw new \RuntimeException( diff --git a/src/Composer/Repository/Vcs/VcsDriver.php b/src/Composer/Repository/Vcs/VcsDriver.php index 321afbef5..37e9fc01f 100644 --- a/src/Composer/Repository/Vcs/VcsDriver.php +++ b/src/Composer/Repository/Vcs/VcsDriver.php @@ -54,13 +54,8 @@ abstract class VcsDriver implements VcsDriverInterface * @param ProcessExecutor $process Process instance, injectable for mocking * @param RemoteFilesystem $remoteFilesystem Remote Filesystem, injectable for mocking */ - final public function __construct( - array $repoConfig, - IOInterface $io, - Config $config, - ProcessExecutor $process = null, - RemoteFilesystem $remoteFilesystem = null - ) { + final public function __construct(array $repoConfig, IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null) + { if (Filesystem::isLocalPath($repoConfig['url'])) { $repoConfig['url'] = Filesystem::getPlatformPath($repoConfig['url']); } From ec277773412545bd1f2732a3cea947e500c22c1c Mon Sep 17 00:00:00 2001 From: Thomas Flori Date: Sat, 12 Nov 2016 11:10:13 +0100 Subject: [PATCH 4/5] code improvements as suggested Thanks for your input! --- .../Repository/Vcs/BitbucketDriver.php | 56 ++++++++----------- .../Repository/Vcs/GitBitbucketDriver.php | 34 ++++++----- src/Composer/Repository/Vcs/GitLabDriver.php | 4 +- .../Repository/Vcs/HgBitbucketDriver.php | 14 ++++- .../Repository/Vcs/PerforceDriver.php | 2 +- src/Composer/Repository/Vcs/SvnDriver.php | 2 + src/Composer/Repository/Vcs/VcsDriver.php | 4 +- src/Composer/Util/Perforce.php | 7 +-- 8 files changed, 65 insertions(+), 58 deletions(-) diff --git a/src/Composer/Repository/Vcs/BitbucketDriver.php b/src/Composer/Repository/Vcs/BitbucketDriver.php index 5afd767cd..e09fe8ae7 100644 --- a/src/Composer/Repository/Vcs/BitbucketDriver.php +++ b/src/Composer/Repository/Vcs/BitbucketDriver.php @@ -20,16 +20,16 @@ abstract class BitbucketDriver extends VcsDriver protected $infoCache = array(); /** - * @var GitDriver + * @var VcsDriver */ - protected $sshDriver; + protected $fallbackDriver; /** * {@inheritDoc} */ public function initialize() { - preg_match('#^https?://bitbucket\.org/([^/]+)/(.+?)(\.git|/?)$#', $this->url, $match); + preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)$#', $this->url, $match); $this->owner = $match[1]; $this->repository = $match[2]; $this->originUrl = 'bitbucket.org'; @@ -49,8 +49,8 @@ abstract class BitbucketDriver extends VcsDriver */ public function getComposerInformation($identifier) { - if ($this->sshDriver) { - return $this->sshDriver->getComposerInformation($identifier); + if ($this->fallbackDriver) { + return $this->fallbackDriver->getComposerInformation($identifier); } if (!isset($this->infoCache[$identifier])) { @@ -110,8 +110,8 @@ abstract class BitbucketDriver extends VcsDriver */ public function getFileContent($file, $identifier) { - if ($this->sshDriver) { - return $this->sshDriver->getFileContent($file, $identifier); + if ($this->fallbackDriver) { + return $this->fallbackDriver->getFileContent($file, $identifier); } if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier . ':' . $file)) { @@ -137,8 +137,8 @@ abstract class BitbucketDriver extends VcsDriver */ public function getChangeDate($identifier) { - if ($this->sshDriver) { - return $this->sshDriver->getChangeDate($identifier); + if ($this->fallbackDriver) { + return $this->fallbackDriver->getChangeDate($identifier); } $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/' @@ -163,22 +163,19 @@ abstract class BitbucketDriver extends VcsDriver } catch (TransportException $e) { $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process, $this->remoteFilesystem); - switch ($e->getCode()) { - case 403: - if (!$this->io->hasAuthentication($this->originUrl) - && $bitbucketUtil->authorizeOAuth($this->originUrl)) { - return parent::getContents($url); - } - - if (!$this->io->isInteractive() && $fetchingRepoData) { - return $this->attemptCloneFallback(); - } - - throw $e; + if (403 === $e->getCode()) { + if (!$this->io->hasAuthentication($this->originUrl) + && $bitbucketUtil->authorizeOAuth($this->originUrl) + ) { + return parent::getContents($url); + } - default: - throw $e; + if (!$this->io->isInteractive() && $fetchingRepoData) { + return $this->attemptCloneFallback(); + } } + + throw $e; } } @@ -187,19 +184,14 @@ abstract class BitbucketDriver extends VcsDriver * * @return string */ - protected function generateSshUrl() - { - return 'git@' . $this->originUrl . ':' . $this->owner.'/'.$this->repository.'.git'; - } + abstract protected function generateSshUrl(); protected function attemptCloneFallback() { try { - $this->setupSshDriver($this->generateSshUrl()); - - return; + $this->setupFallbackDriver($this->generateSshUrl()); } catch (\RuntimeException $e) { - $this->sshDriver = null; + $this->fallbackDriver = null; $this->io->writeError( 'Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode' @@ -209,5 +201,5 @@ abstract class BitbucketDriver extends VcsDriver } } - abstract protected function setupSshDriver($url); + abstract protected function setupFallbackDriver($url); } diff --git a/src/Composer/Repository/Vcs/GitBitbucketDriver.php b/src/Composer/Repository/Vcs/GitBitbucketDriver.php index 9c07fff40..ff92e2820 100644 --- a/src/Composer/Repository/Vcs/GitBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/GitBitbucketDriver.php @@ -32,8 +32,8 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface */ public function getRootIdentifier() { - if ($this->sshDriver) { - return $this->sshDriver->getRootIdentifier(); + if ($this->fallbackDriver) { + return $this->fallbackDriver->getRootIdentifier(); } if (null === $this->rootIdentifier) { @@ -51,8 +51,8 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface */ public function getUrl() { - if ($this->sshDriver) { - return $this->sshDriver->getUrl(); + if ($this->fallbackDriver) { + return $this->fallbackDriver->getUrl(); } return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git'; @@ -63,8 +63,8 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface */ public function getSource($identifier) { - if ($this->sshDriver) { - return $this->sshDriver->getSource($identifier); + if ($this->fallbackDriver) { + return $this->fallbackDriver->getSource($identifier); } return array('type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier); @@ -86,8 +86,8 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface */ public function getTags() { - if ($this->sshDriver) { - return $this->sshDriver->getTags(); + if ($this->fallbackDriver) { + return $this->fallbackDriver->getTags(); } if (null === $this->tags) { @@ -107,8 +107,8 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface */ public function getBranches() { - if ($this->sshDriver) { - return $this->sshDriver->getBranches(); + if ($this->fallbackDriver) { + return $this->fallbackDriver->getBranches(); } if (null === $this->branches) { @@ -144,15 +144,23 @@ class GitBitbucketDriver extends BitbucketDriver implements VcsDriverInterface /** * @param string $url */ - protected function setupSshDriver($url) + protected function setupFallbackDriver($url) { - $this->sshDriver = new GitDriver( + $this->fallbackDriver = new GitDriver( array('url' => $url), $this->io, $this->config, $this->process, $this->remoteFilesystem ); - $this->sshDriver->initialize(); + $this->fallbackDriver->initialize(); + } + + /** + * {@inheritdoc} + */ + protected function generateSshUrl() + { + return 'git@' . $this->originUrl . ':' . $this->owner.'/'.$this->repository.'.git'; } } diff --git a/src/Composer/Repository/Vcs/GitLabDriver.php b/src/Composer/Repository/Vcs/GitLabDriver.php index 2ad00003a..0f932cf91 100644 --- a/src/Composer/Repository/Vcs/GitLabDriver.php +++ b/src/Composer/Repository/Vcs/GitLabDriver.php @@ -155,7 +155,7 @@ class GitLabDriver extends VcsDriver } } - if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier . ':' . $file)) { + if ($isHash = preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier . ':' . $file)) { return $res; } @@ -170,7 +170,7 @@ class GitLabDriver extends VcsDriver return null; } - if (preg_match('{[a-f0-9]{40}}i', $identifier)) { + if ($isHash) { $this->cache->write($identifier . ':' . $file, $content); } diff --git a/src/Composer/Repository/Vcs/HgBitbucketDriver.php b/src/Composer/Repository/Vcs/HgBitbucketDriver.php index 6edc1364e..7ccbc5def 100644 --- a/src/Composer/Repository/Vcs/HgBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/HgBitbucketDriver.php @@ -120,15 +120,23 @@ class HgBitbucketDriver extends BitbucketDriver return true; } - protected function setupSshDriver($url) + protected function setupFallbackDriver($url) { - $this->sshDriver = new HgDriver( + $this->fallbackDriver = new HgDriver( array('url' => $url), $this->io, $this->config, $this->process, $this->remoteFilesystem ); - $this->sshDriver->initialize(); + $this->fallbackDriver->initialize(); + } + + /** + * {@inheritdoc} + */ + protected function generateSshUrl() + { + return 'hg@' . $this->originUrl . '/' . $this->owner.'/'.$this->repository; } } diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 2a011106e..a4de5af05 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -88,7 +88,7 @@ class PerforceDriver extends VcsDriver */ public function getChangeDate($identifier) { - return new \DateTime(); + return null; } /** diff --git a/src/Composer/Repository/Vcs/SvnDriver.php b/src/Composer/Repository/Vcs/SvnDriver.php index 1d3df7909..91623b602 100644 --- a/src/Composer/Repository/Vcs/SvnDriver.php +++ b/src/Composer/Repository/Vcs/SvnDriver.php @@ -224,6 +224,8 @@ class SvnDriver extends VcsDriver return new \DateTime($match[1], new \DateTimeZone('UTC')); } } + + return null; } /** diff --git a/src/Composer/Repository/Vcs/VcsDriver.php b/src/Composer/Repository/Vcs/VcsDriver.php index 37e9fc01f..6276b5168 100644 --- a/src/Composer/Repository/Vcs/VcsDriver.php +++ b/src/Composer/Repository/Vcs/VcsDriver.php @@ -83,8 +83,8 @@ abstract class VcsDriver implements VcsDriverInterface $composer = JsonFile::parseJson($composerFileContent, $identifier . ':composer.json'); - if (empty($composer['time'])) { - $composer['time'] = $this->getChangeDate($identifier)->format('Y-m-d H:i:s'); + if (empty($composer['time']) && $changeDate = $this->getChangeDate($identifier)) { + $composer['time'] = $changeDate->format('Y-m-d H:i:s'); } $this->infoCache[$identifier] = $composer; diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 533af98cc..f955c10db 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -439,13 +439,10 @@ class Perforce $index2 = strpos($result, 'no such file(s).'); if ($index2 === false) { $index3 = strpos($result, 'change'); - if (!($index3 === false)) { + if ($index3 !== false) { $phrase = trim(substr($result, $index3)); $fields = explode(' ', $phrase); - $id = $fields[1]; - $path = substr($identifier, 0, $index) . '/' . $file . '@' . $id; - - return $path; + return substr($identifier, 0, $index) . '/' . $file . '@' . $fields[1]; } } } From 7896b1ffab6dedc917f4d125efb8d3010e54a35c Mon Sep 17 00:00:00 2001 From: Thomas Flori Date: Tue, 15 Nov 2016 07:52:17 +0100 Subject: [PATCH 5/5] cache only rendered composer information As suggested we cache now only composer information and also the rendered version again. Perforce is using the same property cache as others and the `Util\Perforce::getComposerInformation()` is using the newly created methods. --- .../Repository/Vcs/BitbucketDriver.php | 18 ++--- .../Repository/Vcs/GitBitbucketDriver.php | 3 - src/Composer/Repository/Vcs/GitDriver.php | 8 --- src/Composer/Repository/Vcs/GitHubDriver.php | 17 +++-- src/Composer/Repository/Vcs/GitLabDriver.php | 69 ------------------- .../Repository/Vcs/HgBitbucketDriver.php | 1 - .../Repository/Vcs/PerforceDriver.php | 23 +------ src/Composer/Repository/Vcs/SvnDriver.php | 48 ++----------- src/Composer/Repository/Vcs/VcsDriver.php | 43 ++++++++++-- src/Composer/Util/Perforce.php | 50 ++------------ 10 files changed, 66 insertions(+), 214 deletions(-) diff --git a/src/Composer/Repository/Vcs/BitbucketDriver.php b/src/Composer/Repository/Vcs/BitbucketDriver.php index e09fe8ae7..a1d9a8e26 100644 --- a/src/Composer/Repository/Vcs/BitbucketDriver.php +++ b/src/Composer/Repository/Vcs/BitbucketDriver.php @@ -54,7 +54,11 @@ abstract class BitbucketDriver extends VcsDriver } if (!isset($this->infoCache[$identifier])) { - $composer = parent::getComposerInformation($identifier); + if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) { + return $this->infoCache[$identifier] = JsonFile::parseJson($res); + } + + $composer = $this->getBaseComposerInformation($identifier); // specials for bitbucket if (!isset($composer['support']['source'])) { @@ -100,6 +104,10 @@ abstract class BitbucketDriver extends VcsDriver } $this->infoCache[$identifier] = $composer; + + if ($this->shouldCache($identifier)) { + $this->cache->write($identifier, json_encode($composer)); + } } return $this->infoCache[$identifier]; @@ -114,10 +122,6 @@ abstract class BitbucketDriver extends VcsDriver return $this->fallbackDriver->getFileContent($file, $identifier); } - if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier . ':' . $file)) { - return $res; - } - $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/' . $this->owner . '/' . $this->repository . '/src/' . $identifier . '/' . $file; $fileData = JsonFile::parseJson($this->getContents($resource), $resource); @@ -125,10 +129,6 @@ abstract class BitbucketDriver extends VcsDriver return null; } - if (preg_match('{[a-f0-9]{40}}i', $identifier)) { - $this->cache->write($identifier . ':' . $file, $fileData['data']); - } - return $fileData['data']; } diff --git a/src/Composer/Repository/Vcs/GitBitbucketDriver.php b/src/Composer/Repository/Vcs/GitBitbucketDriver.php index ff92e2820..2874fe77d 100644 --- a/src/Composer/Repository/Vcs/GitBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/GitBitbucketDriver.php @@ -12,12 +12,9 @@ namespace Composer\Repository\Vcs; -use Composer\Cache; use Composer\Config; -use Composer\Downloader\TransportException; use Composer\Json\JsonFile; use Composer\IO\IOInterface; -use Composer\Util\Bitbucket; /** * @author Per Bernhardt diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index a93447c73..7093ce94d 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -124,10 +124,6 @@ class GitDriver extends VcsDriver */ public function getFileContent($file, $identifier) { - if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier . ':' . $file)) { - return $res; - } - $resource = sprintf('%s:%s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file)); $this->process->execute(sprintf('git show %s', $resource), $content, $this->repoDir); @@ -135,10 +131,6 @@ class GitDriver extends VcsDriver return null; } - if (preg_match('{[a-f0-9]{40}}i', $identifier)) { - $this->cache->write($identifier . ':' . $file, $content); - } - return $content; } diff --git a/src/Composer/Repository/Vcs/GitHubDriver.php b/src/Composer/Repository/Vcs/GitHubDriver.php index 04ac5d7cd..b33b99916 100644 --- a/src/Composer/Repository/Vcs/GitHubDriver.php +++ b/src/Composer/Repository/Vcs/GitHubDriver.php @@ -147,8 +147,11 @@ class GitHubDriver extends VcsDriver } if (!isset($this->infoCache[$identifier])) { + if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) { + return $this->infoCache[$identifier] = JsonFile::parseJson($res); + } - $composer = parent::getComposerInformation($identifier); + $composer = $this->getBaseComposerInformation($identifier); // specials for github if (!isset($composer['support']['source'])) { @@ -159,6 +162,10 @@ class GitHubDriver extends VcsDriver $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository); } + if ($this->shouldCache($identifier)) { + $this->cache->write($identifier, json_encode($composer)); + } + $this->infoCache[$identifier] = $composer; } @@ -174,10 +181,6 @@ class GitHubDriver extends VcsDriver return $this->gitDriver->getFileContent($file, $identifier); } - if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier . ':' . $file)) { - return $res; - } - $notFoundRetries = 2; while ($notFoundRetries) { try { @@ -188,10 +191,6 @@ class GitHubDriver extends VcsDriver throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier); } - if ($content && preg_match('{[a-f0-9]{40}}i', $identifier)) { - $this->cache->write($identifier . ':' . $file, $content); - } - return $content; } catch (TransportException $e) { if (404 !== $e->getCode()) { diff --git a/src/Composer/Repository/Vcs/GitLabDriver.php b/src/Composer/Repository/Vcs/GitLabDriver.php index 0f932cf91..5f3538869 100644 --- a/src/Composer/Repository/Vcs/GitLabDriver.php +++ b/src/Composer/Repository/Vcs/GitLabDriver.php @@ -32,8 +32,6 @@ class GitLabDriver extends VcsDriver private $owner; private $repository; - private $cache; - /** * @var array Project data returned by GitLab API */ @@ -97,51 +95,6 @@ class GitLabDriver extends VcsDriver $this->remoteFilesystem = $remoteFilesystem; } - /** - * Fetches the composer.json file from the project by a identifier. - * - * if specific keys arent present it will try and infer them by default values. - * - * {@inheritDoc} - */ - public function getComposerInformation($identifier) - { - // Convert the root identifier to a cachable commit id - if (!preg_match('{[a-f0-9]{40}}i', $identifier)) { - $branches = $this->getBranches(); - if (isset($branches[$identifier])) { - $identifier = $branches[$identifier]; - } - } - - if (isset($this->infoCache[$identifier])) { - return $this->infoCache[$identifier]; - } - - if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier)) { - return $this->infoCache[$identifier] = JsonFile::parseJson($res, $res); - } - - try { - $composer = $this->fetchComposerFile($identifier); - } catch (TransportException $e) { - if ($e->getCode() !== 404) { - throw $e; - } - $composer = false; - } - - if ($composer && !isset($composer['time']) && isset($this->commits[$identifier])) { - $composer['time'] = $this->commits[$identifier]['committed_date']; - } - - if (preg_match('{[a-f0-9]{40}}i', $identifier)) { - $this->cache->write($identifier, json_encode($composer)); - } - - return $this->infoCache[$identifier] = $composer; - } - /** * {@inheritdoc} */ @@ -155,10 +108,6 @@ class GitLabDriver extends VcsDriver } } - if ($isHash = preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier . ':' . $file)) { - return $res; - } - $resource = $this->getApiUrl().'/repository/blobs/'.$identifier.'?filepath=' . $file; try { @@ -170,10 +119,6 @@ class GitLabDriver extends VcsDriver return null; } - if ($isHash) { - $this->cache->write($identifier . ':' . $file, $content); - } - return $content; } @@ -256,20 +201,6 @@ class GitLabDriver extends VcsDriver return $this->tags; } - /** - * Fetches composer.json file from the repository through api. - * - * @param string $identifier - * - * @return array - */ - protected function fetchComposerFile($identifier) - { - $resource = $this->getApiUrl().'/repository/blobs/'.$identifier.'?filepath=composer.json'; - - return JsonFile::parseJson($this->getContents($resource), $resource); - } - /** * @return string Base URL for GitLab API v3 */ diff --git a/src/Composer/Repository/Vcs/HgBitbucketDriver.php b/src/Composer/Repository/Vcs/HgBitbucketDriver.php index 7ccbc5def..c456121c0 100644 --- a/src/Composer/Repository/Vcs/HgBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/HgBitbucketDriver.php @@ -12,7 +12,6 @@ namespace Composer\Repository\Vcs; -use Composer\Cache; use Composer\Config; use Composer\Json\JsonFile; use Composer\IO\IOInterface; diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index a4de5af05..7aaa6efb4 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -26,9 +26,6 @@ class PerforceDriver extends VcsDriver protected $branch; /** @var Perforce */ protected $perforce; - protected $composerInfo; - protected $composerInfoIdentifier; - /** * {@inheritDoc} */ @@ -60,20 +57,6 @@ class PerforceDriver extends VcsDriver $this->perforce = Perforce::create($repoConfig, $this->getUrl(), $repoDir, $this->process, $this->io); } - /** - * {@inheritDoc} - */ - public function getComposerInformation($identifier) - { - if (!empty($this->composerInfoIdentifier)) { - if (strcmp($identifier, $this->composerInfoIdentifier) === 0) { - return $this->composerInfo; - } - } - $composer_info = $this->perforce->getComposerInformation($identifier); - - return $composer_info; - } /** * {@inheritdoc} @@ -155,10 +138,10 @@ class PerforceDriver extends VcsDriver */ public function hasComposerFile($identifier) { - $this->composerInfo = $this->perforce->getComposerInformation('//' . $this->depot . '/' . $identifier); - $this->composerInfoIdentifier = $identifier; + $composerInfo = $this->perforce->getComposerInformation('//' . $this->depot . '/' . $identifier); + $composerInfoIdentifier = $identifier; - return !empty($this->composerInfo); + return !empty($composerInfo); } /** diff --git a/src/Composer/Repository/Vcs/SvnDriver.php b/src/Composer/Repository/Vcs/SvnDriver.php index 91623b602..f2d6a4754 100644 --- a/src/Composer/Repository/Vcs/SvnDriver.php +++ b/src/Composer/Repository/Vcs/SvnDriver.php @@ -116,53 +116,23 @@ class SvnDriver extends VcsDriver } /** - * {@inheritDoc} + * {@inheritdoc} */ public function getComposerInformation($identifier) { - $identifier = '/' . trim($identifier, '/') . '/'; - - if ($res = $this->cache->read($identifier.'.json')) { - $this->infoCache[$identifier] = JsonFile::parseJson($res); - } - if (!isset($this->infoCache[$identifier])) { - preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match); - if (!empty($match[2])) { - $path = $match[1]; - $rev = $match[2]; - } else { - $path = $identifier; - $rev = ''; - } - - try { - $resource = $path.'composer.json'; - $output = $this->execute('svn cat', $this->baseUrl . $resource . $rev); - if (!trim($output)) { - return; - } - } catch (\RuntimeException $e) { - throw new TransportException($e->getMessage()); + if ($res = $this->cache->read($identifier.'.json')) { + return $this->infoCache[$identifier] = JsonFile::parseJson($res); } - $composer = JsonFile::parseJson($output, $this->baseUrl . $resource . $rev); - - if (empty($composer['time'])) { - $output = $this->execute('svn info', $this->baseUrl . $path . $rev); - foreach ($this->process->splitLines($output) as $line) { - if ($line && preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) { - $date = new \DateTime($match[1], new \DateTimeZone('UTC')); - $composer['time'] = $date->format('Y-m-d H:i:s'); - break; - } - } - } + $composer = $this->getBaseComposerInformation($identifier); $this->cache->write($identifier.'.json', json_encode($composer)); + $this->infoCache[$identifier] = $composer; } + return $this->infoCache[$identifier]; } @@ -174,10 +144,6 @@ class SvnDriver extends VcsDriver { $identifier = '/' . trim($identifier, '/') . '/'; - if ($res = $this->cache->read($identifier . ':' . $file)) { - return $res; - } - preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match); if (!empty($match[2])) { $path = $match[1]; @@ -197,8 +163,6 @@ class SvnDriver extends VcsDriver throw new TransportException($e->getMessage()); } - $this->cache->write($identifier . ':' . $file, $output); - return $output; } diff --git a/src/Composer/Repository/Vcs/VcsDriver.php b/src/Composer/Repository/Vcs/VcsDriver.php index 6276b5168..c72a6c6a8 100644 --- a/src/Composer/Repository/Vcs/VcsDriver.php +++ b/src/Composer/Repository/Vcs/VcsDriver.php @@ -12,6 +12,7 @@ namespace Composer\Repository\Vcs; +use Composer\Cache; use Composer\Downloader\TransportException; use Composer\Config; use Composer\Factory; @@ -44,6 +45,8 @@ abstract class VcsDriver implements VcsDriverInterface protected $remoteFilesystem; /** @var array */ protected $infoCache = array(); + /** @var Cache */ + protected $cache; /** * Constructor. @@ -69,22 +72,31 @@ abstract class VcsDriver implements VcsDriverInterface $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config); } + /** + * Returns whether or not the given $identifier should be cached or not. + * + * @param string $identifier + * @return boolean + */ + protected function shouldCache($identifier) + { + return $this->cache && preg_match('{[a-f0-9]{40}}i', $identifier); + } + /** * {@inheritdoc} */ public function getComposerInformation($identifier) { if (!isset($this->infoCache[$identifier])) { - $composerFileContent = $this->getFileContent('composer.json', $identifier); - - if (!$composerFileContent) { - return null; + if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) { + return $this->infoCache[$identifier] = JsonFile::parseJson($res); } - $composer = JsonFile::parseJson($composerFileContent, $identifier . ':composer.json'); + $composer = $this->getBaseComposerInformation($identifier); - if (empty($composer['time']) && $changeDate = $this->getChangeDate($identifier)) { - $composer['time'] = $changeDate->format('Y-m-d H:i:s'); + if ($this->shouldCache($identifier)) { + $this->cache->write($identifier, json_encode($composer)); } $this->infoCache[$identifier] = $composer; @@ -94,6 +106,23 @@ abstract class VcsDriver implements VcsDriverInterface return $this->infoCache[$identifier]; } + protected function getBaseComposerInformation($identifier) + { + $composerFileContent = $this->getFileContent('composer.json', $identifier); + + if (!$composerFileContent) { + return null; + } + + $composer = JsonFile::parseJson($composerFileContent, $identifier . ':composer.json'); + + if (empty($composer['time']) && $changeDate = $this->getChangeDate($identifier)) { + $composer['time'] = $changeDate->format('Y-m-d H:i:s'); + } + + return $composer; + } + /** * {@inheritDoc} */ diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index f955c10db..f3c20fce3 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -399,14 +399,13 @@ class Perforce public function getComposerInformation($identifier) { - $index = strpos($identifier, '@'); - if ($index === false) { - $composerJson = $identifier. '/composer.json'; + $composerFileContent = $this->getFileContent('composer.json', $identifier); - return $this->getComposerInformationFromPath($composerJson); + if (!$composerFileContent) { + return; } - return $this->getComposerInformationFromLabel($identifier, $index); + return json_decode($composerFileContent, true); } public function getFileContent($file, $identifier) @@ -450,47 +449,6 @@ class Perforce return null; } - public function getComposerInformationFromPath($composerJson) - { - $command = $this->generateP4Command(' print ' . $composerJson); - $this->executeCommand($command); - $result = $this->commandResult; - $index = strpos($result, '{'); - if ($index === false) { - return ''; - } - if ($index >= 0) { - $rawData = substr($result, $index); - $composer_info = json_decode($rawData, true); - - return $composer_info; - } - - return ''; - } - - public function getComposerInformationFromLabel($identifier, $index) - { - $composerJsonPath = substr($identifier, 0, $index) . '/composer.json' . substr($identifier, $index); - $command = $this->generateP4Command(' files ' . $composerJsonPath, false); - $this->executeCommand($command); - $result = $this->commandResult; - $index2 = strpos($result, 'no such file(s).'); - if ($index2 === false) { - $index3 = strpos($result, 'change'); - if (!($index3 === false)) { - $phrase = trim(substr($result, $index3)); - $fields = explode(' ', $phrase); - $id = $fields[1]; - $composerJson = substr($identifier, 0, $index) . '/composer.json@' . $id; - - return $this->getComposerInformationFromPath($composerJson); - } - } - - return ""; - } - public function getBranches() { $possibleBranches = array();