From de7f666118df3f9b4ed6aebd798ed5ae8a186081 Mon Sep 17 00:00:00 2001 From: Leszek Prabucki Date: Sun, 22 Jan 2012 22:06:09 +0100 Subject: [PATCH 01/42] Added and extended some unit tests --- .../Test/DependencyResolver/PoolTest.php | 61 +++++ .../RuleSetIteratorTest.php | 19 ++ .../Test/DependencyResolver/RuleSetTest.php | 139 ++++++++++- .../Test/DependencyResolver/RuleTest.php | 170 ++++++++++++++ .../Test/Downloader/GitDownloaderTest.php | 111 +++++++++ .../Test/Downloader/HgDownloaderTest.php | 111 +++++++++ tests/Composer/Test/IO/ConsoleIOTest.php | 219 ++++++++++++++++++ 7 files changed, 829 insertions(+), 1 deletion(-) create mode 100644 tests/Composer/Test/DependencyResolver/RuleTest.php create mode 100644 tests/Composer/Test/Downloader/GitDownloaderTest.php create mode 100644 tests/Composer/Test/Downloader/HgDownloaderTest.php create mode 100644 tests/Composer/Test/IO/ConsoleIOTest.php diff --git a/tests/Composer/Test/DependencyResolver/PoolTest.php b/tests/Composer/Test/DependencyResolver/PoolTest.php index c4dcb0bcc..643be0428 100644 --- a/tests/Composer/Test/DependencyResolver/PoolTest.php +++ b/tests/Composer/Test/DependencyResolver/PoolTest.php @@ -30,4 +30,65 @@ class PoolTest extends TestCase $this->assertEquals(array($package), $pool->whatProvides('foo')); $this->assertEquals(array($package), $pool->whatProvides('foo')); } + + /** + * @expectedException \RuntimeException + */ + public function testGetPriorityForNotRegisteredRepository() + { + $pool = new Pool; + $repository = new ArrayRepository; + + $pool->getPriority($repository); + } + + public function testGetPriorityWhenRepositoryIsRegistered() + { + $pool = new Pool; + $firstRepository = new ArrayRepository; + $pool->addRepository($firstRepository); + $secondRepository = new ArrayRepository; + $pool->addRepository($secondRepository); + + $firstPriority = $pool->getPriority($firstRepository); + $secondPriority = $pool->getPriority($secondRepository); + + $this->assertEquals(0, $firstPriority); + $this->assertEquals(1, $secondPriority); + } + + public function testPackageById() + { + $pool = new Pool; + $repository = new ArrayRepository; + $package = $this->getPackage('foo', '1'); + + $repository->addPackage($package); + $pool->addRepository($repository); + + $this->assertSame($package, $pool->packageById(1)); + } + + public function testWhatProvidesWhenPackageCannotBeFound() + { + $pool = new Pool; + + $this->assertEquals(array(), $pool->whatProvides('foo')); + } + + public function testGetMaxId() + { + $pool = new Pool; + $repository = new ArrayRepository; + $firstPackage = $this->getPackage('foo', '1'); + $secondPackage = $this->getPackage('foo1', '1'); + + $this->assertEquals(0, $pool->getMaxId()); + + $repository->addPackage($firstPackage); + $repository->addPackage($secondPackage); + $pool->addRepository($repository); + + $this->assertEquals(2, $pool->getMaxId()); + } } diff --git a/tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php b/tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php index 2daa64eb6..d45f9a561 100644 --- a/tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php +++ b/tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php @@ -52,4 +52,23 @@ class ResultSetIteratorTest extends \PHPUnit_Framework_TestCase $this->assertEquals($expected, $result); } + + public function testKeys() + { + $ruleSetIterator = new RuleSetIterator($this->rules); + + $result = array(); + foreach ($ruleSetIterator as $key => $rule) + { + $result[] = $key; + } + + $expected = array( + RuleSet::TYPE_JOB, + RuleSet::TYPE_JOB, + RuleSet::TYPE_UPDATE, + ); + + $this->assertEquals($expected, $result); + } } diff --git a/tests/Composer/Test/DependencyResolver/RuleSetTest.php b/tests/Composer/Test/DependencyResolver/RuleSetTest.php index fa42d4522..be37b8795 100644 --- a/tests/Composer/Test/DependencyResolver/RuleSetTest.php +++ b/tests/Composer/Test/DependencyResolver/RuleSetTest.php @@ -14,8 +14,10 @@ namespace Composer\Test\DependencyResolver; use Composer\DependencyResolver\Rule; use Composer\DependencyResolver\RuleSet; +use Composer\DependencyResolver\Literal; +use Composer\Test\TestCase; -class RuleSetTest extends \PHPUnit_Framework_TestCase +class RuleSetTest extends TestCase { public function testAdd() { @@ -41,4 +43,139 @@ class RuleSetTest extends \PHPUnit_Framework_TestCase $this->assertEquals($rules, $ruleSet->getRules()); } + + /** + * @expectedException \OutOfBoundsException + */ + public function testAddWhenTypeIsNotRecognized() + { + $ruleSet = new RuleSet; + + $ruleSet->add(new Rule(array(), 'job1', null), 7); + } + + public function testAddWhenTypeIsUnknow() + { + $ruleSet = new RuleSet; + + $rule = new Rule(array(), 'job1', null); + $ruleSet->add($rule, -1); + + $rules = $ruleSet->getRules(); + $this->assertSame($rule, $rules[-1][0]); + } + + public function testCount() + { + $ruleSet = new RuleSet; + + $ruleSet->add(new Rule(array(), 'job1', null), RuleSet::TYPE_JOB); + $ruleSet->add(new Rule(array(), 'job2', null), RuleSet::TYPE_JOB); + + $this->assertEquals(2, $ruleSet->count()); + } + + public function testRuleById() + { + $ruleSet = new RuleSet; + + $rule = new Rule(array(), 'job1', null); + $ruleSet->add($rule, RuleSet::TYPE_JOB); + + $this->assertSame($rule, $ruleSet->ruleById(0)); + } + + public function testGetIterator() + { + $ruleSet = new RuleSet; + + $rule1 = new Rule(array(), 'job1', null); + $rule2 = new Rule(array(), 'job1', null); + $ruleSet->add($rule1, RuleSet::TYPE_JOB); + $ruleSet->add($rule2, RuleSet::TYPE_UPDATE); + + $iterator = $ruleSet->getIterator(); + + $this->assertSame($rule1, $iterator->current()); + $iterator->next(); + $this->assertSame($rule2, $iterator->current()); + } + + public function testGetIteratorFor() + { + $ruleSet = new RuleSet; + $rule1 = new Rule(array(), 'job1', null); + $rule2 = new Rule(array(), 'job1', null); + + $ruleSet->add($rule1, RuleSet::TYPE_JOB); + $ruleSet->add($rule2, RuleSet::TYPE_UPDATE); + + $iterator = $ruleSet->getIteratorFor(RuleSet::TYPE_UPDATE); + + $this->assertSame($rule2, $iterator->current()); + } + + public function testGetIteratorWithout() + { + $ruleSet = new RuleSet; + $rule1 = new Rule(array(), 'job1', null); + $rule2 = new Rule(array(), 'job1', null); + + $ruleSet->add($rule1, RuleSet::TYPE_JOB); + $ruleSet->add($rule2, RuleSet::TYPE_UPDATE); + + $iterator = $ruleSet->getIteratorWithout(RuleSet::TYPE_JOB); + + $this->assertSame($rule2, $iterator->current()); + } + + public function testContainsEqual() + { + $ruleSet = new RuleSet; + + $rule = $this->getRuleMock(); + $rule->expects($this->any()) + ->method('getHash') + ->will($this->returnValue('rule_1_hash')); + $rule->expects($this->any()) + ->method('equals') + ->will($this->returnValue(true)); + + $rule2 = $this->getRuleMock(); + $rule2->expects($this->any()) + ->method('getHash') + ->will($this->returnValue('rule_2_hash')); + + $rule3 = $this->getRuleMock(); + $rule3->expects($this->any()) + ->method('getHash') + ->will($this->returnValue('rule_1_hash')); + $rule3->expects($this->any()) + ->method('equal') + ->will($this->returnValue(false)); + + $ruleSet->add($rule, RuleSet::TYPE_UPDATE); + + $this->assertTrue($ruleSet->containsEqual($rule)); + $this->assertFalse($ruleSet->containsEqual($rule2)); + $this->assertFalse($ruleSet->containsEqual($rule3)); + } + + public function testToString() + { + $ruleSet = new RuleSet; + $literal = new Literal($this->getPackage('foo', '2.1'), true); + $rule = new Rule(array($literal), 'job1', null); + + $ruleSet->add($rule, RuleSet::TYPE_UPDATE); + + $this->assertContains('UPDATE : (+foo-2.1.0.0)', $ruleSet->__toString()); + } + + private function getRuleMock() + { + return $this->getMockBuilder('Composer\DependencyResolver\Rule') + ->disableOriginalConstructor() + ->getMock(); + } } diff --git a/tests/Composer/Test/DependencyResolver/RuleTest.php b/tests/Composer/Test/DependencyResolver/RuleTest.php new file mode 100644 index 000000000..f76f46eb1 --- /dev/null +++ b/tests/Composer/Test/DependencyResolver/RuleTest.php @@ -0,0 +1,170 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Test\DependencyResolver; + +use Composer\DependencyResolver\Rule; +use Composer\DependencyResolver\Literal; +use Composer\Test\TestCase; + +class RuleTest extends TestCase +{ + public function testGetHash() + { + $rule = new Rule(array(), 'job1', null); + $rule->ruleHash = '123'; + + $this->assertEquals('123', $rule->getHash()); + } + + public function testSetAndGetId() + { + $rule = new Rule(array(), 'job1', null); + $rule->setId(666); + + $this->assertEquals(666, $rule->getId()); + } + + public function testEqualsForRulesWithDifferentHashes() + { + $rule = new Rule(array(), 'job1', null); + $rule->ruleHash = '123'; + + $rule2 = new Rule(array(), 'job1', null); + $rule2->ruleHash = '321'; + + $this->assertFalse($rule->equals($rule2)); + } + + public function testEqualsForRulesWithDifferentLiterals() + { + $literal = $this->getLiteralMock(); + $literal->expects($this->any()) + ->method('getId') + ->will($this->returnValue(1)); + $rule = new Rule(array($literal), 'job1', null); + $rule->ruleHash = '123'; + + $literal = $this->getLiteralMock(); + $literal->expects($this->any()) + ->method('getId') + ->will($this->returnValue(12)); + $rule2 = new Rule(array($literal), 'job1', null); + $rule2->ruleHash = '123'; + + $this->assertFalse($rule->equals($rule2)); + } + + public function testEqualsForRulesWithDifferLiteralsQuantity() + { + $literal = $this->getLiteralMock(); + $literal->expects($this->any()) + ->method('getId') + ->will($this->returnValue(1)); + $literal2 = $this->getLiteralMock(); + $literal2->expects($this->any()) + ->method('getId') + ->will($this->returnValue(12)); + + $rule = new Rule(array($literal, $literal2), 'job1', null); + $rule->ruleHash = '123'; + $rule2 = new Rule(array($literal), 'job1', null); + $rule2->ruleHash = '123'; + + $this->assertFalse($rule->equals($rule2)); + } + + public function testEqualsForRulesWithThisSameLiterals() + { + $literal = $this->getLiteralMock(); + $literal->expects($this->any()) + ->method('getId') + ->will($this->returnValue(1)); + $literal2 = $this->getLiteralMock(); + $literal2->expects($this->any()) + ->method('getId') + ->will($this->returnValue(12)); + + $rule = new Rule(array($literal, $literal2), 'job1', null); + $rule2 = new Rule(array($literal, $literal2), 'job1', null); + + $this->assertTrue($rule->equals($rule2)); + } + + public function testSetAndGetType() + { + $rule = new Rule(array(), 'job1', null); + $rule->setType('someType'); + + $this->assertEquals('someType', $rule->getType()); + } + + public function testEnable() + { + $rule = new Rule(array(), 'job1', null); + $rule->disable(); + $rule->enable(); + + $this->assertTrue($rule->isEnabled()); + $this->assertFalse($rule->isDisabled()); + } + + public function testDisable() + { + $rule = new Rule(array(), 'job1', null); + $rule->enable(); + $rule->disable(); + + $this->assertTrue($rule->isDisabled()); + $this->assertFalse($rule->isEnabled()); + } + + public function testSetWeak() + { + $rule = new Rule(array(), 'job1', null); + $rule->setWeak(true); + + $rule2 = new Rule(array(), 'job1', null); + $rule2->setWeak(false); + + $this->assertTrue($rule->isWeak()); + $this->assertFalse($rule2->isWeak()); + } + + public function testIsAssertions() + { + $literal = $this->getLiteralMock(); + $literal2 = $this->getLiteralMock(); + $rule = new Rule(array($literal, $literal2), 'job1', null); + $rule2 = new Rule(array($literal), 'job1', null); + + $this->assertFalse($rule->isAssertion()); + $this->assertTrue($rule2->isAssertion()); + } + + public function testToString() + { + $literal = new Literal($this->getPackage('foo', '2.1'), true); + $literal2 = new Literal($this->getPackage('baz', '1.1'), false); + + $rule = new Rule(array($literal, $literal2), 'job1', null); + + $this->assertEquals('(-baz-1.1.0.0|+foo-2.1.0.0)', $rule->__toString()); + } + + private function getLiteralMock() + { + return $this->getMockBuilder('Composer\DependencyResolver\Literal') + ->disableOriginalConstructor() + ->getMock(); + } +} diff --git a/tests/Composer/Test/Downloader/GitDownloaderTest.php b/tests/Composer/Test/Downloader/GitDownloaderTest.php new file mode 100644 index 000000000..57cbd945d --- /dev/null +++ b/tests/Composer/Test/Downloader/GitDownloaderTest.php @@ -0,0 +1,111 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Test\Downloader; + +use Composer\Downloader\GitDownloader; + +class GitDownloaderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @expectedException \InvalidArgumentException + */ + public function testDownloadForPackageWithoutSourceReference() + { + $packageMock = $this->getMock('Composer\Package\PackageInterface'); + $packageMock->expects($this->once()) + ->method('getSourceReference') + ->will($this->returnValue(null)); + + $downloader = new GitDownloader(); + $downloader->download($packageMock, '/path'); + } + + public function testDownload() + { + $expectedGitCommand = 'git clone \'https://github.com/l3l0/composer\' composerPath && cd composerPath && git checkout \'ref\' && git reset --hard \'ref\''; + $packageMock = $this->getMock('Composer\Package\PackageInterface'); + $packageMock->expects($this->any()) + ->method('getSourceReference') + ->will($this->returnValue('ref')); + $packageMock->expects($this->once()) + ->method('getSourceUrl') + ->will($this->returnValue('https://github.com/l3l0/composer')); + $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); + $processExecutor->expects($this->once()) + ->method('execute') + ->with($this->equalTo($expectedGitCommand)); + + $downloader = new GitDownloader($processExecutor); + $downloader->download($packageMock, 'composerPath'); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testUpdateforPackageWithoutSourceReference() + { + $initialPackageMock = $this->getMock('Composer\Package\PackageInterface'); + $sourcePackageMock = $this->getMock('Composer\Package\PackageInterface'); + $sourcePackageMock->expects($this->once()) + ->method('getSourceReference') + ->will($this->returnValue(null)); + + $downloader = new GitDownloader(); + $downloader->update($initialPackageMock, $sourcePackageMock, '/path'); + } + + public function testUpdate() + { + $expectedGitUpdateCommand = 'cd composerPath && git fetch && git checkout ref && git reset --hard ref'; + $expectedGitResetCommand = 'cd composerPath && git status --porcelain'; + + $packageMock = $this->getMock('Composer\Package\PackageInterface'); + $packageMock->expects($this->any()) + ->method('getSourceReference') + ->will($this->returnValue('ref')); + $packageMock->expects($this->any()) + ->method('getSourceUrl') + ->will($this->returnValue('https://github.com/l3l0/composer')); + $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); + $processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedGitResetCommand)); + $processExecutor->expects($this->at(1)) + ->method('execute') + ->with($this->equalTo($expectedGitUpdateCommand)); + + $downloader = new GitDownloader($processExecutor); + $downloader->update($packageMock, $packageMock, 'composerPath'); + } + + public function testRemove() + { + $expectedGitResetCommand = 'cd composerPath && git status --porcelain'; + + $packageMock = $this->getMock('Composer\Package\PackageInterface'); + $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); + $processExecutor->expects($this->any()) + ->method('execute') + ->with($this->equalTo($expectedGitResetCommand)); + + $downloader = new GitDownloader($processExecutor); + $downloader->remove($packageMock, 'composerPath'); + } + + public function testGetInstallationSource() + { + $downloader = new GitDownloader(); + + $this->assertEquals('source', $downloader->getInstallationSource()); + } +} diff --git a/tests/Composer/Test/Downloader/HgDownloaderTest.php b/tests/Composer/Test/Downloader/HgDownloaderTest.php new file mode 100644 index 000000000..d6752eb4a --- /dev/null +++ b/tests/Composer/Test/Downloader/HgDownloaderTest.php @@ -0,0 +1,111 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Test\Downloader; + +use Composer\Downloader\HgDownloader; + +class HgDownloaderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @expectedException \InvalidArgumentException + */ + public function testDownloadForPackageWithoutSourceReference() + { + $packageMock = $this->getMock('Composer\Package\PackageInterface'); + $packageMock->expects($this->once()) + ->method('getSourceReference') + ->will($this->returnValue(null)); + + $downloader = new HgDownloader(); + $downloader->download($packageMock, '/path'); + } + + public function testDownload() + { + $expectedGitCommand = '(hg clone \'https://mercurial.dev/l3l0/composer\' composerPath 2> /dev/null) && cd composerPath && hg up \'ref\''; + $packageMock = $this->getMock('Composer\Package\PackageInterface'); + $packageMock->expects($this->any()) + ->method('getSourceReference') + ->will($this->returnValue('ref')); + $packageMock->expects($this->once()) + ->method('getSourceUrl') + ->will($this->returnValue('https://mercurial.dev/l3l0/composer')); + $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); + $processExecutor->expects($this->once()) + ->method('execute') + ->with($this->equalTo($expectedGitCommand)); + + $downloader = new HgDownloader($processExecutor); + $downloader->download($packageMock, 'composerPath'); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testUpdateforPackageWithoutSourceReference() + { + $initialPackageMock = $this->getMock('Composer\Package\PackageInterface'); + $sourcePackageMock = $this->getMock('Composer\Package\PackageInterface'); + $sourcePackageMock->expects($this->once()) + ->method('getSourceReference') + ->will($this->returnValue(null)); + + $downloader = new HgDownloader(); + $downloader->update($initialPackageMock, $sourcePackageMock, '/path'); + } + + public function testUpdate() + { + $expectedGitUpdateCommand = 'cd composerPath && hg pull && hg up \'ref\''; + $expectedGitResetCommand = 'cd composerPath && hg st'; + + $packageMock = $this->getMock('Composer\Package\PackageInterface'); + $packageMock->expects($this->any()) + ->method('getSourceReference') + ->will($this->returnValue('ref')); + $packageMock->expects($this->any()) + ->method('getSourceUrl') + ->will($this->returnValue('https://github.com/l3l0/composer')); + $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); + $processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedGitResetCommand)); + $processExecutor->expects($this->at(1)) + ->method('execute') + ->with($this->equalTo($expectedGitUpdateCommand)); + + $downloader = new HgDownloader($processExecutor); + $downloader->update($packageMock, $packageMock, 'composerPath'); + } + + public function testRemove() + { + $expectedGitResetCommand = 'cd composerPath && hg st'; + + $packageMock = $this->getMock('Composer\Package\PackageInterface'); + $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); + $processExecutor->expects($this->any()) + ->method('execute') + ->with($this->equalTo($expectedGitResetCommand)); + + $downloader = new HgDownloader($processExecutor); + $downloader->remove($packageMock, 'composerPath'); + } + + public function testGetInstallationSource() + { + $downloader = new HgDownloader(); + + $this->assertEquals('source', $downloader->getInstallationSource()); + } +} diff --git a/tests/Composer/Test/IO/ConsoleIOTest.php b/tests/Composer/Test/IO/ConsoleIOTest.php new file mode 100644 index 000000000..78450eb53 --- /dev/null +++ b/tests/Composer/Test/IO/ConsoleIOTest.php @@ -0,0 +1,219 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Test\IO; + +use Composer\IO\ConsoleIO; +use Composer\Test\TestCase; + +class ConsoleIOTest extends TestCase +{ + public function testIsInteractive() + { + $inputMock = $this->getMock('Symfony\Component\Console\Input\InputInterface'); + $inputMock->expects($this->at(0)) + ->method('isInteractive') + ->will($this->returnValue(true)); + $inputMock->expects($this->at(1)) + ->method('isInteractive') + ->will($this->returnValue(false)); + + $outputMock = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); + $helperMock = $this->getMock('Symfony\Component\Console\Helper\HelperSet'); + + $consoleIO = new ConsoleIO($inputMock, $outputMock, $helperMock); + + $this->assertTrue($consoleIO->isInteractive()); + $this->assertFalse($consoleIO->isInteractive()); + } + + public function testWrite() + { + $inputMock = $this->getMock('Symfony\Component\Console\Input\InputInterface'); + $outputMock = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); + $outputMock->expects($this->once()) + ->method('write') + ->with($this->equalTo('some information about something'), $this->equalTo(false)); + $helperMock = $this->getMock('Symfony\Component\Console\Helper\HelperSet'); + + $consoleIO = new ConsoleIO($inputMock, $outputMock, $helperMock); + $consoleIO->write('some information about something', false); + } + + public function testOverwrite() + { + $inputMock = $this->getMock('Symfony\Component\Console\Input\InputInterface'); + $outputMock = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); + $outputMock->expects($this->at(0)) + ->method('write') + ->with($this->equalTo("\x08"), $this->equalTo(false)); + $outputMock->expects($this->at(19)) + ->method('write') + ->with($this->equalTo("\x08"), $this->equalTo(false)); + $outputMock->expects($this->at(20)) + ->method('write') + ->with($this->equalTo('some information'), $this->equalTo(false)); + $outputMock->expects($this->at(21)) + ->method('write') + ->with($this->equalTo(' '), $this->equalTo(false)); + $outputMock->expects($this->at(24)) + ->method('write') + ->with($this->equalTo(' '), $this->equalTo(false)); + $outputMock->expects($this->at(25)) + ->method('write') + ->with($this->equalTo("\x08"), $this->equalTo(false)); + $outputMock->expects($this->at(28)) + ->method('write') + ->with($this->equalTo("\x08"), $this->equalTo(false)); + $outputMock->expects($this->at(29)) + ->method('write') + ->with($this->equalTo('')); + + $helperMock = $this->getMock('Symfony\Component\Console\Helper\HelperSet'); + + $consoleIO = new ConsoleIO($inputMock, $outputMock, $helperMock); + $consoleIO->overwrite('some information', true, 20); + } + + public function testAsk() + { + $inputMock = $this->getMock('Symfony\Component\Console\Input\InputInterface'); + $outputMock = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); + $dialogMock = $this->getMock('Symfony\Component\Console\Helper\DialogHelper'); + $helperMock = $this->getMock('Symfony\Component\Console\Helper\HelperSet'); + + $dialogMock->expects($this->once()) + ->method('ask') + ->with($this->isInstanceOf('Symfony\Component\Console\Output\OutputInterface'), + $this->equalTo('Why?'), + $this->equalTo('default')); + $helperMock->expects($this->once()) + ->method('get') + ->with($this->equalTo('dialog')) + ->will($this->returnValue($dialogMock)); + + $consoleIO = new ConsoleIO($inputMock, $outputMock, $helperMock); + $consoleIO->ask('Why?', 'default'); + } + + public function testAskConfirmation() + { + $inputMock = $this->getMock('Symfony\Component\Console\Input\InputInterface'); + $outputMock = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); + $dialogMock = $this->getMock('Symfony\Component\Console\Helper\DialogHelper'); + $helperMock = $this->getMock('Symfony\Component\Console\Helper\HelperSet'); + + $dialogMock->expects($this->once()) + ->method('askConfirmation') + ->with($this->isInstanceOf('Symfony\Component\Console\Output\OutputInterface'), + $this->equalTo('Why?'), + $this->equalTo('default')); + $helperMock->expects($this->once()) + ->method('get') + ->with($this->equalTo('dialog')) + ->will($this->returnValue($dialogMock)); + + $consoleIO = new ConsoleIO($inputMock, $outputMock, $helperMock); + $consoleIO->askConfirmation('Why?', 'default'); + } + + public function testAskAndValidate() + { + $inputMock = $this->getMock('Symfony\Component\Console\Input\InputInterface'); + $outputMock = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); + $dialogMock = $this->getMock('Symfony\Component\Console\Helper\DialogHelper'); + $helperMock = $this->getMock('Symfony\Component\Console\Helper\HelperSet'); + + $dialogMock->expects($this->once()) + ->method('askAndValidate') + ->with($this->isInstanceOf('Symfony\Component\Console\Output\OutputInterface'), + $this->equalTo('Why?'), + $this->equalTo('validator'), + $this->equalTo(10), + $this->equalTo('default')); + $helperMock->expects($this->once()) + ->method('get') + ->with($this->equalTo('dialog')) + ->will($this->returnValue($dialogMock)); + + $consoleIO = new ConsoleIO($inputMock, $outputMock, $helperMock); + $consoleIO->askAndValidate('Why?', 'validator', 10, 'default'); + } + + public function testSetAndGetAuthorization() + { + $inputMock = $this->getMock('Symfony\Component\Console\Input\InputInterface'); + $outputMock = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); + $helperMock = $this->getMock('Symfony\Component\Console\Helper\HelperSet'); + + $consoleIO = new ConsoleIO($inputMock, $outputMock, $helperMock); + $consoleIO->setAuthorization('repoName', 'l3l0', 'passwd'); + + $this->assertEquals( + array('username' => 'l3l0', 'password' => 'passwd'), + $consoleIO->getAuthorization('repoName') + ); + } + + public function testGetAuthorizationWhenDidNotSet() + { + $inputMock = $this->getMock('Symfony\Component\Console\Input\InputInterface'); + $outputMock = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); + $helperMock = $this->getMock('Symfony\Component\Console\Helper\HelperSet'); + + $consoleIO = new ConsoleIO($inputMock, $outputMock, $helperMock); + + $this->assertEquals( + array('username' => null, 'password' => null), + $consoleIO->getAuthorization('repoName') + ); + } + + public function testHasAuthorization() + { + $inputMock = $this->getMock('Symfony\Component\Console\Input\InputInterface'); + $outputMock = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); + $helperMock = $this->getMock('Symfony\Component\Console\Helper\HelperSet'); + + $consoleIO = new ConsoleIO($inputMock, $outputMock, $helperMock); + $consoleIO->setAuthorization('repoName', 'l3l0', 'passwd'); + + $this->assertTrue($consoleIO->hasAuthorization('repoName')); + $this->assertFalse($consoleIO->hasAuthorization('repoName2')); + } + + public function testGetLastUsername() + { + $inputMock = $this->getMock('Symfony\Component\Console\Input\InputInterface'); + $outputMock = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); + $helperMock = $this->getMock('Symfony\Component\Console\Helper\HelperSet'); + + $consoleIO = new ConsoleIO($inputMock, $outputMock, $helperMock); + $consoleIO->setAuthorization('repoName', 'l3l0', 'passwd'); + $consoleIO->setAuthorization('repoName2', 'l3l02', 'passwd2'); + + $this->assertEquals('l3l02', $consoleIO->getLastUsername()); + } + + public function testGetLastPassword() + { + $inputMock = $this->getMock('Symfony\Component\Console\Input\InputInterface'); + $outputMock = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); + $helperMock = $this->getMock('Symfony\Component\Console\Helper\HelperSet'); + + $consoleIO = new ConsoleIO($inputMock, $outputMock, $helperMock); + $consoleIO->setAuthorization('repoName', 'l3l0', 'passwd'); + $consoleIO->setAuthorization('repoName2', 'l3l02', 'passwd2'); + + $this->assertEquals('passwd2', $consoleIO->getLastPassword()); + } +} From 9488b0f85f6dc578f807fa3da1522190495e29fa Mon Sep 17 00:00:00 2001 From: Leszek Prabucki Date: Sun, 22 Jan 2012 22:11:10 +0100 Subject: [PATCH 02/42] Fixed code. Changes improved code testability --- src/Composer/DependencyResolver/Rule.php | 4 +++- src/Composer/Downloader/GitDownloader.php | 1 + src/Composer/Downloader/HgDownloader.php | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index d08c4a5ed..aab1dabab 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -29,6 +29,8 @@ class Rule public $next1; public $next2; + public $ruleHash; + public function __construct(array $literals, $reason, $reasonData) { // sort all packages ascending by id @@ -85,7 +87,7 @@ class Rule } for ($i = 0, $n = count($this->literals); $i < $n; $i++) { - if (!$this->literals[$i]->getId() === $rule->literals[$i]->getId()) { + if (!($this->literals[$i]->getId() === $rule->literals[$i]->getId())) { return false; } } diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index 170749674..2a51c1e9f 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -48,6 +48,7 @@ class GitDownloader extends VcsDownloader */ protected function enforceCleanDirectory($path) { + $output = array(); $this->process->execute(sprintf('cd %s && git status --porcelain', escapeshellarg($path)), $output); if (trim($output)) { throw new \RuntimeException('Source directory has uncommitted changes'); diff --git a/src/Composer/Downloader/HgDownloader.php b/src/Composer/Downloader/HgDownloader.php index 768280845..a9953db0d 100644 --- a/src/Composer/Downloader/HgDownloader.php +++ b/src/Composer/Downloader/HgDownloader.php @@ -48,6 +48,7 @@ class HgDownloader extends VcsDownloader */ protected function enforceCleanDirectory($path) { + $output = array(); $this->process->execute(sprintf('cd %s && hg st', escapeshellarg($path)), $output); if (trim($output)) { throw new \RuntimeException('Source directory has uncommitted changes'); From 19878c2dc10143de20391b805df26a1ca922168b Mon Sep 17 00:00:00 2001 From: Leszek Prabucki Date: Mon, 23 Jan 2012 08:40:34 +0100 Subject: [PATCH 03/42] Fixed tests after update and merge of changes from upstream/master --- .../Test/Downloader/GitDownloaderTest.php | 20 +++++++------- .../Test/Downloader/HgDownloaderTest.php | 26 +++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/tests/Composer/Test/Downloader/GitDownloaderTest.php b/tests/Composer/Test/Downloader/GitDownloaderTest.php index 57cbd945d..7d563d2e4 100644 --- a/tests/Composer/Test/Downloader/GitDownloaderTest.php +++ b/tests/Composer/Test/Downloader/GitDownloaderTest.php @@ -26,13 +26,13 @@ class GitDownloaderTest extends \PHPUnit_Framework_TestCase ->method('getSourceReference') ->will($this->returnValue(null)); - $downloader = new GitDownloader(); + $downloader = new GitDownloader($this->getMock('Composer\IO\IOInterface')); $downloader->download($packageMock, '/path'); } public function testDownload() { - $expectedGitCommand = 'git clone \'https://github.com/l3l0/composer\' composerPath && cd composerPath && git checkout \'ref\' && git reset --hard \'ref\''; + $expectedGitCommand = 'git clone \'https://github.com/l3l0/composer\' \'composerPath\' && cd \'composerPath\' && git checkout \'ref\' && git reset --hard \'ref\''; $packageMock = $this->getMock('Composer\Package\PackageInterface'); $packageMock->expects($this->any()) ->method('getSourceReference') @@ -45,7 +45,7 @@ class GitDownloaderTest extends \PHPUnit_Framework_TestCase ->method('execute') ->with($this->equalTo($expectedGitCommand)); - $downloader = new GitDownloader($processExecutor); + $downloader = new GitDownloader($this->getMock('Composer\IO\IOInterface'), $processExecutor); $downloader->download($packageMock, 'composerPath'); } @@ -60,14 +60,14 @@ class GitDownloaderTest extends \PHPUnit_Framework_TestCase ->method('getSourceReference') ->will($this->returnValue(null)); - $downloader = new GitDownloader(); + $downloader = new GitDownloader($this->getMock('Composer\IO\IOInterface')); $downloader->update($initialPackageMock, $sourcePackageMock, '/path'); } public function testUpdate() { - $expectedGitUpdateCommand = 'cd composerPath && git fetch && git checkout ref && git reset --hard ref'; - $expectedGitResetCommand = 'cd composerPath && git status --porcelain'; + $expectedGitUpdateCommand = 'cd \'composerPath\' && git fetch && git checkout \'ref\' && git reset --hard \'ref\''; + $expectedGitResetCommand = 'cd \'composerPath\' && git status --porcelain'; $packageMock = $this->getMock('Composer\Package\PackageInterface'); $packageMock->expects($this->any()) @@ -84,13 +84,13 @@ class GitDownloaderTest extends \PHPUnit_Framework_TestCase ->method('execute') ->with($this->equalTo($expectedGitUpdateCommand)); - $downloader = new GitDownloader($processExecutor); + $downloader = new GitDownloader($this->getMock('Composer\IO\IOInterface'), $processExecutor); $downloader->update($packageMock, $packageMock, 'composerPath'); } public function testRemove() { - $expectedGitResetCommand = 'cd composerPath && git status --porcelain'; + $expectedGitResetCommand = 'cd \'composerPath\' && git status --porcelain'; $packageMock = $this->getMock('Composer\Package\PackageInterface'); $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); @@ -98,13 +98,13 @@ class GitDownloaderTest extends \PHPUnit_Framework_TestCase ->method('execute') ->with($this->equalTo($expectedGitResetCommand)); - $downloader = new GitDownloader($processExecutor); + $downloader = new GitDownloader($this->getMock('Composer\IO\IOInterface'), $processExecutor); $downloader->remove($packageMock, 'composerPath'); } public function testGetInstallationSource() { - $downloader = new GitDownloader(); + $downloader = new GitDownloader($this->getMock('Composer\IO\IOInterface')); $this->assertEquals('source', $downloader->getInstallationSource()); } diff --git a/tests/Composer/Test/Downloader/HgDownloaderTest.php b/tests/Composer/Test/Downloader/HgDownloaderTest.php index d6752eb4a..81429194d 100644 --- a/tests/Composer/Test/Downloader/HgDownloaderTest.php +++ b/tests/Composer/Test/Downloader/HgDownloaderTest.php @@ -26,13 +26,13 @@ class HgDownloaderTest extends \PHPUnit_Framework_TestCase ->method('getSourceReference') ->will($this->returnValue(null)); - $downloader = new HgDownloader(); + $downloader = new HgDownloader($this->getMock('Composer\IO\IOInterface')); $downloader->download($packageMock, '/path'); } public function testDownload() { - $expectedGitCommand = '(hg clone \'https://mercurial.dev/l3l0/composer\' composerPath 2> /dev/null) && cd composerPath && hg up \'ref\''; + $expectedGitCommand = 'hg clone \'https://mercurial.dev/l3l0/composer\' \'composerPath\' && cd \'composerPath\' && hg up \'ref\''; $packageMock = $this->getMock('Composer\Package\PackageInterface'); $packageMock->expects($this->any()) ->method('getSourceReference') @@ -45,7 +45,7 @@ class HgDownloaderTest extends \PHPUnit_Framework_TestCase ->method('execute') ->with($this->equalTo($expectedGitCommand)); - $downloader = new HgDownloader($processExecutor); + $downloader = new HgDownloader($this->getMock('Composer\IO\IOInterface'), $processExecutor); $downloader->download($packageMock, 'composerPath'); } @@ -60,14 +60,14 @@ class HgDownloaderTest extends \PHPUnit_Framework_TestCase ->method('getSourceReference') ->will($this->returnValue(null)); - $downloader = new HgDownloader(); + $downloader = new HgDownloader($this->getMock('Composer\IO\IOInterface')); $downloader->update($initialPackageMock, $sourcePackageMock, '/path'); } public function testUpdate() { - $expectedGitUpdateCommand = 'cd composerPath && hg pull && hg up \'ref\''; - $expectedGitResetCommand = 'cd composerPath && hg st'; + $expectedUpdateCommand = 'cd \'composerPath\' && hg pull && hg up \'ref\''; + $expectedResetCommand = 'cd \'composerPath\' && hg st'; $packageMock = $this->getMock('Composer\Package\PackageInterface'); $packageMock->expects($this->any()) @@ -79,32 +79,32 @@ class HgDownloaderTest extends \PHPUnit_Framework_TestCase $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); $processExecutor->expects($this->at(0)) ->method('execute') - ->with($this->equalTo($expectedGitResetCommand)); + ->with($this->equalTo($expectedResetCommand)); $processExecutor->expects($this->at(1)) ->method('execute') - ->with($this->equalTo($expectedGitUpdateCommand)); + ->with($this->equalTo($expectedUpdateCommand)); - $downloader = new HgDownloader($processExecutor); + $downloader = new HgDownloader($this->getMock('Composer\IO\IOInterface'), $processExecutor); $downloader->update($packageMock, $packageMock, 'composerPath'); } public function testRemove() { - $expectedGitResetCommand = 'cd composerPath && hg st'; + $expectedResetCommand = 'cd \'composerPath\' && hg st'; $packageMock = $this->getMock('Composer\Package\PackageInterface'); $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); $processExecutor->expects($this->any()) ->method('execute') - ->with($this->equalTo($expectedGitResetCommand)); + ->with($this->equalTo($expectedResetCommand)); - $downloader = new HgDownloader($processExecutor); + $downloader = new HgDownloader($this->getMock('Composer\IO\IOInterface'), $processExecutor); $downloader->remove($packageMock, 'composerPath'); } public function testGetInstallationSource() { - $downloader = new HgDownloader(); + $downloader = new HgDownloader($this->getMock('Composer\IO\IOInterface')); $this->assertEquals('source', $downloader->getInstallationSource()); } From 3f38eede8ab1b9a19c0e87038593651f0fcd80c6 Mon Sep 17 00:00:00 2001 From: Leszek Prabucki Date: Mon, 23 Jan 2012 08:41:59 +0100 Subject: [PATCH 04/42] Made changes which fied warnings and errors in tests. --- src/Composer/Downloader/GitDownloader.php | 1 - src/Composer/Downloader/HgDownloader.php | 1 - src/Composer/Downloader/VcsDownloader.php | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index 2a51c1e9f..170749674 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -48,7 +48,6 @@ class GitDownloader extends VcsDownloader */ protected function enforceCleanDirectory($path) { - $output = array(); $this->process->execute(sprintf('cd %s && git status --porcelain', escapeshellarg($path)), $output); if (trim($output)) { throw new \RuntimeException('Source directory has uncommitted changes'); diff --git a/src/Composer/Downloader/HgDownloader.php b/src/Composer/Downloader/HgDownloader.php index a9953db0d..768280845 100644 --- a/src/Composer/Downloader/HgDownloader.php +++ b/src/Composer/Downloader/HgDownloader.php @@ -48,7 +48,6 @@ class HgDownloader extends VcsDownloader */ protected function enforceCleanDirectory($path) { - $output = array(); $this->process->execute(sprintf('cd %s && hg st', escapeshellarg($path)), $output); if (trim($output)) { throw new \RuntimeException('Source directory has uncommitted changes'); diff --git a/src/Composer/Downloader/VcsDownloader.php b/src/Composer/Downloader/VcsDownloader.php index 8af2ce48e..c24411310 100644 --- a/src/Composer/Downloader/VcsDownloader.php +++ b/src/Composer/Downloader/VcsDownloader.php @@ -100,4 +100,4 @@ abstract class VcsDownloader implements DownloaderInterface * @throws \RuntimeException if the directory is not clean */ abstract protected function enforceCleanDirectory($path); -} \ No newline at end of file +} From f59ca1e2f8ad847a6392db802ff95f2e7aff4e92 Mon Sep 17 00:00:00 2001 From: Leszek Prabucki Date: Mon, 23 Jan 2012 09:21:36 +0100 Subject: [PATCH 05/42] Made fixes after review. --- src/Composer/DependencyResolver/Rule.php | 2 +- .../Test/DependencyResolver/RuleSetIteratorTest.php | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index aab1dabab..8af24094e 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -87,7 +87,7 @@ class Rule } for ($i = 0, $n = count($this->literals); $i < $n; $i++) { - if (!($this->literals[$i]->getId() === $rule->literals[$i]->getId())) { + if ($this->literals[$i]->getId() !== $rule->literals[$i]->getId()) { return false; } } diff --git a/tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php b/tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php index d45f9a561..6340a7f68 100644 --- a/tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php +++ b/tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php @@ -39,8 +39,7 @@ class ResultSetIteratorTest extends \PHPUnit_Framework_TestCase $ruleSetIterator = new RuleSetIterator($this->rules); $result = array(); - foreach ($ruleSetIterator as $rule) - { + foreach ($ruleSetIterator as $rule) { $result[] = $rule; } @@ -58,8 +57,7 @@ class ResultSetIteratorTest extends \PHPUnit_Framework_TestCase $ruleSetIterator = new RuleSetIterator($this->rules); $result = array(); - foreach ($ruleSetIterator as $key => $rule) - { + foreach ($ruleSetIterator as $key => $rule) { $result[] = $key; } From 9ede082371fd24cb52783aa2bcfaedf9750f4120 Mon Sep 17 00:00:00 2001 From: Volker Dusch Date: Sat, 18 Feb 2012 11:36:11 +0100 Subject: [PATCH 06/42] Skip tests if mbstring is not installed --- tests/Composer/Test/Json/JsonFileTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/Composer/Test/Json/JsonFileTest.php b/tests/Composer/Test/Json/JsonFileTest.php index 00711bb11..fc205eceb 100644 --- a/tests/Composer/Test/Json/JsonFileTest.php +++ b/tests/Composer/Test/Json/JsonFileTest.php @@ -133,6 +133,9 @@ class JsonFileTest extends \PHPUnit_Framework_TestCase public function testUnicode() { + if (!function_exists('mb_convert_encoding')) { + $this->markTestSkipped('Test requires the mbstring extension'); + } $data = array("Žluťoučký \" kůň" => "úpěl ďábelské ódy za €"); $json = '{ "Žluťoučký \" kůň": "úpěl ďábelské ódy za €" @@ -143,6 +146,9 @@ class JsonFileTest extends \PHPUnit_Framework_TestCase public function testEscapedSlashes() { + if (!function_exists('mb_convert_encoding')) { + $this->markTestSkipped('Test requires the mbstring extension'); + } $data = "\\/fooƌ"; $this->assertJsonFormat('"\\\\\\/fooƌ"', $data, JSON_UNESCAPED_UNICODE); From f152fe723d557fc9a5210f0bfd6ead8d32b0e0a8 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 18 Feb 2012 12:00:30 +0100 Subject: [PATCH 07/42] Allow local file system git repos & do not restrict to valid http* urls --- src/Composer/Repository/Vcs/GitDriver.php | 9 +++++++++ src/Composer/Repository/VcsRepository.php | 4 ---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index 286cf762a..f3923e4f5 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -169,6 +169,15 @@ class GitDriver extends VcsDriver implements VcsDriverInterface return true; } + // local filesystem + if (preg_match('{^(file://|/|[a-z]:[\\\\/])}', $url)) { + $process = new ProcessExecutor(); + $process->execute(sprintf('cd %s && git log -1 --format=%%at', escapeshellarg($url)), $output); + if (is_numeric(trim($output))) { + return true; + } + } + if (!$deep) { return false; } diff --git a/src/Composer/Repository/VcsRepository.php b/src/Composer/Repository/VcsRepository.php index 1d6e82ab3..a2506d2df 100644 --- a/src/Composer/Repository/VcsRepository.php +++ b/src/Composer/Repository/VcsRepository.php @@ -19,10 +19,6 @@ class VcsRepository extends ArrayRepository public function __construct(array $config, IOInterface $io, array $drivers = null) { - if (!filter_var($config['url'], FILTER_VALIDATE_URL)) { - throw new \UnexpectedValueException('Invalid url given for VCS repository: '.$config['url']); - } - $this->drivers = $drivers ?: array( 'Composer\Repository\Vcs\GitHubDriver', 'Composer\Repository\Vcs\GitBitbucketDriver', From fa8cb14073cb9491b8e8f65a1e9f6f72953fba5b Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 18 Feb 2012 12:12:02 +0100 Subject: [PATCH 08/42] Simplify check --- src/Composer/Repository/Vcs/GitDriver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index f3923e4f5..daab73dfe 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -172,8 +172,8 @@ class GitDriver extends VcsDriver implements VcsDriverInterface // local filesystem if (preg_match('{^(file://|/|[a-z]:[\\\\/])}', $url)) { $process = new ProcessExecutor(); - $process->execute(sprintf('cd %s && git log -1 --format=%%at', escapeshellarg($url)), $output); - if (is_numeric(trim($output))) { + // check whether there is a git repo in that path + if ($process->execute(sprintf('cd %s && git show', escapeshellarg($url)), $output) === 0) { return true; } } From 3b54316e91915ccd063ca359d1b6faa9a4ce266d Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sat, 18 Feb 2012 12:33:55 +0100 Subject: [PATCH 09/42] Add a test for the off by one error in solver conflict resolution --- .../Test/DependencyResolver/SolverTest.php | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index 7496834e6..57f835c88 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -414,6 +414,42 @@ class SolverTest extends TestCase )); } + /** + * If a replacer D replaces B and C with C not otherwise available, + * D must be installed instead of the original B. + */ + public function testUseReplacerIfNecessary() + { + $this->repo->addPackage($packageA = $this->getPackage('A', '1.0')); + $this->repo->addPackage($packageB = $this->getPackage('B', '1.0')); + $this->repo->addPackage($packageD = $this->getPackage('D', '1.0')); + $this->repo->addPackage($packageD2 = $this->getPackage('D', '1.1')); + + $packageA->setRequires(array( + new Link('A', 'B', new VersionConstraint('>=', '1.0'), 'requires'), + new Link('A', 'C', new VersionConstraint('>=', '1.0'), 'requires'), + )); + + $packageD->setReplaces(array( + new Link('D', 'B', new VersionConstraint('>=', '1.0'), 'replaces'), + new Link('D', 'C', new VersionConstraint('>=', '1.0'), 'replaces'), + )); + + $packageD2->setReplaces(array( + new Link('D', 'B', new VersionConstraint('>=', '1.0'), 'replaces'), + new Link('D', 'C', new VersionConstraint('>=', '1.0'), 'replaces'), + )); + + $this->reposComplete(); + + $this->request->install('A'); + + $this->checkSolverResult(array( + array('job' => 'install', 'package' => $packageD2), + array('job' => 'install', 'package' => $packageA), + )); + } + protected function reposComplete() { $this->pool->addRepository($this->repoInstalled); From 460822fb96c8bbe624bb8d336731a2b0e8093d22 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sat, 18 Feb 2012 12:37:45 +0100 Subject: [PATCH 10/42] Fix indentation of doc comment --- tests/Composer/Test/DependencyResolver/SolverTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index 57f835c88..85ef6fc70 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -415,9 +415,9 @@ class SolverTest extends TestCase } /** - * If a replacer D replaces B and C with C not otherwise available, - * D must be installed instead of the original B. - */ + * If a replacer D replaces B and C with C not otherwise available, + * D must be installed instead of the original B. + */ public function testUseReplacerIfNecessary() { $this->repo->addPackage($packageA = $this->getPackage('A', '1.0')); From fb69ef64c5311ca4a3a59a0bfe4e82f4d7f50e67 Mon Sep 17 00:00:00 2001 From: Volker Dusch Date: Sat, 18 Feb 2012 12:44:52 +0100 Subject: [PATCH 11/42] Fix Solver function visibility to reflect what acutally should be the public interface --- src/Composer/DependencyResolver/.Solver.php.swp | Bin 0 -> 94208 bytes src/Composer/DependencyResolver/Solver.php | 16 ++++++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) create mode 100644 src/Composer/DependencyResolver/.Solver.php.swp diff --git a/src/Composer/DependencyResolver/.Solver.php.swp b/src/Composer/DependencyResolver/.Solver.php.swp new file mode 100644 index 0000000000000000000000000000000000000000..91ad3e7d858fd419561b0834bbd41e8b882fc820 GIT binary patch literal 94208 zcmeIb34EMab@x935+H#F64thq$BwWi+p=S4qfX*Pw&lc$Y&nvh5F8`M(#W1zno(vX zFIj+ugs?;5g|b5lZ3s&sKq-6KTh^8xQr0dBP}TrphyV9?m*=_9Hj)?mFYl}Q_~#it z&t1y3g~Pawe+qs_^wX1mr}(Qb{dSm*y(Uz@5m#%hhx14FfTb7C*=ht1dW zsohfrNzFf+r@%Y~4u%3V)8oC5zJKMERVz3p`+j-m{rxlVf0=pzC+_{E``+d%TuVKbU!sYQ}u_x$h;8 z;6DBX-SZju{WqESC%ETVyYGj%2KDhzbkA$<`+1r74|319y6>N7-aptque$FGU4#4d zAL5>SzIj9Dy(3q}C0lujV+bGLMW6qgr@%Y~<|!~wfq4qdQ(&F~^Awn;z&r)!DKJlg zL!>};tWtRdala-(3nA0X|Gz>Y{Ux{?d>(uT{4KZ=>;ucdFA!>f3Vs4U2|fW{0rr6b za3MGkJQSP=jsf=qw<9dS3%nFO0X!D01os1XAZUL8yad$2T5tmR83OuG!Pme)gImFi zz!ShV;8Jipcrf@e!u}_~E#O*E1LuSDz{A0JQ5Jj$To0ZAc7Sui!@Z%umJoRVfee?)!?PzVsJE&&Y}Sx0n}b!olQ87^jTv5pY6Y0&00I!SD)S;P4BKn zty;C+Y*b97CDFN4)mC*fnyl}yjfLrS*N48N8`;_w5!&rwW`zg#x7E+x1-j~M9nAV%2sborxS8zGY|Ws zp=|^GBTJ&uW}`h_CFoeKJ=&`8v?*rOs-(bTisnbIFdmM0{Es$KzmqE0t#u zG$LZ(st8i`onqS$3Pn(=yKm*yeXFkSJEdoNCb@Ocml9W_Ms1%VsG+o}k*HGjnVD!S zmMp25AJ^Daq6iL|o@q5q>>)Di?wY7myXr)HS>#9`{}6xloM{svW|SnNzv777cSL8K z^agB7-Ca|y=HB{Ptp)S6W@;p%@cxrdMNfT^W+o=mLF?mDl2~;1*=NTM&=Xx%@d@gC z#fqq1n;4JAXC}t$6BD9@nC+Z65bRj1j_wZ9Ye&^K>A9jR!8mYSH7aJ9rdz~Ls%P0^ zSu_sWYCW!gwm_seT^pUIzm3l{MyKn|Ml@<#Y^Zj{OubbzG%w|=WsXPVVwJRt2oAM+ zY>AhwaNp6nj+DwJD*1?SUB{%9qLTPe$wkn6x;iu6oM`Tl@4yI85n}#CKXbeVXNB?k7rib$a%JjnvYT}f>(X@6yGG30c7u;tez-QB3?ME{T{FkT1gy^J z5&w}3Hq~rSD1^QXUQX0U57^iGWdmGgYBn{qlSfH!9~m)|RcmH+x_e7gp~LCJJXjWO zQEn!$WzkR#v&#B(vlRx63)*8xrDRy~Q_$At1}1_TJEBlDJ5IT=s3`b0GZ&hXAqZ{j z5D!`jg*H{EY&C@|V4k8}g+Pt8-Gt4JTHCvcIKYsumRJtp35ekEyTpDbs|DtUhhfE>= zvNX`SpM+M0@4AM!3t8pYf;&TWex( zGYfSrh1lO#kQJV08x|b2YpUYBoZ23;8OVIAop1HMzP1(%6rh-(0`F~o|uWy^>G*_i^ z);Th*m;C=oWcgtr`5*Dsd_Kb8`#}S22it(c41xL2JO$<{Fi(Mb3d~bro&xg}n5V!z z1?DL*Pl0&~%u`^V0u{S6mF!Q|Mt3)(g_kuJT78d%{^X_pG65Fr*Wze-ydlQV#rA>K zQhTlGMKiUT+9kUWZ11Y?Se{Nc*_|qgV)m)((b;R_9JE;_`Tram?Ks)PBmYmh2K)!) z`~yHbfV04v;Ct-d|2Mc5Tmc>fP6u7!C+ywd1wH~^4_*#l1}+2J!789V{_n7te=9f% zyo#rOe~PYH7F|(yPlmLaxuoU( zl3ssuSv1+G?Q&1dw#yP#DK4+ox0Byh%2f5LwMN($2uRhfI@DT}o^L~dz0LZV-Iuwl zB7!HX`gqfqB-WY2s!Z+f9veIvK9XNb04;2^b#VQlFF>nSYlv!A@o!qETe&Zbdb{^V zOQV%+IvZuEBD;^;-`<5+jkj&y2fLtmMg09y}C)w+Aw*N;RbHt$xi-g@bl z{t-0d1^fGKZH%L;on989>qRGvew2UJXkV?m$8KXYLb}?|R$tP>DrF{9S5vz50Nfr% zAKV^4keEqqKY2$_%2+@|$y2mA2ZeR*1cR)1+i7v)%V^j%!GZ|6X+&lh1ua$<#h7V$ z%Z79=1r?|BZ1;gpV|g9F8dXhpa*hZ-xQgYCN}yIctN4vCyh+@dR?tsoWz}NBnz72U zUcG$@ECFL(eRZ@Te%9B~*_gY7%|YLG{FU+GJyOdzWu$N0b8UM{fH}DfrI}TNu;bne@yMxq;DS`)G5fQT)1R zM*+{7-P@6==2T&dEMf}cWD5=fIwzA!W8ZG=>vVT0X~Yu9Q)hUZ&5^LlL@U)tJz*N#MG()|{)pnYo{%KFt8?D@7dm2M(n)Q`Ro&!wUZun&{4<6NESP-*p zAPy7A4aP}|hK&k_WJNdqKNB<_oJ&UMiXw)e;;I#QSH&Y!tg+lck!A8|fsDP9B9-)o zR7doM$w$*zlS`|e8=I6sLAZ46&f}GmI0Qm;2idaPYA1t|9mJBt>uq0VC`-S!gI~61 z6b@*XCuIJI`N@W6tJ@lF$2+1{+VG`3i&_)z*LOL*9+@Raw7!yA&4 zO1M>DSP%U!=1jkmQ_+vqxTCaY9dY77@mQ1LGq(_|g!M3ERoo(r7GVuh* z*i3RGh9f!K{jElAOcH__zAZDD*&KUVpHOyr;@9n~kxm+8%w9gAWtH}U_B3+^3wJHa z&&jRW<9!I39Gxx{q__*dqT627q47(|b#%HSUxie%K%m2<7+t|V9 z%WZ~gXgs~4zQ3pmnOcMPkS!Net8b~DHI)*D2m*dolWEo{CR)xm+82dy5{XU0suK`> z>_Ea1m?_tyJ&mSpxG)!E-mU~u%}*a+7R)}rWtQd2oH~$%hGmu)W@%zLtT-8pJIz|E zw(CG-tfSFSaKJ;AqNOlX(*h^1alO{gb6l=_CcRpks@^sGsK*w|=50+5jXid9tG3X% zbYqvDJX@zjGc7#2@;oDI1q@)%GMGgCsDy;96`bktXns<4%`<&@cb?IwUrtvyDk(Yt1ha}4aKNMjVak5eEl2!qwz{gYGE2ds7{ z4jG21HEcpYpCG{`7@6w`&}G9@6DEI~=~X5{W}WPjA2(mOH#A#YETeS0@7U}$VIkWV z2`!Ufs+VgU&G4LfAmQ#VN}?Vj)I~7xp_@JJ)3M@7Bye~3pls&k4rc?ML=2IQ`!gYDs-cqhTAnSCG9Rs$TNkj;9L%~ahS8F zZf&aX;;ArYAJd4Pj>fujsa|tC5u2QKtC&nX9@agGbFi);Ce7K7ztXXF+E>dtR|sF0 zxZ`Mt#M4SlpcT!uIfUA%X-^AnN!#pj)DzbCiD;-|rQU3yZ8_jhF~%%ckK0u&EfLpp z`<%Hdb)u3fZAQmM?SaZ=Wv5BqdCQm$;~$+*surFvHDj60*PSd4PJ$Zp^B;@D`mTmq zhw5}GL!?mz84At9_^iH6*deife(?7-&cE?OOkBD6hv80t@>Bc&8<99aBDs_OfA8P# zjmY^r?|&Lt0e+5Le>eCvcoBFucorB2n}E*yuLlnV$AV8F_kS2%1GMk2bNw#>+rUG? z@jz$zUkh4b0_*{!AOa5upF+NWCb$8d3+_UWe>bRuv%tN=fS7I6TvCqPUQQSfeV55=|2UXMe7e6IiGxw#K-ViFbN*g@m<4>?of(J zu)}|UfD^h?c7gLp=PkhXyo6Zsp=%y#0QD6ctS0>!UQJY` zP%)E!Cbfz}lcXi zre?NqE<5)XCFgU^nnD>&?`sxjVxk<{Nbkz&hk6ODhrG5JGDl8J2G}^GqVx}8$wAB5 zkD4HTe!gN}bX)(h5A`-E}PQwC&b&5S;ob|4e>Jag{am(@W ze~J5yco{>|Hr*(WTT%9NU~cpyN8WLUB}vY22A$D+udpGgfSgy@KVor;g2$zT#q%3l zY1z=tHckwj^LjlHkhO?13vt|ZxPrw3<1Fi=jaIok*r*MTn=Wih8`tT`Ilefg{yHtG z@BaaT!B1e8_^^*}Mp#LNL)k20G=55d!7`3(prY|sbFxAxCM@@r3(TZrr8Gp4KwdD@ z3-97VG(Wp(^0JO5>_%GOve?taSbcmP&l3pzzEI1fjn;+6uKM0uR!q*!YLwq8@*?!X zI^!#)tP!}Y+47re&0!!&Niwcbt_QoWGPkZUKatrXGj1%#l$ET7oy!g`eH7(^_cr6v<#OBK2@tjh+ShJZ&+1;`@ zV%|lRHJj)#(b)iYp0mF-&BYnTNyqctVRyrAv4fNXc|GpeZklq%E2hYiU0xQsXF6c^ z{}JyiBToL`z`qzP5fMovPAlLsIycde_9eALyi;lX#yR3zm02LQw50lK2nIxOg5vf+az0n)5 zc(2-Bz;Y@_!$Z^7%}i>N_t-`rP!LbV*O)Eso)w7#e8KD`7ES#%rwk*_xUl#4poO?I;ECK2E=fr!nfH3KFm64SIi#Jy{dy6>c|Q z_2v^y(#FweFpfF(VbncQ--GMv+CFxtTT_z}yVPlHLY1u(CiLMl3Nt})=jU#J78E5(jl+uj%UOKM!|087nF63D4|NHy*LiztDWd4_fmx2ESH?0*Zm8e9d2!AaoZ;6!i&I2QZ|`hc&3XMpuUX8}$F_XNL1 zH}E0wO7IMDEqD^p*#OxF91s2kd>K7~{QSQbv_T&@1Dp;j;4|nAbS~iI;Dg{9;K^VJ z41k4T0k|DK!h69j;FaJN;0AC#cq}*pJP>>bJ%juS$p8O!U_WSqD}ZbXmVh6kb9e{1 z9_$4ZKxYUp23x=&SPFiL{^2L!?cnc$&J;WWtN=ep4{G#k4?)In6e?~?cmDG5 z4rsgN4(EJ!#W$mA9u-f;v`nDCoKx_%2Usnc?95T@V4Wj@D|kcflh3sEG$Et2V9Ma6 zv`G_R3rSi_m!{~NK95Xtspy_BjmLFo0*QHE!n18jpBTP$cx(SAJT+fzybYUO zs=c*|Xr;Z&z;7jGjBY2Zduo0DSm+Rh@C-|fnM}#Bx`!<;8S1r06kJvF<#WA&=(%Q!k8K>1|+%1`J=y7nfNS^+(>oT9H1D~ANo zia#C25X>Z{qwq-%DV8+p+CbO<>_pZ{50V{SI|Laf3o&o$;8f4X>>-t9P!!Xn5=KuG z#xh7!CtDw9M?v2^MX9R%`q(u-8WyeIfzgPp;uw5Qmn2{yuoKOTd9$-7EsOOmKZgC& zfqm5jNfA6vdFtSPhSA%5 z>Qi>p7hd<{c;@O2_JTEeVbo-5Tf(rMVz|U!v9Pr{1P^xLSW7fK523_#Eog0qjLfIA zAcl+0AvWt)Lq;EFL)us)xslr^vl$j#xndQEBI%-DfxdxG|e8Bb&nLg^&NxwBr6 zW9n)6Rb=$)bw=g5U71#3EghBcLdo_3_*agl3lJ{Q-9t*VZ|8-<|?fX9& zYzF<{QQ%w1?{5HYa4A>=9tDm9zd&aHPw+3`jo^hqvi)O#Wc#JyLEzrteaP=`1hNa* z54M1XKxhBokIa5E*bdf$$?z9}v%sH%Um>6W2lyg*H_+LD32+JM z1rhiKviY6h-Qa0p3fvd`2)X=K;6~5{j{_UQDPR$J0JtZ3FS7Ydz_nl#I2D`#?m{k? zZ-7q&`2>72kbi(GI1@Y!JQ#c)nf&=+Jy-_r1MZ@I)J9)XJI(3Cy2pMt^=%pM-`c$h zCw5Z|B=K`AflsjnJlXlcrx=m~E|HEvoyHA=@l0krp6gj! z)JX@yh|V@wy^$oaVhK6!b9-0HDHYG1j*IoaJ{PXXhzk+xHlU12%@;N-r(^id{+tMKMX6GyHy^fxC3tqg=Mf;s(vR zaka_iVf@V{G^4w_?W7O2+pDr9n>8cnw=>Mi?EwaPnQTTl2-tFY*}Zu0ucnQoNjd2h zA#)TdX>MQ9_9|{?!+j-wyjTbpxe&EfwEwpyxfErd8uS!4)6N?6`~^<58_eYk9JXL4 zk~=2eO})r=313rE>QK^fI8|<@TpX59u?Vh9iGrh2MI-^KoTw>|1jdYQ;F!*kF4bcK z*lWyEDFmevON8N4RL<~g3BeC{94JZFGAsLE2j)5kbV%rbw*MD&;S4Dcs_XubbX#TO zUG2JUN6$POB*Lx>zv#Lwv8y_ney7-`Lp#j9Q_ihJ2Ao{n5nWk>^5uFIgTJ#-kqv*c zNY^yFaOXr*_B0ElogBRnrcggUbeKg;N65|{Ca99ygbJ8ZjBSlhqgVmWO^dqdVf~8- zy3_zslG+sdv1EV>3ObjCUux+Rj%bz~ZcTVaJzONDUxjZN51k?zeOUvO0n`k3eK6d& zm5cP&Zaa?~?}oPxY}N8Ju3TI(hF03$=<{SErK1?md6CyRge@ylwtCmF-erW=8m(J@ z;=S7a>Hp|m*`s-sKliONvW`lut}}s;?sO)p0@?0q@~qxNeAVz#lX9RDF#$6tWT=UKCsH{ zicGx!U&_tRdezqG?zxvej8Ia37|2N?5FHl=djrK;gq&jzC^2T3oXwe72;u|}&s`FS z@Cz~>FHOx#r6FR=9Z=ghVi1lcMoA#sU2JkmM@l{Q>Dkr{T#S#jYU66r>hy??={84A zcY;|1zGEF&zp~aG@7_2jD*W6_CtH3QdH-L)Z9x0}^8ddG{4;^y3SI%U z=PzBr2H@`j_yzL+KY_mkx&uIG0rrC?xB%P>{0cq5o#5->m0%x`jzB&DzXSdi=uUt- zcnG*3xF`4la=-TbKLXwaF<=q!)M*_-il)q#rmBEC4!V@MG`|@OAJp@GQ^(+T$Mpr-0w03-}^< zE4Uf#1%u!Wa3}hJe*rpoFaa(G3&8`yH_!om4txx}2D}990UN-n;JfGpz6_oNt^sv$ z2GD-~PiaTB<#%#=0#Nvnx0V@Uv9)r|nSe&ewA3*GggPTsTe{Qq*~Uh#kE+Yeh! z_**e>UL1>Hy=#od7e-5BXe5)*8n^Soi+DuOhB_oUXG(I0&#o-#IWCi?!gZ2gCe4<% zB6+DLrbJSt$Xv9lk%3zZBs&y~EIt>jf3=F4ypZC`m!uvxZ}?lu9c*Lgn)=`y+X<|x z=C(B}YMH|kZ&S@aTNZ~X*dnj7pbpq;wtQw~g@a@Uzrm<{ixeK>xa}Uen37yExX;)%4YAPs&OB?_w40%5!o&iK={wF|F~$ zB~y@!rO_33yX)-e3NB5NJ&1q7szYi`xs^^-oBr6zl4yl5xJ}0YpY6{6IZA$KVs(*x z*#(Y=7t2l8V)-atY?WS%mqm+Rj^?pHCX*VVlXOMS)DCUj5}S0fgG*`7mYCFcyU)J8 zc!#kAaA|}anaY1u*CsD^*)3jO@nvdrH}mLjY;R0jqmyHcclfBbRS|NtZuAJcwYlCJ zp&1HU2j!8{;P^$Wg-f;+1$!zi?M@o2v7uIrr^NN!wnV4oo^IT{p>Js2`O&J}8+XHY zw35bLvP6xlFZ-KA>+ET|MjMMJ@U+%KkYQo%Zfr4n@p@yg>}+6Oqek`W?p-Ll*{)QY zk*k$el82#;zLOy~@Hj3v=hV1u4!T$MGc3`TB(^IUo2n~Zd5o>IO3${`5&2jKHwqP} zRmm@AORpBv@Gwrv?0Va;hJ&a6k)7{s(Ck{;J@rAIa`q%Lt&b-nnM#GB)9mu8Exr*= zq_s0LqP-7^;Y!!B#L7RD)_C{AOZxjRjMkk$$c^C9!Z5%g=82#grsA_199Zv@KZ)*q za#9dm$c*@~JzI2&p9?5Ei%{?lR~FriY;fJDBXY2)%qAHYQ}66mNeb-5e@VXF;uMCH zH0}0OIFhIp(}-!^>86Hhui0`6=tWobM5{FnJE8}QyJXeDyCc-vC6t#j#*{1*-2Rqp z3HU1|=;t>(%zPW9rUK;kq6)PjR^K8cgc|{6dZ(Fi$1#)<;+|xZoiS<>-_pvT zVJ@qsu^i|wSMZ&*J42;jw-Ar#xI}pAoaGRl8!ai#*3P_#lWTeH(^ZHYB48`iz8Evg zK((G~+q&9T@;~Bofqee&1-cJ#3)lc24P+Pa6Xf}ifaifHfxTb~$dAB!unIg9`~|ot_&74Y z?g@MpI3D~KS^m4=n?N%E2Y_q?-UV(1*8cE88$R;Co#~KUt87c0Tlf`IyrN?z=GV7AvR}u!#b>gNQ-F9W z=hEJ8SF7=QPGR6)=dp_QvRS*CMWc(Mm0v}{^hvLdWjAEQ$7WLbWuRRE#z855#U$na z>zcr?&jqZ}NrK3kx9R*8C7D~oR5VH{I-@Y@xFl00S7;l;8)|8=D7go(5~h7nWl*B& zTY>z_SxF|8Hg>e!uS= zzO}i*UKgYy6i7yer(nbyDe=k)L$f88wuntLLAF>)k3IZSbxg|?N)*?J2~*aH-qd1I ze3_D%#j4S*JXTTY*%~*=H}+l8<0S~i*T)|kaQtBUe!y{QB9)AH=|DE!?7-rm>e~;2 zCbR#G#BS@$5UINo)^--6Ig@4A?Yv09u3kfq#HC!m+|3UOnUh};3(uuzN8IC@WQo=! zS+i<&s>N>j&@5R~he1%ROz)m)M|)~DYg?99Xfql(i&K*ep|MDFoh}{-uo13vA|PWg zmWpZ_)~?wXOnD_y$SOHvnZ9m~po+q)JkCanO2!%_^O#Wrr8KHv|HaxMPkiBp`p@ed7+F7f$>#Hh`quYri?UlgYl|WsLh2tv$+ors z;(VdvwA|2~Hx#MMc4?W{h*^i!kR*E|JjAGKBsTMh?I>8^=d{}8Bb&YYJ*4PLD@Eb#=#A-68W2MOO!%!Ke+x2afZM zFQ!9@S5c8N#lw5SZgV(-VUCd)F*P0lRZ6d*Hp8kjST)HgsYIb>wA`LC6i*M9YaiJX z+YjT?e=l9?1IC&FC1!h@*Ml34gxwjen3w$L6VcySNRK^IGOJovdp z(NJ2f8yNC>|2&U&+KW(pzqYZzMLMqru{#@cOVP7*I< zzs$-1cOvKC0QP}NpfdpDU^O@u+!uTTx&Afa3a|=vgT>(c$o4Mksb?*w-M-4pO$@KjI*X9Jz%e+!T=!5hFnFbQ;? z|1@waI0}3inf@a1dF1xbfoFq11=_p62~2~t!TrF8kjM9d$AL$H&q8<6{vT8Fxod)Q!8Zha{J{f(xq}*Yp%mIFXqpOJ@%+x-CYdYRO><%f-O`tlA zQo0*vIgaEsf|A(^N^7bc1VJBIn>P328uvDN`lwrZQX4swo0fE#YMXZymOg~6^i32A zMT}3*QC*N@TF^7)F#=R9ds}bY1@aMO=wETX^dOb~OKIny=xI)*(!=DF9+*-`GyNWOn!%E&@u=ojhU;+Lgc<&H zZByYcH+&?@7pGRXaqV-9wVr62wl7X?VEZ6RQ`3ApKGwE$aIhRNrhTOBuKt|!b_v9p1|xD(!9&e1U2%~k|HKn%7Dg+Ns018M z?cjR|{G&89DWvp*ajlCJOsU?Kfd5!#v}Fm5DEw>xeIzPedV^%g-l7s5;o4G=f~p?L zZddVi(|4X5I#4qo*eB)K=Fq5k5Z%M)=f5q7kZmthLssLbK!;PCL+%8JT_KyZtCO#* zzGvZsB;%5i)TfnhN!NPbiwwOKt~VPSBjc!!x-l4YL9E6F^Pf%C{c_AAwWbb2CX-3w z8o4k7xvJMyq8sY_Yh!&fV@g(^IxCmXCCEZO&N)Qnq~Ih6;JI7w{4FD>>4rBBZpKFJ zwB@HPKSjo3YZj;1poR6GWq8uM%S~cQH4{q5vCC!f?vS2>NC2kq6kwnJ2~8zTv}>YL*2RnnK*Ie9=q~MNSFLl zBI&>MM4##17(mK_WpvpPmV@=lTL1ph+LSI*>|VI7(Vm%_YPO~^4s#nG=0?ud(ZXnX zye$!Ls3ugmX-8ZiJznLa(A8%D|3u`>S7zk@k0Rf{7_@02D+zcKMhQRqi z`~8muzd^qLD%c6SfNcCf3El{Hfct^tfX@Hl3^sw|z{io}wXgqTa5Xpw+=U$f0x%68 z27ZUU{vL1@sDaJkTyQ!#4Lk^(2;`qna=h*Ycng>YgJ3f_0sI&8`hS8CfxiNh<=29T zfrok7d$VpOd9VTh+$aBqpBwOx_7g`K@wW_JRn3sJ>!_lklfF(ZV`mgg<9gptce4gMP4Lg>*sj zg&egp=VXTVQxd6=zVGSS=X&Q8li?>_d5-bwoMmIUI&J(((`8-D#n*V$!fQqf-a<9D zQWMhK8h7$?m`s&y?kFHrlg_FAhD@hd*pZ30Zr56d9@_uO=2T>ylFGqP z-Yzxiw+hWtob7fhkEB7xT8^ZsThe~JvZ~lD>)I@(;nA<| z(?v-Cr9vH!@Sx%p+CZs)(gFz`l~edh%B>P-RMedJfRRjH%TvhLB$d8ms}x}e3T_eg z14&Brs&gg-gX=B~`azhceiyF%vw=*}vzc$SDmzo%L(Tn&iQx%{(Mqv(U<`N<7o(I zIc79$&){vT;qE%bgk%yiH@>ihQG{7Sw-*@KniVCG{gAQ0DplrqUd8N8ZrDmUZYk=G z(TSNc?OX?!tW>gTS%!(Nm9nq(cL$bn-B+FY;K!N68)FI?!gb=o_$pJ4a$*0;jVJCh z62`MIq;7QTV2kVK&`cNm!{|lw=?OhmoZ-iRdLq6#c(65V_-LnXgK#&>aZ87{eQ$#vkxu*f0IrK{Rr~@3&9J(c2EI# zAme`-dNC)r$a6I?~^8WQ;5=?-F;0wt5F9uHnX9D^3zXN<8{1w;?M!@DpVI z?|^TE_kg#9zX#6(JAwT9KNS2FUBG9+>w$dvKOH#AK(glD!fOH18f!BkVfX(1u!29pN3!T7wfc*GB z7s!wQnc!FG1AYj;1HKL325tpAfOG}-1@{3u>;Eb69?%4fz@Gv60(=no8V&R%AYH<% zz@^|}K(_t<4no-x*pE28;1HyivGVfnq?wHfR;_VHYQ&zNtbmZ2a2y-?g|N{RxDLE= zY=?ZLNIvs26Nhc_D462%SrQ<)5?ByR=OiH~H8^RBlW{Ujcl^LFa|r9)Q#+XrzZQ19 zxXOerA%$7duXE=kkr|WH9||?BvelCofi<8?D96U7kN6Z(r63_soi5%55^))A=3eV= zC;8KIxjL(SD00$Ss*%(3u3?3OGM|Oq6)=%+yhBb;E-F1Y%w9nR#(I1FK&Sczg)3`{ zjvNkqRus{His%v~;My=@GIbGOA*JCdREZOeV;>fK%PHm`kh?P+5|>`JC?ZJ#tHh)^ za@?&-cWV6fs-&o#G4W+_-rJS&x?d=#&6-R$6*ED{W0vv4>JCB}>cvGk==Mhi;B_jg zre~RGDw6B$v(uxX-42H?g~=7uC*%r$4ykkm2x=a*e`&p4rz^hkxvOsGv0$L^GY$>n z8ryE>xt21Qg_wI1IEX#l6y(}{1CG$uM#Qjla57u5^W<*Q*2nTr0;eo88; zV24&&6EmQCL501D>nV_~t`aC5TlGSpu5|6&XhlbnoY2wJiCA-WvdfxjV7y6BvzoH( zwwLRVxec!pBB8{n?rkzcSiP;eoag%JY)~C=EHe2;wQB7cRvFCD-?g7<-^g6qI0a30tIbOzuH$o~HVJ`J7+9tR!+E&+q! zp+Gu<51|jZ4(L9>HQ;n`f1on~IuCFII2HU1UBFMlYrsw53E&#A7TgDX0v*6@;3n{D z&+xvibWWmF7Zmvl+-7Q&FDb$K@X^nY9p2;>4@wg1GtGC}l^7lERzOI?V>{Q2&zT z9JggyTn5ks)dRYP*LnG`YG;7c`x8}MTQ9&M`+yGNaS`P%4!N4^f-up}SG&0A#ZQ%g z`5V3U^GN#KvfiXWj@a&YBzqaxK+uo;^2O1vl8&AJt8X&p$wR;SJ6rqC$#h&5COM_5uIs-3H&xwSKPFZG!BsuI z%5h6w>r2G$8yLFcv-&D#fRGf~-`T-D?tS(iOINDG&gYXdWl1_J&f`m36LoH3S&}Ww zfDqQwD|nDyJSlr+?Hm_}{L}71ak45m^(aOvm}k3;8P}Z0Hs8_nY+5p|dBs~oEkoIg zN)~>C5jR!FL1v%UCFTMTKaUoT;>Cl(ETy%4Q*W=gE;taKiV3IzWC(^$6-?K&#oF?W z@Iv#l>7?Wp#SZrIC^C^9@7#5$hKr1&7u#ft>T}MOD_`H@x~f&Y$UIv)ax9M}lPc1Z z5w|NoX4+GGcAXh5X-(k-T`yF`kyhaQL9NOxh1rnjazluH=Hki4#9pj};<}G$1J^3` zr%ZVi*U>AjYSC%xir)HE%FSDmxI58d~DWmM)VZMOHa+dSTASYd3#$B@1Uml|OK_rfp+5IK?8s%=mtJn6Js>c5K*J?`M$u()r z%Isq|HIW;q{Sd3-6Vo>d^2!$1EWv!jj(;N2b6Hf|U*(32TH;a4tq}|B&u&tO#ik!_ z{L(S!KQwNVvi0M+Zt0`Wav`dBq ztmnC`%x8A(_H6DBn#YCOgaKT7S&UDgm>k?tWma089I?fnZHep}$5+H|BnJ8$c2(>E zOBPutu8s|?=BscQQ!}7wnT!#BMVelA=CWlAVzz8ITD8%U&6nBJWn9X7GpK&&zHd9n z`s#`zTj8sW{XgPu<#$g0-{<7WHzV7>2|O80fX9IyK<5D7h&=xU&;XNQ1-J+JEVBG( zz;nSI|F4e@P6=Qa2?nP&If-A{u_P4cfmWslff1s zzkm+{CxYLgFSr~047?CL7Yu_t&<*?-@V)@|^ZPO25#U5{0(d7ng13UVfa}2%z&O|n z&IOCX?`dPT^KTQ~f%=O+2*zeN!L0(5y#NhW!7Sg^#z8T2Piim0Ca|(GGszprS>{>( ziAJ>nU0Y1Zm7WI`wxGvX8`X&eSITBz5s*g}xu>s=djRU|!U ze5+Ag=K)Oe!R(lfBc?KT5b>KOM((y$@KZ8rxUIr~U|NW{xyMalxQ`F^`IznqqL~4= zXdqS^kNPvnB+KgtmTcOlNmc_ih5VGq74oez(%xMkPnKx9eWaoa=o1%}z<#E5#z8i< zE!-eNQO347yS&7NsHqmPG>8?IjHDu?GmthrAwkut8lG>P%y&C=8p`X&SqHcTteQL( zy`ob3(J-UKu_f$ljQPRXGlpq~OgVDRt5%+cg$$ns)GB0vRB>a44fC@yupF&A=#!c5 z41KJ=#A0eikC8EIZFkGFkDbjR zSVON$ZZQu+S5yxFajCm8#cYm+rHZv3`*t4)$gS8(xkS#4>GnW>-_Yj%^$@|OmMNvR z#qaiSb+?%tzAC=z2(x$ zY9W-g|Ku|*RW+O8*RSDx{ERReFFjqRL22Cj-?+pGQz`0%+M@2DeuiOtj0PIYryV^M zB_{SRP}&v+O?CdH*%GE-?}pO2(?fm3i6P6_Cn?F$bD0|l0?zk@^dUs$%Sk+#!e>&FFQ5W6mzR$T4iA-H}J^jg=71^?NtmvY}v6X(e zyC7a_;2z^rv{mbk8N`cMRt{s%F@ur2JDyd-vh?8|I~Cb5K9_nTyqW7LxGKW-zqo^$ z#Cbe6Mupni?rrSK7PU4#(`u+Tc$)MbGcFuv?)W!mhO`xD%1@-LSXlGrQ8v1@Abx>H z%zM>KCe}rBBK5(q&UH1FS9pbiFDZC=}a{#C|q~uY+j8IP8m)9z*<7 zJ9Z@9yKwg^4xCbPrR(EJ7q^%(zJYQbbQu9jRUc~-6A;ofhPPS?2GH5VX98zNxQ?5H zlp4XHqCDb{9~Arpt}_uo>+URP`DCnQ+V(bt-rj_wCdLxYJ$sEIC5EXTV#>C7ucoKs zFtLl-;@5`QW;RH?@F{15AYq}N#KcK82kbm z|L5TI;H}{0;AKGa{}LeIfU*hD8G#!?9jphdz)J8Fh>t7q}<*Eb{(S!IfYfc;5o@C-^Poe4P{c5cnW?DbT%uOTcev zzaN1A1pfj44(MLM5g=cKYTs^f$R9DRK3-r&m(9Q=+d`xMtxhnJjU8~Cv%2~O8Qn=QEZI(3+xzIx|&)M$js5u^0eXCYX-o@Fo z3t2|^rZ&!>m?RuyoOtv*V4NP@)#bLzv|}{h<|dLb%Kn<#%G@7}hyi5<68+ zldos$m_3~oD?8im48%rF27_b;_vB5&*~zo*Vh*BIl!rbAjoN{#PV!Ba)_0n3&1TK{SRF&G|)*!}Xef19`OK zw+-ni@?&xrEe8X8jeAIw`fNk^W0hGBT#0ef<(?dpyl@ z*eOU>QT53usHa^ME1?laDOnLxFa3u=s7OPP$^MPL>8*7MQtZOt!6vQK0UB*hre7(Z{}@iLn_XNE=~$NY@BDYt4>JuO`pQUY zpi`{wlhJp1Wz2G_%o4|q*rIo7(!O_lZbac0^kqvKXR(i>x0q4|gfaw@Dx7ub$;NV{ zx3{aT9CK}rN=TD(y39hY^z`79RDqqhm07r=11X)3ARb0j-DqEhW{HgXSrB8zINpb zmLq8;QSid*iHdZ`rjr|=N2&A+(pGP=i?Fc$gQ1i6sdbVcD*a}i(k@J56{uVqDoB?{l63_#F zkDUKS@HgN_Z~*iJ`3YDJWCL&vkgvdxfqw?i2G0VL|Njge1>`qC_X55XTmfVYunMdM z_X4*ecp( z{`){a0&W3Qz{~uP=Jy$3G58fS{da)&{N*1&z675St^{8GAL92h;48@Zp8y{RuLaKm zH-PJb?g!irc7d~j&KR5s?nd_i4ER@|y9RcFwcsA$N3`j`gD(S}DfkSy6}%Sg0lnZP zptfHCNAzH< z{1ZKOl~d<8KFB6&=5(i-&+so$c$u5x>0@R;BcW)7$1zKGhDZh%tEy8jM*m?37X8IK z1~a;%xQt-lWms%=C9z#8nH!xerVRWS%vbgHh!fN#NM(y7IjyilaYf8_ePgsnK0}nw zCs5KHu6$dpklk&>z!LE>yTC~|hLbVVJ8-I=Z=JB+Gs~oON2W0yOr$ShK6aK z_x)ZJ zz?u`M8vY=gCG<0w(m$k|$dESB`j`p2Oe1Bl*jCF_98Jwvx&idaR+lARqE1R@Te@!a zF*E%caXLvVqc7@Qh1oQjDsFDj43`$^g6D$9+?#~U7AQrqG_lfu8Pfd^E;K#2xvla) z*vikX@a*Y?aJd(#W>xnBYWS$z&5ebw!0w?x@^406V_m)~qcc!T_@fR!C8OP5r8dF7 ze5TQ;jn>-jD(a=3wNV{_;@L!fPtC|X%f~n-rIQ03w&6ZB_LN;J%M^-u{_QCC+`Bk# zs#^GuUq8zNP;8x9`)2yHt6GUdk?1+?Y{h4!Z%-Mk`7s*S)M7Q{XtM=p7t5rZ@U2OQ zCn|4x>uW9wynN#oOF3#2f1aQ-ujl4hFLd~(WUl6Lp=|vm#bRV&=5CGJ=>f{OL`lUu zsZfITf2ca~3okDNICV)lG6peclN>6dygq3f8Vk{KMIx!@C-ig*O0&EbGL1ZY_xJSg zDD)+he%wr&(%m0sEDXARy1YJAyHj`fItneIde`Lo{r`BMuZYU}#HAOXrAx_%#6T?d zCOs}^16(l)DJ|OpONN6m@$zw@U`$Aa+*ARBVbewO)0!D3?2|{8DcO%X&&(f- zgG<3*zLPk5^Hq&uu;mTpJQewgynNxqA0Fd zE5)m^xwpAPHucK7KSB1-&3f6C8HH=+{tBIrgPpI?4H+Cjat>4~+3?}t#I=`~O60W> z{62P@CCzl5D_H%VWf20AeEXFqsOojefvwdT)+qz~GOkvBX0+O|)Dk!>kbbB8XZCG8 zkD8Q9>^`%RW=~cj3ao~T63W!^?8ph*MPdCjL!0y>YWDfnN7i>TjcPrUSvz*rn}(_6 zik@FFq=KhfZ8kPHb+o0cxBHFU><++&Y3g@U88Zn^!?#)!D6Tjo8@wwH6|Y1U6#bD7 zZA-^Y3LBcOj8Qv&!Gk$UiJB7HEe4Fr+Xv_;lV-~$n=Ac-75o^suxOdg(m&&4D9@w$ zC(5z-sorGg9X<1(QgPS^C|<<*w*j*q5TgHkl9g)0oRA#Ke6i`ps`GHx&CPV43@ zZ(i>6@EbSU0ZNSzZgDMEO+9zhay&r!lQmjy*{&A9GMwVyrw;0Rze{rWCdn*3WHniD z)FTVWLQgnsS@eG^u!G6+`wz5gYXs- z6Wm@}tPy5G*Lag7x$B+d1g#ug)T}oJMGQYKn3EW?S(wqQJn7UlRSA>LS0(>M;X5oE zGF2*)&y|8Hq7yEL%;fIsQZRcaGpCDSCe9#ob_CCrA-gl65_qdWjbfIa0{xITuv0+) zNvmaD;7d5J;~GQrGNlhRvq`~i26LIfW81v!;-G}7Et5GG8nCJ_5tN&( zR-7Ay-z2-_HZMbm<je*@Rf}2RvXhw@ZB-<8)|) za0;|c;E!q)PJ)h4{1{|UEOZDN54rv@M>v&d60?q9NlZs&BKL7M@PoCPP>WoyDtJ*? z_&+S3d0+HUY`_M+2Sn zmreiWKzsQo0QvO$NAMyb+5Yk10`O>X2Dl&4U4TD8hL?}OzX4AM+S4Bex&z=Z!2`f2 zk?CIvHi8KJ1M>T`!Lz{mpbH!eWV8SGKz9J@{=ZYfDd1mLTA;B0UbSO|WDoc?R@ zDzE`8153dhkku~&+H;rO{!8R@`RteM{th77y$$++Z17(VE&|7aA3#^p_HS~syCd|h zU#{H?zmoCFip3g7yvi;XR@{T^m>VWItN4zwyVV3H*VN~8#9lI4D1^!T->ECyZ2XRP z1F_F{pFs9IU~rZy&NoO>R0eproR+D4;4wd&j+xt2rE4^|nM)DNHQDA;y1WBhpY$A- zygsP^cK0Tx8j-n9<7Y;c4hAV7*?$+$|Nd=fkxZfNGDmsJJ!#46rsC7fes|8@q{isu zn$0baGZ!SrjFz-sW|q!osv@&A>sV%1YN_@;xV%mOIKq{-{H4Y&=doniFRF8Kh31lO z=lb|&vKsP3toGbE&Dulb;+9=Wn#gal*@n-EMqMcE(gh_N}{<#q(7}5L{CFVKf{xyVM2Q7w-Fl%lQBcg6=jxsajjU5UDJ+QOeRBA zyDE~)#4tZwEKT){y&SDwL zsZ)E`;Pk9sAb~24SRrd&p=M=n1%X1+jUcITsHUPP;V0C+#w{&-s)FgaxEjSzl}GuT z+21Ne2Z3I%^$D8~K5ZI~E#qk$WwvrDR40|NPeoa~q22J0a;^B6Mc=Us(v5$mzJAin zD*CAtHZ_k1PMnJJ@Xs72;ubAvO&`>d@DILO)R`AlmUOLE@?c{xKlb?I`|sH^P{_H3 zI=GMuJqK1*u<#RBPqj@+yR+BVC#B{~Es_p*Md1_n-(fiqVw2BD&y_D8K0Av=vvp#n zpNNJj;$=7C{Q3W{IQhTow zuKx+5VHSyUv17#KzF1kjPF&{aQE1TZzWmZN@)MGmQ>>H1_|4p26R z7;}(+3hAT-%4<;mM)5kgr9$Y_)d&q$?X&d%UG>>Q7_vxA%y+&psm{e!NGC5=!dOMW zO@?FaF1u}zqA+@v?jT2M9X<==_`*;~*HbF~QPH=`7}_=%Gax0iErF6gDJ%N(QRvZP{n`G90oHR4L0-&u7m!FDI2b>GRXtA&E#T z42&}>TLWnaoVK*0=VhN+&4GNxgRg^kU*Fx6tBrH;>C-OzR%O@;ZQvOX0~vc`JPwSk zm)lBNEIk(orDO<`&U%tLyfu1W3hh)1%HPJ$5%Wjy5d0i#2;!<>_lAp72+jebBDXz9 zW(!Wm>XVB-PKHKE?3&CbYRrLU|CqaL5k>v8JRi#+bAf;2^g=hs!e%*{u>tgX`0u%M zi}=-_9!g1moi(hT+p+Uo6>|0v3YDgWm6)|Gb*t_4x>6CcA2XikST{)GAlX;x&#mZl zoNkq1x|X3}qqnnt=<2aEHGdIDWwuBGUDW7ohHi8>78vew^erHcr^Z%DS z`Tw7g`ELZ%U@dqc_z*Jxvw{5mT>_*7_yY3&yFnYQ1`#+G`~q43=ipsHe*R?-ARqsa z0jGm6BKv;<+y-6%o(!%7E5NtV1>6L5zuycP1ZRV@z^~B-{5$wO_#Ai(cq-5t|D8bk zf`@}2qZ9ZMxCM-Z8jxMU&FBPL;2dxakY3>3;BUe6!Sg@^JOca#x&JQkG4KlTanB{&Hj4c?9X zFaLd)0p0z#9;^gQ!4gmbzjFG4FO}#BJj2v5Sd12~4_&mcjxK8~v|a5g!&teKFFa^W zr{d%f*4u>Rl$2k(Bc=b+dlO}`e)TSnmisAa3YT5IYur3$kJ-CFIBCCpVJZj3EnR0M z$uB*Oj6%Gs5Pa|B?D6Bfl2 z-?tIb4zg8=k#Eys9gW zCn1E6z8L|oEYX}5d65q!rSB@^jpFPX_qFD33S-i?BYZMAK8|k=o!?7N+l7U+Et<4J zq1;%^EX7Zic=;Q>HD~e-DbzBiXLVk7mh3L~rbe_NJmjlznXBtfiGH zp8Z)K$r8{-(6WBQn`s5t7bnYo&tx4%7dh@Sbde@39CgA{Cj*$v(VmmHbTQsb-1EXF zRZ2Nu+a}K*RoilS!eaHnMAsK0QF^Ajk&k4ZK(YrcZ{OPcM}1USlzj72f&znvAe?W_ zvQVD8ig`ZM#sx+;YSiLNWm|)_V%Tw!5o=TFQ6t|OjCL!uDD@PTjET)J#7E+Hz5&ct zZRVafomofzG)m;Cx(l2CbVf=gpP8Q8c|`hzGDTD{u;&d8DoP{#tXNSRKG0e*LliPE z#TdSHcx(Tr;lY86`_>NhGv!R+9(C*-SwrK!Z}BwhW%ft3X<@40-rby;7>o8bTYD;D zIrN*ivHYV47XOtv4mrqGEM9g#8Z2g9QA!Dwq0o~ZFs z&GV`H=pJ*^!(548TxjK1{zh-p65t$nh7DKSp)c0*9Ew_|bJ0A-WoQKVnq32R>Wa!; z^a+Zkh6qK=c(O@MH9M$`N*C@v*FQkP!%J@uz2qW6U;&*>twnrTGBXC#p|7w1UXl3v zP98;<&%nE$qb=pJPGnHQS$Ad+H#yuD#IG-}EjOXny7ubPX@4S&Zlb$J_SGu?A42t2 Apa1{> literal 0 HcmV?d00001 diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index b865aa82e..eea6621e6 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -77,7 +77,7 @@ class Solver * that goes with the reason * @return Rule The generated rule or null if tautological */ - public function createRequireRule(PackageInterface $package, array $providers, $reason, $reasonData = null) + protected function createRequireRule(PackageInterface $package, array $providers, $reason, $reasonData = null) { $literals = array(new Literal($package, false)); @@ -128,7 +128,7 @@ class Solver * goes with the reason * @return Rule The generated rule */ - public function createInstallRule(PackageInterface $package, $reason, $reasonData = null) + protected function createInstallRule(PackageInterface $package, $reason, $reasonData = null) { return new Rule(new Literal($package, true)); } @@ -146,7 +146,7 @@ class Solver * the reason * @return Rule The generated rule */ - public function createInstallOneOfRule(array $packages, $reason, $reasonData = null) + protected function createInstallOneOfRule(array $packages, $reason, $reasonData = null) { if (empty($packages)) { return $this->createImpossibleRule($reason, $reasonData); @@ -172,7 +172,7 @@ class Solver * goes with the reason * @return Rule The generated rule */ - public function createRemoveRule(PackageInterface $package, $reason, $reasonData = null) + protected function createRemoveRule(PackageInterface $package, $reason, $reasonData = null) { return new Rule(array(new Literal($package, false)), $reason, $reasonData); } @@ -191,7 +191,7 @@ class Solver * goes with the reason * @return Rule The generated rule */ - public function createConflictRule(PackageInterface $issuer, PackageInterface $provider, $reason, $reasonData = null) + protected function createConflictRule(PackageInterface $issuer, PackageInterface $provider, $reason, $reasonData = null) { // ignore self conflict if ($issuer === $provider) { @@ -212,7 +212,7 @@ class Solver * the reason * @return Rule An empty rule */ - public function createImpossibleRule($reason, $reasonData = null) + protected function createImpossibleRule($reason, $reasonData = null) { return new Rule(array(), $reason, $reasonData); } @@ -237,7 +237,7 @@ class Solver } } - public function addRulesForPackage(PackageInterface $package) + protected function addRulesForPackage(PackageInterface $package) { $workQueue = new \SplQueue; $workQueue->enqueue($package); @@ -571,7 +571,7 @@ class Solver } } - public function addChoiceRules() + protected function addChoiceRules() { // void From 5e3bf86851a1b269636ac637297a26eb3272aade Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 18 Feb 2012 12:50:45 +0100 Subject: [PATCH 12/42] Remove .swp file --- src/Composer/DependencyResolver/.Solver.php.swp | Bin 94208 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/Composer/DependencyResolver/.Solver.php.swp diff --git a/src/Composer/DependencyResolver/.Solver.php.swp b/src/Composer/DependencyResolver/.Solver.php.swp deleted file mode 100644 index 91ad3e7d858fd419561b0834bbd41e8b882fc820..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94208 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 Apa1{> From 8aa0127de877f7075b3af929bdcae09b92efb987 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sat, 18 Feb 2012 13:09:19 +0100 Subject: [PATCH 13/42] Remove test of undefined behaviour for unknown types in rulesets --- .../Composer/Test/DependencyResolver/RuleSetTest.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tests/Composer/Test/DependencyResolver/RuleSetTest.php b/tests/Composer/Test/DependencyResolver/RuleSetTest.php index be37b8795..7a5b018b4 100644 --- a/tests/Composer/Test/DependencyResolver/RuleSetTest.php +++ b/tests/Composer/Test/DependencyResolver/RuleSetTest.php @@ -54,17 +54,6 @@ class RuleSetTest extends TestCase $ruleSet->add(new Rule(array(), 'job1', null), 7); } - public function testAddWhenTypeIsUnknow() - { - $ruleSet = new RuleSet; - - $rule = new Rule(array(), 'job1', null); - $ruleSet->add($rule, -1); - - $rules = $ruleSet->getRules(); - $this->assertSame($rule, $rules[-1][0]); - } - public function testCount() { $ruleSet = new RuleSet; From cc80e5a3b10a84dc8c79da3803ed6cf1a4cbaaf1 Mon Sep 17 00:00:00 2001 From: Volker Dusch Date: Sat, 18 Feb 2012 14:29:58 +0100 Subject: [PATCH 14/42] Cleanup unreachable code --- src/Composer/DependencyResolver/Solver.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index eea6621e6..00212bb5c 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -944,20 +944,6 @@ class Solver } foreach ($this->jobs as $job) { - switch ($job['cmd']) { - case 'update-all': - foreach ($installedPackages as $package) { - $this->updateMap[$package->getId()] = true; - } - break; - - case 'fix-all': - foreach ($installedPackages as $package) { - $this->fixMap[$package->getId()] = true; - } - break; - } - foreach ($job['packages'] as $package) { switch ($job['cmd']) { case 'fix': From a28fa790beb582d3bef23bd5a43fce900270337e Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 18 Feb 2012 16:03:35 +0100 Subject: [PATCH 15/42] Fix regex --- src/Composer/Repository/Vcs/GitDriver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index daab73dfe..c37b83cae 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -170,7 +170,7 @@ class GitDriver extends VcsDriver implements VcsDriverInterface } // local filesystem - if (preg_match('{^(file://|/|[a-z]:[\\\\/])}', $url)) { + if (preg_match('{^(file://|/|[a-z]:[\\\\/])}i', $url)) { $process = new ProcessExecutor(); // check whether there is a git repo in that path if ($process->execute(sprintf('cd %s && git show', escapeshellarg($url)), $output) === 0) { From a8b2db64d58db5fb88360d812a0dafb75c3c35f2 Mon Sep 17 00:00:00 2001 From: Volker Dusch Date: Sat, 18 Feb 2012 16:55:45 +0100 Subject: [PATCH 16/42] Expaned the update tests to make sure a) Only requested updates execute and b) Installed repos with no actions get pruned from the jobqueue --- .../Test/DependencyResolver/SolverTest.php | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index 85ef6fc70..a71feafce 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -158,6 +158,22 @@ class SolverTest extends TestCase $this->checkSolverResult(array()); } + public function testSolverUpdateOnlyUpdatesSelectedPackage() + { + $this->repoInstalled->addPackage($packageA = $this->getPackage('A', '1.0')); + $this->repoInstalled->addPackage($packageB = $this->getPackage('B', '1.0')); + $this->repo->addPackage($packageAnewer = $this->getPackage('A', '1.1')); + $this->repo->addPackage($packageBnewer = $this->getPackage('B', '1.1')); + + $this->reposComplete(); + + $this->request->update('A'); + + $this->checkSolverResult(array( + array('job' => 'update', 'from' => $packageA, 'to' => $packageAnewer), + )); + } + public function testSolverUpdateConstrained() { $this->repoInstalled->addPackage($packageA = $this->getPackage('A', '1.0')); @@ -192,6 +208,24 @@ class SolverTest extends TestCase ))); } + public function testSolverUpdateFullyConstrainedPrunesInstalledPackages() + { + $this->repoInstalled->addPackage($packageA = $this->getPackage('A', '1.0')); + $this->repoInstalled->addPackage($this->getPackage('B', '1.0')); + $this->repo->addPackage($newPackageA = $this->getPackage('A', '1.2')); + $this->repo->addPackage($this->getPackage('A', '2.0')); + $this->reposComplete(); + + $this->request->install('A', new VersionConstraint('<', '2.0.0.0')); + $this->request->update('A', new VersionConstraint('=', '1.0.0.0')); + + $this->checkSolverResult(array(array( + 'job' => 'update', + 'from' => $packageA, + 'to' => $newPackageA, + ))); + } + public function testSolverAllJobs() { $this->repoInstalled->addPackage($packageD = $this->getPackage('D', '1.0')); From 230e1450536759c47aff54f95487a0573a3e6d10 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 18 Feb 2012 16:59:39 +0100 Subject: [PATCH 17/42] Fix downloader tests on windows and mock Filesystem properly --- src/Composer/Downloader/VcsDownloader.php | 7 +++--- .../Test/Downloader/GitDownloaderTest.php | 25 ++++++++++++++----- .../Test/Downloader/HgDownloaderTest.php | 25 ++++++++++++++----- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src/Composer/Downloader/VcsDownloader.php b/src/Composer/Downloader/VcsDownloader.php index 5fa8c9e4b..5a30dacc5 100644 --- a/src/Composer/Downloader/VcsDownloader.php +++ b/src/Composer/Downloader/VcsDownloader.php @@ -24,11 +24,13 @@ abstract class VcsDownloader implements DownloaderInterface { protected $io; protected $process; + protected $filesystem; - public function __construct(IOInterface $io, ProcessExecutor $process = null) + public function __construct(IOInterface $io, ProcessExecutor $process = null, Filesystem $fs = null) { $this->io = $io; $this->process = $process ?: new ProcessExecutor; + $this->filesystem = $fs ?: new Filesystem; } /** @@ -74,8 +76,7 @@ abstract class VcsDownloader implements DownloaderInterface public function remove(PackageInterface $package, $path) { $this->enforceCleanDirectory($path); - $fs = new Filesystem(); - $fs->removeDirectory($path); + $this->filesystem->removeDirectory($path); } /** diff --git a/tests/Composer/Test/Downloader/GitDownloaderTest.php b/tests/Composer/Test/Downloader/GitDownloaderTest.php index 7d563d2e4..ff1c3ac07 100644 --- a/tests/Composer/Test/Downloader/GitDownloaderTest.php +++ b/tests/Composer/Test/Downloader/GitDownloaderTest.php @@ -32,7 +32,7 @@ class GitDownloaderTest extends \PHPUnit_Framework_TestCase public function testDownload() { - $expectedGitCommand = 'git clone \'https://github.com/l3l0/composer\' \'composerPath\' && cd \'composerPath\' && git checkout \'ref\' && git reset --hard \'ref\''; + $expectedGitCommand = $this->getCmd('git clone \'https://github.com/l3l0/composer\' \'composerPath\' && cd \'composerPath\' && git checkout \'ref\' && git reset --hard \'ref\''); $packageMock = $this->getMock('Composer\Package\PackageInterface'); $packageMock->expects($this->any()) ->method('getSourceReference') @@ -66,8 +66,8 @@ class GitDownloaderTest extends \PHPUnit_Framework_TestCase public function testUpdate() { - $expectedGitUpdateCommand = 'cd \'composerPath\' && git fetch && git checkout \'ref\' && git reset --hard \'ref\''; - $expectedGitResetCommand = 'cd \'composerPath\' && git status --porcelain'; + $expectedGitUpdateCommand = $this->getCmd('cd \'composerPath\' && git fetch && git checkout \'ref\' && git reset --hard \'ref\''); + $expectedGitResetCommand = $this->getCmd('cd \'composerPath\' && git status --porcelain'); $packageMock = $this->getMock('Composer\Package\PackageInterface'); $packageMock->expects($this->any()) @@ -90,22 +90,35 @@ class GitDownloaderTest extends \PHPUnit_Framework_TestCase public function testRemove() { - $expectedGitResetCommand = 'cd \'composerPath\' && git status --porcelain'; + $expectedGitResetCommand = $this->getCmd('cd \'composerPath\' && git status --porcelain'); $packageMock = $this->getMock('Composer\Package\PackageInterface'); $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); $processExecutor->expects($this->any()) ->method('execute') ->with($this->equalTo($expectedGitResetCommand)); + $filesystem = $this->getMock('Composer\Util\Filesystem'); + $filesystem->expects($this->any()) + ->method('removeDirectory') + ->with($this->equalTo('composerPath')); - $downloader = new GitDownloader($this->getMock('Composer\IO\IOInterface'), $processExecutor); + $downloader = new GitDownloader($this->getMock('Composer\IO\IOInterface'), $processExecutor, $filesystem); $downloader->remove($packageMock, 'composerPath'); } public function testGetInstallationSource() { $downloader = new GitDownloader($this->getMock('Composer\IO\IOInterface')); - + $this->assertEquals('source', $downloader->getInstallationSource()); } + + private function getCmd($cmd) + { + if (defined('PHP_WINDOWS_VERSION_BUILD')) { + return strtr($cmd, "'", '"'); + } + + return $cmd; + } } diff --git a/tests/Composer/Test/Downloader/HgDownloaderTest.php b/tests/Composer/Test/Downloader/HgDownloaderTest.php index 81429194d..a7c246394 100644 --- a/tests/Composer/Test/Downloader/HgDownloaderTest.php +++ b/tests/Composer/Test/Downloader/HgDownloaderTest.php @@ -32,7 +32,7 @@ class HgDownloaderTest extends \PHPUnit_Framework_TestCase public function testDownload() { - $expectedGitCommand = 'hg clone \'https://mercurial.dev/l3l0/composer\' \'composerPath\' && cd \'composerPath\' && hg up \'ref\''; + $expectedGitCommand = $this->getCmd('hg clone \'https://mercurial.dev/l3l0/composer\' \'composerPath\' && cd \'composerPath\' && hg up \'ref\''); $packageMock = $this->getMock('Composer\Package\PackageInterface'); $packageMock->expects($this->any()) ->method('getSourceReference') @@ -66,8 +66,8 @@ class HgDownloaderTest extends \PHPUnit_Framework_TestCase public function testUpdate() { - $expectedUpdateCommand = 'cd \'composerPath\' && hg pull && hg up \'ref\''; - $expectedResetCommand = 'cd \'composerPath\' && hg st'; + $expectedUpdateCommand = $this->getCmd('cd \'composerPath\' && hg pull && hg up \'ref\''); + $expectedResetCommand = $this->getCmd('cd \'composerPath\' && hg st'); $packageMock = $this->getMock('Composer\Package\PackageInterface'); $packageMock->expects($this->any()) @@ -90,22 +90,35 @@ class HgDownloaderTest extends \PHPUnit_Framework_TestCase public function testRemove() { - $expectedResetCommand = 'cd \'composerPath\' && hg st'; + $expectedResetCommand = $this->getCmd('cd \'composerPath\' && hg st'); $packageMock = $this->getMock('Composer\Package\PackageInterface'); $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); $processExecutor->expects($this->any()) ->method('execute') ->with($this->equalTo($expectedResetCommand)); + $filesystem = $this->getMock('Composer\Util\Filesystem'); + $filesystem->expects($this->any()) + ->method('removeDirectory') + ->with($this->equalTo('composerPath')); - $downloader = new HgDownloader($this->getMock('Composer\IO\IOInterface'), $processExecutor); + $downloader = new HgDownloader($this->getMock('Composer\IO\IOInterface'), $processExecutor, $filesystem); $downloader->remove($packageMock, 'composerPath'); } public function testGetInstallationSource() { $downloader = new HgDownloader($this->getMock('Composer\IO\IOInterface')); - + $this->assertEquals('source', $downloader->getInstallationSource()); } + + private function getCmd($cmd) + { + if (defined('PHP_WINDOWS_VERSION_BUILD')) { + return strtr($cmd, "'", '"'); + } + + return $cmd; + } } From e2199b2b03889121719582d0f23a8e192eb2671c Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 18 Feb 2012 17:05:13 +0100 Subject: [PATCH 18/42] Fixed automatic date parsing of versions --- src/Composer/Repository/Vcs/GitDriver.php | 2 +- src/Composer/Repository/Vcs/HgDriver.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index c37b83cae..8a8d1f8c6 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -101,7 +101,7 @@ class GitDriver extends VcsDriver implements VcsDriverInterface if (!isset($composer['time'])) { $this->process->execute(sprintf('cd %s && git log -1 --format=%%at %s', escapeshellarg($this->tmpDir), escapeshellarg($identifier)), $output); - $date = new \DateTime('@'.$output[0]); + $date = new \DateTime('@'.trim($output)); $composer['time'] = $date->format('Y-m-d H:i:s'); } $this->infoCache[$identifier] = $composer; diff --git a/src/Composer/Repository/Vcs/HgDriver.php b/src/Composer/Repository/Vcs/HgDriver.php index f65f683c5..1e73104f9 100644 --- a/src/Composer/Repository/Vcs/HgDriver.php +++ b/src/Composer/Repository/Vcs/HgDriver.php @@ -107,7 +107,7 @@ class HgDriver extends VcsDriver implements VcsDriverInterface if (!isset($composer['time'])) { $this->process->execute(sprintf('cd %s && hg log --template "{date|rfc822date}" -r %s', escapeshellarg($this->tmpDir), escapeshellarg($identifier)), $output); - $date = new \DateTime($output[0]); + $date = new \DateTime(trim($output)); $composer['time'] = $date->format('Y-m-d H:i:s'); } $this->infoCache[$identifier] = $composer; From 5fdca198809951f03e0376d3d40e7e42b2b1df0f Mon Sep 17 00:00:00 2001 From: Volker Dusch Date: Sat, 18 Feb 2012 17:50:15 +0100 Subject: [PATCH 19/42] Removed the option to disallowed downgrades and simplifed some places where it was used --- .../DependencyResolver/DefaultPolicy.php | 12 +------- .../DependencyResolver/PolicyInterface.php | 3 +- src/Composer/DependencyResolver/Solver.php | 30 +++++-------------- 3 files changed, 9 insertions(+), 36 deletions(-) diff --git a/src/Composer/DependencyResolver/DefaultPolicy.php b/src/Composer/DependencyResolver/DefaultPolicy.php index 41918b260..f06b4104b 100644 --- a/src/Composer/DependencyResolver/DefaultPolicy.php +++ b/src/Composer/DependencyResolver/DefaultPolicy.php @@ -26,11 +26,6 @@ class DefaultPolicy implements PolicyInterface return true; } - public function allowDowngrade() - { - return true; - } - public function versionCompare(PackageInterface $a, PackageInterface $b, $operator) { $constraint = new VersionConstraint($operator, $b->getVersion()); @@ -39,16 +34,11 @@ class DefaultPolicy implements PolicyInterface return $constraint->matchSpecific($version); } - public function findUpdatePackages(Solver $solver, Pool $pool, array $installedMap, PackageInterface $package, $allowAll = false) + public function findUpdatePackages(Solver $solver, Pool $pool, array $installedMap, PackageInterface $package) { $packages = array(); foreach ($pool->whatProvides($package->getName()) as $candidate) { - // skip old packages unless downgrades are an option - if (!$allowAll && !$this->allowDowngrade() && $this->versionCompare($package, $candidate, '>')) { - continue; - } - if ($candidate !== $package) { $packages[] = $candidate; } diff --git a/src/Composer/DependencyResolver/PolicyInterface.php b/src/Composer/DependencyResolver/PolicyInterface.php index 0271fdab2..45309a081 100644 --- a/src/Composer/DependencyResolver/PolicyInterface.php +++ b/src/Composer/DependencyResolver/PolicyInterface.php @@ -21,9 +21,8 @@ use Composer\Package\PackageInterface; interface PolicyInterface { function allowUninstall(); - function allowDowngrade(); function versionCompare(PackageInterface $a, PackageInterface $b, $operator); - function findUpdatePackages(Solver $solver, Pool $pool, array $installedMap, PackageInterface $package, $allowAll); + function findUpdatePackages(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); } diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 00212bb5c..8f12e6e0a 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -375,9 +375,9 @@ class Solver * be added * @param bool $allowAll Whether downgrades are allowed */ - private function addRulesForUpdatePackages(PackageInterface $package, $allowAll) + private function addRulesForUpdatePackages(PackageInterface $package) { - $updates = $this->policy->findUpdatePackages($this, $this->pool, $this->installedMap, $package, $allowAll); + $updates = $this->policy->findUpdatePackages($this, $this->pool, $this->installedMap, $package); $this->addRulesForPackage($package); @@ -965,7 +965,7 @@ class Solver } foreach ($installedPackages as $package) { - $this->addRulesForUpdatePackages($package, true); + $this->addRulesForUpdatePackages($package); } @@ -983,31 +983,15 @@ class Solver // solver_addrpmrulesforweak(solv, &addedmap); foreach ($installedPackages as $package) { - // create a feature rule which allows downgrades - $updates = $this->policy->findUpdatePackages($this, $this->pool, $this->installedMap, $package, true); - $featureRule = $this->createUpdateRule($package, $updates, self::RULE_INTERNAL_ALLOW_UPDATE, (string) $package); - - // create an update rule which does not allow downgrades - $updates = $this->policy->findUpdatePackages($this, $this->pool, $this->installedMap, $package, false); + $updates = $this->policy->findUpdatePackages($this, $this->pool, $this->installedMap, $package); $rule = $this->createUpdateRule($package, $updates, self::RULE_INTERNAL_ALLOW_UPDATE, (string) $package); - if ($rule->equals($featureRule)) { - if ($this->policy->allowUninstall()) { - $featureRule->setWeak(true); - $this->addRule(RuleSet::TYPE_FEATURE, $featureRule); - $this->packageToFeatureRule[$package->getId()] = $rule; - } else { - $this->addRule(RuleSet::TYPE_UPDATE, $rule); - $this->packageToUpdateRule[$package->getId()] = $rule; - } - } else if ($this->policy->allowUninstall()) { - $featureRule->setWeak(true); + if ($this->policy->allowUninstall()) { $rule->setWeak(true); - $this->addRule(RuleSet::TYPE_FEATURE, $featureRule); - $this->addRule(RuleSet::TYPE_UPDATE, $rule); - $this->packageToFeatureRule[$package->getId()] = $rule; + } else { + $this->addRule(RuleSet::TYPE_UPDATE, $rule); $this->packageToUpdateRule[$package->getId()] = $rule; } } From cbc021c05dc5182f0af578608f2750c892acf681 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sat, 18 Feb 2012 18:04:45 +0100 Subject: [PATCH 20/42] featureRule no longer exists, only update rule --- src/Composer/DependencyResolver/Solver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 8f12e6e0a..680b87591 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -988,7 +988,7 @@ class Solver if ($this->policy->allowUninstall()) { $rule->setWeak(true); - $this->addRule(RuleSet::TYPE_FEATURE, $featureRule); + $this->addRule(RuleSet::TYPE_FEATURE, $rule); $this->packageToFeatureRule[$package->getId()] = $rule; } else { $this->addRule(RuleSet::TYPE_UPDATE, $rule); From ec61297122258f21a030d54844f3c9827bef1e3d Mon Sep 17 00:00:00 2001 From: Volker Dusch Date: Sat, 18 Feb 2012 18:31:19 +0100 Subject: [PATCH 21/42] Remove the allowUninstall policy option and clean up the only usage --- src/Composer/DependencyResolver/DefaultPolicy.php | 5 ----- src/Composer/DependencyResolver/PolicyInterface.php | 1 - src/Composer/DependencyResolver/Solver.php | 11 +++-------- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/Composer/DependencyResolver/DefaultPolicy.php b/src/Composer/DependencyResolver/DefaultPolicy.php index f06b4104b..63699d883 100644 --- a/src/Composer/DependencyResolver/DefaultPolicy.php +++ b/src/Composer/DependencyResolver/DefaultPolicy.php @@ -21,11 +21,6 @@ use Composer\Package\LinkConstraint\VersionConstraint; */ class DefaultPolicy implements PolicyInterface { - public function allowUninstall() - { - return true; - } - public function versionCompare(PackageInterface $a, PackageInterface $b, $operator) { $constraint = new VersionConstraint($operator, $b->getVersion()); diff --git a/src/Composer/DependencyResolver/PolicyInterface.php b/src/Composer/DependencyResolver/PolicyInterface.php index 45309a081..7c26ab63f 100644 --- a/src/Composer/DependencyResolver/PolicyInterface.php +++ b/src/Composer/DependencyResolver/PolicyInterface.php @@ -20,7 +20,6 @@ use Composer\Package\PackageInterface; */ interface PolicyInterface { - function allowUninstall(); function versionCompare(PackageInterface $a, PackageInterface $b, $operator); function findUpdatePackages(Solver $solver, Pool $pool, array $installedMap, PackageInterface $package); function installable(Solver $solver, Pool $pool, array $installedMap, PackageInterface $package); diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 680b87591..25d186073 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -986,14 +986,9 @@ class Solver $updates = $this->policy->findUpdatePackages($this, $this->pool, $this->installedMap, $package); $rule = $this->createUpdateRule($package, $updates, self::RULE_INTERNAL_ALLOW_UPDATE, (string) $package); - if ($this->policy->allowUninstall()) { - $rule->setWeak(true); - $this->addRule(RuleSet::TYPE_FEATURE, $rule); - $this->packageToFeatureRule[$package->getId()] = $rule; - } else { - $this->addRule(RuleSet::TYPE_UPDATE, $rule); - $this->packageToUpdateRule[$package->getId()] = $rule; - } + $rule->setWeak(true); + $this->addRule(RuleSet::TYPE_FEATURE, $rule); + $this->packageToFeatureRule[$package->getId()] = $rule; } foreach ($this->jobs as $job) { From 3fb75faa7589e8967a63ca420319b19225e99aff Mon Sep 17 00:00:00 2001 From: Volker Dusch Date: Sat, 18 Feb 2012 19:19:49 +0100 Subject: [PATCH 22/42] Now that no more update rules are created the code that handles them can be removed too. Also adapted the tests that used TYPE_UPDATE exemplarily to use TYPE_FEATURE. --- src/Composer/DependencyResolver/RuleSet.php | 2 -- src/Composer/DependencyResolver/Solver.php | 17 ++--------------- .../RuleSetIteratorTest.php | 6 +++--- .../Test/DependencyResolver/RuleSetTest.php | 19 +++++++++---------- 4 files changed, 14 insertions(+), 30 deletions(-) diff --git a/src/Composer/DependencyResolver/RuleSet.php b/src/Composer/DependencyResolver/RuleSet.php index 6d79a9678..1f444c788 100644 --- a/src/Composer/DependencyResolver/RuleSet.php +++ b/src/Composer/DependencyResolver/RuleSet.php @@ -20,7 +20,6 @@ class RuleSet implements \IteratorAggregate, \Countable // highest priority => lowest number const TYPE_PACKAGE = 0; const TYPE_JOB = 1; - const TYPE_UPDATE = 2; const TYPE_FEATURE = 3; const TYPE_CHOICE = 4; const TYPE_LEARNED = 5; @@ -29,7 +28,6 @@ class RuleSet implements \IteratorAggregate, \Countable -1 => 'UNKNOWN', self::TYPE_PACKAGE => 'PACKAGE', self::TYPE_FEATURE => 'FEATURE', - self::TYPE_UPDATE => 'UPDATE', self::TYPE_JOB => 'JOB', self::TYPE_CHOICE => 'CHOICE', self::TYPE_LEARNED => 'LEARNED', diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 25d186073..9ff6b0764 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -52,7 +52,6 @@ class Solver protected $decisionMap; protected $installedMap; - protected $packageToUpdateRule = array(); protected $packageToFeatureRule = array(); public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed) @@ -508,7 +507,7 @@ class Solver // push all of our rules (can only be feature or job rules) // asserting this literal on the problem stack - foreach ($this->rules->getIteratorFor(array(RuleSet::TYPE_JOB, RuleSet::TYPE_UPDATE, RuleSet::TYPE_FEATURE)) as $assertRule) { + foreach ($this->rules->getIteratorFor(array(RuleSet::TYPE_JOB, RuleSet::TYPE_FEATURE)) as $assertRule) { if ($assertRule->isDisabled() || !$assertRule->isAssertion() || $assertRule->isWeak()) { continue; } @@ -882,11 +881,6 @@ class Solver protected function disableUpdateRule($package) { - // find update & feature rule and disable - if (isset($this->packageToUpdateRule[$package->getId()])) { - $this->packageToUpdateRule[$package->getId()]->disable(); - } - if (isset($this->packageToFeatureRule[$package->getId()])) { $this->packageToFeatureRule[$package->getId()]->disable(); } @@ -1056,9 +1050,6 @@ class Solver 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()); - } if (isset($this->packageToFeatureRule[$package->getId()])) { $literals = array_merge($literals, $this->packageToFeatureRule[$package->getId()]->getLiterals()); } @@ -1808,11 +1799,7 @@ class Solver $rule = null; - if (isset($this->packageToUpdateRule[$literal->getPackageId()])) { - $rule = $this->packageToUpdateRule[$literal->getPackageId()]; - } - - if ((!$rule || $rule->isDisabled()) && isset($this->packageToFeatureRule[$literal->getPackageId()])) { + if (isset($this->packageToFeatureRule[$literal->getPackageId()])) { $rule = $this->packageToFeatureRule[$literal->getPackageId()]; } diff --git a/tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php b/tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php index 6340a7f68..28db18131 100644 --- a/tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php +++ b/tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php @@ -27,7 +27,7 @@ class ResultSetIteratorTest extends \PHPUnit_Framework_TestCase new Rule(array(), 'job1', null), new Rule(array(), 'job2', null), ), - RuleSet::TYPE_UPDATE => array( + RuleSet::TYPE_FEATURE => array( new Rule(array(), 'update1', null), ), RuleSet::TYPE_PACKAGE => array(), @@ -46,7 +46,7 @@ class ResultSetIteratorTest extends \PHPUnit_Framework_TestCase $expected = array( $this->rules[RuleSet::TYPE_JOB][0], $this->rules[RuleSet::TYPE_JOB][1], - $this->rules[RuleSet::TYPE_UPDATE][0], + $this->rules[RuleSet::TYPE_FEATURE][0], ); $this->assertEquals($expected, $result); @@ -64,7 +64,7 @@ class ResultSetIteratorTest extends \PHPUnit_Framework_TestCase $expected = array( RuleSet::TYPE_JOB, RuleSet::TYPE_JOB, - RuleSet::TYPE_UPDATE, + RuleSet::TYPE_FEATURE, ); $this->assertEquals($expected, $result); diff --git a/tests/Composer/Test/DependencyResolver/RuleSetTest.php b/tests/Composer/Test/DependencyResolver/RuleSetTest.php index 7a5b018b4..54ad88a58 100644 --- a/tests/Composer/Test/DependencyResolver/RuleSetTest.php +++ b/tests/Composer/Test/DependencyResolver/RuleSetTest.php @@ -27,10 +27,9 @@ class RuleSetTest extends TestCase new Rule(array(), 'job1', null), new Rule(array(), 'job2', null), ), - RuleSet::TYPE_UPDATE => array( + RuleSet::TYPE_FEATURE => array( new Rule(array(), 'update1', null), ), - RuleSet::TYPE_FEATURE => array(), RuleSet::TYPE_LEARNED => array(), RuleSet::TYPE_CHOICE => array(), ); @@ -38,7 +37,7 @@ class RuleSetTest extends TestCase $ruleSet = new RuleSet; $ruleSet->add($rules[RuleSet::TYPE_JOB][0], RuleSet::TYPE_JOB); - $ruleSet->add($rules[RuleSet::TYPE_UPDATE][0], RuleSet::TYPE_UPDATE); + $ruleSet->add($rules[RuleSet::TYPE_FEATURE][0], RuleSet::TYPE_FEATURE); $ruleSet->add($rules[RuleSet::TYPE_JOB][1], RuleSet::TYPE_JOB); $this->assertEquals($rules, $ruleSet->getRules()); @@ -81,7 +80,7 @@ class RuleSetTest extends TestCase $rule1 = new Rule(array(), 'job1', null); $rule2 = new Rule(array(), 'job1', null); $ruleSet->add($rule1, RuleSet::TYPE_JOB); - $ruleSet->add($rule2, RuleSet::TYPE_UPDATE); + $ruleSet->add($rule2, RuleSet::TYPE_FEATURE); $iterator = $ruleSet->getIterator(); @@ -97,9 +96,9 @@ class RuleSetTest extends TestCase $rule2 = new Rule(array(), 'job1', null); $ruleSet->add($rule1, RuleSet::TYPE_JOB); - $ruleSet->add($rule2, RuleSet::TYPE_UPDATE); + $ruleSet->add($rule2, RuleSet::TYPE_FEATURE); - $iterator = $ruleSet->getIteratorFor(RuleSet::TYPE_UPDATE); + $iterator = $ruleSet->getIteratorFor(RuleSet::TYPE_FEATURE); $this->assertSame($rule2, $iterator->current()); } @@ -111,7 +110,7 @@ class RuleSetTest extends TestCase $rule2 = new Rule(array(), 'job1', null); $ruleSet->add($rule1, RuleSet::TYPE_JOB); - $ruleSet->add($rule2, RuleSet::TYPE_UPDATE); + $ruleSet->add($rule2, RuleSet::TYPE_FEATURE); $iterator = $ruleSet->getIteratorWithout(RuleSet::TYPE_JOB); @@ -143,7 +142,7 @@ class RuleSetTest extends TestCase ->method('equal') ->will($this->returnValue(false)); - $ruleSet->add($rule, RuleSet::TYPE_UPDATE); + $ruleSet->add($rule, RuleSet::TYPE_FEATURE); $this->assertTrue($ruleSet->containsEqual($rule)); $this->assertFalse($ruleSet->containsEqual($rule2)); @@ -156,9 +155,9 @@ class RuleSetTest extends TestCase $literal = new Literal($this->getPackage('foo', '2.1'), true); $rule = new Rule(array($literal), 'job1', null); - $ruleSet->add($rule, RuleSet::TYPE_UPDATE); + $ruleSet->add($rule, RuleSet::TYPE_FEATURE); - $this->assertContains('UPDATE : (+foo-2.1.0.0)', $ruleSet->__toString()); + $this->assertContains('FEATURE : (+foo-2.1.0.0)', $ruleSet->__toString()); } private function getRuleMock() From f54b04aac84a91d168322247adaea1b1b3d06aca Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 18 Feb 2012 23:28:47 +0100 Subject: [PATCH 23/42] Restore realpath behavior --- src/Composer/Installer/LibraryInstaller.php | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index 1f94f4071..a3f0b2b74 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -78,11 +78,9 @@ class LibraryInstaller implements InstallerInterface */ public function install(PackageInterface $package) { + $this->initializeDirs(); $downloadPath = $this->getInstallPath($package); - $this->filesystem->ensureDirectoryExists($this->vendorDir); - $this->filesystem->ensureDirectoryExists($this->binDir); - // remove the binaries if it appears the package files are missing if (!is_readable($downloadPath) && $this->repository->hasPackage($package)) { $this->removeBinaries($package); @@ -104,11 +102,9 @@ class LibraryInstaller implements InstallerInterface throw new \InvalidArgumentException('Package is not installed: '.$initial); } + $this->initializeDirs(); $downloadPath = $this->getInstallPath($initial); - $this->filesystem->ensureDirectoryExists($this->vendorDir); - $this->filesystem->ensureDirectoryExists($this->binDir); - $this->removeBinaries($initial); $this->downloadManager->update($initial, $target, $downloadPath); $this->installBinaries($target); @@ -191,6 +187,14 @@ class LibraryInstaller implements InstallerInterface } } + protected function initializeDirs() + { + $this->filesystem->ensureDirectoryExists($this->vendorDir); + $this->filesystem->ensureDirectoryExists($this->binDir); + $this->vendorDir = realpath($this->vendorDir); + $this->binDir = realpath($this->binDir); + } + private function generateWindowsProxyCode($bin, $link) { $binPath = $this->filesystem->findShortestPath($link, $bin); From 8fd4e560292c68db8322b2a5fe3d14c083f86551 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sun, 19 Feb 2012 00:13:21 +0100 Subject: [PATCH 24/42] Deciding to install a package and wanting to install it, is not a conflict --- src/Composer/DependencyResolver/Solver.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 9ff6b0764..281685a34 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -1113,6 +1113,8 @@ class Solver protected function addDecision(Literal $l, $level) { + assert($this->decisionMap[$l->getPackageId()] == 0); + if ($l->isWanted()) { $this->decisionMap[$l->getPackageId()] = $level; } else { @@ -1123,6 +1125,9 @@ class Solver protected function addDecisionId($literalId, $level) { $packageId = abs($literalId); + + assert($this->decisionMap[$packageId] == 0); + if ($literalId > 0) { $this->decisionMap[$packageId] = $level; } else { @@ -1165,8 +1170,8 @@ class Solver { $packageId = abs($literalId); return ( - $this->decisionMap[$packageId] > 0 && !($literalId < 0) || - $this->decisionMap[$packageId] < 0 && $literalId > 0 + ($this->decisionMap[$packageId] > 0 && $literalId < 0) || + ($this->decisionMap[$packageId] < 0 && $literalId > 0) ); } From 52d876e11e65a6b4b3780ac5c6ff1083b916d6aa Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sun, 19 Feb 2012 00:15:23 +0100 Subject: [PATCH 25/42] Add SolverProblemsException and test basic solver failures --- src/Composer/DependencyResolver/Solver.php | 4 ++ .../SolverProblemsException.php | 65 +++++++++++++++++++ .../Test/DependencyResolver/SolverTest.php | 43 +++++++++++- 3 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 src/Composer/DependencyResolver/SolverProblemsException.php diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 281685a34..4359f3102 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -1035,6 +1035,10 @@ class Solver //findrecommendedsuggested(solv); //solver_prepare_solutions(solv); + if ($this->problems) { + throw new SolverProblemsException($this->problems, $this->learnedPool); + } + return $this->createTransaction(); } diff --git a/src/Composer/DependencyResolver/SolverProblemsException.php b/src/Composer/DependencyResolver/SolverProblemsException.php new file mode 100644 index 000000000..cbc4fd571 --- /dev/null +++ b/src/Composer/DependencyResolver/SolverProblemsException.php @@ -0,0 +1,65 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\DependencyResolver; + +/** + * @author Nils Adermann + */ +class SolverProblemsException extends \RuntimeException +{ + protected $problems; + + public function __construct(array $problems, array $learnedPool) + { + $message = ''; + foreach ($problems as $i => $problem) { + $message .= '['; + foreach ($problem as $why) { + + if (is_int($why) && isset($learnedPool[$why])) { + $rules = $learnedPool[$why]; + } else { + $rules = $why; + } + + if (isset($rules['packages'])) { + $message .= $this->jobToText($rules); + } else { + $message .= '('; + foreach ($rules as $rule) { + if ($rule instanceof Rule) { + if ($rule->getType() == RuleSet::TYPE_LEARNED) { + $message .= 'learned: '; + } + $message .= $rule . ', '; + } else { + $message .= 'String(' . $rule . '), '; + } + } + $message .= ')'; + } + $message .= ', '; + } + $message .= "]\n"; + } + + parent::__construct($message); + } + + public function jobToText($job) + { + //$output = serialize($job); + $output = 'Job(cmd='.$job['cmd'].', target='.$job['packageName'].', packages=['.implode(', ', $job['packages']).'])'; + return $output; + } +} diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index a71feafce..bea9d989b 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -19,6 +19,7 @@ use Composer\DependencyResolver\DefaultPolicy; use Composer\DependencyResolver\Pool; use Composer\DependencyResolver\Request; use Composer\DependencyResolver\Solver; +use Composer\DependencyResolver\SolverProblemsException; use Composer\Package\Link; use Composer\Package\LinkConstraint\VersionConstraint; use Composer\Test\TestCase; @@ -484,6 +485,47 @@ class SolverTest extends TestCase )); } + public function testConflictResultEmpty() + { + $this->repo->addPackage($packageA = $this->getPackage('A', '1.0')); + $this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));; + + $packageA->setConflicts(array( + new Link('A', 'B', new VersionConstraint('>=', '1.0'), 'conflicts'), + )); + + $this->reposComplete(); + + $this->request->install('A'); + $this->request->install('B'); + + try { + $transaction = $this->solver->solve($this->request); + $this->fail('Unsolvable conflict did not resolve in exception.'); + } catch (SolverProblemsException $e) { + } + } + + public function testUnsatisfiableRequires() + { + $this->repo->addPackage($packageA = $this->getPackage('A', '1.0')); + $this->repo->addPackage($packageB = $this->getPackage('B', '1.0')); + + $packageA->setRequires(array( + new Link('A', 'B', new VersionConstraint('>=', '2.0'), 'requires'), + )); + + $this->reposComplete(); + + $this->request->install('A'); + + try { + $transaction = $this->solver->solve($this->request); + $this->fail('Unsolvable conflict did not resolve in exception.'); + } catch (SolverProblemsException $e) { + } + } + protected function reposComplete() { $this->pool->addRepository($this->repoInstalled); @@ -513,5 +555,4 @@ class SolverTest extends TestCase $this->assertEquals($expected, $result); } - } From e6143d1584a1bd9d344d966b2bd5ebb6b8b175bb Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sun, 19 Feb 2012 00:21:39 +0100 Subject: [PATCH 26/42] Add todos to explain why try/catch is inside the test --- tests/Composer/Test/DependencyResolver/SolverTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index bea9d989b..18cb9f4a1 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -503,6 +503,7 @@ class SolverTest extends TestCase $transaction = $this->solver->solve($this->request); $this->fail('Unsolvable conflict did not resolve in exception.'); } catch (SolverProblemsException $e) { + // @todo: assert problem properties } } @@ -523,6 +524,7 @@ class SolverTest extends TestCase $transaction = $this->solver->solve($this->request); $this->fail('Unsolvable conflict did not resolve in exception.'); } catch (SolverProblemsException $e) { + // @todo: assert problem properties } } From eafe13d5a5eae6b9c18b4f5a8a893b4964be73ea Mon Sep 17 00:00:00 2001 From: Volker Dusch Date: Sun, 19 Feb 2012 14:55:14 +0100 Subject: [PATCH 27/42] Create an impossible rule when trying to install something that doesn't exist. The rule isn't acted upon yet (hence the incomplete test) but it is there as a reminder that this case needs to be handled. --- src/Composer/DependencyResolver/Solver.php | 6 ++++++ .../Test/DependencyResolver/SolverTest.php | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 4359f3102..a395ad969 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -964,6 +964,12 @@ class Solver foreach ($this->jobs as $job) { + if (empty($job['packages']) && $job['cmd'] == 'install') { + $this->addRule( + RuleSet::TYPE_JOB, + $this->createImpossibleRule(static::RULE_JOB_INSTALL, $job) + ); + } foreach ($job['packages'] as $package) { switch ($job['cmd']) { case 'install': diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index 18cb9f4a1..5ad7e90c3 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -55,6 +55,22 @@ class SolverTest extends TestCase )); } + public function testInstallNonExistingPackageFails() + { + $this->repo->addPackage($this->getPackage('A', '1.0')); + $this->reposComplete(); + + $this->request->install('B'); + + try { + $transaction = $this->solver->solve($this->request); + $this->markTestIncomplete('Reporting this failure is not implemented/working yet'); + //$this->fail('Unsolvable conflict did not resolve in exception.'); + } catch (SolverProblemsException $e) { + // @todo: assert problem properties + } + } + public function testSolverInstallWithDeps() { $this->repo->addPackage($packageA = $this->getPackage('A', '1.0')); From fd0bf14eb2ccbda2487a34eeda43fd2d4c1a970e Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 19 Feb 2012 15:04:40 +0100 Subject: [PATCH 28/42] Support both require and requires as depends link-type arg --- src/Composer/Command/DependsCommand.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Composer/Command/DependsCommand.php b/src/Composer/Command/DependsCommand.php index f695487ff..82ff5e02d 100644 --- a/src/Composer/Command/DependsCommand.php +++ b/src/Composer/Command/DependsCommand.php @@ -25,6 +25,8 @@ use Symfony\Component\Console\Output\OutputInterface; */ class DependsCommand extends Command { + protected $linkTypes = array('require', 'recommend', 'suggest'); + protected function configure() { $this @@ -32,7 +34,7 @@ class DependsCommand extends Command ->setDescription('Shows which packages depend on the given package') ->setDefinition(array( new InputArgument('package', InputArgument::REQUIRED, 'Package to inspect'), - new InputOption('link-type', '', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Link types to show', array('requires', 'recommends', 'suggests')) + new InputOption('link-type', '', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Link types to show', $this->linkTypes) )) ->setHelp(<<getRepositoryManager()->getRepositories(); $types = $input->getOption('link-type'); + foreach ($repos as $repository) { foreach ($repository->getPackages() as $package) { foreach ($types as $type) { - foreach ($package->{'get'.$type}() as $link) { + $type = rtrim($type, 's'); + if (!in_array($type, $this->linkTypes)) { + throw new \InvalidArgumentException('Unexpected link type: '.$type.', valid types: '.implode(', ', $this->linkTypes)); + } + foreach ($package->{'get'.$type.'s'}() as $link) { if ($link->getTarget() === $needle) { if ($verbose) { $references[] = array($type, $package, $link); From 0b8fb68e9301a719b4ea664a14d1a6c7bba2fb5f Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sun, 19 Feb 2012 15:19:34 +0100 Subject: [PATCH 29/42] Add a debug print method for the entire watch tree to the solver --- src/Composer/DependencyResolver/Solver.php | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 4359f3102..16295fd5d 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -2033,4 +2033,42 @@ 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*"; + } + } + else if ($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"; + } + } } From 8484199677ecdc5aa54f073aa6938fa723e8d08c Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sun, 19 Feb 2012 15:20:13 +0100 Subject: [PATCH 30/42] Display undecided literals as undecided with a ?, when printing the decision map --- src/Composer/DependencyResolver/Solver.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 16295fd5d..833548246 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -2018,8 +2018,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"; From e20a79ac61de55a8000a24b1926045494d499004 Mon Sep 17 00:00:00 2001 From: Volker Dusch Date: Sun, 19 Feb 2012 15:30:53 +0100 Subject: [PATCH 31/42] Fix TODO tags to confirm with the projects standard --- src/Composer/DependencyResolver/Solver.php | 2 +- tests/Composer/Test/DependencyResolver/SolverTest.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index a395ad969..6d85cb325 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -304,7 +304,7 @@ class Solver // if ignoreinstalledsobsoletes is not set, we're also checking // obsoletes of installed packages (like newer rpm versions) // - /** @TODO: if ($this->noInstalledObsoletes) */ + /** TODO if ($this->noInstalledObsoletes) */ if (true) { $noObsoletes = isset($this->noObsoletes[$package->getId()]); $isInstalled = (isset($this->installedMap[$package->getId()])); diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index 5ad7e90c3..875dca41c 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -67,7 +67,7 @@ class SolverTest extends TestCase $this->markTestIncomplete('Reporting this failure is not implemented/working yet'); //$this->fail('Unsolvable conflict did not resolve in exception.'); } catch (SolverProblemsException $e) { - // @todo: assert problem properties + // TODO assert problem properties } } @@ -519,7 +519,7 @@ class SolverTest extends TestCase $transaction = $this->solver->solve($this->request); $this->fail('Unsolvable conflict did not resolve in exception.'); } catch (SolverProblemsException $e) { - // @todo: assert problem properties + // TODO assert problem properties } } @@ -540,7 +540,7 @@ class SolverTest extends TestCase $transaction = $this->solver->solve($this->request); $this->fail('Unsolvable conflict did not resolve in exception.'); } catch (SolverProblemsException $e) { - // @todo: assert problem properties + // TODO assert problem properties } } From 1ee5d994050f126dbd0ea05a7243cf1491e3d47f Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sun, 19 Feb 2012 15:35:13 +0100 Subject: [PATCH 32/42] When changing watched literals of a rule, update the parent's next pointer The previous rule was not previously updated to point to the next rule when removing a middle rule from the watch tree for a literal. This resulted in jumping from one literal's watch tree to another's, which could then jump back to the original and cause infinite loop in a case like #265. Fixes #265 --- src/Composer/DependencyResolver/Solver.php | 19 ++++++++--- .../Test/DependencyResolver/SolverTest.php | 34 +++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 833548246..6d1293e1b 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -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,23 @@ 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; diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index 18cb9f4a1..e74f11b06 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -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')); From f304a0f129d9159080e73850530356025b389ed1 Mon Sep 17 00:00:00 2001 From: Volker Dusch Date: Sun, 19 Feb 2012 15:38:03 +0100 Subject: [PATCH 33/42] Clean up the incomplete marker like suggested in https://github.com/composer/composer/pull/324#r465391 --- tests/Composer/Test/DependencyResolver/SolverTest.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index 875dca41c..db7bfc1b6 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -57,6 +57,8 @@ class SolverTest extends TestCase public function testInstallNonExistingPackageFails() { + $this->markTestIncomplete('Reporting this failure is not implemented/working yet'); + $this->repo->addPackage($this->getPackage('A', '1.0')); $this->reposComplete(); @@ -64,8 +66,7 @@ class SolverTest extends TestCase try { $transaction = $this->solver->solve($this->request); - $this->markTestIncomplete('Reporting this failure is not implemented/working yet'); - //$this->fail('Unsolvable conflict did not resolve in exception.'); + $this->fail('Unsolvable conflict did not resolve in exception.'); } catch (SolverProblemsException $e) { // TODO assert problem properties } From 2a92b904d2a5628fa52f27e1f71c6f7ad5aeed0d Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sun, 19 Feb 2012 15:42:23 +0100 Subject: [PATCH 34/42] Correct placing of braces --- src/Composer/DependencyResolver/Solver.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 6d1293e1b..4ec591c29 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -1257,8 +1257,7 @@ class Solver } else { $prevRule->next2 = $nextRule; } - } - else { + } else { $this->watches[$literal->getId()] = $nextRule; } @@ -2072,8 +2071,7 @@ class Solver if ($watch->next2 == $watch) { echo $indent." 2 *RECURSION*"; } - } - else if ($watch && ($watch->next1 || $watch->next2)) { + } elseif ($watch && ($watch->next1 || $watch->next2)) { $indent = str_replace(array('1', '2'), ' ', $indent); array_push($queue, array($indent.' 2 ', $watch->next2)); From af408eee9a5b480e385fd6dc5b452eabe78cd905 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sun, 19 Feb 2012 15:54:48 +0100 Subject: [PATCH 35/42] Fix line endings of Composer TestCase --- tests/Composer/Test/TestCase.php | 69 ++++++++++++++++---------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/tests/Composer/Test/TestCase.php b/tests/Composer/Test/TestCase.php index 17255ab2e..05a788517 100644 --- a/tests/Composer/Test/TestCase.php +++ b/tests/Composer/Test/TestCase.php @@ -1,34 +1,35 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Test; - -use Composer\Package\Version\VersionParser; -use Composer\Package\MemoryPackage; - -abstract class TestCase extends \PHPUnit_Framework_TestCase -{ - private static $versionParser; - - public static function setUpBeforeClass() - { - if (!self::$versionParser) { - self::$versionParser = new VersionParser(); - } - } - - protected function getPackage($name, $version) - { - $normVersion = self::$versionParser->normalize($version); - return new MemoryPackage($name, $normVersion, $version); - } -} \ No newline at end of file + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Test; + +use Composer\Package\Version\VersionParser; +use Composer\Package\MemoryPackage; +use Composer\Package\LinkConstraint\VersionConstraint; + +abstract class TestCase extends \PHPUnit_Framework_TestCase +{ + private static $versionParser; + + public static function setUpBeforeClass() + { + if (!self::$versionParser) { + self::$versionParser = new VersionParser(); + } + } + + protected function getPackage($name, $version) + { + $normVersion = self::$versionParser->normalize($version); + return new MemoryPackage($name, $normVersion, $version); + } +} From 3b06a22e694edd6bab29c74d69a02eed838379a8 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sun, 19 Feb 2012 15:55:44 +0100 Subject: [PATCH 36/42] Add getVersionConstraint test case to avoid version normalization issues --- .../Test/DependencyResolver/SolverTest.php | 98 +++++++++---------- tests/Composer/Test/TestCase.php | 8 ++ 2 files changed, 57 insertions(+), 49 deletions(-) diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index e74f11b06..b3c7f4a46 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -61,7 +61,7 @@ class SolverTest extends TestCase $this->repo->addPackage($packageB = $this->getPackage('B', '1.0')); $this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1')); - $packageA->setRequires(array(new Link('A', 'B', new VersionConstraint('<', '1.1'), 'requires'))); + $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('<', '1.1'), 'requires'))); $this->reposComplete(); @@ -123,12 +123,12 @@ class SolverTest extends TestCase $this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1')); $this->reposComplete(); - $packageA->setRequires(array(new Link('A', 'B', new VersionConstraint('>=', '1.0.0.0'), 'requires'))); + $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '1.0.0.0'), 'requires'))); - $this->request->install('A', new VersionConstraint('=', '1.0.0.0')); - $this->request->install('B', new VersionConstraint('=', '1.1.0.0')); - $this->request->update('A', new VersionConstraint('=', '1.0.0.0')); - $this->request->update('B', new VersionConstraint('=', '1.0.0.0')); + $this->request->install('A', $this->getVersionConstraint('=', '1.0.0.0')); + $this->request->install('B', $this->getVersionConstraint('=', '1.1.0.0')); + $this->request->update('A', $this->getVersionConstraint('=', '1.0.0.0')); + $this->request->update('B', $this->getVersionConstraint('=', '1.0.0.0')); $this->checkSolverResult(array( array('job' => 'update', 'from' => $packageB, 'to' => $newPackageB), @@ -182,7 +182,7 @@ class SolverTest extends TestCase $this->repo->addPackage($this->getPackage('A', '2.0')); $this->reposComplete(); - $this->request->install('A', new VersionConstraint('<', '2.0.0.0')); + $this->request->install('A', $this->getVersionConstraint('<', '2.0.0.0')); $this->request->update('A'); $this->checkSolverResult(array(array( @@ -199,8 +199,8 @@ class SolverTest extends TestCase $this->repo->addPackage($this->getPackage('A', '2.0')); $this->reposComplete(); - $this->request->install('A', new VersionConstraint('<', '2.0.0.0')); - $this->request->update('A', new VersionConstraint('=', '1.0.0.0')); + $this->request->install('A', $this->getVersionConstraint('<', '2.0.0.0')); + $this->request->update('A', $this->getVersionConstraint('=', '1.0.0.0')); $this->checkSolverResult(array(array( 'job' => 'update', @@ -217,8 +217,8 @@ class SolverTest extends TestCase $this->repo->addPackage($this->getPackage('A', '2.0')); $this->reposComplete(); - $this->request->install('A', new VersionConstraint('<', '2.0.0.0')); - $this->request->update('A', new VersionConstraint('=', '1.0.0.0')); + $this->request->install('A', $this->getVersionConstraint('<', '2.0.0.0')); + $this->request->update('A', $this->getVersionConstraint('=', '1.0.0.0')); $this->checkSolverResult(array(array( 'job' => 'update', @@ -237,7 +237,7 @@ class SolverTest extends TestCase $this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1')); $this->repo->addPackage($packageC = $this->getPackage('C', '1.1')); $this->repo->addPackage($this->getPackage('D', '1.0')); - $packageA->setRequires(array(new Link('A', 'B', new VersionConstraint('<', '1.1'), 'requires'))); + $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('<', '1.1'), 'requires'))); $this->reposComplete(); @@ -259,8 +259,8 @@ class SolverTest extends TestCase $this->repo->addPackage($middlePackageB = $this->getPackage('B', '1.0')); $this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1')); $this->repo->addPackage($oldPackageB = $this->getPackage('B', '0.9')); - $packageA->setRequires(array(new Link('A', 'B', new VersionConstraint('<', '1.1'), 'requires'))); - $packageA->setConflicts(array(new Link('A', 'B', new VersionConstraint('<', '1.0'), 'conflicts'))); + $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('<', '1.1'), 'requires'))); + $packageA->setConflicts(array(new Link('A', 'B', $this->getVersionConstraint('<', '1.0'), 'conflicts'))); $this->reposComplete(); @@ -306,8 +306,8 @@ class SolverTest extends TestCase $this->repo->addPackage($packageA = $this->getPackage('A', '1.0')); $this->repo->addPackage($packageQ = $this->getPackage('Q', '1.0')); $this->repo->addPackage($packageB = $this->getPackage('B', '0.8')); - $packageA->setRequires(array(new Link('A', 'B', new VersionConstraint('>=', '1.0'), 'requires'))); - $packageQ->setProvides(array(new Link('Q', 'B', new VersionConstraint('=', '1.0'), 'provides'))); + $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires'))); + $packageQ->setProvides(array(new Link('Q', 'B', $this->getVersionConstraint('=', '1.0'), 'provides'))); $this->reposComplete(); @@ -324,8 +324,8 @@ class SolverTest extends TestCase $this->repo->addPackage($packageA = $this->getPackage('A', '1.0')); $this->repo->addPackage($packageQ = $this->getPackage('Q', '1.0')); $this->repo->addPackage($packageB = $this->getPackage('B', '1.0')); - $packageA->setRequires(array(new Link('A', 'B', new VersionConstraint('>=', '1.0'), 'requires'))); - $packageQ->setReplaces(array(new Link('Q', 'B', new VersionConstraint('>=', '1.0'), 'replaces'))); + $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires'))); + $packageQ->setReplaces(array(new Link('Q', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces'))); $this->reposComplete(); @@ -341,8 +341,8 @@ class SolverTest extends TestCase { $this->repo->addPackage($packageA = $this->getPackage('A', '1.0')); $this->repo->addPackage($packageQ = $this->getPackage('Q', '1.0')); - $packageA->setRequires(array(new Link('A', 'B', new VersionConstraint('>=', '1.0'), 'requires'))); - $packageQ->setReplaces(array(new Link('Q', 'B', new VersionConstraint('>=', '1.0'), 'replaces'))); + $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires'))); + $packageQ->setReplaces(array(new Link('Q', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces'))); $this->reposComplete(); @@ -359,8 +359,8 @@ class SolverTest extends TestCase $this->repo->addPackage($packageA = $this->getPackage('A', '1.0')); $this->repo->addPackage($packageQ = $this->getPackage('Q', '1.0')); $this->repo->addPackage($packageB = $this->getPackage('B', '1.0')); - $packageA->setRequires(array(new Link('A', 'B', new VersionConstraint('>=', '1.0'), 'requires'))); - $packageQ->setReplaces(array(new Link('Q', 'B', new VersionConstraint('>=', '1.0'), 'replaces'))); + $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires'))); + $packageQ->setReplaces(array(new Link('Q', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces'))); $this->reposComplete(); @@ -377,24 +377,24 @@ class SolverTest extends TestCase { $this->repo->addPackage($packageX = $this->getPackage('X', '1.0')); $packageX->setRequires(array( - new Link('X', 'A', new VersionConstraint('>=', '2.0.0.0'), 'requires'), - new Link('X', 'B', new VersionConstraint('>=', '2.0.0.0'), 'requires'))); + new Link('X', 'A', $this->getVersionConstraint('>=', '2.0.0.0'), 'requires'), + new Link('X', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), 'requires'))); $this->repo->addPackage($packageA = $this->getPackage('A', '2.0.0')); $this->repo->addPackage($newPackageA = $this->getPackage('A', '2.1.0')); $this->repo->addPackage($newPackageB = $this->getPackage('B', '2.1.0')); - $packageA->setRequires(array(new Link('A', 'B', new VersionConstraint('>=', '2.0.0.0'), 'requires'))); + $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), 'requires'))); // new package A depends on version of package B that does not exist // => new package A is not installable - $newPackageA->setRequires(array(new Link('A', 'B', new VersionConstraint('>=', '2.2.0.0'), 'requires'))); + $newPackageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '2.2.0.0'), 'requires'))); // add a package S replacing both A and B, so that S and B or S and A cannot be simultaneously installed // but an alternative option for A and B both exists // this creates a more difficult so solve conflict $this->repo->addPackage($packageS = $this->getPackage('S', '2.0.0')); - $packageS->setReplaces(array(new Link('S', 'A', new VersionConstraint('>=', '2.0.0.0'), 'replaces'), new Link('S', 'B', new VersionConstraint('>=', '2.0.0.0'), 'replaces'))); + $packageS->setReplaces(array(new Link('S', 'A', $this->getVersionConstraint('>=', '2.0.0.0'), 'replaces'), new Link('S', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), 'replaces'))); $this->reposComplete(); @@ -412,8 +412,8 @@ class SolverTest extends TestCase $this->repo->addPackage($packageA = $this->getPackage('A', '1.0')); $this->repo->addPackage($packageB1 = $this->getPackage('B', '0.9')); $this->repo->addPackage($packageB2 = $this->getPackage('B', '1.1')); - $packageA->setRequires(array(new Link('A', 'B', new VersionConstraint('>=', '1.0'), 'requires'))); - $packageB2->setRequires(array(new Link('B', 'A', new VersionConstraint('>=', '1.0'), 'requires'))); + $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires'))); + $packageB2->setRequires(array(new Link('B', 'A', $this->getVersionConstraint('>=', '1.0'), 'requires'))); $this->reposComplete(); @@ -433,10 +433,10 @@ class SolverTest extends TestCase $this->repo->addPackage($packageB = $this->getPackage('B', '1.0')); $this->repo->addPackage($packageC = $this->getPackage('C', '1.0')); $this->repo->addPackage($packageD = $this->getPackage('D', '1.0')); - $packageA->setRequires(array(new Link('A', 'B', new VersionConstraint('>=', '1.0'), 'requires'))); - $packageB->setRequires(array(new Link('B', 'Virtual', new VersionConstraint('>=', '1.0'), 'requires'))); - $packageC->setRequires(array(new Link('C', 'Virtual', new VersionConstraint('==', '1.0'), 'provides'))); - $packageD->setRequires(array(new Link('D', 'Virtual', new VersionConstraint('==', '1.0'), 'provides'))); + $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires'))); + $packageB->setRequires(array(new Link('B', 'Virtual', $this->getVersionConstraint('>=', '1.0'), 'requires'))); + $packageC->setRequires(array(new Link('C', 'Virtual', $this->getVersionConstraint('==', '1.0'), 'provides'))); + $packageD->setRequires(array(new Link('D', 'Virtual', $this->getVersionConstraint('==', '1.0'), 'provides'))); $this->reposComplete(); @@ -461,18 +461,18 @@ class SolverTest extends TestCase $this->repo->addPackage($packageD2 = $this->getPackage('D', '1.1')); $packageA->setRequires(array( - new Link('A', 'B', new VersionConstraint('>=', '1.0'), 'requires'), - new Link('A', 'C', new VersionConstraint('>=', '1.0'), 'requires'), + new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires'), + new Link('A', 'C', $this->getVersionConstraint('>=', '1.0'), 'requires'), )); $packageD->setReplaces(array( - new Link('D', 'B', new VersionConstraint('>=', '1.0'), 'replaces'), - new Link('D', 'C', new VersionConstraint('>=', '1.0'), 'replaces'), + new Link('D', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces'), + new Link('D', 'C', $this->getVersionConstraint('>=', '1.0'), 'replaces'), )); $packageD2->setReplaces(array( - new Link('D', 'B', new VersionConstraint('>=', '1.0'), 'replaces'), - new Link('D', 'C', new VersionConstraint('>=', '1.0'), 'replaces'), + new Link('D', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces'), + new Link('D', 'C', $this->getVersionConstraint('>=', '1.0'), 'replaces'), )); $this->reposComplete(); @@ -496,23 +496,23 @@ class SolverTest extends TestCase $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'), + new Link('C', 'A', $this->getVersionConstraint('>=', '2.0'), 'requires'), + new Link('C', 'D', $this->getVersionConstraint('>=', '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'), + new Link('D', 'A', $this->getVersionConstraint('>=', '2.1'), 'requires'), + new Link('D', 'B', $this->getVersionConstraint('>=', '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'))); + $packageB1->setRequires(array(new Link('B', 'A', $this->getVersionConstraint('==', '2.1.0.0-dev'), 'requires'))); + $packageB2->setRequires(array(new Link('B', 'A', $this->getVersionConstraint('==', '2.1.0.0-dev'), 'requires'))); - $packageB2->setReplaces(array(new Link('B', 'D', new VersionConstraint('==', '2.0.9.0'), 'replaces'))); + $packageB2->setReplaces(array(new Link('B', 'D', $this->getVersionConstraint('==', '2.0.9.0'), 'replaces'))); $this->reposComplete(); - $this->request->install('C', new VersionConstraint('==', '2.0.0.0-dev')); + $this->request->install('C', $this->getVersionConstraint('==', '2.0.0.0-dev')); $this->setExpectedException('Composer\DependencyResolver\SolverProblemsException'); @@ -525,7 +525,7 @@ class SolverTest extends TestCase $this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));; $packageA->setConflicts(array( - new Link('A', 'B', new VersionConstraint('>=', '1.0'), 'conflicts'), + new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'conflicts'), )); $this->reposComplete(); @@ -547,7 +547,7 @@ class SolverTest extends TestCase $this->repo->addPackage($packageB = $this->getPackage('B', '1.0')); $packageA->setRequires(array( - new Link('A', 'B', new VersionConstraint('>=', '2.0'), 'requires'), + new Link('A', 'B', $this->getVersionConstraint('>=', '2.0'), 'requires'), )); $this->reposComplete(); diff --git a/tests/Composer/Test/TestCase.php b/tests/Composer/Test/TestCase.php index 05a788517..1e3ae257e 100644 --- a/tests/Composer/Test/TestCase.php +++ b/tests/Composer/Test/TestCase.php @@ -27,6 +27,14 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase } } + protected function getVersionConstraint($operator, $version) + { + return new VersionConstraint( + $operator, + self::$versionParser->normalize($version) + ); + } + protected function getPackage($name, $version) { $normVersion = self::$versionParser->normalize($version); From 32157a39047a2cfd50bee69d571e5365a4728fc4 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 19 Feb 2012 16:38:07 +0100 Subject: [PATCH 37/42] Fix local git repo handling in GitDriver --- src/Composer/Repository/Vcs/GitDriver.php | 46 ++++++++++++++++++----- src/Composer/Repository/Vcs/VcsDriver.php | 5 +++ 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index 8a8d1f8c6..e99a0e5f8 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -15,6 +15,7 @@ class GitDriver extends VcsDriver implements VcsDriverInterface protected $branches; protected $rootIdentifier; protected $infoCache = array(); + protected $isLocal = false; public function __construct($url, IOInterface $io, ProcessExecutor $process = null) { @@ -30,10 +31,15 @@ class GitDriver extends VcsDriver implements VcsDriverInterface { $url = escapeshellarg($this->url); $tmpDir = escapeshellarg($this->tmpDir); - if (is_dir($this->tmpDir)) { - $this->process->execute(sprintf('cd %s && git fetch origin', $tmpDir), $output); + + if (static::isLocalUrl($url)) { + $this->isLocal = true; } else { - $this->process->execute(sprintf('git clone %s %s', $url, $tmpDir), $output); + if (is_dir($this->tmpDir)) { + $this->process->execute(sprintf('cd %s && git fetch origin', $tmpDir), $output); + } else { + $this->process->execute(sprintf('git clone %s %s', $url, $tmpDir), $output); + } } $this->getTags(); @@ -47,11 +53,27 @@ class GitDriver extends VcsDriver implements VcsDriverInterface { if (null === $this->rootIdentifier) { $this->rootIdentifier = 'master'; - $this->process->execute(sprintf('cd %s && git branch --no-color -r', escapeshellarg($this->tmpDir)), $output); - foreach ($this->process->splitLines($output) as $branch) { - if ($branch && preg_match('{/HEAD +-> +[^/]+/(\S+)}', $branch, $match)) { - $this->rootIdentifier = $match[1]; - break; + + if ($this->isLocal) { + // select currently checked out branch if master is not available + $this->process->execute(sprintf('cd %s && git branch --no-color', escapeshellarg($this->tmpDir)), $output); + $branches = $this->process->splitLines($output); + if (!in_array('* master', $branches)) { + foreach ($branches as $branch) { + if ($branch && preg_match('{^\* +(\S+)}', $branch, $match)) { + $this->rootIdentifier = $match[1]; + break; + } + } + } + } else { + // try to find a non-master remote HEAD branch + $this->process->execute(sprintf('cd %s && git branch --no-color -r', escapeshellarg($this->tmpDir)), $output); + foreach ($this->process->splitLines($output) as $branch) { + if ($branch && preg_match('{/HEAD +-> +[^/]+/(\S+)}', $branch, $match)) { + $this->rootIdentifier = $match[1]; + break; + } } } } @@ -132,7 +154,11 @@ class GitDriver extends VcsDriver implements VcsDriverInterface if (null === $this->branches) { $branches = array(); - $this->process->execute(sprintf('cd %s && git branch --no-color -rv', escapeshellarg($this->tmpDir)), $output); + $this->process->execute(sprintf( + 'cd %s && git branch --no-color --no-abbrev -v %s', + escapeshellarg($this->tmpDir), + $this->isLocal ? '' : '-r' + ), $output); foreach ($this->process->splitLines($output) as $branch) { if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) { preg_match('{^ *[^/]+/(\S+) *([a-f0-9]+) .*$}', $branch, $match); @@ -170,7 +196,7 @@ class GitDriver extends VcsDriver implements VcsDriverInterface } // local filesystem - if (preg_match('{^(file://|/|[a-z]:[\\\\/])}i', $url)) { + if (static::isLocalUrl($url)) { $process = new ProcessExecutor(); // check whether there is a git repo in that path if ($process->execute(sprintf('cd %s && git show', escapeshellarg($url)), $output) === 0) { diff --git a/src/Composer/Repository/Vcs/VcsDriver.php b/src/Composer/Repository/Vcs/VcsDriver.php index 7008f41be..75b631a42 100644 --- a/src/Composer/Repository/Vcs/VcsDriver.php +++ b/src/Composer/Repository/Vcs/VcsDriver.php @@ -68,4 +68,9 @@ abstract class VcsDriver $rfs = new RemoteFilesystem($this->io); return $rfs->getContents($this->url, $url, false); } + + protected static function isLocalUrl($url) + { + return (Boolean) preg_match('{^(file://|/|[a-z]:[\\\\/])}i', $url); + } } From 3e1749fbad5df859ad0a8a31abfed0a103f92c05 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sun, 19 Feb 2012 16:59:04 +0100 Subject: [PATCH 38/42] Readd update-all jobs and make them available through the request --- src/Composer/DependencyResolver/Request.php | 5 +++++ src/Composer/DependencyResolver/Solver.php | 8 ++++++++ .../Test/DependencyResolver/RequestTest.php | 12 +++++++++++ .../Test/DependencyResolver/SolverTest.php | 20 +++++++++++++++++++ 4 files changed, 45 insertions(+) diff --git a/src/Composer/DependencyResolver/Request.php b/src/Composer/DependencyResolver/Request.php index 201caa1d3..3d1b28448 100644 --- a/src/Composer/DependencyResolver/Request.php +++ b/src/Composer/DependencyResolver/Request.php @@ -55,6 +55,11 @@ class Request ); } + public function updateAll() + { + $this->jobs[] = array('cmd' => 'update-all', 'packages' => array()); + } + public function getJobs() { return $this->jobs; diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index b5bc5cac2..1268a0040 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -952,6 +952,14 @@ class Solver break; } } + + switch ($job['cmd']) { + case 'update-all': + foreach ($installedPackages as $package) { + $this->updateMap[$package->getId()] = true; + } + break; + } } foreach ($installedPackages as $package) { diff --git a/tests/Composer/Test/DependencyResolver/RequestTest.php b/tests/Composer/Test/DependencyResolver/RequestTest.php index da186edb2..e5010e0e4 100644 --- a/tests/Composer/Test/DependencyResolver/RequestTest.php +++ b/tests/Composer/Test/DependencyResolver/RequestTest.php @@ -46,4 +46,16 @@ class RequestTest extends TestCase ), $request->getJobs()); } + + public function testUpdateAll() + { + $pool = new Pool; + $request = new Request($pool); + + $request->updateAll(); + + $this->assertEquals( + array(array('cmd' => 'update-all', 'packages' => array())), + $request->getJobs()); + } } diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index e913dc2a8..28ab91851 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -165,6 +165,26 @@ class SolverTest extends TestCase )); } + public function testSolverUpdateAll() + { + $this->repoInstalled->addPackage($packageA = $this->getPackage('A', '1.0')); + $this->repoInstalled->addPackage($packageB = $this->getPackage('B', '1.0')); + $this->repo->addPackage($newPackageA = $this->getPackage('A', '1.1')); + $this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1')); + + $packageA->setRequires(array(new Link('A', 'B', null, 'requires'))); + + $this->reposComplete(); + + $this->request->install('A'); + $this->request->updateAll(); + + $this->checkSolverResult(array( + array('job' => 'update', 'from' => $packageB, 'to' => $newPackageB), + array('job' => 'update', 'from' => $packageA, 'to' => $newPackageA), + )); + } + public function testSolverUpdateCurrent() { $this->repoInstalled->addPackage($this->getPackage('A', '1.0')); From 509188c112b9117cb7ab30d1a9e03dd4d69f28ce Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sun, 19 Feb 2012 17:14:11 +0100 Subject: [PATCH 39/42] Use updateAll request method in upddate mode in install command --- src/Composer/Command/InstallCommand.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index d656ad5d1..d6f60028b 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -119,14 +119,9 @@ EOT $installedPackages = $installedRepo->getPackages(); $links = $this->collectLinks($composer->getPackage(), $noInstallRecommends, $installSuggests); - foreach ($links as $link) { - foreach ($installedPackages as $package) { - if ($package->getName() === $link->getTarget()) { - $request->update($package->getName(), new VersionConstraint('=', $package->getVersion())); - break; - } - } + $request->updateAll(); + foreach ($links as $link) { $request->install($link->getTarget(), $link->getConstraint()); } } elseif ($composer->getLocker()->isLocked()) { From ab51095f4ca46093b225a03eed43be2bb8210c36 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 19 Feb 2012 18:11:21 +0100 Subject: [PATCH 40/42] Add scripts to json schema --- doc/composer-schema.json | 46 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/doc/composer-schema.json b/doc/composer-schema.json index 2545a8d4b..44ac9e6e7 100644 --- a/doc/composer-schema.json +++ b/doc/composer-schema.json @@ -121,6 +121,52 @@ "type": ["object", "array"], "description": "A set of additional repositories where packages can be found.", "additionalProperties": true + }, + "scripts": { + "type": ["object"], + "description": "Scripts listeners that will be executed before/after some events.", + "properties": { + "pre-install-cmd": { + "type": ["array", "string"], + "description": "Occurs before the install command is executed, contains one or more Class::method callables.", + }, + "post-install-cmd": { + "type": ["array", "string"], + "description": "Occurs after the install command is executed, contains one or more Class::method callables.", + }, + "pre-update-cmd": { + "type": ["array", "string"], + "description": "Occurs before the update command is executed, contains one or more Class::method callables.", + }, + "post-update-cmd": { + "type": ["array", "string"], + "description": "Occurs after the update command is executed, contains one or more Class::method callables.", + }, + "pre-package-install": { + "type": ["array", "string"], + "description": "Occurs before a package is installed, contains one or more Class::method callables.", + }, + "post-package-install": { + "type": ["array", "string"], + "description": "Occurs after a package is installed, contains one or more Class::method callables.", + }, + "pre-package-update": { + "type": ["array", "string"], + "description": "Occurs before a package is updated, contains one or more Class::method callables.", + }, + "post-package-update": { + "type": ["array", "string"], + "description": "Occurs after a package is updated, contains one or more Class::method callables.", + }, + "pre-package-uninstall": { + "type": ["array", "string"], + "description": "Occurs before a package has been uninstalled, contains one or more Class::method callables.", + }, + "post-package-uninstall": { + "type": ["array", "string"], + "description": "Occurs after a package has been uninstalled, contains one or more Class::method callables.", + } + } } } } From 0cb02cf3cae61363c6162cc4d8c338bc9269740f Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 19 Feb 2012 18:24:27 +0100 Subject: [PATCH 41/42] Add config in composer json schema --- doc/composer-schema.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/composer-schema.json b/doc/composer-schema.json index 44ac9e6e7..22311105d 100644 --- a/doc/composer-schema.json +++ b/doc/composer-schema.json @@ -101,6 +101,20 @@ "description": "This is a hash of package name (keys) and version constraints (values) that this package suggests work well with it (typically this will only be suggested to the user).", "additionalProperties": true }, + "config": { + "type": ["object"], + "description": "Composer options.", + "properties": { + "vendor-dir": { + "type": "string", + "description": "The location where all packages are installed, defaults to \"vendor\"." + }, + "bin-dir": { + "type": "string", + "description": "The location where all binaries are linked, defaults to \"vendor/bin\"." + } + } + }, "extra": { "type": ["object", "array"], "description": "Arbitrary extra data that can be used by custom installers, for example, package of type composer-installer must have a 'class' key defining the installer class name.", From ff620afe0585e9ad38ea5f74b50b18656308ce71 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sun, 19 Feb 2012 18:57:03 +0100 Subject: [PATCH 42/42] Correct the parent path in the watch tree, after moving a rule out of the path --- src/Composer/DependencyResolver/Solver.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 1268a0040..e1d6575cd 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -1266,7 +1266,7 @@ class Solver } if ($prevRule) { - if ($prevRule->watch1 === $literal->getId()) { + if ($prevRule->next1 == $rule) { $prevRule->next1 = $nextRule; } else { $prevRule->next2 = $nextRule; @@ -1276,6 +1276,8 @@ class Solver } $this->watches[$ruleLiteral->getId()] = $rule; + + $rule = $prevRule; continue 2; } } @@ -1506,7 +1508,7 @@ class Solver } $why = count($this->learnedPool) - 1; - + assert($learnedLiterals[0] !== null); $newRule = new Rule($learnedLiterals, self::RULE_LEARNED, $why); return array($ruleLevel, $newRule, $why);