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

Request jobs replaced by root require / fixed package
main
Nils Adermann 5 years ago committed by GitHub
commit a8963cc0e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -26,11 +26,10 @@ class GenericRule extends Rule
* @param array $literals * @param array $literals
* @param int|null $reason A RULE_* constant describing the reason for generating this rule * @param int|null $reason A RULE_* constant describing the reason for generating this rule
* @param Link|PackageInterface|int|null $reasonData * @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 all packages ascending by id
sort($literals); sort($literals);

@ -28,11 +28,10 @@ class MultiConflictRule extends Rule
* @param array $literals * @param array $literals
* @param int $reason A RULE_* constant describing the reason for generating this rule * @param int $reason A RULE_* constant describing the reason for generating this rule
* @param Link|PackageInterface $reasonData * @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) { if (count($literals) < 3) {
throw new \RuntimeException("multi conflict rule requires at least 3 literals"); throw new \RuntimeException("multi conflict rule requires at least 3 literals");

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

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

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

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

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

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

@ -69,20 +69,16 @@ class PoolBuilder
} }
} }
foreach ($request->getJobs() as $job) { foreach ($request->getRequires() as $packageName => $constraint) {
switch ($job['cmd']) { if (isset($this->loadedNames[$packageName])) {
case 'install': continue;
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 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? // 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 // also see the solver-problems.test test case
$constraint = array_key_exists($job['packageName'], $loadNames) ? null : $job['constraint']; $constraint = array_key_exists($packageName, $loadNames) ? null : $constraint;
$loadNames[$job['packageName']] = $constraint; $loadNames[$packageName] = $constraint;
$this->nameConstraints[$job['packageName']] = $constraint ? new MultiConstraint(array($constraint), false) : null; $this->nameConstraints[$packageName] = $constraint ? new MultiConstraint(array($constraint), false) : null;
break;
}
} }
while (!empty($loadNames)) { while (!empty($loadNames)) {

@ -28,7 +28,7 @@ class Problem
protected $reasonSeen; 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 * @var array
*/ */
protected $reasons = array(); protected $reasons = array();
@ -49,10 +49,7 @@ class Problem
*/ */
public function addRule(Rule $rule) public function addRule(Rule $rule)
{ {
$this->addReason(spl_object_hash($rule), array( $this->addReason(spl_object_hash($rule), $rule);
'rule' => $rule,
'job' => $rule->getJob(),
));
} }
/** /**
@ -73,16 +70,20 @@ class Problem
*/ */
public function getPrettyString(array $installedMap = array(), array $learnedPool = array()) 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)); $reasons = call_user_func_array('array_merge', array_reverse($this->reasons));
if (count($reasons) === 1) { if (count($reasons) === 1) {
reset($reasons); 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']; $request = $rule->getReasonData();
$constraint = $job['constraint']; $packageName = $request['packageName'];
$constraint = $request['constraint'];
if (isset($constraint)) { if (isset($constraint)) {
$packages = $this->pool->whatProvides($packageName, $constraint); $packages = $this->pool->whatProvides($packageName, $constraint);
@ -90,8 +91,7 @@ class Problem
$packages = array(); $packages = array();
} }
if ($job && ($job['cmd'] === 'install' || $job['cmd'] === 'fix') && empty($packages)) { if (empty($packages)) {
// handle php/hhvm // handle php/hhvm
if ($packageName === 'php' || $packageName === 'php-64bit' || $packageName === 'hhvm') { if ($packageName === 'php' || $packageName === 'php-64bit' || $packageName === 'hhvm') {
$version = phpversion(); $version = phpversion();
@ -164,18 +164,9 @@ class Problem
$messages = array(); $messages = array();
foreach ($reasons as $reason) { foreach ($reasons as $rule) {
$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); $messages[] = $rule->getPrettyString($this->pool, $installedMap, $learnedPool);
} }
}
}
return "\n - ".implode("\n - ", $messages); return "\n - ".implode("\n - ", $messages);
} }
@ -184,10 +175,13 @@ class Problem
* Store a reason descriptor but ignore duplicates * Store a reason descriptor but ignore duplicates
* *
* @param string $id A canonical identifier for the reason * @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])) { if (!isset($this->reasonSeen[$id])) {
$this->reasonSeen[$id] = true; $this->reasonSeen[$id] = true;
$this->reasons[$this->section][] = $reason; $this->reasons[$this->section][] = $reason;
@ -199,42 +193,6 @@ class Problem
$this->section++; $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) protected function getPackageList($packages)
{ {
$prepared = array(); $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 * @param \Composer\Semver\Constraint\ConstraintInterface $constraint
* @return string * @return string

@ -24,7 +24,7 @@ use Composer\Semver\Constraint\ConstraintInterface;
class Request class Request
{ {
protected $lockedRepository; protected $lockedRepository;
protected $jobs = array(); protected $requires = array();
protected $fixedPackages = array(); protected $fixedPackages = array();
protected $unlockables = array(); protected $unlockables = array();
@ -33,9 +33,10 @@ class Request
$this->lockedRepository = $lockedRepository; $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) public function getRequires()
{
$packageName = strtolower($packageName);
$this->jobs[] = array(
'cmd' => $cmd,
'packageName' => $packageName,
'constraint' => $constraint,
);
}
public function getJobs()
{ {
return $this->jobs; return $this->requires;
} }
public function getFixedPackages() public function getFixedPackages()

@ -24,8 +24,8 @@ abstract class Rule
{ {
// reason constants // reason constants
const RULE_INTERNAL_ALLOW_UPDATE = 1; const RULE_INTERNAL_ALLOW_UPDATE = 1;
const RULE_JOB_INSTALL = 2; const RULE_ROOT_REQUIRE = 2;
const RULE_JOB_REMOVE = 3; const RULE_FIXED = 3;
const RULE_PACKAGE_CONFLICT = 6; const RULE_PACKAGE_CONFLICT = 6;
const RULE_PACKAGE_REQUIRES = 7; const RULE_PACKAGE_REQUIRES = 7;
const RULE_PACKAGE_OBSOLETES = 8; const RULE_PACKAGE_OBSOLETES = 8;
@ -41,22 +41,17 @@ abstract class Rule
const BITFIELD_DISABLED = 16; const BITFIELD_DISABLED = 16;
protected $bitfield; protected $bitfield;
protected $job; protected $request;
protected $reasonData; protected $reasonData;
/** /**
* @param int $reason A RULE_* constant describing the reason for generating this rule * @param int $reason A RULE_* constant describing the reason for generating this rule
* @param Link|PackageInterface $reasonData * @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; $this->reasonData = $reasonData;
if ($job) {
$this->job = $job;
}
$this->bitfield = (0 << self::BITFIELD_DISABLED) | $this->bitfield = (0 << self::BITFIELD_DISABLED) |
($reason << self::BITFIELD_REASON) | ($reason << self::BITFIELD_REASON) |
(255 << self::BITFIELD_TYPE); (255 << self::BITFIELD_TYPE);
@ -66,11 +61,6 @@ abstract class Rule
abstract public function getHash(); abstract public function getHash();
public function getJob()
{
return $this->job;
}
abstract public function equals(Rule $rule); abstract public function equals(Rule $rule);
public function getReason() public function getReason()
@ -85,11 +75,17 @@ abstract class Rule
public function getRequiredPackage() public function getRequiredPackage()
{ {
if ($this->getReason() === self::RULE_JOB_INSTALL) { $reason = $this->getReason();
return $this->reasonData;
if ($reason === self::RULE_ROOT_REQUIRE) {
return $this->reasonData['packageName'];
} }
if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) { if ($reason === self::RULE_FIXED) {
return $this->reasonData['package']->getName();
}
if ($reason === self::RULE_PACKAGE_REQUIRES) {
return $this->reasonData->getTarget(); return $this->reasonData->getTarget();
} }
} }
@ -142,11 +138,24 @@ abstract class Rule
case self::RULE_INTERNAL_ALLOW_UPDATE: case self::RULE_INTERNAL_ALLOW_UPDATE:
return $ruleText; return $ruleText;
case self::RULE_JOB_INSTALL: case self::RULE_ROOT_REQUIRE:
return "Install command rule ($ruleText)"; $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 'Root composer.json requires '.$packageName.($constraint ? ' '.$constraint->getPrettyString() : '').' -> satisfiable by '.$this->formatPackagesUnique($pool, $packages).'.';
return "Remove command rule ($ruleText)";
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: case self::RULE_PACKAGE_CONFLICT:
$package1 = $pool->literalToPackage($literals[0]); $package1 = $pool->literalToPackage($literals[0]);
@ -263,6 +272,8 @@ abstract class Rule
*/ */
protected function formatPackagesUnique($pool, array $packages) protected function formatPackagesUnique($pool, array $packages)
{ {
// TODO this is essentially a duplicate of Problem: getPackageList, maintain in one place only?
$prepared = array(); $prepared = array();
foreach ($packages as $package) { foreach ($packages as $package) {
if (!is_object($package)) { if (!is_object($package)) {

@ -28,11 +28,10 @@ class Rule2Literals extends Rule
* @param int $literal2 * @param int $literal2
* @param int $reason A RULE_* constant describing the reason for generating this rule * @param int $reason A RULE_* constant describing the reason for generating this rule
* @param Link|PackageInterface $reasonData * @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) { if ($literal1 < $literal2) {
$this->literal1 = $literal1; $this->literal1 = $literal1;

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

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

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

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

@ -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? // 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(); $targetPackage = $operation->getTargetPackage();
if ($targetPackage->isDev()) { if ($targetPackage->isDev()) {
$initialPackage = $operation->getInitialPackage(); $initialPackage = $operation->getInitialPackage();

@ -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 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) { if ($this->updateMirrors) {
foreach ($lockedRepository->getPackages() as $lockedPackage) { foreach ($lockedRepository->getPackages() as $lockedPackage) {
$request->install($lockedPackage->getName(), new Constraint('==', $lockedPackage->getVersion())); $request->requireName($lockedPackage->getName(), new Constraint('==', $lockedPackage->getVersion()));
} }
} else { } else {
foreach ($links as $link) { 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) { foreach ($lockTransaction->getOperations() as $operation) {
// collect suggestions // collect suggestions
$jobType = $operation->getJobType();
if ($operation instanceof InstallOperation) { if ($operation instanceof InstallOperation) {
$this->suggestedPackagesReporter->addSuggestionsFromPackage($operation->getPackage()); $this->suggestedPackagesReporter->addSuggestionsFromPackage($operation->getPackage());
} }
// output op, but alias op only in debug verbosity // 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)); $this->io->writeError(' - ' . $operation->show(true));
} }
} }
@ -524,7 +523,7 @@ class Installer
$links = $this->package->getRequires(); $links = $this->package->getRequires();
foreach ($links as $link) { foreach ($links as $link) {
$request->install($link->getTarget(), $link->getConstraint()); $request->requireName($link->getTarget(), $link->getConstraint());
} }
$pool = $repositorySet->createPool($request); $pool = $repositorySet->createPool($request);
@ -582,7 +581,7 @@ class Installer
} }
foreach ($this->locker->getPlatformRequirements($this->devMode) as $link) { 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); //$this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $policy, $repositorySet, $installedRepo, $request);
@ -656,7 +655,7 @@ class Installer
} else { } else {
foreach ($localRepoTransaction->getOperations() as $operation) { foreach ($localRepoTransaction->getOperations() as $operation) {
// output op, but alias op only in debug verbosity // 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)); $this->io->writeError(' - ' . $operation->show(false));
} }
} }

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

@ -123,6 +123,6 @@ class Link
*/ */
public function getPrettyString(PackageInterface $sourcePackage) 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() : '');
} }
} }

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

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

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

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

@ -26,9 +26,9 @@ class RuleSetTest extends TestCase
{ {
$rules = array( $rules = array(
RuleSet::TYPE_PACKAGE => array(), RuleSet::TYPE_PACKAGE => array(),
RuleSet::TYPE_JOB => array( RuleSet::TYPE_REQUEST => array(
new GenericRule(array(1), Rule::RULE_JOB_INSTALL, null), new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null),
new GenericRule(array(2), Rule::RULE_JOB_INSTALL, null), new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, null),
), ),
RuleSet::TYPE_LEARNED => array( RuleSet::TYPE_LEARNED => array(
new GenericRule(array(), Rule::RULE_INTERNAL_ALLOW_UPDATE, null), new GenericRule(array(), Rule::RULE_INTERNAL_ALLOW_UPDATE, null),
@ -37,9 +37,9 @@ class RuleSetTest extends TestCase
$ruleSet = new RuleSet; $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_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()); $this->assertEquals($rules, $ruleSet->getRules());
} }
@ -47,20 +47,20 @@ class RuleSetTest extends TestCase
public function testAddIgnoresDuplicates() public function testAddIgnoresDuplicates()
{ {
$rules = array( $rules = array(
RuleSet::TYPE_JOB => array( RuleSet::TYPE_REQUEST => array(
new GenericRule(array(), Rule::RULE_JOB_INSTALL, null), new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null),
new GenericRule(array(), Rule::RULE_JOB_INSTALL, null), new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null),
new GenericRule(array(), Rule::RULE_JOB_INSTALL, null), new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null),
), ),
); );
$ruleSet = new RuleSet; $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_JOB][1], RuleSet::TYPE_JOB); $ruleSet->add($rules[RuleSet::TYPE_REQUEST][1], RuleSet::TYPE_REQUEST);
$ruleSet->add($rules[RuleSet::TYPE_JOB][2], RuleSet::TYPE_JOB); $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 = 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() public function testCount()
{ {
$ruleSet = new RuleSet; $ruleSet = new RuleSet;
$ruleSet->add(new GenericRule(array(1), 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_JOB_INSTALL, null), RuleSet::TYPE_JOB); $ruleSet->add(new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, null), RuleSet::TYPE_REQUEST);
$this->assertEquals(2, $ruleSet->count()); $this->assertEquals(2, $ruleSet->count());
} }
@ -87,8 +87,8 @@ class RuleSetTest extends TestCase
{ {
$ruleSet = new RuleSet; $ruleSet = new RuleSet;
$rule = new GenericRule(array(), Rule::RULE_JOB_INSTALL, null); $rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null);
$ruleSet->add($rule, RuleSet::TYPE_JOB); $ruleSet->add($rule, RuleSet::TYPE_REQUEST);
$this->assertSame($rule, $ruleSet->ruleById[0]); $this->assertSame($rule, $ruleSet->ruleById[0]);
} }
@ -97,9 +97,9 @@ class RuleSetTest extends TestCase
{ {
$ruleSet = new RuleSet; $ruleSet = new RuleSet;
$rule1 = new GenericRule(array(1), Rule::RULE_JOB_INSTALL, null); $rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null);
$rule2 = new GenericRule(array(2), Rule::RULE_JOB_INSTALL, 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); $ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
$iterator = $ruleSet->getIterator(); $iterator = $ruleSet->getIterator();
@ -112,10 +112,10 @@ class RuleSetTest extends TestCase
public function testGetIteratorFor() public function testGetIteratorFor()
{ {
$ruleSet = new RuleSet; $ruleSet = new RuleSet;
$rule1 = new GenericRule(array(1), Rule::RULE_JOB_INSTALL, null); $rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null);
$rule2 = new GenericRule(array(2), Rule::RULE_JOB_INSTALL, 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); $ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
$iterator = $ruleSet->getIteratorFor(RuleSet::TYPE_LEARNED); $iterator = $ruleSet->getIteratorFor(RuleSet::TYPE_LEARNED);
@ -126,13 +126,13 @@ class RuleSetTest extends TestCase
public function testGetIteratorWithout() public function testGetIteratorWithout()
{ {
$ruleSet = new RuleSet; $ruleSet = new RuleSet;
$rule1 = new GenericRule(array(1), Rule::RULE_JOB_INSTALL, null); $rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null);
$rule2 = new GenericRule(array(2), Rule::RULE_JOB_INSTALL, 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); $ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
$iterator = $ruleSet->getIteratorWithout(RuleSet::TYPE_JOB); $iterator = $ruleSet->getIteratorWithout(RuleSet::TYPE_REQUEST);
$this->assertSame($rule2, $iterator->current()); $this->assertSame($rule2, $iterator->current());
} }
@ -145,10 +145,10 @@ class RuleSetTest extends TestCase
$ruleSet = new RuleSet; $ruleSet = new RuleSet;
$literal = $p->getId(); $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,6 +17,7 @@ use Composer\DependencyResolver\Rule;
use Composer\DependencyResolver\RuleSet; use Composer\DependencyResolver\RuleSet;
use Composer\DependencyResolver\Pool; use Composer\DependencyResolver\Pool;
use Composer\Package\BasePackage; use Composer\Package\BasePackage;
use Composer\Package\Link;
use Composer\Repository\ArrayRepository; use Composer\Repository\ArrayRepository;
use Composer\Test\TestCase; use Composer\Test\TestCase;
@ -24,7 +25,7 @@ class RuleTest extends TestCase
{ {
public function testGetHash() 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)); $hash = unpack('ihash', md5('123', true));
$this->assertEquals($hash['hash'], $rule->getHash()); $this->assertEquals($hash['hash'], $rule->getHash());
@ -32,39 +33,39 @@ class RuleTest extends TestCase
public function testEqualsForRulesWithDifferentHashes() public function testEqualsForRulesWithDifferentHashes()
{ {
$rule = new GenericRule(array(1, 2), Rule::RULE_JOB_INSTALL, null); $rule = new GenericRule(array(1, 2), Rule::RULE_ROOT_REQUIRE, null);
$rule2 = new GenericRule(array(1, 3), Rule::RULE_JOB_INSTALL, null); $rule2 = new GenericRule(array(1, 3), Rule::RULE_ROOT_REQUIRE, null);
$this->assertFalse($rule->equals($rule2)); $this->assertFalse($rule->equals($rule2));
} }
public function testEqualsForRulesWithDifferLiteralsQuantity() public function testEqualsForRulesWithDifferLiteralsQuantity()
{ {
$rule = 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), Rule::RULE_JOB_INSTALL, null); $rule2 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null);
$this->assertFalse($rule->equals($rule2)); $this->assertFalse($rule->equals($rule2));
} }
public function testEqualsForRulesWithSameLiterals() public function testEqualsForRulesWithSameLiterals()
{ {
$rule = 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_JOB_INSTALL, null); $rule2 = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, null);
$this->assertTrue($rule->equals($rule2)); $this->assertTrue($rule->equals($rule2));
} }
public function testSetAndGetType() public function testSetAndGetType()
{ {
$rule = new GenericRule(array(), Rule::RULE_JOB_INSTALL, null); $rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null);
$rule->setType(RuleSet::TYPE_JOB); $rule->setType(RuleSet::TYPE_REQUEST);
$this->assertEquals(RuleSet::TYPE_JOB, $rule->getType()); $this->assertEquals(RuleSet::TYPE_REQUEST, $rule->getType());
} }
public function testEnable() public function testEnable()
{ {
$rule = new GenericRule(array(), Rule::RULE_JOB_INSTALL, null); $rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null);
$rule->disable(); $rule->disable();
$rule->enable(); $rule->enable();
@ -74,7 +75,7 @@ class RuleTest extends TestCase
public function testDisable() public function testDisable()
{ {
$rule = new GenericRule(array(), Rule::RULE_JOB_INSTALL, null); $rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null);
$rule->enable(); $rule->enable();
$rule->disable(); $rule->disable();
@ -84,8 +85,8 @@ class RuleTest extends TestCase
public function testIsAssertions() public function testIsAssertions()
{ {
$rule = 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), Rule::RULE_JOB_INSTALL, null); $rule2 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null);
$this->assertFalse($rule->isAssertion()); $this->assertFalse($rule->isAssertion());
$this->assertTrue($rule2->isAssertion()); $this->assertTrue($rule2->isAssertion());
@ -98,8 +99,8 @@ class RuleTest extends TestCase
$p2 = $this->getPackage('baz', '1.1'), $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));
} }
} }

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

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

@ -28,7 +28,7 @@ Your requirements could not be resolved to an installable set of packages.
Problem 1 Problem 1
- c/c 1.0.0 requires x/x 1.0 -> no matching package found. - 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]. - 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: Potential causes:
- A typo in the package name - A typo in the package name

@ -36,7 +36,7 @@ Updating dependencies
Your requirements could not be resolved to an installable set of packages. Your requirements could not be resolved to an installable set of packages.
Problem 1 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. - 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-- --EXPECT--

@ -63,7 +63,7 @@ Your requirements could not be resolved to an installable set of packages.
Problem 3 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. - 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 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. - requirer/pkg 1.0.0 requires dependency/pkg 1.0.0 -> no matching package found.
Potential causes: Potential causes:

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

Loading…
Cancel
Save