PathRepository.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. <?php
  2. /*
  3. * This file is part of Composer.
  4. *
  5. * (c) Nils Adermann <naderman@naderman.de>
  6. * Jordi Boggiano <j.boggiano@seld.be>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Composer\Repository;
  12. use Composer\Config;
  13. use Composer\IO\IOInterface;
  14. use Composer\Json\JsonFile;
  15. use Composer\Package\Loader\ArrayLoader;
  16. use Composer\Package\Locker;
  17. use Composer\Package\Version\VersionGuesser;
  18. use Composer\Package\Version\VersionParser;
  19. use Composer\Util\ProcessExecutor;
  20. /**
  21. * This repository allows installing local packages that are not necessarily under their own VCS.
  22. *
  23. * The local packages will be symlinked when possible, else they will be copied.
  24. *
  25. * @code
  26. * "require": {
  27. * "<vendor>/<local-package>": "*"
  28. * },
  29. * "repositories": [
  30. * {
  31. * "type": "path",
  32. * "url": "../../relative/path/to/package/"
  33. * },
  34. * {
  35. * "type": "path",
  36. * "url": "/absolute/path/to/package/"
  37. * },
  38. * {
  39. * "type": "path",
  40. * "url": "/absolute/path/to/several/packages/*"
  41. * }
  42. * ]
  43. * @endcode
  44. *
  45. * @author Samuel Roze <samuel.roze@gmail.com>
  46. * @author Johann Reinke <johann.reinke@gmail.com>
  47. */
  48. class PathRepository extends ArrayRepository implements ConfigurableRepositoryInterface
  49. {
  50. /**
  51. * @var ArrayLoader
  52. */
  53. private $loader;
  54. /**
  55. * @var VersionGuesser
  56. */
  57. private $versionGuesser;
  58. /**
  59. * @var string
  60. */
  61. private $url;
  62. /**
  63. * @var array
  64. */
  65. private $repoConfig;
  66. /**
  67. * @var ProcessExecutor
  68. */
  69. private $process;
  70. /**
  71. * Initializes path repository.
  72. *
  73. * @param array $repoConfig
  74. * @param IOInterface $io
  75. * @param Config $config
  76. */
  77. public function __construct(array $repoConfig, IOInterface $io, Config $config)
  78. {
  79. if (!isset($repoConfig['url'])) {
  80. throw new \RuntimeException('You must specify the `url` configuration for the path repository');
  81. }
  82. $this->loader = new ArrayLoader();
  83. $this->url = $repoConfig['url'];
  84. $this->process = new ProcessExecutor($io);
  85. $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser());
  86. $this->repoConfig = $repoConfig;
  87. parent::__construct();
  88. }
  89. public function getRepoConfig()
  90. {
  91. return $this->repoConfig;
  92. }
  93. /**
  94. * Initializes path repository.
  95. *
  96. * This method will basically read the folder and add the found package.
  97. */
  98. protected function initialize()
  99. {
  100. parent::initialize();
  101. foreach ($this->getUrlMatches() as $url) {
  102. $path = realpath($url) . DIRECTORY_SEPARATOR;
  103. $composerFilePath = $path.'composer.json';
  104. if (!file_exists($composerFilePath)) {
  105. continue;
  106. }
  107. $json = file_get_contents($composerFilePath);
  108. $package = JsonFile::parseJson($json, $composerFilePath);
  109. $package['dist'] = array(
  110. 'type' => 'path',
  111. 'url' => $url,
  112. 'reference' => sha1($json),
  113. );
  114. if (!isset($package['version'])) {
  115. $package['version'] = $this->versionGuesser->guessVersion($package, $path) ?: 'dev-master';
  116. }
  117. $output = '';
  118. if (is_dir($path . DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $path)) {
  119. $package['dist']['reference'] = trim($output);
  120. }
  121. $package = $this->loader->load($package);
  122. $this->addPackage($package);
  123. }
  124. }
  125. /**
  126. * Get a list of all (possibly relative) path names matching given url (supports globbing).
  127. *
  128. * @return string[]
  129. */
  130. private function getUrlMatches()
  131. {
  132. // Ensure environment-specific path separators are normalized to URL separators
  133. return array_map(function ($val) {
  134. return str_replace(DIRECTORY_SEPARATOR, '/', $val);
  135. }, glob($this->url, GLOB_MARK | GLOB_ONLYDIR));
  136. }
  137. }