You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
4.7KB

  1. <?php
  2. /*
  3. * This file is part of the Fxp Composer Asset Plugin package.
  4. *
  5. * (c) François Pluchino <francois.pluchino@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Fxp\Composer\AssetPlugin\Repository\Vcs;
  11. use Composer\Downloader\TransportException;
  12. use Composer\Json\JsonFile;
  13. /**
  14. * GitHub vcs driver.
  15. *
  16. * @author François Pluchino <francois.pluchino@gmail.com>
  17. */
  18. class GitHubDriver extends AbstractGitHubDriver
  19. {
  20. /**
  21. * {@inheritdoc}
  22. */
  23. public function getComposerInformation($identifier)
  24. {
  25. if ($this->gitDriver) {
  26. return $this->gitDriver->getComposerInformation($identifier);
  27. }
  28. $this->infoCache[$identifier] = Util::readCache($this->infoCache, $this->cache, $this->repoConfig['asset-type'], $identifier);
  29. if (!isset($this->infoCache[$identifier])) {
  30. $resource = $this->getApiUrl().'/repos/'.$this->owner.'/'.$this->repository.'/contents/'.$this->repoConfig['filename'].'?ref='.urlencode($identifier);
  31. $composer = $this->getComposerContent($resource);
  32. if ($composer) {
  33. $composer = $this->convertComposerContent($composer, $resource, $identifier);
  34. } else {
  35. $composer = array('_nonexistent_package' => true);
  36. }
  37. Util::writeCache($this->cache, $this->repoConfig['asset-type'], $identifier, $composer);
  38. $this->infoCache[$identifier] = $composer;
  39. }
  40. return $this->infoCache[$identifier];
  41. }
  42. /**
  43. * Gets content of composer information.
  44. *
  45. * @param string $resource
  46. *
  47. * @return null|false|array
  48. *
  49. * @throws \RuntimeException
  50. * @throws \Composer\Downloader\TransportException
  51. * @throws \Exception
  52. */
  53. protected function getComposerContent($resource)
  54. {
  55. $notFoundRetries = 2;
  56. $composer = null;
  57. while ($notFoundRetries) {
  58. try {
  59. $composer = $this->parseComposerContent($resource);
  60. break;
  61. } catch (TransportException $e) {
  62. if (404 !== $e->getCode()) {
  63. throw $e;
  64. }
  65. // retry fetching if github returns a 404 since they happen randomly
  66. --$notFoundRetries;
  67. $composer = false;
  68. }
  69. }
  70. return $composer;
  71. }
  72. /**
  73. * Parse the composer content.
  74. *
  75. * @param string $resource
  76. *
  77. * @return array
  78. *
  79. * @throws \RuntimeException When the resource could not be retrieved
  80. */
  81. protected function parseComposerContent($resource)
  82. {
  83. $composer = (array) JsonFile::parseJson((string) $this->getContents($resource));
  84. if (empty($composer['content']) || $composer['encoding'] !== 'base64' || !($composer = base64_decode($composer['content']))) {
  85. throw new \RuntimeException('Could not retrieve '.$this->repoConfig['filename'].' from '.$resource);
  86. }
  87. return $composer;
  88. }
  89. /**
  90. * Converts json composer file to array.
  91. *
  92. * @param string $composer
  93. * @param string $resource
  94. * @param string $identifier
  95. *
  96. * @return array
  97. */
  98. protected function convertComposerContent($composer, $resource, $identifier)
  99. {
  100. $composer = JsonFile::parseJson($composer, $resource);
  101. $resource = $this->getApiUrl().'/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier);
  102. $composer = Util::addComposerTime($composer, 'commit.committer.date', $resource, $this);
  103. if (!isset($composer['support']['source'])) {
  104. $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier;
  105. $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label);
  106. }
  107. if (!isset($composer['support']['issues']) && $this->hasIssues) {
  108. $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository);
  109. }
  110. return $composer;
  111. }
  112. /**
  113. * Setup git driver.
  114. *
  115. * @param string $url
  116. */
  117. protected function setupGitDriver($url)
  118. {
  119. $this->gitDriver = new GitDriver(
  120. array(
  121. 'url' => $url,
  122. 'asset-type' => $this->repoConfig['asset-type'],
  123. 'filename' => $this->repoConfig['filename'],
  124. ),
  125. $this->io,
  126. $this->config,
  127. $this->process,
  128. $this->remoteFilesystem
  129. );
  130. $this->gitDriver->initialize();
  131. }
  132. }