Browse Source

Merge pull request #8537 from naderman/remove-jobs-just-require

Request jobs replaced by root require / fixed package
Nils Adermann 5 years ago
parent
commit
a8963cc0e2
33 changed files with 270 additions and 365 deletions
  1. 2 3
      src/Composer/DependencyResolver/GenericRule.php
  2. 2 3
      src/Composer/DependencyResolver/MultiConflictRule.php
  3. 2 2
      src/Composer/DependencyResolver/Operation/InstallOperation.php
  4. 2 2
      src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php
  5. 2 2
      src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.php
  6. 2 2
      src/Composer/DependencyResolver/Operation/OperationInterface.php
  7. 2 2
      src/Composer/DependencyResolver/Operation/UninstallOperation.php
  8. 2 2
      src/Composer/DependencyResolver/Operation/UpdateOperation.php
  9. 9 13
      src/Composer/DependencyResolver/PoolBuilder.php
  10. 19 61
      src/Composer/DependencyResolver/Problem.php
  11. 6 16
      src/Composer/DependencyResolver/Request.php
  12. 32 21
      src/Composer/DependencyResolver/Rule.php
  13. 2 3
      src/Composer/DependencyResolver/Rule2Literals.php
  14. 2 2
      src/Composer/DependencyResolver/RuleSet.php
  15. 19 40
      src/Composer/DependencyResolver/RuleSetGenerator.php
  16. 18 44
      src/Composer/DependencyResolver/Solver.php
  17. 2 2
      src/Composer/DependencyResolver/SolverProblemsException.php
  18. 1 1
      src/Composer/DependencyResolver/Transaction.php
  19. 6 7
      src/Composer/Installer.php
  20. 19 19
      src/Composer/Installer/InstallationManager.php
  21. 1 1
      src/Composer/Package/Link.php
  22. 1 1
      src/Composer/Repository/RepositorySet.php
  23. 1 1
      tests/Composer/Test/DependencyResolver/PoolBuilderTest.php
  24. 6 6
      tests/Composer/Test/DependencyResolver/RequestTest.php
  25. 7 7
      tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php
  26. 31 31
      tests/Composer/Test/DependencyResolver/RuleSetTest.php
  27. 17 16
      tests/Composer/Test/DependencyResolver/RuleTest.php
  28. 49 49
      tests/Composer/Test/DependencyResolver/SolverTest.php
  29. 2 2
      tests/Composer/Test/DependencyResolver/TransactionTest.php
  30. 1 1
      tests/Composer/Test/Fixtures/installer/broken-deps-do-not-replace.test
  31. 1 1
      tests/Composer/Test/Fixtures/installer/github-issues-4319.test
  32. 1 1
      tests/Composer/Test/Fixtures/installer/solver-problems.test
  33. 1 1
      tests/Composer/Test/Mock/InstallationManagerMock.php

+ 2 - 3
src/Composer/DependencyResolver/GenericRule.php

@@ -26,11 +26,10 @@ class GenericRule extends Rule
      * @param array                          $literals
      * @param int|null                       $reason     A RULE_* constant describing the reason for generating this rule
      * @param Link|PackageInterface|int|null $reasonData
-     * @param array                          $job        The job this rule was created from
      */
-    public function __construct(array $literals, $reason, $reasonData, $job = null)
+    public function __construct(array $literals, $reason, $reasonData)
     {
-        parent::__construct($reason, $reasonData, $job);
+        parent::__construct($reason, $reasonData);
 
         // sort all packages ascending by id
         sort($literals);

+ 2 - 3
src/Composer/DependencyResolver/MultiConflictRule.php

@@ -28,11 +28,10 @@ class MultiConflictRule extends Rule
      * @param array                 $literals
      * @param int                   $reason     A RULE_* constant describing the reason for generating this rule
      * @param Link|PackageInterface $reasonData
-     * @param array                 $job        The job this rule was created from
      */
-    public function __construct(array $literals, $reason, $reasonData, $job = null)
+    public function __construct(array $literals, $reason, $reasonData)
     {
-        parent::__construct($reason, $reasonData, $job);
+        parent::__construct($reason, $reasonData);
 
         if (count($literals) < 3) {
             throw new \RuntimeException("multi conflict rule requires at least 3 literals");

+ 2 - 2
src/Composer/DependencyResolver/Operation/InstallOperation.php

@@ -47,11 +47,11 @@ class InstallOperation extends SolverOperation
     }
 
     /**
-     * Returns job type.
+     * Returns operation type.
      *
      * @return string
      */
-    public function getJobType()
+    public function getOperationType()
     {
         return 'install';
     }

+ 2 - 2
src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php

@@ -48,11 +48,11 @@ class MarkAliasInstalledOperation extends SolverOperation
     }
 
     /**
-     * Returns job type.
+     * Returns operation type.
      *
      * @return string
      */
-    public function getJobType()
+    public function getOperationType()
     {
         return 'markAliasInstalled';
     }

+ 2 - 2
src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.php

@@ -48,11 +48,11 @@ class MarkAliasUninstalledOperation extends SolverOperation
     }
 
     /**
-     * Returns job type.
+     * Returns operation type.
      *
      * @return string
      */
-    public function getJobType()
+    public function getOperationType()
     {
         return 'markAliasUninstalled';
     }

+ 2 - 2
src/Composer/DependencyResolver/Operation/OperationInterface.php

@@ -20,11 +20,11 @@ namespace Composer\DependencyResolver\Operation;
 interface OperationInterface
 {
     /**
-     * Returns job type.
+     * Returns operation type.
      *
      * @return string
      */
-    public function getJobType();
+    public function getOperationType();
 
     /**
      * Returns operation reason.

+ 2 - 2
src/Composer/DependencyResolver/Operation/UninstallOperation.php

@@ -47,11 +47,11 @@ class UninstallOperation extends SolverOperation
     }
 
     /**
-     * Returns job type.
+     * Returns operation type.
      *
      * @return string
      */
-    public function getJobType()
+    public function getOperationType()
     {
         return 'uninstall';
     }

+ 2 - 2
src/Composer/DependencyResolver/Operation/UpdateOperation.php

@@ -60,11 +60,11 @@ class UpdateOperation extends SolverOperation
     }
 
     /**
-     * Returns job type.
+     * Returns operation type.
      *
      * @return string
      */
-    public function getJobType()
+    public function getOperationType()
     {
         return 'update';
     }

+ 9 - 13
src/Composer/DependencyResolver/PoolBuilder.php

@@ -69,20 +69,16 @@ class PoolBuilder
             }
         }
 
-        foreach ($request->getJobs() as $job) {
-            switch ($job['cmd']) {
-                case 'install':
-                    if (isset($this->loadedNames[$job['packageName']])) {
-                        continue 2;
-                    }
-                    // TODO currently lock above is always NULL if we adjust that, this needs to merge constraints
-                    // TODO does it really make sense that we can have install requests for the same package that is actively locked with non-matching constraints?
-                    // also see the solver-problems.test test case
-                    $constraint = array_key_exists($job['packageName'], $loadNames) ? null : $job['constraint'];
-                    $loadNames[$job['packageName']] = $constraint;
-                    $this->nameConstraints[$job['packageName']] = $constraint ? new MultiConstraint(array($constraint), false) : null;
-                    break;
+        foreach ($request->getRequires() as $packageName => $constraint) {
+            if (isset($this->loadedNames[$packageName])) {
+                continue;
             }
+            // TODO currently lock above is always NULL if we adjust that, this needs to merge constraints
+            // TODO does it really make sense that we can have install requests for the same package that is actively locked with non-matching constraints?
+            // also see the solver-problems.test test case
+            $constraint = array_key_exists($packageName, $loadNames) ? null : $constraint;
+            $loadNames[$packageName] = $constraint;
+            $this->nameConstraints[$packageName] = $constraint ? new MultiConstraint(array($constraint), false) : null;
         }
 
         while (!empty($loadNames)) {

+ 19 - 61
src/Composer/DependencyResolver/Problem.php

@@ -28,7 +28,7 @@ class Problem
     protected $reasonSeen;
 
     /**
-     * A set of reasons for the problem, each is a rule or a job and a rule
+     * A set of reasons for the problem, each is a rule or a root require and a rule
      * @var array
      */
     protected $reasons = array();
@@ -49,10 +49,7 @@ class Problem
      */
     public function addRule(Rule $rule)
     {
-        $this->addReason(spl_object_hash($rule), array(
-            'rule' => $rule,
-            'job' => $rule->getJob(),
-        ));
+        $this->addReason(spl_object_hash($rule), $rule);
     }
 
     /**
@@ -73,16 +70,20 @@ class Problem
      */
     public function getPrettyString(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));
 
         if (count($reasons) === 1) {
             reset($reasons);
-            $reason = current($reasons);
+            $rule = current($reasons);
 
-            $job = $reason['job'];
+            if (!in_array($rule->getReason(), array(Rule::RULE_ROOT_REQUIRE, Rule::RULE_FIXED), true)) {
+                throw new \LogicException("Single reason problems must contain a request rule.");
+            }
 
-            $packageName = $job['packageName'];
-            $constraint = $job['constraint'];
+            $request = $rule->getReasonData();
+            $packageName = $request['packageName'];
+            $constraint = $request['constraint'];
 
             if (isset($constraint)) {
                 $packages = $this->pool->whatProvides($packageName, $constraint);
@@ -90,8 +91,7 @@ class Problem
                 $packages = array();
             }
 
-            if ($job && ($job['cmd'] === 'install' || $job['cmd'] === 'fix') && empty($packages)) {
-
+            if (empty($packages)) {
                 // handle php/hhvm
                 if ($packageName === 'php' || $packageName === 'php-64bit' || $packageName === 'hhvm') {
                     $version = phpversion();
@@ -164,17 +164,8 @@ class Problem
 
         $messages = array();
 
-        foreach ($reasons as $reason) {
-            $rule = $reason['rule'];
-            $job = $reason['job'];
-
-            if ($job) {
-                $messages[] = $this->jobToText($job);
-            } elseif ($rule) {
-                if ($rule instanceof Rule) {
-                    $messages[] = $rule->getPrettyString($this->pool, $installedMap, $learnedPool);
-                }
-            }
+        foreach ($reasons as $rule) {
+            $messages[] = $rule->getPrettyString($this->pool, $installedMap, $learnedPool);
         }
 
         return "\n    - ".implode("\n    - ", $messages);
@@ -184,10 +175,13 @@ class Problem
      * Store a reason descriptor but ignore duplicates
      *
      * @param string $id     A canonical identifier for the reason
-     * @param string|array $reason The reason descriptor
+     * @param Rule $reason The reason descriptor
      */
-    protected function addReason($id, $reason)
+    protected function addReason($id, Rule $reason)
     {
+        // TODO: if a rule is part of a problem description in two sections, isn't this going to remove a message
+        // that is important to understand the issue?
+
         if (!isset($this->reasonSeen[$id])) {
             $this->reasonSeen[$id] = true;
             $this->reasons[$this->section][] = $reason;
@@ -199,42 +193,6 @@ class Problem
         $this->section++;
     }
 
-    /**
-     * Turns a job into a human readable description
-     *
-     * @param  array  $job
-     * @return string
-     */
-    protected function jobToText($job)
-    {
-        $packageName = $job['packageName'];
-        $constraint = $job['constraint'];
-        switch ($job['cmd']) {
-            case 'fix':
-                $package = $job['package'];
-                if ($job['lockable']) {
-                    return $package->getPrettyName().' is locked to version '.$package->getPrettyVersion().' and an update of this package was not requested.';
-                }
-
-                return $package->getPrettyName().' is present at version '.$package->getPrettyVersion() . ' and cannot be modified by Composer';
-            case 'install':
-                $packages = $this->pool->whatProvides($packageName, $constraint);
-                if (!$packages) {
-                    return 'No package found to satisfy install request for '.$packageName.$this->constraintToText($constraint);
-                }
-
-                return 'Installation request for '.$packageName.$this->constraintToText($constraint).' -> satisfiable by '.$this->getPackageList($packages).'.';
-        }
-
-        if (isset($constraint)) {
-            $packages = $this->pool->whatProvides($packageName, $constraint);
-        } else {
-            $packages = $this->pool->whatProvides($job['packageName'], null);
-        }
-
-        return 'Job(cmd='.$job['cmd'].', target='.$packageName.', packages=['.$this->getPackageList($packages).'])';
-    }
-
     protected function getPackageList($packages)
     {
         $prepared = array();
@@ -250,7 +208,7 @@ class Problem
     }
 
     /**
-     * Turns a constraint into text usable in a sentence describing a job
+     * Turns a constraint into text usable in a sentence describing a request
      *
      * @param  \Composer\Semver\Constraint\ConstraintInterface $constraint
      * @return string

+ 6 - 16
src/Composer/DependencyResolver/Request.php

@@ -24,7 +24,7 @@ use Composer\Semver\Constraint\ConstraintInterface;
 class Request
 {
     protected $lockedRepository;
-    protected $jobs = array();
+    protected $requires = array();
     protected $fixedPackages = array();
     protected $unlockables = array();
 
@@ -33,9 +33,10 @@ class Request
         $this->lockedRepository = $lockedRepository;
     }
 
-    public function install($packageName, ConstraintInterface $constraint = null)
+    public function requireName($packageName, ConstraintInterface $constraint = null)
     {
-        $this->addJob($packageName, 'install', $constraint);
+        $packageName = strtolower($packageName);
+        $this->requires[$packageName] = $constraint;
     }
 
     /**
@@ -52,20 +53,9 @@ class Request
         }
     }
 
-    protected function addJob($packageName, $cmd, ConstraintInterface $constraint = null)
-    {
-        $packageName = strtolower($packageName);
-
-        $this->jobs[] = array(
-            'cmd' => $cmd,
-            'packageName' => $packageName,
-            'constraint' => $constraint,
-        );
-    }
-
-    public function getJobs()
+    public function getRequires()
     {
-        return $this->jobs;
+        return $this->requires;
     }
 
     public function getFixedPackages()

+ 32 - 21
src/Composer/DependencyResolver/Rule.php

@@ -24,8 +24,8 @@ abstract class Rule
 {
     // reason constants
     const RULE_INTERNAL_ALLOW_UPDATE = 1;
-    const RULE_JOB_INSTALL = 2;
-    const RULE_JOB_REMOVE = 3;
+    const RULE_ROOT_REQUIRE = 2;
+    const RULE_FIXED = 3;
     const RULE_PACKAGE_CONFLICT = 6;
     const RULE_PACKAGE_REQUIRES = 7;
     const RULE_PACKAGE_OBSOLETES = 8;
@@ -41,22 +41,17 @@ abstract class Rule
     const BITFIELD_DISABLED = 16;
 
     protected $bitfield;
-    protected $job;
+    protected $request;
     protected $reasonData;
 
     /**
      * @param int                   $reason     A RULE_* constant describing the reason for generating this rule
      * @param Link|PackageInterface $reasonData
-     * @param array                 $job        The job this rule was created from
      */
-    public function __construct($reason, $reasonData, $job = null)
+    public function __construct($reason, $reasonData)
     {
         $this->reasonData = $reasonData;
 
-        if ($job) {
-            $this->job = $job;
-        }
-
         $this->bitfield = (0 << self::BITFIELD_DISABLED) |
             ($reason << self::BITFIELD_REASON) |
             (255 << self::BITFIELD_TYPE);
@@ -66,11 +61,6 @@ abstract class Rule
 
     abstract public function getHash();
 
-    public function getJob()
-    {
-        return $this->job;
-    }
-
     abstract public function equals(Rule $rule);
 
     public function getReason()
@@ -85,11 +75,17 @@ abstract class Rule
 
     public function getRequiredPackage()
     {
-        if ($this->getReason() === self::RULE_JOB_INSTALL) {
-            return $this->reasonData;
+        $reason = $this->getReason();
+
+        if ($reason === self::RULE_ROOT_REQUIRE) {
+            return $this->reasonData['packageName'];
+        }
+
+        if ($reason === self::RULE_FIXED) {
+            return $this->reasonData['package']->getName();
         }
 
-        if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
+        if ($reason === self::RULE_PACKAGE_REQUIRES) {
             return $this->reasonData->getTarget();
         }
     }
@@ -142,11 +138,24 @@ abstract class Rule
             case self::RULE_INTERNAL_ALLOW_UPDATE:
                 return $ruleText;
 
-            case self::RULE_JOB_INSTALL:
-                return "Install command rule ($ruleText)";
+            case self::RULE_ROOT_REQUIRE:
+                $packageName = $this->reasonData['packageName'];
+                $constraint = $this->reasonData['constraint'];
+
+                $packages = $pool->whatProvides($packageName, $constraint);
+                if (!$packages) {
+                    return 'No package found to satisfy root composer.json require '.$packageName.($constraint ? ' '.$constraint->getPrettyString() : '');
+                }
 
-            case self::RULE_JOB_REMOVE:
-                return "Remove command rule ($ruleText)";
+                return 'Root composer.json requires '.$packageName.($constraint ? ' '.$constraint->getPrettyString() : '').' -> satisfiable by '.$this->formatPackagesUnique($pool, $packages).'.';
+
+            case self::RULE_FIXED:
+                $package = $this->reasonData['package'];
+                if ($this->reasonData['lockable']) {
+                    return $package->getPrettyName().' is locked to version '.$package->getPrettyVersion().' and an update of this package was not requested.';
+                }
+
+                return $package->getPrettyName().' is present at version '.$package->getPrettyVersion() . ' and cannot be modified by Composer';
 
             case self::RULE_PACKAGE_CONFLICT:
                 $package1 = $pool->literalToPackage($literals[0]);
@@ -263,6 +272,8 @@ 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) {
             if (!is_object($package)) {

+ 2 - 3
src/Composer/DependencyResolver/Rule2Literals.php

@@ -28,11 +28,10 @@ class Rule2Literals extends Rule
      * @param int                   $literal2
      * @param int                   $reason     A RULE_* constant describing the reason for generating this rule
      * @param Link|PackageInterface $reasonData
-     * @param array                 $job        The job this rule was created from
      */
-    public function __construct($literal1, $literal2, $reason, $reasonData, $job = null)
+    public function __construct($literal1, $literal2, $reason, $reasonData)
     {
-        parent::__construct($reason, $reasonData, $job);
+        parent::__construct($reason, $reasonData);
 
         if ($literal1 < $literal2) {
             $this->literal1 = $literal1;

+ 2 - 2
src/Composer/DependencyResolver/RuleSet.php

@@ -19,7 +19,7 @@ class RuleSet implements \IteratorAggregate, \Countable
 {
     // highest priority => lowest number
     const TYPE_PACKAGE = 0;
-    const TYPE_JOB = 1;
+    const TYPE_REQUEST = 1;
     const TYPE_LEARNED = 4;
 
     /**
@@ -32,7 +32,7 @@ class RuleSet implements \IteratorAggregate, \Countable
     protected static $types = array(
         255 => 'UNKNOWN',
         self::TYPE_PACKAGE => 'PACKAGE',
-        self::TYPE_JOB => 'JOB',
+        self::TYPE_REQUEST => 'REQUEST',
         self::TYPE_LEARNED => 'LEARNED',
     );
 

+ 19 - 40
src/Composer/DependencyResolver/RuleSetGenerator.php

@@ -76,33 +76,17 @@ class RuleSetGenerator
      * @param  array $packages The set of packages to choose from
      * @param  int   $reason   A RULE_* constant describing the reason for
      *                         generating this rule
-     * @param  array $job      The job this rule was created from
+     * @param  array $reasonData Additional data like the root require or fix request info
      * @return Rule  The generated rule
      */
-    protected function createInstallOneOfRule(array $packages, $reason, $job)
+    protected function createInstallOneOfRule(array $packages, $reason, $reasonData)
     {
         $literals = array();
         foreach ($packages as $package) {
             $literals[] = $package->id;
         }
 
-        return new GenericRule($literals, $reason, $job['packageName'], $job);
-    }
-
-    /**
-     * Creates a rule to remove a package
-     *
-     * The rule for a package A is (-A).
-     *
-     * @param  PackageInterface $package The package to be removed
-     * @param  int              $reason  A RULE_* constant describing the
-     *                                   reason for generating this rule
-     * @param  array            $job     The job this rule was created from
-     * @return Rule             The generated rule
-     */
-    protected function createRemoveRule(PackageInterface $package, $reason, $job)
-    {
-        return new GenericRule(array(-$package->id), $reason, $job['packageName'], $job);
+        return new GenericRule($literals, $reason, $reasonData);
     }
 
     /**
@@ -302,34 +286,29 @@ class RuleSetGenerator
 
             $this->addRulesForPackage($package, $ignorePlatformReqs);
 
-            $rule = $this->createInstallOneOfRule(array($package), Rule::RULE_JOB_INSTALL, array(
-                'cmd' => 'fix',
-                'packageName' => $package->getName(),
-                'constraint' => null,
+            $rule = $this->createInstallOneOfRule(array($package), Rule::RULE_FIXED, array(
                 'package' => $package,
                 'lockable' => !isset($unlockableMap[$package->id]),
-                'fixed' => true
             ));
-            $this->addRule(RuleSet::TYPE_JOB, $rule);
+            $this->addRule(RuleSet::TYPE_REQUEST, $rule);
         }
 
-        foreach ($request->getJobs() as $job) {
-            switch ($job['cmd']) {
-                case 'install':
-                    if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
-                        break;
-                    }
+        foreach ($request->getRequires() as $packageName => $constraint) {
+            if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $packageName)) {
+                continue;
+            }
 
-                    $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
-                    if ($packages) {
-                        foreach ($packages as $package) {
-                            $this->addRulesForPackage($package, $ignorePlatformReqs);
-                        }
+            $packages = $this->pool->whatProvides($packageName, $constraint);
+            if ($packages) {
+                foreach ($packages as $package) {
+                    $this->addRulesForPackage($package, $ignorePlatformReqs);
+                }
 
-                        $rule = $this->createInstallOneOfRule($packages, Rule::RULE_JOB_INSTALL, $job);
-                        $this->addRule(RuleSet::TYPE_JOB, $rule);
-                    }
-                    break;
+                $rule = $this->createInstallOneOfRule($packages, Rule::RULE_ROOT_REQUIRE, array(
+                    'packageName' => $packageName,
+                    'constraint' => $constraint,
+                ));
+                $this->addRule(RuleSet::TYPE_REQUEST, $rule);
             }
         }
     }

+ 18 - 44
src/Composer/DependencyResolver/Solver.php

@@ -124,19 +124,19 @@ class Solver
 
                 $problem->addRule($rule);
                 $problem->addRule($conflict);
-                $this->disableProblem($rule);
+                $rule->disable();
                 $this->problems[] = $problem;
                 continue;
             }
 
-            // conflict with another job
+            // conflict with another root require/fixed package
             $problem = new Problem($this->pool);
             $problem->addRule($rule);
             $problem->addRule($conflict);
 
-            // push all of our rules (can only be job rules)
+            // push all of our rules (can only be root require/fixed package rules)
             // asserting this literal on the problem stack
-            foreach ($this->rules->getIteratorFor(RuleSet::TYPE_JOB) as $assertRule) {
+            foreach ($this->rules->getIteratorFor(RuleSet::TYPE_REQUEST) as $assertRule) {
                 if ($assertRule->isDisabled() || !$assertRule->isAssertion()) {
                     continue;
                 }
@@ -148,7 +148,7 @@ class Solver
                     continue;
                 }
                 $problem->addRule($assertRule);
-                $this->disableProblem($assertRule);
+                $assertRule->disable();
             }
             $this->problems[] = $problem;
 
@@ -171,19 +171,15 @@ class Solver
      */
     protected function checkForRootRequireProblems($request, $ignorePlatformReqs)
     {
-        foreach ($request->getJobs() as $job) {
-            switch ($job['cmd']) {
-                case 'install':
-                    if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
-                        break;
-                    }
+        foreach ($request->getRequires() as $packageName => $constraint) {
+            if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $packageName)) {
+                continue;
+            }
 
-                    if (!$this->pool->whatProvides($job['packageName'], $job['constraint'])) {
-                        $problem = new Problem($this->pool);
-                        $problem->addRule(new GenericRule(array(), null, null, $job));
-                        $this->problems[] = $problem;
-                    }
-                    break;
+            if (!$this->pool->whatProvides($packageName, $constraint)) {
+                $problem = new Problem($this->pool);
+                $problem->addRule(new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => $packageName, 'constraint' => $constraint)));
+                $this->problems[] = $problem;
             }
         }
     }
@@ -208,7 +204,7 @@ class Solver
             $this->watchGraph->insert(new RuleWatchNode($rule));
         }
 
-        /* make decisions based on job/update assertions */
+        /* make decisions based on root require/fix assertions */
         $this->makeAssertionRuleDecisions();
 
         $this->io->writeError('Resolving dependencies through SAT', true, IOInterface::DEBUG);
@@ -562,28 +558,6 @@ class Solver
         return 0;
     }
 
-    /**
-     * @param Rule $why
-     */
-    private function disableProblem(Rule $why)
-    {
-        $job = $why->getJob();
-
-        if (!$job) {
-            $why->disable();
-
-            return;
-        }
-
-        // disable all rules of this job
-        foreach ($this->rules as $rule) {
-            /** @var Rule $rule */
-            if ($job === $rule->getJob()) {
-                $rule->disable();
-            }
-        }
-    }
-
     private function resetSolver()
     {
         $this->decisions->reset();
@@ -631,7 +605,7 @@ class Solver
         /*
          * here's the main loop:
          * 1) propagate new decisions (only needed once)
-         * 2) fulfill jobs
+         * 2) fulfill root requires/fixed packages
          * 3) fulfill all unresolved rules
          * 4) minimalize solution if we had choices
          * if we encounter a problem, we rewind to a safe level and restart
@@ -657,9 +631,9 @@ class Solver
                 }
             }
 
-            // handle job rules
+            // handle root require/fixed package rules
             if ($level < $systemLevel) {
-                $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_JOB);
+                $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_REQUEST);
                 foreach ($iterator as $rule) {
                     if ($rule->isEnabled()) {
                         $decisionQueue = array();
@@ -704,7 +678,7 @@ class Solver
 
                 $systemLevel = $level + 1;
 
-                // jobs left
+                // root requires/fixed packages left
                 $iterator->next();
                 if ($iterator->valid()) {
                     continue;

+ 2 - 2
src/Composer/DependencyResolver/SolverProblemsException.php

@@ -78,8 +78,8 @@ class SolverProblemsException extends \RuntimeException
     private function hasExtensionProblems(array $reasonSets)
     {
         foreach ($reasonSets as $reasonSet) {
-            foreach ($reasonSet as $reason) {
-                if (isset($reason["rule"]) && 0 === strpos($reason["rule"]->getRequiredPackage(), 'ext-')) {
+            foreach ($reasonSet as $rule) {
+                if (0 === strpos($rule->getRequiredPackage(), 'ext-')) {
                     return true;
                 }
             }

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

@@ -170,7 +170,7 @@ class Transaction
 
         // TODO skip updates which don't update? is this needed? we shouldn't schedule this update in the first place?
         /*
-        if ('update' === $jobType) {
+        if ('update' === $opType) {
             $targetPackage = $operation->getTargetPackage();
             if ($targetPackage->isDev()) {
                 $initialPackage = $operation->getInitialPackage();

+ 6 - 7
src/Composer/Installer.php

@@ -371,11 +371,11 @@ class Installer
         // if we're updating mirrors we want to keep exactly the same versions installed which are in the lock file, but we want current remote metadata
         if ($this->updateMirrors) {
             foreach ($lockedRepository->getPackages() as $lockedPackage) {
-                $request->install($lockedPackage->getName(), new Constraint('==', $lockedPackage->getVersion()));
+                $request->requireName($lockedPackage->getName(), new Constraint('==', $lockedPackage->getVersion()));
             }
         } else {
             foreach ($links as $link) {
-                $request->install($link->getTarget(), $link->getConstraint());
+                $request->requireName($link->getTarget(), $link->getConstraint());
             }
         }
 
@@ -464,13 +464,12 @@ class Installer
 
         foreach ($lockTransaction->getOperations() as $operation) {
             // collect suggestions
-            $jobType = $operation->getJobType();
             if ($operation instanceof InstallOperation) {
                 $this->suggestedPackagesReporter->addSuggestionsFromPackage($operation->getPackage());
             }
 
             // output op, but alias op only in debug verbosity
-            if (false === strpos($operation->getJobType(), 'Alias') || $this->io->isDebug()) {
+            if (false === strpos($operation->getOperationType(), 'Alias') || $this->io->isDebug()) {
                 $this->io->writeError('  - ' . $operation->show(true));
             }
         }
@@ -524,7 +523,7 @@ class Installer
 
         $links = $this->package->getRequires();
         foreach ($links as $link) {
-            $request->install($link->getTarget(), $link->getConstraint());
+            $request->requireName($link->getTarget(), $link->getConstraint());
         }
 
         $pool = $repositorySet->createPool($request);
@@ -582,7 +581,7 @@ class Installer
             }
 
             foreach ($this->locker->getPlatformRequirements($this->devMode) as $link) {
-                $request->install($link->getTarget(), $link->getConstraint());
+                $request->requireName($link->getTarget(), $link->getConstraint());
             }
 
             //$this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $policy, $repositorySet, $installedRepo, $request);
@@ -656,7 +655,7 @@ class Installer
         } else {
             foreach ($localRepoTransaction->getOperations() as $operation) {
                 // output op, but alias op only in debug verbosity
-                if (false === strpos($operation->getJobType(), 'Alias') || $this->io->isDebug()) {
+                if (false === strpos($operation->getOperationType(), 'Alias') || $this->io->isDebug()) {
                     $this->io->writeError('  - ' . $operation->show(false));
                 }
             }

+ 19 - 19
src/Composer/Installer/InstallationManager.php

@@ -173,14 +173,14 @@ class InstallationManager
         $promises = array();
 
         foreach ($operations as $operation) {
-            $jobType = $operation->getJobType();
+            $opType = $operation->getOperationType();
             $promise = null;
 
-            if ($jobType === 'install') {
+            if ($opType === 'install') {
                 $package = $operation->getPackage();
                 $installer = $this->getInstaller($package->getType());
                 $promise = $installer->download($package);
-            } elseif ($jobType === 'update') {
+            } elseif ($opType === 'update') {
                 $target = $operation->getTargetPackage();
                 $targetType = $target->getType();
                 $installer = $this->getInstaller($targetType);
@@ -197,29 +197,29 @@ class InstallationManager
         }
 
         foreach ($operations as $operation) {
-            $jobType = $operation->getJobType();
+            $opType = $operation->getOperationType();
 
             // ignoring alias ops as they don't need to execute anything
-            if (!in_array($jobType, array('update', 'install', 'uninstall'))) {
+            if (!in_array($opType, array('update', 'install', 'uninstall'))) {
                 // output alias ops in debug verbosity as they have no output otherwise
                 if ($this->io->isDebug()) {
                     $this->io->writeError('  - ' . $operation->show(false));
                 }
-                $this->$jobType($repo, $operation);
+                $this->$opType($repo, $operation);
 
                 continue;
             }
 
-            if ($jobType === 'install' || $jobType === 'uninstall') {
+            if ($opType === 'install' || $opType === 'uninstall') {
                 $package = $operation->getPackage();
                 $initialPackage = null;
-            } elseif ($jobType === 'update') {
+            } elseif ($opType === 'update') {
                 $package = $operation->getTargetPackage();
                 $initialPackage = $operation->getInitialPackage();
             }
             $installer = $this->getInstaller($package->getType());
 
-            $event = 'Composer\Installer\PackageEvents::PRE_PACKAGE_'.strtoupper($jobType);
+            $event = 'Composer\Installer\PackageEvents::PRE_PACKAGE_'.strtoupper($opType);
             if (defined($event) && $runScripts && $this->eventDispatcher) {
                 $this->eventDispatcher->dispatchPackageEvent(constant($event), $devMode, $repo, $operations, $operation);
             }
@@ -229,26 +229,26 @@ class InstallationManager
             $loop = $this->loop;
             $io = $this->io;
 
-            $promise = $installer->prepare($jobType, $package, $initialPackage);
+            $promise = $installer->prepare($opType, $package, $initialPackage);
             if (null === $promise) {
                 $promise = new \React\Promise\Promise(function ($resolve, $reject) { $resolve(); });
             }
 
-            $promise = $promise->then(function () use ($jobType, $installManager, $repo, $operation) {
-                return $installManager->$jobType($repo, $operation);
-            })->then(function () use ($jobType, $installer, $package, $initialPackage) {
-                return $installer->cleanup($jobType, $package, $initialPackage);
-            })->then(function () use ($jobType, $runScripts, $dispatcher, $installManager, $devMode, $repo, $operations, $operation) {
+            $promise = $promise->then(function () use ($opType, $installManager, $repo, $operation) {
+                return $installManager->$opType($repo, $operation);
+            })->then(function () use ($opType, $installer, $package, $initialPackage) {
+                return $installer->cleanup($opType, $package, $initialPackage);
+            })->then(function () use ($opType, $runScripts, $dispatcher, $installManager, $devMode, $repo, $operations, $operation) {
                 $repo->write($devMode, $installManager);
 
-                $event = 'Composer\Installer\PackageEvents::POST_PACKAGE_'.strtoupper($jobType);
+                $event = 'Composer\Installer\PackageEvents::POST_PACKAGE_'.strtoupper($opType);
                 if (defined($event) && $runScripts && $dispatcher) {
                     $dispatcher->dispatchPackageEvent(constant($event), $devMode, $repo, $operations, $operation);
                 }
-            }, function ($e) use ($jobType, $installer, $package, $initialPackage, $loop, $io) {
-                $io->writeError('    <error>' . ucfirst($jobType) .' of '.$package->getPrettyName().' failed</error>');
+            }, function ($e) use ($opType, $installer, $package, $initialPackage, $loop, $io) {
+                $io->writeError('    <error>' . ucfirst($opType) .' of '.$package->getPrettyName().' failed</error>');
 
-                $promise = $installer->cleanup($jobType, $package, $initialPackage);
+                $promise = $installer->cleanup($opType, $package, $initialPackage);
                 if ($promise) {
                     $loop->wait(array($promise));
                 }

+ 1 - 1
src/Composer/Package/Link.php

@@ -123,6 +123,6 @@ class Link
      */
     public function getPrettyString(PackageInterface $sourcePackage)
     {
-        return $sourcePackage->getPrettyString().' '.$this->description.' '.$this->target.' '.$this->constraint->getPrettyString().'';
+        return $sourcePackage->getPrettyString().' '.$this->description.' '.$this->target.($this->constraint ? ' '.$this->constraint->getPrettyString() : '');
     }
 }

+ 1 - 1
src/Composer/Repository/RepositorySet.php

@@ -157,7 +157,7 @@ class RepositorySet
         $request = new Request($lockedRepo);
 
         foreach ($packageNames as $packageName) {
-            $request->install($packageName);
+            $request->requireName($packageName);
         }
 
         return $this->createPool($request);

+ 1 - 1
tests/Composer/Test/DependencyResolver/PoolBuilderTest.php

@@ -82,7 +82,7 @@ class PoolBuilderTest extends TestCase
 
         $request = new Request();
         foreach ($requestData as $package => $constraint) {
-            $request->install($package, $parser->parseConstraints($constraint));
+            $request->requireName($package, $parser->parseConstraints($constraint));
         }
 
         foreach ($fixed as $fixedPackage) {

+ 6 - 6
tests/Composer/Test/DependencyResolver/RequestTest.php

@@ -30,13 +30,13 @@ class RequestTest extends TestCase
         $repo->addPackage($foobar);
 
         $request = new Request();
-        $request->install('foo');
+        $request->requireName('foo');
 
         $this->assertEquals(
             array(
-                array('cmd' => 'install', 'packageName' => 'foo', 'constraint' => null),
+                'foo' => null,
             ),
-            $request->getJobs()
+            $request->getRequires()
         );
     }
 
@@ -52,13 +52,13 @@ class RequestTest extends TestCase
         $repo2->addPackage($foo2);
 
         $request = new Request();
-        $request->install('foo', $constraint = $this->getVersionConstraint('=', '1'));
+        $request->requireName('foo', $constraint = $this->getVersionConstraint('=', '1'));
 
         $this->assertEquals(
             array(
-                    array('cmd' => 'install', 'packageName' => 'foo', 'constraint' => $constraint),
+                'foo' => $constraint,
             ),
-            $request->getJobs()
+            $request->getRequires()
         );
     }
 }

+ 7 - 7
tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php

@@ -30,9 +30,9 @@ class RuleSetIteratorTest extends TestCase
         $this->pool = new Pool();
 
         $this->rules = array(
-            RuleSet::TYPE_JOB => array(
-                new GenericRule(array(), Rule::RULE_JOB_INSTALL, null),
-                new GenericRule(array(), Rule::RULE_JOB_INSTALL, null),
+            RuleSet::TYPE_REQUEST => array(
+                new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null),
+                new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null),
             ),
             RuleSet::TYPE_LEARNED => array(
                 new GenericRule(array(), Rule::RULE_INTERNAL_ALLOW_UPDATE, null),
@@ -51,8 +51,8 @@ class RuleSetIteratorTest extends TestCase
         }
 
         $expected = array(
-            $this->rules[RuleSet::TYPE_JOB][0],
-            $this->rules[RuleSet::TYPE_JOB][1],
+            $this->rules[RuleSet::TYPE_REQUEST][0],
+            $this->rules[RuleSet::TYPE_REQUEST][1],
             $this->rules[RuleSet::TYPE_LEARNED][0],
         );
 
@@ -69,8 +69,8 @@ class RuleSetIteratorTest extends TestCase
         }
 
         $expected = array(
-            RuleSet::TYPE_JOB,
-            RuleSet::TYPE_JOB,
+            RuleSet::TYPE_REQUEST,
+            RuleSet::TYPE_REQUEST,
             RuleSet::TYPE_LEARNED,
         );
 

+ 31 - 31
tests/Composer/Test/DependencyResolver/RuleSetTest.php

@@ -26,9 +26,9 @@ class RuleSetTest extends TestCase
     {
         $rules = array(
             RuleSet::TYPE_PACKAGE => array(),
-            RuleSet::TYPE_JOB => array(
-                new GenericRule(array(1), Rule::RULE_JOB_INSTALL, null),
-                new GenericRule(array(2), Rule::RULE_JOB_INSTALL, null),
+            RuleSet::TYPE_REQUEST => array(
+                new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null),
+                new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, null),
             ),
             RuleSet::TYPE_LEARNED => array(
                 new GenericRule(array(), Rule::RULE_INTERNAL_ALLOW_UPDATE, null),
@@ -37,9 +37,9 @@ class RuleSetTest extends TestCase
 
         $ruleSet = new RuleSet;
 
-        $ruleSet->add($rules[RuleSet::TYPE_JOB][0], RuleSet::TYPE_JOB);
+        $ruleSet->add($rules[RuleSet::TYPE_REQUEST][0], RuleSet::TYPE_REQUEST);
         $ruleSet->add($rules[RuleSet::TYPE_LEARNED][0], RuleSet::TYPE_LEARNED);
-        $ruleSet->add($rules[RuleSet::TYPE_JOB][1], RuleSet::TYPE_JOB);
+        $ruleSet->add($rules[RuleSet::TYPE_REQUEST][1], RuleSet::TYPE_REQUEST);
 
         $this->assertEquals($rules, $ruleSet->getRules());
     }
@@ -47,20 +47,20 @@ class RuleSetTest extends TestCase
     public function testAddIgnoresDuplicates()
     {
         $rules = array(
-            RuleSet::TYPE_JOB => array(
-                new GenericRule(array(), Rule::RULE_JOB_INSTALL, null),
-                new GenericRule(array(), Rule::RULE_JOB_INSTALL, null),
-                new GenericRule(array(), Rule::RULE_JOB_INSTALL, null),
+            RuleSet::TYPE_REQUEST => array(
+                new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null),
+                new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null),
+                new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null),
             ),
         );
 
         $ruleSet = new RuleSet;
 
-        $ruleSet->add($rules[RuleSet::TYPE_JOB][0], RuleSet::TYPE_JOB);
-        $ruleSet->add($rules[RuleSet::TYPE_JOB][1], RuleSet::TYPE_JOB);
-        $ruleSet->add($rules[RuleSet::TYPE_JOB][2], RuleSet::TYPE_JOB);
+        $ruleSet->add($rules[RuleSet::TYPE_REQUEST][0], RuleSet::TYPE_REQUEST);
+        $ruleSet->add($rules[RuleSet::TYPE_REQUEST][1], RuleSet::TYPE_REQUEST);
+        $ruleSet->add($rules[RuleSet::TYPE_REQUEST][2], RuleSet::TYPE_REQUEST);
 
-        $this->assertCount(1, $ruleSet->getIteratorFor(array(RuleSet::TYPE_JOB)));
+        $this->assertCount(1, $ruleSet->getIteratorFor(array(RuleSet::TYPE_REQUEST)));
     }
 
     /**
@@ -70,15 +70,15 @@ class RuleSetTest extends TestCase
     {
         $ruleSet = new RuleSet;
 
-        $ruleSet->add(new GenericRule(array(), Rule::RULE_JOB_INSTALL, null), 7);
+        $ruleSet->add(new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null), 7);
     }
 
     public function testCount()
     {
         $ruleSet = new RuleSet;
 
-        $ruleSet->add(new GenericRule(array(1), Rule::RULE_JOB_INSTALL, null), RuleSet::TYPE_JOB);
-        $ruleSet->add(new GenericRule(array(2), Rule::RULE_JOB_INSTALL, null), RuleSet::TYPE_JOB);
+        $ruleSet->add(new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null), RuleSet::TYPE_REQUEST);
+        $ruleSet->add(new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, null), RuleSet::TYPE_REQUEST);
 
         $this->assertEquals(2, $ruleSet->count());
     }
@@ -87,8 +87,8 @@ class RuleSetTest extends TestCase
     {
         $ruleSet = new RuleSet;
 
-        $rule = new GenericRule(array(), Rule::RULE_JOB_INSTALL, null);
-        $ruleSet->add($rule, RuleSet::TYPE_JOB);
+        $rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null);
+        $ruleSet->add($rule, RuleSet::TYPE_REQUEST);
 
         $this->assertSame($rule, $ruleSet->ruleById[0]);
     }
@@ -97,9 +97,9 @@ class RuleSetTest extends TestCase
     {
         $ruleSet = new RuleSet;
 
-        $rule1 = new GenericRule(array(1), Rule::RULE_JOB_INSTALL, null);
-        $rule2 = new GenericRule(array(2), Rule::RULE_JOB_INSTALL, null);
-        $ruleSet->add($rule1, RuleSet::TYPE_JOB);
+        $rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null);
+        $rule2 = new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, null);
+        $ruleSet->add($rule1, RuleSet::TYPE_REQUEST);
         $ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
 
         $iterator = $ruleSet->getIterator();
@@ -112,10 +112,10 @@ class RuleSetTest extends TestCase
     public function testGetIteratorFor()
     {
         $ruleSet = new RuleSet;
-        $rule1 = new GenericRule(array(1), Rule::RULE_JOB_INSTALL, null);
-        $rule2 = new GenericRule(array(2), Rule::RULE_JOB_INSTALL, null);
+        $rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null);
+        $rule2 = new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, null);
 
-        $ruleSet->add($rule1, RuleSet::TYPE_JOB);
+        $ruleSet->add($rule1, RuleSet::TYPE_REQUEST);
         $ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
 
         $iterator = $ruleSet->getIteratorFor(RuleSet::TYPE_LEARNED);
@@ -126,13 +126,13 @@ class RuleSetTest extends TestCase
     public function testGetIteratorWithout()
     {
         $ruleSet = new RuleSet;
-        $rule1 = new GenericRule(array(1), Rule::RULE_JOB_INSTALL, null);
-        $rule2 = new GenericRule(array(2), Rule::RULE_JOB_INSTALL, null);
+        $rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null);
+        $rule2 = new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, null);
 
-        $ruleSet->add($rule1, RuleSet::TYPE_JOB);
+        $ruleSet->add($rule1, RuleSet::TYPE_REQUEST);
         $ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
 
-        $iterator = $ruleSet->getIteratorWithout(RuleSet::TYPE_JOB);
+        $iterator = $ruleSet->getIteratorWithout(RuleSet::TYPE_REQUEST);
 
         $this->assertSame($rule2, $iterator->current());
     }
@@ -145,10 +145,10 @@ class RuleSetTest extends TestCase
 
         $ruleSet = new RuleSet;
         $literal = $p->getId();
-        $rule = new GenericRule(array($literal), Rule::RULE_JOB_INSTALL, null);
+        $rule = new GenericRule(array($literal), Rule::RULE_ROOT_REQUIRE, array('packageName' => 'foo/bar', 'constraint' => null));
 
-        $ruleSet->add($rule, RuleSet::TYPE_JOB);
+        $ruleSet->add($rule, RuleSet::TYPE_REQUEST);
 
-        $this->assertContains('JOB     : Install command rule (install foo 2.1)', $ruleSet->getPrettyString($pool));
+        $this->assertContains('REQUEST : No package found to satisfy root composer.json require foo/bar', $ruleSet->getPrettyString($pool));
     }
 }

+ 17 - 16
tests/Composer/Test/DependencyResolver/RuleTest.php

@@ -17,6 +17,7 @@ use Composer\DependencyResolver\Rule;
 use Composer\DependencyResolver\RuleSet;
 use Composer\DependencyResolver\Pool;
 use Composer\Package\BasePackage;
+use Composer\Package\Link;
 use Composer\Repository\ArrayRepository;
 use Composer\Test\TestCase;
 
@@ -24,7 +25,7 @@ class RuleTest extends TestCase
 {
     public function testGetHash()
     {
-        $rule = new GenericRule(array(123), Rule::RULE_JOB_INSTALL, null);
+        $rule = new GenericRule(array(123), Rule::RULE_ROOT_REQUIRE, null);
 
         $hash = unpack('ihash', md5('123', true));
         $this->assertEquals($hash['hash'], $rule->getHash());
@@ -32,39 +33,39 @@ class RuleTest extends TestCase
 
     public function testEqualsForRulesWithDifferentHashes()
     {
-        $rule = new GenericRule(array(1, 2), Rule::RULE_JOB_INSTALL, null);
-        $rule2 = new GenericRule(array(1, 3), Rule::RULE_JOB_INSTALL, null);
+        $rule = new GenericRule(array(1, 2), Rule::RULE_ROOT_REQUIRE, null);
+        $rule2 = new GenericRule(array(1, 3), Rule::RULE_ROOT_REQUIRE, null);
 
         $this->assertFalse($rule->equals($rule2));
     }
 
     public function testEqualsForRulesWithDifferLiteralsQuantity()
     {
-        $rule = new GenericRule(array(1, 12), Rule::RULE_JOB_INSTALL, null);
-        $rule2 = new GenericRule(array(1), Rule::RULE_JOB_INSTALL, null);
+        $rule = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, null);
+        $rule2 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null);
 
         $this->assertFalse($rule->equals($rule2));
     }
 
     public function testEqualsForRulesWithSameLiterals()
     {
-        $rule = new GenericRule(array(1, 12), Rule::RULE_JOB_INSTALL, null);
-        $rule2 = new GenericRule(array(1, 12), Rule::RULE_JOB_INSTALL, null);
+        $rule = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, null);
+        $rule2 = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, null);
 
         $this->assertTrue($rule->equals($rule2));
     }
 
     public function testSetAndGetType()
     {
-        $rule = new GenericRule(array(), Rule::RULE_JOB_INSTALL, null);
-        $rule->setType(RuleSet::TYPE_JOB);
+        $rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null);
+        $rule->setType(RuleSet::TYPE_REQUEST);
 
-        $this->assertEquals(RuleSet::TYPE_JOB, $rule->getType());
+        $this->assertEquals(RuleSet::TYPE_REQUEST, $rule->getType());
     }
 
     public function testEnable()
     {
-        $rule = new GenericRule(array(), Rule::RULE_JOB_INSTALL, null);
+        $rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null);
         $rule->disable();
         $rule->enable();
 
@@ -74,7 +75,7 @@ class RuleTest extends TestCase
 
     public function testDisable()
     {
-        $rule = new GenericRule(array(), Rule::RULE_JOB_INSTALL, null);
+        $rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null);
         $rule->enable();
         $rule->disable();
 
@@ -84,8 +85,8 @@ class RuleTest extends TestCase
 
     public function testIsAssertions()
     {
-        $rule = new GenericRule(array(1, 12), Rule::RULE_JOB_INSTALL, null);
-        $rule2 = new GenericRule(array(1), Rule::RULE_JOB_INSTALL, null);
+        $rule = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, null);
+        $rule2 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null);
 
         $this->assertFalse($rule->isAssertion());
         $this->assertTrue($rule2->isAssertion());
@@ -98,8 +99,8 @@ class RuleTest extends TestCase
             $p2 = $this->getPackage('baz', '1.1'),
         ));
 
-        $rule = new GenericRule(array($p1->getId(), -$p2->getId()), Rule::RULE_JOB_INSTALL, null);
+        $rule = new GenericRule(array($p1->getId(), -$p2->getId()), Rule::RULE_PACKAGE_REQUIRES, new Link('baz', 'foo'));
 
-        $this->assertEquals('Install command rule (don\'t install baz 1.1|install foo 2.1)', $rule->getPrettyString($pool));
+        $this->assertEquals('baz 1.1 relates to foo -> satisfiable by foo[2.1].', $rule->getPrettyString($pool));
     }
 }

+ 49 - 49
tests/Composer/Test/DependencyResolver/SolverTest.php

@@ -50,7 +50,7 @@ class SolverTest extends TestCase
         $this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
         $this->reposComplete();
 
-        $this->request->install('A');
+        $this->request->requireName('A');
 
         $this->checkSolverResult(array(
             array('job' => 'install', 'package' => $packageA),
@@ -72,7 +72,7 @@ class SolverTest extends TestCase
         $this->repo->addPackage($this->getPackage('A', '1.0'));
         $this->reposComplete();
 
-        $this->request->install('B', $this->getVersionConstraint('==', '1'));
+        $this->request->requireName('B', $this->getVersionConstraint('==', '1'));
 
         $this->createSolver();
         try {
@@ -97,7 +97,7 @@ class SolverTest extends TestCase
         $this->repoSet->addRepository($repo1);
         $this->repoSet->addRepository($repo2);
 
-        $this->request->install('foo');
+        $this->request->requireName('foo');
 
         $this->checkSolverResult(array(
                 array('job' => 'install', 'package' => $foo1),
@@ -114,7 +114,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
+        $this->request->requireName('A');
 
         $this->checkSolverResult(array(
             array('job' => 'install', 'package' => $packageB),
@@ -140,7 +140,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
+        $this->request->requireName('A');
 
         $this->checkSolverResult(array(
             array('job' => 'install', 'package' => $newPackageB11),
@@ -164,9 +164,9 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
-        $this->request->install('B');
-        $this->request->install('C');
+        $this->request->requireName('A');
+        $this->request->requireName('B');
+        $this->request->requireName('C');
 
         $this->checkSolverResult(array(
             array('job' => 'install', 'package' => $packageA),
@@ -206,7 +206,7 @@ class SolverTest extends TestCase
         $packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0.0.0'), 'requires')));
 
         $this->request->fixPackage($packageA);
-        $this->request->install('B', $this->getVersionConstraint('=', '1.1.0.0'));
+        $this->request->requireName('B', $this->getVersionConstraint('=', '1.1.0.0'));
 
         $this->checkSolverResult(array(
             array('job' => 'update', 'from' => $packageB, 'to' => $newPackageB),
@@ -219,7 +219,7 @@ class SolverTest extends TestCase
         $this->repo->addPackage($newPackageA = $this->getPackage('A', '1.1'));
         $this->reposComplete();
 
-        $this->request->install('A');
+        $this->request->requireName('A');
 
         $this->checkSolverResult(array(
             array('job' => 'update', 'from' => $packageA, 'to' => $newPackageA),
@@ -238,7 +238,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
+        $this->request->requireName('A');
 
         $this->checkSolverResult(array(
             array('job' => 'update', 'from' => $packageB, 'to' => $newPackageB),
@@ -252,7 +252,7 @@ class SolverTest extends TestCase
         $this->repo->addPackage($this->getPackage('A', '1.0'));
         $this->reposComplete();
 
-        $this->request->install('A');
+        $this->request->requireName('A');
 
         $this->checkSolverResult(array());
     }
@@ -266,7 +266,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
+        $this->request->requireName('A');
         $this->request->fixPackage($packageB);
 
         $this->checkSolverResult(array(
@@ -281,7 +281,7 @@ class SolverTest extends TestCase
         $this->repo->addPackage($this->getPackage('A', '2.0'));
         $this->reposComplete();
 
-        $this->request->install('A', $this->getVersionConstraint('<', '2.0.0.0'));
+        $this->request->requireName('A', $this->getVersionConstraint('<', '2.0.0.0'));
 
         $this->checkSolverResult(array(array(
             'job' => 'update',
@@ -297,7 +297,7 @@ class SolverTest extends TestCase
         $this->repo->addPackage($this->getPackage('A', '2.0'));
         $this->reposComplete();
 
-        $this->request->install('A', $this->getVersionConstraint('<', '2.0.0.0'));
+        $this->request->requireName('A', $this->getVersionConstraint('<', '2.0.0.0'));
 
         $this->checkSolverResult(array(array(
             'job' => 'update',
@@ -314,7 +314,7 @@ class SolverTest extends TestCase
         $this->repo->addPackage($this->getPackage('A', '2.0'));
         $this->reposComplete();
 
-        $this->request->install('A', $this->getVersionConstraint('<', '2.0.0.0'));
+        $this->request->requireName('A', $this->getVersionConstraint('<', '2.0.0.0'));
 
         $this->checkSolverResult(array(
             array(
@@ -343,8 +343,8 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
-        $this->request->install('C');
+        $this->request->requireName('A');
+        $this->request->requireName('C');
 
         $this->checkSolverResult(array(
             array('job' => 'remove',  'package' => $packageD),
@@ -365,7 +365,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
+        $this->request->requireName('A');
 
         $this->checkSolverResult(array(
             array('job' => 'install', 'package' => $middlePackageB),
@@ -381,7 +381,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('B');
+        $this->request->requireName('B');
 
         $this->checkSolverResult(array(
             array('job' => 'remove', 'package' => $packageA),
@@ -396,7 +396,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
+        $this->request->requireName('A');
 
         $this->checkSolverResult(array(
             array('job' => 'install', 'package' => $packageA),
@@ -412,7 +412,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
+        $this->request->requireName('A');
 
         // must explicitly pick the provider, so error in this case
         $this->setExpectedException('Composer\DependencyResolver\SolverProblemsException');
@@ -430,7 +430,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
+        $this->request->requireName('A');
 
         $this->checkSolverResult(array(
             array('job' => 'install', 'package' => $packageB),
@@ -447,7 +447,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
+        $this->request->requireName('A');
 
         $this->setExpectedException('Composer\DependencyResolver\SolverProblemsException');
         $this->createSolver();
@@ -464,8 +464,8 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
-        $this->request->install('Q');
+        $this->request->requireName('A');
+        $this->request->requireName('Q');
 
         $this->checkSolverResult(array(
             array('job' => 'install', 'package' => $packageQ),
@@ -502,7 +502,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('X');
+        $this->request->requireName('X');
 
         $this->checkSolverResult(array(
             array('job' => 'install', 'package' => $newPackageB),
@@ -521,7 +521,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
+        $this->request->requireName('A');
 
         $this->checkSolverResult(array(
             array('job' => 'install', 'package' => $packageB2),
@@ -545,8 +545,8 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
-        $this->request->install('C');
+        $this->request->requireName('A');
+        $this->request->requireName('C');
 
         $this->checkSolverResult(array(
             array('job' => 'install', 'package' => $packageB),
@@ -583,8 +583,8 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
-        $this->request->install('D');
+        $this->request->requireName('A');
+        $this->request->requireName('D');
 
         $this->checkSolverResult(array(
             array('job' => 'install', 'package' => $packageD2),
@@ -619,7 +619,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('C', $this->getVersionConstraint('==', '2.0.0.0-dev'));
+        $this->request->requireName('C', $this->getVersionConstraint('==', '2.0.0.0-dev'));
 
         $this->setExpectedException('Composer\DependencyResolver\SolverProblemsException');
 
@@ -637,8 +637,8 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
-        $this->request->install('B');
+        $this->request->requireName('A');
+        $this->request->requireName('B');
 
         $this->createSolver();
         try {
@@ -650,9 +650,9 @@ class SolverTest extends TestCase
 
             $msg = "\n";
             $msg .= "  Problem 1\n";
-            $msg .= "    - Installation request for a -> satisfiable by A[1.0].\n";
+            $msg .= "    - Root composer.json requires a -> satisfiable by A[1.0].\n";
             $msg .= "    - B 1.0 conflicts with A[1.0].\n";
-            $msg .= "    - Installation request for b -> satisfiable by B[1.0].\n";
+            $msg .= "    - Root composer.json requires b -> satisfiable by B[1.0].\n";
             $this->assertEquals($msg, $e->getMessage());
         }
     }
@@ -668,7 +668,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
+        $this->request->requireName('A');
 
         $this->createSolver();
         try {
@@ -681,7 +681,7 @@ class SolverTest extends TestCase
 
             $msg = "\n";
             $msg .= "  Problem 1\n";
-            $msg .= "    - Installation request for a -> satisfiable by A[1.0].\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";
@@ -716,7 +716,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
+        $this->request->requireName('A');
 
         $this->createSolver();
         try {
@@ -733,7 +733,7 @@ class SolverTest extends TestCase
             $msg .= "    - B 1.0 requires c >= 1.0 -> satisfiable by C[1.0].\n";
             $msg .= "    - Same name, can only install one of: B[0.9, 1.0].\n";
             $msg .= "    - A 1.0 requires b >= 1.0 -> satisfiable by B[1.0].\n";
-            $msg .= "    - Installation request for a -> satisfiable by A[1.0].\n";
+            $msg .= "    - Root composer.json requires a -> satisfiable by A[1.0].\n";
             $this->assertEquals($msg, $e->getMessage());
         }
     }
@@ -756,8 +756,8 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('symfony/twig-bridge');
-        $this->request->install('twig/twig');
+        $this->request->requireName('symfony/twig-bridge');
+        $this->request->requireName('twig/twig');
 
         $this->checkSolverResult(array(
             array('job' => 'install', 'package' => $packageTwig16),
@@ -782,7 +782,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A', $this->getVersionConstraint('==', '1.1.0.0'));
+        $this->request->requireName('A', $this->getVersionConstraint('==', '1.1.0.0'));
 
         $this->checkSolverResult(array(
             array('job' => 'install', 'package' => $packageB),
@@ -804,8 +804,8 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A', $this->getVersionConstraint('==', '2.0'));
-        $this->request->install('B');
+        $this->request->requireName('A', $this->getVersionConstraint('==', '2.0'));
+        $this->request->requireName('B');
 
         $this->checkSolverResult(array(
             array('job' => 'install', 'package' => $packageA),
@@ -865,7 +865,7 @@ class SolverTest extends TestCase
 
         $this->reposComplete();
 
-        $this->request->install('A');
+        $this->request->requireName('A');
 
         $this->createSolver();
 
@@ -905,14 +905,14 @@ class SolverTest extends TestCase
 
         $result = array();
         foreach ($transaction->getOperations() as $operation) {
-            if ('update' === $operation->getJobType()) {
+            if ('update' === $operation->getOperationType()) {
                 $result[] = array(
                     'job' => 'update',
                     'from' => $operation->getInitialPackage(),
                     'to' => $operation->getTargetPackage(),
                 );
             } else {
-                $job = ('uninstall' === $operation->getJobType() ? 'remove' : 'install');
+                $job = ('uninstall' === $operation->getOperationType() ? 'remove' : 'install');
                 $result[] = array(
                     'job' => $job,
                     'package' => $operation->getPackage(),

+ 2 - 2
tests/Composer/Test/DependencyResolver/TransactionTest.php

@@ -71,7 +71,7 @@ class TransactionTest extends TestCase
     {
         $result = array();
         foreach ($transaction->getOperations() as $operation) {
-            if ('update' === $operation->getJobType()) {
+            if ('update' === $operation->getOperationType()) {
                 $result[] = array(
                     'job' => 'update',
                     'from' => $operation->getInitialPackage(),
@@ -79,7 +79,7 @@ class TransactionTest extends TestCase
                 );
             } else {
                 $result[] = array(
-                    'job' => $operation->getJobType(),
+                    'job' => $operation->getOperationType(),
                     'package' => $operation->getPackage(),
                 );
             }

+ 1 - 1
tests/Composer/Test/Fixtures/installer/broken-deps-do-not-replace.test

@@ -28,7 +28,7 @@ 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.
     - b/b 1.0.0 requires c/c 1.* -> satisfiable by c/c[1.0.0].
-    - Installation request for b/b 1.* -> satisfiable by b/b[1.0.0].
+    - Root composer.json requires b/b 1.* -> satisfiable by b/b[1.0.0].
 
 Potential causes:
  - A typo in the package name

+ 1 - 1
tests/Composer/Test/Fixtures/installer/github-issues-4319.test

@@ -36,7 +36,7 @@ Updating dependencies
 Your requirements could not be resolved to an installable set of packages.
 
   Problem 1
-    - Installation request for a/a ~1.0 -> satisfiable by a/a[1.0.0].
+    - 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.
 
 --EXPECT--

+ 1 - 1
tests/Composer/Test/Fixtures/installer/solver-problems.test

@@ -63,7 +63,7 @@ Your requirements could not be resolved to an installable set of packages.
   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.
   Problem 4
-    - Installation request for requirer/pkg 1.* -> satisfiable by requirer/pkg[1.0.0].
+    - 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.
 
 Potential causes:

+ 1 - 1
tests/Composer/Test/Mock/InstallationManagerMock.php

@@ -38,7 +38,7 @@ class InstallationManagerMock extends InstallationManager
     public function execute(RepositoryInterface $repo, array $operations, $devMode = true, $runScripts = true)
     {
         foreach ($operations as $operation) {
-            $method = $operation->getJobType();
+            $method = $operation->getOperationType();
             // skipping download() step here for tests
             $this->$method($repo, $operation);
         }