parent
f611c641db
commit
3fc7e10c5c
|
@ -89,7 +89,7 @@ class BaseDependencyCommand extends BaseCommand
|
|||
);
|
||||
|
||||
// Find packages that are or provide the requested package first
|
||||
$packages = $repositorySet->findPackages(strtolower($needle), null, false);
|
||||
$packages = $repositorySet->findPackages(strtolower($needle), null, RepositorySet::ALLOW_PROVIDERS_REPLACERS);
|
||||
if (empty($packages)) {
|
||||
throw new \InvalidArgumentException(sprintf('Could not find package "%s" in your project', $needle));
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ class PoolBuilder
|
|||
private $stabilityFlags;
|
||||
private $rootAliases;
|
||||
private $rootReferences;
|
||||
private $rootRequires;
|
||||
|
||||
private $aliasMap = array();
|
||||
private $nameConstraints = array();
|
||||
|
@ -39,13 +38,12 @@ class PoolBuilder
|
|||
private $packages = array();
|
||||
private $unacceptableFixedPackages = array();
|
||||
|
||||
public function __construct(array $acceptableStabilities, array $stabilityFlags, array $rootAliases, array $rootReferences, array $rootRequires = array())
|
||||
public function __construct(array $acceptableStabilities, array $stabilityFlags, array $rootAliases, array $rootReferences)
|
||||
{
|
||||
$this->acceptableStabilities = $acceptableStabilities;
|
||||
$this->stabilityFlags = $stabilityFlags;
|
||||
$this->rootAliases = $rootAliases;
|
||||
$this->rootReferences = $rootReferences;
|
||||
$this->rootRequires = $rootRequires;
|
||||
}
|
||||
|
||||
public function buildPool(array $repositories, Request $request)
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
namespace Composer\DependencyResolver;
|
||||
|
||||
use Composer\Package\CompletePackageInterface;
|
||||
use Composer\Repository\RepositorySet;
|
||||
use Composer\Semver\Constraint\Constraint;
|
||||
|
||||
/**
|
||||
* Represents a problem detected while solving dependencies
|
||||
|
@ -35,13 +37,6 @@ class Problem
|
|||
|
||||
protected $section = 0;
|
||||
|
||||
protected $pool;
|
||||
|
||||
public function __construct(Pool $pool)
|
||||
{
|
||||
$this->pool = $pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a rule as a reason
|
||||
*
|
||||
|
@ -68,7 +63,7 @@ class Problem
|
|||
* @param array $installedMap A map of all present packages
|
||||
* @return string
|
||||
*/
|
||||
public function getPrettyString(array $installedMap = array(), array $learnedPool = array())
|
||||
public function getPrettyString(RepositorySet $repositorySet, Request $request, array $installedMap = array(), array $learnedPool = array())
|
||||
{
|
||||
// TODO doesn't this entirely defeat the purpose of the problem sections? what's the point of sections?
|
||||
$reasons = call_user_func_array('array_merge', array_reverse($this->reasons));
|
||||
|
@ -81,91 +76,25 @@ class Problem
|
|||
throw new \LogicException("Single reason problems must contain a request rule.");
|
||||
}
|
||||
|
||||
$request = $rule->getReasonData();
|
||||
$packageName = $request['packageName'];
|
||||
$constraint = $request['constraint'];
|
||||
$reasonData = $rule->getReasonData();
|
||||
$packageName = $reasonData['packageName'];
|
||||
$constraint = $reasonData['constraint'];
|
||||
|
||||
if (isset($constraint)) {
|
||||
$packages = $this->pool->whatProvides($packageName, $constraint);
|
||||
$packages = $repositorySet->getPool()->whatProvides($packageName, $constraint);
|
||||
} else {
|
||||
$packages = array();
|
||||
}
|
||||
|
||||
if (empty($packages)) {
|
||||
// handle php/hhvm
|
||||
if ($packageName === 'php' || $packageName === 'php-64bit' || $packageName === 'hhvm') {
|
||||
$version = phpversion();
|
||||
$available = $this->pool->whatProvides($packageName);
|
||||
|
||||
if (count($available)) {
|
||||
$firstAvailable = reset($available);
|
||||
$version = $firstAvailable->getPrettyVersion();
|
||||
$extra = $firstAvailable->getExtra();
|
||||
if ($firstAvailable instanceof CompletePackageInterface && isset($extra['config.platform']) && $extra['config.platform'] === true) {
|
||||
$version .= '; ' . $firstAvailable->getDescription();
|
||||
}
|
||||
}
|
||||
|
||||
$msg = "\n - This package requires ".$packageName.$this->constraintToText($constraint).' but ';
|
||||
|
||||
if (defined('HHVM_VERSION') || (count($available) && $packageName === 'hhvm')) {
|
||||
return $msg . 'your HHVM version does not satisfy that requirement.';
|
||||
}
|
||||
|
||||
if ($packageName === 'hhvm') {
|
||||
return $msg . 'you are running this with PHP and not HHVM.';
|
||||
}
|
||||
|
||||
return $msg . 'your PHP version ('. $version .') does not satisfy that requirement.';
|
||||
}
|
||||
|
||||
// handle php extensions
|
||||
if (0 === stripos($packageName, 'ext-')) {
|
||||
if (false !== strpos($packageName, ' ')) {
|
||||
return "\n - The requested PHP extension ".$packageName.' should be required as '.str_replace(' ', '-', $packageName).'.';
|
||||
}
|
||||
|
||||
$ext = substr($packageName, 4);
|
||||
$error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
|
||||
|
||||
return "\n - The requested PHP extension ".$packageName.$this->constraintToText($constraint).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.';
|
||||
}
|
||||
|
||||
// handle linked libs
|
||||
if (0 === stripos($packageName, 'lib-')) {
|
||||
if (strtolower($packageName) === 'lib-icu') {
|
||||
$error = extension_loaded('intl') ? 'has the wrong version installed, try upgrading the intl extension.' : 'is missing from your system, make sure the intl extension is loaded.';
|
||||
|
||||
return "\n - The requested linked library ".$packageName.$this->constraintToText($constraint).' '.$error;
|
||||
}
|
||||
|
||||
return "\n - The requested linked library ".$packageName.$this->constraintToText($constraint).' has the wrong version installed or is missing from your system, make sure to load the extension providing it.';
|
||||
}
|
||||
|
||||
if (!preg_match('{^[A-Za-z0-9_./-]+$}', $packageName)) {
|
||||
$illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $packageName);
|
||||
|
||||
return "\n - The requested package ".$packageName.' could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.';
|
||||
}
|
||||
|
||||
// TODO: The pool doesn't know about these anymore, it has to ask the RepositorySet
|
||||
/*if ($providers = $this->pool->whatProvides($packageName, $constraint, true, true)) {
|
||||
return "\n - The requested package ".$packageName.$this->constraintToText($constraint).' is satisfiable by '.$this->getPackageList($providers).' but these conflict with your requirements or minimum-stability.';
|
||||
}*/
|
||||
|
||||
// TODO: The pool doesn't know about these anymore, it has to ask the RepositorySet
|
||||
/*if ($providers = $this->pool->whatProvides($packageName, null, true, true)) {
|
||||
return "\n - The requested package ".$packageName.$this->constraintToText($constraint).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.';
|
||||
}*/
|
||||
|
||||
return "\n - The requested package ".$packageName.' could not be found in any version, there may be a typo in the package name.';
|
||||
return "\n ".implode(self::getMissingPackageReason($repositorySet, $request, $packageName, $constraint));
|
||||
}
|
||||
}
|
||||
|
||||
$messages = array();
|
||||
|
||||
foreach ($reasons as $rule) {
|
||||
$messages[] = $rule->getPrettyString($this->pool, $installedMap, $learnedPool);
|
||||
$messages[] = $rule->getPrettyString($repositorySet, $request, $installedMap, $learnedPool);
|
||||
}
|
||||
|
||||
return "\n - ".implode("\n - ", $messages);
|
||||
|
@ -193,7 +122,141 @@ class Problem
|
|||
$this->section++;
|
||||
}
|
||||
|
||||
protected function getPackageList($packages)
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public static function getMissingPackageReason(RepositorySet $repositorySet, Request $request, $packageName, $constraint = null)
|
||||
{
|
||||
$pool = $repositorySet->getPool();
|
||||
|
||||
// handle php/hhvm
|
||||
if ($packageName === 'php' || $packageName === 'php-64bit' || $packageName === 'hhvm') {
|
||||
$version = phpversion();
|
||||
$available = $pool->whatProvides($packageName);
|
||||
|
||||
if (count($available)) {
|
||||
$firstAvailable = reset($available);
|
||||
$version = $firstAvailable->getPrettyVersion();
|
||||
$extra = $firstAvailable->getExtra();
|
||||
if ($firstAvailable instanceof CompletePackageInterface && isset($extra['config.platform']) && $extra['config.platform'] === true) {
|
||||
$version .= '; ' . str_replace('Package ', '', $firstAvailable->getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
$msg = "- Root composer.json requires ".$packageName.self::constraintToText($constraint).' but ';
|
||||
|
||||
if (defined('HHVM_VERSION') || (count($available) && $packageName === 'hhvm')) {
|
||||
return array($msg, 'your HHVM version does not satisfy that requirement.');
|
||||
}
|
||||
|
||||
if ($packageName === 'hhvm') {
|
||||
return array($msg, 'you are running this with PHP and not HHVM.');
|
||||
}
|
||||
|
||||
return array($msg, 'your '.$packageName.' version ('. $version .') does not satisfy that requirement.');
|
||||
}
|
||||
|
||||
// handle php extensions
|
||||
if (0 === stripos($packageName, 'ext-')) {
|
||||
if (false !== strpos($packageName, ' ')) {
|
||||
return array('- ', "PHP extension ".$packageName.' should be required as '.str_replace(' ', '-', $packageName).'.');
|
||||
}
|
||||
|
||||
$ext = substr($packageName, 4);
|
||||
$error = extension_loaded($ext) ? 'it has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'it is missing from your system';
|
||||
|
||||
return array("- Root composer.json requires PHP extension ".$packageName.self::constraintToText($constraint).' but ', $error.'. Install or enable PHP\'s '.$ext.' extension.');
|
||||
}
|
||||
|
||||
// handle linked libs
|
||||
if (0 === stripos($packageName, 'lib-')) {
|
||||
if (strtolower($packageName) === 'lib-icu') {
|
||||
$error = extension_loaded('intl') ? 'it has the wrong version installed, try upgrading the intl extension.' : 'it is missing from your system, make sure the intl extension is loaded.';
|
||||
|
||||
return array("- Root composer.json requires linked library ".$packageName.self::constraintToText($constraint).' but ', $error);
|
||||
}
|
||||
|
||||
return array("- Root composer.json requires linked library ".$packageName.self::constraintToText($constraint).' but ', 'it has the wrong version installed or is missing from your system, make sure to load the extension providing it.');
|
||||
}
|
||||
|
||||
$fixedPackage = null;
|
||||
foreach ($request->getFixedPackages() as $package) {
|
||||
if ($package->getName() === $packageName) {
|
||||
$fixedPackage = $package;
|
||||
if ($pool->isUnacceptableFixedPackage($package)) {
|
||||
return array("- ", $package->getPrettyName().' is fixed to '.$package->getPrettyVersion().' (lock file version) by a partial update but that version is rejected by your minimum-stability. Make sure you whitelist it for update.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// first check if the actual requested package is found in normal conditions
|
||||
// if so it must mean it is rejected by another constraint than the one given here
|
||||
if ($packages = $repositorySet->findPackages($packageName, $constraint)) {
|
||||
$rootReqs = $repositorySet->getRootRequires();
|
||||
if (isset($rootReqs[$packageName])) {
|
||||
$filtered = array_filter($packages, function ($p) use ($rootReqs, $packageName) {
|
||||
return $rootReqs[$packageName]->matches(new Constraint('==', $p->getVersion()));
|
||||
});
|
||||
if (0 === count($filtered)) {
|
||||
return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages).' but '.(self::hasMultipleNames($packages) ? 'these conflict' : 'it conflicts').' with your root composer.json require ('.$rootReqs[$packageName]->getPrettyString().').');
|
||||
}
|
||||
}
|
||||
|
||||
if ($fixedPackage) {
|
||||
$fixedConstraint = new Constraint('==', $fixedPackage->getVersion());
|
||||
$filtered = array_filter($packages, function ($p) use ($fixedConstraint) {
|
||||
return $fixedConstraint->matches(new Constraint('==', $p->getVersion()));
|
||||
});
|
||||
if (0 === count($filtered)) {
|
||||
return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages).' but the package is fixed to '.$fixedPackage->getPrettyVersion().' (lock file version) by a partial update and that version does not match. Make sure you whitelist it for update.');
|
||||
}
|
||||
}
|
||||
|
||||
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.');
|
||||
}
|
||||
|
||||
// check if the package is found when bypassing stability checks
|
||||
if ($packages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES)) {
|
||||
return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages).' but '.(self::hasMultipleNames($packages) ? 'these do' : 'it does').' not match your minimum-stability.');
|
||||
}
|
||||
|
||||
// check if the package is found when bypassing the constraint check
|
||||
if ($packages = $repositorySet->findPackages($packageName, null)) {
|
||||
// we must first verify if a valid package would be found in a lower priority repository
|
||||
if ($allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES)) {
|
||||
$higherRepoPackages = $repositorySet->findPackages($packageName, null);
|
||||
$nextRepoPackages = array();
|
||||
$nextRepo = null;
|
||||
|
||||
foreach ($allReposPackages as $package) {
|
||||
if ($nextRepo === null || $nextRepo === $package->getRepository()) {
|
||||
$nextRepoPackages[] = $package;
|
||||
$nextRepo = $package->getRepository();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', it is ', 'satisfiable by '.self::getPackageList($nextRepoPackages).' from '.$nextRepo->getRepoName().' but '.self::getPackageList($higherRepoPackages).' from '.reset($higherRepoPackages)->getRepository()->getRepoName().' has higher repository priority. The packages with higher priority do not match your constraint and are therefore not installable.');
|
||||
}
|
||||
|
||||
return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages).' but '.(self::hasMultipleNames($packages) ? 'these do' : 'it does').' not match your constraint.');
|
||||
}
|
||||
|
||||
if (!preg_match('{^[A-Za-z0-9_./-]+$}', $packageName)) {
|
||||
$illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $packageName);
|
||||
|
||||
return array("- Root composer.json requires $packageName, it ", 'could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.');
|
||||
}
|
||||
|
||||
return array("- Root composer.json requires $packageName, it ", "could not be found in any version, there may be a typo in the package name.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public static function getPackageList(array $packages)
|
||||
{
|
||||
$prepared = array();
|
||||
foreach ($packages as $package) {
|
||||
|
@ -207,13 +270,27 @@ class Problem
|
|||
return implode(', ', $prepared);
|
||||
}
|
||||
|
||||
private static function hasMultipleNames(array $packages)
|
||||
{
|
||||
$name = null;
|
||||
foreach ($packages as $package) {
|
||||
if ($name === null || $name === $package->getName()) {
|
||||
$name = $package->getName();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a constraint into text usable in a sentence describing a request
|
||||
*
|
||||
* @param \Composer\Semver\Constraint\ConstraintInterface $constraint
|
||||
* @return string
|
||||
*/
|
||||
protected function constraintToText($constraint)
|
||||
protected static function constraintToText($constraint)
|
||||
{
|
||||
return $constraint ? ' '.$constraint->getPrettyString() : '';
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace Composer\DependencyResolver;
|
|||
use Composer\Package\CompletePackage;
|
||||
use Composer\Package\Link;
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\Repository\RepositorySet;
|
||||
|
||||
/**
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
|
@ -122,8 +123,9 @@ abstract class Rule
|
|||
|
||||
abstract public function isAssertion();
|
||||
|
||||
public function getPrettyString(Pool $pool, array $installedMap = array(), array $learnedPool = array())
|
||||
public function getPrettyString(RepositorySet $repositorySet, Request $request, array $installedMap = array(), array $learnedPool = array())
|
||||
{
|
||||
$pool = $repositorySet->getPool();
|
||||
$literals = $this->getLiterals();
|
||||
|
||||
$ruleText = '';
|
||||
|
@ -178,60 +180,9 @@ abstract class Rule
|
|||
} else {
|
||||
$targetName = $this->reasonData->getTarget();
|
||||
|
||||
if ($targetName === 'php' || $targetName === 'php-64bit' || $targetName === 'hhvm') {
|
||||
// handle php/hhvm
|
||||
if (defined('HHVM_VERSION')) {
|
||||
return $text . ' -> your HHVM version does not satisfy that requirement.';
|
||||
}
|
||||
$reason = Problem::getMissingPackageReason($repositorySet, $request, $targetName, $this->reasonData->getConstraint());
|
||||
|
||||
$packages = $pool->whatProvides($targetName);
|
||||
$package = count($packages) ? current($packages) : phpversion();
|
||||
|
||||
if ($targetName === 'hhvm') {
|
||||
if ($package instanceof CompletePackage) {
|
||||
return $text . ' -> your HHVM version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
|
||||
} else {
|
||||
return $text . ' -> you are running this with PHP and not HHVM.';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!($package instanceof CompletePackage)) {
|
||||
return $text . ' -> your PHP version ('.phpversion().') does not satisfy that requirement.';
|
||||
}
|
||||
|
||||
$extra = $package->getExtra();
|
||||
|
||||
if (!empty($extra['config.platform'])) {
|
||||
$text .= ' -> your PHP version ('.phpversion().') overridden by "config.platform.php" version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
|
||||
} else {
|
||||
$text .= ' -> your PHP version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
if (0 === strpos($targetName, 'ext-')) {
|
||||
// handle php extensions
|
||||
$ext = substr($targetName, 4);
|
||||
$error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
|
||||
|
||||
return $text . ' -> the requested PHP extension '.$ext.' '.$error.'.';
|
||||
}
|
||||
|
||||
if (0 === strpos($targetName, 'lib-')) {
|
||||
// handle linked libs
|
||||
$lib = substr($targetName, 4);
|
||||
|
||||
return $text . ' -> the requested linked library '.$lib.' has the wrong version installed or is missing from your system, make sure to have the extension providing it.';
|
||||
}
|
||||
|
||||
// TODO: The pool doesn't know about these anymore, it has to ask the RepositorySet
|
||||
/*if ($providers = $pool->whatProvides($targetName, $this->reasonData->getConstraint(), true, true)) {
|
||||
return $text . ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $providers) .' but these conflict with your requirements or minimum-stability.';
|
||||
}*/
|
||||
|
||||
return $text . ' -> no matching package found.';
|
||||
return $text . ' -> ' . $reason[1];
|
||||
}
|
||||
|
||||
return $text;
|
||||
|
@ -249,7 +200,7 @@ abstract class Rule
|
|||
$learnedString = '(learned rule, ';
|
||||
if (isset($learnedPool[$this->reasonData])) {
|
||||
foreach ($learnedPool[$this->reasonData] as $learnedRule) {
|
||||
$learnedString .= $learnedRule->getPrettyString($pool, $installedMap, $learnedPool);
|
||||
$learnedString .= $learnedRule->getPrettyString($repositorySet, $request, $installedMap, $learnedPool);
|
||||
}
|
||||
} else {
|
||||
$learnedString .= 'reasoning unavailable';
|
||||
|
@ -272,20 +223,13 @@ abstract class Rule
|
|||
*/
|
||||
protected function formatPackagesUnique($pool, array $packages)
|
||||
{
|
||||
// TODO this is essentially a duplicate of Problem: getPackageList, maintain in one place only?
|
||||
|
||||
$prepared = array();
|
||||
foreach ($packages as $package) {
|
||||
foreach ($packages as $index => $package) {
|
||||
if (!is_object($package)) {
|
||||
$package = $pool->literalToPackage($package);
|
||||
$packages[$index] = $pool->literalToPackage($package);
|
||||
}
|
||||
$prepared[$package->getName()]['name'] = $package->getPrettyName();
|
||||
$prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
|
||||
}
|
||||
foreach ($prepared as $name => $package) {
|
||||
$prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
|
||||
}
|
||||
|
||||
return implode(', ', $prepared);
|
||||
return Problem::getPackageList($packages);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
namespace Composer\DependencyResolver;
|
||||
|
||||
use Composer\Repository\RepositorySet;
|
||||
|
||||
/**
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
*/
|
||||
|
@ -155,13 +157,13 @@ class RuleSet implements \IteratorAggregate, \Countable
|
|||
return array_keys($types);
|
||||
}
|
||||
|
||||
public function getPrettyString(Pool $pool = null)
|
||||
public function getPrettyString(RepositorySet $repositorySet = null, Request $request = null)
|
||||
{
|
||||
$string = "\n";
|
||||
foreach ($this->rules as $type => $rules) {
|
||||
$string .= str_pad(self::$types[$type], 8, ' ') . ": ";
|
||||
foreach ($rules as $rule) {
|
||||
$string .= ($pool ? $rule->getPrettyString($pool) : $rule)."\n";
|
||||
$string .= ($repositorySet && $request ? $rule->getPrettyString($repositorySet, $request) : $rule)."\n";
|
||||
}
|
||||
$string .= "\n\n";
|
||||
}
|
||||
|
@ -171,6 +173,6 @@ class RuleSet implements \IteratorAggregate, \Countable
|
|||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getPrettyString(null);
|
||||
return $this->getPrettyString(null, null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,9 @@ class Solver
|
|||
/** @var PolicyInterface */
|
||||
protected $policy;
|
||||
/** @var Pool */
|
||||
protected $pool = null;
|
||||
protected $pool;
|
||||
/** @var RepositorySet */
|
||||
protected $repositorySet;
|
||||
|
||||
/** @var RuleSet */
|
||||
protected $rules;
|
||||
|
@ -65,11 +67,12 @@ class Solver
|
|||
* @param Pool $pool
|
||||
* @param IOInterface $io
|
||||
*/
|
||||
public function __construct(PolicyInterface $policy, Pool $pool, IOInterface $io)
|
||||
public function __construct(PolicyInterface $policy, Pool $pool, IOInterface $io, RepositorySet $repositorySet)
|
||||
{
|
||||
$this->io = $io;
|
||||
$this->policy = $policy;
|
||||
$this->pool = $pool;
|
||||
$this->repositorySet = $repositorySet;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,6 +88,11 @@ class Solver
|
|||
return $this->pool;
|
||||
}
|
||||
|
||||
public function getRepositorySet()
|
||||
{
|
||||
return $this->repositorySet;
|
||||
}
|
||||
|
||||
// aka solver_makeruledecisions
|
||||
|
||||
private function makeAssertionRuleDecisions()
|
||||
|
@ -120,7 +128,7 @@ class Solver
|
|||
$conflict = $this->decisions->decisionRule($literal);
|
||||
|
||||
if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) {
|
||||
$problem = new Problem($this->pool);
|
||||
$problem = new Problem();
|
||||
|
||||
$problem->addRule($rule);
|
||||
$problem->addRule($conflict);
|
||||
|
@ -130,7 +138,7 @@ class Solver
|
|||
}
|
||||
|
||||
// conflict with another root require/fixed package
|
||||
$problem = new Problem($this->pool);
|
||||
$problem = new Problem();
|
||||
$problem->addRule($rule);
|
||||
$problem->addRule($conflict);
|
||||
|
||||
|
@ -177,7 +185,7 @@ class Solver
|
|||
}
|
||||
|
||||
if (!$this->pool->whatProvides($packageName, $constraint)) {
|
||||
$problem = new Problem($this->pool);
|
||||
$problem = new Problem();
|
||||
$problem->addRule(new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => $packageName, 'constraint' => $constraint)));
|
||||
$this->problems[] = $problem;
|
||||
}
|
||||
|
@ -214,7 +222,7 @@ class Solver
|
|||
$this->io->writeError(sprintf('Dependency resolution completed in %.3f seconds', microtime(true) - $before), true, IOInterface::VERBOSE);
|
||||
|
||||
if ($this->problems) {
|
||||
throw new SolverProblemsException($this->problems, $request->getPresentMap(true), $this->learnedPool);
|
||||
throw new SolverProblemsException($this->problems, $this->repositorySet, $request, $this->learnedPool);
|
||||
}
|
||||
|
||||
return new LockTransaction($this->pool, $request->getPresentMap(), $request->getUnlockableMap(), $this->decisions);
|
||||
|
@ -513,7 +521,7 @@ class Solver
|
|||
*/
|
||||
private function analyzeUnsolvable(Rule $conflictRule)
|
||||
{
|
||||
$problem = new Problem($this->pool);
|
||||
$problem = new Problem();
|
||||
$problem->addRule($conflictRule);
|
||||
|
||||
$this->analyzeUnsolvableRule($problem, $conflictRule);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
namespace Composer\DependencyResolver;
|
||||
|
||||
use Composer\Util\IniHelper;
|
||||
use Composer\Repository\RepositorySet;
|
||||
|
||||
/**
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
|
@ -23,21 +24,21 @@ class SolverProblemsException extends \RuntimeException
|
|||
protected $installedMap;
|
||||
protected $learnedPool;
|
||||
|
||||
public function __construct(array $problems, array $installedMap, array $learnedPool)
|
||||
public function __construct(array $problems, RepositorySet $repositorySet, Request $request, array $learnedPool)
|
||||
{
|
||||
$this->problems = $problems;
|
||||
$this->installedMap = $installedMap;
|
||||
$this->installedMap = $request->getPresentMap(true);
|
||||
$this->learnedPool = $learnedPool;
|
||||
|
||||
parent::__construct($this->createMessage(), 2);
|
||||
parent::__construct($this->createMessage($repositorySet, $request), 2);
|
||||
}
|
||||
|
||||
protected function createMessage()
|
||||
protected function createMessage(RepositorySet $repositorySet, Request $request)
|
||||
{
|
||||
$text = "\n";
|
||||
$hasExtensionProblems = false;
|
||||
foreach ($this->problems as $i => $problem) {
|
||||
$text .= " Problem ".($i + 1).$problem->getPrettyString($this->installedMap, $this->learnedPool)."\n";
|
||||
$text .= " Problem ".($i + 1).$problem->getPrettyString($repositorySet, $request, $this->installedMap, $this->learnedPool)."\n";
|
||||
|
||||
if (!$hasExtensionProblems && $this->hasExtensionProblems($problem->getReasons())) {
|
||||
$hasExtensionProblems = true;
|
||||
|
|
|
@ -389,7 +389,7 @@ class Installer
|
|||
$pool = $repositorySet->createPool($request);
|
||||
|
||||
// solve dependencies
|
||||
$solver = new Solver($policy, $pool, $this->io);
|
||||
$solver = new Solver($policy, $pool, $this->io, $repositorySet);
|
||||
try {
|
||||
$lockTransaction = $solver->solve($request, $this->ignorePlatformReqs);
|
||||
$ruleSetSize = $solver->getRuleSetSize();
|
||||
|
@ -529,7 +529,7 @@ class Installer
|
|||
$pool = $repositorySet->createPool($request);
|
||||
|
||||
//$this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request);
|
||||
$solver = new Solver($policy, $pool, $this->io);
|
||||
$solver = new Solver($policy, $pool, $this->io, $repositorySet);
|
||||
try {
|
||||
$nonDevLockTransaction = $solver->solve($request, $this->ignorePlatformReqs);
|
||||
//$this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request, $ops);
|
||||
|
@ -589,7 +589,7 @@ class Installer
|
|||
$pool = $repositorySet->createPool($request);
|
||||
|
||||
// solve dependencies
|
||||
$solver = new Solver($policy, $pool, $this->io);
|
||||
$solver = new Solver($policy, $pool, $this->io, $repositorySet);
|
||||
try {
|
||||
$lockTransaction = $solver->solve($request, $this->ignorePlatformReqs);
|
||||
$solver = null;
|
||||
|
@ -884,7 +884,7 @@ class Installer
|
|||
$packageQueue = new \SplQueue;
|
||||
$nameMatchesRequiredPackage = false;
|
||||
|
||||
$depPackages = $repositorySet->findPackages($packageName, null, false);
|
||||
$depPackages = $repositorySet->findPackages($packageName, null, RepositorySet::ALLOW_PROVIDERS_REPLACERS);
|
||||
$matchesByPattern = array();
|
||||
|
||||
// check if the name is a glob pattern that did not match directly
|
||||
|
@ -892,7 +892,7 @@ class Installer
|
|||
// add any installed package matching the whitelisted name/pattern
|
||||
$whitelistPatternSearchRegexp = BasePackage::packageNameToRegexp($packageName, '^%s$');
|
||||
foreach ($lockRepo->search($whitelistPatternSearchRegexp) as $installedPackage) {
|
||||
$matchesByPattern[] = $repositorySet->findPackages($installedPackage['name'], null, false);
|
||||
$matchesByPattern[] = $repositorySet->findPackages($installedPackage['name'], null, RepositorySet::ALLOW_PROVIDERS_REPLACERS);
|
||||
}
|
||||
|
||||
// add root requirements which match the whitelisted name/pattern
|
||||
|
@ -933,7 +933,7 @@ class Installer
|
|||
$requires = $package->getRequires();
|
||||
|
||||
foreach ($requires as $require) {
|
||||
$requirePackages = $repositorySet->findPackages($require->getTarget(), null, false);
|
||||
$requirePackages = $repositorySet->findPackages($require->getTarget(), null, RepositorySet::ALLOW_PROVIDERS_REPLACERS);
|
||||
|
||||
foreach ($requirePackages as $requirePackage) {
|
||||
if (isset($this->updateWhitelist[$requirePackage->getName()])) {
|
||||
|
|
|
@ -412,7 +412,7 @@ class PluginManager
|
|||
*/
|
||||
private function lookupInstalledPackage(RepositorySet $repositorySet, Link $link)
|
||||
{
|
||||
$packages = $repositorySet->findPackages($link->getTarget(), $link->getConstraint(), false);
|
||||
$packages = $repositorySet->findPackages($link->getTarget(), $link->getConstraint(), RepositorySet::ALLOW_PROVIDERS_REPLACERS | RepositorySet::ALLOW_SHADOWED_REPOSITORIES);
|
||||
|
||||
return !empty($packages) ? $packages[0] : null;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,11 @@ class ArrayRepository extends BaseRepository
|
|||
}
|
||||
}
|
||||
|
||||
public function getRepoName()
|
||||
{
|
||||
return 'array repo (defining '.count($this->packages).' package'.(count($this->packages) > 1 ? 's' : '').')';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@ -57,7 +62,9 @@ class ArrayRepository extends BaseRepository
|
|||
(!$packageMap[$package->getName()] || $packageMap[$package->getName()]->matches(new Constraint('==', $package->getVersion())))
|
||||
&& StabilityFilter::isPackageAcceptable($acceptableStabilities, $stabilityFlags, $package->getNames(), $package->getStability())
|
||||
) {
|
||||
// add selected packages which match stability requirements
|
||||
$result[spl_object_hash($package)] = $package;
|
||||
// add the aliased package for packages where the alias matches
|
||||
if ($package instanceof AliasPackage && !isset($result[spl_object_hash($package->getAliasOf())])) {
|
||||
$result[spl_object_hash($package->getAliasOf())] = $package->getAliasOf();
|
||||
}
|
||||
|
@ -67,6 +74,7 @@ class ArrayRepository extends BaseRepository
|
|||
}
|
||||
}
|
||||
|
||||
// add aliases of packages that were selected, even if the aliases did not match
|
||||
foreach ($packages as $package) {
|
||||
if ($package instanceof AliasPackage) {
|
||||
if (isset($result[spl_object_hash($package->getAliasOf())])) {
|
||||
|
|
|
@ -43,6 +43,11 @@ class ArtifactRepository extends ArrayRepository implements ConfigurableReposito
|
|||
$this->repoConfig = $repoConfig;
|
||||
}
|
||||
|
||||
public function getRepoName()
|
||||
{
|
||||
return 'platform repo ('.$this->lookup.')';
|
||||
}
|
||||
|
||||
public function getRepoConfig()
|
||||
{
|
||||
return $this->repoConfig;
|
||||
|
|
|
@ -125,6 +125,11 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
|||
$this->loop = new Loop($this->httpDownloader);
|
||||
}
|
||||
|
||||
public function getRepoName()
|
||||
{
|
||||
return 'composer repo ('.$this->url.')';
|
||||
}
|
||||
|
||||
public function getRepoConfig()
|
||||
{
|
||||
return $this->repoConfig;
|
||||
|
|
|
@ -39,6 +39,11 @@ class CompositeRepository extends BaseRepository
|
|||
}
|
||||
}
|
||||
|
||||
public function getRepoName()
|
||||
{
|
||||
return 'composite repo ('.count($this->repositories).' repos)';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the wrapped repositories
|
||||
*
|
||||
|
|
|
@ -21,4 +21,8 @@ namespace Composer\Repository;
|
|||
*/
|
||||
class InstalledArrayRepository extends WritableArrayRepository implements InstalledRepositoryInterface
|
||||
{
|
||||
public function getRepoName()
|
||||
{
|
||||
return 'installed '.parent::getRepoName();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,4 +19,8 @@ namespace Composer\Repository;
|
|||
*/
|
||||
class InstalledFilesystemRepository extends FilesystemRepository implements InstalledRepositoryInterface
|
||||
{
|
||||
public function getRepoName()
|
||||
{
|
||||
return 'installed '.parent::getRepoName();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,5 +21,9 @@ namespace Composer\Repository;
|
|||
*/
|
||||
class LockArrayRepository extends ArrayRepository implements RepositoryInterface
|
||||
{
|
||||
public function getRepoName()
|
||||
{
|
||||
return 'lock '.parent::getRepoName();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,4 +58,9 @@ class PackageRepository extends ArrayRepository
|
|||
$this->addPackage($package);
|
||||
}
|
||||
}
|
||||
|
||||
public function getRepoName()
|
||||
{
|
||||
return preg_replace('{^array }', 'package ', parent::getRepoName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,6 +111,11 @@ class PathRepository extends ArrayRepository implements ConfigurableRepositoryIn
|
|||
parent::__construct();
|
||||
}
|
||||
|
||||
public function getRepoName()
|
||||
{
|
||||
return 'path repo ('.$this->repoConfig['url'].')';
|
||||
}
|
||||
|
||||
public function getRepoConfig()
|
||||
{
|
||||
return $this->repoConfig;
|
||||
|
|
|
@ -67,6 +67,11 @@ class PearRepository extends ArrayRepository implements ConfigurableRepositoryIn
|
|||
$this->repoConfig = $repoConfig;
|
||||
}
|
||||
|
||||
public function getRepoName()
|
||||
{
|
||||
return 'pear repo ('.$this->url.')';
|
||||
}
|
||||
|
||||
public function getRepoConfig()
|
||||
{
|
||||
return $this->repoConfig;
|
||||
|
|
|
@ -51,6 +51,11 @@ class PlatformRepository extends ArrayRepository
|
|||
parent::__construct($packages);
|
||||
}
|
||||
|
||||
public function getRepoName()
|
||||
{
|
||||
return 'platform repo';
|
||||
}
|
||||
|
||||
protected function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
|
@ -275,7 +280,7 @@ class PlatformRepository extends ArrayRepository
|
|||
} else {
|
||||
$actualText = 'actual: '.$package->getPrettyVersion();
|
||||
}
|
||||
$overrider->setDescription($overrider->getDescription().' ('.$actualText.')');
|
||||
$overrider->setDescription($overrider->getDescription().', '.$actualText);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -288,7 +293,7 @@ class PlatformRepository extends ArrayRepository
|
|||
} else {
|
||||
$actualText = 'actual: '.$package->getPrettyVersion();
|
||||
}
|
||||
$overrider->setDescription($overrider->getDescription().' ('.$actualText.')');
|
||||
$overrider->setDescription($overrider->getDescription().', '.$actualText);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -83,4 +83,13 @@ interface RepositoryInterface extends \Countable
|
|||
* @return array[] an array of array('name' => '...', 'description' => '...')
|
||||
*/
|
||||
public function search($query, $mode = 0, $type = null);
|
||||
|
||||
/**
|
||||
* Returns a name representing this repository to the user
|
||||
*
|
||||
* This is best effort and definitely can not always be very precise
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRepoName();
|
||||
}
|
||||
|
|
|
@ -29,6 +29,19 @@ use Composer\Package\Version\StabilityFilter;
|
|||
*/
|
||||
class RepositorySet
|
||||
{
|
||||
/**
|
||||
* Packages which replace/provide the given name might be returned as well even if they do not match the name exactly
|
||||
*/
|
||||
const ALLOW_PROVIDERS_REPLACERS = 1;
|
||||
/**
|
||||
* Packages are returned even though their stability does not match the required stability
|
||||
*/
|
||||
const ALLOW_UNACCEPTABLE_STABILITIES = 2;
|
||||
/**
|
||||
* Packages will be looked up in all repositories, even after they have been found in a higher prio one
|
||||
*/
|
||||
const ALLOW_SHADOWED_REPOSITORIES = 4;
|
||||
|
||||
/** @var array */
|
||||
private $rootAliases;
|
||||
/** @var array */
|
||||
|
@ -39,7 +52,7 @@ class RepositorySet
|
|||
|
||||
private $acceptableStabilities;
|
||||
private $stabilityFlags;
|
||||
protected $rootRequires;
|
||||
private $rootRequires;
|
||||
|
||||
/** @var Pool */
|
||||
private $pool;
|
||||
|
@ -64,6 +77,11 @@ class RepositorySet
|
|||
}
|
||||
}
|
||||
|
||||
public function getRootRequires()
|
||||
{
|
||||
return $this->rootRequires;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a repository to this repository set
|
||||
*
|
||||
|
@ -96,15 +114,32 @@ class RepositorySet
|
|||
*
|
||||
* @param string $name
|
||||
* @param ConstraintInterface|null $constraint
|
||||
* @param bool $exactMatch if set to false, packages which replace/provide the given name might be returned as well even if they do not match the name exactly
|
||||
* @param bool $ignoreStability if set to true, packages are returned even though their stability does not match the required stability
|
||||
* @param int $flags any of the ALLOW_* constants from this class to tweak what is returned
|
||||
* @return array
|
||||
*/
|
||||
public function findPackages($name, ConstraintInterface $constraint = null, $exactMatch = true, $ignoreStability = false)
|
||||
public function findPackages($name, ConstraintInterface $constraint = null, $flags = 0)
|
||||
{
|
||||
$exactMatch = ($flags & self::ALLOW_PROVIDERS_REPLACERS) === 0;
|
||||
$ignoreStability = ($flags & self::ALLOW_UNACCEPTABLE_STABILITIES) !== 0;
|
||||
$loadFromAllRepos = ($flags & self::ALLOW_SHADOWED_REPOSITORIES) !== 0;
|
||||
|
||||
$packages = array();
|
||||
foreach ($this->repositories as $repository) {
|
||||
$packages[] = $repository->findPackages($name, $constraint) ?: array();
|
||||
if ($loadFromAllRepos) {
|
||||
foreach ($this->repositories as $repository) {
|
||||
$packages[] = $repository->findPackages($name, $constraint) ?: array();
|
||||
}
|
||||
} else {
|
||||
foreach ($this->repositories as $repository) {
|
||||
$result = $repository->loadPackages(array($name => $constraint), $ignoreStability ? BasePackage::$stabilities : $this->acceptableStabilities, $ignoreStability ? array() : $this->stabilityFlags);
|
||||
|
||||
$packages[] = $result['packages'];
|
||||
foreach ($result['namesFound'] as $nameFound) {
|
||||
// avoid loading the same package again from other repositories once it has been found
|
||||
if ($name === $nameFound) {
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$candidates = $packages ? call_user_func_array('array_merge', $packages) : array();
|
||||
|
@ -135,7 +170,7 @@ class RepositorySet
|
|||
*/
|
||||
public function createPool(Request $request)
|
||||
{
|
||||
$poolBuilder = new PoolBuilder($this->acceptableStabilities, $this->stabilityFlags, $this->rootAliases, $this->rootReferences, $this->rootRequires);
|
||||
$poolBuilder = new PoolBuilder($this->acceptableStabilities, $this->stabilityFlags, $this->rootAliases, $this->rootReferences);
|
||||
|
||||
foreach ($this->repositories as $repo) {
|
||||
if ($repo instanceof InstalledRepositoryInterface) {
|
||||
|
|
|
@ -21,4 +21,8 @@ namespace Composer\Repository;
|
|||
*/
|
||||
class RootPackageRepository extends ArrayRepository
|
||||
{
|
||||
public function getRepoName()
|
||||
{
|
||||
return 'root package repo';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,17 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
$this->processExecutor = new ProcessExecutor($io);
|
||||
}
|
||||
|
||||
public function getRepoName()
|
||||
{
|
||||
$driverClass = get_class($this->getDriver());
|
||||
$driverType = array_search($driverClass, $this->drivers);
|
||||
if (!$driverType) {
|
||||
$driverType = $driverClass;
|
||||
}
|
||||
|
||||
return 'vcs repo ('.$driverType.' '.$this->url.')';
|
||||
}
|
||||
|
||||
public function getRepoConfig()
|
||||
{
|
||||
return $this->repoConfig;
|
||||
|
|
|
@ -143,12 +143,18 @@ class RuleSetTest extends TestCase
|
|||
$p = $this->getPackage('foo', '2.1'),
|
||||
));
|
||||
|
||||
$repositorySetMock = $this->getMockBuilder('Composer\Repository\RepositorySet')->disableOriginalConstructor()->getMock();
|
||||
$repositorySetMock->expects($this->any())
|
||||
->method('getPool')
|
||||
->willReturn($pool);
|
||||
$requestMock = $this->getMockBuilder('Composer\DependencyResolver\Request')->disableOriginalConstructor()->getMock();
|
||||
|
||||
$ruleSet = new RuleSet;
|
||||
$literal = $p->getId();
|
||||
$rule = new GenericRule(array($literal), Rule::RULE_ROOT_REQUIRE, array('packageName' => 'foo/bar', 'constraint' => null));
|
||||
|
||||
$ruleSet->add($rule, RuleSet::TYPE_REQUEST);
|
||||
|
||||
$this->assertContains('REQUEST : No package found to satisfy root composer.json require foo/bar', $ruleSet->getPrettyString($pool));
|
||||
$this->assertContains('REQUEST : No package found to satisfy root composer.json require foo/bar', $ruleSet->getPrettyString($repositorySetMock, $requestMock));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,8 +99,14 @@ class RuleTest extends TestCase
|
|||
$p2 = $this->getPackage('baz', '1.1'),
|
||||
));
|
||||
|
||||
$repositorySetMock = $this->getMockBuilder('Composer\Repository\RepositorySet')->disableOriginalConstructor()->getMock();
|
||||
$repositorySetMock->expects($this->any())
|
||||
->method('getPool')
|
||||
->willReturn($pool);
|
||||
$requestMock = $this->getMockBuilder('Composer\DependencyResolver\Request')->disableOriginalConstructor()->getMock();
|
||||
|
||||
$rule = new GenericRule(array($p1->getId(), -$p2->getId()), Rule::RULE_PACKAGE_REQUIRES, new Link('baz', 'foo'));
|
||||
|
||||
$this->assertEquals('baz 1.1 relates to foo -> satisfiable by foo[2.1].', $rule->getPrettyString($pool));
|
||||
$this->assertEquals('baz 1.1 relates to foo -> satisfiable by foo[2.1].', $rule->getPrettyString($repositorySetMock, $requestMock));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ class SolverTest extends TestCase
|
|||
$problems = $e->getProblems();
|
||||
$this->assertCount(1, $problems);
|
||||
$this->assertEquals(2, $e->getCode());
|
||||
$this->assertEquals("\n - The requested package b could not be found in any version, there may be a typo in the package name.", $problems[0]->getPrettyString());
|
||||
$this->assertEquals("\n - Root composer.json requires b, it could not be found in any version, there may be a typo in the package name.", $problems[0]->getPrettyString($this->repoSet, $this->request));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -682,13 +682,7 @@ class SolverTest extends TestCase
|
|||
$msg = "\n";
|
||||
$msg .= " Problem 1\n";
|
||||
$msg .= " - Root composer.json requires a -> satisfiable by A[1.0].\n";
|
||||
$msg .= " - A 1.0 requires b >= 2.0 -> no matching package found.\n\n";
|
||||
$msg .= "Potential causes:\n";
|
||||
$msg .= " - A typo in the package name\n";
|
||||
$msg .= " - The package is not available in a stable-enough version according to your minimum-stability setting\n";
|
||||
$msg .= " see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.\n";
|
||||
$msg .= " - It's a private package and you forgot to add a custom repository to find it\n\n";
|
||||
$msg .= "Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.";
|
||||
$msg .= " - A 1.0 requires b >= 2.0 -> found B[1.0] but it does not match your constraint.\n";
|
||||
$this->assertEquals($msg, $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
@ -895,7 +889,7 @@ class SolverTest extends TestCase
|
|||
|
||||
protected function createSolver()
|
||||
{
|
||||
$this->solver = new Solver($this->policy, $this->repoSet->createPool($this->request), new NullIO());
|
||||
$this->solver = new Solver($this->policy, $this->repoSet->createPool($this->request), new NullIO(), $this->repoSet);
|
||||
}
|
||||
|
||||
protected function checkSolverResult(array $expected)
|
||||
|
|
|
@ -26,7 +26,7 @@ Updating dependencies
|
|||
Your requirements could not be resolved to an installable set of packages.
|
||||
|
||||
Problem 1
|
||||
- c/c 1.0.0 requires x/x 1.0 -> no matching package found.
|
||||
- c/c 1.0.0 requires x/x 1.0 -> could not be found in any version, there may be a typo in the package name.
|
||||
- b/b 1.0.0 requires c/c 1.* -> satisfiable by c/c[1.0.0].
|
||||
- Root composer.json requires b/b 1.* -> satisfiable by b/b[1.0.0].
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
--TEST--
|
||||
Test the error output of solver problems for conflicts between two dependents
|
||||
--COMPOSER--
|
||||
{
|
||||
"repositories": [
|
||||
{
|
||||
"type": "package",
|
||||
"package": [
|
||||
{ "name": "conflicter/pkg", "version": "1.0.0", "conflict": { "victim/pkg": "1.0.0"} },
|
||||
{ "name": "victim/pkg", "version": "1.0.0" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"conflicter/pkg": "1.0.0",
|
||||
"victim/pkg": "1.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
--RUN--
|
||||
update
|
||||
|
||||
--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 conflicter/pkg 1.0.0 -> satisfiable by conflicter/pkg[1.0.0].
|
||||
- victim/pkg 1.0.0 conflicts with conflicter/pkg[1.0.0].
|
||||
- Root composer.json requires victim/pkg 1.0.0 -> satisfiable by victim/pkg[1.0.0].
|
||||
|
||||
--EXPECT--
|
||||
|
|
@ -37,7 +37,7 @@ Your requirements could not be resolved to an installable set of packages.
|
|||
|
||||
Problem 1
|
||||
- Root composer.json requires a/a ~1.0 -> satisfiable by a/a[1.0.0].
|
||||
- a/a 1.0.0 requires php 5.5 -> your PHP version (%s) overridden by "config.platform.php" version (5.3) does not satisfy that requirement.
|
||||
- a/a 1.0.0 requires php 5.5 -> your php version (5.3; overridden via config.platform, actual: %s) does not satisfy that requirement.
|
||||
|
||||
--EXPECT--
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
--TEST--
|
||||
Partial update from lock file should apply lock file and downgrade unstable packages even if not whitelisted
|
||||
Partial update from lock file should apply lock file and if an unstable package is not allowed anymore by latest composer.json it should fail
|
||||
--COMPOSER--
|
||||
{
|
||||
"repositories": [
|
||||
|
@ -59,12 +59,4 @@ Updating dependencies
|
|||
Your requirements could not be resolved to an installable set of packages.
|
||||
|
||||
Problem 1
|
||||
- The requested package b/unstable could not be found in any version, there may be a typo in the package name.
|
||||
|
||||
Potential causes:
|
||||
- A typo in the package name
|
||||
- The package is not available in a stable-enough version according to your minimum-stability setting
|
||||
see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.
|
||||
- It's a private package and you forgot to add a custom repository to find it
|
||||
|
||||
Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.
|
||||
- b/unstable is fixed to 1.1.0-alpha (lock file version) by a partial update but that version is rejected by your minimum-stability. Make sure you whitelist it for update.
|
||||
|
|
|
@ -28,15 +28,8 @@ Updating dependencies
|
|||
Your requirements could not be resolved to an installable set of packages.
|
||||
|
||||
Problem 1
|
||||
- The requested package foo/a could not be found in any version, there may be a typo in the package name.
|
||||
- Root composer.json requires foo/a 2.*, it is satisfiable by foo/a[2.0.0] from package repo (defining 1 package) but foo/a[1.0.0] from package repo (defining 1 package) has higher repository priority. The packages with higher priority do not match your constraint and are therefore not installable.
|
||||
|
||||
Potential causes:
|
||||
- A typo in the package name
|
||||
- The package is not available in a stable-enough version according to your minimum-stability setting
|
||||
see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.
|
||||
- It's a private package and you forgot to add a custom repository to find it
|
||||
|
||||
Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.
|
||||
--EXPECT--
|
||||
--EXPECT-EXIT-CODE--
|
||||
2
|
||||
|
|
|
@ -6,34 +6,84 @@ Test the error output of solver problems.
|
|||
{
|
||||
"type": "package",
|
||||
"package": [
|
||||
{ "name": "package/found", "version": "2.0.0", "require": {
|
||||
"unstable/package2": "2.*"
|
||||
} },
|
||||
{ "name": "package/found2", "version": "2.0.0", "require": {
|
||||
"invalid/💩package": "*"
|
||||
} },
|
||||
{ "name": "package/found3", "version": "2.0.0", "require": {
|
||||
"unstable/package2": "2.*"
|
||||
} },
|
||||
{ "name": "package/found4", "version": "2.0.0", "require": {
|
||||
"non-existent/pkg2": "1.*"
|
||||
} },
|
||||
{ "name": "package/found5", "version": "2.0.0", "require": {
|
||||
"requirer/pkg": "1.*"
|
||||
} },
|
||||
{ "name": "package/found6", "version": "2.0.0", "require": {
|
||||
"stable-requiree-excluded/pkg2": "1.0.1"
|
||||
} },
|
||||
{ "name": "package/found7", "version": "2.0.0", "require": {
|
||||
"php-64bit": "1.0.1"
|
||||
} },
|
||||
{ "name": "conflict/requirer", "version": "2.0.0", "require": {
|
||||
"conflict/dep": "1.0.0"
|
||||
} },
|
||||
{ "name": "conflict/requirer2", "version": "2.0.0", "require": {
|
||||
"conflict/dep": "2.0.0"
|
||||
} },
|
||||
{ "name": "conflict/dep", "version": "1.0.0" },
|
||||
{ "name": "conflict/dep", "version": "2.0.0" },
|
||||
{ "name": "unstable/package", "version": "2.0.0-alpha" },
|
||||
{ "name": "unstable/package", "version": "1.0.0" },
|
||||
{ "name": "requirer/pkg", "version": "1.0.0", "require": {"dependency/pkg": "1.0.0" } },
|
||||
{ "name": "unstable/package2", "version": "2.0.0-alpha" },
|
||||
{ "name": "unstable/package2", "version": "1.0.0" },
|
||||
{ "name": "requirer/pkg", "version": "1.0.0", "require": {
|
||||
"dependency/pkg": "1.0.0",
|
||||
"dependency/unstable-pkg": "1.0.0-dev"
|
||||
} },
|
||||
{ "name": "dependency/pkg", "version": "2.0.0" },
|
||||
{ "name": "dependency/pkg", "version": "1.0.0" },
|
||||
{ "name": "dependency/unstable-pkg", "version": "1.0.0-dev" },
|
||||
{ "name": "stable-requiree-excluded/pkg", "version": "1.0.1" },
|
||||
{ "name": "stable-requiree-excluded/pkg", "version": "1.0.0" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"package/found": "2.*",
|
||||
"package/found2": "2.*",
|
||||
"package/found3": "2.*",
|
||||
"package/found4": "2.*",
|
||||
"package/found5": "2.*",
|
||||
"package/found6": "2.*",
|
||||
"package/found7": "2.*",
|
||||
"conflict/requirer": "2.*",
|
||||
"conflict/requirer2": "2.*",
|
||||
"unstable/package": "2.*",
|
||||
"bogus/pkg": "1.*",
|
||||
"non-existent/pkg": "1.*",
|
||||
"requirer/pkg": "1.*",
|
||||
"dependency/pkg": "2.*",
|
||||
"stable-requiree-excluded/pkg": "1.0.1"
|
||||
"stable-requiree-excluded/pkg": "1.0.1",
|
||||
"lib-xml": "1002.*",
|
||||
"lib-icu": "1001.*",
|
||||
"ext-xml": "1002.*",
|
||||
"php": "1"
|
||||
}
|
||||
}
|
||||
|
||||
--INSTALLED--
|
||||
[
|
||||
{ "name": "stable-requiree-excluded/pkg", "version": "1.0.0" }
|
||||
{ "name": "stable-requiree-excluded/pkg", "version": "1.0.0" },
|
||||
{ "name": "stable-requiree-excluded/pkg2", "version": "1.0.0" }
|
||||
]
|
||||
|
||||
--LOCK--
|
||||
{
|
||||
"packages": [
|
||||
{ "name": "stable-requiree-excluded/pkg", "version": "1.0.0" }
|
||||
{ "name": "stable-requiree-excluded/pkg", "version": "1.0.0" },
|
||||
{ "name": "stable-requiree-excluded/pkg2", "version": "1.0.0" }
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
|
@ -46,7 +96,7 @@ Test the error output of solver problems.
|
|||
}
|
||||
|
||||
--RUN--
|
||||
update unstable/package requirer/pkg dependency/pkg
|
||||
update unstable/package requirer/pkg dependency/pkg conflict/requirer
|
||||
|
||||
--EXPECT-EXIT-CODE--
|
||||
2
|
||||
|
@ -57,14 +107,44 @@ Updating dependencies
|
|||
Your requirements could not be resolved to an installable set of packages.
|
||||
|
||||
Problem 1
|
||||
- The requested package unstable/package could not be found in any version, there may be a typo in the package name.
|
||||
- Root composer.json requires unstable/package 2.*, found unstable/package[2.0.0-alpha] but it does not match your minimum-stability.
|
||||
Problem 2
|
||||
- The requested package bogus/pkg could not be found in any version, there may be a typo in the package name.
|
||||
- Root composer.json requires non-existent/pkg, it could not be found in any version, there may be a typo in the package name.
|
||||
Problem 3
|
||||
- The requested package stable-requiree-excluded/pkg could not be found in any version, there may be a typo in the package name.
|
||||
- Root composer.json requires stable-requiree-excluded/pkg 1.0.1, found stable-requiree-excluded/pkg[1.0.1] but the package is fixed to 1.0.0 (lock file version) by a partial update and that version does not match. Make sure you whitelist it for update.
|
||||
Problem 4
|
||||
- Root composer.json requires linked library lib-xml 1002.* but it has the wrong version installed or is missing from your system, make sure to load the extension providing it.
|
||||
Problem 5
|
||||
- Root composer.json requires linked library lib-icu 1001.* but it has the wrong version installed, try upgrading the intl extension.
|
||||
Problem 6
|
||||
- Root composer.json requires PHP extension ext-xml 1002.* but it has the wrong version (%s) installed. Install or enable PHP's xml extension.
|
||||
Problem 7
|
||||
- Root composer.json requires php 1 but your php version (%s) does not satisfy that requirement.
|
||||
Problem 8
|
||||
- Root composer.json requires package/found 2.* -> satisfiable by package/found[2.0.0].
|
||||
- package/found 2.0.0 requires unstable/package2 2.* -> found unstable/package2[2.0.0-alpha] but it does not match your minimum-stability.
|
||||
Problem 9
|
||||
- Root composer.json requires package/found2 2.* -> satisfiable by package/found2[2.0.0].
|
||||
- package/found2 2.0.0 requires invalid/💩package * -> could not be found, it looks like its name is invalid, "💩" is not allowed in package names.
|
||||
Problem 10
|
||||
- Root composer.json requires package/found3 2.* -> satisfiable by package/found3[2.0.0].
|
||||
- package/found3 2.0.0 requires unstable/package2 2.* -> found unstable/package2[2.0.0-alpha] but it does not match your minimum-stability.
|
||||
Problem 11
|
||||
- Root composer.json requires package/found4 2.* -> satisfiable by package/found4[2.0.0].
|
||||
- package/found4 2.0.0 requires non-existent/pkg2 1.* -> could not be found in any version, there may be a typo in the package name.
|
||||
Problem 12
|
||||
- Root composer.json requires package/found6 2.* -> satisfiable by package/found6[2.0.0].
|
||||
- package/found6 2.0.0 requires stable-requiree-excluded/pkg2 1.0.1 -> found stable-requiree-excluded/pkg2[1.0.0] but it does not match your constraint.
|
||||
Problem 13
|
||||
- Root composer.json requires package/found7 2.* -> satisfiable by package/found7[2.0.0].
|
||||
- package/found7 2.0.0 requires php-64bit 1.0.1 -> your php-64bit version (%s) does not satisfy that requirement.
|
||||
Problem 14
|
||||
- Root composer.json requires requirer/pkg 1.* -> satisfiable by requirer/pkg[1.0.0].
|
||||
- requirer/pkg 1.0.0 requires dependency/pkg 1.0.0 -> no matching package found.
|
||||
- requirer/pkg 1.0.0 requires dependency/pkg 1.0.0 -> found dependency/pkg[1.0.0] but it conflicts with your root composer.json require (2.*).
|
||||
Problem 15
|
||||
- requirer/pkg 1.0.0 requires dependency/pkg 1.0.0 -> found dependency/pkg[1.0.0] but it conflicts with your root composer.json require (2.*).
|
||||
- package/found5 2.0.0 requires requirer/pkg 1.* -> satisfiable by requirer/pkg[1.0.0].
|
||||
- Root composer.json requires package/found5 2.* -> satisfiable by package/found5[2.0.0].
|
||||
|
||||
Potential causes:
|
||||
- A typo in the package name
|
||||
|
@ -73,6 +153,9 @@ Potential causes:
|
|||
- It's a private package and you forgot to add a custom repository to find it
|
||||
|
||||
Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.
|
||||
To enable extensions, verify that they are enabled in your .ini files:
|
||||
__inilist__
|
||||
You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.
|
||||
|
||||
--EXPECT--
|
||||
|
||||
|
|
|
@ -323,6 +323,9 @@ class InstallerTest extends TestCase
|
|||
$this->assertSame(rtrim($expect), implode("\n", $installationManager->getTrace()));
|
||||
|
||||
if ($expectOutput) {
|
||||
$output = preg_replace('{^ - .*?\.ini$}m', '__inilist__', $output);
|
||||
$output = preg_replace('{(__inilist__\r?\n)+}', "__inilist__\n", $output);
|
||||
|
||||
$this->assertStringMatchesFormat(rtrim($expectOutput), rtrim($output));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue