Skip to content

Commit df2f2dc

Browse files
committed
Merge branch '1.7'
2 parents d100620 + bbd10c1 commit df2f2dc

File tree

6 files changed

+93
-95
lines changed

6 files changed

+93
-95
lines changed

src/Composer/DependencyResolver/Pool.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,12 +317,12 @@ public function isPackageAcceptable($name, $stability)
317317
* Checks if the package matches the given constraint directly or through
318318
* provided or replaced packages
319319
*
320-
* @param array|PackageInterface $candidate
320+
* @param PackageInterface $candidate
321321
* @param string $name Name of the package to be matched
322322
* @param ConstraintInterface $constraint The constraint to verify
323323
* @return int One of the MATCH* constants of this class or 0 if there is no match
324324
*/
325-
private function match($candidate, $name, ConstraintInterface $constraint = null, $bypassFilters)
325+
public function match($candidate, $name, ConstraintInterface $constraint = null, $bypassFilters)
326326
{
327327
$candidateName = $candidate->getName();
328328
$candidateVersion = $candidate->getVersion();

src/Composer/DependencyResolver/RuleSetGenerator.php

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ class RuleSetGenerator
2828
protected $installedMap;
2929
protected $whitelistedMap;
3030
protected $addedMap;
31+
protected $conflictAddedMap;
32+
protected $addedPackages;
33+
protected $addedPackagesByNames;
3134

3235
public function __construct(PolicyInterface $policy, Pool $pool)
3336
{
@@ -185,13 +188,19 @@ protected function addRulesForPackage(PackageInterface $package, $ignorePlatform
185188
$workQueue->enqueue($package);
186189

187190
while (!$workQueue->isEmpty()) {
191+
/** @var PackageInterface $package */
188192
$package = $workQueue->dequeue();
189193
if (isset($this->addedMap[$package->id])) {
190194
continue;
191195
}
192196

193197
$this->addedMap[$package->id] = true;
194198

199+
$this->addedPackages[] = $package;
200+
foreach ($package->getNames() as $name) {
201+
$this->addedPackagesByNames[$name][] = $package;
202+
}
203+
195204
foreach ($package->getRequires() as $link) {
196205
if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
197206
continue;
@@ -206,21 +215,54 @@ protected function addRulesForPackage(PackageInterface $package, $ignorePlatform
206215
}
207216
}
208217

218+
$packageName = $package->getName();
219+
$obsoleteProviders = $this->pool->whatProvides($packageName, null);
220+
221+
foreach ($obsoleteProviders as $provider) {
222+
if ($provider === $package) {
223+
continue;
224+
}
225+
226+
if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
227+
$this->addRule(RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, array($provider), Rule::RULE_PACKAGE_ALIAS, $package));
228+
} elseif (!$this->obsoleteImpossibleForAlias($package, $provider)) {
229+
$reason = ($packageName == $provider->getName()) ? Rule::RULE_PACKAGE_SAME_NAME : Rule::RULE_PACKAGE_IMPLICIT_OBSOLETES;
230+
$this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $package));
231+
}
232+
}
233+
}
234+
}
235+
236+
protected function addConflictRules()
237+
{
238+
/** @var PackageInterface $package */
239+
foreach ($this->addedPackages as $package) {
209240
foreach ($package->getConflicts() as $link) {
210-
$possibleConflicts = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
241+
if (!isset($this->addedPackagesByNames[$link->getTarget()])) {
242+
continue;
243+
}
244+
245+
/** @var PackageInterface $possibleConflict */
246+
foreach ($this->addedPackagesByNames[$link->getTarget()] as $possibleConflict) {
247+
$conflictMatch = $this->pool->match($possibleConflict, $link->getTarget(), $link->getConstraint(), true);
248+
249+
if ($conflictMatch === Pool::MATCH || $conflictMatch === Pool::MATCH_REPLACE) {
250+
$this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $possibleConflict, Rule::RULE_PACKAGE_CONFLICT, $link));
251+
}
211252

212-
foreach ($possibleConflicts as $conflict) {
213-
$this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $conflict, Rule::RULE_PACKAGE_CONFLICT, $link));
214253
}
215254
}
216255

217256
// check obsoletes and implicit obsoletes of a package
218257
$isInstalled = isset($this->installedMap[$package->id]);
219258

220259
foreach ($package->getReplaces() as $link) {
221-
$obsoleteProviders = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
260+
if (!isset($this->addedPackagesByNames[$link->getTarget()])) {
261+
continue;
262+
}
222263

223-
foreach ($obsoleteProviders as $provider) {
264+
/** @var PackageInterface $possibleConflict */
265+
foreach ($this->addedPackagesByNames[$link->getTarget()] as $provider) {
224266
if ($provider === $package) {
225267
continue;
226268
}
@@ -231,22 +273,6 @@ protected function addRulesForPackage(PackageInterface $package, $ignorePlatform
231273
}
232274
}
233275
}
234-
235-
$packageName = $package->getName();
236-
$obsoleteProviders = $this->pool->whatProvides($packageName, null);
237-
238-
foreach ($obsoleteProviders as $provider) {
239-
if ($provider === $package) {
240-
continue;
241-
}
242-
243-
if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
244-
$this->addRule(RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, array($provider), Rule::RULE_PACKAGE_ALIAS, $package));
245-
} elseif (!$this->obsoleteImpossibleForAlias($package, $provider)) {
246-
$reason = ($packageName == $provider->getName()) ? Rule::RULE_PACKAGE_SAME_NAME : Rule::RULE_PACKAGE_IMPLICIT_OBSOLETES;
247-
$this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $package));
248-
}
249-
}
250276
}
251277
}
252278

@@ -327,12 +353,20 @@ public function getRulesFor($jobs, $installedMap, $ignorePlatformReqs = false)
327353
$this->pool->setWhitelist($this->whitelistedMap);
328354

329355
$this->addedMap = array();
356+
$this->conflictAddedMap = array();
357+
$this->addedPackages = array();
358+
$this->addedPackagesByNames = array();
330359
foreach ($this->installedMap as $package) {
331360
$this->addRulesForPackage($package, $ignorePlatformReqs);
332361
}
333362

334363
$this->addRulesForJobs($ignorePlatformReqs);
335364

365+
$this->addConflictRules();
366+
367+
// Remove references to packages
368+
$this->addedPackages = $this->addedPackagesByNames = null;
369+
336370
return $this->rules;
337371
}
338372
}

src/Composer/Repository/Vcs/GitHubDriver.php

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -183,30 +183,13 @@ public function getFileContent($file, $identifier)
183183
return $this->gitDriver->getFileContent($file, $identifier);
184184
}
185185

186-
$notFoundRetries = 2;
187-
while ($notFoundRetries) {
188-
try {
189-
$resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier);
190-
$resource = JsonFile::parseJson($this->getContents($resource));
191-
if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) {
192-
throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier);
193-
}
194-
195-
return $content;
196-
} catch (TransportException $e) {
197-
if (404 !== $e->getCode()) {
198-
throw $e;
199-
}
200-
201-
// TODO should be removed when possible
202-
// retry fetching if github returns a 404 since they happen randomly
203-
$notFoundRetries--;
204-
205-
return null;
206-
}
186+
$resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier);
187+
$resource = JsonFile::parseJson($this->getContents($resource));
188+
if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) {
189+
throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier);
207190
}
208191

209-
return null;
192+
return $content;
210193
}
211194

212195
/**
@@ -378,7 +361,7 @@ protected function getContents($url, $fetchingRepoData = false)
378361
return $this->attemptCloneFallback();
379362
}
380363

381-
$rateLimited = $githubUtil->isRateLimited($e->getHeaders());
364+
$rateLimited = $gitHubUtil->isRateLimited($e->getHeaders());
382365

383366
if (!$this->io->hasAuthentication($this->originUrl)) {
384367
if (!$this->io->isInteractive()) {
@@ -392,7 +375,7 @@ protected function getContents($url, $fetchingRepoData = false)
392375
}
393376

394377
if ($rateLimited) {
395-
$rateLimit = $githubUtil->getRateLimit($e->getHeaders());
378+
$rateLimit = $gitHubUtil->getRateLimit($e->getHeaders());
396379
$this->io->writeError(sprintf(
397380
'<error>GitHub API limit (%d calls/hr) is exhausted. You are already authorized so you have to wait until %s before doing more requests</error>',
398381
$rateLimit['limit'],

tests/Composer/Test/Fixtures/installer/replaced-packages-wrong-version-install.test renamed to tests/Composer/Test/Fixtures/installer/replaced-packages-should-not-be-installed-when-installing-from-lock.test

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Requiring a replaced package in a version, that is not provided by the replacing package, should install correctly (although that is not a very smart idea)
2+
Requiring a replaced package in a version, that is not provided by the replacing package, should result in a conflict, when installing from lock
33
--COMPOSER--
44
{
55
"repositories": [
@@ -17,9 +17,7 @@ Requiring a replaced package in a version, that is not provided by the replacing
1717
"foo/replaced": "2.0.0"
1818
}
1919
}
20-
--RUN--
21-
install
22-
--EXPECT-LOCK--
20+
--LOCK--
2321
{
2422
"packages": [
2523
{ "name": "foo/original", "version": "1.0.0", "replace": {"foo/replaced": "1.0.0"}, "type": "library" },
@@ -34,8 +32,8 @@ install
3432
"platform": [],
3533
"platform-dev": []
3634
}
35+
--RUN--
36+
install
3737
--EXPECT-EXIT-CODE--
38-
0
38+
2
3939
--EXPECT--
40-
Installing foo/original (1.0.0)
41-
Installing foo/replaced (2.0.0)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
Requiring a replaced package in a version, that is not provided by the replacing package, should result in a conflict
3+
--COMPOSER--
4+
{
5+
"repositories": [
6+
{
7+
"type": "package",
8+
"package": [
9+
{ "name": "foo/original", "version": "1.0.0", "replace": {"foo/replaced": "1.0.0"} },
10+
{ "name": "foo/replaced", "version": "1.0.0" },
11+
{ "name": "foo/replaced", "version": "2.0.0" }
12+
]
13+
}
14+
],
15+
"require": {
16+
"foo/original": "1.0.0",
17+
"foo/replaced": "2.0.0"
18+
}
19+
}
20+
--RUN--
21+
install
22+
--EXPECT-EXIT-CODE--
23+
2
24+
--EXPECT--

tests/Composer/Test/Fixtures/installer/replaced-packages-wrong-version-install-from-lock.test

Lines changed: 0 additions & 41 deletions
This file was deleted.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy