RootPackageLoader.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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\Package\Loader;
  12. use Composer\Package\BasePackage;
  13. use Composer\Package\AliasPackage;
  14. use Composer\Config;
  15. use Composer\Factory;
  16. use Composer\Package\Version\VersionGuesser;
  17. use Composer\Package\Version\VersionParser;
  18. use Composer\Repository\RepositoryManager;
  19. use Composer\Util\ProcessExecutor;
  20. /**
  21. * ArrayLoader built for the sole purpose of loading the root package
  22. *
  23. * Sets additional defaults and loads repositories
  24. *
  25. * @author Jordi Boggiano <j.boggiano@seld.be>
  26. */
  27. class RootPackageLoader extends ArrayLoader
  28. {
  29. /**
  30. * @var RepositoryManager
  31. */
  32. private $manager;
  33. /**
  34. * @var Config
  35. */
  36. private $config;
  37. /**
  38. * @var VersionGuesser
  39. */
  40. private $versionGuesser;
  41. public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, VersionGuesser $versionGuesser = null)
  42. {
  43. parent::__construct($parser);
  44. $this->manager = $manager;
  45. $this->config = $config;
  46. $this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor(), $this->versionParser);
  47. }
  48. public function load(array $config, $class = 'Composer\Package\RootPackage')
  49. {
  50. if (!isset($config['name'])) {
  51. $config['name'] = '__root__';
  52. }
  53. $autoVersioned = false;
  54. if (!isset($config['version'])) {
  55. // override with env var if available
  56. if (getenv('COMPOSER_ROOT_VERSION')) {
  57. $version = getenv('COMPOSER_ROOT_VERSION');
  58. } else {
  59. $version = $this->versionGuesser->guessVersion($config, getcwd());
  60. }
  61. if (!$version) {
  62. $version = '1.0.0';
  63. $autoVersioned = true;
  64. }
  65. $config['version'] = $version;
  66. }
  67. $realPackage = $package = parent::load($config, $class);
  68. if ($realPackage instanceof AliasPackage) {
  69. $realPackage = $package->getAliasOf();
  70. }
  71. if ($autoVersioned) {
  72. $realPackage->replaceVersion($realPackage->getVersion(), 'No version set (parsed as 1.0.0)');
  73. }
  74. if (isset($config['minimum-stability'])) {
  75. $realPackage->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
  76. }
  77. $aliases = array();
  78. $stabilityFlags = array();
  79. $references = array();
  80. foreach (array('require', 'require-dev') as $linkType) {
  81. if (isset($config[$linkType])) {
  82. $linkInfo = BasePackage::$supportedLinkTypes[$linkType];
  83. $method = 'get'.ucfirst($linkInfo['method']);
  84. $links = array();
  85. foreach ($realPackage->$method() as $link) {
  86. $links[$link->getTarget()] = $link->getConstraint()->getPrettyString();
  87. }
  88. $aliases = $this->extractAliases($links, $aliases);
  89. $stabilityFlags = $this->extractStabilityFlags($links, $stabilityFlags, $realPackage->getMinimumStability());
  90. $references = $this->extractReferences($links, $references);
  91. }
  92. }
  93. $realPackage->setAliases($aliases);
  94. $realPackage->setStabilityFlags($stabilityFlags);
  95. $realPackage->setReferences($references);
  96. if (isset($config['prefer-stable'])) {
  97. $realPackage->setPreferStable((bool) $config['prefer-stable']);
  98. }
  99. $repos = Factory::createDefaultRepositories(null, $this->config, $this->manager);
  100. foreach ($repos as $repo) {
  101. $this->manager->addRepository($repo);
  102. }
  103. $realPackage->setRepositories($this->config->getRepositories());
  104. return $package;
  105. }
  106. private function extractAliases(array $requires, array $aliases)
  107. {
  108. foreach ($requires as $reqName => $reqVersion) {
  109. if (preg_match('{^([^,\s#]+)(?:#[^ ]+)? +as +([^,\s]+)$}', $reqVersion, $match)) {
  110. $aliases[] = array(
  111. 'package' => strtolower($reqName),
  112. 'version' => $this->versionParser->normalize($match[1], $reqVersion),
  113. 'alias' => $match[2],
  114. 'alias_normalized' => $this->versionParser->normalize($match[2], $reqVersion),
  115. );
  116. }
  117. }
  118. return $aliases;
  119. }
  120. private function extractStabilityFlags(array $requires, array $stabilityFlags, $minimumStability)
  121. {
  122. $stabilities = BasePackage::$stabilities;
  123. $minimumStability = $stabilities[$minimumStability];
  124. foreach ($requires as $reqName => $reqVersion) {
  125. // parse explicit stability flags to the most unstable
  126. if (preg_match('{^[^@]*?@('.implode('|', array_keys($stabilities)).')$}i', $reqVersion, $match)) {
  127. $name = strtolower($reqName);
  128. $stability = $stabilities[VersionParser::normalizeStability($match[1])];
  129. if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
  130. continue;
  131. }
  132. $stabilityFlags[$name] = $stability;
  133. continue;
  134. }
  135. // infer flags for requirements that have an explicit -dev or -beta version specified but only
  136. // for those that are more unstable than the minimumStability or existing flags
  137. $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion);
  138. if (preg_match('{^[^,\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) {
  139. $name = strtolower($reqName);
  140. $stability = $stabilities[$stabilityName];
  141. if ((isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) || ($minimumStability > $stability)) {
  142. continue;
  143. }
  144. $stabilityFlags[$name] = $stability;
  145. }
  146. }
  147. return $stabilityFlags;
  148. }
  149. private function extractReferences(array $requires, array $references)
  150. {
  151. foreach ($requires as $reqName => $reqVersion) {
  152. $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion);
  153. if (preg_match('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === ($stabilityName = VersionParser::parseStability($reqVersion))) {
  154. $name = strtolower($reqName);
  155. $references[$name] = $match[1];
  156. }
  157. }
  158. return $references;
  159. }
  160. }