Move transaction generation to a separate class
parent
8d65d70c56
commit
8fc09afbae
|
@ -30,7 +30,7 @@ class DefaultPolicy implements PolicyInterface
|
||||||
return $constraint->matchSpecific($version);
|
return $constraint->matchSpecific($version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findUpdatePackages(Solver $solver, Pool $pool, array $installedMap, PackageInterface $package)
|
public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package)
|
||||||
{
|
{
|
||||||
$packages = array();
|
$packages = array();
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ use Composer\Package\PackageInterface;
|
||||||
interface PolicyInterface
|
interface PolicyInterface
|
||||||
{
|
{
|
||||||
function versionCompare(PackageInterface $a, PackageInterface $b, $operator);
|
function versionCompare(PackageInterface $a, PackageInterface $b, $operator);
|
||||||
function findUpdatePackages(Solver $solver, Pool $pool, array $installedMap, PackageInterface $package);
|
function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package);
|
||||||
function installable(Solver $solver, Pool $pool, array $installedMap, PackageInterface $package);
|
function installable(Solver $solver, Pool $pool, array $installedMap, PackageInterface $package);
|
||||||
function selectPreferedPackages(Pool $pool, array $installedMap, array $literals);
|
function selectPreferedPackages(Pool $pool, array $installedMap, array $literals);
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,30 +84,6 @@ class Solver
|
||||||
return new Rule($literals, $reason, $reasonData);
|
return new Rule($literals, $reason, $reasonData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new rule for updating a package
|
|
||||||
*
|
|
||||||
* If package A1 can be updated to A2 or A3 the rule is (A1|A2|A3).
|
|
||||||
*
|
|
||||||
* @param PackageInterface $package The package to be updated
|
|
||||||
* @param array $updates An array of update candidate packages
|
|
||||||
* @param int $reason A RULE_* constant describing the
|
|
||||||
* reason for generating this rule
|
|
||||||
* @param mixed $reasonData Any data, e.g. the package name, that
|
|
||||||
* goes with the reason
|
|
||||||
* @return Rule The generated rule or null if tautology
|
|
||||||
*/
|
|
||||||
protected function createUpdateRule(PackageInterface $package, array $updates, $reason, $reasonData = null)
|
|
||||||
{
|
|
||||||
$literals = array(new Literal($package, true));
|
|
||||||
|
|
||||||
foreach ($updates as $update) {
|
|
||||||
$literals[] = new Literal($update, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Rule($literals, $reason, $reasonData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new rule for installing a package
|
* Creates a new rule for installing a package
|
||||||
*
|
*
|
||||||
|
@ -308,7 +284,7 @@ class Solver
|
||||||
*/
|
*/
|
||||||
private function addRulesForUpdatePackages(PackageInterface $package)
|
private function addRulesForUpdatePackages(PackageInterface $package)
|
||||||
{
|
{
|
||||||
$updates = $this->policy->findUpdatePackages($this, $this->pool, $this->installedMap, $package);
|
$updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
|
||||||
|
|
||||||
$this->addRulesForPackage($package);
|
$this->addRulesForPackage($package);
|
||||||
|
|
||||||
|
@ -568,13 +544,6 @@ class Solver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->installedMap as $package) {
|
|
||||||
$updates = $this->policy->findUpdatePackages($this, $this->pool, $this->installedMap, $package);
|
|
||||||
$rule = $this->createUpdateRule($package, $updates, Rule::RULE_INTERNAL_ALLOW_UPDATE, (string) $package);
|
|
||||||
|
|
||||||
$this->packageToUpdateRule[$package->getId()] = $rule;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($this->jobs as $job) {
|
foreach ($this->jobs as $job) {
|
||||||
switch ($job['cmd']) {
|
switch ($job['cmd']) {
|
||||||
case 'install':
|
case 'install':
|
||||||
|
@ -627,133 +596,8 @@ class Solver
|
||||||
throw new SolverProblemsException($this->problems);
|
throw new SolverProblemsException($this->problems);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->createTransaction();
|
$transaction = new Transaction($this->policy, $this->pool, $this->installedMap, $this->decisionMap, $this->decisionQueue, $this->decisionQueueWhy);
|
||||||
}
|
return $transaction->getOperations();
|
||||||
|
|
||||||
protected function createTransaction()
|
|
||||||
{
|
|
||||||
$transaction = array();
|
|
||||||
$installMeansUpdateMap = array();
|
|
||||||
|
|
||||||
foreach ($this->decisionQueue as $i => $literal) {
|
|
||||||
$package = $literal->getPackage();
|
|
||||||
|
|
||||||
// !wanted & installed
|
|
||||||
if (!$literal->isWanted() && isset($this->installedMap[$package->getId()])) {
|
|
||||||
$literals = array();
|
|
||||||
|
|
||||||
if (isset($this->packageToUpdateRule[$package->getId()])) {
|
|
||||||
$literals = array_merge($literals, $this->packageToUpdateRule[$package->getId()]->getLiterals());
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($literals as $updateLiteral) {
|
|
||||||
if (!$updateLiteral->equals($literal)) {
|
|
||||||
$installMeansUpdateMap[$updateLiteral->getPackageId()] = $package;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($this->decisionQueue as $i => $literal) {
|
|
||||||
$package = $literal->getPackage();
|
|
||||||
|
|
||||||
// wanted & installed || !wanted & !installed
|
|
||||||
if ($literal->isWanted() == (isset($this->installedMap[$package->getId()]))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($literal->isWanted()) {
|
|
||||||
if ($package instanceof AliasPackage) {
|
|
||||||
$transaction[] = new Operation\MarkAliasInstalledOperation(
|
|
||||||
$package, $this->decisionQueueWhy[$i]
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($installMeansUpdateMap[$literal->getPackageId()])) {
|
|
||||||
|
|
||||||
$source = $installMeansUpdateMap[$literal->getPackageId()];
|
|
||||||
|
|
||||||
$transaction[] = new Operation\UpdateOperation(
|
|
||||||
$source, $package, $this->decisionQueueWhy[$i]
|
|
||||||
);
|
|
||||||
|
|
||||||
// avoid updates to one package from multiple origins
|
|
||||||
unset($installMeansUpdateMap[$literal->getPackageId()]);
|
|
||||||
$ignoreRemove[$source->getId()] = true;
|
|
||||||
} else {
|
|
||||||
$transaction[] = new Operation\InstallOperation(
|
|
||||||
$package, $this->decisionQueueWhy[$i]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (!isset($ignoreRemove[$package->getId()])) {
|
|
||||||
if ($package instanceof AliasPackage) {
|
|
||||||
$transaction[] = new Operation\MarkAliasInstalledOperation(
|
|
||||||
$package, $this->decisionQueueWhy[$i]
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$transaction[] = new Operation\UninstallOperation(
|
|
||||||
$package, $this->decisionQueueWhy[$i]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$allDecidedMap = $this->decisionMap;
|
|
||||||
foreach ($this->decisionMap as $packageId => $decision) {
|
|
||||||
if ($decision != 0) {
|
|
||||||
$package = $this->pool->packageById($packageId);
|
|
||||||
if ($package instanceof AliasPackage) {
|
|
||||||
$allDecidedMap[$package->getAliasOf()->getId()] = $decision;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($allDecidedMap as $packageId => $decision) {
|
|
||||||
if ($packageId === 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == $decision && isset($this->installedMap[$packageId])) {
|
|
||||||
$package = $this->pool->packageById($packageId);
|
|
||||||
|
|
||||||
if ($package instanceof AliasPackage) {
|
|
||||||
$transaction[] = new Operation\MarkAliasInstalledOperation(
|
|
||||||
$package, null
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$transaction[] = new Operation\UninstallOperation(
|
|
||||||
$package, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->decisionMap[$packageId] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($this->decisionMap as $packageId => $decision) {
|
|
||||||
if ($packageId === 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == $decision && isset($this->installedMap[$packageId])) {
|
|
||||||
$package = $this->pool->packageById($packageId);
|
|
||||||
|
|
||||||
if ($package instanceof AliasPackage) {
|
|
||||||
$transaction[] = new Operation\MarkAliasInstalledOperation(
|
|
||||||
$package, null
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$transaction[] = new Operation\UninstallOperation(
|
|
||||||
$package, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->decisionMap[$packageId] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return array_reverse($transaction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function literalFromId($id)
|
protected function literalFromId($id)
|
||||||
|
|
|
@ -0,0 +1,169 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer\DependencyResolver;
|
||||||
|
|
||||||
|
use Composer\Repository\RepositoryInterface;
|
||||||
|
use Composer\Package\PackageInterface;
|
||||||
|
use Composer\Package\AliasPackage;
|
||||||
|
use Composer\DependencyResolver\Operation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nils Adermann <naderman@naderman.de>
|
||||||
|
*/
|
||||||
|
class Transaction
|
||||||
|
{
|
||||||
|
protected $policy;
|
||||||
|
protected $pool;
|
||||||
|
protected $installedMap;
|
||||||
|
protected $decisionMap;
|
||||||
|
protected $decisionQueue;
|
||||||
|
protected $decisionQueueWhy;
|
||||||
|
|
||||||
|
public function __construct($policy, $pool, $installedMap, $decisionMap, array $decisionQueue, $decisionQueueWhy)
|
||||||
|
{
|
||||||
|
$this->policy = $policy;
|
||||||
|
$this->pool = $pool;
|
||||||
|
$this->installedMap = $installedMap;
|
||||||
|
$this->decisionMap = $decisionMap;
|
||||||
|
$this->decisionQueue = $decisionQueue;
|
||||||
|
$this->decisionQueueWhy = $decisionQueueWhy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOperations()
|
||||||
|
{
|
||||||
|
$transaction = array();
|
||||||
|
$installMeansUpdateMap = array();
|
||||||
|
|
||||||
|
foreach ($this->decisionQueue as $i => $literal) {
|
||||||
|
$package = $literal->getPackage();
|
||||||
|
|
||||||
|
// !wanted & installed
|
||||||
|
if (!$literal->isWanted() && isset($this->installedMap[$package->getId()])) {
|
||||||
|
$updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
|
||||||
|
|
||||||
|
$literals = array(new Literal($package, true));
|
||||||
|
|
||||||
|
foreach ($updates as $update) {
|
||||||
|
$literals[] = new Literal($update, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($literals as $updateLiteral) {
|
||||||
|
if (!$updateLiteral->equals($literal)) {
|
||||||
|
$installMeansUpdateMap[$updateLiteral->getPackageId()] = $package;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->decisionQueue as $i => $literal) {
|
||||||
|
$package = $literal->getPackage();
|
||||||
|
|
||||||
|
// wanted & installed || !wanted & !installed
|
||||||
|
if ($literal->isWanted() == (isset($this->installedMap[$package->getId()]))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($literal->isWanted()) {
|
||||||
|
if ($package instanceof AliasPackage) {
|
||||||
|
$transaction[] = new Operation\MarkAliasInstalledOperation(
|
||||||
|
$package, $this->decisionQueueWhy[$i]
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($installMeansUpdateMap[$literal->getPackageId()])) {
|
||||||
|
|
||||||
|
$source = $installMeansUpdateMap[$literal->getPackageId()];
|
||||||
|
|
||||||
|
$transaction[] = new Operation\UpdateOperation(
|
||||||
|
$source, $package, $this->decisionQueueWhy[$i]
|
||||||
|
);
|
||||||
|
|
||||||
|
// avoid updates to one package from multiple origins
|
||||||
|
unset($installMeansUpdateMap[$literal->getPackageId()]);
|
||||||
|
$ignoreRemove[$source->getId()] = true;
|
||||||
|
} else {
|
||||||
|
$transaction[] = new Operation\InstallOperation(
|
||||||
|
$package, $this->decisionQueueWhy[$i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (!isset($ignoreRemove[$package->getId()])) {
|
||||||
|
if ($package instanceof AliasPackage) {
|
||||||
|
$transaction[] = new Operation\MarkAliasInstalledOperation(
|
||||||
|
$package, $this->decisionQueueWhy[$i]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$transaction[] = new Operation\UninstallOperation(
|
||||||
|
$package, $this->decisionQueueWhy[$i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$allDecidedMap = $this->decisionMap;
|
||||||
|
foreach ($this->decisionMap as $packageId => $decision) {
|
||||||
|
if ($decision != 0) {
|
||||||
|
$package = $this->pool->packageById($packageId);
|
||||||
|
if ($package instanceof AliasPackage) {
|
||||||
|
$allDecidedMap[$package->getAliasOf()->getId()] = $decision;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($allDecidedMap as $packageId => $decision) {
|
||||||
|
if ($packageId === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == $decision && isset($this->installedMap[$packageId])) {
|
||||||
|
$package = $this->pool->packageById($packageId);
|
||||||
|
|
||||||
|
if ($package instanceof AliasPackage) {
|
||||||
|
$transaction[] = new Operation\MarkAliasInstalledOperation(
|
||||||
|
$package, null
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$transaction[] = new Operation\UninstallOperation(
|
||||||
|
$package, null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->decisionMap[$packageId] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->decisionMap as $packageId => $decision) {
|
||||||
|
if ($packageId === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == $decision && isset($this->installedMap[$packageId])) {
|
||||||
|
$package = $this->pool->packageById($packageId);
|
||||||
|
|
||||||
|
if ($package instanceof AliasPackage) {
|
||||||
|
$transaction[] = new Operation\MarkAliasInstalledOperation(
|
||||||
|
$package, null
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$transaction[] = new Operation\UninstallOperation(
|
||||||
|
$package, null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->decisionMap[$packageId] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_reverse($transaction);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue