commit
cb68fc3134
|
@ -13,7 +13,9 @@
|
||||||
namespace Composer\DependencyResolver;
|
namespace Composer\DependencyResolver;
|
||||||
|
|
||||||
use Composer\Package\CompletePackageInterface;
|
use Composer\Package\CompletePackageInterface;
|
||||||
|
use Composer\Package\AliasPackage;
|
||||||
use Composer\Repository\RepositorySet;
|
use Composer\Repository\RepositorySet;
|
||||||
|
use Composer\Repository\LockArrayRepository;
|
||||||
use Composer\Semver\Constraint\Constraint;
|
use Composer\Semver\Constraint\Constraint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,7 +98,7 @@ class Problem
|
||||||
$messages[] = $rule->getPrettyString($repositorySet, $request, $pool, $installedMap, $learnedPool);
|
$messages[] = $rule->getPrettyString($repositorySet, $request, $pool, $installedMap, $learnedPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
return "\n - ".implode("\n - ", $messages);
|
return "\n - ".implode("\n - ", array_unique($messages));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isCausedByLock()
|
public function isCausedByLock()
|
||||||
|
@ -221,6 +223,14 @@ class Problem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$nonLockedPackages = array_filter($packages, function ($p) {
|
||||||
|
return !$p->getRepository() instanceof LockArrayRepository;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!$nonLockedPackages) {
|
||||||
|
return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages).' in lock file but not in remote repositories, make sure you avoid updating this package to keep the one from lock file.');
|
||||||
|
}
|
||||||
|
|
||||||
return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages).' but '.(self::hasMultipleNames($packages) ? 'these conflict' : 'it conflicts').' with another require.');
|
return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages).' but '.(self::hasMultipleNames($packages) ? 'these conflict' : 'it conflicts').' with another require.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,7 +291,7 @@ class Problem
|
||||||
$prepared = array();
|
$prepared = array();
|
||||||
foreach ($packages as $package) {
|
foreach ($packages as $package) {
|
||||||
$prepared[$package->getName()]['name'] = $package->getPrettyName();
|
$prepared[$package->getName()]['name'] = $package->getPrettyName();
|
||||||
$prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
|
$prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion().($package instanceof AliasPackage ? ' (alias of '.$package->getAliasOf()->getPrettyVersion().')' : '');
|
||||||
}
|
}
|
||||||
foreach ($prepared as $name => $package) {
|
foreach ($prepared as $name => $package) {
|
||||||
// remove the implicit dev-master alias to avoid cruft in the display
|
// remove the implicit dev-master alias to avoid cruft in the display
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace Composer\DependencyResolver;
|
||||||
use Composer\Package\CompletePackage;
|
use Composer\Package\CompletePackage;
|
||||||
use Composer\Package\Link;
|
use Composer\Package\Link;
|
||||||
use Composer\Package\PackageInterface;
|
use Composer\Package\PackageInterface;
|
||||||
|
use Composer\Package\AliasPackage;
|
||||||
use Composer\Repository\RepositorySet;
|
use Composer\Repository\RepositorySet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -153,7 +154,7 @@ abstract class Rule
|
||||||
return 'Root composer.json requires '.$packageName.($constraint ? ' '.$constraint->getPrettyString() : '').' -> satisfiable by '.$this->formatPackagesUnique($pool, $packages).'.';
|
return 'Root composer.json requires '.$packageName.($constraint ? ' '.$constraint->getPrettyString() : '').' -> satisfiable by '.$this->formatPackagesUnique($pool, $packages).'.';
|
||||||
|
|
||||||
case self::RULE_FIXED:
|
case self::RULE_FIXED:
|
||||||
$package = $this->reasonData['package'];
|
$package = $this->deduplicateMasterAlias($this->reasonData['package']);
|
||||||
if ($this->reasonData['lockable']) {
|
if ($this->reasonData['lockable']) {
|
||||||
return $package->getPrettyName().' is locked to version '.$package->getPrettyVersion().' and an update of this package was not requested.';
|
return $package->getPrettyName().' is locked to version '.$package->getPrettyVersion().' and an update of this package was not requested.';
|
||||||
}
|
}
|
||||||
|
@ -161,14 +162,14 @@ abstract class Rule
|
||||||
return $package->getPrettyName().' is present at version '.$package->getPrettyVersion() . ' and cannot be modified by Composer';
|
return $package->getPrettyName().' is present at version '.$package->getPrettyVersion() . ' and cannot be modified by Composer';
|
||||||
|
|
||||||
case self::RULE_PACKAGE_CONFLICT:
|
case self::RULE_PACKAGE_CONFLICT:
|
||||||
$package1 = $pool->literalToPackage($literals[0]);
|
$package1 = $this->deduplicateMasterAlias($pool->literalToPackage($literals[0]));
|
||||||
$package2 = $pool->literalToPackage($literals[1]);
|
$package2 = $this->deduplicateMasterAlias($pool->literalToPackage($literals[1]));
|
||||||
|
|
||||||
return $package2->getPrettyString().' conflicts with '.$package1->getPrettyString().'.';
|
return $package2->getPrettyString().' conflicts with '.$package1->getPrettyString().'.';
|
||||||
|
|
||||||
case self::RULE_PACKAGE_REQUIRES:
|
case self::RULE_PACKAGE_REQUIRES:
|
||||||
$sourceLiteral = array_shift($literals);
|
$sourceLiteral = array_shift($literals);
|
||||||
$sourcePackage = $pool->literalToPackage($sourceLiteral);
|
$sourcePackage = $this->deduplicateMasterAlias($pool->literalToPackage($sourceLiteral));
|
||||||
|
|
||||||
$requires = array();
|
$requires = array();
|
||||||
foreach ($literals as $literal) {
|
foreach ($literals as $literal) {
|
||||||
|
@ -279,4 +280,13 @@ abstract class Rule
|
||||||
|
|
||||||
return $names;
|
return $names;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function deduplicateMasterAlias(PackageInterface $package)
|
||||||
|
{
|
||||||
|
if ($package instanceof AliasPackage && $package->getPrettyVersion() === '9999999-dev') {
|
||||||
|
$package = $package->getAliasOf();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $package;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,11 +34,12 @@ class SolverProblemsException extends \RuntimeException
|
||||||
public function getPrettyString(RepositorySet $repositorySet, Request $request, Pool $pool, $isDevExtraction = false)
|
public function getPrettyString(RepositorySet $repositorySet, Request $request, Pool $pool, $isDevExtraction = false)
|
||||||
{
|
{
|
||||||
$installedMap = $request->getPresentMap(true);
|
$installedMap = $request->getPresentMap(true);
|
||||||
$text = "\n";
|
|
||||||
$hasExtensionProblems = false;
|
$hasExtensionProblems = false;
|
||||||
$isCausedByLock = false;
|
$isCausedByLock = false;
|
||||||
foreach ($this->problems as $i => $problem) {
|
|
||||||
$text .= " Problem ".($i + 1).$problem->getPrettyString($repositorySet, $request, $pool, $installedMap, $this->learnedPool)."\n";
|
$problems = array();
|
||||||
|
foreach ($this->problems as $problem) {
|
||||||
|
$problems[] = $problem->getPrettyString($repositorySet, $request, $pool, $installedMap, $this->learnedPool)."\n";
|
||||||
|
|
||||||
if (!$hasExtensionProblems && $this->hasExtensionProblems($problem->getReasons())) {
|
if (!$hasExtensionProblems && $this->hasExtensionProblems($problem->getReasons())) {
|
||||||
$hasExtensionProblems = true;
|
$hasExtensionProblems = true;
|
||||||
|
@ -47,6 +48,12 @@ class SolverProblemsException extends \RuntimeException
|
||||||
$isCausedByLock |= $problem->isCausedByLock();
|
$isCausedByLock |= $problem->isCausedByLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$i = 1;
|
||||||
|
$text = "\n";
|
||||||
|
foreach (array_unique($problems) as $problem) {
|
||||||
|
$text .= " Problem ".($i++).$problem;
|
||||||
|
}
|
||||||
|
|
||||||
if (!$isDevExtraction && (strpos($text, 'could not be found') || strpos($text, 'no matching package found'))) {
|
if (!$isDevExtraction && (strpos($text, 'could not be found') || strpos($text, 'no matching package found'))) {
|
||||||
$text .= "\nPotential causes:\n - A typo in the package name\n - The package is not available in a stable-enough version according to your minimum-stability setting\n see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.\n - It's a private package and you forgot to add a custom repository to find it\n\nRead <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.";
|
$text .= "\nPotential causes:\n - A typo in the package name\n - The package is not available in a stable-enough version according to your minimum-stability setting\n see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.\n - It's a private package and you forgot to add a custom repository to find it\n\nRead <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.";
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,19 +173,27 @@ class AliasPackage extends BasePackage implements CompletePackageInterface
|
||||||
*/
|
*/
|
||||||
protected function replaceSelfVersionDependencies(array $links, $linkType)
|
protected function replaceSelfVersionDependencies(array $links, $linkType)
|
||||||
{
|
{
|
||||||
|
// for self.version requirements, we use the original package's branch name instead of 9999999-dev, to avoid leaking 9999999-dev to users
|
||||||
|
$prettyVersion = $this->prettyVersion;
|
||||||
|
if ($prettyVersion === '9999999-dev') {
|
||||||
|
$prettyVersion = $this->aliasOf->getPrettyVersion();
|
||||||
|
}
|
||||||
|
|
||||||
if (in_array($linkType, array('conflicts', 'provides', 'replaces'), true)) {
|
if (in_array($linkType, array('conflicts', 'provides', 'replaces'), true)) {
|
||||||
$newLinks = array();
|
$newLinks = array();
|
||||||
foreach ($links as $link) {
|
foreach ($links as $link) {
|
||||||
// link is self.version, but must be replacing also the replaced version
|
// link is self.version, but must be replacing also the replaced version
|
||||||
if ('self.version' === $link->getPrettyConstraint()) {
|
if ('self.version' === $link->getPrettyConstraint()) {
|
||||||
$newLinks[] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
|
$newLinks[] = new Link($link->getSource(), $link->getTarget(), $constraint = new Constraint('=', $this->version), $linkType, $prettyVersion);
|
||||||
|
$constraint->setPrettyString($prettyVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$links = array_merge($links, $newLinks);
|
$links = array_merge($links, $newLinks);
|
||||||
} else {
|
} else {
|
||||||
foreach ($links as $index => $link) {
|
foreach ($links as $index => $link) {
|
||||||
if ('self.version' === $link->getPrettyConstraint()) {
|
if ('self.version' === $link->getPrettyConstraint()) {
|
||||||
$links[$index] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
|
$links[$index] = new Link($link->getSource(), $link->getTarget(), $constraint = new Constraint('=', $this->version), $linkType, $prettyVersion);
|
||||||
|
$constraint->setPrettyString($prettyVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -247,11 +247,13 @@ class ArrayLoader implements LoaderInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($aliasNormalized = $this->getBranchAlias($config)) {
|
if ($aliasNormalized = $this->getBranchAlias($config)) {
|
||||||
|
$prettyAlias = preg_replace('{(\.9{7})+}', '.x', $aliasNormalized);
|
||||||
|
|
||||||
if ($package instanceof RootPackageInterface) {
|
if ($package instanceof RootPackageInterface) {
|
||||||
return new RootAliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
|
return new RootAliasPackage($package, $aliasNormalized, $prettyAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new AliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
|
return new AliasPackage($package, $aliasNormalized, $prettyAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $package;
|
return $package;
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
--TEST--
|
||||||
|
Test the error output of solver problems with dev-master aliases.
|
||||||
|
--COMPOSER--
|
||||||
|
{
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "package",
|
||||||
|
"package": [
|
||||||
|
{"name": "a/a", "version": "dev-master", "require": {"d/d": "1.0.0"}},
|
||||||
|
{"name": "b/b", "version": "dev-master", "require": {"d/d": "2.0.0"}},
|
||||||
|
{"name": "d/d", "version": "1.0.0"},
|
||||||
|
{"name": "d/d", "version": "2.0.0"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"a/a": "*@dev",
|
||||||
|
"b/b": "*@dev"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--LOCK--
|
||||||
|
{
|
||||||
|
"packages": [
|
||||||
|
],
|
||||||
|
"packages-dev": [],
|
||||||
|
"aliases": [],
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"stability-flags": [],
|
||||||
|
"prefer-stable": false,
|
||||||
|
"prefer-lowest": false,
|
||||||
|
"platform": [],
|
||||||
|
"platform-dev": []
|
||||||
|
}
|
||||||
|
|
||||||
|
--RUN--
|
||||||
|
update a/a b/b
|
||||||
|
|
||||||
|
--EXPECT-EXIT-CODE--
|
||||||
|
2
|
||||||
|
|
||||||
|
--EXPECT-OUTPUT--
|
||||||
|
Loading composer repositories with package information
|
||||||
|
Updating dependencies
|
||||||
|
Your requirements could not be resolved to an installable set of packages.
|
||||||
|
|
||||||
|
Problem 1
|
||||||
|
- Root composer.json requires b/b *@dev -> satisfiable by b/b[dev-master].
|
||||||
|
- a/a dev-master requires d/d 1.0.0 -> satisfiable by d/d[1.0.0].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: d/d[2.0.0, 1.0.0].
|
||||||
|
- Conclusion: install d/d 2.0.0, learned rules:
|
||||||
|
- Root composer.json requires b/b *@dev -> satisfiable by b/b[dev-master].
|
||||||
|
- b/b dev-master requires d/d 2.0.0 -> satisfiable by d/d[2.0.0].
|
||||||
|
- Root composer.json requires a/a *@dev -> satisfiable by a/a[dev-master].
|
||||||
|
|
||||||
|
--EXPECT--
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
--TEST--
|
||||||
|
Test the error output of solver problems with dev-master aliases.
|
||||||
|
--COMPOSER--
|
||||||
|
{
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "package",
|
||||||
|
"package": [
|
||||||
|
{ "name": "locked/pkg", "version": "dev-master", "require": {"locked/dependency": "1.0.0"} }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"locked/pkg": "*@dev"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--LOCK--
|
||||||
|
{
|
||||||
|
"packages": [
|
||||||
|
{ "name": "locked/pkg", "version": "dev-master", "require": {"locked/dependency": "1.0.0"} },
|
||||||
|
{ "name": "locked/dependency", "version": "1.0.0" }
|
||||||
|
],
|
||||||
|
"packages-dev": [],
|
||||||
|
"aliases": [],
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"stability-flags": [],
|
||||||
|
"prefer-stable": false,
|
||||||
|
"prefer-lowest": false,
|
||||||
|
"platform": [],
|
||||||
|
"platform-dev": []
|
||||||
|
}
|
||||||
|
|
||||||
|
--RUN--
|
||||||
|
update locked/dependency
|
||||||
|
|
||||||
|
--EXPECT-EXIT-CODE--
|
||||||
|
2
|
||||||
|
|
||||||
|
--EXPECT-OUTPUT--
|
||||||
|
Loading composer repositories with package information
|
||||||
|
Updating dependencies
|
||||||
|
Your requirements could not be resolved to an installable set of packages.
|
||||||
|
|
||||||
|
Problem 1
|
||||||
|
- locked/pkg is locked to version dev-master and an update of this package was not requested.
|
||||||
|
- locked/pkg dev-master requires locked/dependency 1.0.0 -> found locked/dependency[1.0.0] in lock file but not in remote repositories, make sure you avoid updating this package to keep the one from lock file.
|
||||||
|
Problem 2
|
||||||
|
- locked/pkg dev-master requires locked/dependency 1.0.0 -> found locked/dependency[1.0.0] in lock file but not in remote repositories, make sure you avoid updating this package to keep the one from lock file.
|
||||||
|
- Root composer.json requires locked/pkg *@dev -> satisfiable by locked/pkg[dev-master].
|
||||||
|
|
||||||
|
Use the option --with-all-dependencies to allow updates and removals for packages currently locked to specific versions.
|
||||||
|
--EXPECT--
|
||||||
|
|
Loading…
Reference in New Issue