Add more type annotations
parent
dd49db6f08
commit
4bcd860b65
|
@ -16,17 +16,21 @@ namespace Composer\DependencyResolver;
|
|||
* Stores decisions on installing, removing or keeping packages
|
||||
*
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
* @implements \Iterator<array{0: int, 1: mixed}>
|
||||
*/
|
||||
class Decisions implements \Iterator, \Countable
|
||||
{
|
||||
const DECISION_LITERAL = 0;
|
||||
const DECISION_REASON = 1;
|
||||
|
||||
/** @var Pool */
|
||||
protected $pool;
|
||||
/** @var array<int, int> */
|
||||
protected $decisionMap;
|
||||
/** @var array<array{0: int, 1: mixed}> */
|
||||
protected $decisionQueue = array();
|
||||
|
||||
public function __construct($pool)
|
||||
public function __construct(Pool $pool)
|
||||
{
|
||||
$this->pool = $pool;
|
||||
$this->decisionMap = array();
|
||||
|
|
|
@ -23,7 +23,9 @@ use Composer\Semver\Constraint\Constraint;
|
|||
*/
|
||||
class DefaultPolicy implements PolicyInterface
|
||||
{
|
||||
/** @var bool */
|
||||
private $preferStable;
|
||||
/** @var bool */
|
||||
private $preferLowest;
|
||||
|
||||
public function __construct($preferStable = false, $preferLowest = false)
|
||||
|
|
|
@ -21,14 +21,11 @@ use Composer\Semver\Constraint\ConstraintInterface;
|
|||
*/
|
||||
class GenericRule extends Rule
|
||||
{
|
||||
/** @var int[] */
|
||||
protected $literals;
|
||||
|
||||
/**
|
||||
* @param array $literals
|
||||
* @param int|null $reason A RULE_* constant describing the reason for generating this rule
|
||||
* @param Link|BasePackage|int|null|array $reasonData
|
||||
*
|
||||
* @phpstan-param Link|BasePackage|int|null|array{packageName: string, constraint: ConstraintInterface} $reasonData
|
||||
* @param int[] $literals
|
||||
*/
|
||||
public function __construct(array $literals, $reason, $reasonData)
|
||||
{
|
||||
|
|
|
@ -22,12 +22,11 @@ use Composer\Package\Link;
|
|||
*/
|
||||
class MultiConflictRule extends Rule
|
||||
{
|
||||
/** @var int[] */
|
||||
protected $literals;
|
||||
|
||||
/**
|
||||
* @param array $literals
|
||||
* @param int $reason A RULE_* constant describing the reason for generating this rule
|
||||
* @param Link|BasePackage $reasonData
|
||||
* @param int[] $literals
|
||||
*/
|
||||
public function __construct(array $literals, $reason, $reasonData)
|
||||
{
|
||||
|
|
|
@ -30,7 +30,9 @@ class Pool implements \Countable
|
|||
protected $packages = array();
|
||||
/** @var array<string, BasePackage[]> */
|
||||
protected $packageByName = array();
|
||||
/** @var VersionParser */
|
||||
protected $versionParser;
|
||||
/** @var array<string, array<string, BasePackage[]>> */
|
||||
protected $providerCache = array();
|
||||
/** @var BasePackage[] */
|
||||
protected $unacceptableFixedOrLockedPackages;
|
||||
|
|
|
@ -94,7 +94,9 @@ class PoolBuilder
|
|||
* @phpstan-var list<PackageInterface>
|
||||
*/
|
||||
private $unacceptableFixedOrLockedPackages = array();
|
||||
/** @var string[] */
|
||||
private $updateAllowList = array();
|
||||
/** @var array<string, string> */
|
||||
private $skippedLoad = array();
|
||||
|
||||
/**
|
||||
|
@ -104,6 +106,8 @@ class PoolBuilder
|
|||
*
|
||||
* Packages get cleared from this list if they get unlocked as in that case
|
||||
* we need to actually load them
|
||||
*
|
||||
* @var array<string, true>
|
||||
*/
|
||||
private $maxExtendedReqs = array();
|
||||
/**
|
||||
|
@ -112,6 +116,7 @@ class PoolBuilder
|
|||
*/
|
||||
private $updateAllowWarned = array();
|
||||
|
||||
/** @var int */
|
||||
private $indexCounter = 0;
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,16 +30,17 @@ class Problem
|
|||
{
|
||||
/**
|
||||
* A map containing the id of each rule part of this problem as a key
|
||||
* @var array
|
||||
* @var array<string, true>
|
||||
*/
|
||||
protected $reasonSeen;
|
||||
|
||||
/**
|
||||
* A set of reasons for the problem, each is a rule or a root require and a rule
|
||||
* @var array
|
||||
* @var array<int, array<int, Rule>>
|
||||
*/
|
||||
protected $reasons = array();
|
||||
|
||||
/** @var int */
|
||||
protected $section = 0;
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,12 +40,19 @@ class Request
|
|||
*/
|
||||
const UPDATE_LISTED_WITH_TRANSITIVE_DEPS = 2;
|
||||
|
||||
/** @var ?LockArrayRepository */
|
||||
protected $lockedRepository;
|
||||
/** @var array<string, ConstraintInterface> */
|
||||
protected $requires = array();
|
||||
/** @var array<string, PackageInterface> */
|
||||
protected $fixedPackages = array();
|
||||
/** @var array<string, PackageInterface> */
|
||||
protected $lockedPackages = array();
|
||||
/** @var array<string, PackageInterface> */
|
||||
protected $fixedLockedPackages = array();
|
||||
/** @var string[] */
|
||||
protected $updateAllowList = array();
|
||||
/** @var false|self::UPDATE_* */
|
||||
protected $updateAllowTransitiveDependencies = false;
|
||||
|
||||
public function __construct(LockArrayRepository $lockedRepository = null)
|
||||
|
@ -169,12 +176,12 @@ class Request
|
|||
|
||||
if ($this->lockedRepository) {
|
||||
foreach ($this->lockedRepository->getPackages() as $package) {
|
||||
$presentMap[$packageIds ? $package->id : spl_object_hash($package)] = $package;
|
||||
$presentMap[$packageIds ? $package->getId() : spl_object_hash($package)] = $package;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->fixedPackages as $package) {
|
||||
$presentMap[$packageIds ? $package->id : spl_object_hash($package)] = $package;
|
||||
$presentMap[$packageIds ? $package->getId() : spl_object_hash($package)] = $package;
|
||||
}
|
||||
|
||||
return $presentMap;
|
||||
|
@ -185,7 +192,7 @@ class Request
|
|||
$fixedPackagesMap = array();
|
||||
|
||||
foreach ($this->fixedPackages as $package) {
|
||||
$fixedPackagesMap[$package->id] = $package;
|
||||
$fixedPackagesMap[$package->getId()] = $package;
|
||||
}
|
||||
|
||||
return $fixedPackagesMap;
|
||||
|
|
|
@ -19,35 +19,45 @@ use Composer\Repository\RepositorySet;
|
|||
use Composer\Repository\PlatformRepository;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Semver\Constraint\Constraint;
|
||||
use Composer\Semver\Constraint\ConstraintInterface;
|
||||
|
||||
/**
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
* @author Ruben Gonzalez <rubenrua@gmail.com>
|
||||
* @phpstan-type ReasonData Link|BasePackage|string|int|array{packageName: string, constraint: ConstraintInterface}|array{package: BasePackage}
|
||||
*/
|
||||
abstract class Rule
|
||||
{
|
||||
// reason constants
|
||||
const RULE_ROOT_REQUIRE = 2;
|
||||
const RULE_FIXED = 3;
|
||||
const RULE_PACKAGE_CONFLICT = 6;
|
||||
const RULE_PACKAGE_REQUIRES = 7;
|
||||
const RULE_PACKAGE_SAME_NAME = 10;
|
||||
const RULE_LEARNED = 12;
|
||||
const RULE_PACKAGE_ALIAS = 13;
|
||||
const RULE_PACKAGE_INVERSE_ALIAS = 14;
|
||||
// reason constants and // their reason data contents
|
||||
const RULE_ROOT_REQUIRE = 2; // array{packageName: string, constraint: ConstraintInterface}
|
||||
const RULE_FIXED = 3; // array{package: BasePackage}
|
||||
const RULE_PACKAGE_CONFLICT = 6; // Link
|
||||
const RULE_PACKAGE_REQUIRES = 7; // Link
|
||||
const RULE_PACKAGE_SAME_NAME = 10; // string (package name)
|
||||
const RULE_LEARNED = 12; // int (rule id)
|
||||
const RULE_PACKAGE_ALIAS = 13; // BasePackage
|
||||
const RULE_PACKAGE_INVERSE_ALIAS = 14; // BasePackage
|
||||
|
||||
// bitfield defs
|
||||
const BITFIELD_TYPE = 0;
|
||||
const BITFIELD_REASON = 8;
|
||||
const BITFIELD_DISABLED = 16;
|
||||
|
||||
/** @var int */
|
||||
protected $bitfield;
|
||||
/** @var Request */
|
||||
protected $request;
|
||||
/**
|
||||
* @var Link|BasePackage|ConstraintInterface|string
|
||||
* @phpstan-var ReasonData
|
||||
*/
|
||||
protected $reasonData;
|
||||
|
||||
/**
|
||||
* @param int $reason A RULE_* constant describing the reason for generating this rule
|
||||
* @param Link|BasePackage $reasonData
|
||||
* @param self::RULE_* $reason A RULE_* constant describing the reason for generating this rule
|
||||
* @param Link|BasePackage|ConstraintInterface|string $reasonData
|
||||
*
|
||||
* @phpstan-param ReasonData $reasonData
|
||||
*/
|
||||
public function __construct($reason, $reasonData)
|
||||
{
|
||||
|
@ -253,17 +263,19 @@ abstract class Rule
|
|||
case self::RULE_PACKAGE_REQUIRES:
|
||||
$sourceLiteral = array_shift($literals);
|
||||
$sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral));
|
||||
/** @var Link */
|
||||
$reasonData = $this->reasonData;
|
||||
|
||||
$requires = array();
|
||||
foreach ($literals as $literal) {
|
||||
$requires[] = $pool->literalToPackage($literal);
|
||||
}
|
||||
|
||||
$text = $this->reasonData->getPrettyString($sourcePackage);
|
||||
$text = $reasonData->getPrettyString($sourcePackage);
|
||||
if ($requires) {
|
||||
$text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires, $isVerbose) . '.';
|
||||
} else {
|
||||
$targetName = $this->reasonData->getTarget();
|
||||
$targetName = $reasonData->getTarget();
|
||||
|
||||
$reason = Problem::getMissingPackageReason($repositorySet, $request, $pool, $isVerbose, $targetName, $this->reasonData->getConstraint());
|
||||
|
||||
|
|
|
@ -20,14 +20,14 @@ use Composer\Package\Link;
|
|||
*/
|
||||
class Rule2Literals extends Rule
|
||||
{
|
||||
/** @var int */
|
||||
protected $literal1;
|
||||
/** @var int */
|
||||
protected $literal2;
|
||||
|
||||
/**
|
||||
* @param int $literal1
|
||||
* @param int $literal2
|
||||
* @param int $reason A RULE_* constant describing the reason for generating this rule
|
||||
* @param Link|BasePackage $reasonData
|
||||
*/
|
||||
public function __construct($literal1, $literal2, $reason, $reasonData)
|
||||
{
|
||||
|
@ -42,11 +42,13 @@ class Rule2Literals extends Rule
|
|||
}
|
||||
}
|
||||
|
||||
/** @return int[] */
|
||||
public function getLiterals()
|
||||
{
|
||||
return array($this->literal1, $this->literal2);
|
||||
}
|
||||
|
||||
/** @return string */
|
||||
public function getHash()
|
||||
{
|
||||
return $this->literal1.','.$this->literal2;
|
||||
|
@ -91,6 +93,7 @@ class Rule2Literals extends Rule
|
|||
return true;
|
||||
}
|
||||
|
||||
/** @return false */
|
||||
public function isAssertion()
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -16,6 +16,7 @@ use Composer\Repository\RepositorySet;
|
|||
|
||||
/**
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
* @implements \IteratorAggregate<Rule>
|
||||
*/
|
||||
class RuleSet implements \IteratorAggregate, \Countable
|
||||
{
|
||||
|
@ -27,10 +28,11 @@ class RuleSet implements \IteratorAggregate, \Countable
|
|||
/**
|
||||
* READ-ONLY: Lookup table for rule id to rule object
|
||||
*
|
||||
* @var Rule[]
|
||||
* @var array<int, Rule>
|
||||
*/
|
||||
public $ruleById;
|
||||
public $ruleById = array();
|
||||
|
||||
/** @var array<255|0|1|4, string> */
|
||||
protected static $types = array(
|
||||
255 => 'UNKNOWN',
|
||||
self::TYPE_PACKAGE => 'PACKAGE',
|
||||
|
@ -38,20 +40,20 @@ class RuleSet implements \IteratorAggregate, \Countable
|
|||
self::TYPE_LEARNED => 'LEARNED',
|
||||
);
|
||||
|
||||
/** @var array<self::TYPE_*, Rule[]> */
|
||||
protected $rules;
|
||||
protected $nextRuleId;
|
||||
|
||||
protected $rulesByHash;
|
||||
/** @var int */
|
||||
protected $nextRuleId = 0;
|
||||
|
||||
/** @var array<string, Rule|Rule[]> */
|
||||
protected $rulesByHash = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->nextRuleId = 0;
|
||||
|
||||
foreach ($this->getTypes() as $type) {
|
||||
$this->rules[$type] = array();
|
||||
}
|
||||
|
||||
$this->rulesByHash = array();
|
||||
}
|
||||
|
||||
public function add(Rule $rule, $type)
|
||||
|
@ -109,6 +111,7 @@ class RuleSet implements \IteratorAggregate, \Countable
|
|||
return $this->ruleById[$id];
|
||||
}
|
||||
|
||||
/** @return array<self::TYPE_*, Rule[]> */
|
||||
public function getRules()
|
||||
{
|
||||
return $this->rules;
|
||||
|
@ -123,6 +126,10 @@ class RuleSet implements \IteratorAggregate, \Countable
|
|||
return new RuleSetIterator($this->getRules());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param self::TYPE_*|array<self::TYPE_*> $types
|
||||
* @return RuleSetIterator
|
||||
*/
|
||||
public function getIteratorFor($types)
|
||||
{
|
||||
if (!\is_array($types)) {
|
||||
|
@ -130,6 +137,8 @@ class RuleSet implements \IteratorAggregate, \Countable
|
|||
}
|
||||
|
||||
$allRules = $this->getRules();
|
||||
|
||||
/** @var array<self::TYPE_*, Rule[]> $rules */
|
||||
$rules = array();
|
||||
|
||||
foreach ($types as $type) {
|
||||
|
@ -154,6 +163,7 @@ class RuleSet implements \IteratorAggregate, \Countable
|
|||
return new RuleSetIterator($rules);
|
||||
}
|
||||
|
||||
/** @return array{0: 0, 1: 1, 2: 4} */
|
||||
public function getTypes()
|
||||
{
|
||||
$types = self::$types;
|
||||
|
|
|
@ -14,25 +14,31 @@ namespace Composer\DependencyResolver;
|
|||
|
||||
use Composer\Package\BasePackage;
|
||||
use Composer\Package\AliasPackage;
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\Repository\PlatformRepository;
|
||||
|
||||
/**
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
* @phpstan-import-type ReasonData from Rule
|
||||
*/
|
||||
class RuleSetGenerator
|
||||
{
|
||||
/** @var PolicyInterface */
|
||||
protected $policy;
|
||||
/** @var Pool */
|
||||
protected $pool;
|
||||
/** @var RuleSet */
|
||||
protected $rules;
|
||||
protected $addedMap;
|
||||
protected $conflictAddedMap;
|
||||
protected $addedPackagesByNames;
|
||||
protected $conflictsForName;
|
||||
/** @var array<int, PackageInterface> */
|
||||
protected $addedMap = array();
|
||||
/** @var array<string, PackageInterface[]> */
|
||||
protected $addedPackagesByNames = array();
|
||||
|
||||
public function __construct(PolicyInterface $policy, Pool $pool)
|
||||
{
|
||||
$this->policy = $policy;
|
||||
$this->pool = $pool;
|
||||
$this->rules = new RuleSet;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,11 +49,13 @@ class RuleSetGenerator
|
|||
*
|
||||
* @param BasePackage $package The package with a requirement
|
||||
* @param array $providers The providers of the requirement
|
||||
* @param int $reason A RULE_* constant describing the
|
||||
* @param Rule::RULE_* $reason A RULE_* constant describing the
|
||||
* reason for generating this rule
|
||||
* @param mixed $reasonData Any data, e.g. the requirement name,
|
||||
* that goes with the reason
|
||||
* @return Rule|null The generated rule or null if tautological
|
||||
*
|
||||
* @phpstan-param ReasonData $reasonData
|
||||
*/
|
||||
protected function createRequireRule(BasePackage $package, array $providers, $reason, $reasonData = null)
|
||||
{
|
||||
|
@ -71,10 +79,12 @@ class RuleSetGenerator
|
|||
* set of packages is empty an impossible rule is generated.
|
||||
*
|
||||
* @param BasePackage[] $packages The set of packages to choose from
|
||||
* @param int $reason A RULE_* constant describing the reason for
|
||||
* @param Rule::RULE_* $reason A RULE_* constant describing the reason for
|
||||
* generating this rule
|
||||
* @param array $reasonData Additional data like the root require or fix request info
|
||||
* @return Rule The generated rule
|
||||
*
|
||||
* @phpstan-param ReasonData $reasonData
|
||||
*/
|
||||
protected function createInstallOneOfRule(array $packages, $reason, $reasonData)
|
||||
{
|
||||
|
@ -94,11 +104,13 @@ class RuleSetGenerator
|
|||
*
|
||||
* @param BasePackage $issuer The package declaring the conflict
|
||||
* @param BasePackage $provider The package causing the conflict
|
||||
* @param int $reason A RULE_* constant describing the
|
||||
* @param Rule::RULE_* $reason A RULE_* constant describing the
|
||||
* reason for generating this rule
|
||||
* @param mixed $reasonData Any data, e.g. the package name, that
|
||||
* goes with the reason
|
||||
* @return Rule|null The generated rule
|
||||
*
|
||||
* @phpstan-param ReasonData $reasonData
|
||||
*/
|
||||
protected function createRule2Literals(BasePackage $issuer, BasePackage $provider, $reason, $reasonData = null)
|
||||
{
|
||||
|
@ -144,11 +156,11 @@ class RuleSetGenerator
|
|||
|
||||
protected function addRulesForPackage(BasePackage $package, $ignorePlatformReqs)
|
||||
{
|
||||
/** @var \SplQueue<BasePackage> */
|
||||
$workQueue = new \SplQueue;
|
||||
$workQueue->enqueue($package);
|
||||
|
||||
while (!$workQueue->isEmpty()) {
|
||||
/** @var BasePackage $package */
|
||||
$package = $workQueue->dequeue();
|
||||
if (isset($this->addedMap[$package->id])) {
|
||||
continue;
|
||||
|
@ -286,13 +298,6 @@ class RuleSetGenerator
|
|||
*/
|
||||
public function getRulesFor(Request $request, $ignorePlatformReqs = false)
|
||||
{
|
||||
$this->rules = new RuleSet;
|
||||
|
||||
$this->addedMap = array();
|
||||
$this->conflictAddedMap = array();
|
||||
$this->addedPackagesByNames = array();
|
||||
$this->conflictsForName = array();
|
||||
|
||||
$this->addRulesForRequest($request, $ignorePlatformReqs);
|
||||
|
||||
$this->addRulesForRootAliases($ignorePlatformReqs);
|
||||
|
@ -300,8 +305,12 @@ class RuleSetGenerator
|
|||
$this->addConflictRules($ignorePlatformReqs);
|
||||
|
||||
// Remove references to packages
|
||||
$this->addedMap = $this->addedPackagesByNames = null;
|
||||
$this->addedMap = $this->addedPackagesByNames = array();
|
||||
|
||||
return $this->rules;
|
||||
$rules = $this->rules;
|
||||
|
||||
$this->rules = new RuleSet;
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,16 +14,25 @@ namespace Composer\DependencyResolver;
|
|||
|
||||
/**
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
* @implements \Iterator<RuleSet::TYPE_*, Rule>
|
||||
*/
|
||||
class RuleSetIterator implements \Iterator
|
||||
{
|
||||
/** @var array<RuleSet::TYPE_*, Rule[]> */
|
||||
protected $rules;
|
||||
/** @var array<RuleSet::TYPE_*> */
|
||||
protected $types;
|
||||
|
||||
/** @var int */
|
||||
protected $currentOffset;
|
||||
/** @var RuleSet::TYPE_*|-1 */
|
||||
protected $currentType;
|
||||
/** @var int */
|
||||
protected $currentTypeOffset;
|
||||
|
||||
/**
|
||||
* @param array<RuleSet::TYPE_*, Rule[]> $rules
|
||||
*/
|
||||
public function __construct(array $rules)
|
||||
{
|
||||
$this->rules = $rules;
|
||||
|
|
|
@ -19,11 +19,10 @@ namespace Composer\DependencyResolver;
|
|||
* method to set the internal iterator to a particular offset.
|
||||
*
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
* @extends \SplDoublyLinkedList<RuleWatchNode>
|
||||
*/
|
||||
class RuleWatchChain extends \SplDoublyLinkedList
|
||||
{
|
||||
protected $offset = 0;
|
||||
|
||||
/**
|
||||
* Moves the internal iterator to the specified offset
|
||||
*
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace Composer\DependencyResolver;
|
|||
*/
|
||||
class RuleWatchGraph
|
||||
{
|
||||
/** @var array<int, RuleWatchChain> */
|
||||
protected $watchChains = array();
|
||||
|
||||
/**
|
||||
|
@ -153,7 +154,7 @@ class RuleWatchGraph
|
|||
* @param int $toLiteral A literal the node should watch now
|
||||
* @param RuleWatchNode $node The rule node to be moved
|
||||
*/
|
||||
protected function moveWatch($fromLiteral, $toLiteral, $node)
|
||||
protected function moveWatch($fromLiteral, $toLiteral, RuleWatchNode $node)
|
||||
{
|
||||
if (!isset($this->watchChains[$toLiteral])) {
|
||||
$this->watchChains[$toLiteral] = new RuleWatchChain;
|
||||
|
|
|
@ -21,9 +21,12 @@ namespace Composer\DependencyResolver;
|
|||
*/
|
||||
class RuleWatchNode
|
||||
{
|
||||
/** @var int */
|
||||
public $watch1;
|
||||
/** @var int */
|
||||
public $watch2;
|
||||
|
||||
/** @var Rule */
|
||||
protected $rule;
|
||||
|
||||
/**
|
||||
|
@ -31,7 +34,7 @@ class RuleWatchNode
|
|||
*
|
||||
* @param Rule $rule The rule to wrap
|
||||
*/
|
||||
public function __construct($rule)
|
||||
public function __construct(Rule $rule)
|
||||
{
|
||||
$this->rule = $rule;
|
||||
|
||||
|
|
|
@ -45,9 +45,9 @@ class Solver
|
|||
protected $branches = array();
|
||||
/** @var Problem[] */
|
||||
protected $problems = array();
|
||||
/** @var array */
|
||||
/** @var array<Rule[]> */
|
||||
protected $learnedPool = array();
|
||||
/** @var array */
|
||||
/** @var array<string, int> */
|
||||
protected $learnedWhy = array();
|
||||
|
||||
/** @var bool */
|
||||
|
|
|
@ -14,15 +14,22 @@ namespace Composer\DependencyResolver;
|
|||
|
||||
use Composer\Util\IniHelper;
|
||||
use Composer\Repository\RepositorySet;
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
*/
|
||||
class SolverProblemsException extends \RuntimeException
|
||||
{
|
||||
/** @var Problem[] */
|
||||
protected $problems;
|
||||
/** @var array<Rule[]> */
|
||||
protected $learnedPool;
|
||||
|
||||
/**
|
||||
* @param Problem[] $problems
|
||||
* @param array<Rule[]> $learnedPool
|
||||
*/
|
||||
public function __construct(array $problems, array $learnedPool)
|
||||
{
|
||||
$this->problems = $problems;
|
||||
|
|
|
@ -16,6 +16,7 @@ use Composer\Package\AliasPackage;
|
|||
use Composer\Package\Link;
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\Repository\PlatformRepository;
|
||||
use Composer\DependencyResolver\Operation\OperationInterface;
|
||||
|
||||
/**
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
|
@ -24,24 +25,24 @@ use Composer\Repository\PlatformRepository;
|
|||
class Transaction
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
* @var OperationInterface[]
|
||||
*/
|
||||
protected $operations;
|
||||
|
||||
/**
|
||||
* Packages present at the beginning of the transaction
|
||||
* @var array
|
||||
* @var PackageInterface[]
|
||||
*/
|
||||
protected $presentPackages;
|
||||
|
||||
/**
|
||||
* Package set resulting from this transaction
|
||||
* @var array
|
||||
* @var array<string, PackageInterface>
|
||||
*/
|
||||
protected $resultPackageMap;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @var array<string, PackageInterface[]>
|
||||
*/
|
||||
protected $resultPackagesByName = array();
|
||||
|
||||
|
@ -52,6 +53,7 @@ class Transaction
|
|||
$this->operations = $this->calculateOperations();
|
||||
}
|
||||
|
||||
/** @return OperationInterface[] */
|
||||
public function getOperations()
|
||||
{
|
||||
return $this->operations;
|
||||
|
@ -201,7 +203,7 @@ class Transaction
|
|||
* These serve as a starting point to enumerate packages in a topological order despite potential cycles.
|
||||
* If there are packages with a cycle on the top level the package with the lowest name gets picked
|
||||
*
|
||||
* @return array
|
||||
* @return array<string, PackageInterface>
|
||||
*/
|
||||
protected function getRootPackages()
|
||||
{
|
||||
|
@ -245,8 +247,8 @@ class Transaction
|
|||
* it at least fixes the symptoms and makes usage of composer possible (again)
|
||||
* in such scenarios.
|
||||
*
|
||||
* @param Operation\OperationInterface[] $operations
|
||||
* @return Operation\OperationInterface[] reordered operation list
|
||||
* @param OperationInterface[] $operations
|
||||
* @return OperationInterface[] reordered operation list
|
||||
*/
|
||||
private function movePluginsToFront(array $operations)
|
||||
{
|
||||
|
@ -322,8 +324,8 @@ class Transaction
|
|||
* Removals of packages should be executed before installations in
|
||||
* case two packages resolve to the same path (due to custom installers)
|
||||
*
|
||||
* @param Operation\OperationInterface[] $operations
|
||||
* @return Operation\OperationInterface[] reordered operation list
|
||||
* @param OperationInterface[] $operations
|
||||
* @return OperationInterface[] reordered operation list
|
||||
*/
|
||||
private function moveUninstallsToFront(array $operations)
|
||||
{
|
||||
|
|
|
@ -17,9 +17,13 @@ namespace Composer\Downloader;
|
|||
*/
|
||||
class TransportException extends \RuntimeException
|
||||
{
|
||||
/** @var ?array<string, string> */
|
||||
protected $headers;
|
||||
/** @var ?string */
|
||||
protected $response;
|
||||
/** @var ?int */
|
||||
protected $statusCode;
|
||||
/** @var ?array<mixed> */
|
||||
protected $responseInfo = array();
|
||||
|
||||
public function setHeaders($headers)
|
||||
|
|
|
@ -38,7 +38,7 @@ abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterfa
|
|||
protected $process;
|
||||
/** @var Filesystem */
|
||||
protected $filesystem;
|
||||
/** @var array */
|
||||
/** @var array<string, true> */
|
||||
protected $hasCleanedChanges = array();
|
||||
|
||||
public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
|
||||
|
|
|
@ -25,8 +25,11 @@ use ZipArchive;
|
|||
*/
|
||||
class ZipDownloader extends ArchiveDownloader
|
||||
{
|
||||
/** @var array<int, array{0: string, 1: string}> */
|
||||
private static $unzipCommands;
|
||||
/** @var bool */
|
||||
private static $hasZipArchive;
|
||||
/** @var bool */
|
||||
private static $isWindows;
|
||||
|
||||
/** @var ZipArchive|null */
|
||||
|
|
|
@ -28,9 +28,13 @@ use Composer\Util\Silencer;
|
|||
*/
|
||||
class BinaryInstaller
|
||||
{
|
||||
/** @var string */
|
||||
protected $binDir;
|
||||
/** @var string */
|
||||
protected $binCompat;
|
||||
/** @var IOInterface */
|
||||
protected $io;
|
||||
/** @var Filesystem */
|
||||
protected $filesystem;
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,6 +20,7 @@ use Composer\Util\Filesystem;
|
|||
use Composer\Util\Silencer;
|
||||
use Composer\Util\Platform;
|
||||
use React\Promise\PromiseInterface;
|
||||
use Composer\Downloader\DownloadManager;
|
||||
|
||||
/**
|
||||
* Package installation manager.
|
||||
|
@ -29,14 +30,19 @@ use React\Promise\PromiseInterface;
|
|||
*/
|
||||
class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface
|
||||
{
|
||||
/** @var Composer */
|
||||
protected $composer;
|
||||
/** @var string */
|
||||
protected $vendorDir;
|
||||
protected $binDir;
|
||||
/** @var DownloadManager */
|
||||
protected $downloadManager;
|
||||
/** @var IOInterface */
|
||||
protected $io;
|
||||
/** @var string */
|
||||
protected $type;
|
||||
/** @var Filesystem */
|
||||
protected $filesystem;
|
||||
protected $binCompat;
|
||||
/** @var BinaryInstaller */
|
||||
protected $binaryInstaller;
|
||||
|
||||
/**
|
||||
|
|
|
@ -99,7 +99,7 @@ class PluginInstaller extends LibraryInstaller
|
|||
return $promise->then(function () use ($self, $pluginManager, $initial, $target, $repo) {
|
||||
try {
|
||||
Platform::workaroundFilesystemIssues();
|
||||
$pluginManager->deactivatePackage($initial, true);
|
||||
$pluginManager->deactivatePackage($initial);
|
||||
$pluginManager->registerPackage($target, true);
|
||||
} catch (\Exception $e) {
|
||||
$self->rollbackInstall($e, $repo, $target);
|
||||
|
@ -109,7 +109,7 @@ class PluginInstaller extends LibraryInstaller
|
|||
|
||||
public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
|
||||
{
|
||||
$this->composer->getPluginManager()->uninstallPackage($package, true);
|
||||
$this->composer->getPluginManager()->uninstallPackage($package);
|
||||
|
||||
return parent::uninstall($repo, $package);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ use Composer\DependencyResolver\Rule;
|
|||
use Composer\DependencyResolver\RuleSet;
|
||||
use Composer\DependencyResolver\RuleSetIterator;
|
||||
use Composer\DependencyResolver\Pool;
|
||||
use Composer\Semver\Constraint\MatchAllConstraint;
|
||||
use Composer\Test\TestCase;
|
||||
|
||||
class RuleSetIteratorTest extends TestCase
|
||||
|
@ -30,11 +31,11 @@ class RuleSetIteratorTest extends TestCase
|
|||
|
||||
$this->rules = array(
|
||||
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, array('packageName' => '', 'constraint' => new MatchAllConstraint)),
|
||||
new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)),
|
||||
),
|
||||
RuleSet::TYPE_LEARNED => array(
|
||||
new GenericRule(array(), Rule::RULE_LEARNED, null),
|
||||
new GenericRule(array(), Rule::RULE_LEARNED, 1),
|
||||
),
|
||||
RuleSet::TYPE_PACKAGE => array(),
|
||||
);
|
||||
|
|
|
@ -16,6 +16,7 @@ use Composer\DependencyResolver\GenericRule;
|
|||
use Composer\DependencyResolver\Rule;
|
||||
use Composer\DependencyResolver\RuleSet;
|
||||
use Composer\DependencyResolver\Pool;
|
||||
use Composer\Semver\Constraint\MatchAllConstraint;
|
||||
use Composer\Semver\Constraint\MatchNoneConstraint;
|
||||
use Composer\Test\TestCase;
|
||||
|
||||
|
@ -26,11 +27,11 @@ class RuleSetTest extends TestCase
|
|||
$rules = array(
|
||||
RuleSet::TYPE_PACKAGE => array(),
|
||||
RuleSet::TYPE_REQUEST => array(
|
||||
new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null),
|
||||
new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, null),
|
||||
new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)),
|
||||
new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)),
|
||||
),
|
||||
RuleSet::TYPE_LEARNED => array(
|
||||
new GenericRule(array(), Rule::RULE_LEARNED, null),
|
||||
new GenericRule(array(), Rule::RULE_LEARNED, 1),
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -47,9 +48,9 @@ class RuleSetTest extends TestCase
|
|||
{
|
||||
$rules = array(
|
||||
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),
|
||||
new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)),
|
||||
new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)),
|
||||
new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)),
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -67,15 +68,15 @@ class RuleSetTest extends TestCase
|
|||
$ruleSet = new RuleSet;
|
||||
|
||||
$this->setExpectedException('OutOfBoundsException');
|
||||
$ruleSet->add(new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null), 7);
|
||||
$ruleSet->add(new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)), 7);
|
||||
}
|
||||
|
||||
public function testCount()
|
||||
{
|
||||
$ruleSet = new RuleSet;
|
||||
|
||||
$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);
|
||||
$ruleSet->add(new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)), RuleSet::TYPE_REQUEST);
|
||||
$ruleSet->add(new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)), RuleSet::TYPE_REQUEST);
|
||||
|
||||
$this->assertEquals(2, $ruleSet->count());
|
||||
}
|
||||
|
@ -84,7 +85,7 @@ class RuleSetTest extends TestCase
|
|||
{
|
||||
$ruleSet = new RuleSet;
|
||||
|
||||
$rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
$ruleSet->add($rule, RuleSet::TYPE_REQUEST);
|
||||
|
||||
$this->assertSame($rule, $ruleSet->ruleById[0]);
|
||||
|
@ -94,8 +95,8 @@ class RuleSetTest extends TestCase
|
|||
{
|
||||
$ruleSet = new RuleSet;
|
||||
|
||||
$rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule2 = new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
$rule2 = new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
$ruleSet->add($rule1, RuleSet::TYPE_REQUEST);
|
||||
$ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
|
||||
|
||||
|
@ -109,8 +110,8 @@ class RuleSetTest extends TestCase
|
|||
public function testGetIteratorFor()
|
||||
{
|
||||
$ruleSet = new RuleSet;
|
||||
$rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule2 = new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
$rule2 = new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
|
||||
$ruleSet->add($rule1, RuleSet::TYPE_REQUEST);
|
||||
$ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
|
||||
|
@ -123,8 +124,8 @@ class RuleSetTest extends TestCase
|
|||
public function testGetIteratorWithout()
|
||||
{
|
||||
$ruleSet = new RuleSet;
|
||||
$rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule2 = new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
$rule2 = new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
|
||||
$ruleSet->add($rule1, RuleSet::TYPE_REQUEST);
|
||||
$ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
|
||||
|
|
|
@ -24,7 +24,7 @@ class RuleTest extends TestCase
|
|||
{
|
||||
public function testGetHash()
|
||||
{
|
||||
$rule = new GenericRule(array(123), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule = new GenericRule(array(123), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
|
||||
$hash = unpack('ihash', md5('123', true));
|
||||
$this->assertEquals($hash['hash'], $rule->getHash());
|
||||
|
@ -32,31 +32,31 @@ class RuleTest extends TestCase
|
|||
|
||||
public function testEqualsForRulesWithDifferentHashes()
|
||||
{
|
||||
$rule = new GenericRule(array(1, 2), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule2 = new GenericRule(array(1, 3), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule = new GenericRule(array(1, 2), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
$rule2 = new GenericRule(array(1, 3), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
|
||||
$this->assertFalse($rule->equals($rule2));
|
||||
}
|
||||
|
||||
public function testEqualsForRulesWithDifferLiteralsQuantity()
|
||||
{
|
||||
$rule = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule2 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
$rule2 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
|
||||
$this->assertFalse($rule->equals($rule2));
|
||||
}
|
||||
|
||||
public function testEqualsForRulesWithSameLiterals()
|
||||
{
|
||||
$rule = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule2 = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
$rule2 = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
|
||||
$this->assertTrue($rule->equals($rule2));
|
||||
}
|
||||
|
||||
public function testSetAndGetType()
|
||||
{
|
||||
$rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
$rule->setType(RuleSet::TYPE_REQUEST);
|
||||
|
||||
$this->assertEquals(RuleSet::TYPE_REQUEST, $rule->getType());
|
||||
|
@ -64,7 +64,7 @@ class RuleTest extends TestCase
|
|||
|
||||
public function testEnable()
|
||||
{
|
||||
$rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
$rule->disable();
|
||||
$rule->enable();
|
||||
|
||||
|
@ -74,7 +74,7 @@ class RuleTest extends TestCase
|
|||
|
||||
public function testDisable()
|
||||
{
|
||||
$rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
$rule->enable();
|
||||
$rule->disable();
|
||||
|
||||
|
@ -84,8 +84,8 @@ class RuleTest extends TestCase
|
|||
|
||||
public function testIsAssertions()
|
||||
{
|
||||
$rule = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule2 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null);
|
||||
$rule = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
$rule2 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
|
||||
|
||||
$this->assertFalse($rule->isAssertion());
|
||||
$this->assertTrue($rule2->isAssertion());
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
|
||||
namespace Composer\Test\DependencyResolver;
|
||||
|
||||
use Composer\DependencyResolver\Operation\InstallOperation;
|
||||
use Composer\DependencyResolver\Operation\MarkAliasInstalledOperation;
|
||||
use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
|
||||
use Composer\DependencyResolver\Operation\UninstallOperation;
|
||||
use Composer\DependencyResolver\Operation\UpdateOperation;
|
||||
use Composer\DependencyResolver\Transaction;
|
||||
use Composer\Package\Link;
|
||||
use Composer\Test\TestCase;
|
||||
|
@ -97,17 +102,19 @@ class TransactionTest extends TestCase
|
|||
{
|
||||
$result = array();
|
||||
foreach ($transaction->getOperations() as $operation) {
|
||||
if ('update' === $operation->getOperationType()) {
|
||||
if ($operation instanceof UpdateOperation) {
|
||||
$result[] = array(
|
||||
'job' => 'update',
|
||||
'from' => $operation->getInitialPackage(),
|
||||
'to' => $operation->getTargetPackage(),
|
||||
);
|
||||
} else {
|
||||
} elseif ($operation instanceof InstallOperation || $operation instanceof UninstallOperation || $operation instanceof MarkAliasInstalledOperation || $operation instanceof MarkAliasUninstalledOperation) {
|
||||
$result[] = array(
|
||||
'job' => $operation->getOperationType(),
|
||||
'package' => $operation->getPackage(),
|
||||
);
|
||||
} else {
|
||||
throw new \UnexpectedValueException('Unknown operation type: '.get_class($operation));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue