Browse Source

Get rid of Literal object / literal id mix, use literals only to save memory

Nils Adermann 13 years ago
parent
commit
451bab1c2c

+ 19 - 17
src/Composer/DependencyResolver/DefaultPolicy.php

@@ -50,44 +50,44 @@ class DefaultPolicy implements PolicyInterface
 
     public function selectPreferedPackages(Pool $pool, array $installedMap, array $literals)
     {
-        $packages = $this->groupLiteralsByNamePreferInstalled($installedMap, $literals);
+        $packages = $this->groupLiteralsByNamePreferInstalled($pool,$installedMap, $literals);
 
         foreach ($packages as &$literals) {
             $policy = $this;
             usort($literals, function ($a, $b) use ($policy, $pool, $installedMap) {
-                return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $a->getPackage(), $b->getPackage(), true);
+                return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), true);
             });
         }
 
         foreach ($packages as &$literals) {
-            $literals = $this->pruneToBestVersion($literals);
+            $literals = $this->pruneToBestVersion($pool, $literals);
 
             $literals = $this->pruneToHighestPriorityOrInstalled($pool, $installedMap, $literals);
 
-            $literals = $this->pruneRemoteAliases($literals);
+            $literals = $this->pruneRemoteAliases($pool, $literals);
         }
 
         $selected = call_user_func_array('array_merge', $packages);
 
         // now sort the result across all packages to respect replaces across packages
         usort($selected, function ($a, $b) use ($policy, $pool, $installedMap) {
-            return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $a->getPackage(), $b->getPackage());
+            return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b));
         });
 
         return $selected;
     }
 
-    protected function groupLiteralsByNamePreferInstalled(array $installedMap, $literals)
+    protected function groupLiteralsByNamePreferInstalled(Pool $pool, array $installedMap, $literals)
     {
         $packages = array();
         foreach ($literals as $literal) {
-            $packageName = $literal->getPackage()->getName();
+            $packageName = $pool->literalToPackage($literal)->getName();
 
             if (!isset($packages[$packageName])) {
                 $packages[$packageName] = array();
             }
 
-            if (isset($installedMap[$literal->getPackageId()])) {
+            if (isset($installedMap[abs($literal)])) {
                 array_unshift($packages[$packageName], $literal);
             } else {
                 $packages[$packageName][] = $literal;
@@ -165,19 +165,21 @@ class DefaultPolicy implements PolicyInterface
         return false;
     }
 
-    protected function pruneToBestVersion($literals)
+    protected function pruneToBestVersion(Pool $pool, $literals)
     {
         $bestLiterals = array($literals[0]);
-        $bestPackage = $literals[0]->getPackage();
+        $bestPackage = $pool->literalToPackage($literals[0]);
         foreach ($literals as $i => $literal) {
             if (0 === $i) {
                 continue;
             }
 
-            if ($this->versionCompare($literal->getPackage(), $bestPackage, '>')) {
-                $bestPackage = $literal->getPackage();
+            $package = $pool->literalToPackage($literal);
+
+            if ($this->versionCompare($package, $bestPackage, '>')) {
+                $bestPackage = $package;
                 $bestLiterals = array($literal);
-            } else if ($this->versionCompare($literal->getPackage(), $bestPackage, '==')) {
+            } else if ($this->versionCompare($package, $bestPackage, '==')) {
                 $bestLiterals[] = $literal;
             }
         }
@@ -215,7 +217,7 @@ class DefaultPolicy implements PolicyInterface
         $priority = null;
 
         foreach ($literals as $literal) {
-            $package = $literal->getPackage();
+            $package = $pool->literalToPackage($literal);
 
             if (isset($installedMap[$package->getId()])) {
                 $selected[] = $literal;
@@ -241,12 +243,12 @@ class DefaultPolicy implements PolicyInterface
      *
      * If no package is a local alias, nothing happens
      */
-    protected function pruneRemoteAliases(array $literals)
+    protected function pruneRemoteAliases(Pool $pool, array $literals)
     {
         $hasLocalAlias = false;
 
         foreach ($literals as $literal) {
-            $package = $literal->getPackage();
+            $package = $pool->literalToPackage($literal);
 
             if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
                 $hasLocalAlias = true;
@@ -260,7 +262,7 @@ class DefaultPolicy implements PolicyInterface
 
         $selected = array();
         foreach ($literals as $literal) {
-            $package = $literal->getPackage();
+            $package = $pool->literalToPackage($literal);
 
             if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
                 $selected[] = $literal;

+ 0 - 67
src/Composer/DependencyResolver/Literal.php

@@ -1,67 +0,0 @@
-<?php
-
-/*
- * This file is part of Composer.
- *
- * (c) Nils Adermann <naderman@naderman.de>
- *     Jordi Boggiano <j.boggiano@seld.be>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Composer\DependencyResolver;
-
-use Composer\Package\PackageInterface;
-
-/**
- * @author Nils Adermann <naderman@naderman.de>
- */
-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()
-    {
-        return $this->wanted;
-    }
-
-    public function getPackage()
-    {
-        return $this->package;
-    }
-
-    public function getPackageId()
-    {
-        return $this->package->getId();
-    }
-
-    public function getId()
-    {
-        return $this->id;
-    }
-
-    public function __toString()
-    {
-        return ($this->wanted ? '+' : '-') . $this->getPackage();
-    }
-
-    public function inverted()
-    {
-        return new Literal($this->getPackage(), !$this->isWanted());
-    }
-
-    public function equals(Literal $b)
-    {
-        return $this->id === $b->id;
-    }
-}

+ 11 - 0
src/Composer/DependencyResolver/Pool.php

@@ -151,4 +151,15 @@ class Pool
 
         return $result;
     }
+
+    public function literalToPackage($literal)
+    {
+        $packageId = abs($literal);
+        return $this->packageById($packageId);
+    }
+
+    public function literalToString($literal)
+    {
+        return ($literal > 0 ? '+' : '-') . $this->literalToPackage($literal);
+    }
 }

+ 14 - 54
src/Composer/DependencyResolver/Rule.php

@@ -29,6 +29,8 @@ class Rule
     const RULE_LEARNED = 12;
     const RULE_PACKAGE_ALIAS = 13;
 
+    protected $pool;
+
     protected $disabled;
     protected $literals;
     protected $type;
@@ -37,18 +39,14 @@ class Rule
 
     protected $job;
 
-    public $watch1;
-    public $watch2;
-
-    public $next1;
-    public $next2;
-
     public $ruleHash;
 
-    public function __construct(array $literals, $reason, $reasonData, $job = null)
+    public function __construct(Pool $pool, array $literals, $reason, $reasonData, $job = null)
     {
+        $this->pool = $pool;
+
         // sort all packages ascending by id
-        usort($literals, array($this, 'compareLiteralsById'));
+        sort($literals);
 
         $this->literals = $literals;
         $this->reason = $reason;
@@ -59,14 +57,9 @@ class Rule
 
         $this->job = $job;
 
-        $this->watch1 = (count($this->literals) > 0) ? $literals[0]->getId() : 0;
-        $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);
+        $this->ruleHash = substr(md5(implode(',', $this->literals)), 0, 5);
     }
 
     public function getHash()
@@ -108,7 +101,7 @@ class Rule
         }
 
         for ($i = 0, $n = count($this->literals); $i < $n; $i++) {
-            if ($this->literals[$i]->getId() !== $rule->literals[$i]->getId()) {
+            if ($this->literals[$i] !== $rule->literals[$i]) {
                 return false;
             }
         }
@@ -166,24 +159,6 @@ class Rule
         return 1 === count($this->literals);
     }
 
-    public function getNext(Literal $literal)
-    {
-        if ($this->watch1 == $literal->getId()) {
-            return $this->next1;
-        } else {
-            return $this->next2;
-        }
-    }
-
-    public function getOtherWatch(Literal $literal)
-    {
-        if ($this->watch1 == $literal->getId()) {
-            return $this->watch2;
-        } else {
-            return $this->watch1;
-        }
-    }
-
     public function toHumanReadableString()
     {
         $ruleText = '';
@@ -191,7 +166,7 @@ class Rule
             if ($i != 0) {
                 $ruleText .= '|';
             }
-            $ruleText .= $literal;
+            $ruleText .= $this->pool->literalToString($literal);
         }
 
         switch ($this->reason) {
@@ -205,18 +180,18 @@ class Rule
                 return "Remove command rule ($ruleText)";
 
             case self::RULE_PACKAGE_CONFLICT:
-                $package1 = $this->literals[0]->getPackage();
-                $package2 = $this->literals[1]->getPackage();
+                $package1 = $this->pool->literalToPackage($this->literals[0]);
+                $package2 = $this->pool->literalToPackage($this->literals[1]);
                 return 'Package "'.$package1.'" conflicts with "'.$package2.'"';
 
             case self::RULE_PACKAGE_REQUIRES:
                 $literals = $this->literals;
                 $sourceLiteral = array_shift($literals);
-                $sourcePackage = $sourceLiteral->getPackage();
+                $sourcePackage = $this->pool->literalToPackage($sourceLiteral);
 
                 $requires = array();
                 foreach ($literals as $literal) {
-                    $requires[] = $literal->getPackage();
+                    $requires[] = $this->pool->literalToPackage($literal);
                 }
 
                 $text = 'Package "'.$sourcePackage.'" contains the rule '.$this->reasonData.'. ';
@@ -255,26 +230,11 @@ class Rule
             if ($i != 0) {
                 $result .= '|';
             }
-            $result .= $literal;
+            $result .= $this->pool->literalToString($literal);
         }
 
         $result .= ')';
 
         return $result;
     }
-
-    /**
-     * Comparison function for sorting literals by their id
-     *
-     * @param  Literal $a
-     * @param  Literal $b
-     * @return int        0 if the literals are equal, 1 if b is larger than a, -1 else
-     */
-    private function compareLiteralsById(Literal $a, Literal $b)
-    {
-        if ($a->getId() === $b->getId()) {
-            return 0;
-        }
-        return $a->getId() < $b->getId() ? -1 : 1;
-    }
 }

+ 7 - 24
src/Composer/DependencyResolver/RuleSetGenerator.php

@@ -50,34 +50,17 @@ class RuleSetGenerator
      */
     protected function createRequireRule(PackageInterface $package, array $providers, $reason, $reasonData = null)
     {
-        $literals = array(new Literal($package, false));
+        $literals = array(-$package->getId());
 
         foreach ($providers as $provider) {
             // self fulfilling rule?
             if ($provider === $package) {
                 return null;
             }
-            $literals[] = new Literal($provider, true);
+            $literals[] = $provider->getId();
         }
 
-        return new Rule($literals, $reason, $reasonData);
-    }
-
-    /**
-     * Creates a new rule for installing a package
-     *
-     * The rule is simply (A) for a package A to be installed.
-     *
-     * @param PackageInterface $package    The package to be installed
-     * @param int              $reason     A RULE_* constant describing the
-     *                                     reason for generating this rule
-     * @param mixed            $reasonData Any data, e.g. the package name, that
-     *                                     goes with the reason
-     * @return Rule                        The generated rule
-     */
-    protected function createInstallRule(PackageInterface $package, $reason, $reasonData = null)
-    {
-        return new Rule(new Literal($package, true));
+        return new Rule($this->pool, $literals, $reason, $reasonData);
     }
 
     /**
@@ -96,10 +79,10 @@ class RuleSetGenerator
     {
         $literals = array();
         foreach ($packages as $package) {
-            $literals[] = new Literal($package, true);
+            $literals[] = $package->getId();
         }
 
-        return new Rule($literals, $reason, $job['packageName'], $job);
+        return new Rule($this->pool, $literals, $reason, $job['packageName'], $job);
     }
 
     /**
@@ -115,7 +98,7 @@ class RuleSetGenerator
      */
     protected function createRemoveRule(PackageInterface $package, $reason, $job)
     {
-        return new Rule(array(new Literal($package, false)), $reason, $job['packageName'], $job);
+        return new Rule($this->pool, array(-$package->getId()), $reason, $job['packageName'], $job);
     }
 
     /**
@@ -139,7 +122,7 @@ class RuleSetGenerator
             return null;
         }
 
-        return new Rule(array(new Literal($issuer, false), new Literal($provider, false)), $reason, $reasonData);
+        return new Rule($this->pool, array(-$issuer->getId(), -$provider->getId()), $reason, $reasonData);
     }
 
     /**

+ 13 - 15
src/Composer/DependencyResolver/RuleWatchGraph.php

@@ -38,33 +38,31 @@ class RuleWatchGraph
         }
     }
 
-    public function contains($literalId)
+    public function contains($literal)
     {
-        return isset($this->watches[$literalId]);
+        return isset($this->watches[$literal]);
     }
 
-    public function walkLiteral($literalId, $level, $skipCallback, $conflictCallback, $decideCallback)
+    public function walkLiteral($literal, $level, $skipCallback, $conflictCallback, $decideCallback)
     {
-        if (!isset($this->watches[$literalId])) {
+        if (!isset($this->watches[$literal])) {
             return null;
         }
 
-        $this->watches[$literalId]->rewind();
-        while ($this->watches[$literalId]->valid()) {
-            $node = $this->watches[$literalId]->current();
-            $otherWatch = $node->getOtherWatch($literalId);
+        $this->watches[$literal]->rewind();
+        while ($this->watches[$literal]->valid()) {
+            $node = $this->watches[$literal]->current();
+            $otherWatch = $node->getOtherWatch($literal);
 
             if (!$node->getRule()->isDisabled() && !call_user_func($skipCallback, $otherWatch)) {
                 $ruleLiterals = $node->getRule()->getLiterals();
 
                 foreach ($ruleLiterals as $ruleLiteral) {
-                    $ruleLiteralId = $ruleLiteral->getId();
+                    if ($literal !== $ruleLiteral &&
+                        $otherWatch !== $ruleLiteral &&
+                        !call_user_func($conflictCallback, $ruleLiteral)) {
 
-                    if ($literalId !== $ruleLiteralId &&
-                        $otherWatch !== $ruleLiteralId &&
-                        !call_user_func($conflictCallback, $ruleLiteralId)) {
-
-                        $this->moveWatch($literalId, $ruleLiteralId, $node);
+                        $this->moveWatch($literal, $ruleLiteral, $node);
 
                         continue 2;
                     }
@@ -77,7 +75,7 @@ class RuleWatchGraph
                 call_user_func($decideCallback, $otherWatch, $level, $node->getRule());
             }
 
-            $this->watches[$literalId]->next();
+            $this->watches[$literal]->next();
         }
 
         return null;

+ 6 - 6
src/Composer/DependencyResolver/RuleWatchNode.php

@@ -28,8 +28,8 @@ class RuleWatchNode
 
         $literals = $rule->getLiterals();
 
-        $this->watch1 = (count($literals) > 0) ? $literals[0]->getId() : 0;
-        $this->watch2 = (count($literals) > 1) ? $literals[1]->getId() : 0;
+        $this->watch1 = (count($literals) > 0) ? $literals[0] : 0;
+        $this->watch2 = (count($literals) > 1) ? $literals[1] : 0;
     }
 
     /**
@@ -47,10 +47,10 @@ class RuleWatchNode
         $watchLevel = 0;
 
         foreach ($literals as $literal) {
-            $level = abs($decisionMap[$literal->getPackageId()]);
+            $level = abs($decisionMap[abs($literal)]);
 
             if ($level > $watchLevel) {
-                $this->rule->watch2 = $literal->getId();
+                $this->rule->watch2 = $literal;
                 $watchLevel = $level;
             }
         }
@@ -61,9 +61,9 @@ class RuleWatchNode
         return $this->rule;
     }
 
-    public function getOtherWatch($literalId)
+    public function getOtherWatch($literal)
     {
-        if ($this->watch1 == $literalId) {
+        if ($this->watch1 == $literal) {
             return $this->watch2;
         } else {
             return $this->watch1;

+ 65 - 107
src/Composer/DependencyResolver/Solver.php

@@ -13,7 +13,6 @@
 namespace Composer\DependencyResolver;
 
 use Composer\Repository\RepositoryInterface;
-use Composer\Package\PackageInterface;
 use Composer\Package\AliasPackage;
 use Composer\DependencyResolver\Operation;
 
@@ -51,10 +50,10 @@ class Solver
         $this->ruleSetGenerator = new RuleSetGenerator($policy, $pool);
     }
 
-    private function findDecisionRule(PackageInterface $package)
+    private function findDecisionRule($packageId)
     {
         foreach ($this->decisionQueue as $i => $literal) {
-            if ($package === $literal->getPackage()) {
+            if ($packageId === abs($literal)) {
                 return $this->decisionQueueWhy[$i];
             }
         }
@@ -77,10 +76,8 @@ class Solver
             $literals = $rule->getLiterals();
             $literal = $literals[0];
 
-            if (!$this->decided($literal->getPackage())) {
-                $this->decisionQueue[] = $literal;
-                $this->decisionQueueWhy[] = $rule;
-                $this->addDecision($literal, 1);
+            if (!$this->decided(abs($literal))) {
+                $this->decide($literal, 1, $rule);
                 continue;
             }
 
@@ -94,7 +91,7 @@ class Solver
                 continue;
             }
 
-            $conflict = $this->findDecisionRule($literal->getPackage());
+            $conflict = $this->findDecisionRule(abs($literal));
 
             if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) {
 
@@ -122,7 +119,7 @@ class Solver
                 $assertRuleLiterals = $assertRule->getLiterals();
                 $assertRuleLiteral = $assertRuleLiterals[0];
 
-                if  ($literal->getPackageId() !== $assertRuleLiteral->getPackageId()) {
+                if  (abs($literal) !== abs($assertRuleLiteral)) {
                     continue;
                 }
 
@@ -136,7 +133,7 @@ class Solver
                 $decisionLiteral = array_pop($this->decisionQueue);
                 array_pop($this->decisionQueueWhy);
                 unset($this->decisionQueueFree[count($this->decisionQueue)]);
-                $this->decisionMap[$decisionLiteral->getPackageId()] = 0;
+                $this->decisionMap[abs($decisionLiteral)] = 0;
             }
             $ruleIndex = -1;
         }
@@ -149,10 +146,8 @@ class Solver
             $literals = $rule->getLiterals();
             $literal = $literals[0];
 
-            if ($this->decisionMap[$literal->getPackageId()] == 0) {
-                $this->decisionQueue[] = $literal;
-                $this->decisionQueueWhy[] = $rule;
-                $this->addDecision($literal, 1);
+            if ($this->decisionMap[abs($literal)] == 0) {
+                $this->decide($literal, 1, $rule);
                 continue;
             }
 
@@ -191,7 +186,7 @@ class Solver
                 case 'install':
                     if (!$job['packages']) {
                         $problem = new Problem();
-                        $problem->addRule(new Rule(array(), null, null, $job));
+                        $problem->addRule(new Rule($this->pool, array(), null, null, $job));
                         $this->problems[] = $problem;
                     }
                 break;
@@ -237,24 +232,20 @@ class Solver
         return new Literal($package, $id > 0);
     }
 
-    protected function addDecision(Literal $l, $level)
+    protected function addDecision($literal, $level)
     {
-        $this->addDecisionId($l->getId(), $level);
-    }
-
-    protected function addDecisionId($literalId, $level)
-    {
-        $packageId = abs($literalId);
+        $packageId = abs($literal);
 
         $previousDecision = $this->decisionMap[$packageId];
         if ($previousDecision != 0) {
-            $literal = $this->literalFromId($literalId);
+            $literalString = $this->pool->literalToString($literal);
+            $package = $this->pool->literalToPackage($literal);
             throw new SolverBugException(
-                "Trying to decide $literal on level $level, even though ".$literal->getPackage()." was previously decided as ".(int) $previousDecision."."
+                "Trying to decide $literalString on level $level, even though $package was previously decided as ".(int) $previousDecision."."
             );
         }
 
-        if ($literalId > 0) {
+        if ($literal > 0) {
             $this->decisionMap[$packageId] = $level;
         } else {
             $this->decisionMap[$packageId] = -$level;
@@ -263,67 +254,49 @@ class Solver
 
     public function decide($literal, $level, $why)
     {
-        $this->addDecisionId($literal, $level);
-        $this->decisionQueue[] = $this->literalFromId($literal);
+        $this->addDecision($literal, $level);
+        $this->decisionQueue[] = $literal;
         $this->decisionQueueWhy[] = $why;
     }
 
-    protected function decisionsContain(Literal $l)
+    public function decisionsContain($literal)
     {
+        $packageId = abs($literal);
         return (
-            $this->decisionMap[$l->getPackageId()] > 0 && $l->isWanted() ||
-            $this->decisionMap[$l->getPackageId()] < 0 && !$l->isWanted()
+            $this->decisionMap[$packageId] > 0 && $literal > 0 ||
+            $this->decisionMap[$packageId] < 0 && $literal < 0
         );
     }
 
-    public function decisionsContainId($literalId)
+    protected function decisionsSatisfy($literal)
     {
-        $packageId = abs($literalId);
+        $packageId = abs($literal);
         return (
-            $this->decisionMap[$packageId] > 0 && $literalId > 0 ||
-            $this->decisionMap[$packageId] < 0 && $literalId < 0
+            $literal > 0 && $this->decisionMap[$packageId] > 0 ||
+            $literal < 0 && $this->decisionMap[$packageId] < 0
         );
     }
 
-    protected function decisionsSatisfy(Literal $l)
-    {
-        return ($l->isWanted() && $this->decisionMap[$l->getPackageId()] > 0) ||
-            (!$l->isWanted() && $this->decisionMap[$l->getPackageId()] < 0);
-    }
-
-    protected function decisionsConflict(Literal $l)
+    public function decisionsConflict($literal)
     {
+        $packageId = abs($literal);
         return (
-            $this->decisionMap[$l->getPackageId()] > 0 && !$l->isWanted() ||
-            $this->decisionMap[$l->getPackageId()] < 0 && $l->isWanted()
+            ($this->decisionMap[$packageId] > 0 && $literal < 0) ||
+            ($this->decisionMap[$packageId] < 0 && $literal > 0)
         );
     }
-
-    public function decisionsConflictId($literalId)
+    protected function decided($packageId)
     {
-        $packageId = abs($literalId);
-        return (
-            ($this->decisionMap[$packageId] > 0 && $literalId < 0) ||
-            ($this->decisionMap[$packageId] < 0 && $literalId > 0)
-        );
+        return $this->decisionMap[$packageId] != 0;
     }
 
-    protected function decided(PackageInterface $p)
+    protected function undecided($packageId)
     {
-        return $this->decisionMap[$p->getId()] != 0;
+        return $this->decisionMap[$packageId] == 0;
     }
 
-    protected function undecided(PackageInterface $p)
-    {
-        return $this->decisionMap[$p->getId()] == 0;
-    }
-
-    protected function decidedInstall(PackageInterface $p) {
-        return $this->decisionMap[$p->getId()] > 0;
-    }
-
-    protected function decidedRemove(PackageInterface $p) {
-        return $this->decisionMap[$p->getId()] < 0;
+    protected function decidedInstall($packageId) {
+        return $this->decisionMap[$packageId] > 0;
     }
 
     /**
@@ -341,15 +314,15 @@ class Solver
             // A was decided => (-A|B) now requires B to be true, so we look for
             // rules which are fulfilled by -A, rather than A.
 
-            $literal = $this->decisionQueue[$this->propagateIndex]->inverted();
+            $literal = -$this->decisionQueue[$this->propagateIndex];
 
             $this->propagateIndex++;
 
             $conflict = $this->watchGraph->walkLiteral(
-                $literal->getId(),
+                $literal,
                 $level,
-                array($this, 'decisionsContainId'),
-                array($this, 'decisionsConflictId'),
+                array($this, 'decisionsContain'),
+                array($this, 'decisionsConflict'),
                 array($this, 'decide')
             );
 
@@ -369,17 +342,17 @@ class Solver
         while (!empty($this->decisionQueue)) {
             $literal = $this->decisionQueue[count($this->decisionQueue) - 1];
 
-            if (!$this->decisionMap[$literal->getPackageId()]) {
+            if (!$this->decisionMap[abs($literal)]) {
                 break;
             }
 
-            $decisionLevel = abs($this->decisionMap[$literal->getPackageId()]);
+            $decisionLevel = abs($this->decisionMap[abs($literal)]);
 
             if ($decisionLevel <= $level) {
                 break;
             }
 
-            $this->decisionMap[$literal->getPackageId()] = 0;
+            $this->decisionMap[abs($literal)] = 0;
             array_pop($this->decisionQueue);
             array_pop($this->decisionQueueWhy);
 
@@ -412,13 +385,11 @@ class Solver
      * returns the new solver level or 0 if unsolvable
      *
      */
-    private function setPropagateLearn($level, Literal $literal, $disableRules, Rule $rule)
+    private function setPropagateLearn($level, $literal, $disableRules, Rule $rule)
     {
         $level++;
 
-        $this->addDecision($literal, $level);
-        $this->decisionQueue[] = $literal;
-        $this->decisionQueueWhy[] = $rule;
+        $this->decide($literal, $level, $rule);
         $this->decisionQueueFree[count($this->decisionQueueWhy) - 1] = true;
 
         while (true) {
@@ -457,9 +428,7 @@ class Solver
             $ruleNode->watch2OnHighest($this->decisionMap);
             $this->watchGraph->insert($ruleNode);
 
-            $this->addDecision($learnLiteral, $level);
-            $this->decisionQueue[] = $learnLiteral;
-            $this->decisionQueueWhy[] = $newRule;
+            $this->decide($learnLiteral, $level, $newRule);
         }
 
         return $level;
@@ -502,12 +471,12 @@ class Solver
                     continue;
                 }
 
-                if (isset($seen[$literal->getPackageId()])) {
+                if (isset($seen[abs($literal)])) {
                     continue;
                 }
-                $seen[$literal->getPackageId()] = true;
+                $seen[abs($literal)] = true;
 
-                $l = abs($this->decisionMap[$literal->getPackageId()]);
+                $l = abs($this->decisionMap[abs($literal)]);
 
                 if (1 === $l) {
                     $l1num++;
@@ -543,15 +512,15 @@ class Solver
 
                     $literal = $this->decisionQueue[$decisionId];
 
-                    if (isset($seen[$literal->getPackageId()])) {
+                    if (isset($seen[abs($literal)])) {
                         break;
                     }
                 }
 
-                unset($seen[$literal->getPackageId()]);
+                unset($seen[abs($literal)]);
 
                 if ($num && 0 === --$num) {
-                    $learnedLiterals[0] = $this->literalFromId(-$literal->getPackageId());
+                    $learnedLiterals[0] = -abs($literal);
 
                     if (!$l1num) {
                         break 2;
@@ -559,7 +528,7 @@ class Solver
 
                     foreach ($learnedLiterals as $i => $learnedLiteral) {
                         if ($i !== 0) {
-                            unset($seen[$literal->getPackageId()]);
+                            unset($seen[abs($learnedLiteral)]);
                         }
                     }
                     // only level 1 marks left
@@ -579,7 +548,7 @@ class Solver
             );
         }
 
-        $newRule = new Rule($learnedLiterals, Rule::RULE_LEARNED, $why);
+        $newRule = new Rule($this->pool, $learnedLiterals, Rule::RULE_LEARNED, $why);
 
         return array($learnedLiterals[0], $ruleLevel, $newRule, $why);
     }
@@ -626,18 +595,12 @@ class Solver
         $seen = array();
         $literals = $conflictRule->getLiterals();
 
-/* unnecessary because unlike rule.d, watch2 == 2nd literal, unless watch2 changed
-        if (sizeof($literals) == 2) {
-            $literals[1] = $this->literalFromId($conflictRule->watch2);
-        }
-*/
-
         foreach ($literals as $literal) {
             // skip the one true literal
             if ($this->decisionsSatisfy($literal)) {
                 continue;
             }
-            $seen[$literal->getPackageId()] = true;
+            $seen[abs($literal)] = true;
         }
 
         $decisionId = count($this->decisionQueue);
@@ -648,7 +611,7 @@ class Solver
             $literal = $this->decisionQueue[$decisionId];
 
             // skip literals that are not in this rule
-            if (!isset($seen[$literal->getPackageId()])) {
+            if (!isset($seen[abs($literal)])) {
                 continue;
             }
 
@@ -658,18 +621,13 @@ class Solver
             $this->analyzeUnsolvableRule($problem, $why, $lastWeakWhy);
 
             $literals = $why->getLiterals();
-/* unnecessary because unlike rule.d, watch2 == 2nd literal, unless watch2 changed
-            if (sizeof($literals) == 2) {
-                $literals[1] = $this->literalFromId($why->watch2);
-            }
-*/
 
             foreach ($literals as $literal) {
                 // skip the one true literal
                 if ($this->decisionsSatisfy($literal)) {
                     continue;
                 }
-                $seen[$literal->getPackageId()] = true;
+                $seen[abs($literal)] = true;
             }
         }
 
@@ -713,7 +671,7 @@ class Solver
     private function resetSolver()
     {
         while ($literal = array_pop($this->decisionQueue)) {
-            $this->decisionMap[$literal->getPackageId()] = 0;
+            $this->decisionMap[abs($literal)] = 0;
         }
 
         $this->decisionQueueWhy = array();
@@ -812,9 +770,9 @@ class Solver
                             if (count($this->installed) != count($this->updateMap)) {
                                 $prunedQueue = array();
                                 foreach ($decisionQueue as $literal) {
-                                    if (isset($this->installedMap[$literal->getPackageId()])) {
+                                    if (isset($this->installedMap[abs($literal)])) {
                                         $prunedQueue[] = $literal;
-                                        if (isset($this->updateMap[$literal->getPackageId()])) {
+                                        if (isset($this->updateMap[abs($literal)])) {
                                             $prunedQueue = $decisionQueue;
                                             break;
                                         }
@@ -873,15 +831,15 @@ class Solver
                 // just need to decide on the positive literals
                 //
                 foreach ($literals as $literal) {
-                    if (!$literal->isWanted()) {
-                        if (!$this->decidedInstall($literal->getPackage())) {
+                    if ($literal <= 0) {
+                        if (!$this->decidedInstall(abs($literal))) {
                             continue 2; // next rule
                         }
                     } else {
-                        if ($this->decidedInstall($literal->getPackage())) {
+                        if ($this->decidedInstall(abs($literal))) {
                             continue 2; // next rule
                         }
-                        if ($this->undecided($literal->getPackage())) {
+                        if ($this->undecided(abs($literal))) {
                             $decisionQueue[] = $literal;
                         }
                     }
@@ -919,7 +877,7 @@ class Solver
                     list($literals, $level) = $this->branches[$i];
 
                     foreach ($literals as $offset => $literal) {
-                        if ($literal && $literal->isWanted() && $this->decisionMap[$literal->getPackageId()] > $level + 1) {
+                        if ($literal && $literal > 0 && $this->decisionMap[abs($literal)] > $level + 1) {
                             $lastLiteral = $literal;
                             $lastBranchIndex = $i;
                             $lastBranchOffset = $offset;

+ 12 - 12
src/Composer/DependencyResolver/Transaction.php

@@ -43,35 +43,35 @@ class Transaction
         $installMeansUpdateMap = array();
 
         foreach ($this->decisionQueue as $i => $literal) {
-            $package = $literal->getPackage();
+            $package = $this->pool->literalToPackage($literal);
 
             // !wanted & installed
-            if (!$literal->isWanted() && isset($this->installedMap[$package->getId()])) {
+            if ($literal <= 0 && isset($this->installedMap[$package->getId()])) {
                 $updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
 
-                $literals = array(new Literal($package, true));
+                $literals = array($package->getId());
 
                 foreach ($updates as $update) {
-                    $literals[] = new Literal($update, true);
+                    $literals[] = $update->getId();
                 }
 
                 foreach ($literals as $updateLiteral) {
-                    if (!$updateLiteral->equals($literal)) {
-                        $installMeansUpdateMap[$updateLiteral->getPackageId()] = $package;
+                    if ($updateLiteral !== $literal) {
+                        $installMeansUpdateMap[abs($updateLiteral)] = $package;
                     }
                 }
             }
         }
 
         foreach ($this->decisionQueue as $i => $literal) {
-            $package = $literal->getPackage();
+            $package = $this->pool->literalToPackage($literal);
 
             // wanted & installed || !wanted & !installed
-            if ($literal->isWanted() == (isset($this->installedMap[$package->getId()]))) {
+            if (($literal > 0) == (isset($this->installedMap[$package->getId()]))) {
                 continue;
             }
 
-            if ($literal->isWanted()) {
+            if ($literal > 0) {
                 if ($package instanceof AliasPackage) {
                     $transaction[] = new Operation\MarkAliasInstalledOperation(
                         $package, $this->decisionQueueWhy[$i]
@@ -79,16 +79,16 @@ class Transaction
                     continue;
                 }
 
-                if (isset($installMeansUpdateMap[$literal->getPackageId()])) {
+                if (isset($installMeansUpdateMap[abs($literal)])) {
 
-                    $source = $installMeansUpdateMap[$literal->getPackageId()];
+                    $source = $installMeansUpdateMap[abs($literal)];
 
                     $transaction[] = new Operation\UpdateOperation(
                         $source, $package, $this->decisionQueueWhy[$i]
                     );
 
                     // avoid updates to one package from multiple origins
-                    unset($installMeansUpdateMap[$literal->getPackageId()]);
+                    unset($installMeansUpdateMap[abs($literal)]);
                     $ignoreRemove[$source->getId()] = true;
                 } else {
                     $transaction[] = new Operation\InstallOperation(

+ 13 - 14
tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php

@@ -16,7 +16,6 @@ use Composer\Repository\ArrayRepository;
 use Composer\Repository\RepositoryInterface;
 use Composer\DependencyResolver\DefaultPolicy;
 use Composer\DependencyResolver\Pool;
-use Composer\DependencyResolver\Literal;
 use Composer\Package\Link;
 use Composer\Package\AliasPackage;
 use Composer\Package\LinkConstraint\VersionConstraint;
@@ -44,8 +43,8 @@ class DefaultPolicyTest extends TestCase
         $this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
         $this->pool->addRepository($this->repo);
 
-        $literals = array(new Literal($packageA, true));
-        $expected = array(new Literal($packageA, true));
+        $literals = array($packageA->getId());
+        $expected = array($packageA->getId());
 
         $selected = $this->policy->selectPreferedPackages($this->pool, array(), $literals);
 
@@ -58,8 +57,8 @@ class DefaultPolicyTest extends TestCase
         $this->repo->addPackage($packageA2 = $this->getPackage('A', '2.0'));
         $this->pool->addRepository($this->repo);
 
-        $literals = array(new Literal($packageA1, true), new Literal($packageA2, true));
-        $expected = array(new Literal($packageA2, true));
+        $literals = array($packageA1->getId(), $packageA2->getId());
+        $expected = array($packageA2->getId());
 
         $selected = $this->policy->selectPreferedPackages($this->pool, array(), $literals);
 
@@ -73,8 +72,8 @@ class DefaultPolicyTest extends TestCase
         $this->pool->addRepository($this->repoInstalled);
         $this->pool->addRepository($this->repo);
 
-        $literals = array(new Literal($packageA, true), new Literal($packageAInstalled, true));
-        $expected = array(new Literal($packageA, true));
+        $literals = array($packageA->getId(), $packageAInstalled->getId());
+        $expected = array($packageA->getId());
 
         $selected = $this->policy->selectPreferedPackages($this->pool, $this->mapFromRepo($this->repoInstalled), $literals);
 
@@ -92,8 +91,8 @@ class DefaultPolicyTest extends TestCase
         $this->pool->addRepository($this->repoImportant);
         $this->pool->addRepository($this->repo);
 
-        $literals = array(new Literal($packageA, true), new Literal($packageAImportant, true));
-        $expected = array(new Literal($packageAImportant, true));
+        $literals = array($packageA->getId(), $packageAImportant->getId());
+        $expected = array($packageAImportant->getId());
 
         $selected = $this->policy->selectPreferedPackages($this->pool, array(), $literals);
 
@@ -119,10 +118,10 @@ class DefaultPolicyTest extends TestCase
         $packages = $this->pool->whatProvides('a', new VersionConstraint('=', '2.1.9999999.9999999-dev'));
         $literals = array();
         foreach ($packages as $package) {
-            $literals[] = new Literal($package, true);
+            $literals[] = $package->getId();
         }
 
-        $expected = array(new Literal($packageAAliasImportant, true));
+        $expected = array($packageAAliasImportant->getId());
 
         $selected = $this->policy->selectPreferedPackages($this->pool, array(), $literals);
 
@@ -139,7 +138,7 @@ class DefaultPolicyTest extends TestCase
 
         $this->pool->addRepository($this->repo);
 
-        $literals = array(new Literal($packageA, true), new Literal($packageB, true));
+        $literals = array($packageA->getId(), $packageB->getId());
         $expected = $literals;
 
         $selected = $this->policy->selectPreferedPackages($this->pool, array(), $literals);
@@ -157,8 +156,8 @@ class DefaultPolicyTest extends TestCase
 
         $this->pool->addRepository($this->repo);
 
-        $literals = array(new Literal($packageA, true), new Literal($packageB, true));
-        $expected = array(new Literal($packageA, true), new Literal($packageB, true));
+        $literals = array($packageA->getId(), $packageB->getId());
+        $expected = $literals;
 
         $selected = $this->policy->selectPreferedPackages($this->pool, array(), $literals);
 

+ 0 - 63
tests/Composer/Test/DependencyResolver/LiteralTest.php

@@ -1,63 +0,0 @@
-<?php
-
-/*
- * This file is part of Composer.
- *
- * (c) Nils Adermann <naderman@naderman.de>
- *     Jordi Boggiano <j.boggiano@seld.be>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Composer\Test\DependencyResolver;
-
-use Composer\DependencyResolver\Literal;
-use Composer\Test\TestCase;
-
-class LiteralTest extends TestCase
-{
-    protected $package;
-
-    public function setUp()
-    {
-        $this->package = $this->getPackage('foo', '1');
-        $this->package->setId(12);
-    }
-
-    public function testLiteralWanted()
-    {
-        $literal = new Literal($this->package, true);
-
-        $this->assertEquals(12, $literal->getId());
-        $this->assertEquals('+'.(string) $this->package, (string) $literal);
-    }
-
-    public function testLiteralUnwanted()
-    {
-        $literal = new Literal($this->package, false);
-
-        $this->assertEquals(-12, $literal->getId());
-        $this->assertEquals('-'.(string) $this->package, (string) $literal);
-    }
-
-    public function testLiteralInverted()
-    {
-        $literal = new Literal($this->package, false);
-
-        $inverted = $literal->inverted();
-
-        $this->assertInstanceOf('\Composer\DependencyResolver\Literal', $inverted);
-        $this->assertTrue($inverted->isWanted());
-        $this->assertSame($this->package, $inverted->getPackage());
-        $this->assertFalse($literal->equals($inverted));
-
-        $doubleInverted = $inverted->inverted();
-
-        $this->assertInstanceOf('\Composer\DependencyResolver\Literal', $doubleInverted);
-        $this->assertFalse($doubleInverted->isWanted());
-        $this->assertSame($this->package, $doubleInverted->getPackage());
-
-        $this->assertTrue($literal->equals($doubleInverted));
-    }
-}

+ 6 - 3
tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php

@@ -15,6 +15,7 @@ namespace Composer\Test\DependencyResolver;
 use Composer\DependencyResolver\Rule;
 use Composer\DependencyResolver\RuleSet;
 use Composer\DependencyResolver\RuleSetIterator;
+use Composer\DependencyResolver\Pool;
 
 class ResultSetIteratorTest extends \PHPUnit_Framework_TestCase
 {
@@ -22,13 +23,15 @@ class ResultSetIteratorTest extends \PHPUnit_Framework_TestCase
 
     protected function setUp()
     {
+        $this->pool = new Pool;
+
         $this->rules = array(
             RuleSet::TYPE_JOB => array(
-                new Rule(array(), 'job1', null),
-                new Rule(array(), 'job2', null),
+                new Rule($this->pool, array(), 'job1', null),
+                new Rule($this->pool, array(), 'job2', null),
             ),
             RuleSet::TYPE_LEARNED => array(
-                new Rule(array(), 'update1', null),
+                new Rule($this->pool, array(), 'update1', null),
             ),
             RuleSet::TYPE_PACKAGE => array(),
         );

+ 28 - 16
tests/Composer/Test/DependencyResolver/RuleSetTest.php

@@ -14,21 +14,29 @@ namespace Composer\Test\DependencyResolver;
 
 use Composer\DependencyResolver\Rule;
 use Composer\DependencyResolver\RuleSet;
-use Composer\DependencyResolver\Literal;
+use Composer\DependencyResolver\Pool;
+use Composer\Repository\ArrayRepository;
 use Composer\Test\TestCase;
 
 class RuleSetTest extends TestCase
 {
+    protected $pool;
+
+    public function setUp()
+    {
+        $this->pool = new Pool;
+    }
+
     public function testAdd()
     {
         $rules = array(
             RuleSet::TYPE_PACKAGE => array(),
             RuleSet::TYPE_JOB => array(
-                new Rule(array(), 'job1', null),
-                new Rule(array(), 'job2', null),
+                new Rule($this->pool, array(), 'job1', null),
+                new Rule($this->pool, array(), 'job2', null),
             ),
             RuleSet::TYPE_LEARNED => array(
-                new Rule(array(), 'update1', null),
+                new Rule($this->pool, array(), 'update1', null),
             ),
         );
 
@@ -48,15 +56,15 @@ class RuleSetTest extends TestCase
     {
         $ruleSet = new RuleSet;
 
-        $ruleSet->add(new Rule(array(), 'job1', null), 7);
+        $ruleSet->add(new Rule($this->pool, array(), 'job1', null), 7);
     }
 
     public function testCount()
     {
         $ruleSet = new RuleSet;
 
-        $ruleSet->add(new Rule(array(), 'job1', null), RuleSet::TYPE_JOB);
-        $ruleSet->add(new Rule(array(), 'job2', null), RuleSet::TYPE_JOB);
+        $ruleSet->add(new Rule($this->pool, array(), 'job1', null), RuleSet::TYPE_JOB);
+        $ruleSet->add(new Rule($this->pool, array(), 'job2', null), RuleSet::TYPE_JOB);
 
         $this->assertEquals(2, $ruleSet->count());
     }
@@ -65,7 +73,7 @@ class RuleSetTest extends TestCase
     {
         $ruleSet = new RuleSet;
 
-        $rule = new Rule(array(), 'job1', null);
+        $rule = new Rule($this->pool, array(), 'job1', null);
         $ruleSet->add($rule, RuleSet::TYPE_JOB);
 
         $this->assertSame($rule, $ruleSet->ruleById(0));
@@ -75,8 +83,8 @@ class RuleSetTest extends TestCase
     {
         $ruleSet = new RuleSet;
 
-        $rule1 = new Rule(array(), 'job1', null);
-        $rule2 = new Rule(array(), 'job1', null);
+        $rule1 = new Rule($this->pool, array(), 'job1', null);
+        $rule2 = new Rule($this->pool, array(), 'job1', null);
         $ruleSet->add($rule1, RuleSet::TYPE_JOB);
         $ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
 
@@ -90,8 +98,8 @@ class RuleSetTest extends TestCase
     public function testGetIteratorFor()
     {
         $ruleSet = new RuleSet;
-        $rule1 = new Rule(array(), 'job1', null);
-        $rule2 = new Rule(array(), 'job1', null);
+        $rule1 = new Rule($this->pool, array(), 'job1', null);
+        $rule2 = new Rule($this->pool, array(), 'job1', null);
 
         $ruleSet->add($rule1, RuleSet::TYPE_JOB);
         $ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
@@ -104,8 +112,8 @@ class RuleSetTest extends TestCase
     public function testGetIteratorWithout()
     {
         $ruleSet = new RuleSet;
-        $rule1 = new Rule(array(), 'job1', null);
-        $rule2 = new Rule(array(), 'job1', null);
+        $rule1 = new Rule($this->pool, array(), 'job1', null);
+        $rule2 = new Rule($this->pool, array(), 'job1', null);
 
         $ruleSet->add($rule1, RuleSet::TYPE_JOB);
         $ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
@@ -149,9 +157,13 @@ class RuleSetTest extends TestCase
 
     public function testToString()
     {
+        $repo = new ArrayRepository;
+        $repo->addPackage($p = $this->getPackage('foo', '2.1'));
+        $this->pool->addRepository($repo);
+
         $ruleSet = new RuleSet;
-        $literal = new Literal($this->getPackage('foo', '2.1'), true);
-        $rule = new Rule(array($literal), 'job1', null);
+        $literal = $p->getId();
+        $rule = new Rule($this->pool, array($literal), 'job1', null);
 
         $ruleSet->add($rule, RuleSet::TYPE_JOB);
 

+ 31 - 56
tests/Composer/Test/DependencyResolver/RuleTest.php

@@ -13,14 +13,22 @@
 namespace Composer\Test\DependencyResolver;
 
 use Composer\DependencyResolver\Rule;
-use Composer\DependencyResolver\Literal;
+use Composer\DependencyResolver\Pool;
+use Composer\Repository\ArrayRepository;
 use Composer\Test\TestCase;
 
 class RuleTest extends TestCase
 {
+    protected $pool;
+
+    public function setUp()
+    {
+        $this->pool = new Pool;
+    }
+
     public function testGetHash()
     {
-        $rule = new Rule(array(), 'job1', null);
+        $rule = new Rule($this->pool, array(), 'job1', null);
         $rule->ruleHash = '123';
 
         $this->assertEquals('123', $rule->getHash());
@@ -28,7 +36,7 @@ class RuleTest extends TestCase
 
     public function testSetAndGetId()
     {
-        $rule = new Rule(array(), 'job1', null);
+        $rule = new Rule($this->pool, array(), 'job1', null);
         $rule->setId(666);
 
         $this->assertEquals(666, $rule->getId());
@@ -36,10 +44,10 @@ class RuleTest extends TestCase
 
     public function testEqualsForRulesWithDifferentHashes()
     {
-        $rule = new Rule(array(), 'job1', null);
+        $rule = new Rule($this->pool, array(), 'job1', null);
         $rule->ruleHash = '123';
 
-        $rule2 = new Rule(array(), 'job1', null);
+        $rule2 = new Rule($this->pool, array(), 'job1', null);
         $rule2->ruleHash = '321';
 
         $this->assertFalse($rule->equals($rule2));
@@ -47,18 +55,10 @@ class RuleTest extends TestCase
 
     public function testEqualsForRulesWithDifferentLiterals()
     {
-        $literal = $this->getLiteralMock();
-        $literal->expects($this->any())
-            ->method('getId')
-            ->will($this->returnValue(1));
-        $rule = new Rule(array($literal), 'job1', null);
+        $rule = new Rule($this->pool, array(1), 'job1', null);
         $rule->ruleHash = '123';
 
-        $literal = $this->getLiteralMock();
-        $literal->expects($this->any())
-            ->method('getId')
-            ->will($this->returnValue(12));
-        $rule2 = new Rule(array($literal), 'job1', null);
+        $rule2 = new Rule($this->pool, array(12), 'job1', null);
         $rule2->ruleHash = '123';
 
         $this->assertFalse($rule->equals($rule2));
@@ -66,18 +66,9 @@ class RuleTest extends TestCase
 
     public function testEqualsForRulesWithDifferLiteralsQuantity()
     {
-        $literal = $this->getLiteralMock();
-        $literal->expects($this->any())
-            ->method('getId')
-            ->will($this->returnValue(1));
-        $literal2 = $this->getLiteralMock();
-        $literal2->expects($this->any())
-            ->method('getId')
-            ->will($this->returnValue(12));
-
-        $rule = new Rule(array($literal, $literal2), 'job1', null);
+        $rule = new Rule($this->pool, array(1, 12), 'job1', null);
         $rule->ruleHash = '123';
-        $rule2 = new Rule(array($literal), 'job1', null);
+        $rule2 = new Rule($this->pool, array(1), 'job1', null);
         $rule2->ruleHash = '123';
 
         $this->assertFalse($rule->equals($rule2));
@@ -85,24 +76,15 @@ class RuleTest extends TestCase
 
     public function testEqualsForRulesWithThisSameLiterals()
     {
-        $literal = $this->getLiteralMock();
-        $literal->expects($this->any())
-            ->method('getId')
-            ->will($this->returnValue(1));
-        $literal2 = $this->getLiteralMock();
-        $literal2->expects($this->any())
-            ->method('getId')
-            ->will($this->returnValue(12));
-
-        $rule = new Rule(array($literal, $literal2), 'job1', null);
-        $rule2 = new Rule(array($literal, $literal2), 'job1', null);
+        $rule = new Rule($this->pool, array(1, 12), 'job1', null);
+        $rule2 = new Rule($this->pool, array(1, 12), 'job1', null);
 
         $this->assertTrue($rule->equals($rule2));
     }
 
     public function testSetAndGetType()
     {
-        $rule = new Rule(array(), 'job1', null);
+        $rule = new Rule($this->pool, array(), 'job1', null);
         $rule->setType('someType');
 
         $this->assertEquals('someType', $rule->getType());
@@ -110,7 +92,7 @@ class RuleTest extends TestCase
 
     public function testEnable()
     {
-        $rule = new Rule(array(), 'job1', null);
+        $rule = new Rule($this->pool, array(), 'job1', null);
         $rule->disable();
         $rule->enable();
 
@@ -120,7 +102,7 @@ class RuleTest extends TestCase
 
     public function testDisable()
     {
-        $rule = new Rule(array(), 'job1', null);
+        $rule = new Rule($this->pool, array(), 'job1', null);
         $rule->enable();
         $rule->disable();
 
@@ -130,10 +112,10 @@ class RuleTest extends TestCase
 
     public function testSetWeak()
     {
-        $rule = new Rule(array(), 'job1', null);
+        $rule = new Rule($this->pool, array(), 'job1', null);
         $rule->setWeak(true);
 
-        $rule2 = new Rule(array(), 'job1', null);
+        $rule2 = new Rule($this->pool, array(), 'job1', null);
         $rule2->setWeak(false);
 
         $this->assertTrue($rule->isWeak());
@@ -142,10 +124,8 @@ class RuleTest extends TestCase
 
     public function testIsAssertions()
     {
-        $literal = $this->getLiteralMock();
-        $literal2 = $this->getLiteralMock();
-        $rule = new Rule(array($literal, $literal2), 'job1', null);
-        $rule2 = new Rule(array($literal), 'job1', null);
+        $rule = new Rule($this->pool, array(1, 12), 'job1', null);
+        $rule2 = new Rule($this->pool, array(1), 'job1', null);
 
         $this->assertFalse($rule->isAssertion());
         $this->assertTrue($rule2->isAssertion());
@@ -153,18 +133,13 @@ class RuleTest extends TestCase
 
     public function testToString()
     {
-        $literal = new Literal($this->getPackage('foo', '2.1'), true);
-        $literal2 = new Literal($this->getPackage('baz', '1.1'), false);
+        $repo = new ArrayRepository;
+        $repo->addPackage($p1 = $this->getPackage('foo', '2.1'));
+        $repo->addPackage($p2 = $this->getPackage('baz', '1.1'));
+        $this->pool->addRepository($repo);
 
-        $rule = new Rule(array($literal, $literal2), 'job1', null);
+        $rule = new Rule($this->pool, array($p1->getId(), -$p2->getId()), 'job1', null);
 
         $this->assertEquals('(-baz-1.1.0.0|+foo-2.1.0.0)', $rule->__toString());
     }
-
-    private function getLiteralMock()
-    {
-        return $this->getMockBuilder('Composer\DependencyResolver\Literal')
-            ->disableOriginalConstructor()
-            ->getMock();
-    }
 }