commit
870dcece1f
|
@ -176,27 +176,32 @@ class Pool implements \Countable
|
||||||
* packages must match or null to return all
|
* packages must match or null to return all
|
||||||
* @param bool $mustMatchName Whether the name of returned packages
|
* @param bool $mustMatchName Whether the name of returned packages
|
||||||
* must match the given name
|
* must match the given name
|
||||||
|
* @param bool $bypassFilters If enabled, filterRequires and stability matching is ignored
|
||||||
* @return PackageInterface[] A set of packages
|
* @return PackageInterface[] A set of packages
|
||||||
*/
|
*/
|
||||||
public function whatProvides($name, ConstraintInterface $constraint = null, $mustMatchName = false)
|
public function whatProvides($name, ConstraintInterface $constraint = null, $mustMatchName = false, $bypassFilters = false)
|
||||||
{
|
{
|
||||||
|
if ($bypassFilters) {
|
||||||
|
return $this->computeWhatProvides($name, $constraint, $mustMatchName, true);
|
||||||
|
}
|
||||||
|
|
||||||
$key = ((int) $mustMatchName).$constraint;
|
$key = ((int) $mustMatchName).$constraint;
|
||||||
if (isset($this->providerCache[$name][$key])) {
|
if (isset($this->providerCache[$name][$key])) {
|
||||||
return $this->providerCache[$name][$key];
|
return $this->providerCache[$name][$key];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName);
|
return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName, $bypassFilters);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see whatProvides
|
* @see whatProvides
|
||||||
*/
|
*/
|
||||||
private function computeWhatProvides($name, $constraint, $mustMatchName = false)
|
private function computeWhatProvides($name, $constraint, $mustMatchName = false, $bypassFilters = false)
|
||||||
{
|
{
|
||||||
$candidates = array();
|
$candidates = array();
|
||||||
|
|
||||||
foreach ($this->providerRepos as $repo) {
|
foreach ($this->providerRepos as $repo) {
|
||||||
foreach ($repo->whatProvides($this, $name) as $candidate) {
|
foreach ($repo->whatProvides($this, $name, $bypassFilters) as $candidate) {
|
||||||
$candidates[] = $candidate;
|
$candidates[] = $candidate;
|
||||||
if ($candidate->id < 1) {
|
if ($candidate->id < 1) {
|
||||||
$candidate->setId($this->id++);
|
$candidate->setId($this->id++);
|
||||||
|
@ -228,13 +233,13 @@ class Pool implements \Countable
|
||||||
$aliasOfCandidate = $candidate->getAliasOf();
|
$aliasOfCandidate = $candidate->getAliasOf();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->whitelist !== null && (
|
if ($this->whitelist !== null && !$bypassFilters && (
|
||||||
(!($candidate instanceof AliasPackage) && !isset($this->whitelist[$candidate->id])) ||
|
(!($candidate instanceof AliasPackage) && !isset($this->whitelist[$candidate->id])) ||
|
||||||
($candidate instanceof AliasPackage && !isset($this->whitelist[$aliasOfCandidate->id]))
|
($candidate instanceof AliasPackage && !isset($this->whitelist[$aliasOfCandidate->id]))
|
||||||
)) {
|
)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch ($this->match($candidate, $name, $constraint)) {
|
switch ($this->match($candidate, $name, $constraint, $bypassFilters)) {
|
||||||
case self::MATCH_NONE:
|
case self::MATCH_NONE:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -317,14 +322,14 @@ class Pool implements \Countable
|
||||||
* @param ConstraintInterface $constraint The constraint to verify
|
* @param ConstraintInterface $constraint The constraint to verify
|
||||||
* @return int One of the MATCH* constants of this class or 0 if there is no match
|
* @return int One of the MATCH* constants of this class or 0 if there is no match
|
||||||
*/
|
*/
|
||||||
private function match($candidate, $name, ConstraintInterface $constraint = null)
|
private function match($candidate, $name, ConstraintInterface $constraint = null, $bypassFilters)
|
||||||
{
|
{
|
||||||
$candidateName = $candidate->getName();
|
$candidateName = $candidate->getName();
|
||||||
$candidateVersion = $candidate->getVersion();
|
$candidateVersion = $candidate->getVersion();
|
||||||
$isDev = $candidate->getStability() === 'dev';
|
$isDev = $candidate->getStability() === 'dev';
|
||||||
$isAlias = $candidate instanceof AliasPackage;
|
$isAlias = $candidate instanceof AliasPackage;
|
||||||
|
|
||||||
if (!$isDev && !$isAlias && isset($this->filterRequires[$name])) {
|
if (!$bypassFilters && !$isDev && !$isAlias && isset($this->filterRequires[$name])) {
|
||||||
$requireFilter = $this->filterRequires[$name];
|
$requireFilter = $this->filterRequires[$name];
|
||||||
} else {
|
} else {
|
||||||
$requireFilter = new EmptyConstraint;
|
$requireFilter = new EmptyConstraint;
|
||||||
|
|
|
@ -129,11 +129,15 @@ class Problem
|
||||||
return "\n - The requested package ".$job['packageName'].' could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.';
|
return "\n - The requested package ".$job['packageName'].' could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->pool->whatProvides($job['packageName'])) {
|
if ($providers = $this->pool->whatProvides($job['packageName'], $job['constraint'], true, true)) {
|
||||||
return "\n - The requested package ".$job['packageName'].' could not be found in any version, there may be a typo in the package name.';
|
return "\n - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' is satisfiable by '.$this->getPackageList($providers).' but those are rejected by your minimum-stability.';
|
||||||
}
|
}
|
||||||
|
|
||||||
return "\n - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' could not be found.';
|
if ($providers = $this->pool->whatProvides($job['packageName'], null, true, true)) {
|
||||||
|
return "\n - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' exists as '.$this->getPackageList($providers).' but those are rejected by your constraint.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return "\n - The requested package ".$job['packageName'].' could not be found in any version, there may be a typo in the package name.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -230,6 +230,10 @@ class Rule
|
||||||
|
|
||||||
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.';
|
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.';
|
||||||
} else {
|
} else {
|
||||||
|
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 . ' -> no matching package found.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -268,9 +268,14 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function whatProvides(Pool $pool, $name)
|
/**
|
||||||
|
* @param Pool $pool
|
||||||
|
* @param string $name package name
|
||||||
|
* @param bool $bypassFilters If set to true, this bypasses the stability filtering, and forces a recompute without cache
|
||||||
|
*/
|
||||||
|
public function whatProvides(Pool $pool, $name, $bypassFilters = false)
|
||||||
{
|
{
|
||||||
if (isset($this->providers[$name])) {
|
if (isset($this->providers[$name]) && !$bypassFilters) {
|
||||||
return $this->providers[$name];
|
return $this->providers[$name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,7 +359,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) {
|
if (!$bypassFilters && !$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,7 +401,18 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->providers[$name];
|
$result = $this->providers[$name];
|
||||||
|
|
||||||
|
// clean up the cache because otherwise using this puts the repo in an inconsistent state with a polluted unfiltered cache
|
||||||
|
// which is likely not an issue but might cause hard to track behaviors depending on how the repo is used
|
||||||
|
if ($bypassFilters) {
|
||||||
|
foreach ($this->providers[$name] as $uid => $provider) {
|
||||||
|
unset($this->providersByUid[$uid]);
|
||||||
|
}
|
||||||
|
unset($this->providers[$name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
--TEST--
|
||||||
|
Test the error output of solver problems.
|
||||||
|
--COMPOSER--
|
||||||
|
{
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "package",
|
||||||
|
"package": [
|
||||||
|
{ "name": "unstable/package", "version": "2.0.0-alpha" },
|
||||||
|
{ "name": "unstable/package", "version": "1.0.0" },
|
||||||
|
{ "name": "requirer", "version": "1.0.0", "require": {"dependency": "1.0.0" } },
|
||||||
|
{ "name": "dependency", "version": "2.0.0" },
|
||||||
|
{ "name": "dependency", "version": "1.0.0" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"unstable/package": "2.*",
|
||||||
|
"bogus": "1.*",
|
||||||
|
"requirer": "1.*",
|
||||||
|
"dependency": "2.*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--RUN--
|
||||||
|
install
|
||||||
|
|
||||||
|
--EXPECT-EXIT-CODE--
|
||||||
|
2
|
||||||
|
|
||||||
|
--EXPECT-OUTPUT--
|
||||||
|
Loading composer repositories with package information
|
||||||
|
Updating dependencies (including require-dev)
|
||||||
|
Your requirements could not be resolved to an installable set of packages.
|
||||||
|
|
||||||
|
Problem 1
|
||||||
|
- The requested package unstable/package 2.* exists as unstable/package[1.0.0] but those are rejected by your constraint.
|
||||||
|
Problem 2
|
||||||
|
- The requested package bogus could not be found in any version, there may be a typo in the package name.
|
||||||
|
Problem 3
|
||||||
|
- Installation request for requirer 1.* -> satisfiable by requirer[1.0.0].
|
||||||
|
- requirer 1.0.0 requires dependency 1.0.0 -> satisfiable by dependency[1.0.0] but these conflict with your requirements or minimum-stability
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.
|
||||||
|
|
||||||
|
--EXPECT--
|
||||||
|
|
Loading…
Reference in New Issue