diff --git a/src/Composer/DependencyResolver/Literal.php b/src/Composer/DependencyResolver/Literal.php index 39f0e4cc5..7234b5857 100644 --- a/src/Composer/DependencyResolver/Literal.php +++ b/src/Composer/DependencyResolver/Literal.php @@ -19,12 +19,15 @@ use Composer\Package\PackageInterface; */ class Literal { + protected $package; protected $wanted; + protected $id; public function __construct(PackageInterface $package, $wanted) { $this->package = $package; $this->wanted = $wanted; + $this->id = ($this->wanted ? '' : '-') . $this->package->getId(); } public function isWanted() @@ -44,7 +47,7 @@ class Literal public function getId() { - return ($this->wanted ? '' : '-') . $this->package->getId(); + return $this->id; } public function __toString() @@ -59,6 +62,6 @@ class Literal public function equals(Literal $b) { - return $this->getId() === $b->getId(); + return $this->id === $b->id; } } diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index 64a3106d2..d08c4a5ed 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -45,6 +45,15 @@ class Rule $this->watch2 = (count($this->literals) > 1) ? $literals[1]->getId() : 0; $this->type = -1; + + $this->ruleHash = substr(md5(implode(',', array_map(function ($l) { + return $l->getId(); + }, $this->literals))), 0, 5); + } + + public function getHash() + { + return $this->ruleHash; } public function setId($id) @@ -67,12 +76,16 @@ class Rule */ public function equals(Rule $rule) { + if ($this->ruleHash !== $rule->ruleHash) { + return false; + } + if (count($this->literals) != count($rule->literals)) { return false; } for ($i = 0, $n = count($this->literals); $i < $n; $i++) { - if (!$this->literals[$i]->equals($rule->literals[$i])) { + if (!$this->literals[$i]->getId() === $rule->literals[$i]->getId()) { return false; } } diff --git a/src/Composer/DependencyResolver/RuleSet.php b/src/Composer/DependencyResolver/RuleSet.php index cc57f8e22..49a7c2536 100644 --- a/src/Composer/DependencyResolver/RuleSet.php +++ b/src/Composer/DependencyResolver/RuleSet.php @@ -39,6 +39,8 @@ class RuleSet implements \IteratorAggregate, \Countable protected $ruleById; protected $nextRuleId; + protected $rulesByHash; + public function __construct() { $this->nextRuleId = 0; @@ -46,6 +48,8 @@ class RuleSet implements \IteratorAggregate, \Countable foreach ($this->getTypes() as $type) { $this->rules[$type] = array(); } + + $this->rulesByHash = array(); } public function add(Rule $rule, $type) @@ -64,6 +68,13 @@ class RuleSet implements \IteratorAggregate, \Countable $rule->setId($this->nextRuleId); $this->nextRuleId++; + + $hash = $rule->getHash(); + if (!isset($this->rulesByHash[$hash])) { + $this->rulesByHash[$hash] = array($rule); + } else { + $this->rulesByHash[$hash][] = $rule; + } } public function count() @@ -129,6 +140,20 @@ class RuleSet implements \IteratorAggregate, \Countable return array_keys($types); } + public function containsEqual($rule) + { + if (isset($this->rulesByHash[$rule->getHash()])) { + $potentialDuplicates = $this->rulesByHash[$rule->getHash()]; + foreach ($potentialDuplicates as $potentialDuplicate) { + if ($rule->equals($potentialDuplicate)) { + return true; + } + } + } + + return false; + } + public function __toString() { $string = "\n"; diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index ba15144cd..1ab152bcc 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -229,10 +229,8 @@ class Solver */ private function addRule($type, Rule $newRule = null) { if ($newRule) { - foreach ($this->rules->getIterator() as $rule) { - if ($rule->equals($newRule)) { - return; - } + if ($this->rules->containsEqual($newRule)) { + return; } $this->rules->add($newRule, $type);