Browse Source

Add conflict detection in why-not, fixes #5013

Jordi Boggiano 9 years ago
parent
commit
3933a7f404

+ 10 - 0
src/Composer/Command/BaseDependencyCommand.php

@@ -18,6 +18,7 @@ use Composer\Package\PackageInterface;
 use Composer\Repository\ArrayRepository;
 use Composer\Repository\CompositeRepository;
 use Composer\Repository\PlatformRepository;
+use Composer\Repository\RepositoryFactory;
 use Composer\Plugin\CommandEvent;
 use Composer\Plugin\PluginEvents;
 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
@@ -93,6 +94,15 @@ class BaseDependencyCommand extends BaseCommand
             throw new \InvalidArgumentException(sprintf('Could not find package "%s" in your project', $needle));
         }
 
+        // If the version we ask for is not installed then we need to locate it in remote repos and add it.
+        // This is needed for why-not to resolve conflicts from an uninstalled version against installed packages.
+        if (!$repository->findPackage($needle, $textConstraint)) {
+            $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO()));
+            if ($match = $defaultRepos->findPackage($needle, $textConstraint)) {
+                $repository->addRepository(new ArrayRepository(array(clone $match)));
+            }
+        }
+
         // Include replaced packages for inverted lookups as they are then the actual starting point to consider
         $needles = array($needle);
         if ($inverted) {

+ 13 - 0
src/Composer/Repository/BaseRepository.php

@@ -14,6 +14,7 @@ namespace Composer\Repository;
 
 use Composer\Package\RootPackageInterface;
 use Composer\Semver\Constraint\ConstraintInterface;
+use Composer\Semver\Constraint\Constraint;
 
 /**
  * Common ancestor class for generic repository functionality.
@@ -80,6 +81,18 @@ abstract class BaseRepository implements RepositoryInterface
                     }
                 }
             }
+
+            // When inverting, we need to check for conflicts of the needles against installed packages
+            if ($invert && in_array($package->getName(), $needles)) {
+                foreach ($package->getConflicts() as $link) {
+                    foreach ($this->findPackages($link->getTarget()) as $pkg) {
+                        $version = new Constraint('=', $pkg->getVersion());
+                        if ($link->getConstraint()->matches($version) === $invert) {
+                            $results[$package->getName()] = array($package, $link, false);
+                        }
+                    }
+                }
+            }
         }
 
         ksort($results);