1
0
Fork 0

Merge pull request #325 from naderman/fix-watches-infinite-loop

When changing watched literals of a rule, update the parent's next pointer
pull/326/merge
Jordi Boggiano 2012-02-19 06:44:41 -08:00
commit 1f311de982
2 changed files with 88 additions and 5 deletions

View File

@ -1222,7 +1222,8 @@ class Solver
continue;
}
for ($rule = $this->watches[$literal->getId()]; $rule !== null; $rule = $nextRule) {
$prevRule = null;
for ($rule = $this->watches[$literal->getId()]; $rule !== null; $prevRule = $rule, $rule = $nextRule) {
$nextRule = $rule->getNext($literal);
if ($rule->isDisabled()) {
@ -1242,13 +1243,22 @@ class Solver
if ($otherWatch !== $ruleLiteral->getId() &&
!$this->decisionsConflict($ruleLiteral)) {
if ($literal->getId() === $rule->watch1) {
$rule->watch1 = $ruleLiteral->getId();
$rule->next1 = (isset($this->watches[$ruleLiteral->getId()])) ? $this->watches[$ruleLiteral->getId()] : null ;
$rule->next1 = (isset($this->watches[$ruleLiteral->getId()])) ? $this->watches[$ruleLiteral->getId()] : null;
} else {
$rule->watch2 = $ruleLiteral->getId();
$rule->next2 = (isset($this->watches[$ruleLiteral->getId()])) ? $this->watches[$ruleLiteral->getId()] : null ;
$rule->next2 = (isset($this->watches[$ruleLiteral->getId()])) ? $this->watches[$ruleLiteral->getId()] : null;
}
if ($prevRule) {
if ($prevRule->watch1 === $literal->getId()) {
$prevRule->next1 = $nextRule;
} else {
$prevRule->next2 = $nextRule;
}
} else {
$this->watches[$literal->getId()] = $nextRule;
}
$this->watches[$ruleLiteral->getId()] = $rule;
@ -2018,8 +2028,10 @@ class Solver
}
if ($level > 0) {
echo ' +' . $this->pool->packageById($packageId)."\n";
} else {
} elseif ($level < 0) {
echo ' -' . $this->pool->packageById($packageId)."\n";
} else {
echo ' ?' . $this->pool->packageById($packageId)."\n";
}
}
echo "\n";
@ -2033,4 +2045,41 @@ class Solver
}
echo "\n";
}
private function printWatches()
{
echo "\nWatches:\n";
foreach ($this->watches as $literalId => $watch) {
echo ' '.$this->literalFromId($literalId)."\n";
$queue = array(array(' ', $watch));
while (!empty($queue)) {
list($indent, $watch) = array_pop($queue);
echo $indent.$watch;
if ($watch) {
echo ' [id='.$watch->getId().',watch1='.$this->literalFromId($watch->watch1).',watch2='.$this->literalFromId($watch->watch2)."]";
}
echo "\n";
if ($watch && ($watch->next1 == $watch || $watch->next2 == $watch)) {
if ($watch->next1 == $watch) {
echo $indent." 1 *RECURSION*";
}
if ($watch->next2 == $watch) {
echo $indent." 2 *RECURSION*";
}
} elseif ($watch && ($watch->next1 || $watch->next2)) {
$indent = str_replace(array('1', '2'), ' ', $indent);
array_push($queue, array($indent.' 2 ', $watch->next2));
array_push($queue, array($indent.' 1 ', $watch->next1));
}
}
echo "\n";
}
}
}

View File

@ -485,6 +485,40 @@ class SolverTest extends TestCase
));
}
public function testIssue265()
{
$this->repo->addPackage($packageA1 = $this->getPackage('A', '2.0.999999-dev'));
$this->repo->addPackage($packageA2 = $this->getPackage('A', '2.1-dev'));
$this->repo->addPackage($packageA3 = $this->getPackage('A', '2.2-dev'));
$this->repo->addPackage($packageB1 = $this->getPackage('B', '2.0.10'));
$this->repo->addPackage($packageB2 = $this->getPackage('B', '2.0.9'));
$this->repo->addPackage($packageC = $this->getPackage('C', '2.0-dev'));
$this->repo->addPackage($packageD = $this->getPackage('D', '2.0.9'));
$packageC->setRequires(array(
new Link('C', 'A', new VersionConstraint('>=', '2.0'), 'requires'),
new Link('C', 'D', new VersionConstraint('>=', '2.0'), 'requires'),
));
$packageD->setRequires(array(
new Link('D', 'A', new VersionConstraint('>=', '2.1'), 'requires'),
new Link('D', 'B', new VersionConstraint('>=', '2.0-dev'), 'requires'),
));
$packageB1->setRequires(array(new Link('B', 'A', new VersionConstraint('==', '2.1.0.0-dev'), 'requires')));
$packageB2->setRequires(array(new Link('B', 'A', new VersionConstraint('==', '2.1.0.0-dev'), 'requires')));
$packageB2->setReplaces(array(new Link('B', 'D', new VersionConstraint('==', '2.0.9.0'), 'replaces')));
$this->reposComplete();
$this->request->install('C', new VersionConstraint('==', '2.0.0.0-dev'));
$this->setExpectedException('Composer\DependencyResolver\SolverProblemsException');
$this->solver->solve($this->request);
}
public function testConflictResultEmpty()
{
$this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));