From 261a31c1498ee56ba651c3b842bf91e6d9b6cee7 Mon Sep 17 00:00:00 2001 From: Webber Wu Date: Wed, 7 Jan 2015 22:52:40 +0800 Subject: [PATCH 001/205] show change if package directory have changed to symbolic link --- src/Composer/Command/StatusCommand.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Composer/Command/StatusCommand.php b/src/Composer/Command/StatusCommand.php index 65662c048..272b3e9d3 100644 --- a/src/Composer/Command/StatusCommand.php +++ b/src/Composer/Command/StatusCommand.php @@ -68,6 +68,10 @@ EOT if ($downloader instanceof ChangeReportInterface) { $targetDir = $im->getInstallPath($package); + if (is_link($targetDir)) { + $errors[$targetDir] = $targetDir . ' is a symbolic link.'; + } + if ($changes = $downloader->getLocalChanges($package, $targetDir)) { $errors[$targetDir] = $changes; } From 1cba63cc0a321938bdfd228c7c5c85dc327a5f54 Mon Sep 17 00:00:00 2001 From: nevvermind Date: Sat, 6 Jun 2015 11:06:14 +0100 Subject: [PATCH 002/205] fix typo + better express order of events The fix here being more "occurs before a package has been uninstalled", which is incorrect. --- doc/articles/scripts.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index dec1fa06d..19a4fc4e2 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -47,10 +47,10 @@ Composer fires the following named events during its execution process: ### Package Events - **pre-package-install**: occurs before a package is installed. -- **post-package-install**: occurs after a package is installed. +- **post-package-install**: occurs after a package has been installed. - **pre-package-update**: occurs before a package is updated. -- **post-package-update**: occurs after a package is updated. -- **pre-package-uninstall**: occurs before a package has been uninstalled. +- **post-package-update**: occurs after a package has been updated. +- **pre-package-uninstall**: occurs before a package is uninstalled. - **post-package-uninstall**: occurs after a package has been uninstalled. ### Plugin Events From a014a2f803dd4a4e76a954ee60ba51feb2a87975 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Sun, 7 Jun 2015 10:38:27 +0200 Subject: [PATCH 003/205] Optimize the regex detecting timestamps Using a possessive quantifier avoids useless backtracking. --- src/Composer/Package/Loader/ArrayLoader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Package/Loader/ArrayLoader.php b/src/Composer/Package/Loader/ArrayLoader.php index 60cff3b33..32c6ffbaf 100644 --- a/src/Composer/Package/Loader/ArrayLoader.php +++ b/src/Composer/Package/Loader/ArrayLoader.php @@ -147,7 +147,7 @@ class ArrayLoader implements LoaderInterface } if (!empty($config['time'])) { - $time = preg_match('/^\d+$/D', $config['time']) ? '@'.$config['time'] : $config['time']; + $time = preg_match('/^\d++$/D', $config['time']) ? '@'.$config['time'] : $config['time']; try { $date = new \DateTime($time, new \DateTimeZone('UTC')); From 222ee004e0dc11ae299fd71bfd1bc1d672798959 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 9 Jun 2015 09:02:32 +0200 Subject: [PATCH 004/205] modified test case --- .../Test/EventDispatcher/EventDispatcherTest.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php index 06d9c652d..a40c6684d 100644 --- a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php +++ b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php @@ -150,12 +150,12 @@ class EventDispatcherTest extends TestCase ); } - public function testDispatcherOutputsCommands() + public function testDispatcherOutputsCommandsInVerboseMode() { $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') ->setConstructorArgs(array( $this->getMock('Composer\Composer'), - $this->getMock('Composer\IO\IOInterface'), + $io = $this->getMock('Composer\IO\IOInterface'), new ProcessExecutor, )) ->setMethods(array('getListeners')) @@ -166,6 +166,14 @@ class EventDispatcherTest extends TestCase ->method('getListeners') ->will($this->returnValue($listener)); + $io->expects($this->once()) + ->method('isVerbose') + ->willReturn(true); + + $io->expects($this->once()) + ->method('writeError') + ->with($this->equalTo('> echo foo')); + ob_start(); $dispatcher->dispatchScript(ScriptEvents::POST_INSTALL_CMD, false); $this->assertEquals('foo', trim(ob_get_clean())); From cbd61660ab26201a2a3e2a4a54328b1b79c81a72 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 9 Jun 2015 09:02:43 +0200 Subject: [PATCH 005/205] implemented verbose output --- src/Composer/EventDispatcher/EventDispatcher.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index 3bb1c8496..e96d47a81 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -170,8 +170,12 @@ class EventDispatcher throw $e; } } else { - $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor','escape'), $event->getArguments())); - if (0 !== ($exitCode = $this->process->execute($callable . ($args === '' ? '' : ' '.$args)))) { + $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor', 'escape'), $event->getArguments())); + $exec = $callable . ($args === '' ? '' : ' '.$args); + if ($this->io->isVerbose()) { + $this->io->writeError(sprintf('> %s', $exec)); + } + if (0 !== ($exitCode = $this->process->execute($exec))) { $this->io->writeError(sprintf('Script %s handling the %s event returned with an error', $callable, $event->getName())); throw new \RuntimeException('Error Output: '.$this->process->getErrorOutput(), $exitCode); From 9223f4a208213a1abde76fb5a6dcf8b403b9ab17 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 9 Jun 2015 13:40:13 +0200 Subject: [PATCH 006/205] show command by default --- src/Composer/EventDispatcher/EventDispatcher.php | 4 +--- .../Test/EventDispatcher/EventDispatcherTest.php | 12 ++++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index e96d47a81..65d6ea700 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -172,9 +172,7 @@ class EventDispatcher } else { $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor', 'escape'), $event->getArguments())); $exec = $callable . ($args === '' ? '' : ' '.$args); - if ($this->io->isVerbose()) { - $this->io->writeError(sprintf('> %s', $exec)); - } + $this->io->writeError(sprintf('> %s', $exec)); if (0 !== ($exitCode = $this->process->execute($exec))) { $this->io->writeError(sprintf('Script %s handling the %s event returned with an error', $callable, $event->getName())); diff --git a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php index a40c6684d..9b5604591 100644 --- a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php +++ b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php @@ -150,7 +150,7 @@ class EventDispatcherTest extends TestCase ); } - public function testDispatcherOutputsCommandsInVerboseMode() + public function testDispatcherOutputsCommand() { $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') ->setConstructorArgs(array( @@ -166,10 +166,6 @@ class EventDispatcherTest extends TestCase ->method('getListeners') ->will($this->returnValue($listener)); - $io->expects($this->once()) - ->method('isVerbose') - ->willReturn(true); - $io->expects($this->once()) ->method('writeError') ->with($this->equalTo('> echo foo')); @@ -196,7 +192,11 @@ class EventDispatcherTest extends TestCase ->method('getListeners') ->will($this->returnValue($listener)); - $io->expects($this->once()) + $io->expects($this->at(0)) + ->method('writeError') + ->willReturn('> exit 1'); + + $io->expects($this->at(1)) ->method('writeError') ->with($this->equalTo('Script '.$code.' handling the post-install-cmd event returned with an error')); From 5146085dc26b360bd68592152fb9d5d21f85cc66 Mon Sep 17 00:00:00 2001 From: Branden Cash Date: Wed, 10 Jun 2015 11:46:08 -0700 Subject: [PATCH 007/205] Follow symlinks when searching for artifacts --- src/Composer/Repository/ArtifactRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/ArtifactRepository.php b/src/Composer/Repository/ArtifactRepository.php index 2bb518b8f..082ae364b 100644 --- a/src/Composer/Repository/ArtifactRepository.php +++ b/src/Composer/Repository/ArtifactRepository.php @@ -48,7 +48,7 @@ class ArtifactRepository extends ArrayRepository { $io = $this->io; - $directory = new \RecursiveDirectoryIterator($path); + $directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS); $iterator = new \RecursiveIteratorIterator($directory); $regex = new \RegexIterator($iterator, '/^.+\.(zip|phar)$/i'); foreach ($regex as $file) { From 50b560fe4c6a618930ecfcd5339736b4ef07284e Mon Sep 17 00:00:00 2001 From: Zsolt Szeberenyi Date: Fri, 12 Jun 2015 22:24:31 +0200 Subject: [PATCH 008/205] Add the hash of the parsed content of the composer.json to the lock file, and use it to verify the json is not changed --- src/Composer/Factory.php | 16 +++++++- src/Composer/Package/Locker.php | 11 ++++- tests/Composer/Test/InstallerTest.php | 4 +- tests/Composer/Test/Package/LockerTest.php | 47 ++++++++++++++++++---- 4 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 6f9a5da36..755b8884f 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -306,7 +306,7 @@ class Factory $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION) ? substr($composerFile, 0, -4).'lock' : $composerFile . '.lock'; - $locker = new Package\Locker($io, new JsonFile($lockFile, new RemoteFilesystem($io, $config)), $rm, $im, md5_file($composerFile)); + $locker = new Package\Locker($io, new JsonFile($lockFile, new RemoteFilesystem($io, $config)), $rm, $im, md5_file($composerFile), $this->getContentHash($composerFile)); $composer->setLocker($locker); } @@ -485,4 +485,18 @@ class Factory return $factory->createComposer($io, $config, $disablePlugins); } + + /** + * Returns the md5 hash of the sorted content of the composer file. + * + * @param string $composerFilePath Path to the composer file. + * + * @return string + */ + private function getContentHash($composerFilePath) + { + $content = json_decode(file_get_contents($composerFilePath), true); + ksort($content); + return md5(json_encode($content)); + } } diff --git a/src/Composer/Package/Locker.php b/src/Composer/Package/Locker.php index 9f9a0abf8..ef5e4fc75 100644 --- a/src/Composer/Package/Locker.php +++ b/src/Composer/Package/Locker.php @@ -35,6 +35,7 @@ class Locker private $repositoryManager; private $installationManager; private $hash; + private $contentHash; private $loader; private $dumper; private $process; @@ -48,13 +49,15 @@ class Locker * @param RepositoryManager $repositoryManager repository manager instance * @param InstallationManager $installationManager installation manager instance * @param string $hash unique hash of the current composer configuration + * @param string $contentHash unique hash of the content of the current composer configuration */ - public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $hash) + public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $hash, $contentHash) { $this->lockFile = $lockFile; $this->repositoryManager = $repositoryManager; $this->installationManager = $installationManager; $this->hash = $hash; + $this->contentHash = $contentHash; $this->loader = new ArrayLoader(null, true); $this->dumper = new ArrayDumper(); $this->process = new ProcessExecutor($io); @@ -85,6 +88,11 @@ class Locker { $lock = $this->lockFile->read(); + if (!empty($lock['content-hash'])) { + // There is a content hash key, use that instead of the file hash + return $this->contentHash == $lock['content-hash']; + } + return $this->hash === $lock['hash']; } @@ -241,6 +249,7 @@ class Locker 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file', 'This file is @gener'.'ated automatically'), 'hash' => $this->hash, + 'content-hash' => $this->contentHash, 'packages' => null, 'packages-dev' => null, 'aliases' => array(), diff --git a/tests/Composer/Test/InstallerTest.php b/tests/Composer/Test/InstallerTest.php index 7fa85d76d..0a1dff0e4 100644 --- a/tests/Composer/Test/InstallerTest.php +++ b/tests/Composer/Test/InstallerTest.php @@ -191,7 +191,8 @@ class InstallerTest extends TestCase })); } - $locker = new Locker($io, $lockJsonMock, $repositoryManager, $composer->getInstallationManager(), md5(json_encode($composerConfig))); + $hash = md5(json_encode($composerConfig)); + $locker = new Locker($io, $lockJsonMock, $repositoryManager, $composer->getInstallationManager(), $hash, $hash); $composer->setLocker($locker); $eventDispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')->disableOriginalConstructor()->getMock(); @@ -237,6 +238,7 @@ class InstallerTest extends TestCase if ($expectLock) { unset($actualLock['hash']); + unset($actualLock['content-hash']); unset($actualLock['_readme']); $this->assertEquals($expectLock, $actualLock); } diff --git a/tests/Composer/Test/Package/LockerTest.php b/tests/Composer/Test/Package/LockerTest.php index 914bbe2f9..6d0937ef1 100644 --- a/tests/Composer/Test/Package/LockerTest.php +++ b/tests/Composer/Test/Package/LockerTest.php @@ -20,7 +20,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase public function testIsLocked() { $json = $this->createJsonFileMock(); - $locker = new Locker(new NullIO, $json, $this->createRepositoryManagerMock(), $this->createInstallationManagerMock(), 'md5'); + $locker = new Locker(new NullIO, $json, $this->createRepositoryManagerMock(), $this->createInstallationManagerMock(), 'md5', 'contentMd5'); $json ->expects($this->any()) @@ -40,7 +40,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase $repo = $this->createRepositoryManagerMock(); $inst = $this->createInstallationManagerMock(); - $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5'); + $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5'); $json ->expects($this->once()) @@ -58,7 +58,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase $repo = $this->createRepositoryManagerMock(); $inst = $this->createInstallationManagerMock(); - $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5'); + $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5'); $json ->expects($this->once()) @@ -85,7 +85,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase $repo = $this->createRepositoryManagerMock(); $inst = $this->createInstallationManagerMock(); - $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5'); + $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5'); $package1 = $this->createPackageMock(); $package2 = $this->createPackageMock(); @@ -124,6 +124,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file', 'This file is @gener'.'ated automatically'), 'hash' => 'md5', + 'content-hash' => 'contentMd5', 'packages' => array( array('name' => 'pkg1', 'version' => '1.0.0-beta'), array('name' => 'pkg2', 'version' => '0.1.10') @@ -148,7 +149,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase $repo = $this->createRepositoryManagerMock(); $inst = $this->createInstallationManagerMock(); - $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5'); + $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'md5'); $package1 = $this->createPackageMock(); $package1 @@ -167,7 +168,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase $repo = $this->createRepositoryManagerMock(); $inst = $this->createInstallationManagerMock(); - $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5'); + $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5'); $json ->expects($this->once()) @@ -183,7 +184,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase $repo = $this->createRepositoryManagerMock(); $inst = $this->createInstallationManagerMock(); - $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5'); + $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5'); $json ->expects($this->once()) @@ -193,6 +194,38 @@ class LockerTest extends \PHPUnit_Framework_TestCase $this->assertFalse($locker->isFresh()); } + public function testIsFreshWithContentHash() + { + $json = $this->createJsonFileMock(); + $repo = $this->createRepositoryManagerMock(); + $inst = $this->createInstallationManagerMock(); + + $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5'); + + $json + ->expects($this->once()) + ->method('read') + ->will($this->returnValue(array('hash' => 'oldMd5', 'content-hash' => 'contentMd5'))); + + $this->assertTrue($locker->isFresh()); + } + + public function testIsFreshFalseWithContentHash() + { + $json = $this->createJsonFileMock(); + $repo = $this->createRepositoryManagerMock(); + $inst = $this->createInstallationManagerMock(); + + $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5'); + + $json + ->expects($this->once()) + ->method('read') + ->will($this->returnValue(array('hash' => 'md5', 'content-hash' => 'oldMd5'))); + + $this->assertFalse($locker->isFresh()); + } + private function createJsonFileMock() { return $this->getMockBuilder('Composer\Json\JsonFile') From 3e0219c4384465bc0f66369817426e3baa103583 Mon Sep 17 00:00:00 2001 From: Zsolt Szeberenyi Date: Sat, 13 Jun 2015 10:15:56 +0200 Subject: [PATCH 009/205] Change the content hash to be only based on values that affect dependency resolution --- src/Composer/Factory.php | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 755b8884f..d14cee7bd 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -496,7 +496,26 @@ class Factory private function getContentHash($composerFilePath) { $content = json_decode(file_get_contents($composerFilePath), true); - ksort($content); - return md5(json_encode($content)); + + $relevantKeys = array( + 'require', + 'require-dev', + 'conflict', + 'replace', + 'provide', + 'suggest', + 'minimum-stability', + 'prefer-stable', + 'repositories', + ); + + $relevantContent = array(); + + foreach (array_intersect($relevantKeys, array_keys($content)) as $key) { + $relevantContent[$key] = $content[$key]; + } + + ksort($relevantContent); + return md5(json_encode($relevantContent)); } } From a4ad3c2146925e02d37de4115c2eacf3eaccb54b Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 14 Jun 2015 10:13:18 +0200 Subject: [PATCH 010/205] Dropped obsolete condition The conditional a few lines above already checks for `bytesMax > 0` --- src/Composer/Util/RemoteFilesystem.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php index 65367dad1..6788182e5 100644 --- a/src/Composer/Util/RemoteFilesystem.php +++ b/src/Composer/Util/RemoteFilesystem.php @@ -326,11 +326,7 @@ class RemoteFilesystem case STREAM_NOTIFY_PROGRESS: if ($this->bytesMax > 0 && $this->progress) { - $progression = 0; - - if ($this->bytesMax > 0) { - $progression = round($bytesTransferred / $this->bytesMax * 100); - } + $progression = round($bytesTransferred / $this->bytesMax * 100); if ((0 === $progression % 5) && 100 !== $progression && $progression !== $this->lastProgress) { $this->lastProgress = $progression; From 94a924b702ce6a35e34ef32fa7b49e8886cd8677 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 14 Jun 2015 10:16:45 +0200 Subject: [PATCH 011/205] Dropped unnecessary break statements Next line breaks nevertheless --- src/Composer/Util/RemoteFilesystem.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php index 65367dad1..ed5995050 100644 --- a/src/Composer/Util/RemoteFilesystem.php +++ b/src/Composer/Util/RemoteFilesystem.php @@ -302,7 +302,6 @@ class RemoteFilesystem } $this->promptAuthAndRetry($messageCode); - break; } break; @@ -314,7 +313,6 @@ class RemoteFilesystem } $this->promptAuthAndRetry($messageCode, $message); - break; } break; From 9b50ca01614f8aa2c8f5e0fcc2d0f7eaf8d75b54 Mon Sep 17 00:00:00 2001 From: Zsolt Szeberenyi Date: Mon, 15 Jun 2015 11:31:33 +0200 Subject: [PATCH 012/205] Add the extra attribute to the content hash --- src/Composer/Factory.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index d14cee7bd..8a2a6a815 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -507,6 +507,7 @@ class Factory 'minimum-stability', 'prefer-stable', 'repositories', + 'extra', ); $relevantContent = array(); From c350bceeea660f49f92f033170aea35fae7333f2 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Sun, 21 Jun 2015 07:46:08 +0200 Subject: [PATCH 013/205] Set this test as slow --- tests/Composer/Test/Util/RemoteFilesystemTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/Composer/Test/Util/RemoteFilesystemTest.php b/tests/Composer/Test/Util/RemoteFilesystemTest.php index 04502ebdc..62a70c901 100644 --- a/tests/Composer/Test/Util/RemoteFilesystemTest.php +++ b/tests/Composer/Test/Util/RemoteFilesystemTest.php @@ -137,6 +137,9 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase $this->assertNull($this->callCallbackGet($fs, STREAM_NOTIFY_FAILURE, 0, 'HTTP/1.1 404 Not Found', 404, 0, 0)); } + /** + * @group slow + */ public function testCaptureAuthenticationParamsFromUrl() { $io = $this->getMock('Composer\IO\IOInterface'); From f1af16984e44aa4e04a416f26eb2973a2449784f Mon Sep 17 00:00:00 2001 From: Gusakov Nikita Date: Mon, 17 Mar 2014 15:26:19 +0400 Subject: [PATCH 014/205] [Command] Add suggests command --- doc/03-cli.md | 11 +++++ src/Composer/Command/SuggestsCommand.php | 59 ++++++++++++++++++++++++ src/Composer/Console/Application.php | 1 + 3 files changed, 71 insertions(+) create mode 100644 src/Composer/Command/SuggestsCommand.php diff --git a/doc/03-cli.md b/doc/03-cli.md index b8921511c..8c5bf2f05 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -294,6 +294,17 @@ in your browser. * **--homepage (-H):** Open the homepage instead of the repository URL. +## suggests + +To list all of vendors suggesting to install packages, you can use the `suggests` command. + + $ php composer.phar suggests + + +### Options + +* **--dev:** Show dev suggests. + ## depends The `depends` command tells you which other packages depend on a certain diff --git a/src/Composer/Command/SuggestsCommand.php b/src/Composer/Command/SuggestsCommand.php new file mode 100644 index 000000000..18e3cf788 --- /dev/null +++ b/src/Composer/Command/SuggestsCommand.php @@ -0,0 +1,59 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Command; + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Gusakov Nikita + */ +class SuggestsCommand extends Command +{ + protected function configure() + { + $this + ->setName('suggests') + ->setDescription('Show packages suggests') + ->setDefinition(array( + new InputOption('dev', null, InputOption::VALUE_NONE, 'Show dev suggests'), + )) + ->setHelp(<<suggests command show packages that suggesting to install other packages. + +EOT + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $lockData = $this->getComposer()->getLocker()->getLockData(); + $this->printSuggests($output, $lockData['packages']); + if ($input->getOption('dev')) { + $this->printSuggests($output, $lockData['packages-dev']); + } + } + + private function printSuggests(OutputInterface $output, array $packages) + { + foreach ($packages as $package) { + if (isset($package['suggest'])) { + foreach ($package['suggest'] as $target => $reason) { + $output->writeln($package['name'].' suggests installing '.$target.' ('.$reason.')'); + } + } + } + } +} diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index ee4f4e9c0..62654bf8b 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -272,6 +272,7 @@ class Application extends BaseApplication $commands[] = new Command\SearchCommand(); $commands[] = new Command\ValidateCommand(); $commands[] = new Command\ShowCommand(); + $commands[] = new Command\SuggestsCommand(); $commands[] = new Command\RequireCommand(); $commands[] = new Command\DumpAutoloadCommand(); $commands[] = new Command\StatusCommand(); From 760eeb0b033c328462093d8440d40aff46726183 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 23 Jun 2015 21:04:06 +0200 Subject: [PATCH 015/205] reworked suggests command --- doc/03-cli.md | 7 ++-- src/Composer/Command/SuggestsCommand.php | 45 +++++++++++++++--------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index 8c5bf2f05..5b6e0fb00 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -296,14 +296,11 @@ in your browser. ## suggests -To list all of vendors suggesting to install packages, you can use the `suggests` command. - - $ php composer.phar suggests - +Lists all packages suggested by currently installed set of packages. ### Options -* **--dev:** Show dev suggests. +* **--no-dev:** Exludes suggestions from `require-dev` packages. ## depends diff --git a/src/Composer/Command/SuggestsCommand.php b/src/Composer/Command/SuggestsCommand.php index 18e3cf788..fd2193f9a 100644 --- a/src/Composer/Command/SuggestsCommand.php +++ b/src/Composer/Command/SuggestsCommand.php @@ -14,44 +14,57 @@ namespace Composer\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Finder\Exception\AccessDeniedException; -/** - * @author Gusakov Nikita - */ class SuggestsCommand extends Command { protected function configure() { $this ->setName('suggests') - ->setDescription('Show packages suggests') + ->setDescription('Show package suggestions') ->setDefinition(array( - new InputOption('dev', null, InputOption::VALUE_NONE, 'Show dev suggests'), + new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'), )) ->setHelp(<<suggests command show packages that suggesting to install other packages. +The %command.name% command shows suggested packages. EOT - ); + ) + ; } protected function execute(InputInterface $input, OutputInterface $output) { - $lockData = $this->getComposer()->getLocker()->getLockData(); - $this->printSuggests($output, $lockData['packages']); - if ($input->getOption('dev')) { - $this->printSuggests($output, $lockData['packages-dev']); + $lock = $this->getComposer()->getLocker()->getLockData(); + + if (empty($lock)) { + throw new \RuntimeException('Lockfile seems to be empty?'); + } + + $stderr = $output; + if ($output instanceof ConsoleOutputInterface) { + $stderr = $output->getErrorOutput(); + } + + $packages = $lock['packages']; + + if (!$input->getOption('no-dev')) { + $packages += $lock['packages-dev']; } - } - private function printSuggests(OutputInterface $output, array $packages) - { foreach ($packages as $package) { - if (isset($package['suggest'])) { + if (!empty($package['suggest'])) { + $stderr->writeln(sprintf('%s suggests:', $package['name'])); foreach ($package['suggest'] as $target => $reason) { - $output->writeln($package['name'].' suggests installing '.$target.' ('.$reason.')'); + if (empty($reason)) { + $reason = '*'; + } + + $output->writeln(sprintf('%s: %s', $target, $reason)); } } } From 33f78b2ccc3fa55ab1ec01d910c7456d8160f510 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 23 Jun 2015 21:29:48 +0200 Subject: [PATCH 016/205] limit suggestions to optional list of packages --- src/Composer/Command/SuggestsCommand.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Composer/Command/SuggestsCommand.php b/src/Composer/Command/SuggestsCommand.php index fd2193f9a..73e988beb 100644 --- a/src/Composer/Command/SuggestsCommand.php +++ b/src/Composer/Command/SuggestsCommand.php @@ -12,6 +12,7 @@ namespace Composer\Command; +use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\ConsoleOutputInterface; @@ -27,6 +28,7 @@ class SuggestsCommand extends Command ->setDescription('Show package suggestions') ->setDefinition(array( new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'), + new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.'), )) ->setHelp(<<getErrorOutput(); } - $packages = $lock['packages']; + $list = $lock['packages']; if (!$input->getOption('no-dev')) { - $packages += $lock['packages-dev']; + $list += $lock['packages-dev']; } - foreach ($packages as $package) { - if (!empty($package['suggest'])) { + $packages = $input->getArgument('packages'); + + foreach ($list as $package) { + if (!empty($package['suggest']) && (empty($packages) || in_array($package['name'], $packages))) { $stderr->writeln(sprintf('%s suggests:', $package['name'])); foreach ($package['suggest'] as $target => $reason) { if (empty($reason)) { From 680082c5fe54bf1afd40af3af7f312d1cea267fe Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 23 Jun 2015 22:03:35 +0200 Subject: [PATCH 017/205] output based purely on verbosity --- src/Composer/Command/SuggestsCommand.php | 34 ++++++++++++++---------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/Composer/Command/SuggestsCommand.php b/src/Composer/Command/SuggestsCommand.php index 73e988beb..13558b693 100644 --- a/src/Composer/Command/SuggestsCommand.php +++ b/src/Composer/Command/SuggestsCommand.php @@ -15,9 +15,7 @@ namespace Composer\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Finder\Exception\AccessDeniedException; class SuggestsCommand extends Command { @@ -47,11 +45,7 @@ EOT throw new \RuntimeException('Lockfile seems to be empty?'); } - $stderr = $output; - if ($output instanceof ConsoleOutputInterface) { - $stderr = $output->getErrorOutput(); - } - + $io = $this->getIO(); $list = $lock['packages']; if (!$input->getOption('no-dev')) { @@ -62,14 +56,26 @@ EOT foreach ($list as $package) { if (!empty($package['suggest']) && (empty($packages) || in_array($package['name'], $packages))) { - $stderr->writeln(sprintf('%s suggests:', $package['name'])); - foreach ($package['suggest'] as $target => $reason) { - if (empty($reason)) { - $reason = '*'; - } + $this->printSuggestions($package['name'], $package['suggest']); + } + } + } + + protected function printSuggestions($name, $suggests) + { + $io = $this->getIO(); + + foreach ($suggests as $target => $reason) { + if (empty($reason)) { + $reason = '*'; + } - $output->writeln(sprintf('%s: %s', $target, $reason)); - } + if ($io->isVeryVerbose()) { + $io->write(sprintf('%s suggests %s: %s', $name, $target, $reason)); + } elseif ($io->isVerbose()) { + $io->write(sprintf('%s suggests %s', $name, $target)); + } else { + $io->write(sprintf('%s', $target)); } } } From b523a226414738d4739eae423d151735406dd852 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 23 Jun 2015 22:44:02 +0200 Subject: [PATCH 018/205] updated doc --- doc/03-cli.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index 5b6e0fb00..db5f70dfa 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -296,11 +296,15 @@ in your browser. ## suggests -Lists all packages suggested by currently installed set of packages. +Lists all packages suggested by currently installed set of packages. You can +optionally pass one or multiple package names in the format of `vendor/package` +to limit output to suggestions made by those packages only. ### Options * **--no-dev:** Exludes suggestions from `require-dev` packages. +* **-v[v]:** Increased verbosity adds suggesting package name (`-v`) and + reason for suggestion (`-vv`). ## depends From adc3e3a7f29ff7be3e02f2ec8cd00dfb47855738 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Wed, 24 Jun 2015 08:43:07 +0200 Subject: [PATCH 019/205] fixed typo (and auto whitespace) --- doc/03-cli.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index db5f70dfa..6182db682 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -87,7 +87,7 @@ resolution. installing a package, you can use `--dry-run`. This will simulate the installation and show you what would happen. * **--dev:** Install packages listed in `require-dev` (this is the default behavior). -* **--no-dev:** Skip installing packages listed in `require-dev`. The autoloader +* **--no-dev:** Skip installing packages listed in `require-dev`. The autoloader generation skips the `autoload-dev` rules. * **--no-autoloader:** Skips autoloader generation. * **--no-scripts:** Skips execution of scripts defined in `composer.json`. @@ -302,7 +302,7 @@ to limit output to suggestions made by those packages only. ### Options -* **--no-dev:** Exludes suggestions from `require-dev` packages. +* **--no-dev:** Excludes suggestions from `require-dev` packages. * **-v[v]:** Increased verbosity adds suggesting package name (`-v`) and reason for suggestion (`-vv`). @@ -387,7 +387,7 @@ sudo composer self-update ### Options * **--rollback (-r):** Rollback to the last version you had installed. -* **--clean-backups:** Delete old backups during an update. This makes the +* **--clean-backups:** Delete old backups during an update. This makes the current version of Composer the only backup available after the update. ## config From 0a0f7f4db296f251f078f21a07206a2312faaafc Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Wed, 24 Jun 2015 08:58:03 +0200 Subject: [PATCH 020/205] 1.0.0 -> 1.1.0 --- CONTRIBUTING.md | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 786b92efd..b5a69bd00 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ Contributing to Composer ======================== Please note that this project is released with a -[Contributor Code of Conduct](http://contributor-covenant.org/version/1/0/0/). +[Contributor Code of Conduct](http://contributor-covenant.org/version/1/1/0/). By participating in this project you agree to abide by its terms. Reporting Issues diff --git a/README.md b/README.md index c7bcca110..13795e3a4 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Composer helps you declare, manage and install dependencies of PHP projects, ens See [https://getcomposer.org/](https://getcomposer.org/) for more information and documentation. [![Build Status](https://travis-ci.org/composer/composer.svg?branch=master)](https://travis-ci.org/composer/composer) -[![Dependency Status](https://www.versioneye.com/php/composer:composer/dev-master/badge.svg)](https://www.versioneye.com/php/composer:composer/dev-master) +[![Dependency Status](https://www.versioneye.com/php/composer:composer/dev-master/badge.svg)](https://www.versioneye.com/php/composer:composer/dev-master) [![Reference Status](https://www.versioneye.com/php/composer:composer/reference_badge.svg?style=flat)](https://www.versioneye.com/php/composer:composer/references) Installation / Usage @@ -56,7 +56,7 @@ For support, Stack Overflow also offers a good collection of [Composer related questions](https://stackoverflow.com/questions/tagged/composer-php). Please note that this project is released with a -[Contributor Code of Conduct](http://contributor-covenant.org/version/1/0/0/). +[Contributor Code of Conduct](http://contributor-covenant.org/version/1/1/0/). By participating in this project and its community you agree to abide by those terms. Requirements From fd34c5883afa4e5c0eb6fa70746c4ba406bfcdd8 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Wed, 24 Jun 2015 09:21:36 +0200 Subject: [PATCH 021/205] added php script handler info as well --- .../EventDispatcher/EventDispatcher.php | 2 ++ .../EventDispatcher/EventDispatcherTest.php | 25 +++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index 65d6ea700..7b70fb76c 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -197,6 +197,8 @@ class EventDispatcher { $event = $this->checkListenerExpectedEvent(array($className, $methodName), $event); + $this->io->writeError(sprintf('> %s::%s', $className, $methodName)); + return $className::$methodName($event); } diff --git a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php index 9b5604591..973827cec 100644 --- a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php +++ b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php @@ -32,7 +32,11 @@ class EventDispatcherTest extends TestCase 'Composer\Test\EventDispatcher\EventDispatcherTest::call' ), $io); - $io->expects($this->once()) + $io->expects($this->at(0)) + ->method('writeError') + ->with('> Composer\Test\EventDispatcher\EventDispatcherTest::call'); + + $io->expects($this->at(1)) ->method('writeError') ->with('Script Composer\Test\EventDispatcher\EventDispatcherTest::call handling the post-install-cmd event terminated with an exception'); @@ -94,12 +98,11 @@ class EventDispatcherTest extends TestCase $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') ->setConstructorArgs(array( $this->getMock('Composer\Composer'), - $this->getMock('Composer\IO\IOInterface'), + $io = $this->getMock('Composer\IO\IOInterface'), $process, )) ->setMethods(array( 'getListeners', - 'executeEventPhpScript', )) ->getMock(); @@ -112,14 +115,22 @@ class EventDispatcherTest extends TestCase 'Composer\\Test\\EventDispatcher\\EventDispatcherTest::someMethod', 'echo -n bar', ); + $dispatcher->expects($this->atLeastOnce()) ->method('getListeners') ->will($this->returnValue($listeners)); - $dispatcher->expects($this->once()) - ->method('executeEventPhpScript') - ->with('Composer\Test\EventDispatcher\EventDispatcherTest', 'someMethod') - ->will($this->returnValue(true)); + $io->expects($this->at(0)) + ->method('writeError') + ->with($this->equalTo('> echo -n foo')); + + $io->expects($this->at(1)) + ->method('writeError') + ->with($this->equalTo('> Composer\Test\EventDispatcher\EventDispatcherTest::someMethod')); + + $io->expects($this->at(2)) + ->method('writeError') + ->with($this->equalTo('> echo -n bar')); $dispatcher->dispatchScript(ScriptEvents::POST_INSTALL_CMD, false); } From 3dffdc8705b24f8535c676e36e4e4d061acc9531 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Wed, 24 Jun 2015 11:06:21 +0200 Subject: [PATCH 022/205] don't suggest packages already installed --- src/Composer/Command/SuggestsCommand.php | 50 ++++++++++++++++-------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/Composer/Command/SuggestsCommand.php b/src/Composer/Command/SuggestsCommand.php index 13558b693..c6f7385fd 100644 --- a/src/Composer/Command/SuggestsCommand.php +++ b/src/Composer/Command/SuggestsCommand.php @@ -45,38 +45,54 @@ EOT throw new \RuntimeException('Lockfile seems to be empty?'); } - $io = $this->getIO(); - $list = $lock['packages']; + $packages = $lock['packages']; if (!$input->getOption('no-dev')) { - $list += $lock['packages-dev']; + $packages += $lock['packages-dev']; } - $packages = $input->getArgument('packages'); + $filter = $input->getArgument('packages'); + + foreach ($packages as $package) { + if (empty($package['suggest'])) { + continue; + } - foreach ($list as $package) { - if (!empty($package['suggest']) && (empty($packages) || in_array($package['name'], $packages))) { - $this->printSuggestions($package['name'], $package['suggest']); + if (!empty($filter) && !in_array($package['name'], $filter)) { + continue; } + + $this->printSuggestions($packages, $package['name'], $package['suggest']); } } - protected function printSuggestions($name, $suggests) + protected function printSuggestions($installed, $source, $suggestions) { - $io = $this->getIO(); + foreach ($suggestions as $suggestion => $reason) { + foreach ($installed as $package) { + if ($package['name'] === $suggestion) { + continue 2; + } + } - foreach ($suggests as $target => $reason) { if (empty($reason)) { $reason = '*'; } - if ($io->isVeryVerbose()) { - $io->write(sprintf('%s suggests %s: %s', $name, $target, $reason)); - } elseif ($io->isVerbose()) { - $io->write(sprintf('%s suggests %s', $name, $target)); - } else { - $io->write(sprintf('%s', $target)); - } + $this->printSuggestion($source, $suggestion, $reason); + } + } + + protected function printSuggestion($package, $suggestion, $reason) + { + $io = $this->getIO(); + + if ($io->isVeryVerbose()) { + $io->write(sprintf('%s suggests %s: %s', $package, $suggestion, $reason)); + } elseif ($io->isVerbose()) { + $io->write(sprintf('%s suggests %s', $package, $suggestion)); + } else { + $io->write(sprintf('%s', $suggestion)); } } } From 943107cfe717a74aa791f57b87fa514c88582b0d Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 26 Jun 2015 13:50:02 +0100 Subject: [PATCH 023/205] Load most specific namespaces always, and dependents before dependencies when building classmaps This also adds notifications of duplicate classes --- src/Composer/Autoload/AutoloadGenerator.php | 35 +++++++++++++++++---- src/Composer/Autoload/ClassMapGenerator.php | 2 +- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 3df98f700..284150135 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -174,10 +174,21 @@ EOF; // flatten array $classMap = array(); if ($scanPsr0Packages) { + $namespacesToScan = array(); + // Scan the PSR-0/4 directories for class files, and add them to the class map foreach (array('psr-0', 'psr-4') as $psrType) { foreach ($autoloads[$psrType] as $namespace => $paths) { - foreach ($paths as $dir) { + $namespacesToScan[$namespace][] = array('paths' => $paths, 'type' => $psrType); + } + } + + krsort($namespacesToScan); + + foreach ($namespacesToScan as $namespace => $groups) { + foreach ($groups as $group) { + $psrType = $group['type']; + foreach ($group['paths'] as $dir) { $dir = $filesystem->normalizePath($filesystem->isAbsolutePath($dir) ? $dir : $basePath.'/'.$dir); if (!is_dir($dir)) { continue; @@ -190,9 +201,14 @@ EOF; $namespaceFilter = $namespace === '' ? null : $namespace; foreach (ClassMapGenerator::createMap($dir, $whitelist, $this->io, $namespaceFilter) as $class => $path) { + $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path); if (!isset($classMap[$class])) { - $path = $this->getPathCode($filesystem, $basePath, $vendorPath, $path); - $classMap[$class] = $path.",\n"; + $classMap[$class] = $pathCode.",\n"; + } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) { + $this->io->writeError( + 'Warning: Ambiguous class resolution, "'.$class.'"'. + ' was found in both "'.str_replace(array('$vendorDir . \'', "',\n"), array($vendorPath, ''), $classMap[$class]).'" and "'.$path.'", the first will be used.' + ); } } } @@ -202,8 +218,15 @@ EOF; foreach ($autoloads['classmap'] as $dir) { foreach (ClassMapGenerator::createMap($dir, null, $this->io) as $class => $path) { - $path = $this->getPathCode($filesystem, $basePath, $vendorPath, $path); - $classMap[$class] = $path.",\n"; + $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path); + if (!isset($classMap[$class])) { + $classMap[$class] = $pathCode.",\n"; + } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) { + $this->io->writeError( + 'Warning: Ambiguous class resolution, "'.$class.'"'. + ' was found in both "'.str_replace(array('$vendorDir . \'', "',\n"), array($vendorPath, ''), $classMap[$class]).'" and "'.$path.'", the first will be used.' + ); + } } } @@ -310,7 +333,7 @@ EOF; $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $mainPackage); $psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage); - $classmap = $this->parseAutoloadsType($sortedPackageMap, 'classmap', $mainPackage); + $classmap = $this->parseAutoloadsType(array_reverse($sortedPackageMap), 'classmap', $mainPackage); $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage); krsort($psr0); diff --git a/src/Composer/Autoload/ClassMapGenerator.php b/src/Composer/Autoload/ClassMapGenerator.php index 02b21bd40..e6ff636da 100644 --- a/src/Composer/Autoload/ClassMapGenerator.php +++ b/src/Composer/Autoload/ClassMapGenerator.php @@ -91,7 +91,7 @@ class ClassMapGenerator if (!isset($map[$class])) { $map[$class] = $filePath; - } elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) { + } elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) { $io->writeError( 'Warning: Ambiguous class resolution, "'.$class.'"'. ' was found in both "'.$map[$class].'" and "'.$filePath.'", the first will be used.' From 26a2e94e78340a00fc4d9ca9b945cb50b65880b7 Mon Sep 17 00:00:00 2001 From: Jonathan Eskew Date: Sat, 27 Jun 2015 14:38:09 -0700 Subject: [PATCH 024/205] Add a line and example to the documentation covering the need to require the autoloader file in order to use autoloaded files --- doc/articles/scripts.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index dec1fa06d..d7cdd7602 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -82,6 +82,8 @@ For any given event: and command-line executable commands. - PHP classes containing defined callbacks must be autoloadable via Composer's autoload functionality. +- If a defined callback relies on functions defined outside of a class, the callback +must explicitly require the composer autoloader. Script definition example: @@ -121,6 +123,14 @@ class MyClass $composer = $event->getComposer(); // do stuff } + + public static function postAutoloadDump(Event $event) + { + $vendorDir = $event->getComposer()->getConfig()->get('vendor-dir'); + require "$vendorDir/autoload.php"; + + some_function_from_an_autoloaded_file(); + } public static function postPackageInstall(PackageEvent $event) { From eac5fbdee43a5a018dd308ffbeb3c28585d99584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Mo=CC=88ller?= Date: Sun, 28 Jun 2015 23:20:54 -0400 Subject: [PATCH 025/205] Fix: Remove unused imports --- src/Composer/Command/HomeCommand.php | 1 - src/Composer/Config.php | 1 - src/Composer/Downloader/GitDownloader.php | 1 - src/Composer/IO/ConsoleIO.php | 1 - src/Composer/Installer/PackageEvent.php | 1 - src/Composer/Installer/PluginInstaller.php | 1 - src/Composer/Repository/ComposerRepository.php | 1 - src/Composer/Util/GitHub.php | 1 - 8 files changed, 8 deletions(-) diff --git a/src/Composer/Command/HomeCommand.php b/src/Composer/Command/HomeCommand.php index b20e661f9..e742cadf5 100644 --- a/src/Composer/Command/HomeCommand.php +++ b/src/Composer/Command/HomeCommand.php @@ -14,7 +14,6 @@ namespace Composer\Command; use Composer\Factory; use Composer\Package\CompletePackageInterface; -use Composer\Repository\CompositeRepository; use Composer\Repository\RepositoryInterface; use Composer\Repository\ArrayRepository; use Composer\Util\ProcessExecutor; diff --git a/src/Composer/Config.php b/src/Composer/Config.php index 49d477154..a6bb51b99 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -13,7 +13,6 @@ namespace Composer; use Composer\Config\ConfigSourceInterface; -use Composer\Plugin\PluginInterface; /** * @author Jordi Boggiano diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index a869e5b5a..f187ec9a7 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -13,7 +13,6 @@ namespace Composer\Downloader; use Composer\Package\PackageInterface; -use Composer\Util\GitHub; use Composer\Util\Git as GitUtil; use Composer\Util\ProcessExecutor; use Composer\IO\IOInterface; diff --git a/src/Composer/IO/ConsoleIO.php b/src/Composer/IO/ConsoleIO.php index 622e73ccf..e37b9f1ad 100644 --- a/src/Composer/IO/ConsoleIO.php +++ b/src/Composer/IO/ConsoleIO.php @@ -18,7 +18,6 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Helper\HelperSet; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Question\Question; -use Symfony\Component\Process\ExecutableFinder; /** * The Input/Output helper. diff --git a/src/Composer/Installer/PackageEvent.php b/src/Composer/Installer/PackageEvent.php index e1c5e6080..f5cf0ed6e 100644 --- a/src/Composer/Installer/PackageEvent.php +++ b/src/Composer/Installer/PackageEvent.php @@ -18,7 +18,6 @@ use Composer\DependencyResolver\Operation\OperationInterface; use Composer\DependencyResolver\PolicyInterface; use Composer\DependencyResolver\Pool; use Composer\DependencyResolver\Request; -use Composer\EventDispatcher\Event; use Composer\Repository\CompositeRepository; /** diff --git a/src/Composer/Installer/PluginInstaller.php b/src/Composer/Installer/PluginInstaller.php index ddb8e5bdd..b96a972be 100644 --- a/src/Composer/Installer/PluginInstaller.php +++ b/src/Composer/Installer/PluginInstaller.php @@ -13,7 +13,6 @@ namespace Composer\Installer; use Composer\Composer; -use Composer\Package\Package; use Composer\IO\IOInterface; use Composer\Repository\InstalledRepositoryInterface; use Composer\Package\PackageInterface; diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 1d3c2cd92..b0b3d2689 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -13,7 +13,6 @@ namespace Composer\Repository; use Composer\Package\Loader\ArrayLoader; -use Composer\Package\Package; use Composer\Package\PackageInterface; use Composer\Package\AliasPackage; use Composer\Package\Version\VersionParser; diff --git a/src/Composer/Util/GitHub.php b/src/Composer/Util/GitHub.php index 22c67c61b..369214e5d 100644 --- a/src/Composer/Util/GitHub.php +++ b/src/Composer/Util/GitHub.php @@ -15,7 +15,6 @@ namespace Composer\Util; use Composer\IO\IOInterface; use Composer\Config; use Composer\Downloader\TransportException; -use Composer\Json\JsonFile; /** * @author Jordi Boggiano From 3854d2d457adcc51352ecee30911cf9f8aa40cdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Mo=CC=88ller?= Date: Sun, 28 Jun 2015 23:25:55 -0400 Subject: [PATCH 026/205] Fix: Remove unused private property --- src/Composer/Installer/PluginInstaller.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Composer/Installer/PluginInstaller.php b/src/Composer/Installer/PluginInstaller.php index ddb8e5bdd..55945c671 100644 --- a/src/Composer/Installer/PluginInstaller.php +++ b/src/Composer/Installer/PluginInstaller.php @@ -27,7 +27,6 @@ use Composer\Package\PackageInterface; class PluginInstaller extends LibraryInstaller { private $installationManager; - private static $classCounter = 0; /** * Initializes Plugin installer. From e184118d76b7be88fbeda7133003e717adc2d33f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Mo=CC=88ller?= Date: Sun, 28 Jun 2015 23:28:45 -0400 Subject: [PATCH 027/205] Fix: Docblock --- src/Composer/DependencyResolver/RuleWatchNode.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/DependencyResolver/RuleWatchNode.php b/src/Composer/DependencyResolver/RuleWatchNode.php index cdbf6a00b..5cfd7d1e0 100644 --- a/src/Composer/DependencyResolver/RuleWatchNode.php +++ b/src/Composer/DependencyResolver/RuleWatchNode.php @@ -83,7 +83,7 @@ class RuleWatchNode /** * Given one watched literal, this method returns the other watched literal * - * @param int The watched literal that should not be returned + * @param int $literal The watched literal that should not be returned * @return int A literal */ public function getOtherWatch($literal) From 12ffe2b4d4bbe2cb4d5f12af2e2983adb6e75cf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Mo=CC=88ller?= Date: Sun, 28 Jun 2015 23:37:04 -0400 Subject: [PATCH 028/205] Fix: Add missing imports --- .../DependencyResolver/Operation/MarkAliasInstalledOperation.php | 1 + .../Operation/MarkAliasUninstalledOperation.php | 1 + src/Composer/EventDispatcher/EventDispatcher.php | 1 + src/Composer/Installer/InstallerInterface.php | 1 + src/Composer/Repository/ArtifactRepository.php | 1 + src/Composer/Repository/RepositoryManager.php | 1 + 6 files changed, 6 insertions(+) diff --git a/src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php b/src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php index c901bd190..920e54e67 100644 --- a/src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php +++ b/src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php @@ -13,6 +13,7 @@ namespace Composer\DependencyResolver\Operation; use Composer\Package\AliasPackage; +use Composer\Package\PackageInterface; /** * Solver install operation. diff --git a/src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.php b/src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.php index 56f7ac19b..77f3aef8c 100644 --- a/src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.php +++ b/src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.php @@ -13,6 +13,7 @@ namespace Composer\DependencyResolver\Operation; use Composer\Package\AliasPackage; +use Composer\Package\PackageInterface; /** * Solver install operation. diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index 3bb1c8496..84fdb0db5 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -21,6 +21,7 @@ use Composer\Composer; use Composer\DependencyResolver\Operation\OperationInterface; use Composer\Repository\CompositeRepository; use Composer\Script; +use Composer\Script\CommandEvent; use Composer\Script\PackageEvent; use Composer\Util\ProcessExecutor; diff --git a/src/Composer/Installer/InstallerInterface.php b/src/Composer/Installer/InstallerInterface.php index 469b91ed4..e64dfadd2 100644 --- a/src/Composer/Installer/InstallerInterface.php +++ b/src/Composer/Installer/InstallerInterface.php @@ -14,6 +14,7 @@ namespace Composer\Installer; use Composer\Package\PackageInterface; use Composer\Repository\InstalledRepositoryInterface; +use InvalidArgumentException; /** * Interface for the package installation manager. diff --git a/src/Composer/Repository/ArtifactRepository.php b/src/Composer/Repository/ArtifactRepository.php index 2bb518b8f..603d71ddc 100644 --- a/src/Composer/Repository/ArtifactRepository.php +++ b/src/Composer/Repository/ArtifactRepository.php @@ -15,6 +15,7 @@ namespace Composer\Repository; use Composer\IO\IOInterface; use Composer\Json\JsonFile; use Composer\Package\Loader\ArrayLoader; +use Composer\Package\Loader\LoaderInterface; /** * @author Serge Smertin diff --git a/src/Composer/Repository/RepositoryManager.php b/src/Composer/Repository/RepositoryManager.php index 47c152398..9dd88b176 100644 --- a/src/Composer/Repository/RepositoryManager.php +++ b/src/Composer/Repository/RepositoryManager.php @@ -15,6 +15,7 @@ namespace Composer\Repository; use Composer\IO\IOInterface; use Composer\Config; use Composer\EventDispatcher\EventDispatcher; +use Composer\Package\PackageInterface; /** * Repositories manager. From e698636af4fe12dfe532d331f3c2067797ae2343 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Mon, 29 Jun 2015 09:42:40 +0200 Subject: [PATCH 029/205] added test to reproduce #4183 --- .../Package/Archiver/ArchivableFilesFinderTest.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php b/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php index e9233f3cb..3c0c44abe 100644 --- a/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php +++ b/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php @@ -75,7 +75,8 @@ class ArchivableFilesFinderTest extends \PHPUnit_Framework_TestCase 'parameters.yml', 'parameters.yml.dist', '!important!.txt', - '!important_too!.txt' + '!important_too!.txt', + '#weirdfile', ); foreach ($fileTree as $relativePath) { @@ -98,7 +99,7 @@ class ArchivableFilesFinderTest extends \PHPUnit_Framework_TestCase '!/prefixB.foo', '/prefixA.foo', 'prefixC.*', - '!*/*/*/prefixC.foo' + '!*/*/*/prefixC.foo', ); $this->finder = new ArchivableFilesFinder($this->sources, $excludes); @@ -106,6 +107,7 @@ class ArchivableFilesFinderTest extends \PHPUnit_Framework_TestCase $this->assertArchivableFiles(array( '/!important!.txt', '/!important_too!.txt', + '/#weirdfile', '/A/prefixA.foo', '/A/prefixD.foo', '/A/prefixE.foo', @@ -170,7 +172,8 @@ class ArchivableFilesFinderTest extends \PHPUnit_Framework_TestCase 'H/**', 'J/', 'parameters.yml', - '\!important!.txt' + '\!important!.txt', + '\#*', ))); // git does not currently support negative git attributes @@ -181,7 +184,7 @@ class ArchivableFilesFinderTest extends \PHPUnit_Framework_TestCase //'!/prefixB.foo export-ignore', '/prefixA.foo export-ignore', 'prefixC.* export-ignore', - //'!/*/*/prefixC.foo export-ignore' + //'!/*/*/prefixC.foo export-ignore', ))); $this->finder = new ArchivableFilesFinder($this->sources, array()); From 5fe37357a230a0b82c2f8b224bb71a1985e50240 Mon Sep 17 00:00:00 2001 From: Jonathan Eskew Date: Mon, 29 Jun 2015 14:44:28 -0700 Subject: [PATCH 030/205] Reiterate the disclaimer in the context of callbacks --- doc/articles/scripts.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index d7cdd7602..5ea5204f7 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -82,8 +82,11 @@ For any given event: and command-line executable commands. - PHP classes containing defined callbacks must be autoloadable via Composer's autoload functionality. -- If a defined callback relies on functions defined outside of a class, the callback -must explicitly require the composer autoloader. +- If a defined callback relies on functions defined outside of a class, the +callback must explicitly require the composer autoloader. If used in a +context where`vendor/autoload.php` might not yet exist (such as during a +`pre-install` or `pre-update` command), the callback should explicitly require +whatever files within your root package it needs to execute successfully. Script definition example: From 0298cdc60d79bdb041973e0d78d73a061ccf092c Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 30 Jun 2015 13:51:17 +0200 Subject: [PATCH 031/205] change delimiter to curly braces --- src/Composer/Package/Archiver/BaseExcludeFilter.php | 4 ++-- tests/Composer/Test/Package/Archiver/GitExcludeFilterTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Composer/Package/Archiver/BaseExcludeFilter.php b/src/Composer/Package/Archiver/BaseExcludeFilter.php index d724f31e4..c94c52a6b 100644 --- a/src/Composer/Package/Archiver/BaseExcludeFilter.php +++ b/src/Composer/Package/Archiver/BaseExcludeFilter.php @@ -123,7 +123,7 @@ abstract class BaseExcludeFilter protected function generatePattern($rule) { $negate = false; - $pattern = '#'; + $pattern = '{'; if (strlen($rule) && $rule[0] === '!') { $negate = true; @@ -143,6 +143,6 @@ abstract class BaseExcludeFilter // remove delimiters as well as caret (^) and dollar sign ($) from the regex $pattern .= substr(Finder\Glob::toRegex($rule), 2, -2) . '(?=$|/)'; - return array($pattern . '#', $negate, false); + return array($pattern . '}', $negate, false); } } diff --git a/tests/Composer/Test/Package/Archiver/GitExcludeFilterTest.php b/tests/Composer/Test/Package/Archiver/GitExcludeFilterTest.php index 97c02c8e6..0a19a1327 100644 --- a/tests/Composer/Test/Package/Archiver/GitExcludeFilterTest.php +++ b/tests/Composer/Test/Package/Archiver/GitExcludeFilterTest.php @@ -29,8 +29,8 @@ class GitExcludeFilterTest extends \PHPUnit_Framework_TestCase public function patterns() { return array( - array('app/config/parameters.yml', array('#(?=[^\.])app/(?=[^\.])config/(?=[^\.])parameters\.yml(?=$|/)#', false, false)), - array('!app/config/parameters.yml', array('#(?=[^\.])app/(?=[^\.])config/(?=[^\.])parameters\.yml(?=$|/)#', true, false)), + array('app/config/parameters.yml', array('{(?=[^\.])app/(?=[^\.])config/(?=[^\.])parameters\.yml(?=$|/)}', false, false)), + array('!app/config/parameters.yml', array('{(?=[^\.])app/(?=[^\.])config/(?=[^\.])parameters\.yml(?=$|/)}', true, false)), ); } } From 5cd1b6d56f4b3cd89490d871633fcf71d8134e51 Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Tue, 30 Jun 2015 10:57:32 +0100 Subject: [PATCH 032/205] Added documentation about -stable suffix in version range comparison. Fixes #4080. --- doc/01-basic-usage.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/doc/01-basic-usage.md b/doc/01-basic-usage.md index 3d4f2b77d..f5f45346c 100644 --- a/doc/01-basic-usage.md +++ b/doc/01-basic-usage.md @@ -94,6 +94,29 @@ so using [stability flags](04-schema.md#package-links). To change that for all packages instead of doing per dependency you can also use the [minimum-stability](04-schema.md#minimum-stability) setting. +If you are using range comparisons when selecting non-stable packages, and you +specify a numeric version number (that is, no suffix indicating alpha, beta, +rc, or stable), then both non-stable and stable versions of a particular +release number will be treated as equally valid. + + * `>=`/`<=` will accept non-stable releases as well as the stable release. + * `<`/`>` will reject non-stable releasese as well as the stable release. + +If you wish to consider only the stable release in the comparison, add the +suffix `-stable` to the version number. + +Here are some examples: + + Example | Interpretation + --------------- | -------------- +`>=1.0.0` | Any release, stable or non-, of 1.0.0 will be allowed +`>=1.0.0-stable` | Only the stable release of 1.0.0 will be allowed +`<2.0.0` | Neither release, stable or non-, of 2.0.0 will be allowed +`<2.0.0-stable` | Only the stable release of 2.0.0 will be disallowed; non-stable releases will be allowed + +Note that the packages matched by these constraints are still checked against +the `minimum-stability` setting and each package's stability flags. + ### Test version constraints You can test version constraints using [semver.mwl.be](http://semver.mwl.be). Fill in From 2cd698874ffd1af8a34b3aedaa5f629d7cb3e799 Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Tue, 30 Jun 2015 11:21:49 +0100 Subject: [PATCH 033/205] Include pre-releases in >=2.3.0 comparison. Fixes #4080. This is a change to the >=2.3.0 comparison. Without this change, such a comparison will exclude pre-release versions. The rationale is that this makes the comparison more consistent with <2.3.0 (which excludes all pre-releases) and ~2.3.0 (which includes pre-releases). --- src/Composer/Package/Version/VersionParser.php | 6 ++++-- tests/Composer/Test/Package/Version/VersionParserTest.php | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Composer/Package/Version/VersionParser.php b/src/Composer/Package/Version/VersionParser.php index b5a32a448..c1cd4d229 100644 --- a/src/Composer/Package/Version/VersionParser.php +++ b/src/Composer/Package/Version/VersionParser.php @@ -443,9 +443,11 @@ class VersionParser if (!empty($stabilityModifier) && $this->parseStability($version) === 'stable') { $version .= '-' . $stabilityModifier; - } elseif ('<' === $matches[1]) { + } elseif ('<' === $matches[1] || '>=' === $matches[1]) { if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) { - $version .= '-dev'; + if (substr($matches[2], 0, 4) !== 'dev-') { + $version .= '-dev'; + } } } diff --git a/tests/Composer/Test/Package/Version/VersionParserTest.php b/tests/Composer/Test/Package/Version/VersionParserTest.php index 565451811..d8f351a27 100644 --- a/tests/Composer/Test/Package/Version/VersionParserTest.php +++ b/tests/Composer/Test/Package/Version/VersionParserTest.php @@ -244,13 +244,13 @@ class VersionParserTest extends \PHPUnit_Framework_TestCase 'greater than' => array('>1.0.0', new VersionConstraint('>', '1.0.0.0')), 'lesser than' => array('<1.2.3.4', new VersionConstraint('<', '1.2.3.4-dev')), 'less/eq than' => array('<=1.2.3', new VersionConstraint('<=', '1.2.3.0')), - 'great/eq than' => array('>=1.2.3', new VersionConstraint('>=', '1.2.3.0')), + 'great/eq than' => array('>=1.2.3', new VersionConstraint('>=', '1.2.3.0-dev')), 'equals' => array('=1.2.3', new VersionConstraint('=', '1.2.3.0')), 'double equals' => array('==1.2.3', new VersionConstraint('=', '1.2.3.0')), 'no op means eq' => array('1.2.3', new VersionConstraint('=', '1.2.3.0')), 'completes version' => array('=1.0', new VersionConstraint('=', '1.0.0.0')), 'shorthand beta' => array('1.2.3b5', new VersionConstraint('=', '1.2.3.0-beta5')), - 'accepts spaces' => array('>= 1.2.3', new VersionConstraint('>=', '1.2.3.0')), + 'accepts spaces' => array('>= 1.2.3', new VersionConstraint('>=', '1.2.3.0-dev')), 'accepts spaces/2' => array('< 1.2.3', new VersionConstraint('<', '1.2.3.0-dev')), 'accepts spaces/3' => array('> 1.2.3', new VersionConstraint('>', '1.2.3.0')), 'accepts master' => array('>=dev-master', new VersionConstraint('>=', '9999999-dev')), @@ -260,6 +260,7 @@ class VersionParserTest extends \PHPUnit_Framework_TestCase 'regression #935' => array('dev-CAPS', new VersionConstraint('=', 'dev-CAPS')), 'ignores aliases' => array('dev-master as 1.0.0', new VersionConstraint('=', '9999999-dev')), 'lesser than override' => array('<1.2.3.4-stable', new VersionConstraint('<', '1.2.3.4')), + 'great/eq than override' => array('>=1.2.3.4-stable', new VersionConstraint('>=', '1.2.3.4')), ); } From b17ccbfa0d73f71ed8c11953e9e1e5d3709bf91e Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 30 Jun 2015 13:27:05 +0100 Subject: [PATCH 034/205] Avoid invalid warnings when scanning the same file twice, fixes #4195, fixes #4197 --- src/Composer/Autoload/AutoloadGenerator.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 284150135..e8de9cd3f 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -201,9 +201,9 @@ EOF; $namespaceFilter = $namespace === '' ? null : $namespace; foreach (ClassMapGenerator::createMap($dir, $whitelist, $this->io, $namespaceFilter) as $class => $path) { - $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path); + $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n"; if (!isset($classMap[$class])) { - $classMap[$class] = $pathCode.",\n"; + $classMap[$class] = $pathCode; } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) { $this->io->writeError( 'Warning: Ambiguous class resolution, "'.$class.'"'. @@ -218,9 +218,9 @@ EOF; foreach ($autoloads['classmap'] as $dir) { foreach (ClassMapGenerator::createMap($dir, null, $this->io) as $class => $path) { - $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path); + $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n"; if (!isset($classMap[$class])) { - $classMap[$class] = $pathCode.",\n"; + $classMap[$class] = $pathCode; } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) { $this->io->writeError( 'Warning: Ambiguous class resolution, "'.$class.'"'. From 4ddd5aa37f2db325aea3de827c37e1f66c8c1969 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Mon, 22 Jun 2015 14:31:33 +0200 Subject: [PATCH 035/205] cleaned up intro page a bit --- doc/00-intro.md | 137 ++++++++++++++++++----------------------------- doc/06-config.md | 16 +++--- 2 files changed, 61 insertions(+), 92 deletions(-) diff --git a/doc/00-intro.md b/doc/00-intro.md index 0496390ca..c0fe1c4dc 100644 --- a/doc/00-intro.md +++ b/doc/00-intro.md @@ -1,54 +1,41 @@ # Introduction Composer is a tool for dependency management in PHP. It allows you to declare -the dependent libraries your project needs and it will install them in your -project for you. +the libraries your project depends on and it will manage (install/update) them +for you. ## Dependency management -Composer is not a package manager. Yes, it deals with "packages" or libraries, but -it manages them on a per-project basis, installing them in a directory (e.g. `vendor`) -inside your project. By default it will never install anything globally. Thus, -it is a dependency manager. +Composer is **not** a package manager in the same sense as Yum or Apt are. Yes, +it deals with "packages" or libraries, but it manages them on a per-project +basis, installing them in a directory (e.g. `vendor`) inside your project. By +default it will never install anything globally. Thus, it is a dependency +manager. -This idea is not new and Composer is strongly inspired by node's [npm](https://npmjs.org/) -and ruby's [bundler](http://bundler.io/). But there has not been such a tool -for PHP. +This idea is not new and Composer is strongly inspired by node's +[npm](https://npmjs.org/) and ruby's [bundler](http://bundler.io/). -The problem that Composer solves is this: +Suppose: a) You have a project that depends on a number of libraries. b) Some of those libraries depend on other libraries. -c) You declare the things you depend on. +Composer: -d) Composer finds out which versions of which packages need to be installed, and - installs them (meaning it downloads them into your project). - -## Declaring dependencies - -Let's say you are creating a project, and you need a library that does logging. -You decide to use [monolog](https://github.com/Seldaek/monolog). In order to -add it to your project, all you need to do is create a `composer.json` file -which describes the project's dependencies. +c) Enables you to declare the libraries you depend on. -```json -{ - "require": { - "monolog/monolog": "1.2.*" - } -} -``` +d) Finds out which versions of which packages can and need to be installed, and + installs them (meaning it downloads them into your project). -We are simply stating that our project requires some `monolog/monolog` package, -any version beginning with `1.2`. +See the [Basic usage](01-basic-usage.md) chapter for more details on declaring +dependencies. ## System Requirements Composer requires PHP 5.3.2+ to run. A few sensitive php settings and compile -flags are also required, but when using the installer you will be warned about any -incompatibilities. +flags are also required, but when using the installer you will be warned about +any incompatibilities. To install packages from sources instead of simple zip archives, you will need git, svn or hg depending on how the package is version-controlled. @@ -79,37 +66,48 @@ curl -sS https://getcomposer.org/installer | php php -r "readfile('https://getcomposer.org/installer');" | php ``` -The installer will just check a few PHP settings and then download `composer.phar` -to your working directory. This file is the Composer binary. It is a PHAR (PHP -archive), which is an archive format for PHP which can be run on the command -line, amongst other things. +The installer will just check a few PHP settings and then download +`composer.phar` to your working directory. This file is the Composer binary. It +is a PHAR (PHP archive), which is an archive format for PHP which can be run on +the command line, amongst other things. You can install Composer to a specific directory by using the `--install-dir` -option and providing a target directory (it can be an absolute or relative path): +option and providing a target directory (it can be an absolute or relative +path): ```sh curl -sS https://getcomposer.org/installer | php -- --install-dir=bin ``` +Now just run `php composer.phar` in order to run Composer. + #### Globally -You can place this file anywhere you wish. If you put it in your `PATH`, -you can access it globally. On unixy systems you can even make it -executable and invoke it without `php`. +You can place the Composer PHAR anywhere you wish. If you put it in a directory +that is part of your `PATH`, you can access it globally. On unixy systems you +can even make it executable and invoke it without directly using the `php` +interpreter. -You can run these commands to easily access `composer` from anywhere on your system: +Run these commands to globally install `composer` on your system: ```sh curl -sS https://getcomposer.org/installer | php mv composer.phar /usr/local/bin/composer +chmod 755 /usr/local/bin/composer ``` -> **Note:** If the above fails due to permissions, run the `mv` line +> **Note:** If the above fails due to permissions, run the `mv` and `chmod` line > again with sudo. -> **Note:** In OSX Yosemite the `/usr` directory does not exist by default. If you receive the error "/usr/local/bin/composer: No such file or directory" then you must create `/usr/local/bin/` manually before proceeding. +> **Note:** On some versions of OSX the `/usr` directory does not exist by +> default. If you receive the error "/usr/local/bin/composer: No such file or +> directory" then you must create the directory manually before proceeding: +> `mkdir -p /usr/local/bin`. -Then, just run `composer` in order to run Composer instead of `php composer.phar`. +> **Note:** For information on changing your PATH, please read the +> [Wikipedia article](https://en.wikipedia.org/wiki/PATH_(variable)) and/or use Google. + +Now just run `composer` in order to run Composer instead of `php composer.phar`. ## Installation - Windows @@ -117,24 +115,26 @@ Then, just run `composer` in order to run Composer instead of `php composer.phar This is the easiest way to get Composer set up on your machine. -Download and run [Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe), -it will install the latest Composer version and set up your PATH so that you can -just call `composer` from any directory in your command line. +Download and run +[Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe). It will +install the latest Composer version and set up your PATH so that you can just +call `composer` from any directory in your command line. -> **Note:** Close your current terminal. Test usage with a new terminal: -> That is important since the PATH only gets loaded when the terminal starts. +> **Note:** Close your current terminal. Test usage with a new terminal: This is +> important since the PATH only gets loaded when the terminal starts. ### Manual Installation Change to a directory on your `PATH` and run the install snippet to download -composer.phar: +`composer.phar`: ```sh C:\Users\username>cd C:\bin C:\bin>php -r "readfile('https://getcomposer.org/installer');" | php ``` -> **Note:** If the above fails due to readfile, use the `http` url or enable php_openssl.dll in php.ini +> **Note:** If the above fails due to readfile, use the `http` url or enable +> php_openssl.dll in php.ini Create a new `composer.bat` file alongside `composer.phar`: @@ -153,38 +153,7 @@ Composer version 27d8904 ## Using Composer -We will now use Composer to install the dependencies of the project. If you -don't have a `composer.json` file in the current directory please skip to the -[Basic Usage](01-basic-usage.md) chapter. - -To resolve and download dependencies, run the `install` command: - -```sh -php composer.phar install -``` - -If you did a global install and do not have the phar in that directory -run this instead: - -```sh -composer install -``` - -Following the [example above](#declaring-dependencies), this will download -monolog into the `vendor/monolog/monolog` directory. - -## Autoloading - -Besides downloading the library, Composer also prepares an autoload file that's -capable of autoloading all of the classes in any of the libraries that it -downloads. To use it, just add the following line to your code's bootstrap -process: - -```php -require __DIR__ . '/vendor/autoload.php'; -``` - -Woah! Now start using monolog! To keep learning more about Composer, keep -reading the "Basic Usage" chapter. +Now that you've installed Composer, you are ready to use it! Head on over to the +next chapter for a short and simple demonstration. -[Basic Usage](01-basic-usage.md) → +[Basic usage](01-basic-usage.md) → diff --git a/doc/06-config.md b/doc/06-config.md index 1dbcf7be2..2564fefef 100644 --- a/doc/06-config.md +++ b/doc/06-config.md @@ -46,6 +46,11 @@ A list of domain names and username/passwords to authenticate against them. For example using `{"example.org": {"username": "alice", "password": "foo"}` as the value of this option will let Composer authenticate against example.org. +> **Note:** Authentication-related config options like `http-basic` and +> `github-oauth` can also be specified inside a `auth.json` file that goes +> besides your `composer.json`. That way you can gitignore it and every +> developer can place their own credentials in there. + ## platform Lets you fake platform packages (PHP and extensions) so that you can emulate a @@ -99,7 +104,7 @@ first until the cache fits. ## prepend-autoloader -Defaults to `true`. If false, the Composer autoloader will not be prepended to +Defaults to `true`. If `false`, the Composer autoloader will not be prepended to existing autoloaders. This is sometimes required to fix interoperability issues with other autoloaders. @@ -110,7 +115,7 @@ autoloader. When null a random one will be generated. ## optimize-autoloader -Defaults to `false`. Always optimize when dumping the autoloader. +Defaults to `false`. If `true`, always optimize when dumping the autoloader. ## classmap-authoritative @@ -125,7 +130,7 @@ used for GitHub Enterprise setups. ## github-expose-hostname -Defaults to `true`. If set to `false`, the OAuth tokens created to access the +Defaults to `true`. If `false`, the OAuth tokens created to access the github API will have a date instead of the machine hostname. ## notify-on-install @@ -163,9 +168,4 @@ Example: } ``` -> **Note:** Authentication-related config options like `http-basic` and -> `github-oauth` can also be specified inside a `auth.json` file that goes -> besides your `composer.json`. That way you can gitignore it and every -> developer can place their own credentials in there. - ← [Repositories](05-repositories.md) | [Community](07-community.md) → From eb98613672e536c2a2b342f9e6e98878ece59071 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 30 Jun 2015 08:43:54 +0200 Subject: [PATCH 036/205] add installer information --- doc/00-intro.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/doc/00-intro.md b/doc/00-intro.md index c0fe1c4dc..4aca7ab17 100644 --- a/doc/00-intro.md +++ b/doc/00-intro.md @@ -47,6 +47,12 @@ Linux and OSX. ### Downloading the Composer Executable +Composer offers a convenient installer that you can execute directly from the +commandline. Feel free to [download this file](https://getcomposer.org/installer) +or review it on [GitHub](https://github.com/composer/getcomposer.org/blob/master/web/installer) +if you wish to know more about the inner workings of the installer. The source +is plain PHP. + There are in short, two ways to install Composer. Locally as part of your project, or globally as a system wide executable. @@ -93,11 +99,16 @@ Run these commands to globally install `composer` on your system: ```sh curl -sS https://getcomposer.org/installer | php mv composer.phar /usr/local/bin/composer -chmod 755 /usr/local/bin/composer ``` -> **Note:** If the above fails due to permissions, run the `mv` and `chmod` line -> again with sudo. +> **Note:** If the above fails due to permissions, run the `mv` line again +> with sudo. + +A quick copy-paste version including sudo: + +```sh +curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer +``` > **Note:** On some versions of OSX the `/usr` directory does not exist by > default. If you receive the error "/usr/local/bin/composer: No such file or From 10b813fc40dd32f27b1bb2f1a201f2cf79b49832 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Mon, 22 Jun 2015 16:24:59 +0200 Subject: [PATCH 037/205] reworking basic usage, added versions article --- doc/00-intro.md | 9 ++- doc/01-basic-usage.md | 169 ++++++++++++++++----------------------- doc/articles/versions.md | 99 +++++++++++++++++++++++ 3 files changed, 172 insertions(+), 105 deletions(-) create mode 100644 doc/articles/versions.md diff --git a/doc/00-intro.md b/doc/00-intro.md index 4aca7ab17..d984eb7b9 100644 --- a/doc/00-intro.md +++ b/doc/00-intro.md @@ -77,15 +77,16 @@ The installer will just check a few PHP settings and then download is a PHAR (PHP archive), which is an archive format for PHP which can be run on the command line, amongst other things. +Now just run `php composer.phar` in order to run Composer. + You can install Composer to a specific directory by using the `--install-dir` -option and providing a target directory (it can be an absolute or relative -path): +option and additionally (re)name it as well using the `--filename` option: ```sh -curl -sS https://getcomposer.org/installer | php -- --install-dir=bin +curl -sS https://getcomposer.org/installer | php -- --install-dir=bin --filename=composer ``` -Now just run `php composer.phar` in order to run Composer. +Now just run `php bin/composer` in order to run Composer. #### Globally diff --git a/doc/01-basic-usage.md b/doc/01-basic-usage.md index f5f45346c..d52a7d735 100644 --- a/doc/01-basic-usage.md +++ b/doc/01-basic-usage.md @@ -1,8 +1,12 @@ # Basic usage -## Installing +## Introduction -If you have not yet installed Composer, refer to the [Intro](00-intro.md) chapter. +If you have not yet installed Composer, refer to the [Intro](00-intro.md) +chapter. For our basic usage introduction, we will be installing +`monolog/monolog`, a logging library. Note that for the sake of simplicity, +this introduction will assume you have performed a [local](00-intro.md#locally) +install of Composer. ## `composer.json`: Project Setup @@ -10,9 +14,6 @@ To start using Composer in your project, all you need is a `composer.json` file. This file describes the dependencies of your project and may contain other metadata as well. -The [JSON format](http://json.org/) is quite easy to write. It allows you to -define nested structures. - ### The `require` Key The first (and often only) thing you specify in `composer.json` is the @@ -27,15 +28,15 @@ depends on. } ``` -As you can see, `require` takes an object that maps **package names** (e.g. `monolog/monolog`) -to **package versions** (e.g. `1.0.*`). +As you can see, `require` takes an object that maps **package names** +(e.g. `monolog/monolog`) to **version constraints** (e.g. `1.0.*`). ### Package Names The package name consists of a vendor name and the project's name. Often these -will be identical - the vendor name just exists to prevent naming clashes. It allows -two different people to create a library named `json`, which would then just be -named `igorw/json` and `seldaek/json`. +will be identical - the vendor name just exists to prevent naming clashes. It +allows two different people to create a library named `json`, which would then +just be named `igorw/json` and `seldaek/json`. Here we are requiring `monolog/monolog`, so the vendor name is the same as the project's name. For projects with a unique name this is recommended. It also @@ -45,53 +46,20 @@ smaller decoupled parts. ### Package Versions -In the previous example we were requiring version [`1.0.*`](http://semver.mwl.be/#?package=monolog%2Fmonolog&version=1.0.*) of monolog. This -means any version in the `1.0` development branch. It would match `1.0.0`, -`1.0.2` or `1.0.20`. - -Version constraints can be specified in a few different ways. - -Name | Example | Description --------------- | ------------------------------------------------------------------------ | ----------- -Exact version | `1.0.2` | You can specify the exact version of a package. -Range | `>=1.0` `>=1.0 <2.0` >=1.0 <1.1 || >=1.2 | By using comparison operators you can specify ranges of valid versions. Valid operators are `>`, `>=`, `<`, `<=`, `!=`.
You can define multiple ranges. Ranges separated by a space ( ) or comma (`,`) will be treated as a **logical AND**. A double pipe (||) will be treated as a **logical OR**. AND has higher precedence than OR. -Hyphen Range | `1.0 - 2.0` | Inclusive set of versions. Partial versions on the right include are completed with a wildcard. For example `1.0 - 2.0` is equivalent to `>=1.0.0 <2.1` as the `2.0` becomes `2.0.*`. On the other hand `1.0.0 - 2.1.0` is equivalent to `>=1.0.0 <=2.1.0`. -Wildcard | `1.0.*` | You can specify a pattern with a `*` wildcard. `1.0.*` is the equivalent of `>=1.0 <1.1`. -Tilde Operator | `~1.2` | Very useful for projects that follow semantic versioning. `~1.2` is equivalent to `>=1.2 <2.0`. For more details, read the next section below. -Caret Operator | `^1.2.3` | Very useful for projects that follow semantic versioning. `^1.2.3` is equivalent to `>=1.2.3 <2.0`. For more details, read the next section below. - -### Next Significant Release (Tilde and Caret Operators) - -The `~` operator is best explained by example: `~1.2` is equivalent to -`>=1.2 <2.0.0`, while `~1.2.3` is equivalent to `>=1.2.3 <1.3.0`. As you can see -it is mostly useful for projects respecting [semantic -versioning](http://semver.org/). A common usage would be to mark the minimum -minor version you depend on, like `~1.2` (which allows anything up to, but not -including, 2.0). Since in theory there should be no backwards compatibility -breaks until 2.0, that works well. Another way of looking at it is that using -`~` specifies a minimum version, but allows the last digit specified to go up. - -The `^` operator behaves very similarly but it sticks closer to semantic -versioning, and will always allow non-breaking updates. For example `^1.2.3` -is equivalent to `>=1.2.3 <2.0.0` as none of the releases until 2.0 should -break backwards compatibility. For pre-1.0 versions it also acts with safety -in mind and treats `^0.3` as `>=0.3.0 <0.4.0` - -> **Note:** Though `2.0-beta.1` is strictly before `2.0`, a version constraint -> like `~1.2` would not install it. As said above `~1.2` only means the `.2` -> can change but the `1.` part is fixed. - -> **Note:** The `~` operator has an exception on its behavior for the major -> release number. This means for example that `~1` is the same as `~1.0` as -> it will not allow the major number to increase trying to keep backwards -> compatibility. +In the previous example we were requiring version +[`1.0.*`](http://semver.mwl.be/#?package=monolog%2Fmonolog&version=1.0.*) of +monolog. This means any version in the `1.0` development branch. It is the +equivalent of saying versions that match `>=1.0 <1.1`. + +Version constraints can be specified in several ways, read +[versions](articles/versions.md) for more in-depth information on this topic. ### Stability -By default only stable releases are taken into consideration. If you would like -to also get RC, beta, alpha or dev versions of your dependencies you can do -so using [stability flags](04-schema.md#package-links). To change that for all -packages instead of doing per dependency you can also use the +By default only stable releases are taken into consideration. If you would +like to also get RC, beta, alpha or dev versions of your dependencies you can +do so using [stability flags](04-schema.md#package-links). To change that for +all packages instead of doing per dependency you can also use the [minimum-stability](04-schema.md#minimum-stability) setting. If you are using range comparisons when selecting non-stable packages, and you @@ -119,15 +87,15 @@ the `minimum-stability` setting and each package's stability flags. ### Test version constraints -You can test version constraints using [semver.mwl.be](http://semver.mwl.be). Fill in -a package name and it will autofill the default version constraint which Composer would add -to your `composer.json` file. You can adjust the version constraint and the tool will highlight -all releases that match. +You can test version constraints using [semver.mwl.be](http://semver.mwl.be). +Fill in a package name and it will autofill the default version constraint +which Composer would add to your `composer.json` file. You can adjust the +version constraint and the tool will highlight all releases that match. ## Installing Dependencies -To fetch the defined dependencies into your local project, just run the -`install` command of `composer.phar`. +To install the defined dependencies for your project, just run the +`install` command. ```sh php composer.phar install @@ -139,11 +107,10 @@ It's a convention to put third party code into a directory named `vendor`. In case of monolog it will put it into `vendor/monolog/monolog`. > **Tip:** If you are using git for your project, you probably want to add -> `vendor` into your `.gitignore`. You really don't want to add all of that +> `vendor` in your `.gitignore`. You really don't want to add all of that > code to your repository. -Another thing that the `install` command does is it adds a `composer.lock` -file into your project root. +You will notice the `install` command also created a `composer.lock` file. ## `composer.lock` - The Lock File @@ -151,72 +118,72 @@ After installing the dependencies, Composer writes the list of the exact versions it installed into a `composer.lock` file. This locks the project to those specific versions. -**Commit your application's `composer.lock` (along with `composer.json`) into version control.** +**Commit your application's `composer.lock` (along with `composer.json`) +into version control.** -This is important because the `install` command checks if a lock file is present, -and if it is, it downloads the versions specified there (regardless of what `composer.json` -says). +This is important because the `install` command checks if a lock file is +present, and if it is, it downloads the versions specified there (regardless +of what `composer.json` says). -This means that anyone who sets up the project will download the exact -same version of the dependencies. Your CI server, production machines, other -developers in your team, everything and everyone runs on the same dependencies, which -mitigates the potential for bugs affecting only some parts of the deployments. Even if you -develop alone, in six months when reinstalling the project you can feel confident the -dependencies installed are still working even if your dependencies released -many new versions since then. +This means that anyone who sets up the project will download the exact same +version of the dependencies. Your CI server, production machines, other +developers in your team, everything and everyone runs on the same dependencies, +which mitigates the potential for bugs affecting only some parts of the +deployments. Even if you develop alone, in six months when reinstalling the +project you can feel confident the dependencies installed are still working even +if your dependencies released many new versions since then. If no `composer.lock` file exists, Composer will read the dependencies and -versions from `composer.json` and create the lock file after executing the `update` or the `install` -command. +versions from `composer.json` and create the lock file after executing the +`update` or the `install` command. -This means that if any of the dependencies get a new version, you won't get the updates -automatically. To update to the new version, use the `update` command. This will fetch -the latest matching versions (according to your `composer.json` file) and also update -the lock file with the new version. +This means that if any of the dependencies get a new version, you won't get the +updates automatically. To update to the new version, use the `update` command. +This will fetch the latest matching versions (according to your `composer.json` +file) and also update the lock file with the new version. ```sh php composer.phar update ``` -> **Note:** Composer will display a Warning when executing an `install` command if - `composer.lock` and `composer.json` are not synchronized. - +> **Note:** Composer will display a Warning when executing an `install` command +> if `composer.lock` and `composer.json` are not synchronized. + If you only want to install or update one dependency, you can whitelist them: ```sh php composer.phar update monolog/monolog [...] ``` -> **Note:** For libraries it is not necessarily recommended to commit the lock file, -> see also: [Libraries - Lock file](02-libraries.md#lock-file). +> **Note:** For libraries it is not necessarily recommended to commit the lock +> file, see also: [Libraries - Lock file](02-libraries.md#lock-file). ## Packagist [Packagist](https://packagist.org/) is the main Composer repository. A Composer repository is basically a package source: a place where you can get packages from. Packagist aims to be the central repository that everybody uses. This -means that you can automatically `require` any package that is available -there. +means that you can automatically `require` any package that is available there. If you go to the [packagist website](https://packagist.org/) (packagist.org), you can browse and search for packages. Any open source project using Composer should publish their packages on -packagist. A library doesn't need to be on packagist to be used by Composer, -but it makes life quite a bit simpler. +packagist. A library doesn't need to be on packagist to be used by Composer, but +it makes life quite a bit simpler. ## Autoloading For libraries that specify autoload information, Composer generates a -`vendor/autoload.php` file. You can simply include this file and you -will get autoloading for free. +`vendor/autoload.php` file. You can simply include this file and you will get +autoloading for free. ```php require 'vendor/autoload.php'; ``` -This makes it really easy to use third party code. For example: If your -project depends on monolog, you can just start using classes from it, and they -will be autoloaded. +This makes it really easy to use third party code. For example: If your project +depends on monolog, you can just start using classes from it, and they will be +autoloaded. ```php $log = new Monolog\Logger('name'); @@ -243,8 +210,8 @@ You define a mapping from namespaces to directories. The `src` directory would be in your project root, on the same level as `vendor` directory is. An example filename would be `src/Foo.php` containing an `Acme\Foo` class. -After adding the `autoload` field, you have to re-run `dump-autoload` to re-generate -the `vendor/autoload.php` file. +After adding the `autoload` field, you have to re-run `dump-autoload` to +re-generate the `vendor/autoload.php` file. Including that file will also return the autoloader instance, so you can store the return value of the include call in a variable and add more namespaces. @@ -256,11 +223,11 @@ $loader->add('Acme\\Test\\', __DIR__); ``` In addition to PSR-4 autoloading, classmap is also supported. This allows -classes to be autoloaded even if they do not conform to PSR-4. See the -[autoload reference](04-schema.md#autoload) for more details. +classes to be autoloaded even if they do not conform to PSR-4. See the [autoload +reference](04-schema.md#autoload) for more details. -> **Note:** Composer provides its own autoloader. If you don't want to use -that one, you can just include `vendor/composer/autoload_*.php` files, -which return associative arrays allowing you to configure your own autoloader. +> **Note:** Composer provides its own autoloader. If you don't want to use that +> one, you can just include `vendor/composer/autoload_*.php` files, which return +> associative arrays allowing you to configure your own autoloader. ← [Intro](00-intro.md) | [Libraries](02-libraries.md) → diff --git a/doc/articles/versions.md b/doc/articles/versions.md new file mode 100644 index 000000000..eae9da9be --- /dev/null +++ b/doc/articles/versions.md @@ -0,0 +1,99 @@ + + +# Versions + +## Basic Constraints + +### Exact + +You can specify the exact version of a package. This will tell Composer to +install this version and this version only. If other dependencies require +a different version, the solver will ultimately fail and abort any install +or update procedures. + +Example: `1.0.2` + +### Range + +By using comparison operators you can specify ranges of valid versions. Valid +operators are `>`, `>=`, `<`, `<=`, `!=`.
You can define multiple ranges. +Ranges separated by a space ( ) or comma (`,`) will be treated as +a **logical AND**. A double pipe (||) will be treated as +a **logical OR**. AND has higher precedence than OR. + +Example: `>=1.0` `>=1.0 <2.0` `>=1.0 <1.1 || >=1.2` + +### Range (Hyphen) + +Inclusive set of versions. Partial versions on the right include are completed +with a wildcard. For example `1.0 - 2.0` is equivalent to `>=1.0.0 <2.1` as the +`2.0` becomes `2.0.*`. On the other hand `1.0.0 - 2.1.0` is equivalent to +`>=1.0.0 <=2.1.0`. + +Example: `1.0 - 2.0` + +### Wildcard + +You can specify a pattern with a `*` wildcard. `1.0.*` is the equivalent of +`>=1.0 <1.1`. + +Example: `1.0.*` + +## Next Significant Release Operators + +### Tilde + +The `~` operator is best explained by example: `~1.2` is equivalent to +`>=1.2 <2.0.0`, while `~1.2.3` is equivalent to `>=1.2.3 <1.3.0`. As you can see +it is mostly useful for projects respecting [semantic +versioning](http://semver.org/). A common usage would be to mark the minimum +minor version you depend on, like `~1.2` (which allows anything up to, but not +including, 2.0). Since in theory there should be no backwards compatibility +breaks until 2.0, that works well. Another way of looking at it is that using +`~` specifies a minimum version, but allows the last digit specified to go up. + +Example: `~1.2` + +> **Note:** Though `2.0-beta.1` is strictly before `2.0`, a version constraint +> like `~1.2` would not install it. As said above `~1.2` only means the `.2` +> can change but the `1.` part is fixed. + +> **Note:** The `~` operator has an exception on its behavior for the major +> release number. This means for example that `~1` is the same as `~1.0` as +> it will not allow the major number to increase trying to keep backwards +> compatibility. + +### Caret + +The `^` operator behaves very similarly but it sticks closer to semantic +versioning, and will always allow non-breaking updates. For example `^1.2.3` +is equivalent to `>=1.2.3 <2.0.0` as none of the releases until 2.0 should +break backwards compatibility. For pre-1.0 versions it also acts with safety +in mind and treats `^0.3` as `>=0.3.0 <0.4.0`. + +Example: `^1.2.3` + +## Stability + +If you are using a constraint that does not explicitly define a stability, +Composer will default interally to `-dev` or `-stable`, depending on the +operator(s) used. This happens transparently. + +If you wish to explicitly consider only the stable release in the comparison, +add the suffix `-stable`. + +Examples: + + Constraint | Internally +---------------------------------------------- + `1.2.3` | `=1.2.3.0-stable` + `>1.2` | `>1.2.0.0-stable` + `>=1.2` | `>=1.2.0.0-dev` + `>=1.2-stable` | `>=1.2.0.0-stable` + `<1.3` | `<1.3.0.0-dev` + `<=1.3` | `<=1.3.0.0-stable` + `1 - 2` | `>=1.0.0.0-dev <3.0.0.0-dev` + `~1.3` | `>=1.3.0.0-dev <2.0.0.0-dev` + `1.4.*` | `>=1.4.0.0-dev <1.5.0.0-dev` From 50db9393e5d852efa00737c2d71d77f91bde0ac3 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Mon, 22 Jun 2015 22:01:20 +0200 Subject: [PATCH 038/205] better phrasing / structure + moved version testing link --- doc/01-basic-usage.md | 41 ++++++---------------------------------- doc/articles/versions.md | 36 ++++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 46 deletions(-) diff --git a/doc/01-basic-usage.md b/doc/01-basic-usage.md index d52a7d735..83bb68e25 100644 --- a/doc/01-basic-usage.md +++ b/doc/01-basic-usage.md @@ -2,11 +2,12 @@ ## Introduction -If you have not yet installed Composer, refer to the [Intro](00-intro.md) -chapter. For our basic usage introduction, we will be installing -`monolog/monolog`, a logging library. Note that for the sake of simplicity, -this introduction will assume you have performed a [local](00-intro.md#locally) -install of Composer. +For our basic usage introduction, we will be installing `monolog/monolog`, +a logging library. If you have not yet installed Composer, refer to the +[Intro](00-intro.md) chapter. + +> **Note:** for the sake of simplicity, this introduction will assume you +> have performed a [local](00-intro.md#locally) install of Composer. ## `composer.json`: Project Setup @@ -62,36 +63,6 @@ do so using [stability flags](04-schema.md#package-links). To change that for all packages instead of doing per dependency you can also use the [minimum-stability](04-schema.md#minimum-stability) setting. -If you are using range comparisons when selecting non-stable packages, and you -specify a numeric version number (that is, no suffix indicating alpha, beta, -rc, or stable), then both non-stable and stable versions of a particular -release number will be treated as equally valid. - - * `>=`/`<=` will accept non-stable releases as well as the stable release. - * `<`/`>` will reject non-stable releasese as well as the stable release. - -If you wish to consider only the stable release in the comparison, add the -suffix `-stable` to the version number. - -Here are some examples: - - Example | Interpretation - --------------- | -------------- -`>=1.0.0` | Any release, stable or non-, of 1.0.0 will be allowed -`>=1.0.0-stable` | Only the stable release of 1.0.0 will be allowed -`<2.0.0` | Neither release, stable or non-, of 2.0.0 will be allowed -`<2.0.0-stable` | Only the stable release of 2.0.0 will be disallowed; non-stable releases will be allowed - -Note that the packages matched by these constraints are still checked against -the `minimum-stability` setting and each package's stability flags. - -### Test version constraints - -You can test version constraints using [semver.mwl.be](http://semver.mwl.be). -Fill in a package name and it will autofill the default version constraint -which Composer would add to your `composer.json` file. You can adjust the -version constraint and the tool will highlight all releases that match. - ## Installing Dependencies To install the defined dependencies for your project, just run the diff --git a/doc/articles/versions.md b/doc/articles/versions.md index eae9da9be..b59e5e70e 100644 --- a/doc/articles/versions.md +++ b/doc/articles/versions.md @@ -8,7 +8,7 @@ ### Exact -You can specify the exact version of a package. This will tell Composer to +You can specify the exact version of a package. This will tell Composer to install this version and this version only. If other dependencies require a different version, the solver will ultimately fail and abort any install or update procedures. @@ -17,26 +17,32 @@ Example: `1.0.2` ### Range -By using comparison operators you can specify ranges of valid versions. Valid -operators are `>`, `>=`, `<`, `<=`, `!=`.
You can define multiple ranges. -Ranges separated by a space ( ) or comma (`,`) will be treated as -a **logical AND**. A double pipe (||) will be treated as -a **logical OR**. AND has higher precedence than OR. +By using comparison operators you can specify ranges of valid versions. Valid +operators are `>`, `>=`, `<`, `<=`, `!=`. -Example: `>=1.0` `>=1.0 <2.0` `>=1.0 <1.1 || >=1.2` +You can define multiple ranges. Ranges separated by a space ( ) or +comma (`,`) will be treated as a **logical AND**. A double pipe +(||) will be treated as a **logical OR**. AND has higher +precedence than OR. + +Examples: + +* `>=1.0` +* `>=1.0 <2.0` +* `>=1.0 <1.1 || >=1.2` ### Range (Hyphen) -Inclusive set of versions. Partial versions on the right include are completed -with a wildcard. For example `1.0 - 2.0` is equivalent to `>=1.0.0 <2.1` as the -`2.0` becomes `2.0.*`. On the other hand `1.0.0 - 2.1.0` is equivalent to +Inclusive set of versions. Partial versions on the right include are completed +with a wildcard. For example `1.0 - 2.0` is equivalent to `>=1.0.0 <2.1` as the +`2.0` becomes `2.0.*`. On the other hand `1.0.0 - 2.1.0` is equivalent to `>=1.0.0 <=2.1.0`. Example: `1.0 - 2.0` ### Wildcard -You can specify a pattern with a `*` wildcard. `1.0.*` is the equivalent of +You can specify a pattern with a `*` wildcard. `1.0.*` is the equivalent of `>=1.0 <1.1`. Example: `1.0.*` @@ -97,3 +103,11 @@ Examples: `1 - 2` | `>=1.0.0.0-dev <3.0.0.0-dev` `~1.3` | `>=1.3.0.0-dev <2.0.0.0-dev` `1.4.*` | `>=1.4.0.0-dev <1.5.0.0-dev` + +## Test version constraints + +You can test version constraints using [semver.mwl.be](http://semver.mwl.be). +Fill in a package name and it will autofill the default version constraint +which Composer would add to your `composer.json` file. You can adjust the +version constraint and the tool will highlight all releases that match. + From d8d2bcadde5071aa3f4fc54f17324d368f89c15b Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 23 Jun 2015 08:47:30 +0200 Subject: [PATCH 039/205] added some links and some restructuring --- doc/01-basic-usage.md | 61 +++++++++++++++++----------------- doc/02-libraries.md | 76 ++++++++++++++++++++++--------------------- 2 files changed, 71 insertions(+), 66 deletions(-) diff --git a/doc/01-basic-usage.md b/doc/01-basic-usage.md index 83bb68e25..8cad96f6c 100644 --- a/doc/01-basic-usage.md +++ b/doc/01-basic-usage.md @@ -18,8 +18,8 @@ other metadata as well. ### The `require` Key The first (and often only) thing you specify in `composer.json` is the -`require` key. You're simply telling Composer which packages your project -depends on. +[`require`](04-schema.md#require) key. You're simply telling Composer which +packages your project depends on. ```json { @@ -29,8 +29,9 @@ depends on. } ``` -As you can see, `require` takes an object that maps **package names** -(e.g. `monolog/monolog`) to **version constraints** (e.g. `1.0.*`). +As you can see, [`require`](04-schema.md#require) takes an object that maps +**package names** (e.g. `monolog/monolog`) to **version constraints** (e.g. +`1.0.*`). ### Package Names @@ -49,7 +50,7 @@ smaller decoupled parts. In the previous example we were requiring version [`1.0.*`](http://semver.mwl.be/#?package=monolog%2Fmonolog&version=1.0.*) of -monolog. This means any version in the `1.0` development branch. It is the +Monolog. This means any version in the `1.0` development branch. It is the equivalent of saying versions that match `>=1.0 <1.1`. Version constraints can be specified in several ways, read @@ -66,7 +67,7 @@ all packages instead of doing per dependency you can also use the ## Installing Dependencies To install the defined dependencies for your project, just run the -`install` command. +[`install`](03-cli.md#install) command. ```sh php composer.phar install @@ -75,13 +76,14 @@ php composer.phar install This will find the latest version of `monolog/monolog` that matches the supplied version constraint and download it into the `vendor` directory. It's a convention to put third party code into a directory named `vendor`. -In case of monolog it will put it into `vendor/monolog/monolog`. +In case of Monolog it will put it into `vendor/monolog/monolog`. > **Tip:** If you are using git for your project, you probably want to add > `vendor` in your `.gitignore`. You really don't want to add all of that > code to your repository. -You will notice the `install` command also created a `composer.lock` file. +You will notice the [`install`](03-cli.md#install) command also created a +`composer.lock` file. ## `composer.lock` - The Lock File @@ -92,9 +94,9 @@ to those specific versions. **Commit your application's `composer.lock` (along with `composer.json`) into version control.** -This is important because the `install` command checks if a lock file is -present, and if it is, it downloads the versions specified there (regardless -of what `composer.json` says). +This is important because the [`install`](03-cli.md#install) command checks +if a lock file is present, and if it is, it downloads the versions specified +there (regardless of what `composer.json` says). This means that anyone who sets up the project will download the exact same version of the dependencies. Your CI server, production machines, other @@ -106,12 +108,13 @@ if your dependencies released many new versions since then. If no `composer.lock` file exists, Composer will read the dependencies and versions from `composer.json` and create the lock file after executing the -`update` or the `install` command. +[`update`](03-cli.md#update) or the [`install`](03-cli.md#install) command. This means that if any of the dependencies get a new version, you won't get the -updates automatically. To update to the new version, use the `update` command. -This will fetch the latest matching versions (according to your `composer.json` -file) and also update the lock file with the new version. +updates automatically. To update to the new version, use the +[`update`](03-cli.md#update) command. This will fetch the latest matching +versions (according to your `composer.json` file) and also update the lock file +with the new version. ```sh php composer.phar update @@ -125,7 +128,7 @@ If you only want to install or update one dependency, you can whitelist them: php composer.phar update monolog/monolog [...] ``` -> **Note:** For libraries it is not necessarily recommended to commit the lock +> **Note:** For libraries it is not necessary to commit the lock > file, see also: [Libraries - Lock file](02-libraries.md#lock-file). ## Packagist @@ -135,12 +138,12 @@ repository is basically a package source: a place where you can get packages from. Packagist aims to be the central repository that everybody uses. This means that you can automatically `require` any package that is available there. -If you go to the [packagist website](https://packagist.org/) (packagist.org), +If you go to the [Packagist website](https://packagist.org/) (packagist.org), you can browse and search for packages. -Any open source project using Composer should publish their packages on -packagist. A library doesn't need to be on packagist to be used by Composer, but -it makes life quite a bit simpler. +Any open source project using Composer is recommended to publish their packages +on Packagist. A library doesn't need to be on Packagist to be used by Composer, +but it enables discovery and adoption by other developers more quickly. ## Autoloading @@ -153,18 +156,17 @@ require 'vendor/autoload.php'; ``` This makes it really easy to use third party code. For example: If your project -depends on monolog, you can just start using classes from it, and they will be +depends on Monolog, you can just start using classes from it, and they will be autoloaded. ```php $log = new Monolog\Logger('name'); $log->pushHandler(new Monolog\Handler\StreamHandler('app.log', Monolog\Logger::WARNING)); - $log->addWarning('Foo'); ``` -You can even add your own code to the autoloader by adding an `autoload` field -to `composer.json`. +You can even add your own code to the autoloader by adding an +[`autoload`](04-schema.md#autoload) field to `composer.json`. ```json { @@ -181,8 +183,9 @@ You define a mapping from namespaces to directories. The `src` directory would be in your project root, on the same level as `vendor` directory is. An example filename would be `src/Foo.php` containing an `Acme\Foo` class. -After adding the `autoload` field, you have to re-run `dump-autoload` to -re-generate the `vendor/autoload.php` file. +After adding the [`autoload`](04-schema.md#autoload) field, you have to re-run +[`dump-autoload`](03-cli.md#dump-autoload) to re-generate the +`vendor/autoload.php` file. Including that file will also return the autoloader instance, so you can store the return value of the include call in a variable and add more namespaces. @@ -193,9 +196,9 @@ $loader = require 'vendor/autoload.php'; $loader->add('Acme\\Test\\', __DIR__); ``` -In addition to PSR-4 autoloading, classmap is also supported. This allows -classes to be autoloaded even if they do not conform to PSR-4. See the [autoload -reference](04-schema.md#autoload) for more details. +In addition to PSR-4 autoloading, Composer also supports PSR-0, classmap and +files autoloading. See the [`autoload`](04-schema.md#autoload) reference for +more information. > **Note:** Composer provides its own autoloader. If you don't want to use that > one, you can just include `vendor/composer/autoload_*.php` files, which return diff --git a/doc/02-libraries.md b/doc/02-libraries.md index 0749ac53f..da5725e4d 100644 --- a/doc/02-libraries.md +++ b/doc/02-libraries.md @@ -1,16 +1,17 @@ # Libraries -This chapter will tell you how to make your library installable through Composer. +This chapter will tell you how to make your library installable through +Composer. ## Every project is a package As soon as you have a `composer.json` in a directory, that directory is a -package. When you add a `require` to a project, you are making a package that -depends on other packages. The only difference between your project and -libraries is that your project is a package without a name. +package. When you add a [`require`](04-schema.md#require) to a project, you are +making a package that depends on other packages. The only difference between +your project and libraries is that your project is a package without a name. In order to make that package installable you need to give it a name. You do -this by adding a `name` to `composer.json`: +this by adding the [`name`](04-schema.md#name) property in `composer.json`: ```json { @@ -21,12 +22,12 @@ this by adding a `name` to `composer.json`: } ``` -In this case the project name is `acme/hello-world`, where `acme` is the -vendor name. Supplying a vendor name is mandatory. +In this case the project name is `acme/hello-world`, where `acme` is the vendor +name. Supplying a vendor name is mandatory. > **Note:** If you don't know what to use as a vendor name, your GitHub -username is usually a good bet. While package names are case insensitive, the -convention is all lowercase and dashes for word separation. +> username is usually a good bet. While package names are case insensitive, the +> convention is all lowercase and dashes for word separation. ## Platform packages @@ -50,15 +51,14 @@ includes PHP itself, PHP extensions and some system libraries. PHP. The following are available: `curl`, `iconv`, `icu`, `libxml`, `openssl`, `pcre`, `uuid`, `xsl`. -You can use `composer show --platform` to get a list of your locally available -platform packages. +You can use [`show --platform`](03-cli.md#show) to get a list of your locally +available platform packages. ## Specifying the version -You need to specify the package's version some way. When you publish your -package on Packagist, it is able to infer the version from the VCS (git, svn, -hg) information, so in that case you do not have to specify it, and it is -recommended not to. See [tags](#tags) and [branches](#branches) to see how +When you publish your package on Packagist, it is able to infer the version +from the VCS (git, svn, hg) information. This means you don't have to +explicitly declare it. Read [tags](#tags) and [branches](#branches) to see how version numbers are extracted from these. If you are creating packages by hand and really have to specify it explicitly, @@ -76,9 +76,9 @@ you can just add a `version` field: ### Tags For every tag that looks like a version, a package version of that tag will be -created. It should match 'X.Y.Z' or 'vX.Y.Z', with an optional suffix -of `-patch` (`-p`), `-alpha` (`-a`), `-beta` (`-b`) or `-RC`. The suffixes -can also be followed by a number. +created. It should match 'X.Y.Z' or 'vX.Y.Z', with an optional suffix of +`-patch` (`-p`), `-alpha` (`-a`), `-beta` (`-b`) or `-RC`. The suffix can also +be followed by a number. Here are a few examples of valid tag names: @@ -89,19 +89,20 @@ Here are a few examples of valid tag names: - v2.0.0-alpha - v2.0.4-p1 -> **Note:** Even if your tag is prefixed with `v`, a [version constraint](01-basic-usage.md#package-versions) -> in a `require` statement has to be specified without prefix -> (e.g. tag `v1.0.0` will result in version `1.0.0`). +> **Note:** Even if your tag is prefixed with `v`, a +> [version constraint](01-basic-usage.md#package-versions) in a `require` +> statement has to be specified without prefix (e.g. tag `v1.0.0` will result +> in version `1.0.0`). ### Branches For every branch, a package development version will be created. If the branch name looks like a version, the version will be `{branchname}-dev`. For example, -the branch `2.0` will get the `2.0.x-dev` version (the `.x` is added for technical -reasons, to make sure it is recognized as a branch). The `2.0.x` branch would also -be valid and be turned into `2.0.x-dev` as well. If the branch does not look -like a version, it will be `dev-{branchname}`. `master` results in a -`dev-master` version. +the branch `2.0` will get the `2.0.x-dev` version (the `.x` is added for +technical reasons, to make sure it is recognized as a branch). The `2.0.x` +branch would also be valid and be turned into `2.0.x-dev` as well. If the +branch does not look like a version, it will be `dev-{branchname}`. `master` +results in a `dev-master` version. Here are some examples of version branch names: @@ -116,8 +117,8 @@ Here are some examples of version branch names: ### Aliases It is possible to alias branch names to versions. For example, you could alias -`dev-master` to `1.0.x-dev`, which would allow you to require `1.0.x-dev` in all -the packages. +`dev-master` to `1.0.x-dev`, which would allow you to require `1.0.x-dev` in +all the packages. See [Aliases](articles/aliases.md) for more information. @@ -133,7 +134,7 @@ the `.gitignore`. ## Publishing to a VCS -Once you have a vcs repository (version control system, e.g. git) containing a +Once you have a VCS repository (version control system, e.g. git) containing a `composer.json` file, your library is already composer-installable. In this example we will publish the `acme/hello-world` library on GitHub under `github.com/username/hello-world`. @@ -180,11 +181,11 @@ For more details on how package repositories work and what other types are available, see [Repositories](05-repositories.md). That's all. You can now install the dependencies by running Composer's -`install` command! +[`install`](03-cli.md#install) command! **Recap:** Any git/svn/hg repository containing a `composer.json` can be added to your project by specifying the package repository and declaring the -dependency in the `require` field. +dependency in the [`require`](04-schema.md#require) field. ## Publishing to packagist @@ -196,15 +197,16 @@ repository for `monolog/monolog`. How did that work? The answer is Packagist. [Packagist](https://packagist.org/) is the main package repository for Composer, and it is enabled by default. Anything that is published on -Packagist is available automatically through Composer. Since monolog -[is on packagist](https://packagist.org/packages/monolog/monolog), we can depend -on it without having to specify any additional repositories. +Packagist is available automatically through Composer. Since +[Monolog is on Packagist](https://packagist.org/packages/monolog/monolog), we +can depend on it without having to specify any additional repositories. If we wanted to share `hello-world` with the world, we would publish it on Packagist as well. Doing so is really easy. -You simply hit the big "Submit Package" button and sign up. Then you submit -the URL to your VCS repository, at which point Packagist will start crawling -it. Once it is done, your package will be available to anyone. +You simply visit [Packagist](https://packagist.org) and hit the "Submit". This +will prompt you to sign up if you haven't already, and then allows you to +submit the URL to your VCS repository, at which point Packagist will start +crawling it. Once it is done, your package will be available to anyone! ← [Basic usage](01-basic-usage.md) | [Command-line interface](03-cli.md) → From 16a7cf19fcb694c7dac5dd61bdcac332ba041180 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 23 Jun 2015 11:20:10 +0200 Subject: [PATCH 040/205] outside of table, no need to escape --- doc/articles/versions.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/articles/versions.md b/doc/articles/versions.md index b59e5e70e..50af64e7d 100644 --- a/doc/articles/versions.md +++ b/doc/articles/versions.md @@ -20,10 +20,9 @@ Example: `1.0.2` By using comparison operators you can specify ranges of valid versions. Valid operators are `>`, `>=`, `<`, `<=`, `!=`. -You can define multiple ranges. Ranges separated by a space ( ) or -comma (`,`) will be treated as a **logical AND**. A double pipe -(||) will be treated as a **logical OR**. AND has higher -precedence than OR. +You can define multiple ranges. Ranges separated by a space (` `) or comma (`,`) +will be treated as a **logical AND**. A double pipe (`||`) will be treated as a +**logical OR**. AND has higher precedence than OR. Examples: From 6a64041055f2df32e2fd5b01ca15b52272b980ac Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 30 Jun 2015 15:38:32 +0100 Subject: [PATCH 041/205] CS fixes --- src/Composer/Command/CreateProjectCommand.php | 4 ++-- src/Composer/Command/DiagnoseCommand.php | 2 +- src/Composer/Console/Application.php | 2 +- src/Composer/Console/HtmlOutputFormatter.php | 1 + .../DependencyResolver/SolverProblemsException.php | 2 +- src/Composer/Downloader/ArchiveDownloader.php | 2 +- src/Composer/Package/Version/VersionParser.php | 8 ++++---- src/Composer/Util/ErrorHandler.php | 1 + src/Composer/Util/GitHub.php | 1 + .../Composer/Test/EventDispatcher/EventDispatcherTest.php | 1 - tests/Composer/Test/InstallerTest.php | 1 - tests/Composer/Test/Package/BasePackageTest.php | 2 -- .../Test/Package/Loader/RootPackageLoaderTest.php | 1 - .../Test/Package/Loader/ValidatingArrayLoaderTest.php | 1 - tests/Composer/Test/Plugin/PluginInstallerTest.php | 2 +- tests/Composer/Test/Repository/ComposerRepositoryTest.php | 1 - tests/Composer/Test/Util/RemoteFilesystemTest.php | 1 - tests/Composer/TestCase.php | 1 - 18 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index 02aaf6f1b..6efec81be 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -290,8 +290,8 @@ EOT // handler Ctrl+C for unix-like systems if (function_exists('pcntl_signal')) { - declare(ticks = 100); - pcntl_signal(SIGINT, function() use ($directory) { + declare (ticks = 100); + pcntl_signal(SIGINT, function () use ($directory) { $fs = new Filesystem(); $fs->removeDirectory($directory); exit(130); diff --git a/src/Composer/Command/DiagnoseCommand.php b/src/Composer/Command/DiagnoseCommand.php index c279d182c..860f85948 100644 --- a/src/Composer/Command/DiagnoseCommand.php +++ b/src/Composer/Command/DiagnoseCommand.php @@ -295,7 +295,7 @@ EOT private function checkDiskSpace($config) { - $minSpaceFree = 1024*1024; + $minSpaceFree = 1024 * 1024; if ((($df = @disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree) || (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree) ) { diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index ee4f4e9c0..8f92c9c55 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -181,7 +181,7 @@ class Application extends BaseApplication if ($composer) { $config = $composer->getConfig(); - $minSpaceFree = 1024*1024; + $minSpaceFree = 1024 * 1024; if ((($df = @disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree) || (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree) || (($df = @disk_free_space($dir = sys_get_temp_dir())) !== false && $df < $minSpaceFree) diff --git a/src/Composer/Console/HtmlOutputFormatter.php b/src/Composer/Console/HtmlOutputFormatter.php index cb42133c3..f5368b5fe 100644 --- a/src/Composer/Console/HtmlOutputFormatter.php +++ b/src/Composer/Console/HtmlOutputFormatter.php @@ -60,6 +60,7 @@ class HtmlOutputFormatter extends OutputFormatter $formatted = parent::format($message); $clearEscapeCodes = '(?:39|49|0|22|24|25|27|28)'; + return preg_replace_callback("{\033\[([0-9;]+)m(.*?)\033\[(?:".$clearEscapeCodes.";)*?".$clearEscapeCodes."m}s", array($this, 'formatHtml'), $formatted); } diff --git a/src/Composer/DependencyResolver/SolverProblemsException.php b/src/Composer/DependencyResolver/SolverProblemsException.php index 308172bcc..9973f9d39 100644 --- a/src/Composer/DependencyResolver/SolverProblemsException.php +++ b/src/Composer/DependencyResolver/SolverProblemsException.php @@ -32,7 +32,7 @@ class SolverProblemsException extends \RuntimeException { $text = "\n"; foreach ($this->problems as $i => $problem) { - $text .= " Problem ".($i+1).$problem->getPrettyString($this->installedMap)."\n"; + $text .= " Problem ".($i + 1).$problem->getPrettyString($this->installedMap)."\n"; } if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) { diff --git a/src/Composer/Downloader/ArchiveDownloader.php b/src/Composer/Downloader/ArchiveDownloader.php index ff0b9e338..4f41285c8 100644 --- a/src/Composer/Downloader/ArchiveDownloader.php +++ b/src/Composer/Downloader/ArchiveDownloader.php @@ -115,7 +115,7 @@ abstract class ArchiveDownloader extends FileDownloader // update api archives to the proper reference $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $package->getDistReference(); } - } else if ($package->getDistReference() && strpos($url, 'bitbucket.org')) { + } elseif ($package->getDistReference() && strpos($url, 'bitbucket.org')) { if (preg_match('{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i', $url, $match)) { // update Bitbucket archives to the proper reference $url = 'https://bitbucket.org/' . $match[1] . '/'. $match[2] . '/get/' . $package->getDistReference() . '.' . $match[4]; diff --git a/src/Composer/Package/Version/VersionParser.php b/src/Composer/Package/Version/VersionParser.php index c1cd4d229..e199838f2 100644 --- a/src/Composer/Package/Version/VersionParser.php +++ b/src/Composer/Package/Version/VersionParser.php @@ -141,10 +141,10 @@ class VersionParser if ('stable' === $matches[$index]) { return $version; } - $version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index+1]) ? $matches[$index+1] : ''); + $version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? $matches[$index + 1] : ''); } - if (!empty($matches[$index+2])) { + if (!empty($matches[$index + 2])) { $version .= '-dev'; } @@ -530,8 +530,8 @@ class VersionParser for ($i = 0, $count = count($pairs); $i < $count; $i++) { $pair = preg_replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', trim($pairs[$i])); - if (false === strpos($pair, ' ') && isset($pairs[$i+1]) && false === strpos($pairs[$i+1], '/')) { - $pair .= ' '.$pairs[$i+1]; + if (false === strpos($pair, ' ') && isset($pairs[$i + 1]) && false === strpos($pairs[$i + 1], '/')) { + $pair .= ' '.$pairs[$i + 1]; $i++; } diff --git a/src/Composer/Util/ErrorHandler.php b/src/Composer/Util/ErrorHandler.php index b10cb15d5..399491f8c 100644 --- a/src/Composer/Util/ErrorHandler.php +++ b/src/Composer/Util/ErrorHandler.php @@ -58,6 +58,7 @@ class ErrorHandler if (isset($a['line'], $a['file'])) { return ' '.$a['file'].':'.$a['line'].''; } + return null; }, array_slice(debug_backtrace(), 2)))); } diff --git a/src/Composer/Util/GitHub.php b/src/Composer/Util/GitHub.php index 369214e5d..8aaa7db65 100644 --- a/src/Composer/Util/GitHub.php +++ b/src/Composer/Util/GitHub.php @@ -94,6 +94,7 @@ class GitHub if (!$token) { $this->io->writeError('No token given, aborting.'); $this->io->writeError('You can also add it manually later by using "composer config github-oauth.github.com "'); + return false; } diff --git a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php index 06d9c652d..a44c6bc5d 100644 --- a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php +++ b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php @@ -13,7 +13,6 @@ namespace Composer\Test\EventDispatcher; use Composer\EventDispatcher\Event; -use Composer\EventDispatcher\EventDispatcher; use Composer\Installer\InstallerEvents; use Composer\TestCase; use Composer\Script\ScriptEvents; diff --git a/tests/Composer/Test/InstallerTest.php b/tests/Composer/Test/InstallerTest.php index 7fa85d76d..16024f517 100644 --- a/tests/Composer/Test/InstallerTest.php +++ b/tests/Composer/Test/InstallerTest.php @@ -14,7 +14,6 @@ namespace Composer\Test; use Composer\Installer; use Composer\Console\Application; -use Composer\Config; use Composer\Json\JsonFile; use Composer\Repository\ArrayRepository; use Composer\Repository\RepositoryManager; diff --git a/tests/Composer/Test/Package/BasePackageTest.php b/tests/Composer/Test/Package/BasePackageTest.php index 1fe0ece84..23c656a4e 100644 --- a/tests/Composer/Test/Package/BasePackageTest.php +++ b/tests/Composer/Test/Package/BasePackageTest.php @@ -12,8 +12,6 @@ namespace Composer\Test\Package; -use Composer\Package\BasePackage; - class BasePackageTest extends \PHPUnit_Framework_TestCase { public function testSetSameRepository() diff --git a/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php b/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php index 37c259676..fc3192414 100644 --- a/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php +++ b/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php @@ -16,7 +16,6 @@ use Composer\Config; use Composer\Package\Loader\RootPackageLoader; use Composer\Package\BasePackage; use Composer\Test\Mock\ProcessExecutorMock; -use Composer\Repository\RepositoryManager; class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase { diff --git a/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php b/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php index 075ee8253..ab61b6c15 100644 --- a/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php +++ b/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php @@ -12,7 +12,6 @@ namespace Composer\Test\Package\Loader; -use Composer\Package; use Composer\Package\Loader\ValidatingArrayLoader; use Composer\Package\Loader\InvalidPackageException; diff --git a/tests/Composer/Test/Plugin/PluginInstallerTest.php b/tests/Composer/Test/Plugin/PluginInstallerTest.php index cd05b922f..4af7197f7 100644 --- a/tests/Composer/Test/Plugin/PluginInstallerTest.php +++ b/tests/Composer/Test/Plugin/PluginInstallerTest.php @@ -242,7 +242,7 @@ class PluginInstallerTest extends TestCase $this->repository ->expects($this->any()) ->method('getPackages') - ->will($this->returnCallback(function() use($plugApiInternalPackage, $plugins) { + ->will($this->returnCallback(function () use ($plugApiInternalPackage, $plugins) { return array_merge(array($plugApiInternalPackage), $plugins); })); diff --git a/tests/Composer/Test/Repository/ComposerRepositoryTest.php b/tests/Composer/Test/Repository/ComposerRepositoryTest.php index 5109ee41f..6f21f9d9c 100644 --- a/tests/Composer/Test/Repository/ComposerRepositoryTest.php +++ b/tests/Composer/Test/Repository/ComposerRepositoryTest.php @@ -12,7 +12,6 @@ namespace Composer\Test\Repository; -use Composer\Repository\ComposerRepository; use Composer\IO\NullIO; use Composer\Test\Mock\FactoryMock; use Composer\TestCase; diff --git a/tests/Composer/Test/Util/RemoteFilesystemTest.php b/tests/Composer/Test/Util/RemoteFilesystemTest.php index 04502ebdc..1bb3e0689 100644 --- a/tests/Composer/Test/Util/RemoteFilesystemTest.php +++ b/tests/Composer/Test/Util/RemoteFilesystemTest.php @@ -13,7 +13,6 @@ namespace Composer\Test\Util; use Composer\Util\RemoteFilesystem; -use Installer\Exception; class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase { diff --git a/tests/Composer/TestCase.php b/tests/Composer/TestCase.php index 760b57291..4abf1a7ff 100644 --- a/tests/Composer/TestCase.php +++ b/tests/Composer/TestCase.php @@ -13,7 +13,6 @@ namespace Composer; use Composer\Package\Version\VersionParser; -use Composer\Package\Package; use Composer\Package\AliasPackage; use Composer\Package\LinkConstraint\VersionConstraint; use Composer\Util\Filesystem; From 962f5a99eab21e78d0679eb2606af93e44426b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Mo=CC=88ller?= Date: Mon, 29 Jun 2015 09:52:37 -0400 Subject: [PATCH 042/205] Fix: Import Symfony\Component\Finder\Finder --- src/Composer/Package/Archiver/ArchivableFilesFinder.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Composer/Package/Archiver/ArchivableFilesFinder.php b/src/Composer/Package/Archiver/ArchivableFilesFinder.php index 44c682616..1e94f1e15 100644 --- a/src/Composer/Package/Archiver/ArchivableFilesFinder.php +++ b/src/Composer/Package/Archiver/ArchivableFilesFinder.php @@ -13,8 +13,7 @@ namespace Composer\Package\Archiver; use Composer\Util\Filesystem; - -use Symfony\Component\Finder; +use Symfony\Component\Finder\Finder; /** * A Symfony Finder wrapper which locates files that should go into archives @@ -27,7 +26,7 @@ use Symfony\Component\Finder; class ArchivableFilesFinder extends \FilterIterator { /** - * @var Symfony\Component\Finder\Finder + * @var Finder */ protected $finder; @@ -49,7 +48,7 @@ class ArchivableFilesFinder extends \FilterIterator new ComposerExcludeFilter($sources, $excludes), ); - $this->finder = new Finder\Finder(); + $this->finder = new Finder(); $filter = function (\SplFileInfo $file) use ($sources, $filters, $fs) { if ($file->isLink() && strpos($file->getLinkTarget(), $sources) !== 0) { From 56ffa407f15a719577f72aeee991152c6a6658a3 Mon Sep 17 00:00:00 2001 From: Jonathan Eskew Date: Wed, 1 Jul 2015 09:15:22 -0700 Subject: [PATCH 043/205] House style requires concatenation in examples --- doc/articles/scripts.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index 5ea5204f7..db983a233 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -83,10 +83,8 @@ and command-line executable commands. - PHP classes containing defined callbacks must be autoloadable via Composer's autoload functionality. - If a defined callback relies on functions defined outside of a class, the -callback must explicitly require the composer autoloader. If used in a -context where`vendor/autoload.php` might not yet exist (such as during a -`pre-install` or `pre-update` command), the callback should explicitly require -whatever files within your root package it needs to execute successfully. +callback itself is responsible for loading the appropriate files, as no files +are autoloaded during Composer commands. Script definition example: @@ -130,7 +128,7 @@ class MyClass public static function postAutoloadDump(Event $event) { $vendorDir = $event->getComposer()->getConfig()->get('vendor-dir'); - require "$vendorDir/autoload.php"; + require $vendorDir . '/autoload.php'; some_function_from_an_autoloaded_file(); } From 4e3fbeabfcdfc03d1bb2fd4996ad54c3b08d4d09 Mon Sep 17 00:00:00 2001 From: Jonathan Eskew Date: Wed, 1 Jul 2015 09:38:14 -0700 Subject: [PATCH 044/205] "No files" was inaccurate; amend to specify "no files except" --- doc/articles/scripts.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index db983a233..8d9eaa17e 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -84,7 +84,8 @@ and command-line executable commands. autoload functionality. - If a defined callback relies on functions defined outside of a class, the callback itself is responsible for loading the appropriate files, as no files -are autoloaded during Composer commands. +beyond those required for `psr-0`, `psr-4`, and `classmap` autoloading are +loaded during Composer commands. Script definition example: @@ -99,6 +100,9 @@ Script definition example: "MyVendor\\MyClass::warmCache", "phpunit -c app/" ], + "post-autoload-dump": [ + "MyVendor\\MyClass::postAutoloadDump" + ] "post-create-project-cmd" : [ "php -r \"copy('config/local-example.php', 'config/local.php');\"" ] From 558fca8a23434b5cd1875decc2e2d6c05ac31c14 Mon Sep 17 00:00:00 2001 From: Jeremy Postlethwaite Date: Wed, 1 Jul 2015 14:15:24 -0700 Subject: [PATCH 045/205] Changing config.json to satis.json Updating docs to use `satis.json` instead of `config.json` --- doc/articles/handling-private-packages-with-satis.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/articles/handling-private-packages-with-satis.md b/doc/articles/handling-private-packages-with-satis.md index e7ce665b6..4294de4fb 100644 --- a/doc/articles/handling-private-packages-with-satis.md +++ b/doc/articles/handling-private-packages-with-satis.md @@ -73,7 +73,7 @@ constraint if you want really specific versions. ``` Once you've done this, you just run `php bin/satis build `. -For example `php bin/satis build config.json web/` would read the `config.json` +For example `php bin/satis build satis.json web/` would read the `satis.json` file and build a static repository inside the `web/` directory. When you ironed out that process, what you would typically do is run this From 99dab8aebdef0f833294268af026069f6f1368cf Mon Sep 17 00:00:00 2001 From: Kunal Mehta Date: Sat, 30 May 2015 23:24:20 -0700 Subject: [PATCH 046/205] Move VersionParser::formatVersion() to BasePackage::getFullPrettyVersion() Working towards #3545. formatVersion() does not belong in VersionParser since it depends upon a Package object, and is creating a more complete pretty formatted version, not parsing anything. The new getFullPrettyVersion() method can be seen as an extension to getPrettyVersion(), and is located in BasePackage as a result. Callers to VersionParser::formatVersion() were not updated in this commit to demonstrate that no functionality was changed in this refactor. They will be updated in a follow up commit. --- src/Composer/Package/BasePackage.php | 17 +++++++++++++++++ src/Composer/Package/PackageInterface.php | 10 ++++++++++ src/Composer/Package/Version/VersionParser.php | 11 +---------- .../Test/Package/Version/VersionParserTest.php | 2 +- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/Composer/Package/BasePackage.php b/src/Composer/Package/BasePackage.php index 965e5ddc8..9b2a683ca 100644 --- a/src/Composer/Package/BasePackage.php +++ b/src/Composer/Package/BasePackage.php @@ -206,6 +206,23 @@ abstract class BasePackage implements PackageInterface return $this->getPrettyName().' '.$this->getPrettyVersion(); } + /** + * {@inheritDoc} + */ + public function getFullPrettyVersion($truncate = true) + { + if (!$this->isDev() || !in_array($this->getSourceType(), array('hg', 'git'))) { + return $this->getPrettyVersion(); + } + + // if source reference is a sha1 hash -- truncate + if ($truncate && strlen($this->getSourceReference()) === 40) { + return $this->getPrettyVersion() . ' ' . substr($this->getSourceReference(), 0, 7); + } + + return $this->getPrettyVersion() . ' ' . $this->getSourceReference(); + } + public function __clone() { $this->repository = null; diff --git a/src/Composer/Package/PackageInterface.php b/src/Composer/Package/PackageInterface.php index a51274d5b..ba34619f1 100644 --- a/src/Composer/Package/PackageInterface.php +++ b/src/Composer/Package/PackageInterface.php @@ -192,6 +192,16 @@ interface PackageInterface */ public function getPrettyVersion(); + /** + * Returns the pretty version string plus a git or hg commit hash of this package + * + * @see getPrettyVersion + * + * @param bool $truncate If the source reference is a sha1 hash, truncate it + * @return string version + */ + public function getFullPrettyVersion($truncate = true); + /** * Returns the release date of the package * diff --git a/src/Composer/Package/Version/VersionParser.php b/src/Composer/Package/Version/VersionParser.php index e199838f2..ee49e81c8 100644 --- a/src/Composer/Package/Version/VersionParser.php +++ b/src/Composer/Package/Version/VersionParser.php @@ -71,16 +71,7 @@ class VersionParser public static function formatVersion(PackageInterface $package, $truncate = true) { - if (!$package->isDev() || !in_array($package->getSourceType(), array('hg', 'git'))) { - return $package->getPrettyVersion(); - } - - // if source reference is a sha1 hash -- truncate - if ($truncate && strlen($package->getSourceReference()) === 40) { - return $package->getPrettyVersion() . ' ' . substr($package->getSourceReference(), 0, 7); - } - - return $package->getPrettyVersion() . ' ' . $package->getSourceReference(); + return $package->getFullPrettyVersion($truncate); } /** diff --git a/tests/Composer/Test/Package/Version/VersionParserTest.php b/tests/Composer/Test/Package/Version/VersionParserTest.php index d8f351a27..18551570d 100644 --- a/tests/Composer/Test/Package/Version/VersionParserTest.php +++ b/tests/Composer/Test/Package/Version/VersionParserTest.php @@ -56,7 +56,7 @@ class VersionParserTest extends \PHPUnit_Framework_TestCase $self = $this; $createPackage = function ($arr) use ($self) { - $package = $self->getMock('\Composer\Package\PackageInterface'); + $package = $self->getMockForAbstractClass('\Composer\Package\BasePackage', array(), '', false); $package->expects($self->once())->method('isDev')->will($self->returnValue(true)); $package->expects($self->once())->method('getSourceType')->will($self->returnValue('git')); $package->expects($self->once())->method('getPrettyVersion')->will($self->returnValue('PrettyVersion')); From f634c6946dcd0f478da65188a1715c612f913ccd Mon Sep 17 00:00:00 2001 From: Kunal Mehta Date: Sat, 30 May 2015 23:30:52 -0700 Subject: [PATCH 047/205] Update callers of VersionParser::formatVersion() Tests were moved to BasePackageTest. --- src/Composer/Command/CreateProjectCommand.php | 2 +- src/Composer/Command/LicensesCommand.php | 11 ++--- src/Composer/Command/ShowCommand.php | 4 +- .../Operation/SolverOperation.php | 3 +- src/Composer/Downloader/FileDownloader.php | 5 +- src/Composer/Downloader/VcsDownloader.php | 7 ++- .../Composer/Test/Package/BasePackageTest.php | 49 +++++++++++++++++++ .../Package/Version/VersionParserTest.php | 46 ----------------- 8 files changed, 62 insertions(+), 65 deletions(-) diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index 6efec81be..d6c68a94f 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -298,7 +298,7 @@ EOT }); } - $io->writeError('Installing ' . $package->getName() . ' (' . VersionParser::formatVersion($package, false) . ')'); + $io->writeError('Installing ' . $package->getName() . ' (' . $package->getFullPrettyVersion(false) . ')'); if ($disablePlugins) { $io->writeError('Plugins have been disabled.'); diff --git a/src/Composer/Command/LicensesCommand.php b/src/Composer/Command/LicensesCommand.php index ddeabf00f..4ba8ed09d 100644 --- a/src/Composer/Command/LicensesCommand.php +++ b/src/Composer/Command/LicensesCommand.php @@ -13,7 +13,6 @@ namespace Composer\Command; use Composer\Json\JsonFile; -use Composer\Package\Version\VersionParser; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Package\PackageInterface; @@ -56,8 +55,6 @@ EOT $root = $composer->getPackage(); $repo = $composer->getRepositoryManager()->getLocalRepository(); - $versionParser = new VersionParser; - if ($input->getOption('no-dev')) { $packages = $this->filterRequiredPackages($repo, $root); } else { @@ -69,7 +66,7 @@ EOT switch ($format = $input->getOption('format')) { case 'text': $this->getIO()->write('Name: '.$root->getPrettyName().''); - $this->getIO()->write('Version: '.$versionParser->formatVersion($root).''); + $this->getIO()->write('Version: '.$root->getFullPrettyVersion().''); $this->getIO()->write('Licenses: '.(implode(', ', $root->getLicense()) ?: 'none').''); $this->getIO()->write('Dependencies:'); $this->getIO()->write(''); @@ -82,7 +79,7 @@ EOT foreach ($packages as $package) { $table->addRow(array( $package->getPrettyName(), - $versionParser->formatVersion($package), + $package->getFullPrettyVersion(), implode(', ', $package->getLicense()) ?: 'none', )); } @@ -92,14 +89,14 @@ EOT case 'json': foreach ($packages as $package) { $dependencies[$package->getPrettyName()] = array( - 'version' => $versionParser->formatVersion($package), + 'version' => $package->getFullPrettyVersion(), 'license' => $package->getLicense(), ); } $this->getIO()->write(JsonFile::encode(array( 'name' => $root->getPrettyName(), - 'version' => $versionParser->formatVersion($root), + 'version' => $root->getFullPrettyVersion(), 'license' => $root->getLicense(), 'dependencies' => $dependencies, ))); diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index b4f5de49b..6c768bf60 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -181,7 +181,7 @@ EOT foreach ($packages[$type] as $package) { if (is_object($package)) { $nameLength = max($nameLength, strlen($package->getPrettyName())); - $versionLength = max($versionLength, strlen($this->versionParser->formatVersion($package))); + $versionLength = max($versionLength, strlen($package->getFullPrettyVersion())); } else { $nameLength = max($nameLength, $package); } @@ -209,7 +209,7 @@ EOT $output->write($indent . str_pad($package->getPrettyName(), $nameLength, ' '), false); if ($writeVersion) { - $output->write(' ' . str_pad($this->versionParser->formatVersion($package), $versionLength, ' '), false); + $output->write(' ' . str_pad($package->getFullPrettyVersion(), $versionLength, ' '), false); } if ($writeDescription) { diff --git a/src/Composer/DependencyResolver/Operation/SolverOperation.php b/src/Composer/DependencyResolver/Operation/SolverOperation.php index a4e8384d3..e1a68585e 100644 --- a/src/Composer/DependencyResolver/Operation/SolverOperation.php +++ b/src/Composer/DependencyResolver/Operation/SolverOperation.php @@ -12,7 +12,6 @@ namespace Composer\DependencyResolver\Operation; -use Composer\Package\Version\VersionParser; use Composer\Package\PackageInterface; /** @@ -46,6 +45,6 @@ abstract class SolverOperation implements OperationInterface protected function formatVersion(PackageInterface $package) { - return VersionParser::formatVersion($package); + return $package->getFullPrettyVersion(); } } diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index 04f8fc4b5..0a2c3a6e5 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -16,7 +16,6 @@ use Composer\Config; use Composer\Cache; use Composer\IO\IOInterface; use Composer\Package\PackageInterface; -use Composer\Package\Version\VersionParser; use Composer\Plugin\PluginEvents; use Composer\Plugin\PreFileDownloadEvent; use Composer\EventDispatcher\EventDispatcher; @@ -81,7 +80,7 @@ class FileDownloader implements DownloaderInterface throw new \InvalidArgumentException('The given package is missing url information'); } - $this->io->writeError(" - Installing " . $package->getName() . " (" . VersionParser::formatVersion($package) . ")"); + $this->io->writeError(" - Installing " . $package->getName() . " (" . $package->getFullPrettyVersion() . ")"); $urls = $package->getDistUrls(); while ($url = array_shift($urls)) { @@ -205,7 +204,7 @@ class FileDownloader implements DownloaderInterface */ public function remove(PackageInterface $package, $path) { - $this->io->writeError(" - Removing " . $package->getName() . " (" . VersionParser::formatVersion($package) . ")"); + $this->io->writeError(" - Removing " . $package->getName() . " (" . $package->getFullPrettyVersion() . ")"); if (!$this->filesystem->removeDirectory($path)) { throw new \RuntimeException('Could not completely delete '.$path.', aborting.'); } diff --git a/src/Composer/Downloader/VcsDownloader.php b/src/Composer/Downloader/VcsDownloader.php index 254f6143d..c77dd439b 100644 --- a/src/Composer/Downloader/VcsDownloader.php +++ b/src/Composer/Downloader/VcsDownloader.php @@ -14,7 +14,6 @@ namespace Composer\Downloader; use Composer\Config; use Composer\Package\PackageInterface; -use Composer\Package\Version\VersionParser; use Composer\Util\ProcessExecutor; use Composer\IO\IOInterface; use Composer\Util\Filesystem; @@ -54,7 +53,7 @@ abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterfa throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information'); } - $this->io->writeError(" - Installing " . $package->getName() . " (" . VersionParser::formatVersion($package) . ")"); + $this->io->writeError(" - Installing " . $package->getName() . " (" . $package->getFullPrettyVersion() . ")"); $this->filesystem->emptyDirectory($path); $urls = $package->getSourceUrls(); @@ -100,8 +99,8 @@ abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterfa } $name .= ' '.$initial->getPrettyVersion(); } else { - $from = VersionParser::formatVersion($initial); - $to = VersionParser::formatVersion($target); + $from = $initial->getFullPrettyVersion(); + $to = $target->getFullPrettyVersion(); } $this->io->writeError(" - Updating " . $name . " (" . $from . " => " . $to . ")"); diff --git a/tests/Composer/Test/Package/BasePackageTest.php b/tests/Composer/Test/Package/BasePackageTest.php index 23c656a4e..d8d4ac8ed 100644 --- a/tests/Composer/Test/Package/BasePackageTest.php +++ b/tests/Composer/Test/Package/BasePackageTest.php @@ -12,6 +12,8 @@ namespace Composer\Test\Package; +use Composer\Package\BasePackage; + class BasePackageTest extends \PHPUnit_Framework_TestCase { public function testSetSameRepository() @@ -37,4 +39,51 @@ class BasePackageTest extends \PHPUnit_Framework_TestCase $package->setRepository($this->getMock('Composer\Repository\RepositoryInterface')); $package->setRepository($this->getMock('Composer\Repository\RepositoryInterface')); } + + /** + * @dataProvider formattedVersions + */ + public function testFormatVersionForDevPackage(BasePackage $package, $truncate, $expected) + { + $this->assertSame($expected, $package->getFullPrettyVersion($truncate)); + } + + public function formattedVersions() + { + $data = array( + array( + 'sourceReference' => 'v2.1.0-RC2', + 'truncate' => true, + 'expected' => 'PrettyVersion v2.1.0-RC2' + ), + array( + 'sourceReference' => 'bbf527a27356414bfa9bf520f018c5cb7af67c77', + 'truncate' => true, + 'expected' => 'PrettyVersion bbf527a' + ), + array( + 'sourceReference' => 'v1.0.0', + 'truncate' => false, + 'expected' => 'PrettyVersion v1.0.0' + ), + array( + 'sourceReference' => 'bbf527a27356414bfa9bf520f018c5cb7af67c77', + 'truncate' => false, + 'expected' => 'PrettyVersion bbf527a27356414bfa9bf520f018c5cb7af67c77' + ), + ); + + $self = $this; + $createPackage = function ($arr) use ($self) { + $package = $self->getMockForAbstractClass('\Composer\Package\BasePackage', array(), '', false); + $package->expects($self->once())->method('isDev')->will($self->returnValue(true)); + $package->expects($self->once())->method('getSourceType')->will($self->returnValue('git')); + $package->expects($self->once())->method('getPrettyVersion')->will($self->returnValue('PrettyVersion')); + $package->expects($self->any())->method('getSourceReference')->will($self->returnValue($arr['sourceReference'])); + + return array($package, $arr['truncate'], $arr['expected']); + }; + + return array_map($createPackage, $data); + } } diff --git a/tests/Composer/Test/Package/Version/VersionParserTest.php b/tests/Composer/Test/Package/Version/VersionParserTest.php index 18551570d..632727165 100644 --- a/tests/Composer/Test/Package/Version/VersionParserTest.php +++ b/tests/Composer/Test/Package/Version/VersionParserTest.php @@ -21,52 +21,6 @@ use Composer\Package\PackageInterface; class VersionParserTest extends \PHPUnit_Framework_TestCase { - /** - * @dataProvider formattedVersions - */ - public function testFormatVersionForDevPackage(PackageInterface $package, $truncate, $expected) - { - $this->assertSame($expected, VersionParser::formatVersion($package, $truncate)); - } - - public function formattedVersions() - { - $data = array( - array( - 'sourceReference' => 'v2.1.0-RC2', - 'truncate' => true, - 'expected' => 'PrettyVersion v2.1.0-RC2' - ), - array( - 'sourceReference' => 'bbf527a27356414bfa9bf520f018c5cb7af67c77', - 'truncate' => true, - 'expected' => 'PrettyVersion bbf527a' - ), - array( - 'sourceReference' => 'v1.0.0', - 'truncate' => false, - 'expected' => 'PrettyVersion v1.0.0' - ), - array( - 'sourceReference' => 'bbf527a27356414bfa9bf520f018c5cb7af67c77', - 'truncate' => false, - 'expected' => 'PrettyVersion bbf527a27356414bfa9bf520f018c5cb7af67c77' - ), - ); - - $self = $this; - $createPackage = function ($arr) use ($self) { - $package = $self->getMockForAbstractClass('\Composer\Package\BasePackage', array(), '', false); - $package->expects($self->once())->method('isDev')->will($self->returnValue(true)); - $package->expects($self->once())->method('getSourceType')->will($self->returnValue('git')); - $package->expects($self->once())->method('getPrettyVersion')->will($self->returnValue('PrettyVersion')); - $package->expects($self->any())->method('getSourceReference')->will($self->returnValue($arr['sourceReference'])); - - return array($package, $arr['truncate'], $arr['expected']); - }; - - return array_map($createPackage, $data); - } /** * @dataProvider numericAliasVersions From c5afb8f23abdf149dd1a52bf6a87bf99a26408cc Mon Sep 17 00:00:00 2001 From: Kunal Mehta Date: Sun, 31 May 2015 13:45:38 -0700 Subject: [PATCH 048/205] Mark VersionParser::formatVersion() as deprecated With 1753c275ff, this will be handled nicely. --- src/Composer/Package/Version/VersionParser.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Composer/Package/Version/VersionParser.php b/src/Composer/Package/Version/VersionParser.php index ee49e81c8..dabf40a7b 100644 --- a/src/Composer/Package/Version/VersionParser.php +++ b/src/Composer/Package/Version/VersionParser.php @@ -69,8 +69,14 @@ class VersionParser return $stability === 'rc' ? 'RC' : $stability; } + /** + * @deprecated Use PackageInterface::getFullPrettyVersion instead + */ public static function formatVersion(PackageInterface $package, $truncate = true) { + trigger_error(__METHOD__.' is deprecated. Use '. + '\Composer\Package\PackageInterface::getFullPrettyVersion() instead', E_USER_DEPRECATED); + return $package->getFullPrettyVersion($truncate); } From e4118385a0bbf7748e22939f678fd53b408f115b Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Thu, 2 Jul 2015 11:23:15 +0200 Subject: [PATCH 049/205] updated spdx related files --- bin/update-spdx-licenses | 5 +- res/spdx-exceptions.json | 29 ++++ res/spdx-licenses.json | 90 +++--------- src/Composer/Util/SpdxLicense.php | 141 ++++++++++++++----- src/Composer/Util/SpdxLicensesUpdater.php | 96 +++++++++++-- tests/Composer/Test/Util/SpdxLicenseTest.php | 13 ++ 6 files changed, 257 insertions(+), 117 deletions(-) mode change 100644 => 100755 bin/update-spdx-licenses create mode 100644 res/spdx-exceptions.json diff --git a/bin/update-spdx-licenses b/bin/update-spdx-licenses old mode 100644 new mode 100755 index e509ded93..f6b6f9209 --- a/bin/update-spdx-licenses +++ b/bin/update-spdx-licenses @@ -5,5 +5,6 @@ require __DIR__ . '/../src/bootstrap.php'; use Composer\Util\SpdxLicensesUpdater; -$licenses = new SpdxLicensesUpdater; -$licenses->update(); +$updater = new SpdxLicensesUpdater; +$updater->dumpLicenses(__DIR__ . '/../res/spdx-licenses.json'); +$updater->dumpExceptions(__DIR__ . '/../res/spdx-exceptions.json'); diff --git a/res/spdx-exceptions.json b/res/spdx-exceptions.json new file mode 100644 index 000000000..15491d2a5 --- /dev/null +++ b/res/spdx-exceptions.json @@ -0,0 +1,29 @@ +{ + "Autoconf-exception-2.0": [ + "Autoconf exception 2.0" + ], + "Autoconf-exception-3.0": [ + "Autoconf exception 3.0" + ], + "Bison-exception-2.2": [ + "Bison exception 2.2" + ], + "Classpath-exception-2.0": [ + "Classpath exception 2.0" + ], + "eCos-exception-2.0": [ + "eCos exception 2.0" + ], + "Font-exception-2.0": [ + "Font exception 2.0" + ], + "GCC-exception-2.0": [ + "GCC Runtime Library exception 2.0" + ], + "GCC-exception-3.1": [ + "GCC Runtime Library exception 3.1" + ], + "WxWindows-exception-3.1": [ + "WxWindows Library Exception 3.1" + ] +} \ No newline at end of file diff --git a/res/spdx-licenses.json b/res/spdx-licenses.json index 3e1d93c35..7cb654966 100644 --- a/res/spdx-licenses.json +++ b/res/spdx-licenses.json @@ -431,10 +431,6 @@ "Eclipse Public License 1.0", true ], - "eCos-2.0": [ - "eCos license version 2.0", - false - ], "ECL-1.0": [ "Educational Community License v1.0", true @@ -499,6 +495,10 @@ "Frameworx Open License 1.0", true ], + "FreeImage": [ + "FreeImage Public License v1.0", + false + ], "FTL": [ "Freetype Project License", false @@ -543,78 +543,26 @@ "GNU General Public License v1.0 only", false ], - "GPL-1.0+": [ - "GNU General Public License v1.0 or later", - false - ], "GPL-2.0": [ "GNU General Public License v2.0 only", true ], - "GPL-2.0+": [ - "GNU General Public License v2.0 or later", - true - ], - "GPL-2.0-with-autoconf-exception": [ - "GNU General Public License v2.0 w/Autoconf exception", - true - ], - "GPL-2.0-with-bison-exception": [ - "GNU General Public License v2.0 w/Bison exception", - true - ], - "GPL-2.0-with-classpath-exception": [ - "GNU General Public License v2.0 w/Classpath exception", - true - ], - "GPL-2.0-with-font-exception": [ - "GNU General Public License v2.0 w/Font exception", - true - ], - "GPL-2.0-with-GCC-exception": [ - "GNU General Public License v2.0 w/GCC Runtime Library exception", - true - ], "GPL-3.0": [ "GNU General Public License v3.0 only", true ], - "GPL-3.0+": [ - "GNU General Public License v3.0 or later", - true - ], - "GPL-3.0-with-autoconf-exception": [ - "GNU General Public License v3.0 w/Autoconf exception", - true - ], - "GPL-3.0-with-GCC-exception": [ - "GNU General Public License v3.0 w/GCC Runtime Library exception", - true - ], "LGPL-2.1": [ "GNU Lesser General Public License v2.1 only", true ], - "LGPL-2.1+": [ - "GNU Lesser General Public License v2.1 or later", - true - ], "LGPL-3.0": [ "GNU Lesser General Public License v3.0 only", true ], - "LGPL-3.0+": [ - "GNU Lesser General Public License v3.0 or later", - true - ], "LGPL-2.0": [ "GNU Library General Public License v2 only", true ], - "LGPL-2.0+": [ - "GNU Library General Public License v2 or later", - true - ], "gnuplot": [ "gnuplot License", false @@ -927,6 +875,10 @@ "Open LDAP Public License v2.7", false ], + "OLDAP-2.8": [ + "Open LDAP Public License v2.8", + false + ], "OML": [ "Open Market License", false @@ -955,10 +907,6 @@ "Open Software License 3.0", true ], - "OLDAP-2.8": [ - "OpenLDAP Public License v2.8", - false - ], "OpenSSL": [ "OpenSSL License", false @@ -1079,10 +1027,6 @@ "Standard ML of New Jersey License", false ], - "StandardML-NJ": [ - "Standard ML of New Jersey License", - false - ], "SugarCRM-1.1.3": [ "SugarCRM Public License v1.1.3", false @@ -1144,17 +1088,17 @@ true ], "W3C": [ - "W3C Software Notice and License", + "W3C Software Notice and License (2002-12-31)", true ], + "W3C-19980720": [ + "W3C Software Notice and License (1998-07-20)", + false + ], "Wsuipa": [ "Wsuipa License", false ], - "WXwindows": [ - "wxWindows Library License", - true - ], "Xnet": [ "X.Net License", true @@ -1203,6 +1147,10 @@ "Zimbra Public License v1.3", false ], + "Zimbra-1.4": [ + "Zimbra Public License v1.4", + false + ], "Zlib": [ "zlib License", true @@ -1222,5 +1170,9 @@ "ZPL-2.1": [ "Zope Public License 2.1", false + ], + "ICU": [ + "ICU License", + false ] } \ No newline at end of file diff --git a/src/Composer/Util/SpdxLicense.php b/src/Composer/Util/SpdxLicense.php index 650b918e4..b9ffdc70d 100644 --- a/src/Composer/Util/SpdxLicense.php +++ b/src/Composer/Util/SpdxLicense.php @@ -12,8 +12,6 @@ namespace Composer\Util; -use Composer\Json\JsonFile; - /** * Supports composer array and SPDX tag notation for disjunctive/conjunctive * licenses. @@ -22,53 +20,60 @@ use Composer\Json\JsonFile; */ class SpdxLicense { - /** - * @var array - */ + /** @var array */ private $licenses; + /** @var array */ + private $exceptions; + public function __construct() { $this->loadLicenses(); + $this->loadExceptions(); } - private function loadLicenses() + /** + * Returns license metadata by license identifier. + * + * @param string $identifier + * + * @return array|null + */ + public function getLicenseByIdentifier($identifier) { - if (is_array($this->licenses)) { - return $this->licenses; + if (!isset($this->licenses[$identifier])) { + return; } - $jsonFile = new JsonFile(__DIR__ . '/../../../res/spdx-licenses.json'); - $this->licenses = $jsonFile->read(); + $license = $this->licenses[$identifier]; + $license[] = 'http://spdx.org/licenses/' . $identifier . '.html#licenseText'; - return $this->licenses; + return $license; } /** - * Returns license metadata by license identifier. + * Returns license exception metadata by license exception identifier. * * @param string $identifier * * @return array|null */ - public function getLicenseByIdentifier($identifier) + public function getExceptionByIdentifier($identifier) { - if (!isset($this->licenses[$identifier])) { + if (!isset($this->exceptions[$identifier])) { return; } - $license = $this->licenses[$identifier]; - - // add URL for the license text (it's not included in the json) - $license[2] = 'http://spdx.org/licenses/' . $identifier . '#licenseText'; + $license = $this->exceptions[$identifier]; + $license[] = 'http://spdx.org/licenses/' . $identifier . '.html#licenseExceptionText'; return $license; } /** - * Returns the short identifier of a license by full name. + * Returns the short identifier of a license (exception) by full name. * - * @param string $identifier + * @param string $name * * @return string */ @@ -79,11 +84,19 @@ class SpdxLicense return $identifier; } } + + foreach ($this->exceptions as $identifier => $licenseData) { + if ($licenseData[0] === $name) { // key 0 = fullname + return $identifier; + } + } } /** * Returns the OSI Approved status for a license by identifier. * + * @param string $identifier + * * @return bool */ public function isOsiApprovedByIdentifier($identifier) @@ -105,6 +118,20 @@ class SpdxLicense return in_array($identifier, $identifiers); } + /** + * Check, if the identifier for a exception is valid. + * + * @param string $identifier + * + * @return bool + */ + private function isValidExceptionIdentifier($identifier) + { + $identifiers = array_keys($this->exceptions); + + return in_array($identifier, $identifiers); + } + /** * @param array|string $license * @@ -118,18 +145,49 @@ class SpdxLicense if ($count !== count(array_filter($license, 'is_string'))) { throw new \InvalidArgumentException('Array of strings expected.'); } - $license = $count > 1 ? '('.implode(' or ', $license).')' : (string) reset($license); + $license = $count > 1 ? '('.implode(' OR ', $license).')' : (string) reset($license); } if (!is_string($license)) { throw new \InvalidArgumentException(sprintf( - 'Array or String expected, %s given.', gettype($license) + 'Array or String expected, %s given.', + gettype($license) )); } return $this->isValidLicenseString($license); } + /** + * @return array + */ + private function loadLicenses() + { + if (is_array($this->licenses)) { + return $this->licenses; + } + + $jsonFile = file_get_contents(__DIR__ . '/../../../res/spdx-licenses.json'); + $this->licenses = json_decode($jsonFile, true); + + return $this->licenses; + } + + /** + * @return array + */ + private function loadExceptions() + { + if (is_array($this->exceptions)) { + return $this->exceptions; + } + + $jsonFile = file_get_contents(__DIR__ . '/../../../res/spdx-exceptions.json'); + $this->exceptions = json_decode($jsonFile, true); + + return $this->exceptions; + } + /** * @param string $license * @@ -141,10 +199,11 @@ class SpdxLicense $tokens = array( 'po' => '\(', 'pc' => '\)', - 'op' => '(?:or|and)', + 'op' => '(?:or|OR|and|AND)', + 'wi' => '(?:with|WITH)', 'lix' => '(?:NONE|NOASSERTION)', 'lir' => 'LicenseRef-\d+', - 'lic' => '[-+_.a-zA-Z0-9]{3,}', + 'lic' => '[-_.a-zA-Z0-9]{3,}\+?', 'ws' => '\s+', '_' => '.', ); @@ -171,44 +230,58 @@ class SpdxLicense return array($name, $matches[0][0]); } - throw new \RuntimeException('At least the last pattern needs to match, but it did not (dot-match-all is missing?).'); + throw new \RuntimeException( + 'At least the last pattern needs to match, but it did not (dot-match-all is missing?).' + ); }; $open = 0; - $require = 1; + $with = false; + $require = true; $lastop = null; while (list($token, $string) = $next()) { switch ($token) { case 'po': - if ($open || !$require) { + if ($open || !$require || $with) { return false; } $open = 1; break; case 'pc': - if ($open !== 1 || $require || !$lastop) { + if ($open !== 1 || $require || !$lastop || $with) { return false; } $open = 2; break; case 'op': - if ($require || !$open) { + if ($require || !$open || $with) { return false; } $lastop || $lastop = $string; if ($lastop !== $string) { return false; } - $require = 1; + $require = true; + break; + case 'wi': + $with = true; break; case 'lix': - if ($open) { + if ($open || $with) { return false; } goto lir; case 'lic': - if (!$this->isValidLicenseIdentifier($string)) { + if ($with && $this->isValidExceptionIdentifier($string)) { + $require = true; + $with = false; + goto lir; + } + if ($with) { + return false; + } + if (!$this->isValidLicenseIdentifier(rtrim($string, '+'))) { return false; } // Fall-through intended @@ -217,7 +290,7 @@ class SpdxLicense if (!$require) { return false; } - $require = 0; + $require = false; break; case 'ws': break; @@ -228,6 +301,6 @@ class SpdxLicense } } - return !($open % 2 || $require); + return !($open % 2 || $require || $with); } } diff --git a/src/Composer/Util/SpdxLicensesUpdater.php b/src/Composer/Util/SpdxLicensesUpdater.php index efcc30065..457f5b389 100644 --- a/src/Composer/Util/SpdxLicensesUpdater.php +++ b/src/Composer/Util/SpdxLicensesUpdater.php @@ -12,8 +12,6 @@ namespace Composer\Util; -use Composer\Json\JsonFormatter; - /** * The SPDX Licenses Updater scrapes licenses from the spdx website * and updates the "res/spdx-licenses.json" file accordingly. @@ -22,21 +20,57 @@ use Composer\Json\JsonFormatter; */ class SpdxLicensesUpdater { - private $licensesUrl = 'http://www.spdx.org/licenses/'; + /** + * @param string $file + * @param string $url + */ + public function dumpLicenses($file, $url = 'http://www.spdx.org/licenses/') + { + $options = 0; - public function update() + if (defined('JSON_PRETTY_PRINT')) { + $options |= JSON_PRETTY_PRINT; + } + + if (defined('JSON_UNESCAPED_SLASHES')) { + $options |= JSON_UNESCAPED_SLASHES; + } + + $licenses = json_encode($this->getLicenses($url), $options); + file_put_contents($file, $licenses); + } + + /** + * @param string $file + * @param string $url + */ + public function dumpExceptions($file, $url = 'http://www.spdx.org/licenses/exceptions-index.html') { - $json = json_encode($this->getLicenses(), true); - $prettyJson = JsonFormatter::format($json, true, true); - file_put_contents(__DIR__ . '/../../../res/spdx-licenses.json', $prettyJson); + $options = 0; + + if (defined('JSON_PRETTY_PRINT')) { + $options |= JSON_PRETTY_PRINT; + } + + if (defined('JSON_UNESCAPED_SLASHES')) { + $options |= JSON_UNESCAPED_SLASHES; + } + + $exceptions = json_encode($this->getExceptions($url), $options); + file_put_contents($file, $exceptions); } - private function getLicenses() + /** + * @param string $url + * + * @return array + */ + private function getLicenses($url) { $licenses = array(); $dom = new \DOMDocument; - $dom->loadHTMLFile($this->licensesUrl); + @$dom->loadHTMLFile($url); $xPath = new \DOMXPath($dom); $trs = $xPath->query('//table//tbody//tr'); @@ -45,8 +79,8 @@ class SpdxLicensesUpdater foreach ($trs as $tr) { $tds = $tr->getElementsByTagName('td'); // get the columns in this row - if ($tds->length < 4) { - throw new \Exception('Obtaining the license table failed. Wrong table format. Found less than 4 cells in a row.'); + if ($tds->length !== 4) { + continue; } if (trim($tds->item(3)->nodeValue) == 'License Text') { @@ -56,7 +90,7 @@ class SpdxLicensesUpdater // The license URL is not scraped intentionally to keep json file size low. // It's build when requested, see SpdxLicense->getLicenseByIdentifier(). - //$licenseURL = = $tds->item(3)->getAttribute('href'); + //$licenseURL = $tds->item(3)->getAttribute('href'); $licenses += array($identifier => array($fullname, $osiApproved)); } @@ -64,4 +98,42 @@ class SpdxLicensesUpdater return $licenses; } + + /** + * @param string $url + * + * @return array + */ + private function getExceptions($url) + { + $exceptions = array(); + + $dom = new \DOMDocument; + @$dom->loadHTMLFile($url); + + $xPath = new \DOMXPath($dom); + $trs = $xPath->query('//table//tbody//tr'); + + // iterate over each row in the table + foreach ($trs as $tr) { + $tds = $tr->getElementsByTagName('td'); // get the columns in this row + + if ($tds->length !== 3) { + continue; + } + + if (trim($tds->item(2)->nodeValue) == 'License Exception Text') { + $fullname = trim($tds->item(0)->nodeValue); + $identifier = trim($tds->item(1)->nodeValue); + + // The license URL is not scraped intentionally to keep json file size low. + // It's build when requested, see SpdxLicense->getLicenseExceptionByIdentifier(). + //$licenseURL = $tds->item(2)->getAttribute('href'); + + $exceptions += array($identifier => array($fullname)); + } + } + + return $exceptions; + } } diff --git a/tests/Composer/Test/Util/SpdxLicenseTest.php b/tests/Composer/Test/Util/SpdxLicenseTest.php index d4665954e..ef6e7d45d 100644 --- a/tests/Composer/Test/Util/SpdxLicenseTest.php +++ b/tests/Composer/Test/Util/SpdxLicenseTest.php @@ -27,12 +27,18 @@ class SpdxLicenseTest extends TestCase $valid = array_merge( array( "MIT", + "MIT+", "NONE", "NOASSERTION", "LicenseRef-3", array("LGPL-2.0", "GPL-3.0+"), "(LGPL-2.0 or GPL-3.0+)", + "(LGPL-2.0 OR GPL-3.0+)", "(EUDatagrid and GPL-3.0+)", + "(EUDatagrid AND GPL-3.0+)", + "GPL-2.0 with Autoconf-exception-2.0", + "GPL-2.0 WITH Autoconf-exception-2.0", + "GPL-2.0+ WITH Autoconf-exception-2.0", ), $identifiers ); @@ -52,7 +58,10 @@ class SpdxLicenseTest extends TestCase array("The system pwns you"), array("()"), array("(MIT)"), + array("(MIT"), + array("MIT)"), array("MIT NONE"), + array("MIT AND NONE"), array("MIT (MIT and MIT)"), array("(MIT and MIT) MIT"), array(array("LGPL-2.0", "The system pwns you")), @@ -64,6 +73,10 @@ class SpdxLicenseTest extends TestCase array("(MIT Or MIT)"), array("(NONE or MIT)"), array("(NOASSERTION or MIT)"), + array("Autoconf-exception-2.0 WITH MIT"), + array("MIT WITH"), + array("MIT OR"), + array("MIT AND"), ); } From b5d286e27b68298d03544eab199b9b1de961dee7 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Fri, 3 Jul 2015 10:15:17 +0200 Subject: [PATCH 050/205] apply a regex solution instead of tokenizer --- src/Composer/Util/SpdxLicense.php | 160 +++++++------------ tests/Composer/Test/Util/SpdxLicenseTest.php | 4 +- 2 files changed, 58 insertions(+), 106 deletions(-) diff --git a/src/Composer/Util/SpdxLicense.php b/src/Composer/Util/SpdxLicense.php index b9ffdc70d..d26c5e9b1 100644 --- a/src/Composer/Util/SpdxLicense.php +++ b/src/Composer/Util/SpdxLicense.php @@ -192,115 +192,69 @@ class SpdxLicense * @param string $license * * @return bool + * * @throws \RuntimeException */ private function isValidLicenseString($license) { - $tokens = array( - 'po' => '\(', - 'pc' => '\)', - 'op' => '(?:or|OR|and|AND)', - 'wi' => '(?:with|WITH)', - 'lix' => '(?:NONE|NOASSERTION)', - 'lir' => 'LicenseRef-\d+', - 'lic' => '[-_.a-zA-Z0-9]{3,}\+?', - 'ws' => '\s+', - '_' => '.', - ); - - $next = function () use ($license, $tokens) { - static $offset = 0; - - if ($offset >= strlen($license)) { - return null; - } - - foreach ($tokens as $name => $token) { - if (false === $r = preg_match('{' . $token . '}', $license, $matches, PREG_OFFSET_CAPTURE, $offset)) { - throw new \RuntimeException('Pattern for token %s failed (regex error).', $name); - } - if ($r === 0) { - continue; - } - if ($matches[0][1] !== $offset) { - continue; - } - $offset += strlen($matches[0][0]); - - return array($name, $matches[0][0]); - } + $licenses = array_map('preg_quote', array_keys($this->licenses)); + sort($licenses); + $licenses = array_reverse($licenses); + $licenses = implode('|', $licenses); + + $exceptions = array_map('preg_quote', array_keys($this->exceptions)); + sort($exceptions); + $exceptions = array_reverse($exceptions); + $exceptions = implode('|', $exceptions); + + $regex = "{ + (?(DEFINE) + # idstring: 1*( ALPHA / DIGIT / - / . ) + (?[\pL\pN\-\.]{1,}) + + # license-id: taken from list + (?${licenses}) + + # license-exception-id: taken from list + (?${exceptions}) + + # license-ref: [DocumentRef-1*(idstring):]LicenseRef-1*(idstring) + (?(?:DocumentRef-(?&idstring):)?LicenseRef-(?&idstring)) + + # simple-expresssion: license-id / license-id+ / license-ref + (?(?&licenseid)\+? | (?&licenseid) | (?&licenseref)) + + # compound expression: 1*( + # simple-expression / + # simple-expression WITH license-exception-id / + # compound-expression AND compound-expression / + # compound-expression OR compound-expression + # ) / ( compound-expression ) ) + (? + (?&simple_expression) ( \s+ (?:with|WITH) \s+ (?&licenseexceptionid))? + | \( \s* (?&compound_expression) \s*\) + ) + (? + (?&compound_head) (?: \s+ (?:and|AND|or|OR) \s+ (?&compound_expression))? + ) + + # license-expression: 1*1(simple-expression / compound-expression) + (?NONE | NOASSERTION | (?&compound_expression) | (?&simple_expression)) + ) # end of define + + ^(?&license_expression)$ + }x"; + + $match = preg_match($regex, $license); + + if (0 === $match) { + return false; + } - throw new \RuntimeException( - 'At least the last pattern needs to match, but it did not (dot-match-all is missing?).' - ); - }; - - $open = 0; - $with = false; - $require = true; - $lastop = null; - - while (list($token, $string) = $next()) { - switch ($token) { - case 'po': - if ($open || !$require || $with) { - return false; - } - $open = 1; - break; - case 'pc': - if ($open !== 1 || $require || !$lastop || $with) { - return false; - } - $open = 2; - break; - case 'op': - if ($require || !$open || $with) { - return false; - } - $lastop || $lastop = $string; - if ($lastop !== $string) { - return false; - } - $require = true; - break; - case 'wi': - $with = true; - break; - case 'lix': - if ($open || $with) { - return false; - } - goto lir; - case 'lic': - if ($with && $this->isValidExceptionIdentifier($string)) { - $require = true; - $with = false; - goto lir; - } - if ($with) { - return false; - } - if (!$this->isValidLicenseIdentifier(rtrim($string, '+'))) { - return false; - } - // Fall-through intended - case 'lir': - lir: - if (!$require) { - return false; - } - $require = false; - break; - case 'ws': - break; - case '_': - return false; - default: - throw new \RuntimeException(sprintf('Unparsed token: %s.', print_r($token, true))); - } + if (false === $match) { + throw new \RuntimeException('Regex failed to compile/run.'); } - return !($open % 2 || $require || $with); + return true; } } diff --git a/tests/Composer/Test/Util/SpdxLicenseTest.php b/tests/Composer/Test/Util/SpdxLicenseTest.php index ef6e7d45d..207e6ed80 100644 --- a/tests/Composer/Test/Util/SpdxLicenseTest.php +++ b/tests/Composer/Test/Util/SpdxLicenseTest.php @@ -39,6 +39,7 @@ class SpdxLicenseTest extends TestCase "GPL-2.0 with Autoconf-exception-2.0", "GPL-2.0 WITH Autoconf-exception-2.0", "GPL-2.0+ WITH Autoconf-exception-2.0", + "(GPL-3.0 and GPL-2.0 or GPL-3.0+)", ), $identifiers ); @@ -57,7 +58,6 @@ class SpdxLicenseTest extends TestCase array(array()), array("The system pwns you"), array("()"), - array("(MIT)"), array("(MIT"), array("MIT)"), array("MIT NONE"), @@ -66,8 +66,6 @@ class SpdxLicenseTest extends TestCase array("(MIT and MIT) MIT"), array(array("LGPL-2.0", "The system pwns you")), array("and GPL-3.0+"), - array("EUDatagrid and GPL-3.0+"), - array("(GPL-3.0 and GPL-2.0 or GPL-3.0+)"), array("(EUDatagrid and GPL-3.0+ and )"), array("(EUDatagrid xor GPL-3.0+)"), array("(MIT Or MIT)"), From 4019f7bb44911dd9c3c0604e6c52167b2940d99f Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Fri, 3 Jul 2015 11:58:42 +0200 Subject: [PATCH 051/205] Revert "apply a regex solution instead of tokenizer" This reverts commit 33a7305e22c8d4e2ce38586855fd3d4b7b2af3dd. --- src/Composer/Util/SpdxLicense.php | 160 ++++++++++++------- tests/Composer/Test/Util/SpdxLicenseTest.php | 4 +- 2 files changed, 106 insertions(+), 58 deletions(-) diff --git a/src/Composer/Util/SpdxLicense.php b/src/Composer/Util/SpdxLicense.php index d26c5e9b1..b9ffdc70d 100644 --- a/src/Composer/Util/SpdxLicense.php +++ b/src/Composer/Util/SpdxLicense.php @@ -192,69 +192,115 @@ class SpdxLicense * @param string $license * * @return bool - * * @throws \RuntimeException */ private function isValidLicenseString($license) { - $licenses = array_map('preg_quote', array_keys($this->licenses)); - sort($licenses); - $licenses = array_reverse($licenses); - $licenses = implode('|', $licenses); - - $exceptions = array_map('preg_quote', array_keys($this->exceptions)); - sort($exceptions); - $exceptions = array_reverse($exceptions); - $exceptions = implode('|', $exceptions); - - $regex = "{ - (?(DEFINE) - # idstring: 1*( ALPHA / DIGIT / - / . ) - (?[\pL\pN\-\.]{1,}) - - # license-id: taken from list - (?${licenses}) - - # license-exception-id: taken from list - (?${exceptions}) - - # license-ref: [DocumentRef-1*(idstring):]LicenseRef-1*(idstring) - (?(?:DocumentRef-(?&idstring):)?LicenseRef-(?&idstring)) - - # simple-expresssion: license-id / license-id+ / license-ref - (?(?&licenseid)\+? | (?&licenseid) | (?&licenseref)) - - # compound expression: 1*( - # simple-expression / - # simple-expression WITH license-exception-id / - # compound-expression AND compound-expression / - # compound-expression OR compound-expression - # ) / ( compound-expression ) ) - (? - (?&simple_expression) ( \s+ (?:with|WITH) \s+ (?&licenseexceptionid))? - | \( \s* (?&compound_expression) \s*\) - ) - (? - (?&compound_head) (?: \s+ (?:and|AND|or|OR) \s+ (?&compound_expression))? - ) - - # license-expression: 1*1(simple-expression / compound-expression) - (?NONE | NOASSERTION | (?&compound_expression) | (?&simple_expression)) - ) # end of define - - ^(?&license_expression)$ - }x"; - - $match = preg_match($regex, $license); - - if (0 === $match) { - return false; - } + $tokens = array( + 'po' => '\(', + 'pc' => '\)', + 'op' => '(?:or|OR|and|AND)', + 'wi' => '(?:with|WITH)', + 'lix' => '(?:NONE|NOASSERTION)', + 'lir' => 'LicenseRef-\d+', + 'lic' => '[-_.a-zA-Z0-9]{3,}\+?', + 'ws' => '\s+', + '_' => '.', + ); + + $next = function () use ($license, $tokens) { + static $offset = 0; + + if ($offset >= strlen($license)) { + return null; + } - if (false === $match) { - throw new \RuntimeException('Regex failed to compile/run.'); + foreach ($tokens as $name => $token) { + if (false === $r = preg_match('{' . $token . '}', $license, $matches, PREG_OFFSET_CAPTURE, $offset)) { + throw new \RuntimeException('Pattern for token %s failed (regex error).', $name); + } + if ($r === 0) { + continue; + } + if ($matches[0][1] !== $offset) { + continue; + } + $offset += strlen($matches[0][0]); + + return array($name, $matches[0][0]); + } + + throw new \RuntimeException( + 'At least the last pattern needs to match, but it did not (dot-match-all is missing?).' + ); + }; + + $open = 0; + $with = false; + $require = true; + $lastop = null; + + while (list($token, $string) = $next()) { + switch ($token) { + case 'po': + if ($open || !$require || $with) { + return false; + } + $open = 1; + break; + case 'pc': + if ($open !== 1 || $require || !$lastop || $with) { + return false; + } + $open = 2; + break; + case 'op': + if ($require || !$open || $with) { + return false; + } + $lastop || $lastop = $string; + if ($lastop !== $string) { + return false; + } + $require = true; + break; + case 'wi': + $with = true; + break; + case 'lix': + if ($open || $with) { + return false; + } + goto lir; + case 'lic': + if ($with && $this->isValidExceptionIdentifier($string)) { + $require = true; + $with = false; + goto lir; + } + if ($with) { + return false; + } + if (!$this->isValidLicenseIdentifier(rtrim($string, '+'))) { + return false; + } + // Fall-through intended + case 'lir': + lir: + if (!$require) { + return false; + } + $require = false; + break; + case 'ws': + break; + case '_': + return false; + default: + throw new \RuntimeException(sprintf('Unparsed token: %s.', print_r($token, true))); + } } - return true; + return !($open % 2 || $require || $with); } } diff --git a/tests/Composer/Test/Util/SpdxLicenseTest.php b/tests/Composer/Test/Util/SpdxLicenseTest.php index 207e6ed80..ef6e7d45d 100644 --- a/tests/Composer/Test/Util/SpdxLicenseTest.php +++ b/tests/Composer/Test/Util/SpdxLicenseTest.php @@ -39,7 +39,6 @@ class SpdxLicenseTest extends TestCase "GPL-2.0 with Autoconf-exception-2.0", "GPL-2.0 WITH Autoconf-exception-2.0", "GPL-2.0+ WITH Autoconf-exception-2.0", - "(GPL-3.0 and GPL-2.0 or GPL-3.0+)", ), $identifiers ); @@ -58,6 +57,7 @@ class SpdxLicenseTest extends TestCase array(array()), array("The system pwns you"), array("()"), + array("(MIT)"), array("(MIT"), array("MIT)"), array("MIT NONE"), @@ -66,6 +66,8 @@ class SpdxLicenseTest extends TestCase array("(MIT and MIT) MIT"), array(array("LGPL-2.0", "The system pwns you")), array("and GPL-3.0+"), + array("EUDatagrid and GPL-3.0+"), + array("(GPL-3.0 and GPL-2.0 or GPL-3.0+)"), array("(EUDatagrid and GPL-3.0+ and )"), array("(EUDatagrid xor GPL-3.0+)"), array("(MIT Or MIT)"), From 0ad9e98a59b18f209a9bafad30b7b5cb18dd7ac5 Mon Sep 17 00:00:00 2001 From: Kunal Mehta Date: Fri, 3 Jul 2015 17:54:30 -0700 Subject: [PATCH 052/205] Don't use BasePackage::$stabilities in VersionParser Working towards #3545. This adds VersionParser::$stabilities, which is an array of the supported stability levels. This adds a little bit of duplication, however we were already hardcoding the various stabilities in regular expressions and functions like parseStability(). --- src/Composer/Package/Version/VersionParser.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Composer/Package/Version/VersionParser.php b/src/Composer/Package/Version/VersionParser.php index dabf40a7b..89bf4819f 100644 --- a/src/Composer/Package/Version/VersionParser.php +++ b/src/Composer/Package/Version/VersionParser.php @@ -12,7 +12,6 @@ namespace Composer\Package\Version; -use Composer\Package\BasePackage; use Composer\Package\PackageInterface; use Composer\Package\Link; use Composer\Package\LinkConstraint\EmptyConstraint; @@ -28,6 +27,10 @@ class VersionParser { private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)(?:[.-]?(\d+))?)?([.-]?dev)?'; + private static $stabilities = array( + 'stable', 'RC', 'beta', 'alpha', 'dev', + ); + /** * Returns the stability of a version * @@ -241,7 +244,7 @@ class VersionParser { $prettyConstraint = $constraints; - if (preg_match('{^([^,\s]*?)@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $constraints, $match)) { + if (preg_match('{^([^,\s]*?)@('.implode('|', self::$stabilities).')$}i', $constraints, $match)) { $constraints = empty($match[1]) ? '*' : $match[1]; } @@ -284,7 +287,7 @@ class VersionParser private function parseConstraint($constraint) { - if (preg_match('{^([^,\s]+?)@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $constraint, $match)) { + if (preg_match('{^([^,\s]+?)@('.implode('|', self::$stabilities).')$}i', $constraint, $match)) { $constraint = $match[1]; if ($match[2] !== 'stable') { $stabilityModifier = $match[2]; From 14d1f0f3f65a12b37800cd2c6ea0647940111a03 Mon Sep 17 00:00:00 2001 From: Kunal Mehta Date: Fri, 3 Jul 2015 19:35:54 -0700 Subject: [PATCH 053/205] Move VersionParser::parseLinks() to ArrayLoader::parseLinks() Working towards #3545. parseLinks is a wrapper around VersionParser::parseConstraints() that creates Link objects, and better belongs in ArrayLoader. --- src/Composer/Package/Loader/ArrayLoader.php | 26 ++++++++++- src/Composer/Package/Locker.php | 6 +-- .../Package/Version/VersionParser.php | 17 +++---- .../Test/Package/Loader/ArrayLoaderTest.php | 46 +++++++++++++++++++ .../Package/Version/VersionParserTest.php | 46 ------------------- 5 files changed, 79 insertions(+), 62 deletions(-) diff --git a/src/Composer/Package/Loader/ArrayLoader.php b/src/Composer/Package/Loader/ArrayLoader.php index 60cff3b33..5d34d1b31 100644 --- a/src/Composer/Package/Loader/ArrayLoader.php +++ b/src/Composer/Package/Loader/ArrayLoader.php @@ -14,6 +14,7 @@ namespace Composer\Package\Loader; use Composer\Package; use Composer\Package\AliasPackage; +use Composer\Package\Link; use Composer\Package\RootAliasPackage; use Composer\Package\RootPackageInterface; use Composer\Package\Version\VersionParser; @@ -115,7 +116,7 @@ class ArrayLoader implements LoaderInterface if (isset($config[$type])) { $method = 'set'.ucfirst($opts['method']); $package->{$method}( - $this->versionParser->parseLinks( + $this->parseLinks( $package->getName(), $package->getPrettyVersion(), $opts['description'], @@ -216,6 +217,29 @@ class ArrayLoader implements LoaderInterface return $package; } + /** + * @param string $source source package name + * @param string $sourceVersion source package version (pretty version ideally) + * @param string $description link description (e.g. requires, replaces, ..) + * @param array $links array of package name => constraint mappings + * @return Link[] + */ + public function parseLinks($source, $sourceVersion, $description, $links) + { + $res = array(); + foreach ($links as $target => $constraint) { + if ('self.version' === $constraint) { + $parsedConstraint = $this->versionParser->parseConstraints($sourceVersion); + } else { + $parsedConstraint = $this->versionParser->parseConstraints($constraint); + } + + $res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint); + } + + return $res; + } + /** * Retrieves a branch alias (dev-master => 1.0.x-dev for example) if it exists * diff --git a/src/Composer/Package/Locker.php b/src/Composer/Package/Locker.php index 9f9a0abf8..5aacf4450 100644 --- a/src/Composer/Package/Locker.php +++ b/src/Composer/Package/Locker.php @@ -19,7 +19,6 @@ use Composer\Util\ProcessExecutor; use Composer\Repository\ArrayRepository; use Composer\Package\Dumper\ArrayDumper; use Composer\Package\Loader\ArrayLoader; -use Composer\Package\Version\VersionParser; use Composer\Util\Git as GitUtil; use Composer\IO\IOInterface; @@ -133,11 +132,10 @@ class Locker public function getPlatformRequirements($withDevReqs = false) { $lockData = $this->getLockData(); - $versionParser = new VersionParser(); $requirements = array(); if (!empty($lockData['platform'])) { - $requirements = $versionParser->parseLinks( + $requirements = $this->loader->parseLinks( '__ROOT__', '1.0.0', 'requires', @@ -146,7 +144,7 @@ class Locker } if ($withDevReqs && !empty($lockData['platform-dev'])) { - $devRequirements = $versionParser->parseLinks( + $devRequirements = $this->loader->parseLinks( '__ROOT__', '1.0.0', 'requires', diff --git a/src/Composer/Package/Version/VersionParser.php b/src/Composer/Package/Version/VersionParser.php index dabf40a7b..719748a3e 100644 --- a/src/Composer/Package/Version/VersionParser.php +++ b/src/Composer/Package/Version/VersionParser.php @@ -18,6 +18,7 @@ use Composer\Package\Link; use Composer\Package\LinkConstraint\EmptyConstraint; use Composer\Package\LinkConstraint\MultiConstraint; use Composer\Package\LinkConstraint\VersionConstraint; +use Composer\Package\Loader\ArrayLoader; /** * Version parser @@ -209,6 +210,7 @@ class VersionParser } /** + * @deprecated use ArrayLoader::parseLinks() instead * @param string $source source package name * @param string $sourceVersion source package version (pretty version ideally) * @param string $description link description (e.g. requires, replaces, ..) @@ -217,18 +219,11 @@ class VersionParser */ public function parseLinks($source, $sourceVersion, $description, $links) { - $res = array(); - foreach ($links as $target => $constraint) { - if ('self.version' === $constraint) { - $parsedConstraint = $this->parseConstraints($sourceVersion); - } else { - $parsedConstraint = $this->parseConstraints($constraint); - } - - $res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint); - } + trigger_error(__METHOD__.' is deprecated. Use '. + '\Composer\Package\Loader\ArrayLoader::parseLinks() instead', E_USER_DEPRECATED); + $loader = new ArrayLoader($this, false); - return $res; + return $loader->parseLinks($source, $sourceVersion, $description, $links); } /** diff --git a/tests/Composer/Test/Package/Loader/ArrayLoaderTest.php b/tests/Composer/Test/Package/Loader/ArrayLoaderTest.php index 1491571a1..b452a4095 100644 --- a/tests/Composer/Test/Package/Loader/ArrayLoaderTest.php +++ b/tests/Composer/Test/Package/Loader/ArrayLoaderTest.php @@ -17,6 +17,12 @@ use Composer\Package\Dumper\ArrayDumper; class ArrayLoaderTest extends \PHPUnit_Framework_TestCase { + + /** + * @var ArrayLoader + */ + private $loader; + public function setUp() { $this->loader = new ArrayLoader(null, true); @@ -207,4 +213,44 @@ class ArrayLoaderTest extends \PHPUnit_Framework_TestCase $package = $this->loader->load($config); $this->assertFalse($package->isAbandoned()); } + + public function pluginApiVersions() + { + return array( + array('1.0'), + array('1.0.0'), + array('1.0.0.0'), + array('1'), + array('=1.0.0'), + array('==1.0'), + array('~1.0.0'), + array('*'), + array('3.0.*'), + array('@stable'), + array('1.0.0@stable'), + array('^5.1'), + array('>=1.0.0 <2.5'), + array('x'), + array('1.0.0-dev'), + ); + } + + /** + * @dataProvider pluginApiVersions + */ + public function testPluginApiVersionAreKeptAsDeclared($apiVersion) + { + $links = $this->loader->parseLinks('Plugin', '9.9.9', '', array('composer-plugin-api' => $apiVersion)); + + $this->assertArrayHasKey('composer-plugin-api', $links); + $this->assertSame($apiVersion, $links['composer-plugin-api']->getConstraint()->getPrettyString()); + } + + public function testPluginApiVersionDoesSupportSelfVersion() + { + $links = $this->loader->parseLinks('Plugin', '6.6.6', '', array('composer-plugin-api' => 'self.version')); + + $this->assertArrayHasKey('composer-plugin-api', $links); + $this->assertSame('6.6.6', $links['composer-plugin-api']->getConstraint()->getPrettyString()); + } } diff --git a/tests/Composer/Test/Package/Version/VersionParserTest.php b/tests/Composer/Test/Package/Version/VersionParserTest.php index 632727165..fe2dab749 100644 --- a/tests/Composer/Test/Package/Version/VersionParserTest.php +++ b/tests/Composer/Test/Package/Version/VersionParserTest.php @@ -469,50 +469,4 @@ class VersionParserTest extends \PHPUnit_Framework_TestCase array('RC', '2.0.0rc1') ); } - - public function pluginApiVersions() - { - return array( - array('1.0'), - array('1.0.0'), - array('1.0.0.0'), - array('1'), - array('=1.0.0'), - array('==1.0'), - array('~1.0.0'), - array('*'), - array('3.0.*'), - array('@stable'), - array('1.0.0@stable'), - array('^5.1'), - array('>=1.0.0 <2.5'), - array('x'), - array('1.0.0-dev'), - ); - } - - /** - * @dataProvider pluginApiVersions - */ - public function testPluginApiVersionAreKeptAsDeclared($apiVersion) - { - $parser = new VersionParser; - - /** @var Link[] $links */ - $links = $parser->parseLinks('Plugin', '9.9.9', '', array('composer-plugin-api' => $apiVersion)); - - $this->assertArrayHasKey('composer-plugin-api', $links); - $this->assertSame($apiVersion, $links['composer-plugin-api']->getConstraint()->getPrettyString()); - } - - public function testPluginApiVersionDoesSupportSelfVersion() - { - $parser = new VersionParser; - - /** @var Link[] $links */ - $links = $parser->parseLinks('Plugin', '6.6.6', '', array('composer-plugin-api' => 'self.version')); - - $this->assertArrayHasKey('composer-plugin-api', $links); - $this->assertSame('6.6.6', $links['composer-plugin-api']->getConstraint()->getPrettyString()); - } } From edf121ce11ce1f66c3221757d7b034caeea26fa0 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 4 Jul 2015 11:51:55 +0100 Subject: [PATCH 054/205] Minor tweaks, refs #4172 --- doc/articles/versions.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/articles/versions.md b/doc/articles/versions.md index 50af64e7d..5e368bca7 100644 --- a/doc/articles/versions.md +++ b/doc/articles/versions.md @@ -1,5 +1,5 @@ # Versions @@ -24,6 +24,10 @@ You can define multiple ranges. Ranges separated by a space (` `) or comma (`,`) will be treated as a **logical AND**. A double pipe (`||`) will be treated as a **logical OR**. AND has higher precedence than OR. +> **Note:** Be careful when using unbounded ranges as you might end up +> unexpectedly installing versions that break backwards compatibility. +> Consider using the [caret](#caret) operator instead for safety. + Examples: * `>=1.0` @@ -78,6 +82,9 @@ is equivalent to `>=1.2.3 <2.0.0` as none of the releases until 2.0 should break backwards compatibility. For pre-1.0 versions it also acts with safety in mind and treats `^0.3` as `>=0.3.0 <0.4.0`. +This is the recommended operator for maximum interoperability when writing +library code. + Example: `^1.2.3` ## Stability @@ -109,4 +116,3 @@ You can test version constraints using [semver.mwl.be](http://semver.mwl.be). Fill in a package name and it will autofill the default version constraint which Composer would add to your `composer.json` file. You can adjust the version constraint and the tool will highlight all releases that match. - From 812167b2a0c768d31cb74620cbd3df73ea4571cc Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 4 Jul 2015 11:54:56 +0100 Subject: [PATCH 055/205] Formatting tweaks, refs #4172 --- doc/articles/versions.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/articles/versions.md b/doc/articles/versions.md index 5e368bca7..183bcbfdd 100644 --- a/doc/articles/versions.md +++ b/doc/articles/versions.md @@ -20,9 +20,9 @@ Example: `1.0.2` By using comparison operators you can specify ranges of valid versions. Valid operators are `>`, `>=`, `<`, `<=`, `!=`. -You can define multiple ranges. Ranges separated by a space (` `) or comma (`,`) -will be treated as a **logical AND**. A double pipe (`||`) will be treated as a -**logical OR**. AND has higher precedence than OR. +You can define multiple ranges. Ranges separated by a space ( ) +or comma (`,`) will be treated as a **logical AND**. A double pipe (`||`) +will be treated as a **logical OR**. AND has higher precedence than OR. > **Note:** Be careful when using unbounded ranges as you might end up > unexpectedly installing versions that break backwards compatibility. @@ -99,7 +99,7 @@ add the suffix `-stable`. Examples: Constraint | Internally ----------------------------------------------- +------------------- | ------------------------ `1.2.3` | `=1.2.3.0-stable` `>1.2` | `>1.2.0.0-stable` `>=1.2` | `>=1.2.0.0-dev` From e817dba90cc0d9ccd2f16a3b7a772f0e7fff752f Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 4 Jul 2015 11:56:17 +0100 Subject: [PATCH 056/205] Rendering fix, refs #4172 --- doc/articles/versions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/articles/versions.md b/doc/articles/versions.md index 183bcbfdd..d1629a494 100644 --- a/doc/articles/versions.md +++ b/doc/articles/versions.md @@ -20,7 +20,7 @@ Example: `1.0.2` By using comparison operators you can specify ranges of valid versions. Valid operators are `>`, `>=`, `<`, `<=`, `!=`. -You can define multiple ranges. Ranges separated by a space ( ) +You can define multiple ranges. Ranges separated by a space ( ) or comma (`,`) will be treated as a **logical AND**. A double pipe (`||`) will be treated as a **logical OR**. AND has higher precedence than OR. From 0964c02acbd86623014774c80d425360df52ef3a Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 4 Jul 2015 12:02:57 +0100 Subject: [PATCH 057/205] Use only one level of verbosity --- doc/03-cli.md | 4 ++-- src/Composer/Command/SuggestsCommand.php | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index 6182db682..136644519 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -303,8 +303,8 @@ to limit output to suggestions made by those packages only. ### Options * **--no-dev:** Excludes suggestions from `require-dev` packages. -* **-v[v]:** Increased verbosity adds suggesting package name (`-v`) and - reason for suggestion (`-vv`). +* **--verbose (-v):** Increased verbosity adds suggesting package name and + reason for suggestion. ## depends diff --git a/src/Composer/Command/SuggestsCommand.php b/src/Composer/Command/SuggestsCommand.php index c6f7385fd..d59ef1dc6 100644 --- a/src/Composer/Command/SuggestsCommand.php +++ b/src/Composer/Command/SuggestsCommand.php @@ -32,6 +32,8 @@ class SuggestsCommand extends Command The %command.name% command shows suggested packages. +With -v you also see which package suggested it and why. + EOT ) ; @@ -87,10 +89,8 @@ EOT { $io = $this->getIO(); - if ($io->isVeryVerbose()) { + if ($io->isVerbose()) { $io->write(sprintf('%s suggests %s: %s', $package, $suggestion, $reason)); - } elseif ($io->isVerbose()) { - $io->write(sprintf('%s suggests %s', $package, $suggestion)); } else { $io->write(sprintf('%s', $suggestion)); } From a8d71be0efa7fc153290608aebf8ee26fd05e81b Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 4 Jul 2015 12:15:04 +0100 Subject: [PATCH 058/205] Add event name in verbose mode, refs #4123 --- src/Composer/EventDispatcher/EventDispatcher.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index 490ba435d..0e00629c4 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -173,7 +173,11 @@ class EventDispatcher } else { $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor', 'escape'), $event->getArguments())); $exec = $callable . ($args === '' ? '' : ' '.$args); - $this->io->writeError(sprintf('> %s', $exec)); + if ($this->io->isVerbose()) { + $this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec)); + } else { + $this->io->writeError(sprintf('> %s', $exec)); + } if (0 !== ($exitCode = $this->process->execute($exec))) { $this->io->writeError(sprintf('Script %s handling the %s event returned with an error', $callable, $event->getName())); @@ -198,7 +202,11 @@ class EventDispatcher { $event = $this->checkListenerExpectedEvent(array($className, $methodName), $event); - $this->io->writeError(sprintf('> %s::%s', $className, $methodName)); + if ($this->io->isVerbose()) { + $this->io->writeError(sprintf('> %s: %s::%s', $event->getName(), $className, $methodName)); + } else { + $this->io->writeError(sprintf('> %s::%s', $className, $methodName)); + } return $className::$methodName($event); } From d79427f1a7b15e8f4d46ce8124a4d0c58ba1479c Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 4 Jul 2015 12:22:58 +0100 Subject: [PATCH 059/205] Fix tests --- .../EventDispatcher/EventDispatcherTest.php | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php index 8fc11b98a..e0cb196cb 100644 --- a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php +++ b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php @@ -32,10 +32,14 @@ class EventDispatcherTest extends TestCase ), $io); $io->expects($this->at(0)) + ->method('isVerbose') + ->willReturn(0); + + $io->expects($this->at(1)) ->method('writeError') ->with('> Composer\Test\EventDispatcher\EventDispatcherTest::call'); - $io->expects($this->at(1)) + $io->expects($this->at(2)) ->method('writeError') ->with('Script Composer\Test\EventDispatcher\EventDispatcherTest::call handling the post-install-cmd event terminated with an exception'); @@ -119,17 +123,21 @@ class EventDispatcherTest extends TestCase ->method('getListeners') ->will($this->returnValue($listeners)); - $io->expects($this->at(0)) - ->method('writeError') - ->with($this->equalTo('> echo -n foo')); + $io->expects($this->any()) + ->method('isVerbose') + ->willReturn(1); $io->expects($this->at(1)) ->method('writeError') - ->with($this->equalTo('> Composer\Test\EventDispatcher\EventDispatcherTest::someMethod')); + ->with($this->equalTo('> post-install-cmd: echo -n foo')); - $io->expects($this->at(2)) + $io->expects($this->at(3)) ->method('writeError') - ->with($this->equalTo('> echo -n bar')); + ->with($this->equalTo('> post-install-cmd: Composer\Test\EventDispatcher\EventDispatcherTest::someMethod')); + + $io->expects($this->at(5)) + ->method('writeError') + ->with($this->equalTo('> post-install-cmd: echo -n bar')); $dispatcher->dispatchScript(ScriptEvents::POST_INSTALL_CMD, false); } @@ -203,10 +211,14 @@ class EventDispatcherTest extends TestCase ->will($this->returnValue($listener)); $io->expects($this->at(0)) + ->method('isVerbose') + ->willReturn(0); + + $io->expects($this->at(1)) ->method('writeError') ->willReturn('> exit 1'); - $io->expects($this->at(1)) + $io->expects($this->at(2)) ->method('writeError') ->with($this->equalTo('Script '.$code.' handling the post-install-cmd event returned with an error')); From 07e1d227c91a0b567028766b713a9228ee556ad2 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Tue, 7 Jul 2015 15:40:26 +0200 Subject: [PATCH 060/205] Output the size of the pool after dependency resolution for users --- src/Composer/DependencyResolver/Pool.php | 10 +++++++++- src/Composer/Installer.php | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Composer/DependencyResolver/Pool.php b/src/Composer/DependencyResolver/Pool.php index 000d63805..343fad9be 100644 --- a/src/Composer/DependencyResolver/Pool.php +++ b/src/Composer/DependencyResolver/Pool.php @@ -31,7 +31,7 @@ use Composer\Package\PackageInterface; * @author Nils Adermann * @author Jordi Boggiano */ -class Pool +class Pool implements \Countable { const MATCH_NAME = -1; const MATCH_NONE = 0; @@ -160,6 +160,14 @@ class Pool return $this->packages[$id - 1]; } + /** + * Returns how many packages have been loaded into the pool + */ + public function count() + { + return count($this->packages); + } + /** * Searches all packages providing the given package name and match the constraint * diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index e58381856..464102120 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -511,6 +511,10 @@ class Installer return max(1, $e->getCode()); } + if ($this->io->isVerbose()) { + $this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies"); + } + // force dev packages to be updated if we update or install from a (potentially new) lock $operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $installFromLock, $withDevReqs, 'force-updates', $operations); From 8dd110e0a986036064edc4d259d8b5d627e2e07d Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Wed, 8 Jul 2015 13:13:47 +0200 Subject: [PATCH 061/205] Remove unnecessary version comparison cache variable and store operators as int --- .../LinkConstraint/VersionConstraint.php | 73 ++++++++++--------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/src/Composer/Package/LinkConstraint/VersionConstraint.php b/src/Composer/Package/LinkConstraint/VersionConstraint.php index cd2336227..f5aee77bc 100644 --- a/src/Composer/Package/LinkConstraint/VersionConstraint.php +++ b/src/Composer/Package/LinkConstraint/VersionConstraint.php @@ -21,6 +21,33 @@ namespace Composer\Package\LinkConstraint; */ class VersionConstraint extends SpecificConstraint { + const OP_EQ = 0; + const OP_LT = 1; + const OP_LE = 2; + const OP_GT = 3; + const OP_GE = 4; + const OP_NE = 5; + + static $transOpStr = array( + '=' => self::OP_EQ, + '==' => self::OP_EQ, + '<' => self::OP_LT, + '<=' => self::OP_LE, + '>' => self::OP_GT, + '>=' => self::OP_GE, + '<>' => self::OP_NE, + '!=' => self::OP_NE, + ); + + static $transOpInt = array( + self::OP_EQ => '==', + self::OP_LT => '<', + self::OP_LE => '<=', + self::OP_GT => '>', + self::OP_GE => '>=', + self::OP_NE => '!=', + ); + private $operator; private $version; @@ -32,15 +59,7 @@ class VersionConstraint extends SpecificConstraint */ public function __construct($operator, $version) { - if ('=' === $operator) { - $operator = '=='; - } - - if ('<>' === $operator) { - $operator = '!='; - } - - $this->operator = $operator; + $this->operator = self::$transOpStr[$operator]; $this->version = $version; } @@ -67,29 +86,13 @@ class VersionConstraint extends SpecificConstraint */ public function matchSpecific(VersionConstraint $provider, $compareBranches = false) { - static $cache = array(); - if (isset($cache[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches])) { - return $cache[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches]; - } - - return $cache[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches] = - $this->doMatchSpecific($provider, $compareBranches); - } - - /** - * @param VersionConstraint $provider - * @param bool $compareBranches - * @return bool - */ - private function doMatchSpecific(VersionConstraint $provider, $compareBranches = false) - { - $noEqualOp = str_replace('=', '', $this->operator); - $providerNoEqualOp = str_replace('=', '', $provider->operator); + $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]); + $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]); - $isEqualOp = '==' === $this->operator; - $isNonEqualOp = '!=' === $this->operator; - $isProviderEqualOp = '==' === $provider->operator; - $isProviderNonEqualOp = '!=' === $provider->operator; + $isEqualOp = self::OP_EQ === $this->operator; + $isNonEqualOp = self::OP_NE === $this->operator; + $isProviderEqualOp = self::OP_EQ === $provider->operator; + $isProviderNonEqualOp = self::OP_NE === $provider->operator; // '!=' operator is match when other operator is not '==' operator or version is not match // these kinds of comparisons always have a solution @@ -100,14 +103,14 @@ class VersionConstraint extends SpecificConstraint // an example for the condition is <= 2.0 & < 1.0 // these kinds of comparisons always have a solution - if ($this->operator != '==' && $noEqualOp == $providerNoEqualOp) { + if ($this->operator != self::OP_EQ && $noEqualOp == $providerNoEqualOp) { return true; } - if ($this->versionCompare($provider->version, $this->version, $this->operator, $compareBranches)) { + if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) { // special case, e.g. require >= 1.0 and provide < 1.0 // 1.0 >= 1.0 but 1.0 is outside of the provided interval - if ($provider->version == $this->version && $provider->operator == $providerNoEqualOp && $this->operator != $noEqualOp) { + if ($provider->version == $this->version && self::$transOpInt[$provider->operator] == $providerNoEqualOp && self::$transOpInt[$this->operator] != $noEqualOp) { return false; } @@ -119,6 +122,6 @@ class VersionConstraint extends SpecificConstraint public function __toString() { - return $this->operator.' '.$this->version; + return self::$transOpInt[$this->operator].' '.$this->version; } } From e88df7429fc707caa9fb3e9361cb7e7526617221 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Wed, 8 Jul 2015 13:36:19 +0200 Subject: [PATCH 062/205] Remove a few hundred/thousand array_merge calls --- src/Composer/Package/Version/VersionParser.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Composer/Package/Version/VersionParser.php b/src/Composer/Package/Version/VersionParser.php index 89bf4819f..f7650f367 100644 --- a/src/Composer/Package/Version/VersionParser.php +++ b/src/Composer/Package/Version/VersionParser.php @@ -257,10 +257,11 @@ class VersionParser foreach ($orConstraints as $constraints) { $andConstraints = preg_split('{(?< ,]) *(? 1) { - $constraintObjects = array(); + $constraintObjects = array(array()); foreach ($andConstraints as $constraint) { - $constraintObjects = array_merge($constraintObjects, $this->parseConstraint($constraint)); + $constraintObjects[] = $this->parseConstraint($constraint); } + $constraintObjects = call_user_func_array('array_merge', $constraintObjects); } else { $constraintObjects = $this->parseConstraint($andConstraints[0]); } From 22ecd0b740b5711655cc09925b27196a3ce7d7d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Mo=CC=88ller?= Date: Wed, 8 Jul 2015 10:39:09 -0400 Subject: [PATCH 063/205] Fix: Update docs for require command --- doc/03-cli.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/03-cli.md b/doc/03-cli.md index 136644519..574958d52 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -180,6 +180,7 @@ php composer.phar require vendor/package:2.* vendor/package2:dev-master * **--update-no-dev** Run the dependency update with the --no-dev option. * **--update-with-dependencies** Also update dependencies of the newly required packages. +* **--sort-packages** Keep packages sorted in `composer.json`. ## remove From 5b1b96b61e28942d623a76fc6f4d0fdf1ddb6382 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Wed, 8 Jul 2015 17:57:23 +0200 Subject: [PATCH 064/205] Output the number of rules used in the solver for profiling purposes --- src/Composer/DependencyResolver/Solver.php | 5 +++++ src/Composer/Installer.php | 1 + 2 files changed, 6 insertions(+) diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 6975df2cd..d0f7ec8fb 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -50,6 +50,11 @@ class Solver $this->ruleSetGenerator = new RuleSetGenerator($policy, $pool); } + public function getRuleSetSize() + { + return count($this->rules); + } + // aka solver_makeruledecisions private function makeAssertionRuleDecisions() { diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 464102120..1b329c2bb 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -513,6 +513,7 @@ class Installer if ($this->io->isVerbose()) { $this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies"); + $this->io->writeError("Analyzed ".$solver->getRuleSetSize()." rules to resolve dependencies"); } // force dev packages to be updated if we update or install from a (potentially new) lock From 15d572da4c2488acc6956dcaa76157da0781f03a Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Wed, 8 Jul 2015 18:36:49 +0200 Subject: [PATCH 065/205] Use 4 byte integer from raw md5 instead of 5 hex representation chars The hash is necessary as comparisons are significantly too slow otherwise. The old hash function used substr on the hexadecimal representation of the md5 hash, rather than the raw binary output. This wastes a significant amount of memory, as each byte can only be used to store up to 4 bit of information. The new hash has 32bit instead of 20bit and uses only a 4 byte integer instead of a 5 byte string. --- src/Composer/DependencyResolver/Rule.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index 37db43745..fe5085ae4 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -55,12 +55,11 @@ class Rule $this->reasonData = $reasonData; $this->disabled = false; - $this->job = $job; - $this->type = -1; - $this->ruleHash = substr(md5(implode(',', $this->literals)), 0, 5); + $data = unpack('ihash', md5(implode(',', $this->literals), true)); + $this->ruleHash = $data['hash']; } public function getHash() From c7e1f49e783f92960441b88fe23bc1e933797daa Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Wed, 8 Jul 2015 19:11:05 +0200 Subject: [PATCH 066/205] Rule hashes are only used in the rule set, so no need to store them --- src/Composer/DependencyResolver/Rule.php | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index fe5085ae4..a19c121c2 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -43,8 +43,6 @@ class Rule protected $job; - protected $ruleHash; - public function __construct(array $literals, $reason, $reasonData, $job = null) { // sort all packages ascending by id @@ -58,13 +56,12 @@ class Rule $this->job = $job; $this->type = -1; - $data = unpack('ihash', md5(implode(',', $this->literals), true)); - $this->ruleHash = $data['hash']; } public function getHash() { - return $this->ruleHash; + $data = unpack('ihash', md5(implode(',', $this->literals), true)); + return $data['hash']; } public function setId($id) @@ -113,10 +110,6 @@ class Rule */ public function equals(Rule $rule) { - if ($this->ruleHash !== $rule->ruleHash) { - return false; - } - if (count($this->literals) != count($rule->literals)) { return false; } From b869fa9662f8f750d3a11dd5e4c7d3b19c947c5b Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Wed, 8 Jul 2015 19:36:13 +0200 Subject: [PATCH 067/205] Correct rule hash test --- tests/Composer/Test/DependencyResolver/RuleTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Composer/Test/DependencyResolver/RuleTest.php b/tests/Composer/Test/DependencyResolver/RuleTest.php index 6688b24aa..4382987eb 100644 --- a/tests/Composer/Test/DependencyResolver/RuleTest.php +++ b/tests/Composer/Test/DependencyResolver/RuleTest.php @@ -30,7 +30,8 @@ class RuleTest extends TestCase { $rule = new Rule(array(123), 'job1', null); - $this->assertEquals(substr(md5('123'), 0, 5), $rule->getHash()); + $hash = unpack('ihash', md5('123', true)); + $this->assertEquals($hash['hash'], $rule->getHash()); } public function testSetAndGetId() From db1d58f3d3937253c2b336619de2855e1f392c3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Mo=CC=88ller?= Date: Wed, 8 Jul 2015 21:42:52 -0400 Subject: [PATCH 068/205] Fix: Append colon to option name (for consistency) --- doc/03-cli.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index 574958d52..c1ac86257 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -142,7 +142,7 @@ php composer.phar update vendor/* a bit of time to run so it is currently not done by default. * **--lock:** Only updates the lock file hash to suppress warning about the lock file being out of date. -* **--with-dependencies** Add also all dependencies of whitelisted packages to the whitelist. +* **--with-dependencies:** Add also all dependencies of whitelisted packages to the whitelist. * **--prefer-stable:** Prefer stable versions of dependencies. * **--prefer-lowest:** Prefer lowest versions of dependencies. Useful for testing minimal versions of requirements, generally used with `--prefer-stable`. @@ -177,10 +177,10 @@ php composer.phar require vendor/package:2.* vendor/package2:dev-master * **--no-update:** Disables the automatic update of the dependencies. * **--no-progress:** Removes the progress display that can mess with some terminals or scripts which don't handle backspace characters. -* **--update-no-dev** Run the dependency update with the --no-dev option. -* **--update-with-dependencies** Also update dependencies of the newly +* **--update-no-dev:** Run the dependency update with the --no-dev option. +* **--update-with-dependencies:** Also update dependencies of the newly required packages. -* **--sort-packages** Keep packages sorted in `composer.json`. +* **--sort-packages:** Keep packages sorted in `composer.json`. ## remove @@ -202,8 +202,8 @@ uninstalled. * **--no-update:** Disables the automatic update of the dependencies. * **--no-progress:** Removes the progress display that can mess with some terminals or scripts which don't handle backspace characters. -* **--update-no-dev** Run the dependency update with the --no-dev option. -* **--update-with-dependencies** Also update dependencies of the removed packages. +* **--update-no-dev:** Run the dependency update with the --no-dev option. +* **--update-with-dependencies:** Also update dependencies of the removed packages. ## global From 8b7f2c4984b1aeb75e8a206787559cc72d8f044e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Mo=CC=88ller?= Date: Wed, 8 Jul 2015 21:45:46 -0400 Subject: [PATCH 069/205] Fix: Render option mono-spaced --- doc/03-cli.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index c1ac86257..12d3c6171 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -177,7 +177,7 @@ php composer.phar require vendor/package:2.* vendor/package2:dev-master * **--no-update:** Disables the automatic update of the dependencies. * **--no-progress:** Removes the progress display that can mess with some terminals or scripts which don't handle backspace characters. -* **--update-no-dev:** Run the dependency update with the --no-dev option. +* **--update-no-dev:** Run the dependency update with the `--no-dev` option. * **--update-with-dependencies:** Also update dependencies of the newly required packages. * **--sort-packages:** Keep packages sorted in `composer.json`. From cb1470775c348e98d7c554e733dfec1882284323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Mo=CC=88ller?= Date: Wed, 8 Jul 2015 09:25:55 -0400 Subject: [PATCH 070/205] Enhancement: Also validate if composer.lock is up to date --- doc/03-cli.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index 136644519..7e9a9a343 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -339,7 +339,8 @@ php composer.phar validate ### Options -* **--no-check-all:** Whether or not Composer does a complete validation. +* **--no-check-all:** Do not emit a warning if requirements in `composer.json` use unbound version constraints. +* **--no-check-publish:** Do not emit an error and exit with non-zero if `composer.json` is unsuitable for publishing as a package on Packagist. ## status From a9b98dc5b0015e652c54a9bb03eb0cb65a9ff4a3 Mon Sep 17 00:00:00 2001 From: Ivan Krechetov Date: Thu, 9 Jul 2015 08:54:24 +0200 Subject: [PATCH 071/205] Fix a typo: interally -> internally --- doc/articles/versions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/articles/versions.md b/doc/articles/versions.md index d1629a494..226fd84e6 100644 --- a/doc/articles/versions.md +++ b/doc/articles/versions.md @@ -90,7 +90,7 @@ Example: `^1.2.3` ## Stability If you are using a constraint that does not explicitly define a stability, -Composer will default interally to `-dev` or `-stable`, depending on the +Composer will default internally to `-dev` or `-stable`, depending on the operator(s) used. This happens transparently. If you wish to explicitly consider only the stable release in the comparison, From 3fd46723829c9fd9ade5db3a2f6fdb8765542738 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 9 Jul 2015 12:57:34 +0200 Subject: [PATCH 072/205] VersionParser: Append elements directly instead of array_merge --- src/Composer/Package/Version/VersionParser.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Composer/Package/Version/VersionParser.php b/src/Composer/Package/Version/VersionParser.php index f7650f367..0f9faa8a7 100644 --- a/src/Composer/Package/Version/VersionParser.php +++ b/src/Composer/Package/Version/VersionParser.php @@ -257,11 +257,12 @@ class VersionParser foreach ($orConstraints as $constraints) { $andConstraints = preg_split('{(?< ,]) *(? 1) { - $constraintObjects = array(array()); + $constraintObjects = array(); foreach ($andConstraints as $constraint) { - $constraintObjects[] = $this->parseConstraint($constraint); + foreach ($this->parseConstraint($constraint) as $parsedConstraint) { + $constraintObjects[] = $parsedConstraint; + } } - $constraintObjects = call_user_func_array('array_merge', $constraintObjects); } else { $constraintObjects = $this->parseConstraint($andConstraints[0]); } From 39e6f51bef3a4b148d9f35a0ae7a082e9aed97f4 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 9 Jul 2015 13:04:41 +0200 Subject: [PATCH 073/205] Clarify --no-check-publish in docs --- doc/03-cli.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index 4ea1d1907..efa21e692 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -341,7 +341,8 @@ php composer.phar validate ### Options * **--no-check-all:** Do not emit a warning if requirements in `composer.json` use unbound version constraints. -* **--no-check-publish:** Do not emit an error and exit with non-zero if `composer.json` is unsuitable for publishing as a package on Packagist. +* **--no-check-publish:** Do not emit an error if `composer.json` is unsuitable for publishing as a package on Packagist but is otherwise valid. + ## status From 6e81f63635fb8f60a3a51af811832db735c8e558 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 9 Jul 2015 17:21:45 +0200 Subject: [PATCH 074/205] Reduce memory footprint of rules by storing data in blob Not declaring the job property saves significant amounts of memory as most rules leave it as null --- src/Composer/DependencyResolver/Problem.php | 2 +- src/Composer/DependencyResolver/Rule.php | 61 +++++++++---------- src/Composer/DependencyResolver/RuleSet.php | 1 - src/Composer/DependencyResolver/Solver.php | 6 +- .../Test/DependencyResolver/RuleTest.php | 13 +--- 5 files changed, 37 insertions(+), 46 deletions(-) diff --git a/src/Composer/DependencyResolver/Problem.php b/src/Composer/DependencyResolver/Problem.php index a1910c3ed..7fcb636b0 100644 --- a/src/Composer/DependencyResolver/Problem.php +++ b/src/Composer/DependencyResolver/Problem.php @@ -47,7 +47,7 @@ class Problem */ public function addRule(Rule $rule) { - $this->addReason($rule->getId(), array( + $this->addReason(spl_object_hash($rule), array( 'rule' => $rule, 'job' => $rule->getJob(), )); diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index a19c121c2..c34015b52 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -35,27 +35,22 @@ class Rule */ public $literals; - protected $disabled; - protected $type; - protected $id; - protected $reason; + protected $blob; protected $reasonData; - protected $job; - public function __construct(array $literals, $reason, $reasonData, $job = null) { // sort all packages ascending by id sort($literals); $this->literals = $literals; - $this->reason = $reason; $this->reasonData = $reasonData; - $this->disabled = false; - $this->job = $job; - $this->type = -1; + if ($job) { + $this->job = $job; + } + $this->blob = pack('ccc', -1, $reason, false); } public function getHash() @@ -64,24 +59,14 @@ class Rule return $data['hash']; } - public function setId($id) - { - $this->id = $id; - } - - public function getId() - { - return $this->id; - } - public function getJob() { - return $this->job; + return isset($this->job) ? $this->job : null; } public function getReason() { - return $this->reason; + return $this->getBlob('a2'); } public function getReasonData() @@ -91,11 +76,11 @@ class Rule public function getRequiredPackage() { - if ($this->reason === self::RULE_JOB_INSTALL) { + if ($this->getReason() === self::RULE_JOB_INSTALL) { return $this->reasonData; } - if ($this->reason === self::RULE_PACKAGE_REQUIRES) { + if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) { return $this->reasonData->getTarget(); } } @@ -125,32 +110,32 @@ class Rule public function setType($type) { - $this->type = $type; + return $this->setBlob('a1', $type); } public function getType() { - return $this->type; + return $this->getBlob('a1'); } public function disable() { - $this->disabled = true; + return $this->setBlob('a3', true); } public function enable() { - $this->disabled = false; + return $this->setBlob('a3', false); } public function isDisabled() { - return $this->disabled; + return (bool) $this->getBlob('a3'); } public function isEnabled() { - return !$this->disabled; + return !$this->getBlob('a3'); } /** @@ -176,7 +161,7 @@ class Rule $ruleText .= $pool->literalToPrettyString($literal, $installedMap); } - switch ($this->reason) { + switch ($this->getReason()) { case self::RULE_INTERNAL_ALLOW_UPDATE: return $ruleText; @@ -268,6 +253,20 @@ class Rule return implode(', ', $prepared); } + private function getBlob($var) + { + $current = unpack('c3a', $this->blob); + return $current[$var]; + } + + private function setBlob($var, $value) + { + $current = unpack('c3a', $this->blob); + $current[$var] = $value; + array_unshift($current, 'ccc'); + $this->blob = call_user_func_array('pack', $current); + } + /** * Formats a rule as a string of the format (Literal1|Literal2|...) * diff --git a/src/Composer/DependencyResolver/RuleSet.php b/src/Composer/DependencyResolver/RuleSet.php index b9545123f..02da881e8 100644 --- a/src/Composer/DependencyResolver/RuleSet.php +++ b/src/Composer/DependencyResolver/RuleSet.php @@ -66,7 +66,6 @@ class RuleSet implements \IteratorAggregate, \Countable $this->ruleById[$this->nextRuleId] = $rule; $rule->setType($type); - $rule->setId($this->nextRuleId); $this->nextRuleId++; $hash = $rule->getHash(); diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index d0f7ec8fb..f8f316269 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -319,7 +319,7 @@ class Solver $this->rules->add($newRule, RuleSet::TYPE_LEARNED); - $this->learnedWhy[$newRule->getId()] = $why; + $this->learnedWhy[spl_object_hash($newRule)] = $why; $ruleNode = new RuleWatchNode($newRule); $ruleNode->watch2OnHighest($this->decisions); @@ -454,7 +454,7 @@ class Solver private function analyzeUnsolvableRule($problem, $conflictRule) { - $why = $conflictRule->getId(); + $why = spl_object_hash($conflictRule); if ($conflictRule->getType() == RuleSet::TYPE_LEARNED) { $learnedWhy = $this->learnedWhy[$why]; @@ -572,7 +572,7 @@ class Solver private function enableDisableLearnedRules() { foreach ($this->rules->getIteratorFor(RuleSet::TYPE_LEARNED) as $rule) { - $why = $this->learnedWhy[$rule->getId()]; + $why = $this->learnedWhy[spl_object_hash($rule)]; $problemRules = $this->learnedPool[$why]; $foundDisabled = false; diff --git a/tests/Composer/Test/DependencyResolver/RuleTest.php b/tests/Composer/Test/DependencyResolver/RuleTest.php index 4382987eb..f71af15bd 100644 --- a/tests/Composer/Test/DependencyResolver/RuleTest.php +++ b/tests/Composer/Test/DependencyResolver/RuleTest.php @@ -13,6 +13,7 @@ namespace Composer\Test\DependencyResolver; use Composer\DependencyResolver\Rule; +use Composer\DependencyResolver\RuleSet; use Composer\DependencyResolver\Pool; use Composer\Repository\ArrayRepository; use Composer\TestCase; @@ -34,14 +35,6 @@ class RuleTest extends TestCase $this->assertEquals($hash['hash'], $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(1, 2), 'job1', null); @@ -69,9 +62,9 @@ class RuleTest extends TestCase public function testSetAndGetType() { $rule = new Rule(array(), 'job1', null); - $rule->setType('someType'); + $rule->setType(RuleSet::TYPE_JOB); - $this->assertEquals('someType', $rule->getType()); + $this->assertEquals(RuleSet::TYPE_JOB, $rule->getType()); } public function testEnable() From 961ea868ac63c38f22ed9d912c98bed06b005935 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 9 Jul 2015 18:26:31 +0200 Subject: [PATCH 075/205] Use an integer bitfield for rule properties instead of a string binary blob --- src/Composer/DependencyResolver/Rule.php | 26 ++++++++++----------- src/Composer/DependencyResolver/RuleSet.php | 4 ++-- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index c34015b52..a45205246 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -50,7 +50,7 @@ class Rule $this->job = $job; } - $this->blob = pack('ccc', -1, $reason, false); + $this->blob = (0 << 16) | ($reason << 8) | (255 << 0); } public function getHash() @@ -66,7 +66,7 @@ class Rule public function getReason() { - return $this->getBlob('a2'); + return $this->getBlob(1); } public function getReasonData() @@ -110,32 +110,32 @@ class Rule public function setType($type) { - return $this->setBlob('a1', $type); + return $this->setBlob(0, $type); } public function getType() { - return $this->getBlob('a1'); + return $this->getBlob(0); } public function disable() { - return $this->setBlob('a3', true); + return $this->setBlob(2, 1); } public function enable() { - return $this->setBlob('a3', false); + return $this->setBlob(2, 0); } public function isDisabled() { - return (bool) $this->getBlob('a3'); + return (bool) $this->getBlob(2); } public function isEnabled() { - return !$this->getBlob('a3'); + return !$this->getBlob(2); } /** @@ -255,16 +255,14 @@ class Rule private function getBlob($var) { - $current = unpack('c3a', $this->blob); - return $current[$var]; + $offset = 8*$var; + return ($this->blob & (255 << $offset)) >> $offset; } private function setBlob($var, $value) { - $current = unpack('c3a', $this->blob); - $current[$var] = $value; - array_unshift($current, 'ccc'); - $this->blob = call_user_func_array('pack', $current); + $offset = 8*$var; + $this->blob = ($this->blob & ~(255 << $offset)) | ((255 & $value) << $offset); } /** diff --git a/src/Composer/DependencyResolver/RuleSet.php b/src/Composer/DependencyResolver/RuleSet.php index 02da881e8..26771cef6 100644 --- a/src/Composer/DependencyResolver/RuleSet.php +++ b/src/Composer/DependencyResolver/RuleSet.php @@ -30,7 +30,7 @@ class RuleSet implements \IteratorAggregate, \Countable public $ruleById; protected static $types = array( - -1 => 'UNKNOWN', + 255 => 'UNKNOWN', self::TYPE_PACKAGE => 'PACKAGE', self::TYPE_JOB => 'JOB', self::TYPE_LEARNED => 'LEARNED', @@ -130,7 +130,7 @@ class RuleSet implements \IteratorAggregate, \Countable public function getTypes() { $types = self::$types; - unset($types[-1]); + unset($types[255]); return array_keys($types); } From 329ab5cf41fd6c2fe5fd037d59e5153dd009d8e3 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 9 Jul 2015 18:44:56 +0200 Subject: [PATCH 076/205] Rename blob rule property to bitfield --- src/Composer/DependencyResolver/Rule.php | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index a45205246..e0f6ac138 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -35,7 +35,7 @@ class Rule */ public $literals; - protected $blob; + protected $bitfield; protected $reasonData; public function __construct(array $literals, $reason, $reasonData, $job = null) @@ -50,7 +50,7 @@ class Rule $this->job = $job; } - $this->blob = (0 << 16) | ($reason << 8) | (255 << 0); + $this->bitfield = (0 << 16) | ($reason << 8) | (255 << 0); } public function getHash() @@ -66,7 +66,7 @@ class Rule public function getReason() { - return $this->getBlob(1); + return $this->getBitfield(1); } public function getReasonData() @@ -110,32 +110,32 @@ class Rule public function setType($type) { - return $this->setBlob(0, $type); + return $this->setBitfield(0, $type); } public function getType() { - return $this->getBlob(0); + return $this->getBitfield(0); } public function disable() { - return $this->setBlob(2, 1); + return $this->setBitfield(2, 1); } public function enable() { - return $this->setBlob(2, 0); + return $this->setBitfield(2, 0); } public function isDisabled() { - return (bool) $this->getBlob(2); + return (bool) $this->getBitfield(2); } public function isEnabled() { - return !$this->getBlob(2); + return !$this->getBitfield(2); } /** @@ -253,16 +253,16 @@ class Rule return implode(', ', $prepared); } - private function getBlob($var) + private function getBitfield($var) { $offset = 8*$var; - return ($this->blob & (255 << $offset)) >> $offset; + return ($this->bitfield & (255 << $offset)) >> $offset; } - private function setBlob($var, $value) + private function setBitfield($var, $value) { $offset = 8*$var; - $this->blob = ($this->blob & ~(255 << $offset)) | ((255 & $value) << $offset); + $this->bitfield = ($this->bitfield & ~(255 << $offset)) | ((255 & $value) << $offset); } /** From f535542fcac3365ca8f237874070bd54e9085d52 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 9 Jul 2015 18:59:16 +0200 Subject: [PATCH 077/205] Use constants with names for bitfield offsets --- src/Composer/DependencyResolver/Rule.php | 28 ++++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index e0f6ac138..776cd1455 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -29,6 +29,10 @@ class Rule const RULE_LEARNED = 12; const RULE_PACKAGE_ALIAS = 13; + const BITFIELD_TYPE = 0; + const BITFIELD_REASON = 8; + const BITFIELD_DISABLED = 16; + /** * READ-ONLY: The literals this rule consists of. * @var array @@ -50,7 +54,9 @@ class Rule $this->job = $job; } - $this->bitfield = (0 << 16) | ($reason << 8) | (255 << 0); + $this->bitfield = (0 << self::BITFIELD_DISABLED) | + ($reason << self::BITFIELD_REASON) | + (255 << self::BITFIELD_TYPE); } public function getHash() @@ -66,7 +72,7 @@ class Rule public function getReason() { - return $this->getBitfield(1); + return $this->getBitfield(self::BITFIELD_REASON); } public function getReasonData() @@ -110,32 +116,32 @@ class Rule public function setType($type) { - return $this->setBitfield(0, $type); + return $this->setBitfield(self::BITFIELD_TYPE, $type); } public function getType() { - return $this->getBitfield(0); + return $this->getBitfield(self::BITFIELD_TYPE); } public function disable() { - return $this->setBitfield(2, 1); + return $this->setBitfield(self::BITFIELD_DISABLED, 1); } public function enable() { - return $this->setBitfield(2, 0); + return $this->setBitfield(self::BITFIELD_DISABLED, 0); } public function isDisabled() { - return (bool) $this->getBitfield(2); + return (bool) $this->getBitfield(self::BITFIELD_DISABLED); } public function isEnabled() { - return !$this->getBitfield(2); + return !$this->getBitfield(self::BITFIELD_DISABLED); } /** @@ -253,15 +259,13 @@ class Rule return implode(', ', $prepared); } - private function getBitfield($var) + private function getBitfield($offset) { - $offset = 8*$var; return ($this->bitfield & (255 << $offset)) >> $offset; } - private function setBitfield($var, $value) + private function setBitfield($offset, $value) { - $offset = 8*$var; $this->bitfield = ($this->bitfield & ~(255 << $offset)) | ((255 & $value) << $offset); } From 956035e64113c985ee7254e6f8f95f1dffdb240f Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 9 Jul 2015 19:40:03 +0200 Subject: [PATCH 078/205] Remove the unnecessary return statements from setters --- src/Composer/DependencyResolver/Rule.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index 776cd1455..f129c6f66 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -116,7 +116,7 @@ class Rule public function setType($type) { - return $this->setBitfield(self::BITFIELD_TYPE, $type); + $this->setBitfield(self::BITFIELD_TYPE, $type); } public function getType() @@ -126,12 +126,12 @@ class Rule public function disable() { - return $this->setBitfield(self::BITFIELD_DISABLED, 1); + $this->setBitfield(self::BITFIELD_DISABLED, 1); } public function enable() { - return $this->setBitfield(self::BITFIELD_DISABLED, 0); + $this->setBitfield(self::BITFIELD_DISABLED, 0); } public function isDisabled() From 5828f6202d332c1c3afe7eb309b3eae994c483a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Mo=CC=88ller?= Date: Tue, 7 Jul 2015 20:12:59 -0400 Subject: [PATCH 079/205] Enhancement: Also validate lock file --- doc/03-cli.md | 2 +- src/Composer/Command/ValidateCommand.php | 26 ++++++++++++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index efa21e692..57e1d08c5 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -341,9 +341,9 @@ php composer.phar validate ### Options * **--no-check-all:** Do not emit a warning if requirements in `composer.json` use unbound version constraints. +* **--no-check-lock:** Do not emit an error if `composer.lock` exists and is not up to date. * **--no-check-publish:** Do not emit an error if `composer.json` is unsuitable for publishing as a package on Packagist but is otherwise valid. - ## status If you often need to modify the code of your dependencies and they are diff --git a/src/Composer/Command/ValidateCommand.php b/src/Composer/Command/ValidateCommand.php index 320032984..8a1595a04 100644 --- a/src/Composer/Command/ValidateCommand.php +++ b/src/Composer/Command/ValidateCommand.php @@ -12,6 +12,7 @@ namespace Composer\Command; +use Composer\Factory; use Composer\Package\Loader\ValidatingArrayLoader; use Composer\Util\ConfigValidator; use Symfony\Component\Console\Input\InputArgument; @@ -34,14 +35,15 @@ class ValidateCommand extends Command { $this ->setName('validate') - ->setDescription('Validates a composer.json') + ->setDescription('Validates a composer.json and composer.lock') ->setDefinition(array( new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not make a complete validation'), + new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'), new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'), new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file', './composer.json') )) ->setHelp(<<getOption('no-check-publish'); list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll); + $checkLock = !$input->getOption('no-check-lock'); + + $lockErrors = array(); + $composer = Factory::create($this->getIO(), $file); + $locker = $composer->getLocker(); + if ($locker->isLocked() && !$locker->isFresh()) { + $lockErrors[] = 'The lock file is not up to date with the latest changes in composer.json.'; + } + // output errors/warnings if (!$errors && !$publishErrors && !$warnings) { $this->getIO()->write('' . $file . ' is valid'); @@ -92,19 +103,26 @@ EOT 'warning' => $warnings, ); - // If checking publish errors, display them errors, otherwise just show them as warnings + // If checking publish errors, display them as errors, otherwise just show them as warnings if ($checkPublish) { $messages['error'] = array_merge($messages['error'], $publishErrors); } else { $messages['warning'] = array_merge($messages['warning'], $publishErrors); } + // If checking lock errors, display them as errors, otherwise just show them as warnings + if ($checkLock) { + $messages['error'] = array_merge($messages['error'], $lockErrors); + } else { + $messages['warning'] = array_merge($messages['warning'], $lockErrors); + } + foreach ($messages as $style => $msgs) { foreach ($msgs as $msg) { $this->getIO()->writeError('<' . $style . '>' . $msg . ''); } } - return $errors || ($publishErrors && $checkPublish) ? 1 : 0; + return $errors || ($publishErrors && $checkPublish) || ($lockErrors && $checkLock) ? 1 : 0; } } From ccaba0d2f733d375bf680c3af3d0ca3b9951541f Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Tue, 14 Jul 2015 14:12:19 +0200 Subject: [PATCH 080/205] Make static translation tables in version constraint private and use === --- src/Composer/Package/LinkConstraint/VersionConstraint.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Composer/Package/LinkConstraint/VersionConstraint.php b/src/Composer/Package/LinkConstraint/VersionConstraint.php index f5aee77bc..4b6cf2ad7 100644 --- a/src/Composer/Package/LinkConstraint/VersionConstraint.php +++ b/src/Composer/Package/LinkConstraint/VersionConstraint.php @@ -28,7 +28,7 @@ class VersionConstraint extends SpecificConstraint const OP_GE = 4; const OP_NE = 5; - static $transOpStr = array( + private static $transOpStr = array( '=' => self::OP_EQ, '==' => self::OP_EQ, '<' => self::OP_LT, @@ -39,7 +39,7 @@ class VersionConstraint extends SpecificConstraint '!=' => self::OP_NE, ); - static $transOpInt = array( + private static $transOpInt = array( self::OP_EQ => '==', self::OP_LT => '<', self::OP_LE => '<=', @@ -103,7 +103,7 @@ class VersionConstraint extends SpecificConstraint // an example for the condition is <= 2.0 & < 1.0 // these kinds of comparisons always have a solution - if ($this->operator != self::OP_EQ && $noEqualOp == $providerNoEqualOp) { + if ($this->operator !== self::OP_EQ && $noEqualOp == $providerNoEqualOp) { return true; } From cf1af585148e4f2c2a7321d59da7cb988b1ba117 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Tue, 14 Jul 2015 14:18:50 +0200 Subject: [PATCH 081/205] Use bitwise operators directly in rules instead of get/set Bitfield --- src/Composer/DependencyResolver/Rule.php | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index f129c6f66..5d95d678a 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -72,7 +72,7 @@ class Rule public function getReason() { - return $this->getBitfield(self::BITFIELD_REASON); + return ($this->bitfield & (255 << self::BITFIELD_REASON)) >> self::BITFIELD_REASON; } public function getReasonData() @@ -116,32 +116,32 @@ class Rule public function setType($type) { - $this->setBitfield(self::BITFIELD_TYPE, $type); + $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_TYPE)) | ((255 & $type) << self::BITFIELD_TYPE); } public function getType() { - return $this->getBitfield(self::BITFIELD_TYPE); + return ($this->bitfield & (255 << self::BITFIELD_TYPE)) >> self::BITFIELD_TYPE; } public function disable() { - $this->setBitfield(self::BITFIELD_DISABLED, 1); + $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_DISABLED)) | (1 << self::BITFIELD_DISABLED); } public function enable() { - $this->setBitfield(self::BITFIELD_DISABLED, 0); + $this->bitfield = $this->bitfield & ~(255 << self::BITFIELD_DISABLED); } public function isDisabled() { - return (bool) $this->getBitfield(self::BITFIELD_DISABLED); + return (bool) (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED); } public function isEnabled() { - return !$this->getBitfield(self::BITFIELD_DISABLED); + return !(($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED); } /** @@ -259,16 +259,6 @@ class Rule return implode(', ', $prepared); } - private function getBitfield($offset) - { - return ($this->bitfield & (255 << $offset)) >> $offset; - } - - private function setBitfield($offset, $value) - { - $this->bitfield = ($this->bitfield & ~(255 << $offset)) | ((255 & $value) << $offset); - } - /** * Formats a rule as a string of the format (Literal1|Literal2|...) * From 5ae9e7fe22f174f2466c631989eeca2a6affd276 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Thu, 16 Jul 2015 11:42:12 +0200 Subject: [PATCH 082/205] remove spdx files, introduce external library --- bin/update-spdx-licenses | 10 - composer.json | 2 +- composer.lock | 63 +- res/spdx-exceptions.json | 29 - res/spdx-licenses.json | 1178 ------------------ src/Composer/Command/ShowCommand.php | 6 +- src/Composer/Util/ConfigValidator.php | 3 +- src/Composer/Util/SpdxLicense.php | 306 ----- src/Composer/Util/SpdxLicensesUpdater.php | 139 --- tests/Composer/Test/Util/SpdxLicenseTest.php | 145 --- 10 files changed, 68 insertions(+), 1813 deletions(-) delete mode 100755 bin/update-spdx-licenses delete mode 100644 res/spdx-exceptions.json delete mode 100644 res/spdx-licenses.json delete mode 100644 src/Composer/Util/SpdxLicense.php delete mode 100644 src/Composer/Util/SpdxLicensesUpdater.php delete mode 100644 tests/Composer/Test/Util/SpdxLicenseTest.php diff --git a/bin/update-spdx-licenses b/bin/update-spdx-licenses deleted file mode 100755 index f6b6f9209..000000000 --- a/bin/update-spdx-licenses +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env php -dumpLicenses(__DIR__ . '/../res/spdx-licenses.json'); -$updater->dumpExceptions(__DIR__ . '/../res/spdx-exceptions.json'); diff --git a/composer.json b/composer.json index ffac4f254..74df757f3 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ }, "require": { "php": ">=5.3.2", - "justinrainbow/json-schema": "~1.4", + "composer/spdx-licenses": "~1.0", "seld/jsonlint": "~1.0", "symfony/console": "~2.5", "symfony/finder": "~2.2", diff --git a/composer.lock b/composer.lock index b45ec64a2..154102042 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,69 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "556ac817fc0b456bddc48918ef09930d", + "hash": "694654491125336d91b339a8e117bb40", "packages": [ + { + "name": "composer/spdx-licenses", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/composer/spdx-licenses.git", + "reference": "abf7dfc7da7d7dc66c147a91b6e927099512292a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/abf7dfc7da7d7dc66c147a91b6e927099512292a", + "reference": "abf7dfc7da7d7dc66c147a91b6e927099512292a", + "shasum": "" + }, + "require": { + "justinrainbow/json-schema": "~1.4", + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.5", + "phpunit/phpunit-mock-objects": "~2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Spdx\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com" + }, + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "SPDX licenses list and validation library.", + "keywords": [ + "license", + "spdx", + "validator" + ], + "time": "2015-07-15 17:38:14" + }, { "name": "justinrainbow/json-schema", "version": "1.4.1", diff --git a/res/spdx-exceptions.json b/res/spdx-exceptions.json deleted file mode 100644 index 15491d2a5..000000000 --- a/res/spdx-exceptions.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "Autoconf-exception-2.0": [ - "Autoconf exception 2.0" - ], - "Autoconf-exception-3.0": [ - "Autoconf exception 3.0" - ], - "Bison-exception-2.2": [ - "Bison exception 2.2" - ], - "Classpath-exception-2.0": [ - "Classpath exception 2.0" - ], - "eCos-exception-2.0": [ - "eCos exception 2.0" - ], - "Font-exception-2.0": [ - "Font exception 2.0" - ], - "GCC-exception-2.0": [ - "GCC Runtime Library exception 2.0" - ], - "GCC-exception-3.1": [ - "GCC Runtime Library exception 3.1" - ], - "WxWindows-exception-3.1": [ - "WxWindows Library Exception 3.1" - ] -} \ No newline at end of file diff --git a/res/spdx-licenses.json b/res/spdx-licenses.json deleted file mode 100644 index 7cb654966..000000000 --- a/res/spdx-licenses.json +++ /dev/null @@ -1,1178 +0,0 @@ -{ - "Glide": [ - "3dfx Glide License", - false - ], - "Abstyles": [ - "Abstyles License", - false - ], - "AFL-1.1": [ - "Academic Free License v1.1", - true - ], - "AFL-1.2": [ - "Academic Free License v1.2", - true - ], - "AFL-2.0": [ - "Academic Free License v2.0", - true - ], - "AFL-2.1": [ - "Academic Free License v2.1", - true - ], - "AFL-3.0": [ - "Academic Free License v3.0", - true - ], - "AMPAS": [ - "Academy of Motion Picture Arts and Sciences BSD", - false - ], - "APL-1.0": [ - "Adaptive Public License 1.0", - true - ], - "Adobe-Glyph": [ - "Adobe Glyph List License", - false - ], - "APAFML": [ - "Adobe Postscript AFM License", - false - ], - "Adobe-2006": [ - "Adobe Systems Incorporated Source Code License Agreement", - false - ], - "AGPL-1.0": [ - "Affero General Public License v1.0", - false - ], - "Afmparse": [ - "Afmparse License", - false - ], - "Aladdin": [ - "Aladdin Free Public License", - false - ], - "ADSL": [ - "Amazon Digital Services License", - false - ], - "AMDPLPA": [ - "AMD's plpa_map.c License", - false - ], - "ANTLR-PD": [ - "ANTLR Software Rights Notice", - false - ], - "Apache-1.0": [ - "Apache License 1.0", - false - ], - "Apache-1.1": [ - "Apache License 1.1", - true - ], - "Apache-2.0": [ - "Apache License 2.0", - true - ], - "AML": [ - "Apple MIT License", - false - ], - "APSL-1.0": [ - "Apple Public Source License 1.0", - true - ], - "APSL-1.1": [ - "Apple Public Source License 1.1", - true - ], - "APSL-1.2": [ - "Apple Public Source License 1.2", - true - ], - "APSL-2.0": [ - "Apple Public Source License 2.0", - true - ], - "Artistic-1.0": [ - "Artistic License 1.0", - true - ], - "Artistic-1.0-Perl": [ - "Artistic License 1.0 (Perl)", - true - ], - "Artistic-1.0-cl8": [ - "Artistic License 1.0 w/clause 8", - true - ], - "Artistic-2.0": [ - "Artistic License 2.0", - true - ], - "AAL": [ - "Attribution Assurance License", - true - ], - "Bahyph": [ - "Bahyph License", - false - ], - "Barr": [ - "Barr License", - false - ], - "Beerware": [ - "Beerware License", - false - ], - "BitTorrent-1.0": [ - "BitTorrent Open Source License v1.0", - false - ], - "BitTorrent-1.1": [ - "BitTorrent Open Source License v1.1", - false - ], - "BSL-1.0": [ - "Boost Software License 1.0", - true - ], - "Borceux": [ - "Borceux license", - false - ], - "BSD-2-Clause": [ - "BSD 2-clause \"Simplified\" License", - true - ], - "BSD-2-Clause-FreeBSD": [ - "BSD 2-clause FreeBSD License", - false - ], - "BSD-2-Clause-NetBSD": [ - "BSD 2-clause NetBSD License", - false - ], - "BSD-3-Clause": [ - "BSD 3-clause \"New\" or \"Revised\" License", - true - ], - "BSD-3-Clause-Clear": [ - "BSD 3-clause Clear License", - false - ], - "BSD-4-Clause": [ - "BSD 4-clause \"Original\" or \"Old\" License", - false - ], - "BSD-Protection": [ - "BSD Protection License", - false - ], - "BSD-3-Clause-Attribution": [ - "BSD with attribution", - false - ], - "BSD-4-Clause-UC": [ - "BSD-4-Clause (University of California-Specific)", - false - ], - "bzip2-1.0.5": [ - "bzip2 and libbzip2 License v1.0.5", - false - ], - "bzip2-1.0.6": [ - "bzip2 and libbzip2 License v1.0.6", - false - ], - "Caldera": [ - "Caldera License", - false - ], - "CECILL-1.0": [ - "CeCILL Free Software License Agreement v1.0", - false - ], - "CECILL-1.1": [ - "CeCILL Free Software License Agreement v1.1", - false - ], - "CECILL-2.0": [ - "CeCILL Free Software License Agreement v2.0", - false - ], - "CECILL-B": [ - "CeCILL-B Free Software License Agreement", - false - ], - "CECILL-C": [ - "CeCILL-C Free Software License Agreement", - false - ], - "ClArtistic": [ - "Clarified Artistic License", - false - ], - "MIT-CMU": [ - "CMU License", - false - ], - "CNRI-Python": [ - "CNRI Python License", - true - ], - "CNRI-Python-GPL-Compatible": [ - "CNRI Python Open Source GPL Compatible License Agreement", - false - ], - "CPOL-1.02": [ - "Code Project Open License 1.02", - false - ], - "CDDL-1.0": [ - "Common Development and Distribution License 1.0", - true - ], - "CDDL-1.1": [ - "Common Development and Distribution License 1.1", - false - ], - "CPAL-1.0": [ - "Common Public Attribution License 1.0", - true - ], - "CPL-1.0": [ - "Common Public License 1.0", - true - ], - "CATOSL-1.1": [ - "Computer Associates Trusted Open Source License 1.1", - true - ], - "Condor-1.1": [ - "Condor Public License v1.1", - false - ], - "CC-BY-1.0": [ - "Creative Commons Attribution 1.0", - false - ], - "CC-BY-2.0": [ - "Creative Commons Attribution 2.0", - false - ], - "CC-BY-2.5": [ - "Creative Commons Attribution 2.5", - false - ], - "CC-BY-3.0": [ - "Creative Commons Attribution 3.0", - false - ], - "CC-BY-4.0": [ - "Creative Commons Attribution 4.0", - false - ], - "CC-BY-ND-1.0": [ - "Creative Commons Attribution No Derivatives 1.0", - false - ], - "CC-BY-ND-2.0": [ - "Creative Commons Attribution No Derivatives 2.0", - false - ], - "CC-BY-ND-2.5": [ - "Creative Commons Attribution No Derivatives 2.5", - false - ], - "CC-BY-ND-3.0": [ - "Creative Commons Attribution No Derivatives 3.0", - false - ], - "CC-BY-ND-4.0": [ - "Creative Commons Attribution No Derivatives 4.0", - false - ], - "CC-BY-NC-1.0": [ - "Creative Commons Attribution Non Commercial 1.0", - false - ], - "CC-BY-NC-2.0": [ - "Creative Commons Attribution Non Commercial 2.0", - false - ], - "CC-BY-NC-2.5": [ - "Creative Commons Attribution Non Commercial 2.5", - false - ], - "CC-BY-NC-3.0": [ - "Creative Commons Attribution Non Commercial 3.0", - false - ], - "CC-BY-NC-4.0": [ - "Creative Commons Attribution Non Commercial 4.0", - false - ], - "CC-BY-NC-ND-1.0": [ - "Creative Commons Attribution Non Commercial No Derivatives 1.0", - false - ], - "CC-BY-NC-ND-2.0": [ - "Creative Commons Attribution Non Commercial No Derivatives 2.0", - false - ], - "CC-BY-NC-ND-2.5": [ - "Creative Commons Attribution Non Commercial No Derivatives 2.5", - false - ], - "CC-BY-NC-ND-3.0": [ - "Creative Commons Attribution Non Commercial No Derivatives 3.0", - false - ], - "CC-BY-NC-ND-4.0": [ - "Creative Commons Attribution Non Commercial No Derivatives 4.0", - false - ], - "CC-BY-NC-SA-1.0": [ - "Creative Commons Attribution Non Commercial Share Alike 1.0", - false - ], - "CC-BY-NC-SA-2.0": [ - "Creative Commons Attribution Non Commercial Share Alike 2.0", - false - ], - "CC-BY-NC-SA-2.5": [ - "Creative Commons Attribution Non Commercial Share Alike 2.5", - false - ], - "CC-BY-NC-SA-3.0": [ - "Creative Commons Attribution Non Commercial Share Alike 3.0", - false - ], - "CC-BY-NC-SA-4.0": [ - "Creative Commons Attribution Non Commercial Share Alike 4.0", - false - ], - "CC-BY-SA-1.0": [ - "Creative Commons Attribution Share Alike 1.0", - false - ], - "CC-BY-SA-2.0": [ - "Creative Commons Attribution Share Alike 2.0", - false - ], - "CC-BY-SA-2.5": [ - "Creative Commons Attribution Share Alike 2.5", - false - ], - "CC-BY-SA-3.0": [ - "Creative Commons Attribution Share Alike 3.0", - false - ], - "CC-BY-SA-4.0": [ - "Creative Commons Attribution Share Alike 4.0", - false - ], - "CC0-1.0": [ - "Creative Commons Zero v1.0 Universal", - false - ], - "Crossword": [ - "Crossword License", - false - ], - "CUA-OPL-1.0": [ - "CUA Office Public License v1.0", - true - ], - "Cube": [ - "Cube License", - false - ], - "D-FSL-1.0": [ - "Deutsche Freie Software Lizenz", - false - ], - "diffmark": [ - "diffmark license", - false - ], - "WTFPL": [ - "Do What The F*ck You Want To Public License", - false - ], - "DOC": [ - "DOC License", - false - ], - "Dotseqn": [ - "Dotseqn License", - false - ], - "DSDP": [ - "DSDP License", - false - ], - "dvipdfm": [ - "dvipdfm License", - false - ], - "EPL-1.0": [ - "Eclipse Public License 1.0", - true - ], - "ECL-1.0": [ - "Educational Community License v1.0", - true - ], - "ECL-2.0": [ - "Educational Community License v2.0", - true - ], - "eGenix": [ - "eGenix.com Public License 1.1.0", - false - ], - "EFL-1.0": [ - "Eiffel Forum License v1.0", - true - ], - "EFL-2.0": [ - "Eiffel Forum License v2.0", - true - ], - "MIT-advertising": [ - "Enlightenment License (e16)", - false - ], - "MIT-enna": [ - "enna License", - false - ], - "Entessa": [ - "Entessa Public License v1.0", - true - ], - "ErlPL-1.1": [ - "Erlang Public License v1.1", - false - ], - "EUDatagrid": [ - "EU DataGrid Software License", - true - ], - "EUPL-1.0": [ - "European Union Public License 1.0", - false - ], - "EUPL-1.1": [ - "European Union Public License 1.1", - true - ], - "Eurosym": [ - "Eurosym License", - false - ], - "Fair": [ - "Fair License", - true - ], - "MIT-feh": [ - "feh License", - false - ], - "Frameworx-1.0": [ - "Frameworx Open License 1.0", - true - ], - "FreeImage": [ - "FreeImage Public License v1.0", - false - ], - "FTL": [ - "Freetype Project License", - false - ], - "FSFUL": [ - "FSF Unlimited License", - false - ], - "FSFULLR": [ - "FSF Unlimited License (with License Retention)", - false - ], - "Giftware": [ - "Giftware License", - false - ], - "GL2PS": [ - "GL2PS License", - false - ], - "Glulxe": [ - "Glulxe License", - false - ], - "AGPL-3.0": [ - "GNU Affero General Public License v3.0", - true - ], - "GFDL-1.1": [ - "GNU Free Documentation License v1.1", - false - ], - "GFDL-1.2": [ - "GNU Free Documentation License v1.2", - false - ], - "GFDL-1.3": [ - "GNU Free Documentation License v1.3", - false - ], - "GPL-1.0": [ - "GNU General Public License v1.0 only", - false - ], - "GPL-2.0": [ - "GNU General Public License v2.0 only", - true - ], - "GPL-3.0": [ - "GNU General Public License v3.0 only", - true - ], - "LGPL-2.1": [ - "GNU Lesser General Public License v2.1 only", - true - ], - "LGPL-3.0": [ - "GNU Lesser General Public License v3.0 only", - true - ], - "LGPL-2.0": [ - "GNU Library General Public License v2 only", - true - ], - "gnuplot": [ - "gnuplot License", - false - ], - "gSOAP-1.3b": [ - "gSOAP Public License v1.3b", - false - ], - "HaskellReport": [ - "Haskell Language Report License", - false - ], - "HPND": [ - "Historic Permission Notice and Disclaimer", - true - ], - "IBM-pibs": [ - "IBM PowerPC Initialization and Boot Software", - false - ], - "IPL-1.0": [ - "IBM Public License v1.0", - true - ], - "ImageMagick": [ - "ImageMagick License", - false - ], - "iMatix": [ - "iMatix Standard Function Library Agreement", - false - ], - "Imlib2": [ - "Imlib2 License", - false - ], - "IJG": [ - "Independent JPEG Group License", - false - ], - "Intel-ACPI": [ - "Intel ACPI Software License Agreement", - false - ], - "Intel": [ - "Intel Open Source License", - true - ], - "IPA": [ - "IPA Font License", - true - ], - "ISC": [ - "ISC License", - true - ], - "JasPer-2.0": [ - "JasPer License", - false - ], - "JSON": [ - "JSON License", - false - ], - "LPPL-1.3a": [ - "LaTeX Project Public License 1.3a", - false - ], - "LPPL-1.0": [ - "LaTeX Project Public License v1.0", - false - ], - "LPPL-1.1": [ - "LaTeX Project Public License v1.1", - false - ], - "LPPL-1.2": [ - "LaTeX Project Public License v1.2", - false - ], - "LPPL-1.3c": [ - "LaTeX Project Public License v1.3c", - true - ], - "Latex2e": [ - "Latex2e License", - false - ], - "BSD-3-Clause-LBNL": [ - "Lawrence Berkeley National Labs BSD variant license", - false - ], - "Leptonica": [ - "Leptonica License", - false - ], - "Libpng": [ - "libpng License", - false - ], - "libtiff": [ - "libtiff License", - false - ], - "LPL-1.02": [ - "Lucent Public License v1.02", - true - ], - "LPL-1.0": [ - "Lucent Public License Version 1.0", - true - ], - "MakeIndex": [ - "MakeIndex License", - false - ], - "MTLL": [ - "Matrix Template Library License", - false - ], - "MS-PL": [ - "Microsoft Public License", - true - ], - "MS-RL": [ - "Microsoft Reciprocal License", - true - ], - "MirOS": [ - "MirOS Licence", - true - ], - "MITNFA": [ - "MIT +no-false-attribs license", - false - ], - "MIT": [ - "MIT License", - true - ], - "Motosoto": [ - "Motosoto License", - true - ], - "MPL-1.0": [ - "Mozilla Public License 1.0", - true - ], - "MPL-1.1": [ - "Mozilla Public License 1.1", - true - ], - "MPL-2.0": [ - "Mozilla Public License 2.0", - true - ], - "MPL-2.0-no-copyleft-exception": [ - "Mozilla Public License 2.0 (no copyleft exception)", - true - ], - "mpich2": [ - "mpich2 License", - false - ], - "Multics": [ - "Multics License", - true - ], - "Mup": [ - "Mup License", - false - ], - "NASA-1.3": [ - "NASA Open Source Agreement 1.3", - true - ], - "Naumen": [ - "Naumen Public License", - true - ], - "NBPL-1.0": [ - "Net Boolean Public License v1", - false - ], - "NetCDF": [ - "NetCDF license", - false - ], - "NGPL": [ - "Nethack General Public License", - true - ], - "NOSL": [ - "Netizen Open Source License", - false - ], - "NPL-1.0": [ - "Netscape Public License v1.0", - false - ], - "NPL-1.1": [ - "Netscape Public License v1.1", - false - ], - "Newsletr": [ - "Newsletr License", - false - ], - "NLPL": [ - "No Limit Public License", - false - ], - "Nokia": [ - "Nokia Open Source License", - true - ], - "NPOSL-3.0": [ - "Non-Profit Open Software License 3.0", - true - ], - "Noweb": [ - "Noweb License", - false - ], - "NRL": [ - "NRL License", - false - ], - "NTP": [ - "NTP License", - true - ], - "Nunit": [ - "Nunit License", - false - ], - "OCLC-2.0": [ - "OCLC Research Public License 2.0", - true - ], - "ODbL-1.0": [ - "ODC Open Database License v1.0", - false - ], - "PDDL-1.0": [ - "ODC Public Domain Dedication & License 1.0", - false - ], - "OGTSL": [ - "Open Group Test Suite License", - true - ], - "OLDAP-2.2.2": [ - "Open LDAP Public License 2.2.2", - false - ], - "OLDAP-1.1": [ - "Open LDAP Public License v1.1", - false - ], - "OLDAP-1.2": [ - "Open LDAP Public License v1.2", - false - ], - "OLDAP-1.3": [ - "Open LDAP Public License v1.3", - false - ], - "OLDAP-1.4": [ - "Open LDAP Public License v1.4", - false - ], - "OLDAP-2.0": [ - "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)", - false - ], - "OLDAP-2.0.1": [ - "Open LDAP Public License v2.0.1", - false - ], - "OLDAP-2.1": [ - "Open LDAP Public License v2.1", - false - ], - "OLDAP-2.2": [ - "Open LDAP Public License v2.2", - false - ], - "OLDAP-2.2.1": [ - "Open LDAP Public License v2.2.1", - false - ], - "OLDAP-2.3": [ - "Open LDAP Public License v2.3", - false - ], - "OLDAP-2.4": [ - "Open LDAP Public License v2.4", - false - ], - "OLDAP-2.5": [ - "Open LDAP Public License v2.5", - false - ], - "OLDAP-2.6": [ - "Open LDAP Public License v2.6", - false - ], - "OLDAP-2.7": [ - "Open LDAP Public License v2.7", - false - ], - "OLDAP-2.8": [ - "Open LDAP Public License v2.8", - false - ], - "OML": [ - "Open Market License", - false - ], - "OPL-1.0": [ - "Open Public License v1.0", - false - ], - "OSL-1.0": [ - "Open Software License 1.0", - true - ], - "OSL-1.1": [ - "Open Software License 1.1", - false - ], - "OSL-2.0": [ - "Open Software License 2.0", - true - ], - "OSL-2.1": [ - "Open Software License 2.1", - true - ], - "OSL-3.0": [ - "Open Software License 3.0", - true - ], - "OpenSSL": [ - "OpenSSL License", - false - ], - "PHP-3.0": [ - "PHP License v3.0", - true - ], - "PHP-3.01": [ - "PHP License v3.01", - false - ], - "Plexus": [ - "Plexus Classworlds License", - false - ], - "PostgreSQL": [ - "PostgreSQL License", - true - ], - "psfrag": [ - "psfrag License", - false - ], - "psutils": [ - "psutils License", - false - ], - "Python-2.0": [ - "Python License 2.0", - true - ], - "QPL-1.0": [ - "Q Public License 1.0", - true - ], - "Qhull": [ - "Qhull License", - false - ], - "Rdisc": [ - "Rdisc License", - false - ], - "RPSL-1.0": [ - "RealNetworks Public Source License v1.0", - true - ], - "RPL-1.1": [ - "Reciprocal Public License 1.1", - true - ], - "RPL-1.5": [ - "Reciprocal Public License 1.5", - true - ], - "RHeCos-1.1": [ - "Red Hat eCos Public License v1.1", - false - ], - "RSCPL": [ - "Ricoh Source Code Public License", - true - ], - "Ruby": [ - "Ruby License", - false - ], - "SAX-PD": [ - "Sax Public Domain Notice", - false - ], - "Saxpath": [ - "Saxpath License", - false - ], - "SCEA": [ - "SCEA Shared Source License", - false - ], - "SWL": [ - "Scheme Widget Library (SWL) Software License Agreement", - false - ], - "SGI-B-1.0": [ - "SGI Free Software License B v1.0", - false - ], - "SGI-B-1.1": [ - "SGI Free Software License B v1.1", - false - ], - "SGI-B-2.0": [ - "SGI Free Software License B v2.0", - false - ], - "OFL-1.0": [ - "SIL Open Font License 1.0", - false - ], - "OFL-1.1": [ - "SIL Open Font License 1.1", - true - ], - "SimPL-2.0": [ - "Simple Public License 2.0", - true - ], - "Sleepycat": [ - "Sleepycat License", - true - ], - "SNIA": [ - "SNIA Public License 1.1", - false - ], - "SMLNJ": [ - "Standard ML of New Jersey License", - false - ], - "SugarCRM-1.1.3": [ - "SugarCRM Public License v1.1.3", - false - ], - "SISSL": [ - "Sun Industry Standards Source License v1.1", - true - ], - "SISSL-1.2": [ - "Sun Industry Standards Source License v1.2", - false - ], - "SPL-1.0": [ - "Sun Public License v1.0", - true - ], - "Watcom-1.0": [ - "Sybase Open Watcom Public License 1.0", - true - ], - "TCL": [ - "TCL/TK License", - false - ], - "Unlicense": [ - "The Unlicense", - false - ], - "TMate": [ - "TMate Open Source License", - false - ], - "TORQUE-1.1": [ - "TORQUE v2.5+ Software License v1.1", - false - ], - "TOSL": [ - "Trusster Open Source License", - false - ], - "Unicode-TOU": [ - "Unicode Terms of Use", - false - ], - "NCSA": [ - "University of Illinois/NCSA Open Source License", - true - ], - "Vim": [ - "Vim License", - false - ], - "VOSTROM": [ - "VOSTROM Public License for Open Source", - false - ], - "VSL-1.0": [ - "Vovida Software License v1.0", - true - ], - "W3C": [ - "W3C Software Notice and License (2002-12-31)", - true - ], - "W3C-19980720": [ - "W3C Software Notice and License (1998-07-20)", - false - ], - "Wsuipa": [ - "Wsuipa License", - false - ], - "Xnet": [ - "X.Net License", - true - ], - "X11": [ - "X11 License", - false - ], - "Xerox": [ - "Xerox License", - false - ], - "XFree86-1.1": [ - "XFree86 License 1.1", - false - ], - "xinetd": [ - "xinetd License", - false - ], - "xpp": [ - "XPP License", - false - ], - "XSkat": [ - "XSkat License", - false - ], - "YPL-1.0": [ - "Yahoo! Public License v1.0", - false - ], - "YPL-1.1": [ - "Yahoo! Public License v1.1", - false - ], - "Zed": [ - "Zed License", - false - ], - "Zend-2.0": [ - "Zend License v2.0", - false - ], - "Zimbra-1.3": [ - "Zimbra Public License v1.3", - false - ], - "Zimbra-1.4": [ - "Zimbra Public License v1.4", - false - ], - "Zlib": [ - "zlib License", - true - ], - "zlib-acknowledgement": [ - "zlib/libpng License with Acknowledgement", - false - ], - "ZPL-1.1": [ - "Zope Public License 1.1", - false - ], - "ZPL-2.0": [ - "Zope Public License 2.0", - true - ], - "ZPL-2.1": [ - "Zope Public License 2.1", - false - ], - "ICU": [ - "ICU License", - false - ] -} \ No newline at end of file diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index 6c768bf60..92811f07a 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -28,7 +28,7 @@ use Composer\Repository\CompositeRepository; use Composer\Repository\ComposerRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryInterface; -use Composer\Util\SpdxLicense; +use Composer\Spdx\SpdxLicenses; /** * @author Robert Schönthal @@ -390,12 +390,12 @@ EOT */ protected function printLicenses(CompletePackageInterface $package) { - $spdxLicense = new SpdxLicense; + $spdxLicenses = new SpdxLicenses(); $licenses = $package->getLicense(); foreach ($licenses as $licenseId) { - $license = $spdxLicense->getLicenseByIdentifier($licenseId); // keys: 0 fullname, 1 osi, 2 url + $license = $spdxLicenses->getLicenseByIdentifier($licenseId); // keys: 0 fullname, 1 osi, 2 url if (!$license) { $out = $licenseId; diff --git a/src/Composer/Util/ConfigValidator.php b/src/Composer/Util/ConfigValidator.php index eac5619e7..e99c2e73c 100644 --- a/src/Composer/Util/ConfigValidator.php +++ b/src/Composer/Util/ConfigValidator.php @@ -18,6 +18,7 @@ use Composer\Package\Loader\InvalidPackageException; use Composer\Json\JsonValidationException; use Composer\IO\IOInterface; use Composer\Json\JsonFile; +use Composer\Spdx\SpdxLicenses; /** * Validates a composer configuration. @@ -82,7 +83,7 @@ class ConfigValidator } } - $licenseValidator = new SpdxLicense(); + $licenseValidator = new SpdxLicenses(); if ('proprietary' !== $manifest['license'] && array() !== $manifest['license'] && !$licenseValidator->validate($manifest['license'])) { $warnings[] = sprintf( 'License %s is not a valid SPDX license identifier, see http://www.spdx.org/licenses/ if you use an open license.' diff --git a/src/Composer/Util/SpdxLicense.php b/src/Composer/Util/SpdxLicense.php deleted file mode 100644 index b9ffdc70d..000000000 --- a/src/Composer/Util/SpdxLicense.php +++ /dev/null @@ -1,306 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Util; - -/** - * Supports composer array and SPDX tag notation for disjunctive/conjunctive - * licenses. - * - * @author Tom Klingenberg - */ -class SpdxLicense -{ - /** @var array */ - private $licenses; - - /** @var array */ - private $exceptions; - - public function __construct() - { - $this->loadLicenses(); - $this->loadExceptions(); - } - - /** - * Returns license metadata by license identifier. - * - * @param string $identifier - * - * @return array|null - */ - public function getLicenseByIdentifier($identifier) - { - if (!isset($this->licenses[$identifier])) { - return; - } - - $license = $this->licenses[$identifier]; - $license[] = 'http://spdx.org/licenses/' . $identifier . '.html#licenseText'; - - return $license; - } - - /** - * Returns license exception metadata by license exception identifier. - * - * @param string $identifier - * - * @return array|null - */ - public function getExceptionByIdentifier($identifier) - { - if (!isset($this->exceptions[$identifier])) { - return; - } - - $license = $this->exceptions[$identifier]; - $license[] = 'http://spdx.org/licenses/' . $identifier . '.html#licenseExceptionText'; - - return $license; - } - - /** - * Returns the short identifier of a license (exception) by full name. - * - * @param string $name - * - * @return string - */ - public function getIdentifierByName($name) - { - foreach ($this->licenses as $identifier => $licenseData) { - if ($licenseData[0] === $name) { // key 0 = fullname - return $identifier; - } - } - - foreach ($this->exceptions as $identifier => $licenseData) { - if ($licenseData[0] === $name) { // key 0 = fullname - return $identifier; - } - } - } - - /** - * Returns the OSI Approved status for a license by identifier. - * - * @param string $identifier - * - * @return bool - */ - public function isOsiApprovedByIdentifier($identifier) - { - return $this->licenses[$identifier][1]; // key 1 = osi approved - } - - /** - * Check, if the identifier for a license is valid. - * - * @param string $identifier - * - * @return bool - */ - private function isValidLicenseIdentifier($identifier) - { - $identifiers = array_keys($this->licenses); - - return in_array($identifier, $identifiers); - } - - /** - * Check, if the identifier for a exception is valid. - * - * @param string $identifier - * - * @return bool - */ - private function isValidExceptionIdentifier($identifier) - { - $identifiers = array_keys($this->exceptions); - - return in_array($identifier, $identifiers); - } - - /** - * @param array|string $license - * - * @return bool - * @throws \InvalidArgumentException - */ - public function validate($license) - { - if (is_array($license)) { - $count = count($license); - if ($count !== count(array_filter($license, 'is_string'))) { - throw new \InvalidArgumentException('Array of strings expected.'); - } - $license = $count > 1 ? '('.implode(' OR ', $license).')' : (string) reset($license); - } - - if (!is_string($license)) { - throw new \InvalidArgumentException(sprintf( - 'Array or String expected, %s given.', - gettype($license) - )); - } - - return $this->isValidLicenseString($license); - } - - /** - * @return array - */ - private function loadLicenses() - { - if (is_array($this->licenses)) { - return $this->licenses; - } - - $jsonFile = file_get_contents(__DIR__ . '/../../../res/spdx-licenses.json'); - $this->licenses = json_decode($jsonFile, true); - - return $this->licenses; - } - - /** - * @return array - */ - private function loadExceptions() - { - if (is_array($this->exceptions)) { - return $this->exceptions; - } - - $jsonFile = file_get_contents(__DIR__ . '/../../../res/spdx-exceptions.json'); - $this->exceptions = json_decode($jsonFile, true); - - return $this->exceptions; - } - - /** - * @param string $license - * - * @return bool - * @throws \RuntimeException - */ - private function isValidLicenseString($license) - { - $tokens = array( - 'po' => '\(', - 'pc' => '\)', - 'op' => '(?:or|OR|and|AND)', - 'wi' => '(?:with|WITH)', - 'lix' => '(?:NONE|NOASSERTION)', - 'lir' => 'LicenseRef-\d+', - 'lic' => '[-_.a-zA-Z0-9]{3,}\+?', - 'ws' => '\s+', - '_' => '.', - ); - - $next = function () use ($license, $tokens) { - static $offset = 0; - - if ($offset >= strlen($license)) { - return null; - } - - foreach ($tokens as $name => $token) { - if (false === $r = preg_match('{' . $token . '}', $license, $matches, PREG_OFFSET_CAPTURE, $offset)) { - throw new \RuntimeException('Pattern for token %s failed (regex error).', $name); - } - if ($r === 0) { - continue; - } - if ($matches[0][1] !== $offset) { - continue; - } - $offset += strlen($matches[0][0]); - - return array($name, $matches[0][0]); - } - - throw new \RuntimeException( - 'At least the last pattern needs to match, but it did not (dot-match-all is missing?).' - ); - }; - - $open = 0; - $with = false; - $require = true; - $lastop = null; - - while (list($token, $string) = $next()) { - switch ($token) { - case 'po': - if ($open || !$require || $with) { - return false; - } - $open = 1; - break; - case 'pc': - if ($open !== 1 || $require || !$lastop || $with) { - return false; - } - $open = 2; - break; - case 'op': - if ($require || !$open || $with) { - return false; - } - $lastop || $lastop = $string; - if ($lastop !== $string) { - return false; - } - $require = true; - break; - case 'wi': - $with = true; - break; - case 'lix': - if ($open || $with) { - return false; - } - goto lir; - case 'lic': - if ($with && $this->isValidExceptionIdentifier($string)) { - $require = true; - $with = false; - goto lir; - } - if ($with) { - return false; - } - if (!$this->isValidLicenseIdentifier(rtrim($string, '+'))) { - return false; - } - // Fall-through intended - case 'lir': - lir: - if (!$require) { - return false; - } - $require = false; - break; - case 'ws': - break; - case '_': - return false; - default: - throw new \RuntimeException(sprintf('Unparsed token: %s.', print_r($token, true))); - } - } - - return !($open % 2 || $require || $with); - } -} diff --git a/src/Composer/Util/SpdxLicensesUpdater.php b/src/Composer/Util/SpdxLicensesUpdater.php deleted file mode 100644 index 457f5b389..000000000 --- a/src/Composer/Util/SpdxLicensesUpdater.php +++ /dev/null @@ -1,139 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Util; - -/** - * The SPDX Licenses Updater scrapes licenses from the spdx website - * and updates the "res/spdx-licenses.json" file accordingly. - * - * The class is used by the update script "bin/update-spdx-licenses". - */ -class SpdxLicensesUpdater -{ - /** - * @param string $file - * @param string $url - */ - public function dumpLicenses($file, $url = 'http://www.spdx.org/licenses/') - { - $options = 0; - - if (defined('JSON_PRETTY_PRINT')) { - $options |= JSON_PRETTY_PRINT; - } - - if (defined('JSON_UNESCAPED_SLASHES')) { - $options |= JSON_UNESCAPED_SLASHES; - } - - $licenses = json_encode($this->getLicenses($url), $options); - file_put_contents($file, $licenses); - } - - /** - * @param string $file - * @param string $url - */ - public function dumpExceptions($file, $url = 'http://www.spdx.org/licenses/exceptions-index.html') - { - $options = 0; - - if (defined('JSON_PRETTY_PRINT')) { - $options |= JSON_PRETTY_PRINT; - } - - if (defined('JSON_UNESCAPED_SLASHES')) { - $options |= JSON_UNESCAPED_SLASHES; - } - - $exceptions = json_encode($this->getExceptions($url), $options); - file_put_contents($file, $exceptions); - } - - /** - * @param string $url - * - * @return array - */ - private function getLicenses($url) - { - $licenses = array(); - - $dom = new \DOMDocument; - @$dom->loadHTMLFile($url); - - $xPath = new \DOMXPath($dom); - $trs = $xPath->query('//table//tbody//tr'); - - // iterate over each row in the table - foreach ($trs as $tr) { - $tds = $tr->getElementsByTagName('td'); // get the columns in this row - - if ($tds->length !== 4) { - continue; - } - - if (trim($tds->item(3)->nodeValue) == 'License Text') { - $fullname = trim($tds->item(0)->nodeValue); - $identifier = trim($tds->item(1)->nodeValue); - $osiApproved = ((isset($tds->item(2)->nodeValue) && $tds->item(2)->nodeValue === 'Y')) ? true : false; - - // The license URL is not scraped intentionally to keep json file size low. - // It's build when requested, see SpdxLicense->getLicenseByIdentifier(). - //$licenseURL = $tds->item(3)->getAttribute('href'); - - $licenses += array($identifier => array($fullname, $osiApproved)); - } - } - - return $licenses; - } - - /** - * @param string $url - * - * @return array - */ - private function getExceptions($url) - { - $exceptions = array(); - - $dom = new \DOMDocument; - @$dom->loadHTMLFile($url); - - $xPath = new \DOMXPath($dom); - $trs = $xPath->query('//table//tbody//tr'); - - // iterate over each row in the table - foreach ($trs as $tr) { - $tds = $tr->getElementsByTagName('td'); // get the columns in this row - - if ($tds->length !== 3) { - continue; - } - - if (trim($tds->item(2)->nodeValue) == 'License Exception Text') { - $fullname = trim($tds->item(0)->nodeValue); - $identifier = trim($tds->item(1)->nodeValue); - - // The license URL is not scraped intentionally to keep json file size low. - // It's build when requested, see SpdxLicense->getLicenseExceptionByIdentifier(). - //$licenseURL = $tds->item(2)->getAttribute('href'); - - $exceptions += array($identifier => array($fullname)); - } - } - - return $exceptions; - } -} diff --git a/tests/Composer/Test/Util/SpdxLicenseTest.php b/tests/Composer/Test/Util/SpdxLicenseTest.php deleted file mode 100644 index ef6e7d45d..000000000 --- a/tests/Composer/Test/Util/SpdxLicenseTest.php +++ /dev/null @@ -1,145 +0,0 @@ -license = new SpdxLicense; - } - - public static function provideValidLicenses() - { - $json = file_get_contents(__DIR__ . '/../../../../res/spdx-licenses.json'); - - $licenses = json_decode($json, true); - - $identifiers = array_keys($licenses); - - $valid = array_merge( - array( - "MIT", - "MIT+", - "NONE", - "NOASSERTION", - "LicenseRef-3", - array("LGPL-2.0", "GPL-3.0+"), - "(LGPL-2.0 or GPL-3.0+)", - "(LGPL-2.0 OR GPL-3.0+)", - "(EUDatagrid and GPL-3.0+)", - "(EUDatagrid AND GPL-3.0+)", - "GPL-2.0 with Autoconf-exception-2.0", - "GPL-2.0 WITH Autoconf-exception-2.0", - "GPL-2.0+ WITH Autoconf-exception-2.0", - ), - $identifiers - ); - - foreach ($valid as &$r) { - $r = array($r); - } - - return $valid; - } - - public static function provideInvalidLicenses() - { - return array( - array(""), - array(array()), - array("The system pwns you"), - array("()"), - array("(MIT)"), - array("(MIT"), - array("MIT)"), - array("MIT NONE"), - array("MIT AND NONE"), - array("MIT (MIT and MIT)"), - array("(MIT and MIT) MIT"), - array(array("LGPL-2.0", "The system pwns you")), - array("and GPL-3.0+"), - array("EUDatagrid and GPL-3.0+"), - array("(GPL-3.0 and GPL-2.0 or GPL-3.0+)"), - array("(EUDatagrid and GPL-3.0+ and )"), - array("(EUDatagrid xor GPL-3.0+)"), - array("(MIT Or MIT)"), - array("(NONE or MIT)"), - array("(NOASSERTION or MIT)"), - array("Autoconf-exception-2.0 WITH MIT"), - array("MIT WITH"), - array("MIT OR"), - array("MIT AND"), - ); - } - - public static function provideInvalidArgument() - { - return array( - array(null), - array(new \stdClass), - array(array(new \stdClass)), - array(array("mixed", new \stdClass)), - array(array(new \stdClass, new \stdClass)), - ); - } - - /** - * @dataProvider provideValidLicenses - * @param $license - */ - public function testValidate($license) - { - $this->assertTrue($this->license->validate($license)); - } - - /** - * @dataProvider provideInvalidLicenses - * @param string|array $invalidLicense - */ - public function testInvalidLicenses($invalidLicense) - { - $this->assertFalse($this->license->validate($invalidLicense)); - } - - /** - * @dataProvider provideInvalidArgument - * @expectedException InvalidArgumentException - */ - public function testInvalidArgument($invalidArgument) - { - $this->license->validate($invalidArgument); - } - - public function testGetLicenseByIdentifier() - { - $license = $this->license->getLicenseByIdentifier('AGPL-1.0'); - $this->assertEquals($license[0], 'Affero General Public License v1.0'); // fullname - $this->assertFalse($license[1]); // osi approved - } - - public function testGetIdentifierByName() - { - $identifier = $this->license->getIdentifierByName('Affero General Public License v1.0'); - $this->assertEquals($identifier, 'AGPL-1.0'); - - $identifier = $this->license->getIdentifierByName('BSD 2-clause "Simplified" License'); - $this->assertEquals($identifier, 'BSD-2-Clause'); - } - - public function testIsOsiApprovedByIdentifier() - { - $osiApproved = $this->license->isOsiApprovedByIdentifier('MIT'); - $this->assertTrue($osiApproved); - - $osiApproved = $this->license->isOsiApprovedByIdentifier('AGPL-1.0'); - $this->assertFalse($osiApproved); - } -} From 417516098edb9b3c9d433c9b6527b0f1492362f4 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 16 Jul 2015 11:51:31 +0200 Subject: [PATCH 083/205] Document that lock file name uses COMPOSER env var --- doc/03-cli.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/03-cli.md b/doc/03-cli.md index 57e1d08c5..7864ea904 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -583,6 +583,8 @@ For example: COMPOSER=composer-other.json php composer.phar install ``` +The generated lock file will use the same name: `composer-other.lock` in this example. + ### COMPOSER_ROOT_VERSION By setting this var you can specify the version of the root package, if it can From 1f006a499e51eaa1958047dc6902115f486e45ea Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Thu, 16 Jul 2015 11:48:30 +0200 Subject: [PATCH 084/205] updated compiler class to include spdx sources --- composer.json | 1 + composer.lock | 14 +++++++------- src/Composer/Compiler.php | 4 +++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 74df757f3..d1af27ec2 100644 --- a/composer.json +++ b/composer.json @@ -23,6 +23,7 @@ }, "require": { "php": ">=5.3.2", + "justinrainbow/json-schema": "~1.4", "composer/spdx-licenses": "~1.0", "seld/jsonlint": "~1.0", "symfony/console": "~2.5", diff --git a/composer.lock b/composer.lock index 154102042..b07d76621 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "694654491125336d91b339a8e117bb40", + "hash": "6d311df5df4ca3795787f58b29b03470", "packages": [ { "name": "composer/spdx-licenses", @@ -69,20 +69,20 @@ }, { "name": "justinrainbow/json-schema", - "version": "1.4.1", + "version": "1.4.4", "source": { "type": "git", "url": "https://github.com/justinrainbow/json-schema.git", - "reference": "2465fe486c864e30badaa4d005ebdf89dbc503f3" + "reference": "8dc9b9d85ab639ca60ab4608b34c1279d6ae7bce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/2465fe486c864e30badaa4d005ebdf89dbc503f3", - "reference": "2465fe486c864e30badaa4d005ebdf89dbc503f3", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/8dc9b9d85ab639ca60ab4608b34c1279d6ae7bce", + "reference": "8dc9b9d85ab639ca60ab4608b34c1279d6ae7bce", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.3.2" }, "require-dev": { "json-schema/json-schema-test-suite": "1.1.0", @@ -131,7 +131,7 @@ "json", "schema" ], - "time": "2015-03-27 16:41:39" + "time": "2015-07-14 16:29:50" }, { "name": "seld/cli-prompt", diff --git a/src/Composer/Compiler.php b/src/Composer/Compiler.php index 749adf659..40e767873 100644 --- a/src/Composer/Compiler.php +++ b/src/Composer/Compiler.php @@ -95,7 +95,8 @@ class Compiler $finder = new Finder(); $finder->files() ->name('*.json') - ->in(__DIR__ . '/../../res') + ->in(__DIR__.'/../../res') + ->in(__DIR__.'/../../vendor/composer/spdx-licenses/res/') ->sort($finderSort) ; @@ -116,6 +117,7 @@ class Compiler ->in(__DIR__.'/../../vendor/seld/jsonlint/') ->in(__DIR__.'/../../vendor/seld/cli-prompt/') ->in(__DIR__.'/../../vendor/justinrainbow/json-schema/') + ->in(__DIR__.'/../../vendor/composer/spdx-licenses/') ->sort($finderSort) ; From c014e0882febd05c438afb89b5b21570123eac70 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 16 Jul 2015 09:21:13 +0200 Subject: [PATCH 085/205] ignore this test with 'jsonc' --- tests/Composer/Test/Json/JsonFileTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/Composer/Test/Json/JsonFileTest.php b/tests/Composer/Test/Json/JsonFileTest.php index 279ccd939..867c69307 100644 --- a/tests/Composer/Test/Json/JsonFileTest.php +++ b/tests/Composer/Test/Json/JsonFileTest.php @@ -54,6 +54,9 @@ class JsonFileTest extends \PHPUnit_Framework_TestCase public function testParseErrorDetectSingleQuotes() { + if (defined('JSON_PARSER_NOTSTRICT')) { + $this->markTestSkipped('jsonc issue, see https://github.com/remicollet/pecl-json-c/issues/23'); + } $json = '{ \'foo\': "bar" }'; From 9b9cbfe111b60afb8076d0a22d84107f7f6c642e Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 16 Jul 2015 09:20:36 +0200 Subject: [PATCH 086/205] fix for changes in justinrainbow/json-schema 1.4.4 --- composer.json | 2 +- tests/Composer/Test/Json/ComposerSchemaTest.php | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index d1af27ec2..ae18931d7 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ }, "require": { "php": ">=5.3.2", - "justinrainbow/json-schema": "~1.4", + "justinrainbow/json-schema": "^1.4.4", "composer/spdx-licenses": "~1.0", "seld/jsonlint": "~1.0", "symfony/console": "~2.5", diff --git a/tests/Composer/Test/Json/ComposerSchemaTest.php b/tests/Composer/Test/Json/ComposerSchemaTest.php index 1b8805f48..cf44d4a84 100644 --- a/tests/Composer/Test/Json/ComposerSchemaTest.php +++ b/tests/Composer/Test/Json/ComposerSchemaTest.php @@ -23,18 +23,18 @@ class ComposerSchemaTest extends \PHPUnit_Framework_TestCase { $json = '{ }'; $this->assertEquals(array( - array('property' => '', 'message' => 'the property name is required'), - array('property' => '', 'message' => 'the property description is required'), + array('property' => 'name', 'message' => 'The property name is required'), + array('property' => 'description', 'message' => 'The property description is required'), ), $this->check($json)); $json = '{ "name": "vendor/package" }'; $this->assertEquals(array( - array('property' => '', 'message' => 'the property description is required'), + array('property' => 'description', 'message' => 'The property description is required'), ), $this->check($json)); $json = '{ "description": "generic description" }'; $this->assertEquals(array( - array('property' => '', 'message' => 'the property name is required'), + array('property' => 'name', 'message' => 'The property name is required'), ), $this->check($json)); } @@ -44,7 +44,7 @@ class ComposerSchemaTest extends \PHPUnit_Framework_TestCase $this->assertEquals(array( array( 'property' => 'minimum-stability', - 'message' => 'does not match the regex pattern ^dev|alpha|beta|rc|RC|stable$' + 'message' => 'Does not match the regex pattern ^dev|alpha|beta|rc|RC|stable$' ), ), $this->check($json), 'empty string'); @@ -52,7 +52,7 @@ class ComposerSchemaTest extends \PHPUnit_Framework_TestCase $this->assertEquals(array( array( 'property' => 'minimum-stability', - 'message' => 'does not match the regex pattern ^dev|alpha|beta|rc|RC|stable$' + 'message' => 'Does not match the regex pattern ^dev|alpha|beta|rc|RC|stable$' ), ), $this->check($json), 'dummy'); From bb1e1b016020c2e246ad174a397ccdacb558de0c Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Thu, 16 Jul 2015 12:03:01 +0200 Subject: [PATCH 087/205] update lock file --- composer.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.lock b/composer.lock index b07d76621..42ad0db14 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "6d311df5df4ca3795787f58b29b03470", + "hash": "ed946efe7113827ff28dec6e3679b74b", "packages": [ { "name": "composer/spdx-licenses", From 616585e0cc5ee6cb0991978064e6ab69dfa469a7 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Thu, 16 Jul 2015 13:21:18 +0200 Subject: [PATCH 088/205] spdxlicense extends spdxlicenses, add depr error --- src/Composer/Util/SpdxLicense.php | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/Composer/Util/SpdxLicense.php diff --git a/src/Composer/Util/SpdxLicense.php b/src/Composer/Util/SpdxLicense.php new file mode 100644 index 000000000..18217e105 --- /dev/null +++ b/src/Composer/Util/SpdxLicense.php @@ -0,0 +1,33 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Util; + +use Composer\Spdx\SpdxLicenses; + +/** + * Supports composer array and SPDX tag notation for disjunctive/conjunctive + * licenses. + * + * @author Tom Klingenberg + * + * @deprecated use Composer\Spdx\SpdxLicenses instead + */ +class SpdxLicense extends SpdxLicenses +{ + public function __construct() + { + parent::__construct(); + + trigger_error(__CLASS__ . ' is deprecated, use Composer\\Spdx\\SpdxLicenses instead', E_USER_DEPRECATED); + } +} From ab08e4be62f5e083e19bc23a2104cc747d69265d Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Fri, 17 Jul 2015 08:19:33 +0200 Subject: [PATCH 089/205] update spdx-licenses to 1.1.0 includes latest licenses and exceptions list --- composer.lock | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index 42ad0db14..bbf036d5f 100644 --- a/composer.lock +++ b/composer.lock @@ -8,20 +8,19 @@ "packages": [ { "name": "composer/spdx-licenses", - "version": "1.0.0", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/composer/spdx-licenses.git", - "reference": "abf7dfc7da7d7dc66c147a91b6e927099512292a" + "reference": "2f17228c1b98283b779698cefa917f7f4fd0b0d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/abf7dfc7da7d7dc66c147a91b6e927099512292a", - "reference": "abf7dfc7da7d7dc66c147a91b6e927099512292a", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/2f17228c1b98283b779698cefa917f7f4fd0b0d4", + "reference": "2f17228c1b98283b779698cefa917f7f4fd0b0d4", "shasum": "" }, "require": { - "justinrainbow/json-schema": "~1.4", "php": ">=5.3.2" }, "require-dev": { @@ -65,7 +64,7 @@ "spdx", "validator" ], - "time": "2015-07-15 17:38:14" + "time": "2015-07-17 06:17:03" }, { "name": "justinrainbow/json-schema", From 56f0d82207e5b9cba8fdb8aa0d43118e3fe1cfe4 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Mon, 20 Jul 2015 11:42:20 +0200 Subject: [PATCH 090/205] get resources dir from spdxlicenses --- src/Composer/Compiler.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Composer/Compiler.php b/src/Composer/Compiler.php index 40e767873..b0448502c 100644 --- a/src/Composer/Compiler.php +++ b/src/Composer/Compiler.php @@ -13,6 +13,7 @@ namespace Composer; use Composer\Json\JsonFile; +use Composer\Spdx\SpdxLicenses; use Symfony\Component\Finder\Finder; use Symfony\Component\Process\Process; use Seld\PharUtils\Timestamps; @@ -96,7 +97,7 @@ class Compiler $finder->files() ->name('*.json') ->in(__DIR__.'/../../res') - ->in(__DIR__.'/../../vendor/composer/spdx-licenses/res/') + ->in(SpdxLicenses::getResourcesDir()) ->sort($finderSort) ; From 2553f5f7d43fe55f95c159a85d0b8e35ef1e8d00 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Mon, 20 Jul 2015 12:10:30 +0200 Subject: [PATCH 091/205] throw error when file is loaded --- src/Composer/Util/SpdxLicense.php | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/Composer/Util/SpdxLicense.php b/src/Composer/Util/SpdxLicense.php index 18217e105..8934de679 100644 --- a/src/Composer/Util/SpdxLicense.php +++ b/src/Composer/Util/SpdxLicense.php @@ -14,20 +14,11 @@ namespace Composer\Util; use Composer\Spdx\SpdxLicenses; +@trigger_error('The ' . __NAMESPACE__ . '\SpdxLicense class is deprecated, use Composer\Spdx\SpdxLicenses instead.', E_USER_DEPRECATED); + /** - * Supports composer array and SPDX tag notation for disjunctive/conjunctive - * licenses. - * - * @author Tom Klingenberg - * * @deprecated use Composer\Spdx\SpdxLicenses instead */ class SpdxLicense extends SpdxLicenses { - public function __construct() - { - parent::__construct(); - - trigger_error(__CLASS__ . ' is deprecated, use Composer\\Spdx\\SpdxLicenses instead', E_USER_DEPRECATED); - } } From ff84b32097796106757a088327ff09fad4e18534 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 20 Jul 2015 17:31:45 +0100 Subject: [PATCH 092/205] Add degraded mode to try and bypass ipv6/gzip issues, refs #4142, refs #4121 --- doc/articles/troubleshooting.md | 22 +++++++++ src/Composer/Util/RemoteFilesystem.php | 68 ++++++++++++++++++++------ 2 files changed, 75 insertions(+), 15 deletions(-) diff --git a/doc/articles/troubleshooting.md b/doc/articles/troubleshooting.md index 25279bddb..1d2339b7b 100644 --- a/doc/articles/troubleshooting.md +++ b/doc/articles/troubleshooting.md @@ -168,3 +168,25 @@ To enable the swap you can use for example: /sbin/mkswap /var/swap.1 /sbin/swapon /var/swap.1 ``` + +## Degraded Mode + +Due to some intermittent issues on Travis and other systems, we introduced a +degraded network mode which helps Composer finish successfully but disables +a few optimizations. This is enabled automatically when an issue is first +detected. + +If you have been pointed to this page, you want to check a few things: + +- If you are using ESET antivirus, go in "Advanced Settings" and disable "HTTP-scanner" + under "web access protection" +- If you are using IPv6, try disabling it. If that solves your issues, get in touch + with your ISP or server host, the problem is not at the Packagist level but in the + routing rules between you and Packagist (i.e. the internet at large). The best way to get + these fixed is raise awareness to the network engineers that have the power to fix it. + + To disable IPv6 on Linux, try using this command which appends a + rule prefering IPv4 over IPv6 to your config: + + `sudo sh -c "echo 'precedence ::ffff:0:0/96 100' >> /etc/gai.conf"` +- If none of the above helped, please report the error. diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php index 3acb7e3ac..ce30b83a7 100644 --- a/src/Composer/Util/RemoteFilesystem.php +++ b/src/Composer/Util/RemoteFilesystem.php @@ -37,6 +37,7 @@ class RemoteFilesystem private $retryAuthFailure; private $lastHeaders; private $storeAuth; + private $degradedMode = false; /** * Constructor. @@ -155,6 +156,10 @@ class RemoteFilesystem if (isset($options['http'])) { $options['http']['ignore_errors'] = true; } + if ($this->degradedMode && substr($fileUrl, 0, 21) === 'http://packagist.org/') { + // access packagist using the resolved IPv4 instead of the hostname to force IPv4 protocol + $fileUrl = 'http://' . gethostbyname('packagist.org') . substr($fileUrl, 20); + } $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet'))); if ($this->progress) { @@ -186,6 +191,16 @@ class RemoteFilesystem } restore_error_handler(); if (isset($e) && !$this->retry) { + if (false !== strpos($e->getMessage(), 'Operation timed out')) { + $this->degradedMode = true; + $this->io->writeError(array( + ''.$e->getMessage().'', + 'Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info' + )); + + return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress); + } + throw $e; } @@ -201,36 +216,45 @@ class RemoteFilesystem $result = false; } + if ($this->progress && !$this->retry) { + $this->io->overwriteError(" Downloading: 100%"); + } + // decode gzip if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http') { $decode = false; foreach ($http_response_header as $header) { if (preg_match('{^content-encoding: *gzip *$}i', $header)) { $decode = true; - continue; } elseif (preg_match('{^HTTP/}i', $header)) { $decode = false; } } if ($decode) { - if (PHP_VERSION_ID >= 50400) { - $result = zlib_decode($result); - } else { - // work around issue with gzuncompress & co that do not work with all gzip checksums - $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result)); - } + try { + if (PHP_VERSION_ID >= 50400) { + $result = zlib_decode($result); + } else { + // work around issue with gzuncompress & co that do not work with all gzip checksums + $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result)); + } - if (!$result) { - throw new TransportException('Failed to decode zlib stream'); + if (!$result) { + throw new TransportException('Failed to decode zlib stream'); + } + } catch (\Exception $e) { + $this->degradedMode = true; + $this->io->writeError(array( + 'Failed to decode response: '.$e->getMessage().'', + 'Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info' + )); + + return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress); } } } - if ($this->progress && !$this->retry) { - $this->io->overwriteError(" Downloading: 100%"); - } - // handle copy command if download was successful if (false !== $result && null !== $fileName) { if ('' === $result) { @@ -269,6 +293,16 @@ class RemoteFilesystem $e->setHeaders($http_response_header); } + if (false !== strpos($e->getMessage(), 'Operation timed out')) { + $this->degradedMode = true; + $this->io->writeError(array( + ''.$e->getMessage().'', + 'Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info' + )); + + return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress); + } + throw $e; } @@ -404,8 +438,12 @@ class RemoteFilesystem } $options = array_replace_recursive($this->options, $additionalOptions); - $options['http']['protocol_version'] = 1.1; - $headers[] = 'Connection: close'; + if (!$this->degradedMode) { + // degraded mode disables HTTP/1.1 which causes issues with some bad + // proxies/software due to the use of chunked encoding + $options['http']['protocol_version'] = 1.1; + $headers[] = 'Connection: close'; + } if ($this->io->hasAuthentication($originUrl)) { $auth = $this->io->getAuthentication($originUrl); From bbf959ac34b24291cc699415c7ad2a4eabd5266a Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 20 Jul 2015 17:44:03 +0100 Subject: [PATCH 093/205] Do not retry failures once degraded mode is already enabled --- src/Composer/Util/RemoteFilesystem.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php index ce30b83a7..edcc465c7 100644 --- a/src/Composer/Util/RemoteFilesystem.php +++ b/src/Composer/Util/RemoteFilesystem.php @@ -191,7 +191,7 @@ class RemoteFilesystem } restore_error_handler(); if (isset($e) && !$this->retry) { - if (false !== strpos($e->getMessage(), 'Operation timed out')) { + if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) { $this->degradedMode = true; $this->io->writeError(array( ''.$e->getMessage().'', @@ -244,6 +244,10 @@ class RemoteFilesystem throw new TransportException('Failed to decode zlib stream'); } } catch (\Exception $e) { + if ($this->degradedMode) { + throw $e; + } + $this->degradedMode = true; $this->io->writeError(array( 'Failed to decode response: '.$e->getMessage().'', @@ -293,7 +297,7 @@ class RemoteFilesystem $e->setHeaders($http_response_header); } - if (false !== strpos($e->getMessage(), 'Operation timed out')) { + if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) { $this->degradedMode = true; $this->io->writeError(array( ''.$e->getMessage().'', From dafa9efa8fc3eceff5e14edbae3a088d6eb2bc16 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 20 Jul 2015 17:50:34 +0100 Subject: [PATCH 094/205] Remove whitespace --- doc/articles/troubleshooting.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/articles/troubleshooting.md b/doc/articles/troubleshooting.md index 1d2339b7b..3445b5f8d 100644 --- a/doc/articles/troubleshooting.md +++ b/doc/articles/troubleshooting.md @@ -61,13 +61,13 @@ This is a list of common pitfalls on using Composer, and how to avoid them. ## Package not found in a Jenkins-build 1. Check the ["Package not found"](#package-not-found) item above. -2. Reason for failing is similar to the problem which can occur on travis-ci.org: The - git-clone / checkout within Jenkins leaves the branch in a "detached HEAD"-state. As - a result, Composer is not able to identify the version of the current checked out branch - and may not be able to resolve a cyclic dependency. To solve this problem, you can use - the "Additional Behaviours" -> "Check out to specific local branch" in your Git-settings - for your Jenkins-job, where your "local branch" shall be the same branch as you are - checking out. Using this, the checkout will not be in detached state any more and cyclic +2. Reason for failing is similar to the problem which can occur on travis-ci.org: The + git-clone / checkout within Jenkins leaves the branch in a "detached HEAD"-state. As + a result, Composer is not able to identify the version of the current checked out branch + and may not be able to resolve a cyclic dependency. To solve this problem, you can use + the "Additional Behaviours" -> "Check out to specific local branch" in your Git-settings + for your Jenkins-job, where your "local branch" shall be the same branch as you are + checking out. Using this, the checkout will not be in detached state any more and cyclic dependency is recognized correctly. ## Need to override a package version From b260a9972f97a8dec9f4f5074c7e6afcb2694309 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 20 Jul 2015 17:50:56 +0100 Subject: [PATCH 095/205] Timeouts are not necessarily cause for alarm --- doc/articles/troubleshooting.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/articles/troubleshooting.md b/doc/articles/troubleshooting.md index 3445b5f8d..bc2aeb15f 100644 --- a/doc/articles/troubleshooting.md +++ b/doc/articles/troubleshooting.md @@ -174,7 +174,10 @@ To enable the swap you can use for example: Due to some intermittent issues on Travis and other systems, we introduced a degraded network mode which helps Composer finish successfully but disables a few optimizations. This is enabled automatically when an issue is first -detected. +detected. If you see this issue sporadically you probably don't have to worry +(a slow or overloaded network can also cause those time outs), but if it +appears repeatedly you might want to look at the options below to identify +and resolve it. If you have been pointed to this page, you want to check a few things: From c6cc6dd6070871f4b198ed39f76dd8047c116b02 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 21 Jul 2015 14:46:38 +0100 Subject: [PATCH 096/205] Advise the use of absolute paths, fixes #4259 --- doc/01-basic-usage.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/doc/01-basic-usage.md b/doc/01-basic-usage.md index 8cad96f6c..b33f06ac6 100644 --- a/doc/01-basic-usage.md +++ b/doc/01-basic-usage.md @@ -3,7 +3,7 @@ ## Introduction For our basic usage introduction, we will be installing `monolog/monolog`, -a logging library. If you have not yet installed Composer, refer to the +a logging library. If you have not yet installed Composer, refer to the [Intro](00-intro.md) chapter. > **Note:** for the sake of simplicity, this introduction will assume you @@ -18,7 +18,7 @@ other metadata as well. ### The `require` Key The first (and often only) thing you specify in `composer.json` is the -[`require`](04-schema.md#require) key. You're simply telling Composer which +[`require`](04-schema.md#require) key. You're simply telling Composer which packages your project depends on. ```json @@ -29,8 +29,8 @@ packages your project depends on. } ``` -As you can see, [`require`](04-schema.md#require) takes an object that maps -**package names** (e.g. `monolog/monolog`) to **version constraints** (e.g. +As you can see, [`require`](04-schema.md#require) takes an object that maps +**package names** (e.g. `monolog/monolog`) to **version constraints** (e.g. `1.0.*`). ### Package Names @@ -53,7 +53,7 @@ In the previous example we were requiring version Monolog. This means any version in the `1.0` development branch. It is the equivalent of saying versions that match `>=1.0 <1.1`. -Version constraints can be specified in several ways, read +Version constraints can be specified in several ways, read [versions](articles/versions.md) for more in-depth information on this topic. ### Stability @@ -82,7 +82,7 @@ In case of Monolog it will put it into `vendor/monolog/monolog`. > `vendor` in your `.gitignore`. You really don't want to add all of that > code to your repository. -You will notice the [`install`](03-cli.md#install) command also created a +You will notice the [`install`](03-cli.md#install) command also created a `composer.lock` file. ## `composer.lock` - The Lock File @@ -94,8 +94,8 @@ to those specific versions. **Commit your application's `composer.lock` (along with `composer.json`) into version control.** -This is important because the [`install`](03-cli.md#install) command checks -if a lock file is present, and if it is, it downloads the versions specified +This is important because the [`install`](03-cli.md#install) command checks +if a lock file is present, and if it is, it downloads the versions specified there (regardless of what `composer.json` says). This means that anyone who sets up the project will download the exact same @@ -111,9 +111,9 @@ versions from `composer.json` and create the lock file after executing the [`update`](03-cli.md#update) or the [`install`](03-cli.md#install) command. This means that if any of the dependencies get a new version, you won't get the -updates automatically. To update to the new version, use the -[`update`](03-cli.md#update) command. This will fetch the latest matching -versions (according to your `composer.json` file) and also update the lock file +updates automatically. To update to the new version, use the +[`update`](03-cli.md#update) command. This will fetch the latest matching +versions (according to your `composer.json` file) and also update the lock file with the new version. ```sh @@ -141,8 +141,8 @@ means that you can automatically `require` any package that is available there. If you go to the [Packagist website](https://packagist.org/) (packagist.org), you can browse and search for packages. -Any open source project using Composer is recommended to publish their packages -on Packagist. A library doesn't need to be on Packagist to be used by Composer, +Any open source project using Composer is recommended to publish their packages +on Packagist. A library doesn't need to be on Packagist to be used by Composer, but it enables discovery and adoption by other developers more quickly. ## Autoloading @@ -152,7 +152,7 @@ For libraries that specify autoload information, Composer generates a autoloading for free. ```php -require 'vendor/autoload.php'; +require __DIR__ . '/vendor/autoload.php'; ``` This makes it really easy to use third party code. For example: If your project @@ -165,7 +165,7 @@ $log->pushHandler(new Monolog\Handler\StreamHandler('app.log', Monolog\Logger::W $log->addWarning('Foo'); ``` -You can even add your own code to the autoloader by adding an +You can even add your own code to the autoloader by adding an [`autoload`](04-schema.md#autoload) field to `composer.json`. ```json @@ -183,8 +183,8 @@ You define a mapping from namespaces to directories. The `src` directory would be in your project root, on the same level as `vendor` directory is. An example filename would be `src/Foo.php` containing an `Acme\Foo` class. -After adding the [`autoload`](04-schema.md#autoload) field, you have to re-run -[`dump-autoload`](03-cli.md#dump-autoload) to re-generate the +After adding the [`autoload`](04-schema.md#autoload) field, you have to re-run +[`dump-autoload`](03-cli.md#dump-autoload) to re-generate the `vendor/autoload.php` file. Including that file will also return the autoloader instance, so you can store @@ -192,12 +192,12 @@ the return value of the include call in a variable and add more namespaces. This can be useful for autoloading classes in a test suite, for example. ```php -$loader = require 'vendor/autoload.php'; +$loader = require __DIR__ . '/vendor/autoload.php'; $loader->add('Acme\\Test\\', __DIR__); ``` -In addition to PSR-4 autoloading, Composer also supports PSR-0, classmap and -files autoloading. See the [`autoload`](04-schema.md#autoload) reference for +In addition to PSR-4 autoloading, Composer also supports PSR-0, classmap and +files autoloading. See the [`autoload`](04-schema.md#autoload) reference for more information. > **Note:** Composer provides its own autoloader. If you don't want to use that From 9392adef79bedd1feea7e3053d695850ef5707f1 Mon Sep 17 00:00:00 2001 From: Tehem Date: Tue, 28 Jul 2015 00:01:01 +0200 Subject: [PATCH 097/205] Fixes #4302 allow COMPOSER env with config statements (overrides --file) --- src/Composer/Command/ConfigCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Command/ConfigCommand.php b/src/Composer/Command/ConfigCommand.php index a833a5140..41e9e3766 100644 --- a/src/Composer/Command/ConfigCommand.php +++ b/src/Composer/Command/ConfigCommand.php @@ -139,7 +139,7 @@ EOT // passed in a file to use $configFile = $input->getOption('global') ? ($this->config->get('home') . '/config.json') - : $input->getOption('file'); + : (trim(getenv('COMPOSER')) ? trim(getenv('COMPOSER')) : $input->getOption('file')); // create global composer.json if this was invoked using `composer global config` if ($configFile === 'composer.json' && !file_exists($configFile) && realpath(getcwd()) === realpath($this->config->get('home'))) { From ef37b86c81d8acbf586df147bd1958a6095f2b4d Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Thu, 30 Jul 2015 13:37:12 +0200 Subject: [PATCH 098/205] closes #1508 - updated tests --- .../Test/Mock/ProcessExecutorMock.php | 31 --- .../Package/Loader/RootPackageLoaderTest.php | 223 ++++++++++++------ 2 files changed, 146 insertions(+), 108 deletions(-) delete mode 100644 tests/Composer/Test/Mock/ProcessExecutorMock.php diff --git a/tests/Composer/Test/Mock/ProcessExecutorMock.php b/tests/Composer/Test/Mock/ProcessExecutorMock.php deleted file mode 100644 index 13ea9792b..000000000 --- a/tests/Composer/Test/Mock/ProcessExecutorMock.php +++ /dev/null @@ -1,31 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Test\Mock; - -use Composer\Util\ProcessExecutor; - -class ProcessExecutorMock extends ProcessExecutor -{ - private $execute; - - public function __construct(\Closure $execute) - { - $this->execute = $execute; - } - - public function execute($command, &$output = null, $cwd = null) - { - $execute = $this->execute; - - return $execute($command, $output, $cwd); - } -} diff --git a/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php b/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php index fc3192414..2a4d9ccf6 100644 --- a/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php +++ b/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php @@ -15,7 +15,6 @@ namespace Composer\Test\Package\Loader; use Composer\Config; use Composer\Package\Loader\RootPackageLoader; use Composer\Package\BasePackage; -use Composer\Test\Mock\ProcessExecutorMock; class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase { @@ -29,27 +28,39 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') ->disableOriginalConstructor() - ->getMock(); + ->getMock() + ; - $self = $this; + $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') + ->setMethods(array('execute')) + ->disableArgumentCloning() + ->disableOriginalConstructor() + ->getMock() + ; - /* Can do away with this mock object when https://github.com/sebastianbergmann/phpunit-mock-objects/issues/81 is fixed */ - $processExecutor = new ProcessExecutorMock(function ($command, &$output = null, $cwd = null) use ($self, $commitHash) { - if (0 === strpos($command, 'git describe')) { - // simulate not being on a tag - return 1; - } + $executor + ->expects($this->at(0)) + ->method('execute') + ->with('git describe --exact-match --tags') + ->willReturn(1) + ; - $self->assertStringStartsWith('git branch', $command); + $self = $this; - $output = "* (no branch) $commitHash Commit message\n"; + $executor + ->expects($this->at(1)) + ->method('execute') + ->willReturnCallback(function ($command, &$output) use ($self, $commitHash) { + $self->assertEquals('git branch --no-color --no-abbrev -v', $command); + $output = "* (no branch) $commitHash Commit message\n"; - return 0; - }); + return 0; + }) + ; $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $processExecutor); + $loader = new RootPackageLoader($manager, $config, null, $executor); $package = $loader->load(array()); $this->assertEquals("dev-$commitHash", $package->getVersion()); @@ -63,22 +74,32 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') ->disableOriginalConstructor() - ->getMock(); + ->getMock() + ; - $self = $this; + $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') + ->setMethods(array('execute')) + ->disableArgumentCloning() + ->disableOriginalConstructor() + ->getMock() + ; - /* Can do away with this mock object when https://github.com/sebastianbergmann/phpunit-mock-objects/issues/81 is fixed */ - $processExecutor = new ProcessExecutorMock(function ($command, &$output = null, $cwd = null) use ($self) { - $self->assertEquals('git describe --exact-match --tags', $command); + $self = $this; - $output = "v2.0.5-alpha2"; + $executor + ->expects($this->at(0)) + ->method('execute') + ->willReturnCallback(function ($command, &$output) use ($self) { + $self->assertEquals('git describe --exact-match --tags', $command); + $output = "v2.0.5-alpha2"; - return 0; - }); + return 0; + }) + ; $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $processExecutor); + $loader = new RootPackageLoader($manager, $config, null, $executor); $package = $loader->load(array()); $this->assertEquals("2.0.5.0-alpha2", $package->getVersion()); @@ -92,26 +113,43 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') ->disableOriginalConstructor() - ->getMock(); + ->getMock() + ; + + $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') + ->setMethods(array('execute')) + ->disableArgumentCloning() + ->disableOriginalConstructor() + ->getMock() + ; $self = $this; - /* Can do away with this mock object when https://github.com/sebastianbergmann/phpunit-mock-objects/issues/81 is fixed */ - $processExecutor = new ProcessExecutorMock(function ($command, &$output = null, $cwd = null) use ($self) { - if ('git describe --exact-match --tags' === $command) { + $executor + ->expects($this->at(0)) + ->method('execute') + ->willReturnCallback(function ($command, &$output) use ($self) { + $self->assertEquals('git describe --exact-match --tags', $command); $output = "foo-bar"; return 0; - } + }) + ; - $output = "* foo 03a15d220da53c52eddd5f32ffca64a7b3801bea Commit message\n"; + $executor + ->expects($this->at(1)) + ->method('execute') + ->willReturnCallback(function ($command, &$output) use ($self) { + $self->assertEquals('git branch --no-color --no-abbrev -v', $command); + $output = "* foo 03a15d220da53c52eddd5f32ffca64a7b3801bea Commit message\n"; - return 0; - }); + return 0; + }) + ; $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $processExecutor); + $loader = new RootPackageLoader($manager, $config, null, $executor); $package = $loader->load(array()); $this->assertEquals("dev-foo", $package->getVersion()); @@ -121,21 +159,25 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase { $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') ->disableOriginalConstructor() - ->getMock(); - - $self = $this; + ->getMock() + ; - /* Can do away with this mock object when https://github.com/sebastianbergmann/phpunit-mock-objects/issues/81 is fixed */ - $processExecutor = $this->getMockBuilder('Composer\Util\ProcessExecutor') + $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') + ->setMethods(array('execute')) + ->disableArgumentCloning() ->disableOriginalConstructor() - ->getMock(); - $processExecutor->expects($this->any()) + ->getMock() + ; + + $executor + ->expects($this->any()) ->method('execute') - ->willReturn(null); + ->willReturn(null) + ; $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $processExecutor); + $loader = new RootPackageLoader($manager, $config, null, $executor); $package = $loader->load(array()); $this->assertEquals("1.0.0.0", $package->getVersion()); @@ -148,10 +190,6 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMock(); - $processExecutor = new ProcessExecutorMock(function ($command, &$output = null, $cwd = null) { - return 1; - }); - $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); @@ -188,32 +226,53 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') ->disableOriginalConstructor() - ->getMock(); + ->getMock() + ; + + $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') + ->setMethods(array('execute')) + ->disableArgumentCloning() + ->disableOriginalConstructor() + ->getMock() + ; $self = $this; - /* Can do away with this mock object when https://github.com/sebastianbergmann/phpunit-mock-objects/issues/81 is fixed */ - $processExecutor = new ProcessExecutorMock(function ($command, &$output = null, $cwd = null) use ($self) { - if (0 === strpos($command, 'git rev-list')) { - $output = ""; + $executor + ->expects($this->at(0)) + ->method('execute') + ->willReturnCallback(function ($command) use ($self) { + $self->assertEquals('git describe --exact-match --tags', $command); - return 0; - } + return 1; + }) + ; - if ('git branch --no-color --no-abbrev -v' !== $command) { - return 1; //0; - } + $executor + ->expects($this->at(1)) + ->method('execute') + ->willReturnCallback(function ($command, &$output) use ($self) { + $self->assertEquals('git branch --no-color --no-abbrev -v', $command); + $output = "* latest-production 38137d2f6c70e775e137b2d8a7a7d3eaebf7c7e5 Commit message\n master 4f6ed96b0bc363d2aa4404c3412de1c011f67c66 Commit message\n"; - $self->assertEquals('git branch --no-color --no-abbrev -v', $command); + return 0; + }) + ; - $output = "* latest-production 38137d2f6c70e775e137b2d8a7a7d3eaebf7c7e5 Commit message\n master 4f6ed96b0bc363d2aa4404c3412de1c011f67c66 Commit message\n"; + $executor + ->expects($this->at(2)) + ->method('execute') + ->willReturnCallback(function ($command, &$output) use ($self) { + $self->assertEquals('git rev-list master..latest-production', $command); + $output = ""; - return 0; - }); + return 0; + }) + ; $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $processExecutor); + $loader = new RootPackageLoader($manager, $config, null, $executor); $package = $loader->load(array('require' => array('foo/bar' => 'self.version'))); $this->assertEquals("dev-master", $package->getPrettyVersion()); @@ -227,32 +286,42 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') ->disableOriginalConstructor() - ->getMock(); - - $self = $this; + ->getMock() + ; - /* Can do away with this mock object when https://github.com/sebastianbergmann/phpunit-mock-objects/issues/81 is fixed */ - $processExecutor = new ProcessExecutorMock(function ($command, &$output = null, $cwd = null) use ($self) { - if (0 === strpos($command, 'git rev-list')) { - $output = ""; + $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') + ->setMethods(array('execute')) + ->disableArgumentCloning() + ->disableOriginalConstructor() + ->getMock() + ; - return 0; - } + $self = $this; - if ('git branch --no-color --no-abbrev -v' !== $command) { - return 1; //0; - } + $executor + ->expects($this->at(0)) + ->method('execute') + ->willReturnCallback(function ($command) use ($self) { + $self->assertEquals('git describe --exact-match --tags', $command); - $self->assertEquals('git branch --no-color --no-abbrev -v', $command); + return 1; + }) + ; - $output = "* latest-production 38137d2f6c70e775e137b2d8a7a7d3eaebf7c7e5 Commit message\n master 4f6ed96b0bc363d2aa4404c3412de1c011f67c66 Commit message\n"; + $executor + ->expects($this->at(1)) + ->method('execute') + ->willReturnCallback(function ($command, &$output) use ($self) { + $self->assertEquals('git branch --no-color --no-abbrev -v', $command); + $output = "* latest-production 38137d2f6c70e775e137b2d8a7a7d3eaebf7c7e5 Commit message\n master 4f6ed96b0bc363d2aa4404c3412de1c011f67c66 Commit message\n"; - return 0; - }); + return 0; + }) + ; $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $processExecutor); + $loader = new RootPackageLoader($manager, $config, null, $executor); $package = $loader->load(array('require' => array('foo/bar' => 'self.version'), "non-feature-branches" => array("latest-.*"))); $this->assertEquals("dev-latest-production", $package->getPrettyVersion()); From 77f1d5945f8ac6e907ac2c092cfced158db16e49 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Fri, 31 Jul 2015 09:57:07 +0200 Subject: [PATCH 099/205] make sure php version errors are less misleading * determine conflicting version in problem using pool package * hide version in rule to keep it generic rather than possibly misleading fixes #4319 --- src/Composer/DependencyResolver/Problem.php | 6 +++++- src/Composer/DependencyResolver/Rule.php | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Composer/DependencyResolver/Problem.php b/src/Composer/DependencyResolver/Problem.php index 7fcb636b0..5d2117f2c 100644 --- a/src/Composer/DependencyResolver/Problem.php +++ b/src/Composer/DependencyResolver/Problem.php @@ -87,8 +87,12 @@ class Problem } if ($job && $job['cmd'] === 'install' && empty($packages)) { + // handle php/hhvm if ($job['packageName'] === 'php' || $job['packageName'] === 'php-64bit' || $job['packageName'] === 'hhvm') { + $available = $this->pool->whatProvides($job['packageName']); + $version = count($available) ? $available[0]->getPrettyVersion() : phpversion(); + $msg = "\n - This package requires ".$job['packageName'].$this->constraintToText($job['constraint']).' but '; if (defined('HHVM_VERSION')) { @@ -97,7 +101,7 @@ class Problem return $msg . 'you are running this with PHP and not HHVM.'; } - return $msg . 'your PHP version ('. phpversion().') does not satisfy that requirement.'; + return $msg . 'your PHP version ('. $version .') does not satisfy that requirement.'; } // handle php extensions diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index 5d95d678a..8f23b6a94 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -199,16 +199,17 @@ class Rule } else { $targetName = $this->reasonData->getTarget(); - // handle php extensions if ($targetName === 'php' || $targetName === 'php-64bit' || $targetName === 'hhvm') { + // handle php/hhvm if (defined('HHVM_VERSION')) { $text .= ' -> your HHVM version does not satisfy that requirement.'; } elseif ($targetName === 'hhvm') { $text .= ' -> you are running this with PHP and not HHVM.'; } else { - $text .= ' -> your PHP version ('. phpversion().') does not satisfy that requirement.'; + $text .= ' -> your PHP version does not satisfy that requirement.'; } } elseif (0 === strpos($targetName, 'ext-')) { + // handle php extensions $ext = substr($targetName, 4); $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system'; From 51ef7b5eef395a2f020df888e9c1d463f4f861a7 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Fri, 31 Jul 2015 10:01:58 +0200 Subject: [PATCH 100/205] instead of generic be more verbose about possible causes --- src/Composer/DependencyResolver/Rule.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index 8f23b6a94..916addead 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -206,7 +206,7 @@ class Rule } elseif ($targetName === 'hhvm') { $text .= ' -> you are running this with PHP and not HHVM.'; } else { - $text .= ' -> your PHP version does not satisfy that requirement.'; + $text .= ' -> your PHP version ('. phpversion() .') or "config.platform.php" value does not satisfy that requirement.'; } } elseif (0 === strpos($targetName, 'ext-')) { // handle php extensions From b35e7623549c2ef2dae65fc6d49b887722a9615e Mon Sep 17 00:00:00 2001 From: Thomas Marcon Date: Fri, 31 Jul 2015 12:00:00 +0200 Subject: [PATCH 101/205] Updated configFile parsing to first look into -f parameter, then COMPOSER environment variable, then default to composer.json --- src/Composer/Command/ConfigCommand.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Composer/Command/ConfigCommand.php b/src/Composer/Command/ConfigCommand.php index 41e9e3766..f792f84bd 100644 --- a/src/Composer/Command/ConfigCommand.php +++ b/src/Composer/Command/ConfigCommand.php @@ -66,7 +66,7 @@ class ConfigCommand extends Command new InputOption('auth', 'a', InputOption::VALUE_NONE, 'Affect auth config file (only used for --editor)'), new InputOption('unset', null, InputOption::VALUE_NONE, 'Unset the given setting-key'), new InputOption('list', 'l', InputOption::VALUE_NONE, 'List configuration settings'), - new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json', 'composer.json'), + new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json'), new InputOption('absolute', null, InputOption::VALUE_NONE, 'Returns absolute paths when fetching *-dir config values instead of relative'), new InputArgument('setting-key', null, 'Setting key'), new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value'), @@ -138,8 +138,12 @@ EOT // Get the local composer.json, global config.json, or if the user // passed in a file to use $configFile = $input->getOption('global') - ? ($this->config->get('home') . '/config.json') - : (trim(getenv('COMPOSER')) ? trim(getenv('COMPOSER')) : $input->getOption('file')); + ? ($this->config->get('home').'/config.json') + : ( + $input->getOption('file') + ? $input->getOption('file') + : (trim(getenv('COMPOSER')) ? trim(getenv('COMPOSER')) : 'composer.json') + ); // create global composer.json if this was invoked using `composer global config` if ($configFile === 'composer.json' && !file_exists($configFile) && realpath(getcwd()) === realpath($this->config->get('home'))) { From 767279b41ac88a72d138e27b7088f0bc21b42976 Mon Sep 17 00:00:00 2001 From: Malte Wunsch Date: Mon, 3 Aug 2015 18:28:04 +0200 Subject: [PATCH 102/205] getCanonicalPackages returns packages with same name in different versions --- src/Composer/Repository/ArrayRepository.php | 1 + .../Repository/WritableArrayRepository.php | 7 +++-- .../WritableArrayRepositoryTest.php | 29 +++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 tests/Composer/Test/Repository/WritableArrayRepositoryTest.php diff --git a/src/Composer/Repository/ArrayRepository.php b/src/Composer/Repository/ArrayRepository.php index 4f6e2daa7..a5023c1fe 100644 --- a/src/Composer/Repository/ArrayRepository.php +++ b/src/Composer/Repository/ArrayRepository.php @@ -26,6 +26,7 @@ use Composer\Package\LinkConstraint\VersionConstraint; */ class ArrayRepository implements RepositoryInterface { + /** @var PackageInterface[] */ protected $packages; public function __construct(array $packages = array()) diff --git a/src/Composer/Repository/WritableArrayRepository.php b/src/Composer/Repository/WritableArrayRepository.php index 756f24137..6b47e7e47 100644 --- a/src/Composer/Repository/WritableArrayRepository.php +++ b/src/Composer/Repository/WritableArrayRepository.php @@ -42,11 +42,12 @@ class WritableArrayRepository extends ArrayRepository implements WritableReposit { $packages = $this->getPackages(); - // get at most one package of each name, prefering non-aliased ones + // get at most one package of each (name, version) combination, prefering non-aliased ones $packagesByName = array(); foreach ($packages as $package) { - if (!isset($packagesByName[$package->getName()]) || $packagesByName[$package->getName()] instanceof AliasPackage) { - $packagesByName[$package->getName()] = $package; + $index = $package->getName() . $package->getVersion(); + if (!isset($packagesByName[$index]) || $packagesByName[$index] instanceof AliasPackage) { + $packagesByName[$index] = $package; } } diff --git a/tests/Composer/Test/Repository/WritableArrayRepositoryTest.php b/tests/Composer/Test/Repository/WritableArrayRepositoryTest.php new file mode 100644 index 000000000..e4cb36ccc --- /dev/null +++ b/tests/Composer/Test/Repository/WritableArrayRepositoryTest.php @@ -0,0 +1,29 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Test\Repository; + +use Composer\Repository\WritableArrayRepository; +use Composer\TestCase; + +final class WritableArrayRepositoryTest extends TestCase +{ + public function testGetCanonicalPackagesReturnsDifferentVersionsOfSameNamedPackage() + { + $repository = new WritableArrayRepository(); + + $repository->addPackage($this->getPackage('foo', 1)); + $repository->addPackage($this->getPackage('foo', 2)); + + $this->assertCount(2, $repository->getCanonicalPackages()); + } +} From 9e592f19a1298f46b7222005634064c2e42a250b Mon Sep 17 00:00:00 2001 From: Tehem Date: Mon, 3 Aug 2015 23:36:05 +0200 Subject: [PATCH 103/205] Used shorthand version for ternary operator --- src/Composer/Command/ConfigCommand.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Composer/Command/ConfigCommand.php b/src/Composer/Command/ConfigCommand.php index f792f84bd..96c431655 100644 --- a/src/Composer/Command/ConfigCommand.php +++ b/src/Composer/Command/ConfigCommand.php @@ -138,12 +138,8 @@ EOT // Get the local composer.json, global config.json, or if the user // passed in a file to use $configFile = $input->getOption('global') - ? ($this->config->get('home').'/config.json') - : ( - $input->getOption('file') - ? $input->getOption('file') - : (trim(getenv('COMPOSER')) ? trim(getenv('COMPOSER')) : 'composer.json') - ); + ? ($this->config->get('home') . '/config.json') + : ($input->getOption('file') ?: (trim(getenv('COMPOSER')) ? trim(getenv('COMPOSER')) : 'composer.json')); // create global composer.json if this was invoked using `composer global config` if ($configFile === 'composer.json' && !file_exists($configFile) && realpath(getcwd()) === realpath($this->config->get('home'))) { From 70ff00c9de4c7bd52c7078f5d53f1bfd4a1f6a9d Mon Sep 17 00:00:00 2001 From: Malte Wunsch Date: Tue, 4 Aug 2015 09:32:23 +0200 Subject: [PATCH 104/205] Reverted inadvertent API change, improved API documentation --- .../Repository/WritableArrayRepository.php | 7 ++--- .../WritableRepositoryInterface.php | 4 +-- .../WritableArrayRepositoryTest.php | 29 ------------------- 3 files changed, 5 insertions(+), 35 deletions(-) delete mode 100644 tests/Composer/Test/Repository/WritableArrayRepositoryTest.php diff --git a/src/Composer/Repository/WritableArrayRepository.php b/src/Composer/Repository/WritableArrayRepository.php index 6b47e7e47..041e40562 100644 --- a/src/Composer/Repository/WritableArrayRepository.php +++ b/src/Composer/Repository/WritableArrayRepository.php @@ -42,12 +42,11 @@ class WritableArrayRepository extends ArrayRepository implements WritableReposit { $packages = $this->getPackages(); - // get at most one package of each (name, version) combination, prefering non-aliased ones + // get at most one package of each name, preferring non-aliased ones $packagesByName = array(); foreach ($packages as $package) { - $index = $package->getName() . $package->getVersion(); - if (!isset($packagesByName[$index]) || $packagesByName[$index] instanceof AliasPackage) { - $packagesByName[$index] = $package; + if (!isset($packagesByName[$package->getName()]) || $packagesByName[$package->getName()] instanceof AliasPackage) { + $packagesByName[$package->getName()] = $package; } } diff --git a/src/Composer/Repository/WritableRepositoryInterface.php b/src/Composer/Repository/WritableRepositoryInterface.php index c046c377c..4500005d9 100644 --- a/src/Composer/Repository/WritableRepositoryInterface.php +++ b/src/Composer/Repository/WritableRepositoryInterface.php @@ -41,14 +41,14 @@ interface WritableRepositoryInterface extends RepositoryInterface public function removePackage(PackageInterface $package); /** - * Get unique packages, with aliases resolved and removed + * Get unique packages (at most one package of each name), with aliases resolved and removed. * * @return PackageInterface[] */ public function getCanonicalPackages(); /** - * Forces a reload of all packages + * Forces a reload of all packages. */ public function reload(); } diff --git a/tests/Composer/Test/Repository/WritableArrayRepositoryTest.php b/tests/Composer/Test/Repository/WritableArrayRepositoryTest.php deleted file mode 100644 index e4cb36ccc..000000000 --- a/tests/Composer/Test/Repository/WritableArrayRepositoryTest.php +++ /dev/null @@ -1,29 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Test\Repository; - -use Composer\Repository\WritableArrayRepository; -use Composer\TestCase; - -final class WritableArrayRepositoryTest extends TestCase -{ - public function testGetCanonicalPackagesReturnsDifferentVersionsOfSameNamedPackage() - { - $repository = new WritableArrayRepository(); - - $repository->addPackage($this->getPackage('foo', 1)); - $repository->addPackage($this->getPackage('foo', 2)); - - $this->assertCount(2, $repository->getCanonicalPackages()); - } -} From fbae6b1589ef28b77f0c38d1c9d4b964fb4d45bc Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 4 Aug 2015 10:34:54 +0200 Subject: [PATCH 105/205] Revert "Merge pull request #3975 from marc-mabe/hotfix/3974" This reverts commit bdb6ecb29e9624fb767aa690d09c780249050fc6, reversing changes made to 8a12e50a16dbc4ddf808b752ad64b412dba272d5. --- src/Composer/Autoload/ClassLoader.php | 8 ++++---- tests/Composer/Test/Autoload/ClassLoaderTest.php | 11 ----------- .../Composer/Test/Autoload/Fixtures/DirDotPhp/Dir.php | 6 ------ .../Autoload/Fixtures/DirDotPhp/psr4/Dir.php/File.php | 6 ------ 4 files changed, 4 insertions(+), 27 deletions(-) delete mode 100644 tests/Composer/Test/Autoload/Fixtures/DirDotPhp/Dir.php delete mode 100644 tests/Composer/Test/Autoload/Fixtures/DirDotPhp/psr4/Dir.php/File.php diff --git a/src/Composer/Autoload/ClassLoader.php b/src/Composer/Autoload/ClassLoader.php index 4e05d3b15..5e1469e83 100644 --- a/src/Composer/Autoload/ClassLoader.php +++ b/src/Composer/Autoload/ClassLoader.php @@ -351,7 +351,7 @@ class ClassLoader foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { if (0 === strpos($class, $prefix)) { foreach ($this->prefixDirsPsr4[$prefix] as $dir) { - if (is_file($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { return $file; } } @@ -361,7 +361,7 @@ class ClassLoader // PSR-4 fallback dirs foreach ($this->fallbackDirsPsr4 as $dir) { - if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { return $file; } } @@ -380,7 +380,7 @@ class ClassLoader foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { if (0 === strpos($class, $prefix)) { foreach ($dirs as $dir) { - if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { return $file; } } @@ -390,7 +390,7 @@ class ClassLoader // PSR-0 fallback dirs foreach ($this->fallbackDirsPsr0 as $dir) { - if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { return $file; } } diff --git a/tests/Composer/Test/Autoload/ClassLoaderTest.php b/tests/Composer/Test/Autoload/ClassLoaderTest.php index ec4156a15..50772101e 100644 --- a/tests/Composer/Test/Autoload/ClassLoaderTest.php +++ b/tests/Composer/Test/Autoload/ClassLoaderTest.php @@ -9,17 +9,6 @@ use Composer\Autoload\ClassLoader; */ class ClassLoaderTest extends \PHPUnit_Framework_TestCase { - public function testLoadClassDotPhp() - { - $loader = new ClassLoader(); - $loader->add('DirDotPhp\\', __DIR__ . '/Fixtures'); - $loader->addPsr4('DirDotPhp\\', __DIR__ . '/Fixtures/DirDotPhp/psr4'); - - $class = 'DirDotPhp\\Dir'; - $loader->loadClass($class); - $this->assertTrue(class_exists($class, false), "->loadClass() loads '$class'."); - } - /** * Tests regular PSR-0 and PSR-4 class loading. * diff --git a/tests/Composer/Test/Autoload/Fixtures/DirDotPhp/Dir.php b/tests/Composer/Test/Autoload/Fixtures/DirDotPhp/Dir.php deleted file mode 100644 index 9d9d62d8c..000000000 --- a/tests/Composer/Test/Autoload/Fixtures/DirDotPhp/Dir.php +++ /dev/null @@ -1,6 +0,0 @@ - Date: Tue, 4 Aug 2015 16:54:43 -0400 Subject: [PATCH 106/205] Clarified instructions --- doc/05-repositories.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/05-repositories.md b/doc/05-repositories.md index ffa29ede8..0a12da4cc 100644 --- a/doc/05-repositories.md +++ b/doc/05-repositories.md @@ -263,6 +263,8 @@ custom repository has priority over packagist. If you want to rename the package, you should do so in the default (often master) branch and not in a feature branch, since the package name is taken from the default branch. +Also note that the override will not work if you change the `name` property in your forked repository's composer.json file as this needs to match the original for the override to work. + If other dependencies rely on the package you forked, it is possible to inline-alias it so that it matches a constraint that it otherwise would not. For more information [see the aliases article](articles/aliases.md). From 976491d86584b5fb2c8140dce3370aa8c2f09de6 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 9 Aug 2015 15:09:34 +0100 Subject: [PATCH 107/205] Rewrap markdown, refs #4329 --- doc/05-repositories.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/05-repositories.md b/doc/05-repositories.md index 0a12da4cc..1df20828a 100644 --- a/doc/05-repositories.md +++ b/doc/05-repositories.md @@ -263,7 +263,9 @@ custom repository has priority over packagist. If you want to rename the package, you should do so in the default (often master) branch and not in a feature branch, since the package name is taken from the default branch. -Also note that the override will not work if you change the `name` property in your forked repository's composer.json file as this needs to match the original for the override to work. +Also note that the override will not work if you change the `name` property +in your forked repository's composer.json file as this needs to match the +original for the override to work. If other dependencies rely on the package you forked, it is possible to inline-alias it so that it matches a constraint that it otherwise would not. From d02ab54be1b988dddbc338f0938789908b881ed3 Mon Sep 17 00:00:00 2001 From: iamluc Date: Sun, 9 Aug 2015 17:27:05 +0200 Subject: [PATCH 108/205] Add a new option to view local modifications (git diff) --- src/Composer/Downloader/GitDownloader.php | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index f187ec9a7..82552c009 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -81,7 +81,7 @@ class GitDownloader extends VcsDownloader $command = 'git remote set-url composer %s && git fetch composer && git fetch --tags composer'; $commandCallable = function ($url) use ($command) { - return sprintf($command, ProcessExecutor::escape ($url)); + return sprintf($command, ProcessExecutor::escape($url)); }; $this->gitUtil->runCommand($commandCallable, $url, $path); @@ -149,7 +149,7 @@ class GitDownloader extends VcsDownloader } while (true) { - switch ($this->io->ask(' Discard changes [y,n,v,'.($update ? 's,' : '').'?]? ', '?')) { + switch ($this->io->ask(' Discard changes [y,n,v,d,'.($update ? 's,' : '').'?]? ', '?')) { case 'y': $this->discardChanges($path); break 2; @@ -169,6 +169,10 @@ class GitDownloader extends VcsDownloader $this->io->writeError($changes); break; + case 'd': + $this->viewDiff($path); + break; + case '?': default: help: @@ -176,6 +180,7 @@ class GitDownloader extends VcsDownloader ' y - discard changes and apply the '.($update ? 'update' : 'uninstall'), ' n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up', ' v - view modified files', + ' d - view local modifications (diff)', )); if ($update) { $this->io->writeError(' s - stash changes and try to reapply them after the update'); @@ -326,6 +331,20 @@ class GitDownloader extends VcsDownloader $this->hasStashedChanges = true; } + /** + * @param $path + * @throws \RuntimeException + */ + protected function viewDiff($path) + { + $path = $this->normalizePath($path); + if (0 !== $this->process->execute('git diff HEAD', $output, $path)) { + throw new \RuntimeException("Could not view diff\n\n:".$this->process->getErrorOutput()); + } + + $this->io->writeError($output); + } + protected function normalizePath($path) { if (defined('PHP_WINDOWS_VERSION_MAJOR') && strlen($path) > 0) { From b16c5fbeb928f488beec012186be09a12d37818d Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 10 Aug 2015 00:56:55 +0100 Subject: [PATCH 109/205] Shorten ternary and reuse config file instead of the null argument to figure out path to auth.json --- src/Composer/Command/ConfigCommand.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Composer/Command/ConfigCommand.php b/src/Composer/Command/ConfigCommand.php index 96c431655..d572f020c 100644 --- a/src/Composer/Command/ConfigCommand.php +++ b/src/Composer/Command/ConfigCommand.php @@ -139,7 +139,7 @@ EOT // passed in a file to use $configFile = $input->getOption('global') ? ($this->config->get('home') . '/config.json') - : ($input->getOption('file') ?: (trim(getenv('COMPOSER')) ? trim(getenv('COMPOSER')) : 'composer.json')); + : ($input->getOption('file') ?: trim(getenv('COMPOSER')) ?: 'composer.jsonw'); // create global composer.json if this was invoked using `composer global config` if ($configFile === 'composer.json' && !file_exists($configFile) && realpath(getcwd()) === realpath($this->config->get('home'))) { @@ -151,7 +151,7 @@ EOT $authConfigFile = $input->getOption('global') ? ($this->config->get('home') . '/auth.json') - : dirname(realpath($input->getOption('file'))) . '/auth.json'; + : dirname(realpath($configFile)) . '/auth.json'; $this->authConfigFile = new JsonFile($authConfigFile); $this->authConfigSource = new JsonConfigSource($this->authConfigFile, true); From 33badac0a85c950fb6c1d30bf2114d0ad35f4c3d Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 10 Aug 2015 00:57:13 +0100 Subject: [PATCH 110/205] Include full error message in debug mode --- src/Composer/Downloader/ArchiveDownloader.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Composer/Downloader/ArchiveDownloader.php b/src/Composer/Downloader/ArchiveDownloader.php index 4f41285c8..f42b82872 100644 --- a/src/Composer/Downloader/ArchiveDownloader.php +++ b/src/Composer/Downloader/ArchiveDownloader.php @@ -77,7 +77,11 @@ abstract class ArchiveDownloader extends FileDownloader // retry downloading if we have an invalid zip file if ($retries && $e instanceof \UnexpectedValueException && class_exists('ZipArchive') && $e->getCode() === \ZipArchive::ER_NOZIP) { - $this->io->writeError(' Invalid zip file, retrying...'); + if ($this->io->isDebug()) { + $this->io->writeError(' Invalid zip file ('.$e->getMessage().'), retrying...'); + } else { + $this->io->writeError(' Invalid zip file, retrying...'); + } usleep(500000); continue; } From 4824b4504eee9971a8e2e2015bf3d3d7c04fbb3d Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 10 Aug 2015 01:05:32 +0100 Subject: [PATCH 111/205] Remove typo --- src/Composer/Command/ConfigCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Command/ConfigCommand.php b/src/Composer/Command/ConfigCommand.php index d572f020c..5feb9f1cb 100644 --- a/src/Composer/Command/ConfigCommand.php +++ b/src/Composer/Command/ConfigCommand.php @@ -139,7 +139,7 @@ EOT // passed in a file to use $configFile = $input->getOption('global') ? ($this->config->get('home') . '/config.json') - : ($input->getOption('file') ?: trim(getenv('COMPOSER')) ?: 'composer.jsonw'); + : ($input->getOption('file') ?: trim(getenv('COMPOSER')) ?: 'composer.json'); // create global composer.json if this was invoked using `composer global config` if ($configFile === 'composer.json' && !file_exists($configFile) && realpath(getcwd()) === realpath($this->config->get('home'))) { From 65bb8d99f44c053684b3b59c98fd1f75a3128241 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 10 Aug 2015 08:34:33 +0100 Subject: [PATCH 112/205] Fix global switch regression on config command, fixes #4344 --- src/Composer/Command/ConfigCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Command/ConfigCommand.php b/src/Composer/Command/ConfigCommand.php index 5feb9f1cb..6c12a7a72 100644 --- a/src/Composer/Command/ConfigCommand.php +++ b/src/Composer/Command/ConfigCommand.php @@ -129,7 +129,7 @@ EOT { parent::initialize($input, $output); - if ($input->getOption('global') && 'composer.json' !== $input->getOption('file')) { + if ($input->getOption('global') && null !== $input->getOption('file')) { throw new \RuntimeException('--file and --global can not be combined'); } From 812523f1abc5fdcbaa09110482d9f5709efaf968 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 10 Aug 2015 10:07:48 +0100 Subject: [PATCH 113/205] Add more debug info on cache write failure, refs #4249 --- src/Composer/Cache.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Composer/Cache.php b/src/Composer/Cache.php index e49edf649..746a31aec 100644 --- a/src/Composer/Cache.php +++ b/src/Composer/Cache.php @@ -86,6 +86,9 @@ class Cache try { return file_put_contents($this->root . $file, $contents); } catch (\ErrorException $e) { + if ($this->io->isDebug()) { + $this->io->writeError('Failed to write into cache: '.$e->getMessage().''); + } if (preg_match('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) { // Remove partial file. unlink($this->root . $file); From 0457ec6fb3426234e2c968b87bdc69fa29448904 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 10 Aug 2015 12:42:51 +0100 Subject: [PATCH 114/205] Remove deadcode, fixes #4345, fixes #4268 --- src/Composer/Repository/CompositeRepository.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/Composer/Repository/CompositeRepository.php b/src/Composer/Repository/CompositeRepository.php index d05259f88..7f29385bf 100644 --- a/src/Composer/Repository/CompositeRepository.php +++ b/src/Composer/Repository/CompositeRepository.php @@ -108,20 +108,6 @@ class CompositeRepository implements RepositoryInterface return $matches ? call_user_func_array('array_merge', $matches) : array(); } - /** - * {@inheritDoc} - */ - public function filterPackages($callback, $class = 'Composer\Package\Package') - { - foreach ($this->repositories as $repository) { - if (false === $repository->filterPackages($callback, $class)) { - return false; - } - } - - return true; - } - /** * {@inheritdoc} */ From cedbe7f1a0c85a998e3d3e707e53de0781820087 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 10 Aug 2015 12:58:58 +0100 Subject: [PATCH 115/205] Bump vcs verbosity output to very verbose, refs #4330 --- src/Composer/Repository/VcsRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/VcsRepository.php b/src/Composer/Repository/VcsRepository.php index 034260d0c..bb9d76814 100644 --- a/src/Composer/Repository/VcsRepository.php +++ b/src/Composer/Repository/VcsRepository.php @@ -55,7 +55,7 @@ class VcsRepository extends ArrayRepository $this->url = $repoConfig['url']; $this->io = $io; $this->type = isset($repoConfig['type']) ? $repoConfig['type'] : 'vcs'; - $this->verbose = $io->isVerbose(); + $this->verbose = $io->isVeryVerbose(); $this->config = $config; $this->repoConfig = $repoConfig; } From df10a80501472b6414ad8cbc3215956a8b677d86 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 11 Aug 2015 08:37:24 +0200 Subject: [PATCH 116/205] updated code of conduct and minor addition in contrib --- CONTRIBUTING.md | 8 +++++--- README.md | 3 +-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b5a69bd00..6c3be2943 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ Contributing to Composer ======================== Please note that this project is released with a -[Contributor Code of Conduct](http://contributor-covenant.org/version/1/1/0/). +[Contributor Code of Conduct](http://contributor-covenant.org/version/1/2/0/). By participating in this project you agree to abide by its terms. Reporting Issues @@ -42,6 +42,8 @@ Contributing policy Fork the project, create a feature branch, and send us a pull request. To ensure a consistent code base, you should make sure the code follows -the [PSR-2 Coding Standards](http://www.php-fig.org/psr/psr-2/). +the [PSR-2 Coding Standards](http://www.php-fig.org/psr/psr-2/). You can also +run [php-cs-fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer) with the +configuration file that can be found in the project root directory. -If you would like to help, take a look at the [list of issues](https://github.com/composer/composer/issues). +If you would like to help, take a look at the [list of open issues](https://github.com/composer/composer/issues). diff --git a/README.md b/README.md index 13795e3a4..ccbfdcd34 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,6 @@ Updating Composer Running `php composer.phar self-update` or equivalent will update a phar install to the latest version. - Community --------- @@ -56,7 +55,7 @@ For support, Stack Overflow also offers a good collection of [Composer related questions](https://stackoverflow.com/questions/tagged/composer-php). Please note that this project is released with a -[Contributor Code of Conduct](http://contributor-covenant.org/version/1/1/0/). +[Contributor Code of Conduct](http://contributor-covenant.org/version/1/2/0/). By participating in this project and its community you agree to abide by those terms. Requirements From a979cc78ed141855a76b7f196d24205c41107bbc Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 11 Aug 2015 11:20:15 +0100 Subject: [PATCH 117/205] Suppress warnings on touch() failures of the vendor dir, refs #4070 --- src/Composer/Installer.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 1b329c2bb..a3eb66301 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -344,7 +344,9 @@ class Installer $vendorDir = $this->config->get('vendor-dir'); if (is_dir($vendorDir)) { - touch($vendorDir); + // suppress errors as this fails sometimes on OSX for no apparent reason + // see https://github.com/composer/composer/issues/4070#issuecomment-129792748 + @touch($vendorDir); } } From 593af4b1bfaeaa512b4c09f929186bb2c7533cfc Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Fri, 14 Aug 2015 12:00:21 +0200 Subject: [PATCH 118/205] add license file during autoload dumping closes #4288 --- src/Composer/Autoload/AutoloadGenerator.php | 26 ++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index e8de9cd3f..4a55a53c0 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -261,14 +261,8 @@ EOF; file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix)); file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFile, $targetDirLoader, (bool) $includeFilesFile, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $classMapAuthoritative)); - // use stream_copy_to_stream instead of copy - // to work around https://bugs.php.net/bug.php?id=64634 - $sourceLoader = fopen(__DIR__.'/ClassLoader.php', 'r'); - $targetLoader = fopen($targetDir.'/ClassLoader.php', 'w+'); - stream_copy_to_stream($sourceLoader, $targetLoader); - fclose($sourceLoader); - fclose($targetLoader); - unset($sourceLoader, $targetLoader); + $this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php'); + $this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE'); $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, array(), array( 'optimize' => (bool) $scanPsr0Packages, @@ -750,4 +744,20 @@ FOOTER; return $sortedPackageMap; } + + /** + * Copy file using stream_copy_to_stream to work around https://bugs.php.net/bug.php?id=6463 + * + * @param string $source + * @param string $target + */ + protected function safeCopy($source, $target) + { + $source = fopen($source, 'r'); + $target = fopen($target, 'w+'); + + stream_copy_to_stream($source, $target); + fclose($source); + fclose($target); + } } From 61dc752c78f672f514e00f9511cee79abf96e6c4 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Fri, 14 Aug 2015 13:13:10 +0200 Subject: [PATCH 119/205] Warn if cache directory cannot be created closes #1161 --- src/Composer/Cache.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Composer/Cache.php b/src/Composer/Cache.php index 746a31aec..22e744fd2 100644 --- a/src/Composer/Cache.php +++ b/src/Composer/Cache.php @@ -45,6 +45,7 @@ class Cache if (!is_dir($this->root)) { if (!@mkdir($this->root, 0777, true)) { + $this->io->writeError('Cannot create cache directory ' . $this->root . ', proceeding without cache'); $this->enabled = false; } } From 3c5f3e6dc7e953ccf44d78a88044c317d6b9e04e Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 14 Aug 2015 13:30:42 +0100 Subject: [PATCH 120/205] Warn if cache isnt writable as well --- src/Composer/Cache.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Composer/Cache.php b/src/Composer/Cache.php index 22e744fd2..9f9c55ba6 100644 --- a/src/Composer/Cache.php +++ b/src/Composer/Cache.php @@ -43,11 +43,12 @@ class Cache $this->whitelist = $whitelist; $this->filesystem = $filesystem ?: new Filesystem(); - if (!is_dir($this->root)) { - if (!@mkdir($this->root, 0777, true)) { - $this->io->writeError('Cannot create cache directory ' . $this->root . ', proceeding without cache'); - $this->enabled = false; - } + if ( + (!is_dir($this->root) && !@mkdir($this->root, 0777, true)) + || !is_writable($this->root) + ) { + $this->io->writeError('Cannot create cache directory ' . $this->root . ', or directory is not writable. Proceeding without cache'); + $this->enabled = false; } } From 3d962879a8bb9874a6d8b2eeb90f3d13b153d174 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 14 Aug 2015 14:55:08 +0100 Subject: [PATCH 121/205] Update deps --- composer.json | 2 +- composer.lock | 204 ++++++++++++++++++++++++-------------------------- 2 files changed, 100 insertions(+), 106 deletions(-) diff --git a/composer.json b/composer.json index ae18931d7..c53971509 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,7 @@ "phpunit/phpunit": "~4.5", "phpunit/phpunit-mock-objects": "2.3.0" }, - "_": "phpunit/phpunit-mock-objects required in 2.3.0 due to https://github.com/sebastianbergmann/phpunit-mock-objects/issues/223", + "_": "phpunit/phpunit-mock-objects required in 2.3.0 due to https://github.com/sebastianbergmann/phpunit-mock-objects/issues/223 - needs hhvm 3.8+ on travis", "config": { "platform": { "php": "5.3.3" diff --git a/composer.lock b/composer.lock index bbf036d5f..f05689b63 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "ed946efe7113827ff28dec6e3679b74b", + "hash": "6fbac2ddcd4e9064c84090f6d5514412", "packages": [ { "name": "composer/spdx-licenses", @@ -272,17 +272,17 @@ }, { "name": "symfony/console", - "version": "v2.6.9", + "version": "v2.6.11", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "b5ec0c11a204718f2b656357f5505a8e578f30dd" + "reference": "0e5e18ae09d3f5c06367759be940e9ed3f568359" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/b5ec0c11a204718f2b656357f5505a8e578f30dd", - "reference": "b5ec0c11a204718f2b656357f5505a8e578f30dd", + "url": "https://api.github.com/repos/symfony/Console/zipball/0e5e18ae09d3f5c06367759be940e9ed3f568359", + "reference": "0e5e18ae09d3f5c06367759be940e9ed3f568359", "shasum": "" }, "require": { @@ -326,21 +326,21 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2015-05-29 14:42:58" + "time": "2015-07-26 09:08:40" }, { "name": "symfony/finder", - "version": "v2.6.9", + "version": "v2.6.11", "target-dir": "Symfony/Component/Finder", "source": { "type": "git", "url": "https://github.com/symfony/Finder.git", - "reference": "ffedd3e0ff8155188155e9322fe21b9ee012ac14" + "reference": "203a10f928ae30176deeba33512999233181dd28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/ffedd3e0ff8155188155e9322fe21b9ee012ac14", - "reference": "ffedd3e0ff8155188155e9322fe21b9ee012ac14", + "url": "https://api.github.com/repos/symfony/Finder/zipball/203a10f928ae30176deeba33512999233181dd28", + "reference": "203a10f928ae30176deeba33512999233181dd28", "shasum": "" }, "require": { @@ -376,21 +376,21 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2015-05-15 13:32:45" + "time": "2015-07-09 16:02:48" }, { "name": "symfony/process", - "version": "v2.6.9", + "version": "v2.6.11", "target-dir": "Symfony/Component/Process", "source": { "type": "git", "url": "https://github.com/symfony/Process.git", - "reference": "7856d78ab6cce6e59d02d9e1a873441f6bd21306" + "reference": "57f1e88bb5dafa449b83f9f265b11d52d517b3e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/7856d78ab6cce6e59d02d9e1a873441f6bd21306", - "reference": "7856d78ab6cce6e59d02d9e1a873441f6bd21306", + "url": "https://api.github.com/repos/symfony/Process/zipball/57f1e88bb5dafa449b83f9f265b11d52d517b3e9", + "reference": "57f1e88bb5dafa449b83f9f265b11d52d517b3e9", "shasum": "" }, "require": { @@ -426,22 +426,22 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2015-05-15 13:32:45" + "time": "2015-06-30 16:10:16" } ], "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.0.4", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119" + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f976e5de371104877ebc89bd8fecb0019ed9c119", - "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", "shasum": "" }, "require": { @@ -452,7 +452,7 @@ "ext-pdo": "*", "ext-phar": "*", "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "2.0.*@ALPHA" + "squizlabs/php_codesniffer": "~2.0" }, "type": "library", "extra": { @@ -461,8 +461,8 @@ } }, "autoload": { - "psr-0": { - "Doctrine\\Instantiator\\": "src" + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", @@ -482,7 +482,7 @@ "constructor", "instantiate" ], - "time": "2014-10-13 12:58:55" + "time": "2015-06-14 21:17:01" }, { "name": "phpdocumentor/reflection-docblock", @@ -535,16 +535,16 @@ }, { "name": "phpspec/prophecy", - "version": "v1.4.1", + "version": "v1.5.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373" + "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373", - "reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4745ded9307786b730d7a60df5cb5a6c43cf95f7", + "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7", "shasum": "" }, "require": { @@ -591,20 +591,20 @@ "spy", "stub" ], - "time": "2015-04-27 22:15:08" + "time": "2015-08-13 10:07:40" }, { "name": "phpunit/php-code-coverage", - "version": "2.1.5", + "version": "2.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "be2286cb8c7e1773eded49d9719219e6f74f9e3e" + "reference": "2d7c03c0e4e080901b8f33b2897b0577be18a13c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/be2286cb8c7e1773eded49d9719219e6f74f9e3e", - "reference": "be2286cb8c7e1773eded49d9719219e6f74f9e3e", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2d7c03c0e4e080901b8f33b2897b0577be18a13c", + "reference": "2d7c03c0e4e080901b8f33b2897b0577be18a13c", "shasum": "" }, "require": { @@ -612,7 +612,7 @@ "phpunit/php-file-iterator": "~1.3", "phpunit/php-text-template": "~1.2", "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "~1.0", + "sebastian/environment": "^1.3.2", "sebastian/version": "~1.0" }, "require-dev": { @@ -627,7 +627,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1.x-dev" + "dev-master": "2.2.x-dev" } }, "autoload": { @@ -653,20 +653,20 @@ "testing", "xunit" ], - "time": "2015-06-09 13:05:42" + "time": "2015-08-04 03:42:39" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb" + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a923bb15680d0089e2316f7a4af8f437046e96bb", - "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", "shasum": "" }, "require": { @@ -700,20 +700,20 @@ "filesystem", "iterator" ], - "time": "2015-04-02 05:19:05" + "time": "2015-06-21 13:08:43" }, { "name": "phpunit/php-text-template", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "shasum": "" }, "require": { @@ -722,20 +722,17 @@ "type": "library", "autoload": { "classmap": [ - "Text/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -744,20 +741,20 @@ "keywords": [ "template" ], - "time": "2014-01-30 17:20:04" + "time": "2015-06-21 13:50:34" }, { "name": "phpunit/php-timer", - "version": "1.0.5", + "version": "1.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" + "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", "shasum": "" }, "require": { @@ -766,13 +763,10 @@ "type": "library", "autoload": { "classmap": [ - "PHP/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -788,20 +782,20 @@ "keywords": [ "timer" ], - "time": "2013-08-02 07:42:54" + "time": "2015-06-21 08:01:12" }, { "name": "phpunit/php-token-stream", - "version": "1.4.1", + "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "eab81d02569310739373308137284e0158424330" + "reference": "09fc125d65c344c53a7c7ad8f261e3f3af9f76c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330", - "reference": "eab81d02569310739373308137284e0158424330", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/09fc125d65c344c53a7c7ad8f261e3f3af9f76c5", + "reference": "09fc125d65c344c53a7c7ad8f261e3f3af9f76c5", "shasum": "" }, "require": { @@ -837,20 +831,20 @@ "keywords": [ "tokenizer" ], - "time": "2015-04-08 04:46:07" + "time": "2015-08-13 14:23:08" }, { "name": "phpunit/phpunit", - "version": "4.7.2", + "version": "4.8.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "8e0c63329c8c4185296b8d357daa5c6bae43080f" + "reference": "fd3050e26e3105f416d74c4d33aea659b406c59d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e0c63329c8c4185296b8d357daa5c6bae43080f", - "reference": "8e0c63329c8c4185296b8d357daa5c6bae43080f", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fd3050e26e3105f416d74c4d33aea659b406c59d", + "reference": "fd3050e26e3105f416d74c4d33aea659b406c59d", "shasum": "" }, "require": { @@ -860,15 +854,15 @@ "ext-reflection": "*", "ext-spl": "*", "php": ">=5.3.3", - "phpspec/prophecy": "~1.3,>=1.3.1", + "phpspec/prophecy": "^1.3.1", "phpunit/php-code-coverage": "~2.1", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "~1.0", + "phpunit/php-timer": ">=1.0.6", "phpunit/phpunit-mock-objects": "~2.3", "sebastian/comparator": "~1.1", "sebastian/diff": "~1.2", - "sebastian/environment": "~1.2", + "sebastian/environment": "~1.3", "sebastian/exporter": "~1.2", "sebastian/global-state": "~1.0", "sebastian/version": "~1.0", @@ -883,7 +877,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.7.x-dev" + "dev-master": "4.8.x-dev" } }, "autoload": { @@ -909,7 +903,7 @@ "testing", "xunit" ], - "time": "2015-06-06 08:36:08" + "time": "2015-08-10 09:16:56" }, { "name": "phpunit/phpunit-mock-objects", @@ -968,16 +962,16 @@ }, { "name": "sebastian/comparator", - "version": "1.1.1", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "1dd8869519a225f7f2b9eb663e225298fade819e" + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e", - "reference": "1dd8869519a225f7f2b9eb663e225298fade819e", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", "shasum": "" }, "require": { @@ -991,7 +985,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -1028,7 +1022,7 @@ "compare", "equality" ], - "time": "2015-01-29 16:28:08" + "time": "2015-07-26 15:48:44" }, { "name": "sebastian/diff", @@ -1084,16 +1078,16 @@ }, { "name": "sebastian/environment", - "version": "1.2.2", + "version": "1.3.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e" + "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5a8c7d31914337b69923db26c4221b81ff5a196e", - "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6324c907ce7a52478eeeaede764f48733ef5ae44", + "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44", "shasum": "" }, "require": { @@ -1130,20 +1124,20 @@ "environment", "hhvm" ], - "time": "2015-01-01 10:01:08" + "time": "2015-08-03 06:14:51" }, { "name": "sebastian/exporter", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "84839970d05254c73cde183a721c7af13aede943" + "reference": "7ae5513327cb536431847bcc0c10edba2701064e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943", - "reference": "84839970d05254c73cde183a721c7af13aede943", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", + "reference": "7ae5513327cb536431847bcc0c10edba2701064e", "shasum": "" }, "require": { @@ -1196,7 +1190,7 @@ "export", "exporter" ], - "time": "2015-01-27 07:23:06" + "time": "2015-06-21 07:55:53" }, { "name": "sebastian/global-state", @@ -1251,16 +1245,16 @@ }, { "name": "sebastian/recursion-context", - "version": "1.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "3989662bbb30a29d20d9faa04a846af79b276252" + "reference": "994d4a811bafe801fb06dccbee797863ba2792ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252", - "reference": "3989662bbb30a29d20d9faa04a846af79b276252", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/994d4a811bafe801fb06dccbee797863ba2792ba", + "reference": "994d4a811bafe801fb06dccbee797863ba2792ba", "shasum": "" }, "require": { @@ -1300,20 +1294,20 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-01-24 09:48:32" + "time": "2015-06-21 08:04:50" }, { "name": "sebastian/version", - "version": "1.0.5", + "version": "1.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4" + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", - "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", "shasum": "" }, "type": "library", @@ -1335,21 +1329,21 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-02-24 06:35:25" + "time": "2015-06-21 13:59:46" }, { "name": "symfony/yaml", - "version": "v2.6.9", + "version": "v2.6.11", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2" + "reference": "c044d1744b8e91aaaa0d9bac683ab87ec7cbf359" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/f157ab074e453ecd4c0fa775f721f6e67a99d9e2", - "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/c044d1744b8e91aaaa0d9bac683ab87ec7cbf359", + "reference": "c044d1744b8e91aaaa0d9bac683ab87ec7cbf359", "shasum": "" }, "require": { @@ -1385,7 +1379,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2015-07-26 08:59:42" } ], "aliases": [], From 4fa1cb2e9c3e4cf3fe8242b99551e76c00d3277d Mon Sep 17 00:00:00 2001 From: voroks Date: Sat, 15 Aug 2015 16:12:16 +0800 Subject: [PATCH 122/205] Removing file autoload_files.php was added (#4254) --- src/Composer/Autoload/AutoloadGenerator.php | 7 +- .../Test/Autoload/AutoloadGeneratorTest.php | 65 +++++++++++++++++++ ...oad_files_functions_with_removed_extra.php | 10 +++ ...load_real_functions_with_removed_extra.php | 50 ++++++++++++++ 4 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 tests/Composer/Test/Autoload/Fixtures/autoload_files_functions_with_removed_extra.php create mode 100644 tests/Composer/Test/Autoload/Fixtures/autoload_real_functions_with_removed_extra.php diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 4a55a53c0..b89c23113 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -255,9 +255,12 @@ EOF; if ($includePathFile = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) { file_put_contents($targetDir.'/include_paths.php', $includePathFile); } + $includeFilesFilePath = $targetDir.'/autoload_files.php'; if ($includeFilesFile = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) { - file_put_contents($targetDir.'/autoload_files.php', $includeFilesFile); - } + file_put_contents($includeFilesFilePath, $includeFilesFile); + } else if (file_exists($includeFilesFilePath) === true) { + unlink($includeFilesFilePath); + } file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix)); file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFile, $targetDirLoader, (bool) $includeFilesFile, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $classMapAuthoritative)); diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index dbb7d2fad..bf63af717 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -585,6 +585,71 @@ class AutoloadGeneratorTest extends TestCase $this->assertTrue(function_exists('testFilesAutoloadGenerationRoot')); } + public function testFilesAutoloadGenerationRemoveExtraEntitiesFromAutoloadFiles() + { + $autoloadPackage = new Package('a', '1.0', '1.0'); + $autoloadPackage->setAutoload(array('files' => array('root.php'))); + + $notAutoloadPackage = new Package('a', '1.0', '1.0'); + + $autoloadPackages = array(); + $autoloadPackages[] = $a = new Package('a/a', '1.0', '1.0'); + $autoloadPackages[] = $b = new Package('b/b', '1.0', '1.0'); + $autoloadPackages[] = $c = new Package('c/c', '1.0', '1.0'); + $a->setAutoload(array('files' => array('test.php'))); + $b->setAutoload(array('files' => array('test2.php'))); + $c->setAutoload(array('files' => array('test3.php', 'foo/bar/test4.php'))); + $c->setTargetDir('foo/bar'); + + $notAutoloadPackages = array(); + $notAutoloadPackages[] = $a = new Package('a/a', '1.0', '1.0'); + $notAutoloadPackages[] = $b = new Package('b/b', '1.0', '1.0'); + $notAutoloadPackages[] = $c = new Package('c/c', '1.0', '1.0'); + + $this->repository->expects($this->at(0)) + ->method('getCanonicalPackages') + ->will($this->returnValue($autoloadPackages)); + + $this->repository->expects($this->at(1)) + ->method('getCanonicalPackages') + ->will($this->returnValue($notAutoloadPackages)); + + $this->repository->expects($this->at(2)) + ->method('getCanonicalPackages') + ->will($this->returnValue($notAutoloadPackages)); + + $this->fs->ensureDirectoryExists($this->vendorDir.'/a/a'); + $this->fs->ensureDirectoryExists($this->vendorDir.'/b/b'); + $this->fs->ensureDirectoryExists($this->vendorDir.'/c/c/foo/bar'); + file_put_contents($this->vendorDir.'/a/a/test.php', 'vendorDir.'/b/b/test2.php', 'vendorDir.'/c/c/foo/bar/test3.php', 'vendorDir.'/c/c/foo/bar/test4.php', 'workingDir.'/root.php', 'generator->dump($this->config, $this->repository, $autoloadPackage, $this->im, 'composer', false, 'FilesAutoload'); + $this->assertFileEquals(__DIR__.'/Fixtures/autoload_functions.php', $this->vendorDir.'/autoload.php'); + $this->assertFileEquals(__DIR__.'/Fixtures/autoload_real_functions.php', $this->vendorDir.'/composer/autoload_real.php'); + $this->assertFileEquals(__DIR__.'/Fixtures/autoload_files_functions.php', $this->vendorDir.'/composer/autoload_files.php'); + + $this->generator->dump($this->config, $this->repository, $autoloadPackage, $this->im, 'composer', false, 'FilesAutoload'); + $this->assertFileEquals(__DIR__.'/Fixtures/autoload_functions.php', $this->vendorDir.'/autoload.php'); + $this->assertFileEquals(__DIR__.'/Fixtures/autoload_real_functions.php', $this->vendorDir.'/composer/autoload_real.php'); + $this->assertFileEquals(__DIR__.'/Fixtures/autoload_files_functions_with_removed_extra.php', $this->vendorDir.'/composer/autoload_files.php'); + + $this->generator->dump($this->config, $this->repository, $notAutoloadPackage, $this->im, 'composer', false, 'FilesAutoload'); + $this->assertFileEquals(__DIR__.'/Fixtures/autoload_functions.php', $this->vendorDir.'/autoload.php'); + $this->assertFileEquals(__DIR__.'/Fixtures/autoload_real_functions_with_removed_extra.php', $this->vendorDir.'/composer/autoload_real.php'); + $this->assertFileNotExists($this->vendorDir.'/composer/autoload_files.php'); + + include $this->vendorDir . '/autoload.php'; + $this->assertFalse(function_exists('testFilesAutoloadGeneration1')); + $this->assertFalse(function_exists('testFilesAutoloadGeneration2')); + $this->assertFalse(function_exists('testFilesAutoloadGeneration3')); + $this->assertFalse(function_exists('testFilesAutoloadGeneration4')); + $this->assertFalse(function_exists('testFilesAutoloadGenerationRoot')); + } + public function testFilesAutoloadOrderByDependencies() { $package = new Package('a', '1.0', '1.0'); diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_files_functions_with_removed_extra.php b/tests/Composer/Test/Autoload/Fixtures/autoload_files_functions_with_removed_extra.php new file mode 100644 index 000000000..8d124df37 --- /dev/null +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_files_functions_with_removed_extra.php @@ -0,0 +1,10 @@ + $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + + $loader->register(true); + + return $loader; + } +} + +function composerRequireFilesAutoload($file) +{ + require $file; +} From 85de450fe9d0069b9f89234db658ad030d5ca91e Mon Sep 17 00:00:00 2001 From: voroks Date: Sat, 15 Aug 2015 16:41:35 +0800 Subject: [PATCH 123/205] Removed some extra assertions. --- tests/Composer/Test/Autoload/AutoloadGeneratorTest.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index bf63af717..08f9cc09d 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -641,13 +641,6 @@ class AutoloadGeneratorTest extends TestCase $this->assertFileEquals(__DIR__.'/Fixtures/autoload_functions.php', $this->vendorDir.'/autoload.php'); $this->assertFileEquals(__DIR__.'/Fixtures/autoload_real_functions_with_removed_extra.php', $this->vendorDir.'/composer/autoload_real.php'); $this->assertFileNotExists($this->vendorDir.'/composer/autoload_files.php'); - - include $this->vendorDir . '/autoload.php'; - $this->assertFalse(function_exists('testFilesAutoloadGeneration1')); - $this->assertFalse(function_exists('testFilesAutoloadGeneration2')); - $this->assertFalse(function_exists('testFilesAutoloadGeneration3')); - $this->assertFalse(function_exists('testFilesAutoloadGeneration4')); - $this->assertFalse(function_exists('testFilesAutoloadGenerationRoot')); } public function testFilesAutoloadOrderByDependencies() From 6ce9d2e15266be261c6f033cb40188b830cdcf69 Mon Sep 17 00:00:00 2001 From: DSanchez Date: Tue, 7 Jul 2015 10:54:04 -0400 Subject: [PATCH 124/205] Remove useless variable, method return void! --- src/Composer/Installer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index a3eb66301..2b11a56c0 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -615,7 +615,7 @@ class Installer if (!$this->dryRun) { // force source/dist urls to be updated for all packages - $operations = $this->processPackageUrls($pool, $policy, $localRepo, $repositories); + $this->processPackageUrls($pool, $policy, $localRepo, $repositories); $localRepo->write(); } From abfe54f3344553d7de42fbe13f21e0f5ffb82d8c Mon Sep 17 00:00:00 2001 From: DSanchez Date: Tue, 7 Jul 2015 10:53:33 -0400 Subject: [PATCH 125/205] Add missing PHPDoc Conflicts: src/Composer/Installer.php --- src/Composer/Installer.php | 64 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 2b11a56c0..8aecea402 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -18,6 +18,7 @@ use Composer\DependencyResolver\Operation\UpdateOperation; use Composer\DependencyResolver\Operation\InstallOperation; use Composer\DependencyResolver\Operation\UninstallOperation; use Composer\DependencyResolver\Operation\OperationInterface; +use Composer\DependencyResolver\PolicyInterface; use Composer\DependencyResolver\Pool; use Composer\DependencyResolver\Request; use Composer\DependencyResolver\Rule; @@ -43,6 +44,7 @@ use Composer\Repository\InstalledFilesystemRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryInterface; use Composer\Repository\RepositoryManager; +use Composer\Repository\WritableRepositoryInterface; use Composer\Script\ScriptEvents; /** @@ -353,6 +355,14 @@ class Installer return 0; } + /** + * @param RepositoryInterface $localRepo + * @param RepositoryInterface $installedRepo + * @param PlatformRepository $platformRepo + * @param array $aliases + * @param bool $withDevReqs + * @return int + */ protected function doInstall($localRepo, $installedRepo, $platformRepo, $aliases, $withDevReqs) { // init vars @@ -686,6 +696,11 @@ class Installer return array_merge($uninstOps, $operations); } + /** + * @param bool $withDevReqs + * @param RepositoryInterface|null $lockedRepository + * @return Pool + */ private function createPool($withDevReqs, RepositoryInterface $lockedRepository = null) { if (!$this->update && $this->locker->isLocked()) { // install from lock @@ -724,6 +739,9 @@ class Installer return new Pool($minimumStability, $stabilityFlags, $rootConstraints); } + /** + * @return DefaultPolicy + */ private function createPolicy() { $preferStable = null; @@ -744,6 +762,11 @@ class Installer return new DefaultPolicy($preferStable, $preferLowest); } + /** + * @param RootPackageInterface $rootPackage + * @param PlatformRepository $platformRepo + * @return Request + */ private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo) { $request = new Request(); @@ -777,6 +800,19 @@ class Installer return $request; } + /** + * @param WritableRepositoryInterface $localRepo + * @param Pool $pool + * @param PolicyInterface $policy + * @param array $repositories + * @param RepositoryInterface $installedRepo + * @param RepositoryInterface $lockedRepository + * @param bool $installFromLock + * @param bool $withDevReqs + * @param string $task + * @param array|null $operations + * @return array + */ private function processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $installFromLock, $withDevReqs, $task, array $operations = null) { if ($task === 'force-updates' && null === $operations) { @@ -909,6 +945,9 @@ class Installer /** * Loads the most "current" list of packages that are installed meaning from lock ideally or from installed repo as fallback + * @param bool $withDevReqs + * @param RepositoryInterface $installedRepo + * @return array */ private function getCurrentPackages($withDevReqs, $installedRepo) { @@ -924,6 +963,9 @@ class Installer return $installedRepo->getPackages(); } + /** + * @return array + */ private function getRootAliases() { if (!$this->update && $this->locker->isLocked()) { @@ -944,6 +986,12 @@ class Installer return $normalizedAliases; } + /** + * @param Pool $pool + * @param PolicyInterface $policy + * @param WritableRepositoryInterface $localRepo + * @param array $repositories + */ private function processPackageUrls($pool, $policy, $localRepo, $repositories) { if (!$this->update) { @@ -984,6 +1032,10 @@ class Installer } } + /** + * @param PlatformRepository $platformRepo + * @param array $aliases + */ private function aliasPlatformPackages(PlatformRepository $platformRepo, $aliases) { foreach ($aliases as $package => $versions) { @@ -998,6 +1050,10 @@ class Installer } } + /** + * @param PackageInterface $package + * @return bool + */ private function isUpdateable(PackageInterface $package) { if (!$this->updateWhitelist) { @@ -1027,6 +1083,10 @@ class Installer return "{^" . $cleanedWhiteListedPattern . "$}i"; } + /** + * @param array $links + * @return array + */ private function extractPlatformRequirements($links) { $platformReqs = array(); @@ -1179,6 +1239,10 @@ class Installer ); } + /** + * @param RepositoryInterface $additionalInstalledRepository + * @return $this + */ public function setAdditionalInstalledRepository(RepositoryInterface $additionalInstalledRepository) { $this->additionalInstalledRepository = $additionalInstalledRepository; From 9859859f1082d94e546aa75746867df127aa0d9e Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 17 Aug 2015 15:57:00 +0100 Subject: [PATCH 126/205] Add comment, fixes #4145 --- src/Composer/Util/RemoteFilesystem.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php index edcc465c7..12ec0fbfc 100644 --- a/src/Composer/Util/RemoteFilesystem.php +++ b/src/Composer/Util/RemoteFilesystem.php @@ -227,6 +227,8 @@ class RemoteFilesystem if (preg_match('{^content-encoding: *gzip *$}i', $header)) { $decode = true; } elseif (preg_match('{^HTTP/}i', $header)) { + // In case of redirects, http_response_headers contains the headers of all responses + // so we reset the flag when a new response is being parsed as we are only interested in the last response $decode = false; } } From cca42ff0be37f9eff7380953549174dca59cd040 Mon Sep 17 00:00:00 2001 From: voroks Date: Tue, 18 Aug 2015 15:29:22 +0800 Subject: [PATCH 127/205] Fixed indents: we should use spaces instead tabulation. --- src/Composer/Autoload/AutoloadGenerator.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index b89c23113..86f954aba 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -255,12 +255,12 @@ EOF; if ($includePathFile = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) { file_put_contents($targetDir.'/include_paths.php', $includePathFile); } - $includeFilesFilePath = $targetDir.'/autoload_files.php'; + $includeFilesFilePath = $targetDir.'/autoload_files.php'; if ($includeFilesFile = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) { file_put_contents($includeFilesFilePath, $includeFilesFile); } else if (file_exists($includeFilesFilePath) === true) { - unlink($includeFilesFilePath); - } + unlink($includeFilesFilePath); + } file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix)); file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFile, $targetDirLoader, (bool) $includeFilesFile, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $classMapAuthoritative)); From 457bc20c34e4e1ac2ba8868184822495b5300a1c Mon Sep 17 00:00:00 2001 From: voroks Date: Tue, 18 Aug 2015 16:10:59 +0800 Subject: [PATCH 128/205] Explicit comparison was removed. --- src/Composer/Autoload/AutoloadGenerator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 86f954aba..90d17bcf3 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -258,7 +258,7 @@ EOF; $includeFilesFilePath = $targetDir.'/autoload_files.php'; if ($includeFilesFile = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) { file_put_contents($includeFilesFilePath, $includeFilesFile); - } else if (file_exists($includeFilesFilePath) === true) { + } else if (file_exists($includeFilesFilePath)) { unlink($includeFilesFilePath); } file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix)); From ead68d3d4900d63284e1db3d360cd5c8353c39e5 Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Tue, 18 Aug 2015 14:40:48 +0100 Subject: [PATCH 129/205] Create the path repository and downloader --- composer.json | 1 + composer.lock | 52 +++++++++- src/Composer/Downloader/PathDownloader.php | 50 ++++++++++ src/Composer/Factory.php | 2 + src/Composer/Repository/PathRepository.php | 105 +++++++++++++++++++++ src/Composer/Util/Filesystem.php | 9 +- 6 files changed, 217 insertions(+), 2 deletions(-) create mode 100644 src/Composer/Downloader/PathDownloader.php create mode 100644 src/Composer/Repository/PathRepository.php diff --git a/composer.json b/composer.json index c53971509..4ba003887 100644 --- a/composer.json +++ b/composer.json @@ -29,6 +29,7 @@ "symfony/console": "~2.5", "symfony/finder": "~2.2", "symfony/process": "~2.1", + "symfony/filesystem": "~2.5", "seld/phar-utils": "~1.0", "seld/cli-prompt": "~1.0" }, diff --git a/composer.lock b/composer.lock index f05689b63..fc7e1ef34 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "6fbac2ddcd4e9064c84090f6d5514412", + "hash": "3024e89a7e808b8dece156112459a7ea", "packages": [ { "name": "composer/spdx-licenses", @@ -328,6 +328,56 @@ "homepage": "https://symfony.com", "time": "2015-07-26 09:08:40" }, + { + "name": "symfony/filesystem", + "version": "v2.6.11", + "target-dir": "Symfony/Component/Filesystem", + "source": { + "type": "git", + "url": "https://github.com/symfony/Filesystem.git", + "reference": "823c035b1a5c13a4924e324d016eb07e70f94735" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/823c035b1a5c13a4924e324d016eb07e70f94735", + "reference": "823c035b1a5c13a4924e324d016eb07e70f94735", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Filesystem\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2015-07-08 05:59:48" + }, { "name": "symfony/finder", "version": "v2.6.11", diff --git a/src/Composer/Downloader/PathDownloader.php b/src/Composer/Downloader/PathDownloader.php new file mode 100644 index 000000000..fbdb0aebc --- /dev/null +++ b/src/Composer/Downloader/PathDownloader.php @@ -0,0 +1,50 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Downloader; + +use Composer\Package\PackageInterface; +use Symfony\Component\Filesystem\Exception\IOException; +use Symfony\Component\Filesystem\Filesystem; + +/** + * Download a package from a local path. + * + * @author Samuel Roze + * @author Johann Reinke + */ +class PathDownloader extends FileDownloader +{ + /** + * {@inheritdoc} + */ + public function download(PackageInterface $package, $path) + { + $fileSystem = new Filesystem(); + if ($fileSystem->exists($path)) { + $fileSystem->remove($path); + } + + try { + $fileSystem->symlink($package->getDistUrl(), $path); + } catch (IOException $e) { + $fileSystem->mirror($package->getDistUrl(), $path); + } + + $this->io->writeError(sprintf( + ' Downloaded %s (%s) from %s', + $package->getName(), + $package->getFullPrettyVersion(), + $package->getDistUrl() + )); + } +} diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 6f9a5da36..4fabbe455 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -331,6 +331,7 @@ class Factory $rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository'); $rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository'); $rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository'); + $rm->setRepositoryClass('path', 'Composer\Repository\PathRepository'); return $rm; } @@ -403,6 +404,7 @@ class Factory $dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $eventDispatcher, $cache)); $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache)); $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache)); + $dm->setDownloader('path', new Downloader\PathDownloader($io, $config, $eventDispatcher, $cache)); return $dm; } diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php new file mode 100644 index 000000000..63bd3be01 --- /dev/null +++ b/src/Composer/Repository/PathRepository.php @@ -0,0 +1,105 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Repository; + +use Composer\Json\JsonFile; +use Composer\Package\Loader\ArrayLoader; +use Symfony\Component\Filesystem\Filesystem; + +/** + * This repository allows installing local packages that are not necessarily under their own VCS. + * + * The local packages will be symlinked when possible, else they will be copied. + * + * @code + * "require": { + * "/": "*" + * }, + * "repositories": [ + * { + * "type": "path", + * "url": "../../relative/path/to/package/" + * }, + * { + * "type": "path", + * "url": "/absolute/path/to/package/" + * } + * ] + * @endcode + * + * @author Samuel Roze + * @author Johann Reinke + */ +class PathRepository extends ArrayRepository +{ + /** + * @var Filesystem + */ + private $fileSystem; + + /** + * @var ArrayLoader + */ + private $loader; + + /** + * @var string + */ + private $path; + + /** + * Initializes path repository. + * + * @param array $config package definition + */ + public function __construct(array $config) + { + if (!isset($config['url'])) { + throw new \RuntimeException('You must specify the `url` configuration for the path repository'); + } + + $this->fileSystem = new Filesystem(); + $this->loader = new ArrayLoader(); + $this->path = realpath(rtrim($config['url'], '/')) . '/'; + } + + /** + * Initializes path repository. + * + * This method will basically read the folder and add the found package. + * + */ + protected function initialize() + { + parent::initialize(); + + $composerFilePath = $this->path.'composer.json'; + if (!$this->fileSystem->exists($composerFilePath)) { + throw new \RuntimeException(sprintf('No `composer.json` file found in path repository "%s"', $this->path)); + } + + $json = file_get_contents($composerFilePath); + $package = JsonFile::parseJson($json, $composerFilePath); + $package['dist'] = array( + 'type' => 'folder', + 'url' => $this->path, + ); + + if (!isset($package['version'])) { + $package['version'] = 'dev-master'; + } + + $package = $this->loader->load($package); + $this->addPackage($package); + } +} diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index 92e5e0623..c36347fb7 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -508,7 +508,14 @@ class Filesystem return unlink($path); } - private function isSymlinkedDirectory($directory) + /** + * return true if that directory is a symlink. + * + * @param string $directory + * + * @return bool + */ + public function isSymlinkedDirectory($directory) { if (!is_dir($directory)) { return false; From 5261a5fa03892f7f25aadff5d74678d5f76a4bed Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Tue, 18 Aug 2015 14:58:18 +0100 Subject: [PATCH 130/205] Move version guessing in `VersionGuesser` class --- src/Composer/Factory.php | 4 +- .../Package/Loader/RootPackageLoader.php | 195 ++--------------- .../Package/Version/VersionGuesser.php | 201 ++++++++++++++++++ .../Package/Loader/RootPackageLoaderTest.php | 183 +++------------- .../Package/Version/VersionGuesserTest.php | 158 ++++++++++++++ 5 files changed, 405 insertions(+), 336 deletions(-) create mode 100644 src/Composer/Package/Version/VersionGuesser.php create mode 100644 tests/Composer/Test/Package/Version/VersionGuesserTest.php diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 4fabbe455..1da6c30da 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -16,6 +16,7 @@ use Composer\Config\JsonConfigSource; use Composer\Json\JsonFile; use Composer\IO\IOInterface; use Composer\Package\Archiver; +use Composer\Package\Version\VersionGuesser; use Composer\Repository\RepositoryManager; use Composer\Repository\WritableRepositoryInterface; use Composer\Util\ProcessExecutor; @@ -264,7 +265,8 @@ class Factory // load package $parser = new VersionParser; - $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, new ProcessExecutor($io)); + $guesser = new VersionGuesser(new ProcessExecutor($io), $parser); + $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser); $package = $loader->load($localConfig); $composer->setPackage($package); diff --git a/src/Composer/Package/Loader/RootPackageLoader.php b/src/Composer/Package/Loader/RootPackageLoader.php index 9c7c436bc..3043a18c5 100644 --- a/src/Composer/Package/Loader/RootPackageLoader.php +++ b/src/Composer/Package/Loader/RootPackageLoader.php @@ -16,13 +16,10 @@ use Composer\Package\BasePackage; use Composer\Package\AliasPackage; use Composer\Config; use Composer\Factory; +use Composer\Package\Version\VersionGuesser; use Composer\Package\Version\VersionParser; use Composer\Repository\RepositoryManager; -use Composer\Repository\Vcs\HgDriver; -use Composer\IO\NullIO; use Composer\Util\ProcessExecutor; -use Composer\Util\Git as GitUtil; -use Composer\Util\Svn as SvnUtil; /** * ArrayLoader built for the sole purpose of loading the root package @@ -33,16 +30,28 @@ use Composer\Util\Svn as SvnUtil; */ class RootPackageLoader extends ArrayLoader { + /** + * @var RepositoryManager + */ private $manager; + + /** + * @var Config + */ private $config; - private $process; - public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, ProcessExecutor $process = null) + /** + * @var VersionGuesser + */ + private $versionGuesser; + + public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, VersionGuesser $versionGuesser = null) { + parent::__construct($parser); + $this->manager = $manager; $this->config = $config; - $this->process = $process ?: new ProcessExecutor(); - parent::__construct($parser); + $this->versionGuesser = $versionGuesser ?: new VersionGuesser(new ProcessExecutor(), $this->versionParser); } public function load(array $config, $class = 'Composer\Package\RootPackage') @@ -56,7 +65,7 @@ class RootPackageLoader extends ArrayLoader if (getenv('COMPOSER_ROOT_VERSION')) { $version = getenv('COMPOSER_ROOT_VERSION'); } else { - $version = $this->guessVersion($config); + $version = $this->versionGuesser->guessVersion($this->config, $config); } if (!$version) { @@ -176,172 +185,4 @@ class RootPackageLoader extends ArrayLoader return $references; } - - private function guessVersion(array $config) - { - if (function_exists('proc_open')) { - $version = $this->guessGitVersion($config); - if (null !== $version) { - return $version; - } - - $version = $this->guessHgVersion($config); - if (null !== $version) { - return $version; - } - - return $this->guessSvnVersion($config); - } - } - - private function guessGitVersion(array $config) - { - GitUtil::cleanEnv(); - - // try to fetch current version from git tags - if (0 === $this->process->execute('git describe --exact-match --tags', $output)) { - try { - return $this->versionParser->normalize(trim($output)); - } catch (\Exception $e) { - } - } - - // try to fetch current version from git branch - if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output)) { - $branches = array(); - $isFeatureBranch = false; - $version = null; - - // find current branch and collect all branch names - foreach ($this->process->splitLines($output) as $branch) { - if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) { - if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ') { - $version = 'dev-'.$match[2]; - $isFeatureBranch = true; - } else { - $version = $this->versionParser->normalizeBranch($match[1]); - $isFeatureBranch = 0 === strpos($version, 'dev-'); - if ('9999999-dev' === $version) { - $version = 'dev-'.$match[1]; - } - } - } - - if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) { - if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) { - $branches[] = $match[1]; - } - } - } - - if (!$isFeatureBranch) { - return $version; - } - - // try to find the best (nearest) version branch to assume this feature's version - $version = $this->guessFeatureVersion($config, $version, $branches, 'git rev-list %candidate%..%branch%'); - - return $version; - } - } - - private function guessHgVersion(array $config) - { - // try to fetch current version from hg branch - if (0 === $this->process->execute('hg branch', $output)) { - $branch = trim($output); - $version = $this->versionParser->normalizeBranch($branch); - $isFeatureBranch = 0 === strpos($version, 'dev-'); - - if ('9999999-dev' === $version) { - $version = 'dev-'.$branch; - } - - if (!$isFeatureBranch) { - return $version; - } - - // re-use the HgDriver to fetch branches (this properly includes bookmarks) - $config = array('url' => getcwd()); - $driver = new HgDriver($config, new NullIO(), $this->config, $this->process); - $branches = array_keys($driver->getBranches()); - - // try to find the best (nearest) version branch to assume this feature's version - $version = $this->guessFeatureVersion($config, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"'); - - return $version; - } - } - - private function guessFeatureVersion(array $config, $version, array $branches, $scmCmdline) - { - // ignore feature branches if they have no branch-alias or self.version is used - // and find the branch they came from to use as a version instead - if ((isset($config['extra']['branch-alias']) && !isset($config['extra']['branch-alias'][$version])) - || strpos(json_encode($config), '"self.version"') - ) { - $branch = preg_replace('{^dev-}', '', $version); - $length = PHP_INT_MAX; - - $nonFeatureBranches = ''; - if (!empty($config['non-feature-branches'])) { - $nonFeatureBranches = implode('|', $config['non-feature-branches']); - } - - foreach ($branches as $candidate) { - // return directly, if branch is configured to be non-feature branch - if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) { - return $version; - } - - // do not compare against other feature branches - if ($candidate === $branch || !preg_match('{^(master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) { - continue; - } - - $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline); - if (0 !== $this->process->execute($cmdLine, $output)) { - continue; - } - - if (strlen($output) < $length) { - $length = strlen($output); - $version = $this->versionParser->normalizeBranch($candidate); - if ('9999999-dev' === $version) { - $version = 'dev-'.$match[1]; - } - } - } - } - - return $version; - } - - private function guessSvnVersion(array $config) - { - SvnUtil::cleanEnv(); - - // try to fetch current version from svn - if (0 === $this->process->execute('svn info --xml', $output)) { - $trunkPath = isset($config['trunk-path']) ? preg_quote($config['trunk-path'], '#') : 'trunk'; - $branchesPath = isset($config['branches-path']) ? preg_quote($config['branches-path'], '#') : 'branches'; - $tagsPath = isset($config['tags-path']) ? preg_quote($config['tags-path'], '#') : 'tags'; - - $urlPattern = '#.*/('.$trunkPath.'|('.$branchesPath.'|'. $tagsPath .')/(.*))#'; - - if (preg_match($urlPattern, $output, $matches)) { - if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) { - // we are in a branches path - $version = $this->versionParser->normalizeBranch($matches[3]); - if ('9999999-dev' === $version) { - $version = 'dev-'.$matches[3]; - } - - return $version; - } - - return $this->versionParser->normalize(trim($matches[1])); - } - } - } } diff --git a/src/Composer/Package/Version/VersionGuesser.php b/src/Composer/Package/Version/VersionGuesser.php new file mode 100644 index 000000000..98cf216c8 --- /dev/null +++ b/src/Composer/Package/Version/VersionGuesser.php @@ -0,0 +1,201 @@ +process = $process; + $this->versionParser = $versionParser; + } + + public function guessVersion(Config $config, array $packageConfig) + { + if (function_exists('proc_open')) { + $version = $this->guessGitVersion($packageConfig); + if (null !== $version) { + return $version; + } + + $version = $this->guessHgVersion($config, $packageConfig); + if (null !== $version) { + return $version; + } + + return $this->guessSvnVersion($packageConfig); + } + } + + private function guessGitVersion(array $config) + { + GitUtil::cleanEnv(); + + // try to fetch current version from git tags + if (0 === $this->process->execute('git describe --exact-match --tags', $output)) { + try { + return $this->versionParser->normalize(trim($output)); + } catch (\Exception $e) { + } + } + + // try to fetch current version from git branch + if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output)) { + $branches = array(); + $isFeatureBranch = false; + $version = null; + + // find current branch and collect all branch names + foreach ($this->process->splitLines($output) as $branch) { + if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) { + if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ') { + $version = 'dev-'.$match[2]; + $isFeatureBranch = true; + } else { + $version = $this->versionParser->normalizeBranch($match[1]); + $isFeatureBranch = 0 === strpos($version, 'dev-'); + if ('9999999-dev' === $version) { + $version = 'dev-'.$match[1]; + } + } + } + + if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) { + if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) { + $branches[] = $match[1]; + } + } + } + + if (!$isFeatureBranch) { + return $version; + } + + // try to find the best (nearest) version branch to assume this feature's version + $version = $this->guessFeatureVersion($config, $version, $branches, 'git rev-list %candidate%..%branch%'); + + return $version; + } + } + + private function guessHgVersion(Config $config, array $packageConfig) + { + // try to fetch current version from hg branch + if (0 === $this->process->execute('hg branch', $output)) { + $branch = trim($output); + $version = $this->versionParser->normalizeBranch($branch); + $isFeatureBranch = 0 === strpos($version, 'dev-'); + + if ('9999999-dev' === $version) { + $version = 'dev-'.$branch; + } + + if (!$isFeatureBranch) { + return $version; + } + + // re-use the HgDriver to fetch branches (this properly includes bookmarks) + $packageConfig = array('url' => getcwd()); + $driver = new HgDriver($packageConfig, new NullIO(), $config, $this->process); + $branches = array_keys($driver->getBranches()); + + // try to find the best (nearest) version branch to assume this feature's version + $version = $this->guessFeatureVersion($config, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"'); + + return $version; + } + } + + private function guessFeatureVersion(array $config, $version, array $branches, $scmCmdline) + { + // ignore feature branches if they have no branch-alias or self.version is used + // and find the branch they came from to use as a version instead + if ((isset($config['extra']['branch-alias']) && !isset($config['extra']['branch-alias'][$version])) + || strpos(json_encode($config), '"self.version"') + ) { + $branch = preg_replace('{^dev-}', '', $version); + $length = PHP_INT_MAX; + + $nonFeatureBranches = ''; + if (!empty($config['non-feature-branches'])) { + $nonFeatureBranches = implode('|', $config['non-feature-branches']); + } + + foreach ($branches as $candidate) { + // return directly, if branch is configured to be non-feature branch + if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) { + return $version; + } + + // do not compare against other feature branches + if ($candidate === $branch || !preg_match('{^(master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) { + continue; + } + + $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline); + if (0 !== $this->process->execute($cmdLine, $output)) { + continue; + } + + if (strlen($output) < $length) { + $length = strlen($output); + $version = $this->versionParser->normalizeBranch($candidate); + if ('9999999-dev' === $version) { + $version = 'dev-'.$match[1]; + } + } + } + } + + return $version; + } + + private function guessSvnVersion(array $config) + { + SvnUtil::cleanEnv(); + + // try to fetch current version from svn + if (0 === $this->process->execute('svn info --xml', $output)) { + $trunkPath = isset($config['trunk-path']) ? preg_quote($config['trunk-path'], '#') : 'trunk'; + $branchesPath = isset($config['branches-path']) ? preg_quote($config['branches-path'], '#') : 'branches'; + $tagsPath = isset($config['tags-path']) ? preg_quote($config['tags-path'], '#') : 'tags'; + + $urlPattern = '#.*/('.$trunkPath.'|('.$branchesPath.'|'. $tagsPath .')/(.*))#'; + + if (preg_match($urlPattern, $output, $matches)) { + if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) { + // we are in a branches path + $version = $this->versionParser->normalizeBranch($matches[3]); + if ('9999999-dev' === $version) { + $version = 'dev-'.$matches[3]; + } + + return $version; + } + + return $this->versionParser->normalize(trim($matches[1])); + } + } + } +} diff --git a/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php b/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php index 2a4d9ccf6..77139f928 100644 --- a/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php +++ b/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php @@ -15,144 +15,43 @@ namespace Composer\Test\Package\Loader; use Composer\Config; use Composer\Package\Loader\RootPackageLoader; use Composer\Package\BasePackage; +use Composer\Package\Version\VersionGuesser; +use Composer\Package\Version\VersionParser; class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase { - public function testDetachedHeadBecomesDevHash() + protected function loadPackage($data) { - if (!function_exists('proc_open')) { - $this->markTestSkipped('proc_open() is not available'); - } - - $commitHash = '03a15d220da53c52eddd5f32ffca64a7b3801bea'; - $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') ->disableOriginalConstructor() - ->getMock() - ; - - $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') - ->setMethods(array('execute')) - ->disableArgumentCloning() - ->disableOriginalConstructor() - ->getMock() - ; - - $executor - ->expects($this->at(0)) - ->method('execute') - ->with('git describe --exact-match --tags') - ->willReturn(1) - ; - - $self = $this; - - $executor - ->expects($this->at(1)) - ->method('execute') - ->willReturnCallback(function ($command, &$output) use ($self, $commitHash) { - $self->assertEquals('git branch --no-color --no-abbrev -v', $command); - $output = "* (no branch) $commitHash Commit message\n"; - - return 0; - }) - ; + ->getMock(); $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $executor); - $package = $loader->load(array()); - - $this->assertEquals("dev-$commitHash", $package->getVersion()); - } - - public function testTagBecomesVersion() - { - if (!function_exists('proc_open')) { - $this->markTestSkipped('proc_open() is not available'); - } - $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') - ->disableOriginalConstructor() - ->getMock() - ; - - $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') - ->setMethods(array('execute')) - ->disableArgumentCloning() - ->disableOriginalConstructor() - ->getMock() - ; - - $self = $this; - - $executor - ->expects($this->at(0)) - ->method('execute') - ->willReturnCallback(function ($command, &$output) use ($self) { - $self->assertEquals('git describe --exact-match --tags', $command); - $output = "v2.0.5-alpha2"; - - return 0; - }) - ; - - $config = new Config; - $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $executor); - $package = $loader->load(array()); + $loader = new RootPackageLoader($manager, $config); - $this->assertEquals("2.0.5.0-alpha2", $package->getVersion()); + return $loader->load($data); } - public function testInvalidTagBecomesVersion() + public function testStabilityFlagsParsing() { - if (!function_exists('proc_open')) { - $this->markTestSkipped('proc_open() is not available'); - } - - $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') - ->disableOriginalConstructor() - ->getMock() - ; - - $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') - ->setMethods(array('execute')) - ->disableArgumentCloning() - ->disableOriginalConstructor() - ->getMock() - ; - - $self = $this; - - $executor - ->expects($this->at(0)) - ->method('execute') - ->willReturnCallback(function ($command, &$output) use ($self) { - $self->assertEquals('git describe --exact-match --tags', $command); - $output = "foo-bar"; - - return 0; - }) - ; - - $executor - ->expects($this->at(1)) - ->method('execute') - ->willReturnCallback(function ($command, &$output) use ($self) { - $self->assertEquals('git branch --no-color --no-abbrev -v', $command); - $output = "* foo 03a15d220da53c52eddd5f32ffca64a7b3801bea Commit message\n"; - - return 0; - }) - ; - - $config = new Config; - $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $executor); - $package = $loader->load(array()); + $package = $this->loadPackage(array( + 'require' => array( + 'foo/bar' => '~2.1.0-beta2', + 'bar/baz' => '1.0.x-dev as 1.2.0', + 'qux/quux' => '1.0.*@rc', + 'zux/complex' => '~1.0,>=1.0.2@dev' + ), + 'minimum-stability' => 'alpha', + )); - $this->assertEquals("dev-foo", $package->getVersion()); + $this->assertEquals('alpha', $package->getMinimumStability()); + $this->assertEquals(array( + 'bar/baz' => BasePackage::STABILITY_DEV, + 'qux/quux' => BasePackage::STABILITY_RC, + 'zux/complex' => BasePackage::STABILITY_DEV, + ), $package->getStabilityFlags()); } public function testNoVersionIsVisibleInPrettyVersion() @@ -177,46 +76,14 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $executor); + $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($executor, new VersionParser())); $package = $loader->load(array()); $this->assertEquals("1.0.0.0", $package->getVersion()); $this->assertEquals("No version set (parsed as 1.0.0)", $package->getPrettyVersion()); } - protected function loadPackage($data) - { - $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') - ->disableOriginalConstructor() - ->getMock(); - - $config = new Config; - $config->merge(array('repositories' => array('packagist' => false))); - - $loader = new RootPackageLoader($manager, $config); - - return $loader->load($data); - } - public function testStabilityFlagsParsing() - { - $package = $this->loadPackage(array( - 'require' => array( - 'foo/bar' => '~2.1.0-beta2', - 'bar/baz' => '1.0.x-dev as 1.2.0', - 'qux/quux' => '1.0.*@rc', - 'zux/complex' => '~1.0,>=1.0.2@dev' - ), - 'minimum-stability' => 'alpha', - )); - - $this->assertEquals('alpha', $package->getMinimumStability()); - $this->assertEquals(array( - 'bar/baz' => BasePackage::STABILITY_DEV, - 'qux/quux' => BasePackage::STABILITY_RC, - 'zux/complex' => BasePackage::STABILITY_DEV, - ), $package->getStabilityFlags()); - } public function testFeatureBranchPrettyVersion() { @@ -272,7 +139,7 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $executor); + $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($executor, new VersionParser())); $package = $loader->load(array('require' => array('foo/bar' => 'self.version'))); $this->assertEquals("dev-master", $package->getPrettyVersion()); @@ -321,7 +188,7 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, $executor); + $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($executor, new VersionParser())); $package = $loader->load(array('require' => array('foo/bar' => 'self.version'), "non-feature-branches" => array("latest-.*"))); $this->assertEquals("dev-latest-production", $package->getPrettyVersion()); diff --git a/tests/Composer/Test/Package/Version/VersionGuesserTest.php b/tests/Composer/Test/Package/Version/VersionGuesserTest.php new file mode 100644 index 000000000..7891d1062 --- /dev/null +++ b/tests/Composer/Test/Package/Version/VersionGuesserTest.php @@ -0,0 +1,158 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Test\Package\Version; + +use Composer\Config; +use Composer\Package\Loader\RootPackageLoader; +use Composer\Package\Version\VersionGuesser; +use Composer\Package\Version\VersionParser; + +class VersionGuesserTest extends \PHPUnit_Framework_TestCase +{ + public function testDetachedHeadBecomesDevHash() + { + if (!function_exists('proc_open')) { + $this->markTestSkipped('proc_open() is not available'); + } + + $commitHash = '03a15d220da53c52eddd5f32ffca64a7b3801bea'; + + $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') + ->disableOriginalConstructor() + ->getMock() + ; + + $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') + ->setMethods(array('execute')) + ->disableArgumentCloning() + ->disableOriginalConstructor() + ->getMock() + ; + + $executor + ->expects($this->at(0)) + ->method('execute') + ->with('git describe --exact-match --tags') + ->willReturn(1) + ; + + $self = $this; + + $executor + ->expects($this->at(1)) + ->method('execute') + ->willReturnCallback(function ($command, &$output) use ($self, $commitHash) { + $self->assertEquals('git branch --no-color --no-abbrev -v', $command); + $output = "* (no branch) $commitHash Commit message\n"; + + return 0; + }) + ; + + $config = new Config; + $config->merge(array('repositories' => array('packagist' => false))); + $guesser = new VersionGuesser($executor, new VersionParser()); + $version = $guesser->guessVersion($config, []); + + $this->assertEquals("dev-$commitHash", $version); + } + + public function testTagBecomesVersion() + { + if (!function_exists('proc_open')) { + $this->markTestSkipped('proc_open() is not available'); + } + + $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') + ->disableOriginalConstructor() + ->getMock() + ; + + $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') + ->setMethods(array('execute')) + ->disableArgumentCloning() + ->disableOriginalConstructor() + ->getMock() + ; + + $self = $this; + + $executor + ->expects($this->at(0)) + ->method('execute') + ->willReturnCallback(function ($command, &$output) use ($self) { + $self->assertEquals('git describe --exact-match --tags', $command); + $output = "v2.0.5-alpha2"; + + return 0; + }) + ; + + $config = new Config; + $config->merge(array('repositories' => array('packagist' => false))); + $guesser = new VersionGuesser($executor, new VersionParser()); + $version = $guesser->guessVersion($config, []); + + $this->assertEquals("2.0.5.0-alpha2", $version); + } + + public function testInvalidTagBecomesVersion() + { + if (!function_exists('proc_open')) { + $this->markTestSkipped('proc_open() is not available'); + } + + $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') + ->disableOriginalConstructor() + ->getMock() + ; + + $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') + ->setMethods(array('execute')) + ->disableArgumentCloning() + ->disableOriginalConstructor() + ->getMock() + ; + + $self = $this; + + $executor + ->expects($this->at(0)) + ->method('execute') + ->willReturnCallback(function ($command, &$output) use ($self) { + $self->assertEquals('git describe --exact-match --tags', $command); + $output = "foo-bar"; + + return 0; + }) + ; + + $executor + ->expects($this->at(1)) + ->method('execute') + ->willReturnCallback(function ($command, &$output) use ($self) { + $self->assertEquals('git branch --no-color --no-abbrev -v', $command); + $output = "* foo 03a15d220da53c52eddd5f32ffca64a7b3801bea Commit message\n"; + + return 0; + }) + ; + + $config = new Config; + $config->merge(array('repositories' => array('packagist' => false))); + $guesser = new VersionGuesser($executor, new VersionParser()); + $version = $guesser->guessVersion($config, []); + + $this->assertEquals("dev-foo", $version); + } +} From 623f31fcc4f1546dd1153c725850fc1ebcd1589e Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Tue, 18 Aug 2015 15:08:27 +0100 Subject: [PATCH 131/205] Use version guesser to get local package version --- .../Package/Version/VersionGuesser.php | 21 +++++++---- src/Composer/Repository/PathRepository.php | 37 ++++++++++++++++--- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/Composer/Package/Version/VersionGuesser.php b/src/Composer/Package/Version/VersionGuesser.php index 98cf216c8..eba3249f6 100644 --- a/src/Composer/Package/Version/VersionGuesser.php +++ b/src/Composer/Package/Version/VersionGuesser.php @@ -21,14 +21,21 @@ class VersionGuesser */ private $versionParser; + /** + * @var null|string + */ + private $cwd; + /** * @param ProcessExecutor $process * @param VersionParser $versionParser + * @param string $cwd */ - public function __construct(ProcessExecutor $process, VersionParser $versionParser) + public function __construct(ProcessExecutor $process, VersionParser $versionParser, $cwd = null) { $this->process = $process; $this->versionParser = $versionParser; + $this->cwd = $cwd ?: getcwd(); } public function guessVersion(Config $config, array $packageConfig) @@ -53,7 +60,7 @@ class VersionGuesser GitUtil::cleanEnv(); // try to fetch current version from git tags - if (0 === $this->process->execute('git describe --exact-match --tags', $output)) { + if (0 === $this->process->execute('git describe --exact-match --tags', $output, $this->cwd)) { try { return $this->versionParser->normalize(trim($output)); } catch (\Exception $e) { @@ -61,7 +68,7 @@ class VersionGuesser } // try to fetch current version from git branch - if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output)) { + if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output, $this->cwd)) { $branches = array(); $isFeatureBranch = false; $version = null; @@ -102,7 +109,7 @@ class VersionGuesser private function guessHgVersion(Config $config, array $packageConfig) { // try to fetch current version from hg branch - if (0 === $this->process->execute('hg branch', $output)) { + if (0 === $this->process->execute('hg branch', $output, $this->cwd)) { $branch = trim($output); $version = $this->versionParser->normalizeBranch($branch); $isFeatureBranch = 0 === strpos($version, 'dev-'); @@ -116,7 +123,7 @@ class VersionGuesser } // re-use the HgDriver to fetch branches (this properly includes bookmarks) - $packageConfig = array('url' => getcwd()); + $packageConfig = array('url' => $this->cwd); $driver = new HgDriver($packageConfig, new NullIO(), $config, $this->process); $branches = array_keys($driver->getBranches()); @@ -154,7 +161,7 @@ class VersionGuesser } $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline); - if (0 !== $this->process->execute($cmdLine, $output)) { + if (0 !== $this->process->execute($cmdLine, $output, $this->cwd)) { continue; } @@ -176,7 +183,7 @@ class VersionGuesser SvnUtil::cleanEnv(); // try to fetch current version from svn - if (0 === $this->process->execute('svn info --xml', $output)) { + if (0 === $this->process->execute('svn info --xml', $output, $this->cwd)) { $trunkPath = isset($config['trunk-path']) ? preg_quote($config['trunk-path'], '#') : 'trunk'; $branchesPath = isset($config['branches-path']) ? preg_quote($config['branches-path'], '#') : 'branches'; $tagsPath = isset($config['tags-path']) ? preg_quote($config['tags-path'], '#') : 'tags'; diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index 63bd3be01..cdadbb518 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -12,8 +12,13 @@ namespace Composer\Repository; +use Composer\Config; +use Composer\IO\IOInterface; use Composer\Json\JsonFile; use Composer\Package\Loader\ArrayLoader; +use Composer\Package\Version\VersionGuesser; +use Composer\Package\Version\VersionParser; +use Composer\Util\ProcessExecutor; use Symfony\Component\Filesystem\Filesystem; /** @@ -42,6 +47,11 @@ use Symfony\Component\Filesystem\Filesystem; */ class PathRepository extends ArrayRepository { + /** + * @var Config + */ + private $config; + /** * @var Filesystem */ @@ -52,6 +62,16 @@ class PathRepository extends ArrayRepository */ private $loader; + /** + * @var VersionGuesser + */ + private $versionGuesser; + + /** + * @var array + */ + private $packageConfig; + /** * @var string */ @@ -60,17 +80,22 @@ class PathRepository extends ArrayRepository /** * Initializes path repository. * - * @param array $config package definition + * @param array $packageConfig + * @param IOInterface $io + * @param Config $config */ - public function __construct(array $config) + public function __construct(array $packageConfig, IOInterface $io, Config $config) { - if (!isset($config['url'])) { + if (!isset($packageConfig['url'])) { throw new \RuntimeException('You must specify the `url` configuration for the path repository'); } $this->fileSystem = new Filesystem(); $this->loader = new ArrayLoader(); - $this->path = realpath(rtrim($config['url'], '/')) . '/'; + $this->config = $config; + $this->packageConfig = $packageConfig; + $this->path = realpath(rtrim($packageConfig['url'], '/')) . '/'; + $this->versionGuesser = new VersionGuesser(new ProcessExecutor($io), new VersionParser(), $this->path); } /** @@ -91,12 +116,12 @@ class PathRepository extends ArrayRepository $json = file_get_contents($composerFilePath); $package = JsonFile::parseJson($json, $composerFilePath); $package['dist'] = array( - 'type' => 'folder', + 'type' => 'path', 'url' => $this->path, ); if (!isset($package['version'])) { - $package['version'] = 'dev-master'; + $package['version'] = $this->versionGuesser->guessVersion($this->config, $this->packageConfig) ?: 'dev-master'; } $package = $this->loader->load($package); From 4ab123291d9ca44a5f55088c64564e42166662a7 Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Tue, 18 Aug 2015 15:10:59 +0100 Subject: [PATCH 132/205] Add missing licence in VersionGuesser --- src/Composer/Package/Version/VersionGuesser.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Composer/Package/Version/VersionGuesser.php b/src/Composer/Package/Version/VersionGuesser.php index eba3249f6..4a5e2cc0a 100644 --- a/src/Composer/Package/Version/VersionGuesser.php +++ b/src/Composer/Package/Version/VersionGuesser.php @@ -1,5 +1,15 @@ + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Composer\Package\Version; use Composer\Config; @@ -9,6 +19,12 @@ use Composer\Util\Git as GitUtil; use Composer\Util\ProcessExecutor; use Composer\Util\Svn as SvnUtil; +/** + * Try to guess the current version number based on different VCS configuration. + * + * @author Jordi Boggiano + * @author Samuel Roze + */ class VersionGuesser { /** From dfccb686cea8f8b0c044f1858a2d8d6e382151f9 Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Tue, 18 Aug 2015 15:16:15 +0100 Subject: [PATCH 133/205] Replace usage of brackets by legacy array notation --- tests/Composer/Test/Package/Version/VersionGuesserTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Composer/Test/Package/Version/VersionGuesserTest.php b/tests/Composer/Test/Package/Version/VersionGuesserTest.php index 7891d1062..d6437f5e7 100644 --- a/tests/Composer/Test/Package/Version/VersionGuesserTest.php +++ b/tests/Composer/Test/Package/Version/VersionGuesserTest.php @@ -62,7 +62,7 @@ class VersionGuesserTest extends \PHPUnit_Framework_TestCase $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); $guesser = new VersionGuesser($executor, new VersionParser()); - $version = $guesser->guessVersion($config, []); + $version = $guesser->guessVersion($config, array()); $this->assertEquals("dev-$commitHash", $version); } @@ -101,7 +101,7 @@ class VersionGuesserTest extends \PHPUnit_Framework_TestCase $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); $guesser = new VersionGuesser($executor, new VersionParser()); - $version = $guesser->guessVersion($config, []); + $version = $guesser->guessVersion($config, array()); $this->assertEquals("2.0.5.0-alpha2", $version); } @@ -151,7 +151,7 @@ class VersionGuesserTest extends \PHPUnit_Framework_TestCase $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); $guesser = new VersionGuesser($executor, new VersionParser()); - $version = $guesser->guessVersion($config, []); + $version = $guesser->guessVersion($config, array()); $this->assertEquals("dev-foo", $version); } From 154092ba1a9b05caa0c450dd947be286c4897191 Mon Sep 17 00:00:00 2001 From: voroks Date: Wed, 19 Aug 2015 15:08:27 +0800 Subject: [PATCH 134/205] Added removing file 'include_path.php' (if it is empty). --- src/Composer/Autoload/AutoloadGenerator.php | 13 ++-- .../Test/Autoload/AutoloadGeneratorTest.php | 13 +++- ...load_real_functions_with_include_paths.php | 59 +++++++++++++++++++ ...moved_include_paths_and_autolad_files.php} | 0 .../Fixtures/include_paths_functions.php | 15 +++++ ...ude_paths_functions_with_removed_extra.php | 11 ++++ 6 files changed, 103 insertions(+), 8 deletions(-) create mode 100644 tests/Composer/Test/Autoload/Fixtures/autoload_real_functions_with_include_paths.php rename tests/Composer/Test/Autoload/Fixtures/{autoload_real_functions_with_removed_extra.php => autoload_real_functions_with_removed_include_paths_and_autolad_files.php} (100%) create mode 100644 tests/Composer/Test/Autoload/Fixtures/include_paths_functions.php create mode 100644 tests/Composer/Test/Autoload/Fixtures/include_paths_functions_with_removed_extra.php diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 90d17bcf3..7227166a8 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -252,17 +252,20 @@ EOF; file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile); file_put_contents($targetDir.'/autoload_psr4.php', $psr4File); file_put_contents($targetDir.'/autoload_classmap.php', $classmapFile); - if ($includePathFile = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) { - file_put_contents($targetDir.'/include_paths.php', $includePathFile); + $includePathFilePath = $targetDir.'/include_paths.php'; + if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) { + file_put_contents($includePathFilePath, $includePathFileContents); + } else if (file_exists($includePathFilePath)){ + unlink($includePathFilePath); } $includeFilesFilePath = $targetDir.'/autoload_files.php'; - if ($includeFilesFile = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) { - file_put_contents($includeFilesFilePath, $includeFilesFile); + if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) { + file_put_contents($includeFilesFilePath, $includeFilesFileContents); } else if (file_exists($includeFilesFilePath)) { unlink($includeFilesFilePath); } file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix)); - file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFile, $targetDirLoader, (bool) $includeFilesFile, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $classMapAuthoritative)); + file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $classMapAuthoritative)); $this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php'); $this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE'); diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index 08f9cc09d..007f16363 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -589,6 +589,7 @@ class AutoloadGeneratorTest extends TestCase { $autoloadPackage = new Package('a', '1.0', '1.0'); $autoloadPackage->setAutoload(array('files' => array('root.php'))); + $autoloadPackage->setIncludePaths(array('/lib', '/src')); $notAutoloadPackage = new Package('a', '1.0', '1.0'); @@ -597,8 +598,11 @@ class AutoloadGeneratorTest extends TestCase $autoloadPackages[] = $b = new Package('b/b', '1.0', '1.0'); $autoloadPackages[] = $c = new Package('c/c', '1.0', '1.0'); $a->setAutoload(array('files' => array('test.php'))); + $a->setIncludePaths(array('lib1', 'src1')); $b->setAutoload(array('files' => array('test2.php'))); + $b->setIncludePaths(array('lib2')); $c->setAutoload(array('files' => array('test3.php', 'foo/bar/test4.php'))); + $c->setIncludePaths(array('lib3')); $c->setTargetDir('foo/bar'); $notAutoloadPackages = array(); @@ -629,18 +633,21 @@ class AutoloadGeneratorTest extends TestCase $this->generator->dump($this->config, $this->repository, $autoloadPackage, $this->im, 'composer', false, 'FilesAutoload'); $this->assertFileEquals(__DIR__.'/Fixtures/autoload_functions.php', $this->vendorDir.'/autoload.php'); - $this->assertFileEquals(__DIR__.'/Fixtures/autoload_real_functions.php', $this->vendorDir.'/composer/autoload_real.php'); + $this->assertFileEquals(__DIR__.'/Fixtures/autoload_real_functions_with_include_paths.php', $this->vendorDir.'/composer/autoload_real.php'); $this->assertFileEquals(__DIR__.'/Fixtures/autoload_files_functions.php', $this->vendorDir.'/composer/autoload_files.php'); + $this->assertFileEquals(__DIR__.'/Fixtures/include_paths_functions.php', $this->vendorDir.'/composer/include_paths.php'); $this->generator->dump($this->config, $this->repository, $autoloadPackage, $this->im, 'composer', false, 'FilesAutoload'); $this->assertFileEquals(__DIR__.'/Fixtures/autoload_functions.php', $this->vendorDir.'/autoload.php'); - $this->assertFileEquals(__DIR__.'/Fixtures/autoload_real_functions.php', $this->vendorDir.'/composer/autoload_real.php'); + $this->assertFileEquals(__DIR__.'/Fixtures/autoload_real_functions_with_include_paths.php', $this->vendorDir.'/composer/autoload_real.php'); $this->assertFileEquals(__DIR__.'/Fixtures/autoload_files_functions_with_removed_extra.php', $this->vendorDir.'/composer/autoload_files.php'); + $this->assertFileEquals(__DIR__.'/Fixtures/include_paths_functions_with_removed_extra.php', $this->vendorDir.'/composer/include_paths.php'); $this->generator->dump($this->config, $this->repository, $notAutoloadPackage, $this->im, 'composer', false, 'FilesAutoload'); $this->assertFileEquals(__DIR__.'/Fixtures/autoload_functions.php', $this->vendorDir.'/autoload.php'); - $this->assertFileEquals(__DIR__.'/Fixtures/autoload_real_functions_with_removed_extra.php', $this->vendorDir.'/composer/autoload_real.php'); + $this->assertFileEquals(__DIR__.'/Fixtures/autoload_real_functions_with_removed_include_paths_and_autolad_files.php', $this->vendorDir.'/composer/autoload_real.php'); $this->assertFileNotExists($this->vendorDir.'/composer/autoload_files.php'); + $this->assertFileNotExists($this->vendorDir.'/composer/include_paths.php'); } public function testFilesAutoloadOrderByDependencies() diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_real_functions_with_include_paths.php b/tests/Composer/Test/Autoload/Fixtures/autoload_real_functions_with_include_paths.php new file mode 100644 index 000000000..68fb6ecbf --- /dev/null +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_real_functions_with_include_paths.php @@ -0,0 +1,59 @@ + $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + + $loader->register(true); + + $includeFiles = require __DIR__ . '/autoload_files.php'; + foreach ($includeFiles as $file) { + composerRequireFilesAutoload($file); + } + + return $loader; + } +} + +function composerRequireFilesAutoload($file) +{ + require $file; +} diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_real_functions_with_removed_extra.php b/tests/Composer/Test/Autoload/Fixtures/autoload_real_functions_with_removed_include_paths_and_autolad_files.php similarity index 100% rename from tests/Composer/Test/Autoload/Fixtures/autoload_real_functions_with_removed_extra.php rename to tests/Composer/Test/Autoload/Fixtures/autoload_real_functions_with_removed_include_paths_and_autolad_files.php diff --git a/tests/Composer/Test/Autoload/Fixtures/include_paths_functions.php b/tests/Composer/Test/Autoload/Fixtures/include_paths_functions.php new file mode 100644 index 000000000..f1095cf67 --- /dev/null +++ b/tests/Composer/Test/Autoload/Fixtures/include_paths_functions.php @@ -0,0 +1,15 @@ + Date: Sun, 16 Aug 2015 13:56:52 -0600 Subject: [PATCH 135/205] Add cli argument for classmap-authoritative Add a `--classmap-authoritative (-a)` argument to `composer install`, `composer update` and `composer dumpautoload`. This enables the same authoritative classmap behavior as the existing `classmap-authoritative` configuration setting. The option can be used for creating highly optimized production autoloaders via `composer install --no-dev --optimize-autoloader --classmap-authoritative` for projects where multiple autoloaders are present and unnecessary `file_exists` calls introduce performance issues. Closes #4361 --- doc/03-cli.md | 6 ++++ doc/06-config.md | 5 ++-- src/Composer/Autoload/AutoloadGenerator.php | 30 ++++++++++++++++--- src/Composer/Command/DumpAutoloadCommand.php | 7 +++-- src/Composer/Command/InstallCommand.php | 5 +++- src/Composer/Command/UpdateCommand.php | 5 +++- src/Composer/Installer.php | 25 ++++++++++++++++ .../Test/Autoload/AutoloadGeneratorTest.php | 24 +++++++-------- .../Autoload/Fixtures/autoload_classmap8.php | 12 ++++++++ 9 files changed, 96 insertions(+), 23 deletions(-) create mode 100644 tests/Composer/Test/Autoload/Fixtures/autoload_classmap8.php diff --git a/doc/03-cli.md b/doc/03-cli.md index 7864ea904..ee9a62028 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -97,6 +97,8 @@ resolution. * **--optimize-autoloader (-o):** Convert PSR-0/4 autoloading to classmap to get a faster autoloader. This is recommended especially for production, but can take a bit of time to run so it is currently not done by default. +* **--classmap-authoritative (-a):** Autoload classes from the classmap only. + Implicitly enables `--optimize-autoloader`. ## update @@ -140,6 +142,8 @@ php composer.phar update vendor/* * **--optimize-autoloader (-o):** Convert PSR-0/4 autoloading to classmap to get a faster autoloader. This is recommended especially for production, but can take a bit of time to run so it is currently not done by default. +* **--classmap-authoritative (-a):** Autoload classes from the classmap only. + Implicitly enables `--optimize-autoloader`. * **--lock:** Only updates the lock file hash to suppress warning about the lock file being out of date. * **--with-dependencies:** Add also all dependencies of whitelisted packages to the whitelist. @@ -505,6 +509,8 @@ performance. * **--optimize (-o):** Convert PSR-0/4 autoloading to classmap to get a faster autoloader. This is recommended especially for production, but can take a bit of time to run so it is currently not done by default. +* **--classmap-authoritative (-a):** Autoload classes from the classmap only. + Implicitly enables `--optimize`. * **--no-dev:** Disables autoload-dev rules. ## clear-cache diff --git a/doc/06-config.md b/doc/06-config.md index 2564fefef..4716b93bb 100644 --- a/doc/06-config.md +++ b/doc/06-config.md @@ -119,9 +119,8 @@ Defaults to `false`. If `true`, always optimize when dumping the autoloader. ## classmap-authoritative -Defaults to `false`. If `true`, the Composer autoloader will not scan the -filesystem for classes that are not found in the class map. Implies -'optimize-autoloader'. +Defaults to `false`. If `true`, the Composer autoloader will only load classes +from the classmap. Implies `optimize-autoloader`. ## github-domains diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 7227166a8..4784aae12 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -38,8 +38,16 @@ class AutoloadGenerator */ private $io; + /** + * @var bool + */ private $devMode = false; + /** + * @var bool + */ + private $classMapAuthoritative = false; + public function __construct(EventDispatcher $eventDispatcher, IOInterface $io = null) { $this->eventDispatcher = $eventDispatcher; @@ -51,8 +59,23 @@ class AutoloadGenerator $this->devMode = (boolean) $devMode; } + /** + * Whether or not generated autoloader considers the class map + * authoritative. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = (boolean) $classMapAuthoritative; + } + public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '') { + if ($this->classMapAuthoritative) { + // Force scanPsr0Packages when classmap is authoritative + $scanPsr0Packages = true; + } $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, array(), array( 'optimize' => (bool) $scanPsr0Packages, )); @@ -63,7 +86,6 @@ class AutoloadGenerator $vendorPath = $filesystem->normalizePath(realpath($config->get('vendor-dir'))); $useGlobalIncludePath = (bool) $config->get('use-include-path'); $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true'; - $classMapAuthoritative = $config->get('classmap-authoritative'); $targetDir = $vendorPath.'/'.$targetDir; $filesystem->ensureDirectoryExists($targetDir); @@ -265,7 +287,7 @@ EOF; unlink($includeFilesFilePath); } file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix)); - file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $classMapAuthoritative)); + file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader)); $this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php'); $this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE'); @@ -476,7 +498,7 @@ return ComposerAutoloaderInit$suffix::getLoader(); AUTOLOAD; } - protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $classMapAuthoritative) + protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader) { // TODO the class ComposerAutoloaderInit should be revert to a closure // when APC has been fixed: @@ -553,7 +575,7 @@ PSR4; CLASSMAP; } - if ($classMapAuthoritative) { + if ($this->classMapAuthoritative) { $file .= <<<'CLASSMAPAUTHORITATIVE' $loader->setClassMapAuthoritative(true); diff --git a/src/Composer/Command/DumpAutoloadCommand.php b/src/Composer/Command/DumpAutoloadCommand.php index f560953b8..c452d1fb4 100644 --- a/src/Composer/Command/DumpAutoloadCommand.php +++ b/src/Composer/Command/DumpAutoloadCommand.php @@ -31,6 +31,7 @@ class DumpAutoloadCommand extends Command ->setDescription('Dumps the autoloader') ->setDefinition(array( new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.'), + new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize`.'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules.'), )) ->setHelp(<<getPackage(); $config = $composer->getConfig(); - $optimize = $input->getOption('optimize') || $config->get('optimize-autoloader') || $config->get('classmap-authoritative'); + $optimize = $input->getOption('optimize') || $config->get('optimize-autoloader'); + $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative'); - if ($optimize) { + if ($optimize || $authoritative) { $this->getIO()->writeError('Generating optimized autoload files'); } else { $this->getIO()->writeError('Generating autoload files'); @@ -62,6 +64,7 @@ EOT $generator = $composer->getAutoloadGenerator(); $generator->setDevMode(!$input->getOption('no-dev')); + $generator->setClassMapAuthoritative($authoritative); $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize); } } diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index e548b8d69..2494fdd67 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -46,6 +46,7 @@ class InstallCommand extends Command new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'), + new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'), new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.'), )) @@ -110,7 +111,8 @@ EOT $preferDist = $input->getOption('prefer-dist'); } - $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader') || $config->get('classmap-authoritative'); + $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader'); + $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative'); $install ->setDryRun($input->getOption('dry-run')) @@ -121,6 +123,7 @@ EOT ->setDumpAutoloader(!$input->getOption('no-autoloader')) ->setRunScripts(!$input->getOption('no-scripts')) ->setOptimizeAutoloader($optimize) + ->setClassMapAuthoritative($authoritative) ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs')) ; diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index 579236143..c6828d10b 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -47,6 +47,7 @@ class UpdateCommand extends Command new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also all dependencies of whitelisted packages to the whitelist.'), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'), + new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'), new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'), new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'), @@ -114,7 +115,8 @@ EOT $preferDist = $input->getOption('prefer-dist'); } - $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader') || $config->get('classmap-authoritative'); + $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader'); + $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative'); $install ->setDryRun($input->getOption('dry-run')) @@ -125,6 +127,7 @@ EOT ->setDumpAutoloader(!$input->getOption('no-autoloader')) ->setRunScripts(!$input->getOption('no-scripts')) ->setOptimizeAutoloader($optimize) + ->setClassMapAuthoritative($authoritative) ->setUpdate(true) ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $input->getArgument('packages')) ->setWhitelistDependencies($input->getOption('with-dependencies')) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 8aecea402..3d06cd5eb 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -103,6 +103,7 @@ class Installer protected $preferSource = false; protected $preferDist = false; protected $optimizeAutoloader = false; + protected $classMapAuthoritative = false; protected $devMode = false; protected $dryRun = false; protected $verbose = false; @@ -335,6 +336,7 @@ class Installer } $this->autoloadGenerator->setDevMode($this->devMode); + $this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative); $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader); } @@ -1308,6 +1310,29 @@ class Installer public function setOptimizeAutoloader($optimizeAutoloader = false) { $this->optimizeAutoloader = (boolean) $optimizeAutoloader; + if (!$this->optimizeAutoloader) { + // Force classMapAuthoritative off when not optimizing the + // autoloader + $this->setClassMapAuthoritative(false); + } + + return $this; + } + + /** + * Whether or not generated autoloader considers the class map + * authoritative. + * + * @param bool $classMapAuthoritative + * @return Installer + */ + public function setClassMapAuthoritative($classMapAuthoritative = false) + { + $this->classMapAuthoritative = (boolean) $classMapAuthoritative; + if ($this->classMapAuthoritative) { + // Force optimizeAutoloader when classmap is authoritative + $this->setOptimizeAutoloader(true); + } return $this; } diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index 007f16363..b5f6e930b 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -512,35 +512,35 @@ class AutoloadGeneratorTest extends TestCase $packages[] = $a = new Package('a/a', '1.0', '1.0'); $packages[] = $b = new Package('b/b', '1.0', '1.0'); $packages[] = $c = new Package('c/c', '1.0', '1.0'); - $a->setAutoload(array('classmap' => array(''))); - $b->setAutoload(array('classmap' => array('test.php'))); - $c->setAutoload(array('classmap' => array('./'))); + $a->setAutoload(array('psr-4' => array('' => 'src/'))); + $b->setAutoload(array('psr-4' => array('' => './'))); + $c->setAutoload(array('psr-4' => array('' => 'foo/'))); $this->repository->expects($this->once()) ->method('getCanonicalPackages') ->will($this->returnValue($packages)); - $this->configValueMap['classmap-authoritative'] = true; - $this->fs->ensureDirectoryExists($this->vendorDir.'/composer'); $this->fs->ensureDirectoryExists($this->vendorDir.'/a/a/src'); $this->fs->ensureDirectoryExists($this->vendorDir.'/b/b'); $this->fs->ensureDirectoryExists($this->vendorDir.'/c/c/foo'); - file_put_contents($this->vendorDir.'/a/a/src/a.php', 'vendorDir.'/b/b/test.php', 'vendorDir.'/c/c/foo/test.php', 'vendorDir.'/a/a/src/ClassMapFoo.php', 'vendorDir.'/b/b/ClassMapBar.php', 'vendorDir.'/c/c/foo/ClassMapBaz.php', 'generator->setClassMapAuthoritative(true); $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, '_7'); + $this->assertTrue(file_exists($this->vendorDir.'/composer/autoload_classmap.php'), "ClassMap file needs to be generated."); $this->assertEquals( array( - 'ClassMapBar' => $this->vendorDir.'/b/b/test.php', - 'ClassMapBaz' => $this->vendorDir.'/c/c/foo/test.php', - 'ClassMapFoo' => $this->vendorDir.'/a/a/src/a.php', + 'ClassMapBar' => $this->vendorDir.'/b/b/ClassMapBar.php', + 'ClassMapBaz' => $this->vendorDir.'/c/c/foo/ClassMapBaz.php', + 'ClassMapFoo' => $this->vendorDir.'/a/a/src/ClassMapFoo.php', ), include $this->vendorDir.'/composer/autoload_classmap.php' ); - $this->assertAutoloadFiles('classmap5', $this->vendorDir.'/composer', 'classmap'); + $this->assertAutoloadFiles('classmap8', $this->vendorDir.'/composer', 'classmap'); $this->assertContains('$loader->setClassMapAuthoritative(true);', file_get_contents($this->vendorDir.'/composer/autoload_real.php')); } diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_classmap8.php b/tests/Composer/Test/Autoload/Fixtures/autoload_classmap8.php new file mode 100644 index 000000000..0a40d114c --- /dev/null +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_classmap8.php @@ -0,0 +1,12 @@ + $vendorDir . '/b/b/ClassMapBar.php', + 'ClassMapBaz' => $vendorDir . '/c/c/foo/ClassMapBaz.php', + 'ClassMapFoo' => $vendorDir . '/a/a/src/ClassMapFoo.php', +); From 71cb5876111558aafce7a867ff8b9d32328174cc Mon Sep 17 00:00:00 2001 From: Bryan Davis Date: Tue, 18 Aug 2015 09:54:56 -0600 Subject: [PATCH 136/205] Add autoloader cli options to `require` and `remove` Update the `composer require` and `composer remove` commands to support the `--optimize-autoloader` and `--classmap-authoritative` cli options and associated configuration settings. All cli entry points that invoke `Installer::run()` or `AutoloadGenerator::dump()` now have consistent support for these autoloader optimization flags. --- doc/03-cli.md | 10 ++++++++++ src/Composer/Command/RemoveCommand.php | 7 +++++++ src/Composer/Command/RequireCommand.php | 6 ++++++ 3 files changed, 23 insertions(+) diff --git a/doc/03-cli.md b/doc/03-cli.md index ee9a62028..b7a908f3d 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -185,6 +185,11 @@ php composer.phar require vendor/package:2.* vendor/package2:dev-master * **--update-with-dependencies:** Also update dependencies of the newly required packages. * **--sort-packages:** Keep packages sorted in `composer.json`. +* **--optimize-autoloader (-o):** Convert PSR-0/4 autoloading to classmap to + get a faster autoloader. This is recommended especially for production, but + can take a bit of time to run so it is currently not done by default. +* **--classmap-authoritative (-a):** Autoload classes from the classmap only. + Implicitly enables `--optimize-autoloader`. ## remove @@ -208,6 +213,11 @@ uninstalled. terminals or scripts which don't handle backspace characters. * **--update-no-dev:** Run the dependency update with the --no-dev option. * **--update-with-dependencies:** Also update dependencies of the removed packages. +* **--optimize-autoloader (-o):** Convert PSR-0/4 autoloading to classmap to + get a faster autoloader. This is recommended especially for production, but + can take a bit of time to run so it is currently not done by default. +* **--classmap-authoritative (-a):** Autoload classes from the classmap only. + Implicitly enables `--optimize-autoloader`. ## global diff --git a/src/Composer/Command/RemoveCommand.php b/src/Composer/Command/RemoveCommand.php index 3779b09e9..3f507775f 100644 --- a/src/Composer/Command/RemoveCommand.php +++ b/src/Composer/Command/RemoveCommand.php @@ -42,6 +42,8 @@ class RemoveCommand extends Command new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'), new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies.'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'), + new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'), + new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'), )) ->setHelp(<<remove command removes a package from the current @@ -99,9 +101,14 @@ EOT $install = Installer::create($io, $composer); $updateDevMode = !$input->getOption('update-no-dev'); + $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader'); + $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative'); + $install ->setVerbose($input->getOption('verbose')) ->setDevMode($updateDevMode) + ->setOptimizeAutoloader($optimize) + ->setClassMapAuthoritative($authoritative) ->setUpdate(true) ->setUpdateWhitelist($packages) ->setWhitelistDependencies($input->getOption('update-with-dependencies')) diff --git a/src/Composer/Command/RequireCommand.php b/src/Composer/Command/RequireCommand.php index 82401ffb2..ed3a9d624 100644 --- a/src/Composer/Command/RequireCommand.php +++ b/src/Composer/Command/RequireCommand.php @@ -48,6 +48,8 @@ class RequireCommand extends InitCommand new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies.'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'), new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages when adding/updating a new dependency'), + new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'), + new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'), )) ->setHelp(<<getOption('update-no-dev'); + $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader'); + $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative'); // Update packages $this->resetComposer(); @@ -149,6 +153,8 @@ EOT ->setPreferSource($input->getOption('prefer-source')) ->setPreferDist($input->getOption('prefer-dist')) ->setDevMode($updateDevMode) + ->setOptimizeAutoloader($optimize) + ->setClassMapAuthoritative($authoritative) ->setUpdate(true) ->setUpdateWhitelist(array_keys($requirements)) ->setWhitelistDependencies($input->getOption('update-with-dependencies')) From cae8ed476c87f73466e3a78adc3802fc2f58380d Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Thu, 20 Aug 2015 13:02:17 +0200 Subject: [PATCH 137/205] Update the config of the apt addon to the new syntax --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b1aa4414d..383ad0334 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,9 @@ cache: - $HOME/.composer/cache addons: - apt_packages: - - parallel + apt: + packages: + - parallel php: - 5.3.3 From bfb83f1fb7ba811baf9508a6d337fa5608ce4379 Mon Sep 17 00:00:00 2001 From: Zsolt Szeberenyi Date: Fri, 21 Aug 2015 16:54:28 +1200 Subject: [PATCH 138/205] Add name and version to the relevant fields, move content hash checking to the Locker --- src/Composer/Factory.php | 36 +-------------- src/Composer/Package/Locker.php | 50 +++++++++++++++++---- tests/Composer/Test/InstallerTest.php | 4 +- tests/Composer/Test/Package/LockerTest.php | 51 +++++++++++++++------- 4 files changed, 81 insertions(+), 60 deletions(-) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 8a2a6a815..6a206d039 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -306,7 +306,7 @@ class Factory $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION) ? substr($composerFile, 0, -4).'lock' : $composerFile . '.lock'; - $locker = new Package\Locker($io, new JsonFile($lockFile, new RemoteFilesystem($io, $config)), $rm, $im, md5_file($composerFile), $this->getContentHash($composerFile)); + $locker = new Package\Locker($io, new JsonFile($lockFile, new RemoteFilesystem($io, $config)), $rm, $im, file_get_contents($composerFile)); $composer->setLocker($locker); } @@ -485,38 +485,4 @@ class Factory return $factory->createComposer($io, $config, $disablePlugins); } - - /** - * Returns the md5 hash of the sorted content of the composer file. - * - * @param string $composerFilePath Path to the composer file. - * - * @return string - */ - private function getContentHash($composerFilePath) - { - $content = json_decode(file_get_contents($composerFilePath), true); - - $relevantKeys = array( - 'require', - 'require-dev', - 'conflict', - 'replace', - 'provide', - 'suggest', - 'minimum-stability', - 'prefer-stable', - 'repositories', - 'extra', - ); - - $relevantContent = array(); - - foreach (array_intersect($relevantKeys, array_keys($content)) as $key) { - $relevantContent[$key] = $content[$key]; - } - - ksort($relevantContent); - return md5(json_encode($relevantContent)); - } } diff --git a/src/Composer/Package/Locker.php b/src/Composer/Package/Locker.php index ef5e4fc75..6b6d913ff 100644 --- a/src/Composer/Package/Locker.php +++ b/src/Composer/Package/Locker.php @@ -45,19 +45,18 @@ class Locker * Initializes packages locker. * * @param IOInterface $io - * @param JsonFile $lockFile lockfile loader - * @param RepositoryManager $repositoryManager repository manager instance - * @param InstallationManager $installationManager installation manager instance - * @param string $hash unique hash of the current composer configuration - * @param string $contentHash unique hash of the content of the current composer configuration + * @param JsonFile $lockFile lockfile loader + * @param RepositoryManager $repositoryManager repository manager instance + * @param InstallationManager $installationManager installation manager instance + * @param string $composerFileContents The contents of the composer file */ - public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $hash, $contentHash) + public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $composerFileContents) { $this->lockFile = $lockFile; $this->repositoryManager = $repositoryManager; $this->installationManager = $installationManager; - $this->hash = $hash; - $this->contentHash = $contentHash; + $this->hash = md5($composerFileContents); + $this->contentHash = $this->getContentHash($composerFileContents); $this->loader = new ArrayLoader(null, true); $this->dumper = new ArrayDumper(); $this->process = new ProcessExecutor($io); @@ -387,4 +386,39 @@ class Locker return $datetime ? $datetime->format('Y-m-d H:i:s') : null; } + + /** + * Returns the md5 hash of the sorted content of the composer file. + * + * @param string $composerFileContents The contents of the composer file. + * + * @return string + */ + private function getContentHash($composerFileContents) + { + $content = json_decode($composerFileContents, true); + + $relevantKeys = array( + 'require', + 'require-dev', + 'conflict', + 'replace', + 'provide', + 'minimum-stability', + 'prefer-stable', + 'repositories', + 'extra', + 'version', + 'name', + ); + + $relevantContent = array(); + + foreach (array_intersect($relevantKeys, array_keys($content)) as $key) { + $relevantContent[$key] = $content[$key]; + } + + ksort($relevantContent); + return md5(json_encode($relevantContent)); + } } diff --git a/tests/Composer/Test/InstallerTest.php b/tests/Composer/Test/InstallerTest.php index 0a1dff0e4..4b8aa28f9 100644 --- a/tests/Composer/Test/InstallerTest.php +++ b/tests/Composer/Test/InstallerTest.php @@ -191,8 +191,8 @@ class InstallerTest extends TestCase })); } - $hash = md5(json_encode($composerConfig)); - $locker = new Locker($io, $lockJsonMock, $repositoryManager, $composer->getInstallationManager(), $hash, $hash); + $contents = json_encode($composerConfig); + $locker = new Locker($io, $lockJsonMock, $repositoryManager, $composer->getInstallationManager(), $contents); $composer->setLocker($locker); $eventDispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')->disableOriginalConstructor()->getMock(); diff --git a/tests/Composer/Test/Package/LockerTest.php b/tests/Composer/Test/Package/LockerTest.php index 6d0937ef1..960d4f9c5 100644 --- a/tests/Composer/Test/Package/LockerTest.php +++ b/tests/Composer/Test/Package/LockerTest.php @@ -20,7 +20,8 @@ class LockerTest extends \PHPUnit_Framework_TestCase public function testIsLocked() { $json = $this->createJsonFileMock(); - $locker = new Locker(new NullIO, $json, $this->createRepositoryManagerMock(), $this->createInstallationManagerMock(), 'md5', 'contentMd5'); + $locker = new Locker(new NullIO, $json, $this->createRepositoryManagerMock(), $this->createInstallationManagerMock(), + $this->getJsonContent()); $json ->expects($this->any()) @@ -40,7 +41,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase $repo = $this->createRepositoryManagerMock(); $inst = $this->createInstallationManagerMock(); - $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5'); + $locker = new Locker(new NullIO, $json, $repo, $inst, $this->getJsonContent()); $json ->expects($this->once()) @@ -58,7 +59,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase $repo = $this->createRepositoryManagerMock(); $inst = $this->createInstallationManagerMock(); - $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5'); + $locker = new Locker(new NullIO, $json, $repo, $inst, $this->getJsonContent()); $json ->expects($this->once()) @@ -85,7 +86,8 @@ class LockerTest extends \PHPUnit_Framework_TestCase $repo = $this->createRepositoryManagerMock(); $inst = $this->createInstallationManagerMock(); - $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5'); + $jsonContent = $this->getJsonContent() . ' '; + $locker = new Locker(new NullIO, $json, $repo, $inst, $jsonContent); $package1 = $this->createPackageMock(); $package2 = $this->createPackageMock(); @@ -116,6 +118,9 @@ class LockerTest extends \PHPUnit_Framework_TestCase ->method('getVersion') ->will($this->returnValue('0.1.10.0')); + $hash = md5($jsonContent); + $contentHash = md5(trim($jsonContent)); + $json ->expects($this->once()) ->method('write') @@ -123,8 +128,8 @@ class LockerTest extends \PHPUnit_Framework_TestCase '_readme' => array('This file locks the dependencies of your project to a known state', 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file', 'This file is @gener'.'ated automatically'), - 'hash' => 'md5', - 'content-hash' => 'contentMd5', + 'hash' => $hash, + 'content-hash' => $contentHash, 'packages' => array( array('name' => 'pkg1', 'version' => '1.0.0-beta'), array('name' => 'pkg2', 'version' => '0.1.10') @@ -149,7 +154,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase $repo = $this->createRepositoryManagerMock(); $inst = $this->createInstallationManagerMock(); - $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'md5'); + $locker = new Locker(new NullIO, $json, $repo, $inst, $this->getJsonContent()); $package1 = $this->createPackageMock(); $package1 @@ -168,12 +173,13 @@ class LockerTest extends \PHPUnit_Framework_TestCase $repo = $this->createRepositoryManagerMock(); $inst = $this->createInstallationManagerMock(); - $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5'); + $jsonContent = $this->getJsonContent(); + $locker = new Locker(new NullIO, $json, $repo, $inst, $jsonContent); $json ->expects($this->once()) ->method('read') - ->will($this->returnValue(array('hash' => 'md5'))); + ->will($this->returnValue(array('hash' => md5($jsonContent)))); $this->assertTrue($locker->isFresh()); } @@ -184,12 +190,12 @@ class LockerTest extends \PHPUnit_Framework_TestCase $repo = $this->createRepositoryManagerMock(); $inst = $this->createInstallationManagerMock(); - $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5'); + $locker = new Locker(new NullIO, $json, $repo, $inst, $this->getJsonContent()); $json ->expects($this->once()) ->method('read') - ->will($this->returnValue(array('hash' => 'oldmd5'))); + ->will($this->returnValue(array('hash' => $this->getJsonContent(array('name' => 'test2'))))); $this->assertFalse($locker->isFresh()); } @@ -200,12 +206,13 @@ class LockerTest extends \PHPUnit_Framework_TestCase $repo = $this->createRepositoryManagerMock(); $inst = $this->createInstallationManagerMock(); - $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5'); + $jsonContent = $this->getJsonContent(); + $locker = new Locker(new NullIO, $json, $repo, $inst, $jsonContent); $json ->expects($this->once()) ->method('read') - ->will($this->returnValue(array('hash' => 'oldMd5', 'content-hash' => 'contentMd5'))); + ->will($this->returnValue(array('hash' => md5($jsonContent . ' '), 'content-hash' => md5($jsonContent)))); $this->assertTrue($locker->isFresh()); } @@ -216,12 +223,14 @@ class LockerTest extends \PHPUnit_Framework_TestCase $repo = $this->createRepositoryManagerMock(); $inst = $this->createInstallationManagerMock(); - $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5'); + $locker = new Locker(new NullIO, $json, $repo, $inst, $this->getJsonContent()); + + $differentHash = md5($this->getJsonContent(['name' => 'test2'])); $json ->expects($this->once()) ->method('read') - ->will($this->returnValue(array('hash' => 'md5', 'content-hash' => 'oldMd5'))); + ->will($this->returnValue(array('hash' => $differentHash, 'content-hash' => $differentHash))); $this->assertFalse($locker->isFresh()); } @@ -260,4 +269,16 @@ class LockerTest extends \PHPUnit_Framework_TestCase return $this->getMockBuilder('Composer\Package\PackageInterface') ->getMock(); } + + private function getJsonContent(array $customData = array()) + { + $data = array_merge(array( + 'minimum-stability' => 'beta', + 'name' => 'test', + ), $customData); + + ksort($data); + + return json_encode($data); + } } From 62630e5c69c3fcc10dc1b15c4222724caa76f1d1 Mon Sep 17 00:00:00 2001 From: Zsolt Szeberenyi Date: Fri, 21 Aug 2015 16:55:44 +1200 Subject: [PATCH 139/205] Fix strict comparison of the content hash --- src/Composer/Package/Locker.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Package/Locker.php b/src/Composer/Package/Locker.php index 6b6d913ff..bbd45012d 100644 --- a/src/Composer/Package/Locker.php +++ b/src/Composer/Package/Locker.php @@ -89,7 +89,7 @@ class Locker if (!empty($lock['content-hash'])) { // There is a content hash key, use that instead of the file hash - return $this->contentHash == $lock['content-hash']; + return $this->contentHash === $lock['content-hash']; } return $this->hash === $lock['hash']; From d7a94bda1bcd50bae9080533bdc4b0dccbd0ca31 Mon Sep 17 00:00:00 2001 From: Zsolt Szeberenyi Date: Fri, 21 Aug 2015 16:57:31 +1200 Subject: [PATCH 140/205] Change short array syntax to long for 5.3 compatibility --- tests/Composer/Test/Package/LockerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Composer/Test/Package/LockerTest.php b/tests/Composer/Test/Package/LockerTest.php index 960d4f9c5..2a45b1c66 100644 --- a/tests/Composer/Test/Package/LockerTest.php +++ b/tests/Composer/Test/Package/LockerTest.php @@ -225,7 +225,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase $locker = new Locker(new NullIO, $json, $repo, $inst, $this->getJsonContent()); - $differentHash = md5($this->getJsonContent(['name' => 'test2'])); + $differentHash = md5($this->getJsonContent(array('name' => 'test2'))); $json ->expects($this->once()) From bb81e3721a20b7238acb228f506aa461cad7bb49 Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Tue, 25 Aug 2015 09:19:10 +0100 Subject: [PATCH 141/205] Move the `proc_open` test in setUp --- .../Package/Version/VersionGuesserTest.php | 29 +++---------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/tests/Composer/Test/Package/Version/VersionGuesserTest.php b/tests/Composer/Test/Package/Version/VersionGuesserTest.php index d6437f5e7..2c5db1ff5 100644 --- a/tests/Composer/Test/Package/Version/VersionGuesserTest.php +++ b/tests/Composer/Test/Package/Version/VersionGuesserTest.php @@ -13,25 +13,22 @@ namespace Composer\Test\Package\Version; use Composer\Config; -use Composer\Package\Loader\RootPackageLoader; use Composer\Package\Version\VersionGuesser; use Composer\Package\Version\VersionParser; class VersionGuesserTest extends \PHPUnit_Framework_TestCase { - public function testDetachedHeadBecomesDevHash() + public function setUp() { if (!function_exists('proc_open')) { $this->markTestSkipped('proc_open() is not available'); } + } + public function testDetachedHeadBecomesDevHash() + { $commitHash = '03a15d220da53c52eddd5f32ffca64a7b3801bea'; - $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') - ->disableOriginalConstructor() - ->getMock() - ; - $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') ->setMethods(array('execute')) ->disableArgumentCloning() @@ -69,15 +66,6 @@ class VersionGuesserTest extends \PHPUnit_Framework_TestCase public function testTagBecomesVersion() { - if (!function_exists('proc_open')) { - $this->markTestSkipped('proc_open() is not available'); - } - - $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') - ->disableOriginalConstructor() - ->getMock() - ; - $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') ->setMethods(array('execute')) ->disableArgumentCloning() @@ -108,15 +96,6 @@ class VersionGuesserTest extends \PHPUnit_Framework_TestCase public function testInvalidTagBecomesVersion() { - if (!function_exists('proc_open')) { - $this->markTestSkipped('proc_open() is not available'); - } - - $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') - ->disableOriginalConstructor() - ->getMock() - ; - $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') ->setMethods(array('execute')) ->disableArgumentCloning() From 6c1615330290082ef7f08919ed1475529f0b8f5b Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Tue, 25 Aug 2015 22:06:48 +0100 Subject: [PATCH 142/205] Added repository tests --- src/Composer/Repository/PathRepository.php | 12 ++-- .../Fixtures/path/with-version/composer.json | 4 ++ .../path/without-version/composer.json | 3 + .../Test/Repository/PathRepositoryTest.php | 62 +++++++++++++++++++ 4 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 tests/Composer/Test/Repository/Fixtures/path/with-version/composer.json create mode 100644 tests/Composer/Test/Repository/Fixtures/path/without-version/composer.json create mode 100644 tests/Composer/Test/Repository/PathRepositoryTest.php diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index cdadbb518..a907c5adb 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -16,6 +16,7 @@ use Composer\Config; use Composer\IO\IOInterface; use Composer\Json\JsonFile; use Composer\Package\Loader\ArrayLoader; +use Composer\Package\Loader\LoaderInterface; use Composer\Package\Version\VersionGuesser; use Composer\Package\Version\VersionParser; use Composer\Util\ProcessExecutor; @@ -83,19 +84,22 @@ class PathRepository extends ArrayRepository * @param array $packageConfig * @param IOInterface $io * @param Config $config + * @param LoaderInterface $loader + * @param Filesystem $filesystem + * @param VersionGuesser $versionGuesser */ - public function __construct(array $packageConfig, IOInterface $io, Config $config) + public function __construct(array $packageConfig, IOInterface $io, Config $config, LoaderInterface $loader = null, Filesystem $filesystem = null, VersionGuesser $versionGuesser = null) { if (!isset($packageConfig['url'])) { throw new \RuntimeException('You must specify the `url` configuration for the path repository'); } - $this->fileSystem = new Filesystem(); - $this->loader = new ArrayLoader(); + $this->fileSystem = $filesystem ?: new Filesystem(); + $this->loader = $loader ?: new ArrayLoader(); $this->config = $config; $this->packageConfig = $packageConfig; $this->path = realpath(rtrim($packageConfig['url'], '/')) . '/'; - $this->versionGuesser = new VersionGuesser(new ProcessExecutor($io), new VersionParser(), $this->path); + $this->versionGuesser = $versionGuesser ?: new VersionGuesser(new ProcessExecutor($io), new VersionParser(), $this->path); } /** diff --git a/tests/Composer/Test/Repository/Fixtures/path/with-version/composer.json b/tests/Composer/Test/Repository/Fixtures/path/with-version/composer.json new file mode 100644 index 000000000..fa853d690 --- /dev/null +++ b/tests/Composer/Test/Repository/Fixtures/path/with-version/composer.json @@ -0,0 +1,4 @@ +{ + "name": "test/path", + "version": "0.0.2" +} \ No newline at end of file diff --git a/tests/Composer/Test/Repository/Fixtures/path/without-version/composer.json b/tests/Composer/Test/Repository/Fixtures/path/without-version/composer.json new file mode 100644 index 000000000..2fcbad12a --- /dev/null +++ b/tests/Composer/Test/Repository/Fixtures/path/without-version/composer.json @@ -0,0 +1,3 @@ +{ + "name": "test/path" +} \ No newline at end of file diff --git a/tests/Composer/Test/Repository/PathRepositoryTest.php b/tests/Composer/Test/Repository/PathRepositoryTest.php new file mode 100644 index 000000000..fb64e458b --- /dev/null +++ b/tests/Composer/Test/Repository/PathRepositoryTest.php @@ -0,0 +1,62 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Repository; + +use Composer\Package\Loader\ArrayLoader; +use Composer\Package\Version\VersionParser; +use Composer\TestCase; +use Composer\IO\NullIO; +use Composer\Config; +use Composer\Package\BasePackage; + +class PathRepositoryTest extends TestCase +{ + public function testLoadPackageFromFileSystemWithVersion() + { + $ioInterface = $this->getMockBuilder('Composer\IO\IOInterface') + ->getMock(); + + $config = new \Composer\Config(); + $loader = new ArrayLoader(new VersionParser()); + $versionGuesser = null; + + $repositoryUrl = implode(DIRECTORY_SEPARATOR, array(__DIR__, 'Fixtures', 'path', 'with-version')); + $repository = new PathRepository(array('url' => $repositoryUrl), $ioInterface, $config, $loader); + $repository->getPackages(); + + $this->assertEquals(1, $repository->count()); + $this->assertTrue($repository->hasPackage($this->getPackage('test/path', '0.0.2'))); + } + + public function testLoadPackageFromFileSystemWithoutVersion() + { + $ioInterface = $this->getMockBuilder('Composer\IO\IOInterface') + ->getMock(); + + $config = new \Composer\Config(); + $loader = new ArrayLoader(new VersionParser()); + $versionGuesser = null; + + $repositoryUrl = implode(DIRECTORY_SEPARATOR, array(__DIR__, 'Fixtures', 'path', 'without-version')); + $repository = new PathRepository(array('url' => $repositoryUrl), $ioInterface, $config, $loader); + $packages = $repository->getPackages(); + + $this->assertEquals(1, $repository->count()); + + $package = $packages[0]; + $this->assertEquals('test/path', $package->getName()); + + $packageVersion = $package->getVersion(); + $this->assertTrue(!empty($packageVersion)); + } +} From dd7243fc0118795f72f52f1c82a8325703275bee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Hern=C3=A1ndez?= Date: Wed, 26 Aug 2015 13:08:40 +0200 Subject: [PATCH 143/205] Archive command shows created package path --- src/Composer/Command/ArchiveCommand.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Composer/Command/ArchiveCommand.php b/src/Composer/Command/ArchiveCommand.php index b7c039510..b9cdf03cc 100644 --- a/src/Composer/Command/ArchiveCommand.php +++ b/src/Composer/Command/ArchiveCommand.php @@ -105,7 +105,8 @@ EOT } $io->writeError('Creating the archive into "'.$dest.'".'); - $archiveManager->archive($package, $format, $dest); + $packagePath = $archiveManager->archive($package, $format, $dest); + $io->writeError('Created archive file path: "'.$packagePath.'"'); return 0; } From afd98b74f13b9def1b2447f16fd0bfd4d96dff94 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 31 Aug 2015 10:58:25 +0100 Subject: [PATCH 144/205] Fix handling of www.github.com in GitHubDriver, fixes composer/packagist#572 --- src/Composer/Repository/Vcs/GitHubDriver.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Composer/Repository/Vcs/GitHubDriver.php b/src/Composer/Repository/Vcs/GitHubDriver.php index fd2e71545..517012751 100644 --- a/src/Composer/Repository/Vcs/GitHubDriver.php +++ b/src/Composer/Repository/Vcs/GitHubDriver.php @@ -50,6 +50,9 @@ class GitHubDriver extends VcsDriver $this->owner = $match[3]; $this->repository = $match[4]; $this->originUrl = !empty($match[1]) ? $match[1] : $match[2]; + if ($this->originUrl === 'www.github.com') { + $this->originUrl = 'github.com'; + } $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository); if (isset($this->repoConfig['no-api']) && $this->repoConfig['no-api']) { @@ -260,7 +263,7 @@ class GitHubDriver extends VcsDriver } $originUrl = !empty($matches[2]) ? $matches[2] : $matches[3]; - if (!in_array($originUrl, $config->get('github-domains'))) { + if (!in_array(preg_replace('{^www\.}i', '', $originUrl), $config->get('github-domains'))) { return false; } From d19aeab55c3b8e7bf350b2e2dbb64966e5c40820 Mon Sep 17 00:00:00 2001 From: Daniel Fahlke Date: Sat, 5 Sep 2015 11:46:02 +0200 Subject: [PATCH 145/205] add another case when package is not found occurred for my when I wanted to update a meta package, where nearly **ALL** dependencies changed their version. --- doc/articles/troubleshooting.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/articles/troubleshooting.md b/doc/articles/troubleshooting.md index bc2aeb15f..2fb9e7b1a 100644 --- a/doc/articles/troubleshooting.md +++ b/doc/articles/troubleshooting.md @@ -43,6 +43,10 @@ This is a list of common pitfalls on using Composer, and how to avoid them. 5. If you are updating to a recently published version of a package, be aware that Packagist has a delay of up to 1 minute before new packages are visible to Composer. +6. If you are updating a single package, it may depend on newer versions itself. + In this cases add the `--with-dependencies` argument **or** add all dependencies which + need an update to the command + ## Package not found on travis-ci.org 1. Check the ["Package not found"](#package-not-found) item above. From f0d6436293751cc5adb45c7c3f37b8d0f34bb9f8 Mon Sep 17 00:00:00 2001 From: Daniel Fahlke Date: Sat, 5 Sep 2015 17:12:20 +0200 Subject: [PATCH 146/205] add period --- doc/articles/troubleshooting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/articles/troubleshooting.md b/doc/articles/troubleshooting.md index 2fb9e7b1a..d01735a53 100644 --- a/doc/articles/troubleshooting.md +++ b/doc/articles/troubleshooting.md @@ -45,7 +45,7 @@ This is a list of common pitfalls on using Composer, and how to avoid them. 6. If you are updating a single package, it may depend on newer versions itself. In this cases add the `--with-dependencies` argument **or** add all dependencies which - need an update to the command + need an update to the command. ## Package not found on travis-ci.org From 9f6fdfd703f433bd0777fd89fb4684908a6c4f06 Mon Sep 17 00:00:00 2001 From: Rob Date: Mon, 7 Sep 2015 18:55:30 +0200 Subject: [PATCH 147/205] spelling --- doc/articles/troubleshooting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/articles/troubleshooting.md b/doc/articles/troubleshooting.md index d01735a53..f0f55385d 100644 --- a/doc/articles/troubleshooting.md +++ b/doc/articles/troubleshooting.md @@ -44,7 +44,7 @@ This is a list of common pitfalls on using Composer, and how to avoid them. Packagist has a delay of up to 1 minute before new packages are visible to Composer. 6. If you are updating a single package, it may depend on newer versions itself. - In this cases add the `--with-dependencies` argument **or** add all dependencies which + In this case add the `--with-dependencies` argument **or** add all dependencies which need an update to the command. ## Package not found on travis-ci.org From 89c6a68a76a8beb9284ece77f65530a9da5fdb38 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 12 Sep 2015 22:28:03 +0100 Subject: [PATCH 148/205] Updates to path repository and path downloader, refs #4365 --- src/Composer/Downloader/PathDownloader.php | 18 +++-- src/Composer/Factory.php | 2 +- .../Package/Loader/RootPackageLoader.php | 4 +- .../Package/Version/VersionGuesser.php | 67 ++++++++++--------- src/Composer/Repository/PathRepository.php | 49 ++++++-------- .../Package/Loader/RootPackageLoaderTest.php | 6 +- .../Package/Version/VersionGuesserTest.php | 12 ++-- 7 files changed, 74 insertions(+), 84 deletions(-) diff --git a/src/Composer/Downloader/PathDownloader.php b/src/Composer/Downloader/PathDownloader.php index fbdb0aebc..3ae458d71 100644 --- a/src/Composer/Downloader/PathDownloader.php +++ b/src/Composer/Downloader/PathDownloader.php @@ -30,21 +30,19 @@ class PathDownloader extends FileDownloader public function download(PackageInterface $package, $path) { $fileSystem = new Filesystem(); - if ($fileSystem->exists($path)) { - $fileSystem->remove($path); - } - - try { - $fileSystem->symlink($package->getDistUrl(), $path); - } catch (IOException $e) { - $fileSystem->mirror($package->getDistUrl(), $path); - } + $this->filesystem->removeDirectory($path); $this->io->writeError(sprintf( - ' Downloaded %s (%s) from %s', + ' - Installing %s (%s) from %s', $package->getName(), $package->getFullPrettyVersion(), $package->getDistUrl() )); + + try { + $fileSystem->symlink($package->getDistUrl(), $path); + } catch (IOException $e) { + $fileSystem->mirror($package->getDistUrl(), $path); + } } } diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 1da6c30da..406ee91fd 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -265,7 +265,7 @@ class Factory // load package $parser = new VersionParser; - $guesser = new VersionGuesser(new ProcessExecutor($io), $parser); + $guesser = new VersionGuesser($config, new ProcessExecutor($io), $parser); $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser); $package = $loader->load($localConfig); $composer->setPackage($package); diff --git a/src/Composer/Package/Loader/RootPackageLoader.php b/src/Composer/Package/Loader/RootPackageLoader.php index 3043a18c5..c084c846a 100644 --- a/src/Composer/Package/Loader/RootPackageLoader.php +++ b/src/Composer/Package/Loader/RootPackageLoader.php @@ -51,7 +51,7 @@ class RootPackageLoader extends ArrayLoader $this->manager = $manager; $this->config = $config; - $this->versionGuesser = $versionGuesser ?: new VersionGuesser(new ProcessExecutor(), $this->versionParser); + $this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor(), $this->versionParser); } public function load(array $config, $class = 'Composer\Package\RootPackage') @@ -65,7 +65,7 @@ class RootPackageLoader extends ArrayLoader if (getenv('COMPOSER_ROOT_VERSION')) { $version = getenv('COMPOSER_ROOT_VERSION'); } else { - $version = $this->versionGuesser->guessVersion($this->config, $config); + $version = $this->versionGuesser->guessVersion($config, getcwd()); } if (!$version) { diff --git a/src/Composer/Package/Version/VersionGuesser.php b/src/Composer/Package/Version/VersionGuesser.php index 4a5e2cc0a..34f997078 100644 --- a/src/Composer/Package/Version/VersionGuesser.php +++ b/src/Composer/Package/Version/VersionGuesser.php @@ -27,6 +27,11 @@ use Composer\Util\Svn as SvnUtil; */ class VersionGuesser { + /** + * @var Config + */ + private $config; + /** * @var ProcessExecutor */ @@ -38,45 +43,44 @@ class VersionGuesser private $versionParser; /** - * @var null|string - */ - private $cwd; - - /** + * @param Config $config * @param ProcessExecutor $process * @param VersionParser $versionParser - * @param string $cwd */ - public function __construct(ProcessExecutor $process, VersionParser $versionParser, $cwd = null) + public function __construct(Config $config, ProcessExecutor $process, VersionParser $versionParser) { + $this->config = $config; $this->process = $process; $this->versionParser = $versionParser; - $this->cwd = $cwd ?: getcwd(); } - public function guessVersion(Config $config, array $packageConfig) + /** + * @param array $packageConfig + * @param string $path Path to guess into + */ + public function guessVersion(array $packageConfig, $path) { if (function_exists('proc_open')) { - $version = $this->guessGitVersion($packageConfig); + $version = $this->guessGitVersion($packageConfig, $path); if (null !== $version) { return $version; } - $version = $this->guessHgVersion($config, $packageConfig); + $version = $this->guessHgVersion($packageConfig, $path); if (null !== $version) { return $version; } - return $this->guessSvnVersion($packageConfig); + return $this->guessSvnVersion($packageConfig, $path); } } - private function guessGitVersion(array $config) + private function guessGitVersion(array $packageConfig, $path) { GitUtil::cleanEnv(); // try to fetch current version from git tags - if (0 === $this->process->execute('git describe --exact-match --tags', $output, $this->cwd)) { + if (0 === $this->process->execute('git describe --exact-match --tags', $output, $path)) { try { return $this->versionParser->normalize(trim($output)); } catch (\Exception $e) { @@ -84,7 +88,7 @@ class VersionGuesser } // try to fetch current version from git branch - if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output, $this->cwd)) { + if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output, $path)) { $branches = array(); $isFeatureBranch = false; $version = null; @@ -116,16 +120,16 @@ class VersionGuesser } // try to find the best (nearest) version branch to assume this feature's version - $version = $this->guessFeatureVersion($config, $version, $branches, 'git rev-list %candidate%..%branch%'); + $version = $this->guessFeatureVersion($packageConfig, $version, $branches, 'git rev-list %candidate%..%branch%', $path); return $version; } } - private function guessHgVersion(Config $config, array $packageConfig) + private function guessHgVersion(array $packageConfig, $path) { // try to fetch current version from hg branch - if (0 === $this->process->execute('hg branch', $output, $this->cwd)) { + if (0 === $this->process->execute('hg branch', $output, $path)) { $branch = trim($output); $version = $this->versionParser->normalizeBranch($branch); $isFeatureBranch = 0 === strpos($version, 'dev-'); @@ -139,30 +143,29 @@ class VersionGuesser } // re-use the HgDriver to fetch branches (this properly includes bookmarks) - $packageConfig = array('url' => $this->cwd); - $driver = new HgDriver($packageConfig, new NullIO(), $config, $this->process); + $driver = new HgDriver(array('url' => $path), new NullIO(), $this->config, $this->process); $branches = array_keys($driver->getBranches()); // try to find the best (nearest) version branch to assume this feature's version - $version = $this->guessFeatureVersion($config, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"'); + $version = $this->guessFeatureVersion($packageConfig, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"', $path); return $version; } } - private function guessFeatureVersion(array $config, $version, array $branches, $scmCmdline) + private function guessFeatureVersion(array $packageConfig, $version, array $branches, $scmCmdline, $path) { // ignore feature branches if they have no branch-alias or self.version is used // and find the branch they came from to use as a version instead - if ((isset($config['extra']['branch-alias']) && !isset($config['extra']['branch-alias'][$version])) - || strpos(json_encode($config), '"self.version"') + if ((isset($packageConfig['extra']['branch-alias']) && !isset($packageConfig['extra']['branch-alias'][$version])) + || strpos(json_encode($packageConfig), '"self.version"') ) { $branch = preg_replace('{^dev-}', '', $version); $length = PHP_INT_MAX; $nonFeatureBranches = ''; - if (!empty($config['non-feature-branches'])) { - $nonFeatureBranches = implode('|', $config['non-feature-branches']); + if (!empty($packageConfig['non-feature-branches'])) { + $nonFeatureBranches = implode('|', $packageConfig['non-feature-branches']); } foreach ($branches as $candidate) { @@ -177,7 +180,7 @@ class VersionGuesser } $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline); - if (0 !== $this->process->execute($cmdLine, $output, $this->cwd)) { + if (0 !== $this->process->execute($cmdLine, $output, $path)) { continue; } @@ -194,15 +197,15 @@ class VersionGuesser return $version; } - private function guessSvnVersion(array $config) + private function guessSvnVersion(array $packageConfig, $path) { SvnUtil::cleanEnv(); // try to fetch current version from svn - if (0 === $this->process->execute('svn info --xml', $output, $this->cwd)) { - $trunkPath = isset($config['trunk-path']) ? preg_quote($config['trunk-path'], '#') : 'trunk'; - $branchesPath = isset($config['branches-path']) ? preg_quote($config['branches-path'], '#') : 'branches'; - $tagsPath = isset($config['tags-path']) ? preg_quote($config['tags-path'], '#') : 'tags'; + if (0 === $this->process->execute('svn info --xml', $output, $path)) { + $trunkPath = isset($packageConfig['trunk-path']) ? preg_quote($packageConfig['trunk-path'], '#') : 'trunk'; + $branchesPath = isset($packageConfig['branches-path']) ? preg_quote($packageConfig['branches-path'], '#') : 'branches'; + $tagsPath = isset($packageConfig['tags-path']) ? preg_quote($packageConfig['tags-path'], '#') : 'tags'; $urlPattern = '#.*/('.$trunkPath.'|('.$branchesPath.'|'. $tagsPath .')/(.*))#'; diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index a907c5adb..970edac72 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -20,7 +20,6 @@ use Composer\Package\Loader\LoaderInterface; use Composer\Package\Version\VersionGuesser; use Composer\Package\Version\VersionParser; use Composer\Util\ProcessExecutor; -use Symfony\Component\Filesystem\Filesystem; /** * This repository allows installing local packages that are not necessarily under their own VCS. @@ -48,16 +47,6 @@ use Symfony\Component\Filesystem\Filesystem; */ class PathRepository extends ArrayRepository { - /** - * @var Config - */ - private $config; - - /** - * @var Filesystem - */ - private $fileSystem; - /** * @var ArrayLoader */ @@ -69,51 +58,47 @@ class PathRepository extends ArrayRepository private $versionGuesser; /** - * @var array + * @var string */ - private $packageConfig; + private $path; /** - * @var string + * @var ProcessExecutor */ - private $path; + private $process; /** * Initializes path repository. * - * @param array $packageConfig + * @param array $repoConfig * @param IOInterface $io * @param Config $config - * @param LoaderInterface $loader - * @param Filesystem $filesystem - * @param VersionGuesser $versionGuesser */ - public function __construct(array $packageConfig, IOInterface $io, Config $config, LoaderInterface $loader = null, Filesystem $filesystem = null, VersionGuesser $versionGuesser = null) + public function __construct(array $repoConfig, IOInterface $io, Config $config) { - if (!isset($packageConfig['url'])) { + if (!isset($repoConfig['url'])) { throw new \RuntimeException('You must specify the `url` configuration for the path repository'); } - $this->fileSystem = $filesystem ?: new Filesystem(); - $this->loader = $loader ?: new ArrayLoader(); - $this->config = $config; - $this->packageConfig = $packageConfig; - $this->path = realpath(rtrim($packageConfig['url'], '/')) . '/'; - $this->versionGuesser = $versionGuesser ?: new VersionGuesser(new ProcessExecutor($io), new VersionParser(), $this->path); + $this->loader = new ArrayLoader(); + $this->path = realpath(rtrim($repoConfig['url'], '/')) . '/'; + $this->process = new ProcessExecutor($io); + $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser()); + + parent::__construct(); } /** * Initializes path repository. * * This method will basically read the folder and add the found package. - * */ protected function initialize() { parent::initialize(); $composerFilePath = $this->path.'composer.json'; - if (!$this->fileSystem->exists($composerFilePath)) { + if (!file_exists($composerFilePath)) { throw new \RuntimeException(sprintf('No `composer.json` file found in path repository "%s"', $this->path)); } @@ -122,10 +107,14 @@ class PathRepository extends ArrayRepository $package['dist'] = array( 'type' => 'path', 'url' => $this->path, + 'reference' => '', ); if (!isset($package['version'])) { - $package['version'] = $this->versionGuesser->guessVersion($this->config, $this->packageConfig) ?: 'dev-master'; + $package['version'] = $this->versionGuesser->guessVersion($package, $this->path) ?: 'dev-master'; + } + if (is_dir($this->path.'/.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $this->path)) { + $package['dist']['reference'] = trim($output); } $package = $this->loader->load($package); diff --git a/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php b/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php index 77139f928..cec33fd94 100644 --- a/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php +++ b/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php @@ -76,7 +76,7 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($executor, new VersionParser())); + $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($config, $executor, new VersionParser())); $package = $loader->load(array()); $this->assertEquals("1.0.0.0", $package->getVersion()); @@ -139,7 +139,7 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($executor, new VersionParser())); + $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($config, $executor, new VersionParser())); $package = $loader->load(array('require' => array('foo/bar' => 'self.version'))); $this->assertEquals("dev-master", $package->getPrettyVersion()); @@ -188,7 +188,7 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($executor, new VersionParser())); + $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($config, $executor, new VersionParser())); $package = $loader->load(array('require' => array('foo/bar' => 'self.version'), "non-feature-branches" => array("latest-.*"))); $this->assertEquals("dev-latest-production", $package->getPrettyVersion()); diff --git a/tests/Composer/Test/Package/Version/VersionGuesserTest.php b/tests/Composer/Test/Package/Version/VersionGuesserTest.php index 2c5db1ff5..6f7f7ce83 100644 --- a/tests/Composer/Test/Package/Version/VersionGuesserTest.php +++ b/tests/Composer/Test/Package/Version/VersionGuesserTest.php @@ -58,8 +58,8 @@ class VersionGuesserTest extends \PHPUnit_Framework_TestCase $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $guesser = new VersionGuesser($executor, new VersionParser()); - $version = $guesser->guessVersion($config, array()); + $guesser = new VersionGuesser($config, $executor, new VersionParser()); + $version = $guesser->guessVersion(array(), 'dummy/path'); $this->assertEquals("dev-$commitHash", $version); } @@ -88,8 +88,8 @@ class VersionGuesserTest extends \PHPUnit_Framework_TestCase $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $guesser = new VersionGuesser($executor, new VersionParser()); - $version = $guesser->guessVersion($config, array()); + $guesser = new VersionGuesser($config, $executor, new VersionParser()); + $version = $guesser->guessVersion(array(), 'dummy/path'); $this->assertEquals("2.0.5.0-alpha2", $version); } @@ -129,8 +129,8 @@ class VersionGuesserTest extends \PHPUnit_Framework_TestCase $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $guesser = new VersionGuesser($executor, new VersionParser()); - $version = $guesser->guessVersion($config, array()); + $guesser = new VersionGuesser($config, $executor, new VersionParser()); + $version = $guesser->guessVersion(array(), 'dummy/path'); $this->assertEquals("dev-foo", $version); } From 6508dc432203b30c27dc6aff2964fb287a95810b Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 12 Sep 2015 22:29:19 +0100 Subject: [PATCH 149/205] Allow packages with only a dist ref to be force updated when the dist ref changes --- src/Composer/Installer.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 8aecea402..a61475f3c 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -569,7 +569,8 @@ class Installer if ('update' === $operation->getJobType() && $operation->getTargetPackage()->isDev() && $operation->getTargetPackage()->getVersion() === $operation->getInitialPackage()->getVersion() - && $operation->getTargetPackage()->getSourceReference() === $operation->getInitialPackage()->getSourceReference() + && (!$operation->getTargetPackage()->getSourceReference() || $operation->getTargetPackage()->getSourceReference() === $operation->getInitialPackage()->getSourceReference()) + && (!$operation->getTargetPackage()->getDistReference() || $operation->getTargetPackage()->getDistReference() === $operation->getInitialPackage()->getDistReference()) ) { if ($this->io->isDebug()) { $this->io->writeError(' - Skipping update of '. $operation->getTargetPackage()->getPrettyName().' to the same reference-locked version'); From 1215e194eda21bd225e0ab149930e03c332149cf Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 12 Sep 2015 22:31:24 +0100 Subject: [PATCH 150/205] Update deps --- composer.lock | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/composer.lock b/composer.lock index fc7e1ef34..288b61e4e 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "composer/spdx-licenses", - "version": "1.1.0", + "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/composer/spdx-licenses.git", - "reference": "2f17228c1b98283b779698cefa917f7f4fd0b0d4" + "reference": "324b3530ac3e6277ff4bedf82a34fbf35836eb8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/2f17228c1b98283b779698cefa917f7f4fd0b0d4", - "reference": "2f17228c1b98283b779698cefa917f7f4fd0b0d4", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/324b3530ac3e6277ff4bedf82a34fbf35836eb8d", + "reference": "324b3530ac3e6277ff4bedf82a34fbf35836eb8d", "shasum": "" }, "require": { @@ -30,7 +30,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.x-dev" } }, "autoload": { @@ -64,20 +64,20 @@ "spdx", "validator" ], - "time": "2015-07-17 06:17:03" + "time": "2015-09-07 16:25:20" }, { "name": "justinrainbow/json-schema", - "version": "1.4.4", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/justinrainbow/json-schema.git", - "reference": "8dc9b9d85ab639ca60ab4608b34c1279d6ae7bce" + "reference": "a4bee9f4b344b66e0a0d96c7afae1e92edf385fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/8dc9b9d85ab639ca60ab4608b34c1279d6ae7bce", - "reference": "8dc9b9d85ab639ca60ab4608b34c1279d6ae7bce", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/a4bee9f4b344b66e0a0d96c7afae1e92edf385fe", + "reference": "a4bee9f4b344b66e0a0d96c7afae1e92edf385fe", "shasum": "" }, "require": { @@ -98,8 +98,8 @@ } }, "autoload": { - "psr-0": { - "JsonSchema": "src/" + "psr-4": { + "JsonSchema\\": "src/JsonSchema/" } }, "notification-url": "https://packagist.org/downloads/", @@ -130,7 +130,7 @@ "json", "schema" ], - "time": "2015-07-14 16:29:50" + "time": "2015-09-08 22:28:04" }, { "name": "seld/cli-prompt", @@ -836,16 +836,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.4.5", + "version": "1.4.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "09fc125d65c344c53a7c7ad8f261e3f3af9f76c5" + "reference": "3ab72c62e550370a6cd5dc873e1a04ab57562f5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/09fc125d65c344c53a7c7ad8f261e3f3af9f76c5", - "reference": "09fc125d65c344c53a7c7ad8f261e3f3af9f76c5", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3ab72c62e550370a6cd5dc873e1a04ab57562f5b", + "reference": "3ab72c62e550370a6cd5dc873e1a04ab57562f5b", "shasum": "" }, "require": { @@ -881,20 +881,20 @@ "keywords": [ "tokenizer" ], - "time": "2015-08-13 14:23:08" + "time": "2015-08-16 08:51:00" }, { "name": "phpunit/phpunit", - "version": "4.8.3", + "version": "4.8.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "fd3050e26e3105f416d74c4d33aea659b406c59d" + "reference": "2246830f4a1a551c67933e4171bf2126dc29d357" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fd3050e26e3105f416d74c4d33aea659b406c59d", - "reference": "fd3050e26e3105f416d74c4d33aea659b406c59d", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2246830f4a1a551c67933e4171bf2126dc29d357", + "reference": "2246830f4a1a551c67933e4171bf2126dc29d357", "shasum": "" }, "require": { @@ -953,7 +953,7 @@ "testing", "xunit" ], - "time": "2015-08-10 09:16:56" + "time": "2015-08-24 04:09:38" }, { "name": "phpunit/phpunit-mock-objects", From 66acee7feb51d4b30e8983c703bf07ce1d06883e Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 12 Sep 2015 23:04:37 +0100 Subject: [PATCH 151/205] Add config.platform to the list of locked properties --- composer.lock | 1 + src/Composer/Package/Locker.php | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/composer.lock b/composer.lock index 288b61e4e..0c6108927 100644 --- a/composer.lock +++ b/composer.lock @@ -5,6 +5,7 @@ "This file is @generated automatically" ], "hash": "3024e89a7e808b8dece156112459a7ea", + "content-hash": "01608741fe66bb9528d7c77c0a422965", "packages": [ { "name": "composer/spdx-licenses", diff --git a/src/Composer/Package/Locker.php b/src/Composer/Package/Locker.php index 34f547c5e..6ef0fe979 100644 --- a/src/Composer/Package/Locker.php +++ b/src/Composer/Package/Locker.php @@ -397,6 +397,8 @@ class Locker $content = json_decode($composerFileContents, true); $relevantKeys = array( + 'name', + 'version', 'require', 'require-dev', 'conflict', @@ -406,8 +408,6 @@ class Locker 'prefer-stable', 'repositories', 'extra', - 'version', - 'name', ); $relevantContent = array(); @@ -415,6 +415,9 @@ class Locker foreach (array_intersect($relevantKeys, array_keys($content)) as $key) { $relevantContent[$key] = $content[$key]; } + if (isset($content['config']['platform'])) { + $relevantContent['config']['platform'] = $content['config']['platform']; + } ksort($relevantContent); return md5(json_encode($relevantContent)); From 284e4761bfc94dc69f216a5e27a75898cc676ede Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Mon, 14 Sep 2015 09:48:15 +0100 Subject: [PATCH 152/205] Add documentation about the `path` repository --- doc/05-repositories.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/doc/05-repositories.md b/doc/05-repositories.md index 1df20828a..5dae47295 100644 --- a/doc/05-repositories.md +++ b/doc/05-repositories.md @@ -606,6 +606,39 @@ imported. When an archive with a newer version is added in the artifact folder and you run `update`, that version will be imported as well and Composer will update to the latest version. +### Path + +In addition to the artifact repository, you can use the path one, which allow +you to depends on a relative directory. This can be especially useful when dealing +with monolith repositories. + +For instance, if you have the following directory structure in your repository: +``` +- apps +\_ my-app + \_ composer.json +- packages +\_ my-package + \_ composer.json +``` + +Then, to add the package `my/package` as a dependency, in your `apps/my-app/composer.json` +file, you can use the following configuration: + +```json +{ + "repositories": [ + { + "type": "path", + "url": "../../packages/my-package" + } + ], + "require": { + "my/package": "*@dev" + } +} +``` + ## Disabling Packagist You can disable the default Packagist repository by adding this to your From 0e8c5fa62e215471d425740bcd3ef4556e127daa Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Mon, 14 Sep 2015 09:58:07 +0100 Subject: [PATCH 153/205] Store path from composer.json with the `path` repository to ensure lock file to be reused --- src/Composer/Downloader/PathDownloader.php | 7 +++++++ src/Composer/Repository/PathRepository.php | 23 +++++++++++++++------- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/Composer/Downloader/PathDownloader.php b/src/Composer/Downloader/PathDownloader.php index 3ae458d71..88b860c54 100644 --- a/src/Composer/Downloader/PathDownloader.php +++ b/src/Composer/Downloader/PathDownloader.php @@ -39,6 +39,13 @@ class PathDownloader extends FileDownloader $package->getDistUrl() )); + if (!file_exists($path) || !is_dir($path)) { + throw new \RuntimeException(sprintf( + 'Path "%s" is not found', + $path + )); + } + try { $fileSystem->symlink($package->getDistUrl(), $path); } catch (IOException $e) { diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index 970edac72..8e0b2edca 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -60,7 +60,7 @@ class PathRepository extends ArrayRepository /** * @var string */ - private $path; + private $url; /** * @var ProcessExecutor @@ -81,7 +81,7 @@ class PathRepository extends ArrayRepository } $this->loader = new ArrayLoader(); - $this->path = realpath(rtrim($repoConfig['url'], '/')) . '/'; + $this->url = $repoConfig['url']; $this->process = new ProcessExecutor($io); $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser()); @@ -97,27 +97,36 @@ class PathRepository extends ArrayRepository { parent::initialize(); - $composerFilePath = $this->path.'composer.json'; + $path = $this->getPath(); + $composerFilePath = $path.'composer.json'; if (!file_exists($composerFilePath)) { - throw new \RuntimeException(sprintf('No `composer.json` file found in path repository "%s"', $this->path)); + throw new \RuntimeException(sprintf('No `composer.json` file found in path repository "%s"', $path)); } $json = file_get_contents($composerFilePath); $package = JsonFile::parseJson($json, $composerFilePath); $package['dist'] = array( 'type' => 'path', - 'url' => $this->path, + 'url' => $this->url, 'reference' => '', ); if (!isset($package['version'])) { - $package['version'] = $this->versionGuesser->guessVersion($package, $this->path) ?: 'dev-master'; + $package['version'] = $this->versionGuesser->guessVersion($package, $path) ?: 'dev-master'; } - if (is_dir($this->path.'/.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $this->path)) { + if (is_dir($path.'/.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $path)) { $package['dist']['reference'] = trim($output); } $package = $this->loader->load($package); $this->addPackage($package); } + + /** + * @return string + */ + private function getPath() + { + return realpath(rtrim($this->url, '/')) . '/'; + } } From a3f5f603591e1866481877ed065787af1690c0b1 Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Mon, 14 Sep 2015 10:17:13 +0100 Subject: [PATCH 154/205] Update output to have a coherent one --- src/Composer/Downloader/PathDownloader.php | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Composer/Downloader/PathDownloader.php b/src/Composer/Downloader/PathDownloader.php index 88b860c54..c58a3f23a 100644 --- a/src/Composer/Downloader/PathDownloader.php +++ b/src/Composer/Downloader/PathDownloader.php @@ -33,13 +33,13 @@ class PathDownloader extends FileDownloader $this->filesystem->removeDirectory($path); $this->io->writeError(sprintf( - ' - Installing %s (%s) from %s', + ' - Installing %s (%s)', $package->getName(), - $package->getFullPrettyVersion(), - $package->getDistUrl() + $package->getFullPrettyVersion() )); - if (!file_exists($path) || !is_dir($path)) { + $url = $package->getDistUrl(); + if (!file_exists($url) || !is_dir($url)) { throw new \RuntimeException(sprintf( 'Path "%s" is not found', $path @@ -47,9 +47,13 @@ class PathDownloader extends FileDownloader } try { - $fileSystem->symlink($package->getDistUrl(), $path); + $fileSystem->symlink($url, $path); + $this->io->writeError(sprintf(' Symlinked from %s', $url)); } catch (IOException $e) { - $fileSystem->mirror($package->getDistUrl(), $path); + $fileSystem->mirror($url, $path); + $this->io->writeError(sprintf(' Mirrored from %s', $url)); } + + $this->io->writeError(''); } } From cc522c20bb90ba3c2f604232ca08fbfcf260f34b Mon Sep 17 00:00:00 2001 From: Olivier Laviale Date: Sun, 13 Sep 2015 23:30:09 +0200 Subject: [PATCH 155/205] Optimized this->getIO() --- src/Composer/Command/ConfigCommand.php | 5 +- src/Composer/Command/CreateProjectCommand.php | 5 +- src/Composer/Command/DependsCommand.php | 5 +- src/Composer/Command/DiagnoseCommand.php | 42 ++++++------ src/Composer/Command/HomeCommand.php | 5 +- src/Composer/Command/InitCommand.php | 51 ++++++++------- src/Composer/Command/InstallCommand.php | 8 +-- src/Composer/Command/LicensesCommand.php | 13 ++-- src/Composer/Command/RemoveCommand.php | 12 ++-- src/Composer/Command/RequireCommand.php | 14 ++-- src/Composer/Command/RunScriptCommand.php | 5 +- src/Composer/Command/SearchCommand.php | 7 +- src/Composer/Command/SelfUpdateCommand.php | 26 ++++---- src/Composer/Command/ShowCommand.php | 64 ++++++++++--------- src/Composer/Command/StatusCommand.php | 13 ++-- src/Composer/Command/UpdateCommand.php | 6 +- src/Composer/Command/ValidateCommand.php | 25 ++++---- src/Composer/Console/Application.php | 25 ++++---- 18 files changed, 177 insertions(+), 154 deletions(-) diff --git a/src/Composer/Command/ConfigCommand.php b/src/Composer/Command/ConfigCommand.php index 6c12a7a72..2b7fd4846 100644 --- a/src/Composer/Command/ConfigCommand.php +++ b/src/Composer/Command/ConfigCommand.php @@ -464,6 +464,7 @@ EOT protected function listConfiguration(array $contents, array $rawContents, OutputInterface $output, $k = null) { $origK = $k; + $io = $this->getIO(); foreach ($contents as $key => $value) { if ($k === null && !in_array($key, array('config', 'repositories'))) { continue; @@ -498,9 +499,9 @@ EOT } if (is_string($rawVal) && $rawVal != $value) { - $this->getIO()->write('[' . $k . $key . '] ' . $rawVal . ' (' . $value . ')'); + $io->write('[' . $k . $key . '] ' . $rawVal . ' (' . $value . ')'); } else { - $this->getIO()->write('[' . $k . $key . '] ' . $value . ''); + $io->write('[' . $k . $key . '] ' . $value . ''); } } } diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index d6c68a94f..54cd63538 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -100,16 +100,17 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { $config = Factory::createConfig(); + $io = $this->getIO(); $this->updatePreferredOptions($config, $input, $preferSource, $preferDist, true); if ($input->getOption('no-custom-installers')) { - $this->getIO()->writeError('You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.'); + $io->writeError('You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.'); $input->setOption('no-plugins', true); } return $this->installProject( - $this->getIO(), + $io, $config, $input->getArgument('package'), $input->getArgument('directory'), diff --git a/src/Composer/Command/DependsCommand.php b/src/Composer/Command/DependsCommand.php index 97b9d0f39..b4017c2fe 100644 --- a/src/Composer/Command/DependsCommand.php +++ b/src/Composer/Command/DependsCommand.php @@ -81,6 +81,7 @@ EOT $messages = array(); $outputPackages = array(); + $io = $this->getIO(); foreach ($repo->getPackages() as $package) { foreach ($types as $type) { foreach ($package->{'get'.$linkTypes[$type][0]}() as $link) { @@ -96,9 +97,9 @@ EOT if ($messages) { sort($messages); - $this->getIO()->write($messages); + $io->write($messages); } else { - $this->getIO()->writeError('There is no installed package depending on "'.$needle.'".'); + $io->writeError('There is no installed package depending on "'.$needle.'".'); } } } diff --git a/src/Composer/Command/DiagnoseCommand.php b/src/Composer/Command/DiagnoseCommand.php index 860f85948..30d38b0c1 100644 --- a/src/Composer/Command/DiagnoseCommand.php +++ b/src/Composer/Command/DiagnoseCommand.php @@ -57,12 +57,13 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { $composer = $this->getComposer(false); + $io = $this->getIO(); if ($composer) { $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); - $this->getIO()->write('Checking composer.json: ', false); + $io->write('Checking composer.json: ', false); $this->outputResult($this->checkComposerSchema()); } @@ -72,44 +73,44 @@ EOT $config = Factory::createConfig(); } - $this->rfs = new RemoteFilesystem($this->getIO(), $config); - $this->process = new ProcessExecutor($this->getIO()); + $this->rfs = new RemoteFilesystem($io, $config); + $this->process = new ProcessExecutor($io); - $this->getIO()->write('Checking platform settings: ', false); + $io->write('Checking platform settings: ', false); $this->outputResult($this->checkPlatform()); - $this->getIO()->write('Checking git settings: ', false); + $io->write('Checking git settings: ', false); $this->outputResult($this->checkGit()); - $this->getIO()->write('Checking http connectivity to packagist: ', false); + $io->write('Checking http connectivity to packagist: ', false); $this->outputResult($this->checkHttp('http')); - $this->getIO()->write('Checking https connectivity to packagist: ', false); + $io->write('Checking https connectivity to packagist: ', false); $this->outputResult($this->checkHttp('https')); $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org')); if (!empty($opts['http']['proxy'])) { - $this->getIO()->write('Checking HTTP proxy: ', false); + $io->write('Checking HTTP proxy: ', false); $this->outputResult($this->checkHttpProxy()); - $this->getIO()->write('Checking HTTP proxy support for request_fulluri: ', false); + $io->write('Checking HTTP proxy support for request_fulluri: ', false); $this->outputResult($this->checkHttpProxyFullUriRequestParam()); - $this->getIO()->write('Checking HTTPS proxy support for request_fulluri: ', false); + $io->write('Checking HTTPS proxy support for request_fulluri: ', false); $this->outputResult($this->checkHttpsProxyFullUriRequestParam()); } if ($oauth = $config->get('github-oauth')) { foreach ($oauth as $domain => $token) { - $this->getIO()->write('Checking '.$domain.' oauth access: ', false); + $io->write('Checking '.$domain.' oauth access: ', false); $this->outputResult($this->checkGithubOauth($domain, $token)); } } else { - $this->getIO()->write('Checking github.com rate limit: ', false); + $io->write('Checking github.com rate limit: ', false); try { $rate = $this->getGithubRateLimit('github.com'); $this->outputResult(true); if (10 > $rate['remaining']) { - $this->getIO()->write('WARNING'); - $this->getIO()->write(sprintf( + $io->write('WARNING'); + $io->write(sprintf( 'Github has a rate limit on their API. ' . 'You currently have %u ' . 'out of %u requests left.' . PHP_EOL @@ -128,10 +129,10 @@ EOT } } - $this->getIO()->write('Checking disk free space: ', false); + $io->write('Checking disk free space: ', false); $this->outputResult($this->checkDiskSpace($config)); - $this->getIO()->write('Checking composer version: ', false); + $io->write('Checking composer version: ', false); $this->outputResult($this->checkVersion()); return $this->failures; @@ -322,15 +323,16 @@ EOT */ private function outputResult($result) { + $io = $this->getIO(); if (true === $result) { - $this->getIO()->write('OK'); + $io->write('OK'); } else { $this->failures++; - $this->getIO()->write('FAIL'); + $io->write('FAIL'); if ($result instanceof \Exception) { - $this->getIO()->write('['.get_class($result).'] '.$result->getMessage()); + $io->write('['.get_class($result).'] '.$result->getMessage()); } elseif ($result) { - $this->getIO()->write(trim($result)); + $io->write(trim($result)); } } } diff --git a/src/Composer/Command/HomeCommand.php b/src/Composer/Command/HomeCommand.php index e742cadf5..fff1f86eb 100644 --- a/src/Composer/Command/HomeCommand.php +++ b/src/Composer/Command/HomeCommand.php @@ -57,6 +57,7 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { $repos = $this->initializeRepos(); + $io = $this->getIO(); $return = 0; foreach ($input->getArgument('packages') as $packageName) { @@ -74,12 +75,12 @@ EOT if (!$packageExists) { $return = 1; - $this->getIO()->writeError('Package '.$packageName.' not found'); + $io->writeError('Package '.$packageName.' not found'); } if (!$handled) { $return = 1; - $this->getIO()->writeError(''.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.''); + $io->writeError(''.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.''); } } diff --git a/src/Composer/Command/InitCommand.php b/src/Composer/Command/InitCommand.php index 971477306..112c10129 100644 --- a/src/Composer/Command/InitCommand.php +++ b/src/Composer/Command/InitCommand.php @@ -106,11 +106,12 @@ EOT $file = new JsonFile('composer.json'); $json = $file->encode($options); + $io = $this->getIO(); if ($input->isInteractive()) { - $this->getIO()->writeError(array('', $json, '')); - if (!$this->getIO()->askConfirmation('Do you confirm generation [yes]? ', true)) { - $this->getIO()->writeError('Command aborted'); + $io->writeError(array('', $json, '')); + if (!$io->askConfirmation('Do you confirm generation [yes]? ', true)) { + $io->writeError('Command aborted'); return 1; } @@ -128,7 +129,7 @@ EOT if (!$this->hasVendorIgnore($ignoreFile)) { $question = 'Would you like the vendor directory added to your .gitignore [yes]? '; - if ($this->getIO()->askConfirmation($question, true)) { + if ($io->askConfirmation($question, true)) { $this->addVendorIgnore($ignoreFile); } } @@ -141,17 +142,17 @@ EOT protected function interact(InputInterface $input, OutputInterface $output) { $git = $this->getGitConfig(); - + $io = $this->getIO(); $formatter = $this->getHelperSet()->get('formatter'); - $this->getIO()->writeError(array( + $io->writeError(array( '', $formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', true), '' )); // namespace - $this->getIO()->writeError(array( + $io->writeError(array( '', 'This command will guide you through creating your composer.json config.', '', @@ -181,7 +182,7 @@ EOT } } - $name = $this->getIO()->askAndValidate( + $name = $io->askAndValidate( 'Package name (/) ['.$name.']: ', function ($value) use ($name) { if (null === $value) { @@ -202,7 +203,7 @@ EOT $input->setOption('name', $name); $description = $input->getOption('description') ?: false; - $description = $this->getIO()->ask( + $description = $io->ask( 'Description ['.$description.']: ', $description ); @@ -215,7 +216,7 @@ EOT } $self = $this; - $author = $this->getIO()->askAndValidate( + $author = $io->askAndValidate( 'Author ['.$author.']: ', function ($value) use ($self, $author) { $value = $value ?: $author; @@ -229,7 +230,7 @@ EOT $input->setOption('author', $author); $minimumStability = $input->getOption('stability') ?: null; - $minimumStability = $this->getIO()->askAndValidate( + $minimumStability = $io->askAndValidate( 'Minimum Stability ['.$minimumStability.']: ', function ($value) use ($self, $minimumStability) { if (null === $value) { @@ -251,31 +252,31 @@ EOT $input->setOption('stability', $minimumStability); $type = $input->getOption('type') ?: false; - $type = $this->getIO()->ask( + $type = $io->ask( 'Package Type ['.$type.']: ', $type ); $input->setOption('type', $type); $license = $input->getOption('license') ?: false; - $license = $this->getIO()->ask( + $license = $io->ask( 'License ['.$license.']: ', $license ); $input->setOption('license', $license); - $this->getIO()->writeError(array('', 'Define your dependencies.', '')); + $io->writeError(array('', 'Define your dependencies.', '')); $question = 'Would you like to define your dependencies (require) interactively [yes]? '; $requirements = array(); - if ($this->getIO()->askConfirmation($question, true)) { + if ($io->askConfirmation($question, true)) { $requirements = $this->determineRequirements($input, $output, $input->getOption('require')); } $input->setOption('require', $requirements); $question = 'Would you like to define your dev dependencies (require-dev) interactively [yes]? '; $devRequirements = array(); - if ($this->getIO()->askConfirmation($question, true)) { + if ($io->askConfirmation($question, true)) { $devRequirements = $this->determineRequirements($input, $output, $input->getOption('require-dev')); } $input->setOption('require-dev', $devRequirements); @@ -325,6 +326,7 @@ EOT if ($requires) { $requires = $this->normalizeRequirements($requires); $result = array(); + $io = $this->getIO(); foreach ($requires as $requirement) { if (!isset($requirement['version'])) { @@ -332,7 +334,7 @@ EOT $version = $this->findBestVersionForPackage($input, $requirement['name']); $requirement['version'] = $version; - $this->getIO()->writeError(sprintf( + $io->writeError(sprintf( 'Using version %s for %s', $requirement['version'], $requirement['name'] @@ -346,7 +348,8 @@ EOT } $versionParser = new VersionParser(); - while (null !== $package = $this->getIO()->ask('Search for a package: ')) { + $io = $this->getIO(); + while (null !== $package = $io->ask('Search for a package: ')) { $matches = $this->findPackages($package); if (count($matches)) { @@ -362,14 +365,14 @@ EOT // no match, prompt which to pick if (!$exactMatch) { - $this->getIO()->writeError(array( + $io->writeError(array( '', sprintf('Found %s packages matching %s', count($matches), $package), '' )); - $this->getIO()->writeError($choices); - $this->getIO()->writeError(''); + $io->writeError($choices); + $io->writeError(''); $validator = function ($selection) use ($matches, $versionParser) { if ('' === $selection) { @@ -399,7 +402,7 @@ EOT throw new \Exception('Not a valid selection'); }; - $package = $this->getIO()->askAndValidate( + $package = $io->askAndValidate( 'Enter package # to add, or the complete package name if it is not listed: ', $validator, 3, @@ -415,7 +418,7 @@ EOT return $input ?: false; }; - $constraint = $this->getIO()->askAndValidate( + $constraint = $io->askAndValidate( 'Enter the version constraint to require (or leave blank to use the latest version): ', $validator, 3, @@ -425,7 +428,7 @@ EOT if (false === $constraint) { $constraint = $this->findBestVersionForPackage($input, $package); - $this->getIO()->writeError(sprintf( + $io->writeError(sprintf( 'Using version %s for %s', $constraint, $package diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index e548b8d69..b8708611d 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -64,24 +64,24 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { + $io = $this->getIO(); if ($args = $input->getArgument('packages')) { - $this->getIO()->writeError('Invalid argument '.implode(' ', $args).'. Use "composer require '.implode(' ', $args).'" instead to add packages to your composer.json.'); + $io->writeError('Invalid argument '.implode(' ', $args).'. Use "composer require '.implode(' ', $args).'" instead to add packages to your composer.json.'); return 1; } if ($input->getOption('no-custom-installers')) { - $this->getIO()->writeError('You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.'); + $io->writeError('You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.'); $input->setOption('no-plugins', true); } if ($input->getOption('dev')) { - $this->getIO()->writeError('You are using the deprecated option "dev". Dev packages are installed by default now.'); + $io->writeError('You are using the deprecated option "dev". Dev packages are installed by default now.'); } $composer = $this->getComposer(true, $input->getOption('no-plugins')); $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress')); - $io = $this->getIO(); $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); diff --git a/src/Composer/Command/LicensesCommand.php b/src/Composer/Command/LicensesCommand.php index 4ba8ed09d..b542c3fe6 100644 --- a/src/Composer/Command/LicensesCommand.php +++ b/src/Composer/Command/LicensesCommand.php @@ -62,14 +62,15 @@ EOT } ksort($packages); + $io = $this->getIO(); switch ($format = $input->getOption('format')) { case 'text': - $this->getIO()->write('Name: '.$root->getPrettyName().''); - $this->getIO()->write('Version: '.$root->getFullPrettyVersion().''); - $this->getIO()->write('Licenses: '.(implode(', ', $root->getLicense()) ?: 'none').''); - $this->getIO()->write('Dependencies:'); - $this->getIO()->write(''); + $io->write('Name: '.$root->getPrettyName().''); + $io->write('Version: '.$root->getFullPrettyVersion().''); + $io->write('Licenses: '.(implode(', ', $root->getLicense()) ?: 'none').''); + $io->write('Dependencies:'); + $io->write(''); $table = new Table($output); $table->setStyle('compact'); @@ -94,7 +95,7 @@ EOT ); } - $this->getIO()->write(JsonFile::encode(array( + $io->write(JsonFile::encode(array( 'name' => $root->getPrettyName(), 'version' => $root->getFullPrettyVersion(), 'license' => $root->getLicense(), diff --git a/src/Composer/Command/RemoveCommand.php b/src/Composer/Command/RemoveCommand.php index 3779b09e9..fdbd146bb 100644 --- a/src/Composer/Command/RemoveCommand.php +++ b/src/Composer/Command/RemoveCommand.php @@ -68,19 +68,20 @@ EOT $type = $input->getOption('dev') ? 'require-dev' : 'require'; $altType = !$input->getOption('dev') ? 'require-dev' : 'require'; + $io = $this->getIO(); foreach ($packages as $package) { if (isset($composer[$type][$package])) { $json->removeLink($type, $package); } elseif (isset($composer[$altType][$package])) { - $this->getIO()->writeError(''.$package.' could not be found in '.$type.' but it is present in '.$altType.''); - if ($this->getIO()->isInteractive()) { - if ($this->getIO()->askConfirmation('Do you want to remove it from '.$altType.' [yes]? ', true)) { + $io->writeError(''.$package.' could not be found in '.$type.' but it is present in '.$altType.''); + if ($io->isInteractive()) { + if ($io->askConfirmation('Do you want to remove it from '.$altType.' [yes]? ', true)) { $json->removeLink($altType, $package); } } } else { - $this->getIO()->writeError(''.$package.' is not required in your composer.json and has not been removed'); + $io->writeError(''.$package.' is not required in your composer.json and has not been removed'); } } @@ -91,7 +92,6 @@ EOT // Update packages $composer = $this->getComposer(); $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress')); - $io = $this->getIO(); $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); @@ -110,7 +110,7 @@ EOT $status = $install->run(); if ($status !== 0) { - $this->getIO()->writeError("\n".'Removal failed, reverting '.$file.' to its original content.'); + $io->writeError("\n".'Removal failed, reverting '.$file.' to its original content.'); file_put_contents($jsonFile->getPath(), $composerBackup); } diff --git a/src/Composer/Command/RequireCommand.php b/src/Composer/Command/RequireCommand.php index 82401ffb2..6be23102a 100644 --- a/src/Composer/Command/RequireCommand.php +++ b/src/Composer/Command/RequireCommand.php @@ -64,20 +64,21 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { $file = Factory::getComposerFile(); + $io = $this->getIO(); $newlyCreated = !file_exists($file); if (!file_exists($file) && !file_put_contents($file, "{\n}\n")) { - $this->getIO()->writeError(''.$file.' could not be created.'); + $io->writeError(''.$file.' could not be created.'); return 1; } if (!is_readable($file)) { - $this->getIO()->writeError(''.$file.' is not readable.'); + $io->writeError(''.$file.' is not readable.'); return 1; } if (!is_writable($file)) { - $this->getIO()->writeError(''.$file.' is not writable.'); + $io->writeError(''.$file.' is not writable.'); return 1; } @@ -126,7 +127,7 @@ EOT $json->write($composerDefinition); } - $this->getIO()->writeError(''.$file.' has been '.($newlyCreated ? 'created' : 'updated').''); + $io->writeError(''.$file.' has been '.($newlyCreated ? 'created' : 'updated').''); if ($input->getOption('no-update')) { return 0; @@ -137,7 +138,6 @@ EOT $this->resetComposer(); $composer = $this->getComposer(); $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress')); - $io = $this->getIO(); $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); @@ -158,10 +158,10 @@ EOT $status = $install->run(); if ($status !== 0) { if ($newlyCreated) { - $this->getIO()->writeError("\n".'Installation failed, deleting '.$file.'.'); + $io->writeError("\n".'Installation failed, deleting '.$file.'.'); unlink($json->getPath()); } else { - $this->getIO()->writeError("\n".'Installation failed, reverting '.$file.' to its original content.'); + $io->writeError("\n".'Installation failed, reverting '.$file.' to its original content.'); file_put_contents($json->getPath(), $composerBackup); } } diff --git a/src/Composer/Command/RunScriptCommand.php b/src/Composer/Command/RunScriptCommand.php index 8b5b13d2a..5ad87bf40 100644 --- a/src/Composer/Command/RunScriptCommand.php +++ b/src/Composer/Command/RunScriptCommand.php @@ -104,9 +104,10 @@ EOT return 0; } - $this->getIO()->writeError('scripts:'); + $io = $this->getIO(); + $io->writeError('scripts:'); foreach ($scripts as $name => $script) { - $this->getIO()->write(' ' . $name); + $io->write(' ' . $name); } return 0; diff --git a/src/Composer/Command/SearchCommand.php b/src/Composer/Command/SearchCommand.php index 54990f30d..e636fc4d0 100644 --- a/src/Composer/Command/SearchCommand.php +++ b/src/Composer/Command/SearchCommand.php @@ -56,13 +56,14 @@ EOT { // init repos $platformRepo = new PlatformRepository; + $io = $this->getIO(); if ($composer = $this->getComposer(false)) { $localRepo = $composer->getRepositoryManager()->getLocalRepository(); $installedRepo = new CompositeRepository(array($localRepo, $platformRepo)); $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories())); } else { - $defaultRepos = Factory::createDefaultRepositories($this->getIO()); - $this->getIO()->writeError('No composer.json found in the current directory, showing packages from ' . implode(', ', array_keys($defaultRepos))); + $defaultRepos = Factory::createDefaultRepositories($io); + $io->writeError('No composer.json found in the current directory, showing packages from ' . implode(', ', array_keys($defaultRepos))); $installedRepo = $platformRepo; $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos)); } @@ -78,7 +79,7 @@ EOT $results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags); foreach ($results as $result) { - $this->getIO()->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : '')); + $io->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : '')); } } } diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index e4e96e8f4..35c1b85ce 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -60,7 +60,8 @@ EOT { $baseUrl = (extension_loaded('openssl') ? 'https' : 'http') . '://' . self::HOMEPAGE; $config = Factory::createConfig(); - $remoteFilesystem = new RemoteFilesystem($this->getIO(), $config); + $io = $this->getIO(); + $remoteFilesystem = new RemoteFilesystem($io, $config); $cacheDir = $config->get('cache-dir'); $rollbackDir = $config->get('home'); $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0]; @@ -84,13 +85,13 @@ EOT $updateVersion = $input->getArgument('version') ?: $latestVersion; if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) { - $this->getIO()->writeError('You can not update to a specific SHA-1 as those phars are not available for download'); + $io->writeError('You can not update to a specific SHA-1 as those phars are not available for download'); return 1; } if (Composer::VERSION === $updateVersion) { - $this->getIO()->writeError('You are already using composer version '.$updateVersion.'.'); + $io->writeError('You are already using composer version '.$updateVersion.'.'); return 0; } @@ -104,11 +105,11 @@ EOT self::OLD_INSTALL_EXT ); - $this->getIO()->writeError(sprintf("Updating to version %s.", $updateVersion)); + $io->writeError(sprintf("Updating to version %s.", $updateVersion)); $remoteFilename = $baseUrl . (preg_match('{^[0-9a-f]{40}$}', $updateVersion) ? '/composer.phar' : "/download/{$updateVersion}/composer.phar"); $remoteFilesystem->copy(self::HOMEPAGE, $remoteFilename, $tempFilename, !$input->getOption('no-progress')); if (!file_exists($tempFilename)) { - $this->getIO()->writeError('The download of the new composer version failed for an unexpected reason'); + $io->writeError('The download of the new composer version failed for an unexpected reason'); return 1; } @@ -120,22 +121,22 @@ EOT $fs = new Filesystem; foreach ($finder as $file) { $file = (string) $file; - $this->getIO()->writeError('Removing: '.$file.''); + $io->writeError('Removing: '.$file.''); $fs->remove($file); } } if ($err = $this->setLocalPhar($localFilename, $tempFilename, $backupFile)) { - $this->getIO()->writeError('The file is corrupted ('.$err->getMessage().').'); - $this->getIO()->writeError('Please re-run the self-update command to try again.'); + $io->writeError('The file is corrupted ('.$err->getMessage().').'); + $io->writeError('Please re-run the self-update command to try again.'); return 1; } if (file_exists($backupFile)) { - $this->getIO()->writeError('Use composer self-update --rollback to return to version '.Composer::VERSION); + $io->writeError('Use composer self-update --rollback to return to version '.Composer::VERSION); } else { - $this->getIO()->writeError('A backup of the current version could not be written to '.$backupFile.', no rollback possible'); + $io->writeError('A backup of the current version could not be written to '.$backupFile.', no rollback possible'); } } @@ -160,9 +161,10 @@ EOT } $oldFile = $rollbackDir . "/{$rollbackVersion}" . self::OLD_INSTALL_EXT; - $this->getIO()->writeError(sprintf("Rolling back to version %s.", $rollbackVersion)); + $io = $this->getIO(); + $io->writeError(sprintf("Rolling back to version %s.", $rollbackVersion)); if ($err = $this->setLocalPhar($localFilename, $oldFile)) { - $this->getIO()->writeError('The backup file was corrupted ('.$err->getMessage().') and has been removed.'); + $io->writeError('The backup file was corrupted ('.$err->getMessage().') and has been removed.'); return 1; } diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index 92811f07a..30d8797c8 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -71,6 +71,7 @@ EOT $platformRepo = new PlatformRepository; $composer = $this->getComposer(false); + $io = $this->getIO(); if ($input->getOption('self')) { $package = $this->getComposer()->getPackage(); $repos = $installedRepo = new ArrayRepository(array($package)); @@ -83,17 +84,17 @@ EOT if ($composer) { $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories()); } else { - $defaultRepos = Factory::createDefaultRepositories($this->getIO()); + $defaultRepos = Factory::createDefaultRepositories($io); $repos = new CompositeRepository($defaultRepos); - $this->getIO()->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos))); + $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos))); } } elseif ($composer) { $localRepo = $composer->getRepositoryManager()->getLocalRepository(); $installedRepo = new CompositeRepository(array($localRepo, $platformRepo)); $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories())); } else { - $defaultRepos = Factory::createDefaultRepositories($this->getIO()); - $this->getIO()->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos))); + $defaultRepos = Factory::createDefaultRepositories($io); + $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos))); $installedRepo = $platformRepo; $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos)); } @@ -120,9 +121,9 @@ EOT $this->printLinks($package, 'requires'); $this->printLinks($package, 'devRequires', 'requires (dev)'); if ($package->getSuggests()) { - $this->getIO()->write("\nsuggests"); + $io->write("\nsuggests"); foreach ($package->getSuggests() as $suggested => $reason) { - $this->getIO()->write($suggested . ' ' . $reason . ''); + $io->write($suggested . ' ' . $reason . ''); } } $this->printLinks($package, 'provides'); @@ -173,7 +174,7 @@ EOT foreach (array('platform:' => true, 'available:' => false, 'installed:' => true) as $type => $showVersion) { if (isset($packages[$type])) { if ($tree) { - $this->getIO()->write($type); + $io->write($type); } ksort($packages[$type]); @@ -197,7 +198,7 @@ EOT } if ($input->getOption('path') && null === $composer) { - $this->getIO()->writeError('No composer.json found in the current directory, disabling "path" option'); + $io->writeError('No composer.json found in the current directory, disabling "path" option'); $input->setOption('path', false); } @@ -228,10 +229,10 @@ EOT } else { $output->write($indent . $package); } - $this->getIO()->write(''); + $io->write(''); } if ($tree) { - $this->getIO()->write(''); + $io->write(''); } } } @@ -291,53 +292,54 @@ EOT */ protected function printMeta(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo) { - $this->getIO()->write('name : ' . $package->getPrettyName()); - $this->getIO()->write('descrip. : ' . $package->getDescription()); - $this->getIO()->write('keywords : ' . join(', ', $package->getKeywords() ?: array())); + $io = $this->getIO(); + $io->write('name : ' . $package->getPrettyName()); + $io->write('descrip. : ' . $package->getDescription()); + $io->write('keywords : ' . join(', ', $package->getKeywords() ?: array())); $this->printVersions($package, $versions, $installedRepo); - $this->getIO()->write('type : ' . $package->getType()); + $io->write('type : ' . $package->getType()); $this->printLicenses($package); - $this->getIO()->write('source : ' . sprintf('[%s] %s %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference())); - $this->getIO()->write('dist : ' . sprintf('[%s] %s %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference())); - $this->getIO()->write('names : ' . implode(', ', $package->getNames())); + $io->write('source : ' . sprintf('[%s] %s %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference())); + $io->write('dist : ' . sprintf('[%s] %s %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference())); + $io->write('names : ' . implode(', ', $package->getNames())); if ($package->isAbandoned()) { $replacement = ($package->getReplacementPackage() !== null) ? ' The author suggests using the ' . $package->getReplacementPackage(). ' package instead.' : null; - $this->getIO()->writeError( + $io->writeError( sprintf('Attention: This package is abandoned and no longer maintained.%s', $replacement) ); } if ($package->getSupport()) { - $this->getIO()->write("\nsupport"); + $io->write("\nsupport"); foreach ($package->getSupport() as $type => $value) { - $this->getIO()->write('' . $type . ' : '.$value); + $io->write('' . $type . ' : '.$value); } } if ($package->getAutoload()) { - $this->getIO()->write("\nautoload"); + $io->write("\nautoload"); foreach ($package->getAutoload() as $type => $autoloads) { - $this->getIO()->write('' . $type . ''); + $io->write('' . $type . ''); if ($type === 'psr-0') { foreach ($autoloads as $name => $path) { - $this->getIO()->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.'))); + $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.'))); } } elseif ($type === 'psr-4') { foreach ($autoloads as $name => $path) { - $this->getIO()->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.'))); + $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.'))); } } elseif ($type === 'classmap') { - $this->getIO()->write(implode(', ', $autoloads)); + $io->write(implode(', ', $autoloads)); } } if ($package->getIncludePaths()) { - $this->getIO()->write('include-path'); - $this->getIO()->write(implode(', ', $package->getIncludePaths())); + $io->write('include-path'); + $io->write(implode(', ', $package->getIncludePaths())); } } } @@ -374,11 +376,12 @@ EOT protected function printLinks(CompletePackageInterface $package, $linkType, $title = null) { $title = $title ?: $linkType; + $io = $this->getIO(); if ($links = $package->{'get'.ucfirst($linkType)}()) { - $this->getIO()->write("\n" . $title . ""); + $io->write("\n" . $title . ""); foreach ($links as $link) { - $this->getIO()->write($link->getTarget() . ' ' . $link->getPrettyConstraint() . ''); + $io->write($link->getTarget() . ' ' . $link->getPrettyConstraint() . ''); } } } @@ -393,6 +396,7 @@ EOT $spdxLicenses = new SpdxLicenses(); $licenses = $package->getLicense(); + $io = $this->getIO(); foreach ($licenses as $licenseId) { $license = $spdxLicenses->getLicenseByIdentifier($licenseId); // keys: 0 fullname, 1 osi, 2 url @@ -408,7 +412,7 @@ EOT } } - $this->getIO()->write('license : ' . $out); + $io->write('license : ' . $out); } } } diff --git a/src/Composer/Command/StatusCommand.php b/src/Composer/Command/StatusCommand.php index f17124226..7455e84b8 100644 --- a/src/Composer/Command/StatusCommand.php +++ b/src/Composer/Command/StatusCommand.php @@ -60,6 +60,7 @@ EOT $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_STATUS_CMD, true); $errors = array(); + $io = $this->getIO(); // list packages foreach ($installedRepo->getPackages() as $package) { @@ -80,9 +81,9 @@ EOT // output errors/warnings if (!$errors) { - $this->getIO()->writeError('No local changes'); + $io->writeError('No local changes'); } else { - $this->getIO()->writeError('You have changes in the following dependencies:'); + $io->writeError('You have changes in the following dependencies:'); } foreach ($errors as $path => $changes) { @@ -90,15 +91,15 @@ EOT $indentedChanges = implode("\n", array_map(function ($line) { return ' ' . ltrim($line); }, explode("\n", $changes))); - $this->getIO()->write(''.$path.':'); - $this->getIO()->write($indentedChanges); + $io->write(''.$path.':'); + $io->write($indentedChanges); } else { - $this->getIO()->write($path); + $io->write($path); } } if ($errors && !$input->getOption('verbose')) { - $this->getIO()->writeError('Use --verbose (-v) to see modified files'); + $io->writeError('Use --verbose (-v) to see modified files'); } // Dispatch post-status-command diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index 579236143..32968a56c 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -74,18 +74,18 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { + $io = $this->getIO(); if ($input->getOption('no-custom-installers')) { - $this->getIO()->writeError('You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.'); + $io->writeError('You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.'); $input->setOption('no-plugins', true); } if ($input->getOption('dev')) { - $this->getIO()->writeError('You are using the deprecated option "dev". Dev packages are installed by default now.'); + $io->writeError('You are using the deprecated option "dev". Dev packages are installed by default now.'); } $composer = $this->getComposer(true, $input->getOption('no-plugins')); $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress')); - $io = $this->getIO(); $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); diff --git a/src/Composer/Command/ValidateCommand.php b/src/Composer/Command/ValidateCommand.php index 8a1595a04..a26f1a868 100644 --- a/src/Composer/Command/ValidateCommand.php +++ b/src/Composer/Command/ValidateCommand.php @@ -58,19 +58,20 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { $file = $input->getArgument('file'); + $io = $this->getIO(); if (!file_exists($file)) { - $this->getIO()->writeError('' . $file . ' not found.'); + $io->writeError('' . $file . ' not found.'); return 1; } if (!is_readable($file)) { - $this->getIO()->writeError('' . $file . ' is not readable.'); + $io->writeError('' . $file . ' is not readable.'); return 1; } - $validator = new ConfigValidator($this->getIO()); + $validator = new ConfigValidator($io); $checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL; $checkPublish = !$input->getOption('no-check-publish'); list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll); @@ -78,7 +79,7 @@ EOT $checkLock = !$input->getOption('no-check-lock'); $lockErrors = array(); - $composer = Factory::create($this->getIO(), $file); + $composer = Factory::create($io, $file); $locker = $composer->getLocker(); if ($locker->isLocked() && !$locker->isFresh()) { $lockErrors[] = 'The lock file is not up to date with the latest changes in composer.json.'; @@ -86,16 +87,16 @@ EOT // output errors/warnings if (!$errors && !$publishErrors && !$warnings) { - $this->getIO()->write('' . $file . ' is valid'); + $io->write('' . $file . ' is valid'); } elseif (!$errors && !$publishErrors) { - $this->getIO()->writeError('' . $file . ' is valid, but with a few warnings'); - $this->getIO()->writeError('See https://getcomposer.org/doc/04-schema.md for details on the schema'); + $io->writeError('' . $file . ' is valid, but with a few warnings'); + $io->writeError('See https://getcomposer.org/doc/04-schema.md for details on the schema'); } elseif (!$errors) { - $this->getIO()->writeError('' . $file . ' is valid for simple usage with composer but has'); - $this->getIO()->writeError('strict errors that make it unable to be published as a package:'); - $this->getIO()->writeError('See https://getcomposer.org/doc/04-schema.md for details on the schema'); + $io->writeError('' . $file . ' is valid for simple usage with composer but has'); + $io->writeError('strict errors that make it unable to be published as a package:'); + $io->writeError('See https://getcomposer.org/doc/04-schema.md for details on the schema'); } else { - $this->getIO()->writeError('' . $file . ' is invalid, the following errors/warnings were found:'); + $io->writeError('' . $file . ' is invalid, the following errors/warnings were found:'); } $messages = array( @@ -119,7 +120,7 @@ EOT foreach ($messages as $style => $msgs) { foreach ($msgs as $msg) { - $this->getIO()->writeError('<' . $style . '>' . $msg . ''); + $io->writeError('<' . $style . '>' . $msg . ''); } } diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index 91ad1f9d4..84e03f754 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -89,9 +89,10 @@ class Application extends BaseApplication { $this->io = new ConsoleIO($input, $output, $this->getHelperSet()); ErrorHandler::register($this->io); + $io = $this->getIO(); if (PHP_VERSION_ID < 50302) { - $this->getIO()->writeError('Composer only officially supports PHP 5.3.2 and above, you will most likely encounter problems with your PHP '.PHP_VERSION.', upgrading is strongly recommended.'); + $io->writeError('Composer only officially supports PHP 5.3.2 and above, you will most likely encounter problems with your PHP '.PHP_VERSION.', upgrading is strongly recommended.'); } if (defined('COMPOSER_DEV_WARNING_TIME')) { @@ -104,7 +105,7 @@ class Application extends BaseApplication } if ($commandName !== 'self-update' && $commandName !== 'selfupdate') { if (time() > COMPOSER_DEV_WARNING_TIME) { - $this->getIO()->writeError(sprintf('Warning: This development build of composer is over 60 days old. It is recommended to update it by running "%s self-update" to get the latest version.', $_SERVER['PHP_SELF'])); + $io->writeError(sprintf('Warning: This development build of composer is over 60 days old. It is recommended to update it by running "%s self-update" to get the latest version.', $_SERVER['PHP_SELF'])); } } } @@ -117,8 +118,8 @@ class Application extends BaseApplication if ($newWorkDir = $this->getNewWorkingDir($input)) { $oldWorkingDir = getcwd(); chdir($newWorkDir); - if ($this->getIO()->isDebug() >= 4) { - $this->getIO()->writeError('Changed CWD to ' . getcwd()); + if ($io->isDebug() >= 4) { + $io->writeError('Changed CWD to ' . getcwd()); } } @@ -129,7 +130,7 @@ class Application extends BaseApplication foreach ($composer['scripts'] as $script => $dummy) { if (!defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) { if ($this->has($script)) { - $this->getIO()->writeError('A script named '.$script.' would override a native Composer function and has been skipped'); + $io->writeError('A script named '.$script.' would override a native Composer function and has been skipped'); } else { $this->add(new Command\ScriptAliasCommand($script)); } @@ -150,7 +151,7 @@ class Application extends BaseApplication } if (isset($startTime)) { - $this->getIO()->writeError('Memory usage: '.round(memory_get_usage() / 1024 / 1024, 2).'MB (peak: '.round(memory_get_peak_usage() / 1024 / 1024, 2).'MB), time: '.round(microtime(true) - $startTime, 2).'s'); + $io->writeError('Memory usage: '.round(memory_get_usage() / 1024 / 1024, 2).'MB (peak: '.round(memory_get_peak_usage() / 1024 / 1024, 2).'MB), time: '.round(microtime(true) - $startTime, 2).'s'); } return $result; @@ -176,6 +177,8 @@ class Application extends BaseApplication */ public function renderException($exception, $output) { + $io = $this->getIO(); + try { $composer = $this->getComposer(false, true); if ($composer) { @@ -186,20 +189,20 @@ class Application extends BaseApplication || (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree) || (($df = @disk_free_space($dir = sys_get_temp_dir())) !== false && $df < $minSpaceFree) ) { - $this->getIO()->writeError('The disk hosting '.$dir.' is full, this may be the cause of the following exception'); + $io->writeError('The disk hosting '.$dir.' is full, this may be the cause of the following exception'); } } } catch (\Exception $e) { } if (defined('PHP_WINDOWS_VERSION_BUILD') && false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) { - $this->getIO()->writeError('The following exception may be caused by a stale entry in your cmd.exe AutoRun'); - $this->getIO()->writeError('Check https://getcomposer.org/doc/articles/troubleshooting.md#-the-system-cannot-find-the-path-specified-windows- for details'); + $io->writeError('The following exception may be caused by a stale entry in your cmd.exe AutoRun'); + $io->writeError('Check https://getcomposer.org/doc/articles/troubleshooting.md#-the-system-cannot-find-the-path-specified-windows- for details'); } if (false !== strpos($exception->getMessage(), 'fork failed - Cannot allocate memory')) { - $this->getIO()->writeError('The following exception is caused by a lack of memory and not having swap configured'); - $this->getIO()->writeError('Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details'); + $io->writeError('The following exception is caused by a lack of memory and not having swap configured'); + $io->writeError('Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details'); } if ($output instanceof ConsoleOutputInterface) { From d0a9550dea3235ea6ee1927840fab9644a6c9da0 Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Mon, 14 Sep 2015 15:20:06 +0100 Subject: [PATCH 156/205] Uses `realpath` to fix relative path issues --- src/Composer/Downloader/PathDownloader.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Composer/Downloader/PathDownloader.php b/src/Composer/Downloader/PathDownloader.php index c58a3f23a..409a27cae 100644 --- a/src/Composer/Downloader/PathDownloader.php +++ b/src/Composer/Downloader/PathDownloader.php @@ -39,18 +39,19 @@ class PathDownloader extends FileDownloader )); $url = $package->getDistUrl(); - if (!file_exists($url) || !is_dir($url)) { + $realUrl = realpath($url); + if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) { throw new \RuntimeException(sprintf( 'Path "%s" is not found', - $path + $url )); } try { - $fileSystem->symlink($url, $path); + $fileSystem->symlink($realUrl, $path); $this->io->writeError(sprintf(' Symlinked from %s', $url)); } catch (IOException $e) { - $fileSystem->mirror($url, $path); + $fileSystem->mirror($realUrl, $path); $this->io->writeError(sprintf(' Mirrored from %s', $url)); } From 323537ad0fc59e0abb91cfffb0e3795657eba283 Mon Sep 17 00:00:00 2001 From: Dennis Birkholz Date: Tue, 15 Sep 2015 16:41:07 +0200 Subject: [PATCH 157/205] Allow wildcards in repository path names. --- src/Composer/Repository/PathRepository.php | 53 ++++++++++--------- .../Fixtures/path/with-version/composer.json | 2 +- .../path/without-version/composer.json | 2 +- .../Test/Repository/PathRepositoryTest.php | 26 ++++++++- 4 files changed, 54 insertions(+), 29 deletions(-) diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index 8e0b2edca..f2753241a 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -97,36 +97,39 @@ class PathRepository extends ArrayRepository { parent::initialize(); - $path = $this->getPath(); - $composerFilePath = $path.'composer.json'; - if (!file_exists($composerFilePath)) { - throw new \RuntimeException(sprintf('No `composer.json` file found in path repository "%s"', $path)); + foreach ($this->getPaths() as $path) { + $composerFilePath = $path.'composer.json'; + if (!file_exists($composerFilePath)) { + continue; + } + + $json = file_get_contents($composerFilePath); + $package = JsonFile::parseJson($json, $composerFilePath); + $package['dist'] = array( + 'type' => 'path', + 'url' => $this->url, + 'reference' => '', + ); + + if (!isset($package['version'])) { + $package['version'] = $this->versionGuesser->guessVersion($package, $path) ?: 'dev-master'; + } + if (is_dir($path.'/.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $path)) { + $package['dist']['reference'] = trim($output); + } + + $package = $this->loader->load($package); + $this->addPackage($package); } - - $json = file_get_contents($composerFilePath); - $package = JsonFile::parseJson($json, $composerFilePath); - $package['dist'] = array( - 'type' => 'path', - 'url' => $this->url, - 'reference' => '', - ); - - if (!isset($package['version'])) { - $package['version'] = $this->versionGuesser->guessVersion($package, $path) ?: 'dev-master'; - } - if (is_dir($path.'/.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $path)) { - $package['dist']['reference'] = trim($output); - } - - $package = $this->loader->load($package); - $this->addPackage($package); } /** - * @return string + * Get a list of all absolute path names matching the supplied urls + * + * @return string[] */ - private function getPath() + private function getPaths() { - return realpath(rtrim($this->url, '/')) . '/'; + return glob($this->url, GLOB_MARK|GLOB_ONLYDIR); } } diff --git a/tests/Composer/Test/Repository/Fixtures/path/with-version/composer.json b/tests/Composer/Test/Repository/Fixtures/path/with-version/composer.json index fa853d690..985b89947 100644 --- a/tests/Composer/Test/Repository/Fixtures/path/with-version/composer.json +++ b/tests/Composer/Test/Repository/Fixtures/path/with-version/composer.json @@ -1,4 +1,4 @@ { - "name": "test/path", + "name": "test/path-versioned", "version": "0.0.2" } \ No newline at end of file diff --git a/tests/Composer/Test/Repository/Fixtures/path/without-version/composer.json b/tests/Composer/Test/Repository/Fixtures/path/without-version/composer.json index 2fcbad12a..cddefceb2 100644 --- a/tests/Composer/Test/Repository/Fixtures/path/without-version/composer.json +++ b/tests/Composer/Test/Repository/Fixtures/path/without-version/composer.json @@ -1,3 +1,3 @@ { - "name": "test/path" + "name": "test/path-unversioned" } \ No newline at end of file diff --git a/tests/Composer/Test/Repository/PathRepositoryTest.php b/tests/Composer/Test/Repository/PathRepositoryTest.php index fb64e458b..03ad46fea 100644 --- a/tests/Composer/Test/Repository/PathRepositoryTest.php +++ b/tests/Composer/Test/Repository/PathRepositoryTest.php @@ -35,7 +35,7 @@ class PathRepositoryTest extends TestCase $repository->getPackages(); $this->assertEquals(1, $repository->count()); - $this->assertTrue($repository->hasPackage($this->getPackage('test/path', '0.0.2'))); + $this->assertTrue($repository->hasPackage($this->getPackage('test/path-versioned', '0.0.2'))); } public function testLoadPackageFromFileSystemWithoutVersion() @@ -54,9 +54,31 @@ class PathRepositoryTest extends TestCase $this->assertEquals(1, $repository->count()); $package = $packages[0]; - $this->assertEquals('test/path', $package->getName()); + $this->assertEquals('test/path-unversioned', $package->getName()); $packageVersion = $package->getVersion(); $this->assertTrue(!empty($packageVersion)); } + + public function testLoadPackageFromFileSystemWithWildcard() + { + $ioInterface = $this->getMockBuilder('Composer\IO\IOInterface') + ->getMock(); + + $config = new \Composer\Config(); + $loader = new ArrayLoader(new VersionParser()); + $versionGuesser = null; + + $repositoryUrl = implode(DIRECTORY_SEPARATOR, array(__DIR__, 'Fixtures', 'path', '*')); + $repository = new PathRepository(array('url' => $repositoryUrl), $ioInterface, $config, $loader); + $packages = $repository->getPackages(); + + $this->assertEquals(2, $repository->count()); + + $package = $packages[0]; + $this->assertEquals('test/path-versioned', $package->getName()); + + $package = $packages[1]; + $this->assertEquals('test/path-unversioned', $package->getName()); + } } From dd0070af98525eef36e3ed5c175165e4c7dfcf3b Mon Sep 17 00:00:00 2001 From: Gabriele Santini Date: Tue, 15 Sep 2015 16:44:41 +0200 Subject: [PATCH 158/205] Update 05-repositories.md fix typo --- doc/05-repositories.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/05-repositories.md b/doc/05-repositories.md index 5dae47295..a9e1c98e1 100644 --- a/doc/05-repositories.md +++ b/doc/05-repositories.md @@ -608,8 +608,8 @@ update to the latest version. ### Path -In addition to the artifact repository, you can use the path one, which allow -you to depends on a relative directory. This can be especially useful when dealing +In addition to the artifact repository, you can use the path one, which allows +you to depend on a relative directory. This can be especially useful when dealing with monolith repositories. For instance, if you have the following directory structure in your repository: From 4209fd2e4aaf7951712d3749effd27d8f9f45216 Mon Sep 17 00:00:00 2001 From: Dennis Birkholz Date: Tue, 15 Sep 2015 17:27:36 +0200 Subject: [PATCH 159/205] Store correct url for package, not original url containing wildcards. --- src/Composer/Repository/PathRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index f2753241a..81de87866 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -107,7 +107,7 @@ class PathRepository extends ArrayRepository $package = JsonFile::parseJson($json, $composerFilePath); $package['dist'] = array( 'type' => 'path', - 'url' => $this->url, + 'url' => $path, 'reference' => '', ); From 1d7fa565e64d154dd1b43b802dff102a1369d12b Mon Sep 17 00:00:00 2001 From: Dennis Birkholz Date: Tue, 15 Sep 2015 17:33:31 +0200 Subject: [PATCH 160/205] Fix check for flag in case RELATIVE_PATHS should be changed somehow --- src/Composer/Config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Config.php b/src/Composer/Config.php index a6bb51b99..819b7cd12 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -180,7 +180,7 @@ class Config return $val; } - return ($flags & self::RELATIVE_PATHS == 1) ? $val : $this->realpath($val); + return ($flags & self::RELATIVE_PATHS == self::RELATIVE_PATHS) ? $val : $this->realpath($val); case 'cache-ttl': return (int) $this->config[$key]; From e4435790a4055c58f60200c34b527f649455b311 Mon Sep 17 00:00:00 2001 From: Dennis Birkholz Date: Tue, 15 Sep 2015 17:39:55 +0200 Subject: [PATCH 161/205] Documentation --- doc/05-repositories.md | 7 +++++-- src/Composer/Repository/PathRepository.php | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/doc/05-repositories.md b/doc/05-repositories.md index 5dae47295..8e0442bd8 100644 --- a/doc/05-repositories.md +++ b/doc/05-repositories.md @@ -608,8 +608,8 @@ update to the latest version. ### Path -In addition to the artifact repository, you can use the path one, which allow -you to depends on a relative directory. This can be especially useful when dealing +In addition to the artifact repository, you can use the path one, which allows +you to depend on a relative directory. This can be especially useful when dealing with monolith repositories. For instance, if you have the following directory structure in your repository: @@ -639,6 +639,9 @@ file, you can use the following configuration: } ``` +Repository paths can also contain wildcards like ``*`` and ``?``. +For details, see the [PHP glob function](http://php.net/glob). + ## Disabling Packagist You can disable the default Packagist repository by adding this to your diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index 81de87866..94df63104 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -38,6 +38,10 @@ use Composer\Util\ProcessExecutor; * { * "type": "path", * "url": "/absolute/path/to/package/" + * }, + * { + * "type": "path", + * "url": "/absolute/path/to/several/packages/*" * } * ] * @endcode From c06edd61e4f6e2e93273809a7da32d12922b3b71 Mon Sep 17 00:00:00 2001 From: Dennis Birkholz Date: Tue, 15 Sep 2015 18:28:17 +0200 Subject: [PATCH 162/205] Fail if no repository was found --- src/Composer/Repository/PathRepository.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index 94df63104..1abca00b6 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -101,12 +101,15 @@ class PathRepository extends ArrayRepository { parent::initialize(); + $foundPackage = false; + foreach ($this->getPaths() as $path) { $composerFilePath = $path.'composer.json'; if (!file_exists($composerFilePath)) { continue; } + $foundPackage = true; $json = file_get_contents($composerFilePath); $package = JsonFile::parseJson($json, $composerFilePath); $package['dist'] = array( @@ -125,6 +128,10 @@ class PathRepository extends ArrayRepository $package = $this->loader->load($package); $this->addPackage($package); } + + if (!$foundPackage) { + throw new \RuntimeException(sprintf('No `composer.json` file found in any path repository in "%s"', $this->url)); + } } /** From f6d5d65bcdbf472bb16006567d25c18e75d431c7 Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Wed, 16 Sep 2015 10:06:32 +0100 Subject: [PATCH 163/205] Use shortest relative paths for symlinks --- src/Composer/Downloader/PathDownloader.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Composer/Downloader/PathDownloader.php b/src/Composer/Downloader/PathDownloader.php index 409a27cae..3ff47da8e 100644 --- a/src/Composer/Downloader/PathDownloader.php +++ b/src/Composer/Downloader/PathDownloader.php @@ -48,7 +48,8 @@ class PathDownloader extends FileDownloader } try { - $fileSystem->symlink($realUrl, $path); + $shortestPath = $this->filesystem->findShortestPath($path, $realUrl); + $fileSystem->symlink($shortestPath, $path); $this->io->writeError(sprintf(' Symlinked from %s', $url)); } catch (IOException $e) { $fileSystem->mirror($realUrl, $path); From 0cbf679f2150c622af3807a90f39912479cf6561 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 17 Sep 2015 14:45:50 +0100 Subject: [PATCH 164/205] Avoid failing to write the lock file if a lock file is present but corrupt/conflicted --- src/Composer/Package/Locker.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Composer/Package/Locker.php b/src/Composer/Package/Locker.php index 6ef0fe979..a3c8baf32 100644 --- a/src/Composer/Package/Locker.php +++ b/src/Composer/Package/Locker.php @@ -21,6 +21,7 @@ use Composer\Package\Dumper\ArrayDumper; use Composer\Package\Loader\ArrayLoader; use Composer\Util\Git as GitUtil; use Composer\IO\IOInterface; +use Seld\JsonLint\ParsingException; /** * Reads/writes project lockfile (composer.lock). @@ -286,7 +287,12 @@ class Locker return false; } - if (!$this->isLocked() || $lock !== $this->getLockData()) { + try { + $isLocked = $this->isLocked(); + } catch (ParsingException $e) { + $isLocked = false; + } + if (!$isLocked || $lock !== $this->getLockData()) { $this->lockFile->write($lock); $this->lockDataCache = null; From 2db52ebebab221fe6e5c56cfa730444ad5bc3c2d Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Fri, 18 Sep 2015 12:04:21 +0200 Subject: [PATCH 165/205] Also update source type and reference when changing URLs --- src/Composer/Installer.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index a61475f3c..667d60d96 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -1023,7 +1023,9 @@ class Installer $newPackage = $pool->literalToPackage($matches[0]); // update the dist and source URLs + $package->setSourceType($newPackage->getSourceType()); $package->setSourceUrl($newPackage->getSourceUrl()); + $package->setSourceReference($newPackage->getSourceReference()); // only update dist url for github/bitbucket dists as they use a combination of dist url + dist reference to install // but for other urls this is ambiguous and could result in bad outcomes if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}', $newPackage->getDistUrl())) { From 17636d1bd243f50a6820ec7c3f32a1ae59239b57 Mon Sep 17 00:00:00 2001 From: Dennis Birkholz Date: Fri, 18 Sep 2015 14:23:54 +0200 Subject: [PATCH 166/205] Use 'note' box to inform about wildcards --- doc/05-repositories.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/05-repositories.md b/doc/05-repositories.md index 8e0442bd8..9308e1279 100644 --- a/doc/05-repositories.md +++ b/doc/05-repositories.md @@ -639,8 +639,8 @@ file, you can use the following configuration: } ``` -Repository paths can also contain wildcards like ``*`` and ``?``. -For details, see the [PHP glob function](http://php.net/glob). +> **Note:** Repository paths can also contain wildcards like ``*`` and ``?``. +> For details, see the [PHP glob function](http://php.net/glob). ## Disabling Packagist From 19146d1cecaeee46700eb272000a55e47a23975c Mon Sep 17 00:00:00 2001 From: Dennis Birkholz Date: Fri, 18 Sep 2015 14:26:01 +0200 Subject: [PATCH 167/205] Docblock fix as suggested by @alcohol --- src/Composer/Repository/PathRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index 1abca00b6..5f9fc0a53 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -135,7 +135,7 @@ class PathRepository extends ArrayRepository } /** - * Get a list of all absolute path names matching the supplied urls + * Get a list of all absolute path names matching given url (supports globbing). * * @return string[] */ From 973491b65df45a5f82c125aaae0427da1b0dda30 Mon Sep 17 00:00:00 2001 From: Dennis Birkholz Date: Fri, 18 Sep 2015 14:29:42 +0200 Subject: [PATCH 168/205] Fix docblock, path names returned by glob() are not necessary absolute --- src/Composer/Repository/PathRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index 5f9fc0a53..665e4037b 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -135,7 +135,7 @@ class PathRepository extends ArrayRepository } /** - * Get a list of all absolute path names matching given url (supports globbing). + * Get a list of all path names matching given url (supports globbing). * * @return string[] */ From 3ef222c9201e990aa380930802678467c558401f Mon Sep 17 00:00:00 2001 From: Dennis Birkholz Date: Fri, 18 Sep 2015 15:01:06 +0200 Subject: [PATCH 169/205] Make repository path absolute (again) --- src/Composer/Repository/PathRepository.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index 665e4037b..891320118 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -104,6 +104,8 @@ class PathRepository extends ArrayRepository $foundPackage = false; foreach ($this->getPaths() as $path) { + $path = realpath($path); + $composerFilePath = $path.'composer.json'; if (!file_exists($composerFilePath)) { continue; From 2fb7dd881a9f692379b493280515497bef82c482 Mon Sep 17 00:00:00 2001 From: Dennis Birkholz Date: Fri, 18 Sep 2015 15:03:15 +0200 Subject: [PATCH 170/205] Fix missing trailing / in repository paths --- src/Composer/Repository/PathRepository.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index 891320118..5e4b1d931 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -104,8 +104,8 @@ class PathRepository extends ArrayRepository $foundPackage = false; foreach ($this->getPaths() as $path) { - $path = realpath($path); - + $path = realpath($path) . '/'; + $composerFilePath = $path.'composer.json'; if (!file_exists($composerFilePath)) { continue; From 2c926741f95bfbe6839a710f4c2e5b58f331a830 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 18 Sep 2015 14:21:22 +0100 Subject: [PATCH 171/205] Add appveyor config --- appveyor.yml | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..0adc717bb --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,49 @@ +build: false +shallow_clone: true +platform: x86 +clone_folder: c:\projects\composer + +environment: + matrix: + - PHP_EXT: 1 + - PHP_EXT: 0 + +cache: + - c:\php -> appveyor.yml + - .phpunit -> phpunit + +init: + - SET PATH=c:\php;%PATH% + - SET COMPOSER_NO_INTERACTION=1 + - SET PHP=1 + - SET ANSICON=121x90 (121x90) + +install: + - IF EXIST c:\php (SET PHP=0) ELSE (mkdir c:\php) + - cd c:\php + - IF %PHP%==1 appveyor DownloadFile http://windows.php.net/downloads/releases/archives/php-5.3.11-nts-Win32-VC9-x86.zip + - IF %PHP%==1 7z x php-5.3.11-nts-Win32-VC9-x86.zip -y > 7z.log + - IF %PHP%==1 appveyor DownloadFile http://nebm.ist.utl.pt/~glopes/misc/intl_win/ICU-51.2-dlls.zip + - IF %PHP%==1 7z x ICU-51.2-dlls.zip -y > 7z.log + - IF %PHP%==1 cd ext + - IF %PHP%==1 appveyor DownloadFile http://nebm.ist.utl.pt/~glopes/misc/intl_win/php_intl-3.0.0-5.3-nts-vc9-x86.zip + - IF %PHP%==1 7z x php_intl-3.0.0-5.3-nts-vc9-x86.zip -y > 7z.log + - IF %PHP%==1 appveyor DownloadFile http://windows.php.net/downloads/pecl/releases/apc/3.1.13/php_apc-3.1.13-5.3-nts-vc9-x86.zip + - IF %PHP%==1 7z x php_apc-3.1.13-5.3-nts-vc9-x86.zip -y > 7z.log + - IF %PHP%==1 cd .. + - IF %PHP%==1 echo @php %%~dp0composer.phar %%* > composer.bat + - appveyor DownloadFile https://getcomposer.org/composer.phar + - copy php.ini-production php.ini /Y + - echo date.timezone="UTC" >> php.ini + - echo extension_dir=ext >> php.ini + - echo extension=php_openssl.dll >> php.ini + - IF %PHP_EXT%==1 echo extension=php_apc.dll >> php.ini + - IF %PHP_EXT%==1 echo extension=php_intl.dll >> php.ini + - IF %PHP_EXT%==1 echo extension=php_mbstring.dll >> php.ini + - IF %PHP_EXT%==1 echo extension=php_fileinfo.dll >> php.ini + - cd c:\projects\composer + - composer install --prefer-source --no-progress + +test_script: + - cd c:\projects\composer + - php phpunit -c tests/complete.phpunit.xml --colors=always From ede458b403d73eeea1796b3726a3d1c556026b27 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 18 Sep 2015 14:25:05 +0100 Subject: [PATCH 172/205] Appveyor tweaks --- appveyor.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 0adc717bb..18cb04d2a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,7 +10,6 @@ environment: cache: - c:\php -> appveyor.yml - - .phpunit -> phpunit init: - SET PATH=c:\php;%PATH% @@ -46,4 +45,4 @@ install: test_script: - cd c:\projects\composer - - php phpunit -c tests/complete.phpunit.xml --colors=always + - vendor/bin/phpunit -c tests/complete.phpunit.xml --colors=always From 3c08318ea0613eb52311d13a1133c0faa01bf003 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Fri, 18 Sep 2015 15:31:54 +0200 Subject: [PATCH 173/205] Add test --- src/Composer/Installer.php | 12 +++- .../update-picks-up-change-of-vcs-type.test | 57 +++++++++++++++++++ 2 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 tests/Composer/Test/Fixtures/installer/update-picks-up-change-of-vcs-type.test diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 667d60d96..eacc0fe0e 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -1023,9 +1023,15 @@ class Installer $newPackage = $pool->literalToPackage($matches[0]); // update the dist and source URLs - $package->setSourceType($newPackage->getSourceType()); - $package->setSourceUrl($newPackage->getSourceUrl()); - $package->setSourceReference($newPackage->getSourceReference()); + $sourceUrl = $package->getSourceUrl(); + $newSourceUrl = $newPackage->getSourceUrl(); + + if ($sourceUrl !== $newSourceUrl) { + $package->setSourceType($newPackage->getSourceType()); + $package->setSourceUrl($newSourceUrl); + $package->setSourceReference($newPackage->getSourceReference()); + } + // only update dist url for github/bitbucket dists as they use a combination of dist url + dist reference to install // but for other urls this is ambiguous and could result in bad outcomes if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}', $newPackage->getDistUrl())) { diff --git a/tests/Composer/Test/Fixtures/installer/update-picks-up-change-of-vcs-type.test b/tests/Composer/Test/Fixtures/installer/update-picks-up-change-of-vcs-type.test new file mode 100644 index 000000000..1e528d047 --- /dev/null +++ b/tests/Composer/Test/Fixtures/installer/update-picks-up-change-of-vcs-type.test @@ -0,0 +1,57 @@ +--TEST-- +Converting from one VCS type to another (including an URL change) should update the lock file. +--COMPOSER-- +{ + "repositories": [ + { + "type": "package", + "package": [ + { + "name": "a/a", "version": "1.0.0", + "source": { "reference": "new-git-ref", "type": "git", "url": "new-git-url" } + } + ] + } + ], + "require": { + "a/a": "1.0.0" + } +} +--INSTALLED-- +[ + { + "name": "a/a", "version": "1.0.0", + "source": { "reference": "old-hg-ref", "type": "hg", "url": "old-hg-url" } + } +] +--LOCK-- +{ + "packages": [ + { + "name": "a/a", "version": "1.0.0", + "source": { "reference": "old-hg-ref", "type": "hg", "url": "old-hg-url" } + } + ] +} +--RUN-- +update +--EXPECT-LOCK-- +{ + "packages": [ + { + "name": "a/a", "version": "1.0.0", + "source": { "reference": "new-git-ref", "type": "git", "url": "new-git-url" }, + "type": "library" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} +--EXPECT-- + From c96a031dab7ad4e08ab874b34893a00cc7a1d713 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 18 Sep 2015 14:33:13 +0100 Subject: [PATCH 174/205] Run only the basic test suite on appveyor --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 18cb04d2a..024d26047 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -45,4 +45,4 @@ install: test_script: - cd c:\projects\composer - - vendor/bin/phpunit -c tests/complete.phpunit.xml --colors=always + - vendor/bin/phpunit --colors=always From 6b1c9882dd113f630c2dcf69115e02887f5e2a27 Mon Sep 17 00:00:00 2001 From: Dennis Birkholz Date: Fri, 18 Sep 2015 17:26:31 +0200 Subject: [PATCH 175/205] Replace tracking variable with direct package count check --- src/Composer/Repository/PathRepository.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index 5e4b1d931..b4b08b152 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -101,8 +101,6 @@ class PathRepository extends ArrayRepository { parent::initialize(); - $foundPackage = false; - foreach ($this->getPaths() as $path) { $path = realpath($path) . '/'; @@ -111,7 +109,6 @@ class PathRepository extends ArrayRepository continue; } - $foundPackage = true; $json = file_get_contents($composerFilePath); $package = JsonFile::parseJson($json, $composerFilePath); $package['dist'] = array( @@ -131,7 +128,7 @@ class PathRepository extends ArrayRepository $this->addPackage($package); } - if (!$foundPackage) { + if (count($this) == 0) { throw new \RuntimeException(sprintf('No `composer.json` file found in any path repository in "%s"', $this->url)); } } From 681e543793d402f712d033a2cc4530a064ccad70 Mon Sep 17 00:00:00 2001 From: Dennis Birkholz Date: Fri, 18 Sep 2015 17:55:07 +0200 Subject: [PATCH 176/205] Make check more obvious --- src/Composer/Repository/PathRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index b4b08b152..a76a2e052 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -128,7 +128,7 @@ class PathRepository extends ArrayRepository $this->addPackage($package); } - if (count($this) == 0) { + if (count($this->getPackages()) == 0) { throw new \RuntimeException(sprintf('No `composer.json` file found in any path repository in "%s"', $this->url)); } } From 620e629ec321c6e74df11993acb3be3aa705b172 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 20 Sep 2015 14:11:09 +0100 Subject: [PATCH 177/205] Update some more descriptions, refs #4114 --- doc/articles/scripts.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index 510f9de7c..14e5b5a63 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -23,26 +23,26 @@ Composer fires the following named events during its execution process: ### Command Events - **pre-install-cmd**: occurs before the `install` command is executed. -- **post-install-cmd**: occurs after the `install` command is executed. +- **post-install-cmd**: occurs after the `install` command has been executed. - **pre-update-cmd**: occurs before the `update` command is executed. -- **post-update-cmd**: occurs after the `update` command is executed. +- **post-update-cmd**: occurs after the `update` command has been executed. - **pre-status-cmd**: occurs before the `status` command is executed. -- **post-status-cmd**: occurs after the `status` command is executed. +- **post-status-cmd**: occurs after the `status` command has been executed. - **pre-archive-cmd**: occurs before the `archive` command is executed. -- **post-archive-cmd**: occurs after the `archive` command is executed. +- **post-archive-cmd**: occurs after the `archive` command has been executed. - **pre-autoload-dump**: occurs before the autoloader is dumped, either during `install`/`update`, or via the `dump-autoload` command. -- **post-autoload-dump**: occurs after the autoloader is dumped, either +- **post-autoload-dump**: occurs after the autoloader has been dumped, either during `install`/`update`, or via the `dump-autoload` command. - **post-root-package-install**: occurs after the root package has been installed, during the `create-project` command. -- **post-create-project-cmd**: occurs after the `create-project` command is - executed. +- **post-create-project-cmd**: occurs after the `create-project` command has + been executed. ### Installer Events - **pre-dependencies-solving**: occurs before the dependencies are resolved. -- **post-dependencies-solving**: occurs after the dependencies are resolved. +- **post-dependencies-solving**: occurs after the dependencies have been resolved. ### Package Events From 1e8d7255b7d50238b95eb41b86ac49ecd2f10aba Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 20 Sep 2015 17:38:37 +0100 Subject: [PATCH 178/205] Fix access to undefined var, refs #4422 --- src/Composer/Command/RemoveCommand.php | 4 ++-- src/Composer/Command/RequireCommand.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Composer/Command/RemoveCommand.php b/src/Composer/Command/RemoveCommand.php index 40776bcba..869720718 100644 --- a/src/Composer/Command/RemoveCommand.php +++ b/src/Composer/Command/RemoveCommand.php @@ -101,8 +101,8 @@ EOT $install = Installer::create($io, $composer); $updateDevMode = !$input->getOption('update-no-dev'); - $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader'); - $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative'); + $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader'); + $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative'); $install ->setVerbose($input->getOption('verbose')) diff --git a/src/Composer/Command/RequireCommand.php b/src/Composer/Command/RequireCommand.php index 04af94129..4499904bb 100644 --- a/src/Composer/Command/RequireCommand.php +++ b/src/Composer/Command/RequireCommand.php @@ -135,8 +135,8 @@ EOT return 0; } $updateDevMode = !$input->getOption('update-no-dev'); - $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader'); - $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative'); + $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader'); + $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative'); // Update packages $this->resetComposer(); From ed954485239ad88f94bcee80a6a648d7943932f8 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 20 Sep 2015 18:26:23 +0100 Subject: [PATCH 179/205] URL-encode dollar signs to work around bad proxy failures --- src/Composer/Repository/ComposerRepository.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index b0b3d2689..f3b0642d0 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -584,6 +584,11 @@ class ComposerRepository extends ArrayRepository $filename = $this->baseUrl.'/'.$filename; } + // url-encode $ signs in URLs as bad proxies choke on them + if ($pos = strpos($filename, '$')) { + $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos+1); + } + $retries = 3; while ($retries--) { try { From e61b3a6370fad13f141016e249b581b5ef047558 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 20 Sep 2015 19:28:36 +0100 Subject: [PATCH 180/205] Allow the validate command to validate dependencies with -A/--with-dependencies, refs #3202 --- src/Composer/Command/ValidateCommand.php | 54 ++++++++++++++++++------ 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/src/Composer/Command/ValidateCommand.php b/src/Composer/Command/ValidateCommand.php index a26f1a868..c08cf2c10 100644 --- a/src/Composer/Command/ValidateCommand.php +++ b/src/Composer/Command/ValidateCommand.php @@ -40,11 +40,16 @@ class ValidateCommand extends Command new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not make a complete validation'), new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'), new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'), + new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies.'), new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file', './composer.json') )) ->setHelp(<<writeError('' . $file . ' not found.'); - return 1; + return 3; } if (!is_readable($file)) { $io->writeError('' . $file . ' is not readable.'); - return 1; + return 3; } $validator = new ConfigValidator($io); $checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL; $checkPublish = !$input->getOption('no-check-publish'); - list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll); - $checkLock = !$input->getOption('no-check-lock'); + list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll); $lockErrors = array(); $composer = Factory::create($io, $file); @@ -85,18 +89,44 @@ EOT $lockErrors[] = 'The lock file is not up to date with the latest changes in composer.json.'; } - // output errors/warnings + $this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, true); + + $exitCode = $errors || ($publishErrors && $checkPublish) || ($lockErrors && $checkLock) ? 1 : 0; + + if ($input->getOption('with-dependencies')) { + $localRepo = $composer->getRepositoryManager()->getLocalRepository(); + foreach ($localRepo->getPackages() as $package) { + $path = $composer->getInstallationManager()->getInstallPath($package); + $file = $path . '/composer.json'; + if (is_dir($path) && file_exists($file)) { + list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll); + $this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors); + + $exitCode = $exitCode === 1 || $errors || ($publishErrors && $checkPublish) ? 1 : 0; + } + } + } + + return $exitCode; + } + + private function outputResult($io, $name, $errors, $warnings, $checkPublish = false, $publishErrors = array(), $checkLock = false, $lockErrors = array(), $printSchemaUrl = false) + { if (!$errors && !$publishErrors && !$warnings) { - $io->write('' . $file . ' is valid'); + $io->write('' . $name . ' is valid'); } elseif (!$errors && !$publishErrors) { - $io->writeError('' . $file . ' is valid, but with a few warnings'); - $io->writeError('See https://getcomposer.org/doc/04-schema.md for details on the schema'); + $io->writeError('' . $name . ' is valid, but with a few warnings'); + if ($printSchemaUrl) { + $io->writeError('See https://getcomposer.org/doc/04-schema.md for details on the schema'); + } } elseif (!$errors) { - $io->writeError('' . $file . ' is valid for simple usage with composer but has'); + $io->writeError('' . $name . ' is valid for simple usage with composer but has'); $io->writeError('strict errors that make it unable to be published as a package:'); - $io->writeError('See https://getcomposer.org/doc/04-schema.md for details on the schema'); + if ($printSchemaUrl) { + $io->writeError('See https://getcomposer.org/doc/04-schema.md for details on the schema'); + } } else { - $io->writeError('' . $file . ' is invalid, the following errors/warnings were found:'); + $io->writeError('' . $name . ' is invalid, the following errors/warnings were found:'); } $messages = array( @@ -123,7 +153,5 @@ EOT $io->writeError('<' . $style . '>' . $msg . ''); } } - - return $errors || ($publishErrors && $checkPublish) || ($lockErrors && $checkLock) ? 1 : 0; } } From ae23979dfa849b3871993e068d09331fc3d714fd Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 20 Sep 2015 19:29:39 +0100 Subject: [PATCH 181/205] Add validation warning for prs-0/4 definitions without namespace prefix, refs #3202 --- src/Composer/Util/ConfigValidator.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Composer/Util/ConfigValidator.php b/src/Composer/Util/ConfigValidator.php index e99c2e73c..dfd662ea0 100644 --- a/src/Composer/Util/ConfigValidator.php +++ b/src/Composer/Util/ConfigValidator.php @@ -124,6 +124,14 @@ class ConfigValidator } } + // check for empty psr-0/psr-4 namespace prefixes + if (isset($manifest['autoload']['psr-0'][''])) { + $warnings[] = "Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance"; + } + if (isset($manifest['autoload']['psr-4'][''])) { + $warnings[] = "Defining autoload.psr-4 with an empty namespace prefix is a bad idea for performance"; + } + try { $loader = new ValidatingArrayLoader(new ArrayLoader(), true, null, $arrayLoaderValidationFlags); if (!isset($manifest['version'])) { From 9f2e562e48145f10bf224f93f561e762df980638 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 20 Sep 2015 19:44:55 +0100 Subject: [PATCH 182/205] Add --strict flag to validate command to treat warnings as failures as well, refs #3202 --- src/Composer/Command/ValidateCommand.php | 32 +++++++++++++----------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/Composer/Command/ValidateCommand.php b/src/Composer/Command/ValidateCommand.php index c08cf2c10..54177576e 100644 --- a/src/Composer/Command/ValidateCommand.php +++ b/src/Composer/Command/ValidateCommand.php @@ -40,14 +40,16 @@ class ValidateCommand extends Command new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not make a complete validation'), new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'), new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'), - new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies.'), + new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'), + new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'), new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file', './composer.json') )) ->setHelp(<<getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL; $checkPublish = !$input->getOption('no-check-publish'); $checkLock = !$input->getOption('no-check-lock'); + $isStrict = $input->getOption('strict'); list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll); $lockErrors = array(); @@ -91,7 +94,7 @@ EOT $this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, true); - $exitCode = $errors || ($publishErrors && $checkPublish) || ($lockErrors && $checkLock) ? 1 : 0; + $exitCode = $errors || ($publishErrors && $checkPublish) || ($lockErrors && $checkLock) ? 2 : ($isStrict && $warnings ? 1 : 0); if ($input->getOption('with-dependencies')) { $localRepo = $composer->getRepositoryManager()->getLocalRepository(); @@ -102,7 +105,8 @@ EOT list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll); $this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors); - $exitCode = $exitCode === 1 || $errors || ($publishErrors && $checkPublish) ? 1 : 0; + $depCode = $errors || ($publishErrors && $checkPublish) ? 2 : ($isStrict && $warnings ? 1 : 0); + $exitCode = max($depCode, $exitCode); } } } @@ -110,7 +114,7 @@ EOT return $exitCode; } - private function outputResult($io, $name, $errors, $warnings, $checkPublish = false, $publishErrors = array(), $checkLock = false, $lockErrors = array(), $printSchemaUrl = false) + private function outputResult($io, $name, &$errors, &$warnings, $checkPublish = false, $publishErrors = array(), $checkLock = false, $lockErrors = array(), $printSchemaUrl = false) { if (!$errors && !$publishErrors && !$warnings) { $io->write('' . $name . ' is valid'); @@ -129,25 +133,25 @@ EOT $io->writeError('' . $name . ' is invalid, the following errors/warnings were found:'); } - $messages = array( - 'error' => $errors, - 'warning' => $warnings, - ); - // If checking publish errors, display them as errors, otherwise just show them as warnings if ($checkPublish) { - $messages['error'] = array_merge($messages['error'], $publishErrors); + $errors = array_merge($errors, $publishErrors); } else { - $messages['warning'] = array_merge($messages['warning'], $publishErrors); + $warnings = array_merge($warnings, $publishErrors); } // If checking lock errors, display them as errors, otherwise just show them as warnings if ($checkLock) { - $messages['error'] = array_merge($messages['error'], $lockErrors); + $errors = array_merge($errors, $lockErrors); } else { - $messages['warning'] = array_merge($messages['warning'], $lockErrors); + $warnings = array_merge($warnings, $lockErrors); } + $messages = array( + 'error' => $errors, + 'warning' => $warnings, + ); + foreach ($messages as $style => $msgs) { foreach ($msgs as $msg) { $io->writeError('<' . $style . '>' . $msg . ''); From 80f1e4372a10427aaf06d5cda87a9bf74db200ab Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 22 Sep 2015 23:54:43 +0100 Subject: [PATCH 183/205] Remove empty bin dir after all binaries have been removed from it, fixes #3451 --- src/Composer/Installer/LibraryInstaller.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index aa2d46062..b785c4da2 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -266,6 +266,11 @@ class LibraryInstaller implements InstallerInterface $this->filesystem->unlink($link.'.bat'); } } + + // attempt removing the bin dir in case it is left empty + if ($this->filesystem->isDirEmpty($this->binDir)) { + @rmdir($this->binDir); + } } protected function initializeVendorDir() From facb88c55a3f08acb49e54a34bae3e717fd6ef47 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 23 Sep 2015 00:16:27 +0100 Subject: [PATCH 184/205] Appveyor tweaks --- appveyor.yml | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 024d26047..04ba267e0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,37 +9,27 @@ environment: - PHP_EXT: 0 cache: - - c:\php -> appveyor.yml + - c:\tools\php -> appveyor.yml init: - - SET PATH=c:\php;%PATH% + - SET PATH=C:\Program Files\OpenSSL;c:\tools\php;%PATH% - SET COMPOSER_NO_INTERACTION=1 - SET PHP=1 - SET ANSICON=121x90 (121x90) install: - - IF EXIST c:\php (SET PHP=0) ELSE (mkdir c:\php) - - cd c:\php - - IF %PHP%==1 appveyor DownloadFile http://windows.php.net/downloads/releases/archives/php-5.3.11-nts-Win32-VC9-x86.zip - - IF %PHP%==1 7z x php-5.3.11-nts-Win32-VC9-x86.zip -y > 7z.log - - IF %PHP%==1 appveyor DownloadFile http://nebm.ist.utl.pt/~glopes/misc/intl_win/ICU-51.2-dlls.zip - - IF %PHP%==1 7z x ICU-51.2-dlls.zip -y > 7z.log - - IF %PHP%==1 cd ext - - IF %PHP%==1 appveyor DownloadFile http://nebm.ist.utl.pt/~glopes/misc/intl_win/php_intl-3.0.0-5.3-nts-vc9-x86.zip - - IF %PHP%==1 7z x php_intl-3.0.0-5.3-nts-vc9-x86.zip -y > 7z.log - - IF %PHP%==1 appveyor DownloadFile http://windows.php.net/downloads/pecl/releases/apc/3.1.13/php_apc-3.1.13-5.3-nts-vc9-x86.zip - - IF %PHP%==1 7z x php_apc-3.1.13-5.3-nts-vc9-x86.zip -y > 7z.log - - IF %PHP%==1 cd .. + - IF EXIST c:\tools\php (SET PHP=0) + - IF %PHP%==1 cinst -y OpenSSL.Light + - IF %PHP%==1 cinst -y php + - cd c:\tools\php + - IF %PHP%==1 copy php.ini-production php.ini /Y + - IF %PHP%==1 echo date.timezone="UTC" >> php.ini + - IF %PHP%==1 echo extension_dir=ext >> php.ini + - IF %PHP%==1 echo extension=php_openssl.dll >> php.ini + - IF %PHP%==1 echo extension=php_mbstring.dll >> php.ini + - IF %PHP%==1 echo extension=php_fileinfo.dll >> php.ini - IF %PHP%==1 echo @php %%~dp0composer.phar %%* > composer.bat - appveyor DownloadFile https://getcomposer.org/composer.phar - - copy php.ini-production php.ini /Y - - echo date.timezone="UTC" >> php.ini - - echo extension_dir=ext >> php.ini - - echo extension=php_openssl.dll >> php.ini - - IF %PHP_EXT%==1 echo extension=php_apc.dll >> php.ini - - IF %PHP_EXT%==1 echo extension=php_intl.dll >> php.ini - - IF %PHP_EXT%==1 echo extension=php_mbstring.dll >> php.ini - - IF %PHP_EXT%==1 echo extension=php_fileinfo.dll >> php.ini - cd c:\projects\composer - composer install --prefer-source --no-progress From 8a7e48ce4a85888c8c380d64a0061bf62126ec72 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 23 Sep 2015 00:17:02 +0100 Subject: [PATCH 185/205] Remove appveyor matrix --- appveyor.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 04ba267e0..efc7c624e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,11 +3,6 @@ shallow_clone: true platform: x86 clone_folder: c:\projects\composer -environment: - matrix: - - PHP_EXT: 1 - - PHP_EXT: 0 - cache: - c:\tools\php -> appveyor.yml From 41a87a3ae7bce14930b4a25c8c6a08a15b928bda Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 23 Sep 2015 00:41:24 +0100 Subject: [PATCH 186/205] Adjust file path output, refs #4379 --- src/Composer/Command/ArchiveCommand.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Composer/Command/ArchiveCommand.php b/src/Composer/Command/ArchiveCommand.php index b9cdf03cc..8114435b2 100644 --- a/src/Composer/Command/ArchiveCommand.php +++ b/src/Composer/Command/ArchiveCommand.php @@ -19,6 +19,7 @@ use Composer\Repository\CompositeRepository; use Composer\Script\ScriptEvents; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; +use Composer\Util\Filesystem; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -106,7 +107,11 @@ EOT $io->writeError('Creating the archive into "'.$dest.'".'); $packagePath = $archiveManager->archive($package, $format, $dest); - $io->writeError('Created archive file path: "'.$packagePath.'"'); + $fs = new Filesystem; + $shortPath = $fs->findShortestPath(getcwd(), $packagePath, true); + + $io->writeError('Created: ', false); + $io->write(strlen($shortPath) < strlen($packagePath) ? $shortPath : $packagePath); return 0; } From c1e60a0abdb4fd6d5e2fa6874b0bc3354d397439 Mon Sep 17 00:00:00 2001 From: Gavin Staniforth Date: Wed, 23 Sep 2015 13:46:35 +0100 Subject: [PATCH 187/205] Ensure the bin directory exists before checking empty Line 130 has similar logic so avoided doing the check withiin `isDirEmpty()` --- src/Composer/Installer/LibraryInstaller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index b785c4da2..75b3a0c6e 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -268,7 +268,7 @@ class LibraryInstaller implements InstallerInterface } // attempt removing the bin dir in case it is left empty - if ($this->filesystem->isDirEmpty($this->binDir)) { + if ((is_dir($this->binDir)) && ($this->filesystem->isDirEmpty($this->binDir))) { @rmdir($this->binDir); } } From 9febf55f7671a769d4bea46dde3cdc9ad1a9b659 Mon Sep 17 00:00:00 2001 From: Dennis Birkholz Date: Wed, 23 Sep 2015 17:51:41 +0200 Subject: [PATCH 188/205] Store url relative again, fix 4439 --- src/Composer/Repository/PathRepository.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index a76a2e052..3b600ea36 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -101,10 +101,10 @@ class PathRepository extends ArrayRepository { parent::initialize(); - foreach ($this->getPaths() as $path) { - $path = realpath($path) . '/'; - + foreach ($this->getUrlMatches() as $url) { + $path = realpath($url) . '/'; $composerFilePath = $path.'composer.json'; + if (!file_exists($composerFilePath)) { continue; } @@ -113,7 +113,7 @@ class PathRepository extends ArrayRepository $package = JsonFile::parseJson($json, $composerFilePath); $package['dist'] = array( 'type' => 'path', - 'url' => $path, + 'url' => $url, 'reference' => '', ); @@ -134,11 +134,11 @@ class PathRepository extends ArrayRepository } /** - * Get a list of all path names matching given url (supports globbing). + * Get a list of all (possibly relative) path names matching given url (supports globbing). * * @return string[] */ - private function getPaths() + private function getUrlMatches() { return glob($this->url, GLOB_MARK|GLOB_ONLYDIR); } From 3febbc2cbf2192cde1842ff29921ecf9650bb34a Mon Sep 17 00:00:00 2001 From: Dennis Birkholz Date: Wed, 23 Sep 2015 18:15:43 +0200 Subject: [PATCH 189/205] Test case to verify relative paths remain relative --- .../Test/Repository/PathRepositoryTest.php | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/Composer/Test/Repository/PathRepositoryTest.php b/tests/Composer/Test/Repository/PathRepositoryTest.php index 03ad46fea..1a5392c28 100644 --- a/tests/Composer/Test/Repository/PathRepositoryTest.php +++ b/tests/Composer/Test/Repository/PathRepositoryTest.php @@ -81,4 +81,29 @@ class PathRepositoryTest extends TestCase $package = $packages[1]; $this->assertEquals('test/path-unversioned', $package->getName()); } + + /** + * Verify relative repository URLs remain relative, see #4439 + */ + public function testUrlRemainsRelative() + { + $ioInterface = $this->getMockBuilder('Composer\IO\IOInterface') + ->getMock(); + + $config = new \Composer\Config(); + $loader = new ArrayLoader(new VersionParser()); + $versionGuesser = null; + + $repositoryUrl = implode(DIRECTORY_SEPARATOR, array(__DIR__, 'Fixtures', 'path', 'with-version')); + $relativeUrl = ltrim(substr($repositoryUrl, strlen(getcwd())), DIRECTORY_SEPARATOR); + + $repository = new PathRepository(array('url' => $relativeUrl), $ioInterface, $config, $loader); + $packages = $repository->getPackages(); + + $this->assertEquals(1, $repository->count()); + + $package = $packages[0]; + $this->assertEquals('test/path-versioned', $package->getName()); + $this->assertEquals(rtrim($relativeUrl, DIRECTORY_SEPARATOR), rtrim($package->getDistUrl(), DIRECTORY_SEPARATOR)); + } } From 1ccfc8eb96a6cc320703a5b1fae6c6a1bb2cc162 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Thu, 24 Sep 2015 16:28:28 +0200 Subject: [PATCH 190/205] add semver, deprecated existing classes --- composer.json | 3 +- composer.lock | 64 ++- .../LinkConstraint/EmptyConstraint.php | 35 +- .../LinkConstraintInterface.php | 14 +- .../LinkConstraint/MultiConstraint.php | 71 +-- .../LinkConstraint/SpecificConstraint.php | 41 +- .../LinkConstraint/VersionConstraint.php | 115 +--- .../Package/Version/VersionParser.php | 507 +----------------- .../LinkConstraint/MultiConstraintTest.php | 54 -- .../LinkConstraint/VersionConstraintTest.php | 105 ---- .../Package/Version/VersionParserTest.php | 472 ---------------- 11 files changed, 98 insertions(+), 1383 deletions(-) delete mode 100644 tests/Composer/Test/Package/LinkConstraint/MultiConstraintTest.php delete mode 100644 tests/Composer/Test/Package/LinkConstraint/VersionConstraintTest.php delete mode 100644 tests/Composer/Test/Package/Version/VersionParserTest.php diff --git a/composer.json b/composer.json index 4ba003887..b4e372ac4 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,8 @@ "require": { "php": ">=5.3.2", "justinrainbow/json-schema": "^1.4.4", - "composer/spdx-licenses": "~1.0", + "composer/spdx-licenses": "^1.0", + "composer/semver": "^1.0", "seld/jsonlint": "~1.0", "symfony/console": "~2.5", "symfony/finder": "~2.2", diff --git a/composer.lock b/composer.lock index 0c6108927..25dc03c27 100644 --- a/composer.lock +++ b/composer.lock @@ -4,9 +4,69 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "3024e89a7e808b8dece156112459a7ea", - "content-hash": "01608741fe66bb9528d7c77c0a422965", + "hash": "af3956ae4c1a09e3e72cd66346a6176d", "packages": [ + { + "name": "composer/semver", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "d0e1ccc6d44ab318b758d709e19176037da6b1ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/d0e1ccc6d44ab318b758d709e19176037da6b1ba", + "reference": "d0e1ccc6d44ab318b758d709e19176037da6b1ba", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.5", + "phpunit/phpunit-mock-objects": "~2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.1-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com" + }, + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "time": "2015-09-21 09:42:36" + }, { "name": "composer/spdx-licenses", "version": "1.1.1", diff --git a/src/Composer/Package/LinkConstraint/EmptyConstraint.php b/src/Composer/Package/LinkConstraint/EmptyConstraint.php index ca1c75ff5..43cc65163 100644 --- a/src/Composer/Package/LinkConstraint/EmptyConstraint.php +++ b/src/Composer/Package/LinkConstraint/EmptyConstraint.php @@ -12,36 +12,13 @@ namespace Composer\Package\LinkConstraint; +use Composer\Semver\Constraint\EmptyConstraint as BaseEmptyConstraint; + +@trigger_error('The ' . __NAMESPACE__ . '\EmptyConstraint class is deprecated, use Composer\Semver\Constraint\EmptyConstraint instead.', E_USER_DEPRECATED); + /** - * Defines an absence of constraints - * - * @author Jordi Boggiano + * @deprecated use Composer\Semver\Constraint\EmptyConstraint instead */ -class EmptyConstraint implements LinkConstraintInterface +class EmptyConstraint extends BaseEmptyConstraint { - protected $prettyString; - - public function matches(LinkConstraintInterface $provider) - { - return true; - } - - public function setPrettyString($prettyString) - { - $this->prettyString = $prettyString; - } - - public function getPrettyString() - { - if ($this->prettyString) { - return $this->prettyString; - } - - return $this->__toString(); - } - - public function __toString() - { - return '[]'; - } } diff --git a/src/Composer/Package/LinkConstraint/LinkConstraintInterface.php b/src/Composer/Package/LinkConstraint/LinkConstraintInterface.php index 199c9fc42..bac98c6f9 100644 --- a/src/Composer/Package/LinkConstraint/LinkConstraintInterface.php +++ b/src/Composer/Package/LinkConstraint/LinkConstraintInterface.php @@ -12,15 +12,13 @@ namespace Composer\Package\LinkConstraint; +use Composer\Semver\Constraint\ConstraintInterface; + +@trigger_error('The ' . __NAMESPACE__ . '\LinkConstraintInterface interface is deprecated, use Composer\Semver\Constraint\ConstraintInterface instead.', E_USER_DEPRECATED); + /** - * Defines a constraint on a link between two packages. - * - * @author Nils Adermann + * @deprecated use Composer\Semver\Constraint\ConstraintInterface instead */ -interface LinkConstraintInterface +interface LinkConstraintInterface extends ConstraintInterface { - public function matches(LinkConstraintInterface $provider); - public function setPrettyString($prettyString); - public function getPrettyString(); - public function __toString(); } diff --git a/src/Composer/Package/LinkConstraint/MultiConstraint.php b/src/Composer/Package/LinkConstraint/MultiConstraint.php index 3871aeb2f..296076b18 100644 --- a/src/Composer/Package/LinkConstraint/MultiConstraint.php +++ b/src/Composer/Package/LinkConstraint/MultiConstraint.php @@ -12,72 +12,13 @@ namespace Composer\Package\LinkConstraint; +use Composer\Semver\Constraint\MultiConstraint as BaseMultiConstraint; + +@trigger_error('The ' . __NAMESPACE__ . '\MultiConstraint class is deprecated, use Composer\Semver\Constraint\MultiConstraint instead.', E_USER_DEPRECATED); + /** - * Defines a conjunctive or disjunctive set of constraints on the target of a package link - * - * @author Nils Adermann - * @author Jordi Boggiano + * @deprecated use Composer\Semver\Constraint\MultiConstraint instead */ -class MultiConstraint implements LinkConstraintInterface +class MultiConstraint extends BaseMultiConstraint { - protected $constraints; - protected $prettyString; - protected $conjunctive; - - /** - * Sets operator and version to compare a package with - * - * @param array $constraints A set of constraints - * @param bool $conjunctive Whether the constraints should be treated as conjunctive or disjunctive - */ - public function __construct(array $constraints, $conjunctive = true) - { - $this->constraints = $constraints; - $this->conjunctive = $conjunctive; - } - - public function matches(LinkConstraintInterface $provider) - { - if (false === $this->conjunctive) { - foreach ($this->constraints as $constraint) { - if ($constraint->matches($provider)) { - return true; - } - } - - return false; - } - - foreach ($this->constraints as $constraint) { - if (!$constraint->matches($provider)) { - return false; - } - } - - return true; - } - - public function setPrettyString($prettyString) - { - $this->prettyString = $prettyString; - } - - public function getPrettyString() - { - if ($this->prettyString) { - return $this->prettyString; - } - - return $this->__toString(); - } - - public function __toString() - { - $constraints = array(); - foreach ($this->constraints as $constraint) { - $constraints[] = $constraint->__toString(); - } - - return '['.implode($this->conjunctive ? ' ' : ' || ', $constraints).']'; - } } diff --git a/src/Composer/Package/LinkConstraint/SpecificConstraint.php b/src/Composer/Package/LinkConstraint/SpecificConstraint.php index e0904dbbf..409f0a440 100644 --- a/src/Composer/Package/LinkConstraint/SpecificConstraint.php +++ b/src/Composer/Package/LinkConstraint/SpecificConstraint.php @@ -12,42 +12,13 @@ namespace Composer\Package\LinkConstraint; +use Composer\Semver\Constraint\AbstractConstraint; + +@trigger_error('The ' . __NAMESPACE__ . '\SpecificConstraint abstract class is deprecated, use Composer\Semver\Constraint\AbstractConstraint instead.', E_USER_DEPRECATED); + /** - * Provides a common basis for specific package link constraints - * - * @author Nils Adermann + * @deprecated use Composer\Semver\Constraint\AbstractConstraint instead */ -abstract class SpecificConstraint implements LinkConstraintInterface +abstract class SpecificConstraint extends AbstractConstraint { - protected $prettyString; - - public function matches(LinkConstraintInterface $provider) - { - if ($provider instanceof MultiConstraint) { - // turn matching around to find a match - return $provider->matches($this); - } elseif ($provider instanceof $this) { - return $this->matchSpecific($provider); - } - - return true; - } - - public function setPrettyString($prettyString) - { - $this->prettyString = $prettyString; - } - - public function getPrettyString() - { - if ($this->prettyString) { - return $this->prettyString; - } - - return $this->__toString(); - } - - // implementations must implement a method of this format: - // not declared abstract here because type hinting violates parameter coherence (TODO right word?) - // public function matchSpecific( $provider); } diff --git a/src/Composer/Package/LinkConstraint/VersionConstraint.php b/src/Composer/Package/LinkConstraint/VersionConstraint.php index 4b6cf2ad7..45d471254 100644 --- a/src/Composer/Package/LinkConstraint/VersionConstraint.php +++ b/src/Composer/Package/LinkConstraint/VersionConstraint.php @@ -12,116 +12,13 @@ namespace Composer\Package\LinkConstraint; +use Composer\Semver\Constraint\Constraint; + +@trigger_error('The ' . __NAMESPACE__ . '\VersionConstraint class is deprecated, use Composer\Semver\Constraint\Constraint instead.', E_USER_DEPRECATED); + /** - * Constrains a package link based on package version - * - * Version numbers must be compatible with version_compare - * - * @author Nils Adermann + * @deprecated use Composer\Semver\Constraint\Constraint instead */ -class VersionConstraint extends SpecificConstraint +class VersionConstraint extends Constraint { - const OP_EQ = 0; - const OP_LT = 1; - const OP_LE = 2; - const OP_GT = 3; - const OP_GE = 4; - const OP_NE = 5; - - private static $transOpStr = array( - '=' => self::OP_EQ, - '==' => self::OP_EQ, - '<' => self::OP_LT, - '<=' => self::OP_LE, - '>' => self::OP_GT, - '>=' => self::OP_GE, - '<>' => self::OP_NE, - '!=' => self::OP_NE, - ); - - private static $transOpInt = array( - self::OP_EQ => '==', - self::OP_LT => '<', - self::OP_LE => '<=', - self::OP_GT => '>', - self::OP_GE => '>=', - self::OP_NE => '!=', - ); - - private $operator; - private $version; - - /** - * Sets operator and version to compare a package with - * - * @param string $operator A comparison operator - * @param string $version A version to compare to - */ - public function __construct($operator, $version) - { - $this->operator = self::$transOpStr[$operator]; - $this->version = $version; - } - - public function versionCompare($a, $b, $operator, $compareBranches = false) - { - $aIsBranch = 'dev-' === substr($a, 0, 4); - $bIsBranch = 'dev-' === substr($b, 0, 4); - if ($aIsBranch && $bIsBranch) { - return $operator == '==' && $a === $b; - } - - // when branches are not comparable, we make sure dev branches never match anything - if (!$compareBranches && ($aIsBranch || $bIsBranch)) { - return false; - } - - return version_compare($a, $b, $operator); - } - - /** - * @param VersionConstraint $provider - * @param bool $compareBranches - * @return bool - */ - public function matchSpecific(VersionConstraint $provider, $compareBranches = false) - { - $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]); - $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]); - - $isEqualOp = self::OP_EQ === $this->operator; - $isNonEqualOp = self::OP_NE === $this->operator; - $isProviderEqualOp = self::OP_EQ === $provider->operator; - $isProviderNonEqualOp = self::OP_NE === $provider->operator; - - // '!=' operator is match when other operator is not '==' operator or version is not match - // these kinds of comparisons always have a solution - if ($isNonEqualOp || $isProviderNonEqualOp) { - return !$isEqualOp && !$isProviderEqualOp - || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches); - } - - // an example for the condition is <= 2.0 & < 1.0 - // these kinds of comparisons always have a solution - if ($this->operator !== self::OP_EQ && $noEqualOp == $providerNoEqualOp) { - return true; - } - - if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) { - // special case, e.g. require >= 1.0 and provide < 1.0 - // 1.0 >= 1.0 but 1.0 is outside of the provided interval - if ($provider->version == $this->version && self::$transOpInt[$provider->operator] == $providerNoEqualOp && self::$transOpInt[$this->operator] != $noEqualOp) { - return false; - } - - return true; - } - - return false; - } - - public function __toString() - { - return self::$transOpInt[$this->operator].' '.$this->version; - } } diff --git a/src/Composer/Package/Version/VersionParser.php b/src/Composer/Package/Version/VersionParser.php index cacc0b118..4c29599c8 100644 --- a/src/Composer/Package/Version/VersionParser.php +++ b/src/Composer/Package/Version/VersionParser.php @@ -12,513 +12,14 @@ namespace Composer\Package\Version; -use Composer\Package\PackageInterface; -use Composer\Package\Link; -use Composer\Package\LinkConstraint\EmptyConstraint; -use Composer\Package\LinkConstraint\MultiConstraint; -use Composer\Package\LinkConstraint\VersionConstraint; -use Composer\Package\Loader\ArrayLoader; +use Composer\Semver\VersionParser as BaseVersionParser; -/** - * Version parser - * - * @author Jordi Boggiano - */ -class VersionParser +class VersionParser extends BaseVersionParser { - private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)(?:[.-]?(\d+))?)?([.-]?dev)?'; - - private static $stabilities = array( - 'stable', 'RC', 'beta', 'alpha', 'dev', - ); - - /** - * Returns the stability of a version - * - * @param string $version - * @return string - */ - public static function parseStability($version) - { - $version = preg_replace('{#.+$}i', '', $version); - - if ('dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4)) { - return 'dev'; - } - - preg_match('{'.self::$modifierRegex.'$}i', strtolower($version), $match); - if (!empty($match[3])) { - return 'dev'; - } - - if (!empty($match[1])) { - if ('beta' === $match[1] || 'b' === $match[1]) { - return 'beta'; - } - if ('alpha' === $match[1] || 'a' === $match[1]) { - return 'alpha'; - } - if ('rc' === $match[1]) { - return 'RC'; - } - } - - return 'stable'; - } - - public static function normalizeStability($stability) - { - $stability = strtolower($stability); - - return $stability === 'rc' ? 'RC' : $stability; - } - - /** - * @deprecated Use PackageInterface::getFullPrettyVersion instead - */ - public static function formatVersion(PackageInterface $package, $truncate = true) - { - trigger_error(__METHOD__.' is deprecated. Use '. - '\Composer\Package\PackageInterface::getFullPrettyVersion() instead', E_USER_DEPRECATED); - - return $package->getFullPrettyVersion($truncate); - } - - /** - * Normalizes a version string to be able to perform comparisons on it - * - * @param string $version - * @param string $fullVersion optional complete version string to give more context - * @throws \UnexpectedValueException - * @return string - */ - public function normalize($version, $fullVersion = null) - { - $version = trim($version); - if (null === $fullVersion) { - $fullVersion = $version; - } - - // ignore aliases and just assume the alias is required instead of the source - if (preg_match('{^([^,\s]+) +as +([^,\s]+)$}', $version, $match)) { - $version = $match[1]; - } - - // ignore build metadata - if (preg_match('{^([^,\s+]+)\+[^\s]+$}', $version, $match)) { - $version = $match[1]; - } - - // match master-like branches - if (preg_match('{^(?:dev-)?(?:master|trunk|default)$}i', $version)) { - return '9999999-dev'; - } - - if ('dev-' === strtolower(substr($version, 0, 4))) { - return 'dev-'.substr($version, 4); - } - - // match classical versioning - if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?'.self::$modifierRegex.'$}i', $version, $matches)) { - $version = $matches[1] - .(!empty($matches[2]) ? $matches[2] : '.0') - .(!empty($matches[3]) ? $matches[3] : '.0') - .(!empty($matches[4]) ? $matches[4] : '.0'); - $index = 5; - } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)'.self::$modifierRegex.'$}i', $version, $matches)) { // match date-based versioning - $version = preg_replace('{\D}', '-', $matches[1]); - $index = 2; - } elseif (preg_match('{^v?(\d{4,})(\.\d+)?(\.\d+)?(\.\d+)?'.self::$modifierRegex.'$}i', $version, $matches)) { - $version = $matches[1] - .(!empty($matches[2]) ? $matches[2] : '.0') - .(!empty($matches[3]) ? $matches[3] : '.0') - .(!empty($matches[4]) ? $matches[4] : '.0'); - $index = 5; - } - - // add version modifiers if a version was matched - if (isset($index)) { - if (!empty($matches[$index])) { - if ('stable' === $matches[$index]) { - return $version; - } - $version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? $matches[$index + 1] : ''); - } - - if (!empty($matches[$index + 2])) { - $version .= '-dev'; - } - - return $version; - } - - // match dev branches - if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) { - try { - return $this->normalizeBranch($match[1]); - } catch (\Exception $e) { - } - } - - $extraMessage = ''; - if (preg_match('{ +as +'.preg_quote($version).'$}', $fullVersion)) { - $extraMessage = ' in "'.$fullVersion.'", the alias must be an exact version'; - } elseif (preg_match('{^'.preg_quote($version).' +as +}', $fullVersion)) { - $extraMessage = ' in "'.$fullVersion.'", the alias source must be an exact version, if it is a branch name you should prefix it with dev-'; - } - - throw new \UnexpectedValueException('Invalid version string "'.$version.'"'.$extraMessage); - } - - /** - * Extract numeric prefix from alias, if it is in numeric format, suitable for - * version comparison - * - * @param string $branch Branch name (e.g. 2.1.x-dev) - * @return string|false Numeric prefix if present (e.g. 2.1.) or false - */ - public function parseNumericAliasPrefix($branch) - { - if (preg_match('/^(?P(\d+\\.)*\d+)(?:\.x)?-dev$/i', $branch, $matches)) { - return $matches['version']."."; - } - - return false; - } - - /** - * Normalizes a branch name to be able to perform comparisons on it - * - * @param string $name - * @return string - */ - public function normalizeBranch($name) - { - $name = trim($name); - - if (in_array($name, array('master', 'trunk', 'default'))) { - return $this->normalize($name); - } - - if (preg_match('#^v?(\d+)(\.(?:\d+|[xX*]))?(\.(?:\d+|[xX*]))?(\.(?:\d+|[xX*]))?$#i', $name, $matches)) { - $version = ''; - for ($i = 1; $i < 5; $i++) { - $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x'; - } - - return str_replace('x', '9999999', $version).'-dev'; - } - - return 'dev-'.$name; - } - - /** - * @deprecated use ArrayLoader::parseLinks() instead - * @param string $source source package name - * @param string $sourceVersion source package version (pretty version ideally) - * @param string $description link description (e.g. requires, replaces, ..) - * @param array $links array of package name => constraint mappings - * @return Link[] - */ - public function parseLinks($source, $sourceVersion, $description, $links) - { - trigger_error(__METHOD__.' is deprecated. Use '. - '\Composer\Package\Loader\ArrayLoader::parseLinks() instead', E_USER_DEPRECATED); - $loader = new ArrayLoader($this, false); - - return $loader->parseLinks($source, $sourceVersion, $description, $links); - } - - /** - * Parses as constraint string into LinkConstraint objects - * - * @param string $constraints - * @return \Composer\Package\LinkConstraint\LinkConstraintInterface - */ - public function parseConstraints($constraints) - { - $prettyConstraint = $constraints; - - if (preg_match('{^([^,\s]*?)@('.implode('|', self::$stabilities).')$}i', $constraints, $match)) { - $constraints = empty($match[1]) ? '*' : $match[1]; - } - - if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraints, $match)) { - $constraints = $match[1]; - } - - $orConstraints = preg_split('{\s*\|\|?\s*}', trim($constraints)); - $orGroups = array(); - foreach ($orConstraints as $constraints) { - $andConstraints = preg_split('{(?< ,]) *(? 1) { - $constraintObjects = array(); - foreach ($andConstraints as $constraint) { - foreach ($this->parseConstraint($constraint) as $parsedConstraint) { - $constraintObjects[] = $parsedConstraint; - } - } - } else { - $constraintObjects = $this->parseConstraint($andConstraints[0]); - } - - if (1 === count($constraintObjects)) { - $constraint = $constraintObjects[0]; - } else { - $constraint = new MultiConstraint($constraintObjects); - } - - $orGroups[] = $constraint; - } - - if (1 === count($orGroups)) { - $constraint = $orGroups[0]; - } else { - $constraint = new MultiConstraint($orGroups, false); - } - - $constraint->setPrettyString($prettyConstraint); - - return $constraint; - } - - private function parseConstraint($constraint) - { - if (preg_match('{^([^,\s]+?)@('.implode('|', self::$stabilities).')$}i', $constraint, $match)) { - $constraint = $match[1]; - if ($match[2] !== 'stable') { - $stabilityModifier = $match[2]; - } - } - - if (preg_match('{^[xX*](\.[xX*])*$}i', $constraint)) { - return array(new EmptyConstraint); - } - - $versionRegex = '(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.(\d+))?'.self::$modifierRegex; - - // match tilde constraints - // like wildcard constraints, unsuffixed tilde constraints say that they must be greater than the previous - // version, to ensure that unstable instances of the current version are allowed. - // however, if a stability suffix is added to the constraint, then a >= match on the current version is - // used instead - if (preg_match('{^~>?'.$versionRegex.'$}i', $constraint, $matches)) { - if (substr($constraint, 0, 2) === '~>') { - throw new \UnexpectedValueException( - 'Could not parse version constraint '.$constraint.': '. - 'Invalid operator "~>", you probably meant to use the "~" operator' - ); - } - - // Work out which position in the version we are operating at - if (isset($matches[4]) && '' !== $matches[4]) { - $position = 4; - } elseif (isset($matches[3]) && '' !== $matches[3]) { - $position = 3; - } elseif (isset($matches[2]) && '' !== $matches[2]) { - $position = 2; - } else { - $position = 1; - } - - // Calculate the stability suffix - $stabilitySuffix = ''; - if (!empty($matches[5])) { - $stabilitySuffix .= '-' . $this->expandStability($matches[5]) . (!empty($matches[6]) ? $matches[6] : ''); - } - - if (!empty($matches[7])) { - $stabilitySuffix .= '-dev'; - } - - if (!$stabilitySuffix) { - $stabilitySuffix = "-dev"; - } - $lowVersion = $this->manipulateVersionString($matches, $position, 0) . $stabilitySuffix; - $lowerBound = new VersionConstraint('>=', $lowVersion); - - // For upper bound, we increment the position of one more significance, - // but highPosition = 0 would be illegal - $highPosition = max(1, $position - 1); - $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev'; - $upperBound = new VersionConstraint('<', $highVersion); - - return array( - $lowerBound, - $upperBound - ); - } - - // match caret constraints - if (preg_match('{^\^'.$versionRegex.'($)}i', $constraint, $matches)) { - // Work out which position in the version we are operating at - if ('0' !== $matches[1] || '' === $matches[2]) { - $position = 1; - } elseif ('0' !== $matches[2] || '' === $matches[3]) { - $position = 2; - } else { - $position = 3; - } - - // Calculate the stability suffix - $stabilitySuffix = ''; - if (empty($matches[5]) && empty($matches[7])) { - $stabilitySuffix .= '-dev'; - } - - $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1)); - $lowerBound = new VersionConstraint('>=', $lowVersion); - - // For upper bound, we increment the position of one more significance, - // but highPosition = 0 would be illegal - $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev'; - $upperBound = new VersionConstraint('<', $highVersion); - - return array( - $lowerBound, - $upperBound - ); - } - - // match wildcard constraints - if (preg_match('{^(\d+)(?:\.(\d+))?(?:\.(\d+))?\.[xX*]$}', $constraint, $matches)) { - if (isset($matches[3]) && '' !== $matches[3]) { - $position = 3; - } elseif (isset($matches[2]) && '' !== $matches[2]) { - $position = 2; - } else { - $position = 1; - } - - $lowVersion = $this->manipulateVersionString($matches, $position) . "-dev"; - $highVersion = $this->manipulateVersionString($matches, $position, 1) . "-dev"; - - if ($lowVersion === "0.0.0.0-dev") { - return array(new VersionConstraint('<', $highVersion)); - } - - return array( - new VersionConstraint('>=', $lowVersion), - new VersionConstraint('<', $highVersion), - ); - } - - // match hyphen constraints - if (preg_match('{^(?P'.$versionRegex.') +- +(?P'.$versionRegex.')($)}i', $constraint, $matches)) { - // Calculate the stability suffix - $lowStabilitySuffix = ''; - if (empty($matches[6]) && empty($matches[8])) { - $lowStabilitySuffix = '-dev'; - } - - $lowVersion = $this->normalize($matches['from']); - $lowerBound = new VersionConstraint('>=', $lowVersion . $lowStabilitySuffix); - - $empty = function ($x) { - return ($x === 0 || $x === "0") ? false : empty($x); - }; - - if ((!$empty($matches[11]) && !$empty($matches[12])) || !empty($matches[14]) || !empty($matches[16])) { - $highVersion = $this->normalize($matches['to']); - $upperBound = new VersionConstraint('<=', $highVersion); - } else { - $highMatch = array('', $matches[10], $matches[11], $matches[12], $matches[13]); - $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[11]) ? 1 : 2, 1) . '-dev'; - $upperBound = new VersionConstraint('<', $highVersion); - } - - return array( - $lowerBound, - $upperBound - ); - } - - // match operators constraints - if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) { - try { - $version = $this->normalize($matches[2]); - - if (!empty($stabilityModifier) && $this->parseStability($version) === 'stable') { - $version .= '-' . $stabilityModifier; - } elseif ('<' === $matches[1] || '>=' === $matches[1]) { - if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) { - if (substr($matches[2], 0, 4) !== 'dev-') { - $version .= '-dev'; - } - } - } - - return array(new VersionConstraint($matches[1] ?: '=', $version)); - } catch (\Exception $e) { - } - } - - $message = 'Could not parse version constraint '.$constraint; - if (isset($e)) { - $message .= ': '. $e->getMessage(); - } - - throw new \UnexpectedValueException($message); - } - - /** - * Increment, decrement, or simply pad a version number. - * - * Support function for {@link parseConstraint()} - * - * @param array $matches Array with version parts in array indexes 1,2,3,4 - * @param int $position 1,2,3,4 - which segment of the version to decrement - * @param int $increment - * @param string $pad The string to pad version parts after $position - * @return string The new version - */ - private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0') - { - for ($i = 4; $i > 0; $i--) { - if ($i > $position) { - $matches[$i] = $pad; - } elseif ($i == $position && $increment) { - $matches[$i] += $increment; - // If $matches[$i] was 0, carry the decrement - if ($matches[$i] < 0) { - $matches[$i] = $pad; - $position--; - - // Return null on a carry overflow - if ($i == 1) { - return; - } - } - } - } - - return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4]; - } - - private function expandStability($stability) - { - $stability = strtolower($stability); - - switch ($stability) { - case 'a': - return 'alpha'; - case 'b': - return 'beta'; - case 'p': - case 'pl': - return 'patch'; - case 'rc': - return 'RC'; - default: - return $stability; - } - } - /** - * Parses a name/version pairs and returns an array of pairs + the + * @param array $pairs * - * @param array $pairs a set of package/version pairs separated by ":", "=" or " " - * @return array[] array of arrays containing a name and (if provided) a version + * @return array[] */ public function parseNameVersionPairs(array $pairs) { diff --git a/tests/Composer/Test/Package/LinkConstraint/MultiConstraintTest.php b/tests/Composer/Test/Package/LinkConstraint/MultiConstraintTest.php deleted file mode 100644 index 892b7fef7..000000000 --- a/tests/Composer/Test/Package/LinkConstraint/MultiConstraintTest.php +++ /dev/null @@ -1,54 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Test\Package\LinkConstraint; - -use Composer\Package\LinkConstraint\VersionConstraint; -use Composer\Package\LinkConstraint\MultiConstraint; - -class MultiConstraintTest extends \PHPUnit_Framework_TestCase -{ - public function testMultiVersionMatchSucceeds() - { - $versionRequireStart = new VersionConstraint('>', '1.0'); - $versionRequireEnd = new VersionConstraint('<', '1.2'); - $versionProvide = new VersionConstraint('==', '1.1'); - - $multiRequire = new MultiConstraint(array($versionRequireStart, $versionRequireEnd)); - - $this->assertTrue($multiRequire->matches($versionProvide)); - } - - public function testMultiVersionProvidedMatchSucceeds() - { - $versionRequireStart = new VersionConstraint('>', '1.0'); - $versionRequireEnd = new VersionConstraint('<', '1.2'); - $versionProvideStart = new VersionConstraint('>=', '1.1'); - $versionProvideEnd = new VersionConstraint('<', '2.0'); - - $multiRequire = new MultiConstraint(array($versionRequireStart, $versionRequireEnd)); - $multiProvide = new MultiConstraint(array($versionProvideStart, $versionProvideEnd)); - - $this->assertTrue($multiRequire->matches($multiProvide)); - } - - public function testMultiVersionMatchFails() - { - $versionRequireStart = new VersionConstraint('>', '1.0'); - $versionRequireEnd = new VersionConstraint('<', '1.2'); - $versionProvide = new VersionConstraint('==', '1.2'); - - $multiRequire = new MultiConstraint(array($versionRequireStart, $versionRequireEnd)); - - $this->assertFalse($multiRequire->matches($versionProvide)); - } -} diff --git a/tests/Composer/Test/Package/LinkConstraint/VersionConstraintTest.php b/tests/Composer/Test/Package/LinkConstraint/VersionConstraintTest.php deleted file mode 100644 index e2adda282..000000000 --- a/tests/Composer/Test/Package/LinkConstraint/VersionConstraintTest.php +++ /dev/null @@ -1,105 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Test\Package\LinkConstraint; - -use Composer\Package\LinkConstraint\VersionConstraint; - -class VersionConstraintTest extends \PHPUnit_Framework_TestCase -{ - public static function successfulVersionMatches() - { - return array( - // require provide - array('==', '1', '==', '1'), - array('>=', '1', '>=', '2'), - array('>=', '2', '>=', '1'), - array('>=', '2', '>', '1'), - array('<=', '2', '>=', '1'), - array('>=', '1', '<=', '2'), - array('==', '2', '>=', '2'), - array('!=', '1', '!=', '1'), - array('!=', '1', '==', '2'), - array('!=', '1', '<', '1'), - array('!=', '1', '<=', '1'), - array('!=', '1', '>', '1'), - array('!=', '1', '>=', '1'), - array('==', 'dev-foo-bar', '==', 'dev-foo-bar'), - array('==', 'dev-foo-xyz', '==', 'dev-foo-xyz'), - array('>=', 'dev-foo-bar', '>=', 'dev-foo-xyz'), - array('<=', 'dev-foo-bar', '<', 'dev-foo-xyz'), - array('!=', 'dev-foo-bar', '<', 'dev-foo-xyz'), - array('>=', 'dev-foo-bar', '!=', 'dev-foo-bar'), - array('!=', 'dev-foo-bar', '!=', 'dev-foo-xyz'), - ); - } - - /** - * @dataProvider successfulVersionMatches - */ - public function testVersionMatchSucceeds($requireOperator, $requireVersion, $provideOperator, $provideVersion) - { - $versionRequire = new VersionConstraint($requireOperator, $requireVersion); - $versionProvide = new VersionConstraint($provideOperator, $provideVersion); - - $this->assertTrue($versionRequire->matches($versionProvide)); - } - - public static function failingVersionMatches() - { - return array( - // require provide - array('==', '1', '==', '2'), - array('>=', '2', '<=', '1'), - array('>=', '2', '<', '2'), - array('<=', '2', '>', '2'), - array('>', '2', '<=', '2'), - array('<=', '1', '>=', '2'), - array('>=', '2', '<=', '1'), - array('==', '2', '<', '2'), - array('!=', '1', '==', '1'), - array('==', '1', '!=', '1'), - array('==', 'dev-foo-dist', '==', 'dev-foo-zist'), - array('==', 'dev-foo-bist', '==', 'dev-foo-aist'), - array('<=', 'dev-foo-bist', '>=', 'dev-foo-aist'), - array('>=', 'dev-foo-bist', '<', 'dev-foo-aist'), - array('<', '0.12', '==', 'dev-foo'), // branches are not comparable - array('>', '0.12', '==', 'dev-foo'), // branches are not comparable - ); - } - - /** - * @dataProvider failingVersionMatches - */ - public function testVersionMatchFails($requireOperator, $requireVersion, $provideOperator, $provideVersion) - { - $versionRequire = new VersionConstraint($requireOperator, $requireVersion); - $versionProvide = new VersionConstraint($provideOperator, $provideVersion); - - $this->assertFalse($versionRequire->matches($versionProvide)); - } - - public function testComparableBranches() - { - $versionRequire = new VersionConstraint('>', '0.12'); - $versionProvide = new VersionConstraint('==', 'dev-foo'); - - $this->assertFalse($versionRequire->matches($versionProvide)); - $this->assertFalse($versionRequire->matchSpecific($versionProvide, true)); - - $versionRequire = new VersionConstraint('<', '0.12'); - $versionProvide = new VersionConstraint('==', 'dev-foo'); - - $this->assertFalse($versionRequire->matches($versionProvide)); - $this->assertTrue($versionRequire->matchSpecific($versionProvide, true)); - } -} diff --git a/tests/Composer/Test/Package/Version/VersionParserTest.php b/tests/Composer/Test/Package/Version/VersionParserTest.php deleted file mode 100644 index fe2dab749..000000000 --- a/tests/Composer/Test/Package/Version/VersionParserTest.php +++ /dev/null @@ -1,472 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Test\Package\Version; - -use Composer\Package\Link; -use Composer\Package\Version\VersionParser; -use Composer\Package\LinkConstraint\MultiConstraint; -use Composer\Package\LinkConstraint\VersionConstraint; -use Composer\Package\LinkConstraint\EmptyConstraint; -use Composer\Package\PackageInterface; - -class VersionParserTest extends \PHPUnit_Framework_TestCase -{ - - /** - * @dataProvider numericAliasVersions - */ - public function testParseNumericAliasPrefix($input, $expected) - { - $parser = new VersionParser; - $this->assertSame($expected, $parser->parseNumericAliasPrefix($input)); - } - - public function numericAliasVersions() - { - return array( - array('0.x-dev', '0.'), - array('1.0.x-dev', '1.0.'), - array('1.x-dev', '1.'), - array('1.2.x-dev', '1.2.'), - array('1.2-dev', '1.2.'), - array('1-dev', '1.'), - array('dev-develop', false), - array('dev-master', false), - ); - } - - /** - * @dataProvider successfulNormalizedVersions - */ - public function testNormalizeSucceeds($input, $expected) - { - $parser = new VersionParser; - $this->assertSame($expected, $parser->normalize($input)); - } - - public function successfulNormalizedVersions() - { - return array( - 'none' => array('1.0.0', '1.0.0.0'), - 'none/2' => array('1.2.3.4', '1.2.3.4'), - 'parses state' => array('1.0.0RC1dev', '1.0.0.0-RC1-dev'), - 'CI parsing' => array('1.0.0-rC15-dev', '1.0.0.0-RC15-dev'), - 'delimiters' => array('1.0.0.RC.15-dev', '1.0.0.0-RC15-dev'), - 'RC uppercase' => array('1.0.0-rc1', '1.0.0.0-RC1'), - 'patch replace' => array('1.0.0.pl3-dev', '1.0.0.0-patch3-dev'), - 'forces w.x.y.z' => array('1.0-dev', '1.0.0.0-dev'), - 'forces w.x.y.z/2' => array('0', '0.0.0.0'), - 'parses long' => array('10.4.13-beta', '10.4.13.0-beta'), - 'parses long/2' => array('10.4.13beta2', '10.4.13.0-beta2'), - 'parses long/semver' => array('10.4.13beta.2', '10.4.13.0-beta2'), - 'expand shorthand' => array('10.4.13-b', '10.4.13.0-beta'), - 'expand shorthand2' => array('10.4.13-b5', '10.4.13.0-beta5'), - 'strips leading v' => array('v1.0.0', '1.0.0.0'), - 'strips v/datetime' => array('v20100102', '20100102'), - 'parses dates y-m' => array('2010.01', '2010-01'), - 'parses dates w/ .' => array('2010.01.02', '2010-01-02'), - 'parses dates w/ -' => array('2010-01-02', '2010-01-02'), - 'parses numbers' => array('2010-01-02.5', '2010-01-02-5'), - 'parses dates y.m.Y' => array('2010.1.555', '2010.1.555.0'), - 'parses datetime' => array('20100102-203040', '20100102-203040'), - 'parses dt+number' => array('20100102203040-10', '20100102203040-10'), - 'parses dt+patch' => array('20100102-203040-p1', '20100102-203040-patch1'), - 'parses master' => array('dev-master', '9999999-dev'), - 'parses trunk' => array('dev-trunk', '9999999-dev'), - 'parses branches' => array('1.x-dev', '1.9999999.9999999.9999999-dev'), - 'parses arbitrary' => array('dev-feature-foo', 'dev-feature-foo'), - 'parses arbitrary2' => array('DEV-FOOBAR', 'dev-FOOBAR'), - 'parses arbitrary3' => array('dev-feature/foo', 'dev-feature/foo'), - 'ignores aliases' => array('dev-master as 1.0.0', '9999999-dev'), - 'semver metadata' => array('dev-master+foo.bar', '9999999-dev'), - 'semver metadata/2' => array('1.0.0-beta.5+foo', '1.0.0.0-beta5'), - 'semver metadata/3' => array('1.0.0+foo', '1.0.0.0'), - 'metadata w/ alias' => array('1.0.0+foo as 2.0', '1.0.0.0'), - ); - } - - /** - * @dataProvider failingNormalizedVersions - * @expectedException UnexpectedValueException - */ - public function testNormalizeFails($input) - { - $parser = new VersionParser; - $parser->normalize($input); - } - - public function failingNormalizedVersions() - { - return array( - 'empty ' => array(''), - 'invalid chars' => array('a'), - 'invalid type' => array('1.0.0-meh'), - 'too many bits' => array('1.0.0.0.0'), - 'non-dev arbitrary' => array('feature-foo'), - 'metadata w/ space' => array('1.0.0+foo bar'), - ); - } - - /** - * @dataProvider successfulNormalizedBranches - */ - public function testNormalizeBranch($input, $expected) - { - $parser = new VersionParser; - $this->assertSame((string) $expected, (string) $parser->normalizeBranch($input)); - } - - public function successfulNormalizedBranches() - { - return array( - 'parses x' => array('v1.x', '1.9999999.9999999.9999999-dev'), - 'parses *' => array('v1.*', '1.9999999.9999999.9999999-dev'), - 'parses digits' => array('v1.0', '1.0.9999999.9999999-dev'), - 'parses digits/2' => array('2.0', '2.0.9999999.9999999-dev'), - 'parses long x' => array('v1.0.x', '1.0.9999999.9999999-dev'), - 'parses long *' => array('v1.0.3.*', '1.0.3.9999999-dev'), - 'parses long digits' => array('v2.4.0', '2.4.0.9999999-dev'), - 'parses long digits/2' => array('2.4.4', '2.4.4.9999999-dev'), - 'parses master' => array('master', '9999999-dev'), - 'parses trunk' => array('trunk', '9999999-dev'), - 'parses arbitrary' => array('feature-a', 'dev-feature-a'), - 'parses arbitrary/2' => array('FOOBAR', 'dev-FOOBAR'), - ); - } - - public function testParseConstraintsIgnoresStabilityFlag() - { - $parser = new VersionParser; - $this->assertSame((string) new VersionConstraint('=', '1.0.0.0'), (string) $parser->parseConstraints('1.0@dev')); - } - - public function testParseConstraintsIgnoresReferenceOnDevVersion() - { - $parser = new VersionParser; - $this->assertSame((string) new VersionConstraint('=', '1.0.9999999.9999999-dev'), (string) $parser->parseConstraints('1.0.x-dev#abcd123')); - $this->assertSame((string) new VersionConstraint('=', '1.0.9999999.9999999-dev'), (string) $parser->parseConstraints('1.0.x-dev#trunk/@123')); - } - - /** - * @expectedException UnexpectedValueException - */ - public function testParseConstraintsFailsOnBadReference() - { - $parser = new VersionParser; - $this->assertSame((string) new VersionConstraint('=', '1.0.0.0'), (string) $parser->parseConstraints('1.0#abcd123')); - $this->assertSame((string) new VersionConstraint('=', '1.0.0.0'), (string) $parser->parseConstraints('1.0#trunk/@123')); - } - - /** - * @expectedException UnexpectedValueException - * @expectedExceptionMessage Invalid operator "~>", you probably meant to use the "~" operator - */ - public function testParseConstraintsNudgesRubyDevsTowardsThePathOfRighteousness() - { - $parser = new VersionParser; - $parser->parseConstraints('~>1.2'); - } - - /** - * @dataProvider simpleConstraints - */ - public function testParseConstraintsSimple($input, $expected) - { - $parser = new VersionParser; - $this->assertSame((string) $expected, (string) $parser->parseConstraints($input)); - } - - public function simpleConstraints() - { - return array( - 'match any' => array('*', new EmptyConstraint()), - 'match any/2' => array('*.*', new EmptyConstraint()), - 'match any/3' => array('*.x.*', new EmptyConstraint()), - 'match any/4' => array('x.X.x.*', new EmptyConstraint()), - 'not equal' => array('<>1.0.0', new VersionConstraint('<>', '1.0.0.0')), - 'not equal/2' => array('!=1.0.0', new VersionConstraint('!=', '1.0.0.0')), - 'greater than' => array('>1.0.0', new VersionConstraint('>', '1.0.0.0')), - 'lesser than' => array('<1.2.3.4', new VersionConstraint('<', '1.2.3.4-dev')), - 'less/eq than' => array('<=1.2.3', new VersionConstraint('<=', '1.2.3.0')), - 'great/eq than' => array('>=1.2.3', new VersionConstraint('>=', '1.2.3.0-dev')), - 'equals' => array('=1.2.3', new VersionConstraint('=', '1.2.3.0')), - 'double equals' => array('==1.2.3', new VersionConstraint('=', '1.2.3.0')), - 'no op means eq' => array('1.2.3', new VersionConstraint('=', '1.2.3.0')), - 'completes version' => array('=1.0', new VersionConstraint('=', '1.0.0.0')), - 'shorthand beta' => array('1.2.3b5', new VersionConstraint('=', '1.2.3.0-beta5')), - 'accepts spaces' => array('>= 1.2.3', new VersionConstraint('>=', '1.2.3.0-dev')), - 'accepts spaces/2' => array('< 1.2.3', new VersionConstraint('<', '1.2.3.0-dev')), - 'accepts spaces/3' => array('> 1.2.3', new VersionConstraint('>', '1.2.3.0')), - 'accepts master' => array('>=dev-master', new VersionConstraint('>=', '9999999-dev')), - 'accepts master/2' => array('dev-master', new VersionConstraint('=', '9999999-dev')), - 'accepts arbitrary' => array('dev-feature-a', new VersionConstraint('=', 'dev-feature-a')), - 'regression #550' => array('dev-some-fix', new VersionConstraint('=', 'dev-some-fix')), - 'regression #935' => array('dev-CAPS', new VersionConstraint('=', 'dev-CAPS')), - 'ignores aliases' => array('dev-master as 1.0.0', new VersionConstraint('=', '9999999-dev')), - 'lesser than override' => array('<1.2.3.4-stable', new VersionConstraint('<', '1.2.3.4')), - 'great/eq than override' => array('>=1.2.3.4-stable', new VersionConstraint('>=', '1.2.3.4')), - ); - } - - /** - * @dataProvider wildcardConstraints - */ - public function testParseConstraintsWildcard($input, $min, $max) - { - $parser = new VersionParser; - if ($min) { - $expected = new MultiConstraint(array($min, $max)); - } else { - $expected = $max; - } - - $this->assertSame((string) $expected, (string) $parser->parseConstraints($input)); - } - - public function wildcardConstraints() - { - return array( - array('2.*', new VersionConstraint('>=', '2.0.0.0-dev'), new VersionConstraint('<', '3.0.0.0-dev')), - array('20.*', new VersionConstraint('>=', '20.0.0.0-dev'), new VersionConstraint('<', '21.0.0.0-dev')), - array('2.0.*', new VersionConstraint('>=', '2.0.0.0-dev'), new VersionConstraint('<', '2.1.0.0-dev')), - array('2.2.x', new VersionConstraint('>=', '2.2.0.0-dev'), new VersionConstraint('<', '2.3.0.0-dev')), - array('2.10.X', new VersionConstraint('>=', '2.10.0.0-dev'), new VersionConstraint('<', '2.11.0.0-dev')), - array('2.1.3.*', new VersionConstraint('>=', '2.1.3.0-dev'), new VersionConstraint('<', '2.1.4.0-dev')), - array('0.*', null, new VersionConstraint('<', '1.0.0.0-dev')), - ); - } - - /** - * @dataProvider tildeConstraints - */ - public function testParseTildeWildcard($input, $min, $max) - { - $parser = new VersionParser; - if ($min) { - $expected = new MultiConstraint(array($min, $max)); - } else { - $expected = $max; - } - - $this->assertSame((string) $expected, (string) $parser->parseConstraints($input)); - } - - public function tildeConstraints() - { - return array( - array('~1', new VersionConstraint('>=', '1.0.0.0-dev'), new VersionConstraint('<', '2.0.0.0-dev')), - array('~1.0', new VersionConstraint('>=', '1.0.0.0-dev'), new VersionConstraint('<', '2.0.0.0-dev')), - array('~1.0.0', new VersionConstraint('>=', '1.0.0.0-dev'), new VersionConstraint('<', '1.1.0.0-dev')), - array('~1.2', new VersionConstraint('>=', '1.2.0.0-dev'), new VersionConstraint('<', '2.0.0.0-dev')), - array('~1.2.3', new VersionConstraint('>=', '1.2.3.0-dev'), new VersionConstraint('<', '1.3.0.0-dev')), - array('~1.2.3.4', new VersionConstraint('>=', '1.2.3.4-dev'), new VersionConstraint('<', '1.2.4.0-dev')), - array('~1.2-beta',new VersionConstraint('>=', '1.2.0.0-beta'), new VersionConstraint('<', '2.0.0.0-dev')), - array('~1.2-b2', new VersionConstraint('>=', '1.2.0.0-beta2'), new VersionConstraint('<', '2.0.0.0-dev')), - array('~1.2-BETA2', new VersionConstraint('>=', '1.2.0.0-beta2'), new VersionConstraint('<', '2.0.0.0-dev')), - array('~1.2.2-dev', new VersionConstraint('>=', '1.2.2.0-dev'), new VersionConstraint('<', '1.3.0.0-dev')), - array('~1.2.2-stable', new VersionConstraint('>=', '1.2.2.0-stable'), new VersionConstraint('<', '1.3.0.0-dev')), - ); - } - - /** - * @dataProvider caretConstraints - */ - public function testParseCaretWildcard($input, $min, $max) - { - $parser = new VersionParser; - if ($min) { - $expected = new MultiConstraint(array($min, $max)); - } else { - $expected = $max; - } - - $this->assertSame((string) $expected, (string) $parser->parseConstraints($input)); - } - - public function caretConstraints() - { - return array( - array('^1', new VersionConstraint('>=', '1.0.0.0-dev'), new VersionConstraint('<', '2.0.0.0-dev')), - array('^0', new VersionConstraint('>=', '0.0.0.0-dev'), new VersionConstraint('<', '1.0.0.0-dev')), - array('^0.0', new VersionConstraint('>=', '0.0.0.0-dev'), new VersionConstraint('<', '0.1.0.0-dev')), - array('^1.2', new VersionConstraint('>=', '1.2.0.0-dev'), new VersionConstraint('<', '2.0.0.0-dev')), - array('^1.2.3-beta.2', new VersionConstraint('>=', '1.2.3.0-beta2'), new VersionConstraint('<', '2.0.0.0-dev')), - array('^1.2.3.4', new VersionConstraint('>=', '1.2.3.4-dev'), new VersionConstraint('<', '2.0.0.0-dev')), - array('^1.2.3', new VersionConstraint('>=', '1.2.3.0-dev'), new VersionConstraint('<', '2.0.0.0-dev')), - array('^0.2.3', new VersionConstraint('>=', '0.2.3.0-dev'), new VersionConstraint('<', '0.3.0.0-dev')), - array('^0.2', new VersionConstraint('>=', '0.2.0.0-dev'), new VersionConstraint('<', '0.3.0.0-dev')), - array('^0.2.0', new VersionConstraint('>=', '0.2.0.0-dev'), new VersionConstraint('<', '0.3.0.0-dev')), - array('^0.0.3', new VersionConstraint('>=', '0.0.3.0-dev'), new VersionConstraint('<', '0.0.4.0-dev')), - array('^0.0.3-alpha', new VersionConstraint('>=', '0.0.3.0-alpha'), new VersionConstraint('<', '0.0.4.0-dev')), - array('^0.0.3-dev', new VersionConstraint('>=', '0.0.3.0-dev'), new VersionConstraint('<', '0.0.4.0-dev')), - ); - } - - /** - * @dataProvider hyphenConstraints - */ - public function testParseHyphen($input, $min, $max) - { - $parser = new VersionParser; - if ($min) { - $expected = new MultiConstraint(array($min, $max)); - } else { - $expected = $max; - } - - $this->assertSame((string) $expected, (string) $parser->parseConstraints($input)); - } - - public function hyphenConstraints() - { - return array( - array('1 - 2', new VersionConstraint('>=', '1.0.0.0-dev'), new VersionConstraint('<', '3.0.0.0-dev')), - array('1.2.3 - 2.3.4.5', new VersionConstraint('>=', '1.2.3.0-dev'), new VersionConstraint('<=', '2.3.4.5')), - array('1.2-beta - 2.3', new VersionConstraint('>=', '1.2.0.0-beta'), new VersionConstraint('<', '2.4.0.0-dev')), - array('1.2-beta - 2.3-dev', new VersionConstraint('>=', '1.2.0.0-beta'), new VersionConstraint('<=', '2.3.0.0-dev')), - array('1.2-RC - 2.3.1', new VersionConstraint('>=', '1.2.0.0-RC'), new VersionConstraint('<=', '2.3.1.0')), - array('1.2.3-alpha - 2.3-RC', new VersionConstraint('>=', '1.2.3.0-alpha'), new VersionConstraint('<=', '2.3.0.0-RC')), - array('1 - 2.0', new VersionConstraint('>=', '1.0.0.0-dev'), new VersionConstraint('<', '2.1.0.0-dev')), - array('1 - 2.1', new VersionConstraint('>=', '1.0.0.0-dev'), new VersionConstraint('<', '2.2.0.0-dev')), - array('1.2 - 2.1.0', new VersionConstraint('>=', '1.2.0.0-dev'), new VersionConstraint('<=', '2.1.0.0')), - array('1.3 - 2.1.3', new VersionConstraint('>=', '1.3.0.0-dev'), new VersionConstraint('<=', '2.1.3.0')), - ); - } - - /** - * @dataProvider multiConstraintProvider - */ - public function testParseConstraintsMulti($constraint) - { - $parser = new VersionParser; - $first = new VersionConstraint('>', '2.0.0.0'); - $second = new VersionConstraint('<=', '3.0.0.0'); - $multi = new MultiConstraint(array($first, $second)); - $this->assertSame((string) $multi, (string) $parser->parseConstraints($constraint)); - } - - public function multiConstraintProvider() - { - return array( - array('>2.0,<=3.0'), - array('>2.0 <=3.0'), - array('>2.0 <=3.0'), - array('>2.0, <=3.0'), - array('>2.0 ,<=3.0'), - array('>2.0 , <=3.0'), - array('>2.0 , <=3.0'), - array('> 2.0 <= 3.0'), - array('> 2.0 , <= 3.0'), - array(' > 2.0 , <= 3.0 '), - ); - } - - public function testParseConstraintsMultiWithStabilitySuffix() - { - $parser = new VersionParser; - $first = new VersionConstraint('>=', '1.1.0.0-alpha4'); - $second = new VersionConstraint('<', '1.2.9999999.9999999-dev'); - $multi = new MultiConstraint(array($first, $second)); - $this->assertSame((string) $multi, (string) $parser->parseConstraints('>=1.1.0-alpha4,<1.2.x-dev')); - - $first = new VersionConstraint('>=', '1.1.0.0-alpha4'); - $second = new VersionConstraint('<', '1.2.0.0-beta2'); - $multi = new MultiConstraint(array($first, $second)); - $this->assertSame((string) $multi, (string) $parser->parseConstraints('>=1.1.0-alpha4,<1.2-beta2')); - } - - /** - * @dataProvider multiConstraintProvider2 - */ - public function testParseConstraintsMultiDisjunctiveHasPrioOverConjuctive($constraint) - { - $parser = new VersionParser; - $first = new VersionConstraint('>', '2.0.0.0'); - $second = new VersionConstraint('<', '2.0.5.0-dev'); - $third = new VersionConstraint('>', '2.0.6.0'); - $multi1 = new MultiConstraint(array($first, $second)); - $multi2 = new MultiConstraint(array($multi1, $third), false); - $this->assertSame((string) $multi2, (string) $parser->parseConstraints($constraint)); - } - - public function multiConstraintProvider2() - { - return array( - array('>2.0,<2.0.5 | >2.0.6'), - array('>2.0,<2.0.5 || >2.0.6'), - array('> 2.0 , <2.0.5 | > 2.0.6'), - ); - } - - public function testParseConstraintsMultiWithStabilities() - { - $parser = new VersionParser; - $first = new VersionConstraint('>', '2.0.0.0'); - $second = new VersionConstraint('<=', '3.0.0.0-dev'); - $multi = new MultiConstraint(array($first, $second)); - $this->assertSame((string) $multi, (string) $parser->parseConstraints('>2.0@stable,<=3.0@dev')); - } - - /** - * @dataProvider failingConstraints - * @expectedException UnexpectedValueException - */ - public function testParseConstraintsFails($input) - { - $parser = new VersionParser; - $parser->parseConstraints($input); - } - - public function failingConstraints() - { - return array( - 'empty ' => array(''), - 'invalid version' => array('1.0.0-meh'), - 'operator abuse' => array('>2.0,,<=3.0'), - 'operator abuse/2' => array('>2.0 ,, <=3.0'), - 'operator abuse/3' => array('>2.0 ||| <=3.0'), - ); - } - - /** - * @dataProvider stabilityProvider - */ - public function testParseStability($expected, $version) - { - $this->assertSame($expected, VersionParser::parseStability($version)); - } - - public function stabilityProvider() - { - return array( - array('stable', '1'), - array('stable', '1.0'), - array('stable', '3.2.1'), - array('stable', 'v3.2.1'), - array('dev', 'v2.0.x-dev'), - array('dev', 'v2.0.x-dev#abc123'), - array('dev', 'v2.0.x-dev#trunk/@123'), - array('RC', '3.0-RC2'), - array('dev', 'dev-master'), - array('dev', '3.1.2-dev'), - array('stable', '3.1.2-pl2'), - array('stable', '3.1.2-patch'), - array('alpha', '3.1.2-alpha5'), - array('beta', '3.1.2-beta'), - array('beta', '2.0B1'), - array('alpha', '1.2.0a1'), - array('alpha', '1.2_a1'), - array('RC', '2.0.0rc1') - ); - } -} From a1427d7fd626d4308c190a267dd7a993f87c6a2a Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Thu, 24 Sep 2015 16:32:36 +0200 Subject: [PATCH 191/205] replace all occurences in code and comments --- src/Composer/Command/CreateProjectCommand.php | 2 +- src/Composer/Command/InitCommand.php | 2 +- src/Composer/Command/RequireCommand.php | 2 +- src/Composer/Command/ShowCommand.php | 2 +- .../DependencyResolver/DefaultPolicy.php | 8 ++--- src/Composer/DependencyResolver/Pool.php | 34 +++++++++---------- src/Composer/DependencyResolver/Problem.php | 2 +- src/Composer/DependencyResolver/Request.php | 12 +++---- src/Composer/Factory.php | 2 +- src/Composer/Installer.php | 18 +++++----- src/Composer/Package/AliasPackage.php | 8 ++--- src/Composer/Package/Link.php | 18 +++++----- src/Composer/Package/Loader/ArrayLoader.php | 2 +- .../Package/Loader/RootPackageLoader.php | 2 +- .../Package/Loader/ValidatingArrayLoader.php | 6 ++-- src/Composer/Package/Package.php | 2 +- .../Package/Version/VersionGuesser.php | 1 + .../Package/Version/VersionSelector.php | 1 + src/Composer/Plugin/PluginManager.php | 6 ++-- src/Composer/Repository/ArrayRepository.php | 14 ++++---- .../Repository/ComposerRepository.php | 14 ++++---- src/Composer/Repository/PathRepository.php | 2 +- src/Composer/Repository/PearRepository.php | 8 ++--- .../Repository/PlatformRepository.php | 2 +- .../Repository/RepositoryInterface.php | 8 ++--- src/Composer/Repository/RepositoryManager.php | 8 ++--- src/Composer/Repository/VcsRepository.php | 2 +- .../DependencyResolver/DefaultPolicyTest.php | 14 ++++---- .../Test/DependencyResolver/SolverTest.php | 2 +- .../Test/Package/CompletePackageTest.php | 2 +- .../Test/Package/Dumper/ArrayDumperTest.php | 16 ++++----- .../Package/Loader/RootPackageLoaderTest.php | 2 +- .../Package/Version/VersionGuesserTest.php | 2 +- .../Package/Version/VersionSelectorTest.php | 2 +- .../Repository/ComposerRepositoryTest.php | 2 +- .../Test/Repository/PathRepositoryTest.php | 2 +- .../Repository/Pear/ChannelReaderTest.php | 8 ++--- tests/Composer/TestCase.php | 6 ++-- 38 files changed, 124 insertions(+), 122 deletions(-) diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index 54cd63538..4c93561eb 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -36,7 +36,7 @@ use Composer\Json\JsonFile; use Composer\Config\JsonConfigSource; use Composer\Util\Filesystem; use Composer\Util\RemoteFilesystem; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; /** * Install a package as new project into new directory. diff --git a/src/Composer/Command/InitCommand.php b/src/Composer/Command/InitCommand.php index 112c10129..fe5e1bda0 100644 --- a/src/Composer/Command/InitCommand.php +++ b/src/Composer/Command/InitCommand.php @@ -19,7 +19,7 @@ use Composer\Package\BasePackage; use Composer\Package\Version\VersionSelector; use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; use Composer\Util\ProcessExecutor; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; diff --git a/src/Composer/Command/RequireCommand.php b/src/Composer/Command/RequireCommand.php index 4499904bb..c7bcc8735 100644 --- a/src/Composer/Command/RequireCommand.php +++ b/src/Composer/Command/RequireCommand.php @@ -20,7 +20,7 @@ use Composer\Factory; use Composer\Installer; use Composer\Json\JsonFile; use Composer\Json\JsonManipulator; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Repository\CompositeRepository; diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index 30d8797c8..81bc93b3f 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -16,7 +16,7 @@ use Composer\DependencyResolver\Pool; use Composer\DependencyResolver\DefaultPolicy; use Composer\Factory; use Composer\Package\CompletePackageInterface; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Symfony\Component\Console\Input\InputInterface; diff --git a/src/Composer/DependencyResolver/DefaultPolicy.php b/src/Composer/DependencyResolver/DefaultPolicy.php index 440d6856c..684f11851 100644 --- a/src/Composer/DependencyResolver/DefaultPolicy.php +++ b/src/Composer/DependencyResolver/DefaultPolicy.php @@ -15,7 +15,7 @@ namespace Composer\DependencyResolver; use Composer\Package\PackageInterface; use Composer\Package\AliasPackage; use Composer\Package\BasePackage; -use Composer\Package\LinkConstraint\VersionConstraint; +use Composer\Semver\Constraint\Constraint; /** * @author Nils Adermann @@ -38,8 +38,8 @@ class DefaultPolicy implements PolicyInterface return BasePackage::$stabilities[$stabA] < BasePackage::$stabilities[$stabB]; } - $constraint = new VersionConstraint($operator, $b->getVersion()); - $version = new VersionConstraint('==', $a->getVersion()); + $constraint = new Constraint($operator, $b->getVersion()); + $version = new Constraint('==', $a->getVersion()); return $constraint->matchSpecific($version, true); } @@ -194,7 +194,7 @@ class DefaultPolicy implements PolicyInterface foreach ($source->getReplaces() as $link) { if ($link->getTarget() === $target->getName() // && (null === $link->getConstraint() || -// $link->getConstraint()->matches(new VersionConstraint('==', $target->getVersion())))) { +// $link->getConstraint()->matches(new Constraint('==', $target->getVersion())))) { ) { return true; } diff --git a/src/Composer/DependencyResolver/Pool.php b/src/Composer/DependencyResolver/Pool.php index 343fad9be..d5eac138e 100644 --- a/src/Composer/DependencyResolver/Pool.php +++ b/src/Composer/DependencyResolver/Pool.php @@ -14,10 +14,10 @@ namespace Composer\DependencyResolver; use Composer\Package\BasePackage; use Composer\Package\AliasPackage; -use Composer\Package\Version\VersionParser; -use Composer\Package\LinkConstraint\LinkConstraintInterface; -use Composer\Package\LinkConstraint\VersionConstraint; -use Composer\Package\LinkConstraint\EmptyConstraint; +use Composer\Semver\VersionParser; +use Composer\Semver\Constraint\ConstraintInterface; +use Composer\Semver\Constraint\Constraint; +use Composer\Semver\Constraint\EmptyConstraint; use Composer\Repository\RepositoryInterface; use Composer\Repository\CompositeRepository; use Composer\Repository\ComposerRepository; @@ -171,14 +171,14 @@ class Pool implements \Countable /** * Searches all packages providing the given package name and match the constraint * - * @param string $name The package name to be searched for - * @param LinkConstraintInterface $constraint A constraint that all returned - * packages must match or null to return all - * @param bool $mustMatchName Whether the name of returned packages - * must match the given name - * @return PackageInterface[] A set of packages + * @param string $name The package name to be searched for + * @param ConstraintInterface $constraint A constraint that all returned + * packages must match or null to return all + * @param bool $mustMatchName Whether the name of returned packages + * must match the given name + * @return PackageInterface[] A set of packages */ - public function whatProvides($name, LinkConstraintInterface $constraint = null, $mustMatchName = false) + public function whatProvides($name, ConstraintInterface $constraint = null, $mustMatchName = false) { $key = ((int) $mustMatchName).$constraint; if (isset($this->providerCache[$name][$key])) { @@ -317,12 +317,12 @@ class Pool implements \Countable * Checks if the package matches the given constraint directly or through * provided or replaced packages * - * @param array|PackageInterface $candidate - * @param string $name Name of the package to be matched - * @param LinkConstraintInterface $constraint The constraint to verify - * @return int One of the MATCH* constants of this class or 0 if there is no match + * @param array|PackageInterface $candidate + * @param string $name Name of the package to be matched + * @param ConstraintInterface $constraint The constraint to verify + * @return int One of the MATCH* constants of this class or 0 if there is no match */ - private function match($candidate, $name, LinkConstraintInterface $constraint = null) + private function match($candidate, $name, ConstraintInterface $constraint = null) { $candidateName = $candidate->getName(); $candidateVersion = $candidate->getVersion(); @@ -336,7 +336,7 @@ class Pool implements \Countable } if ($candidateName === $name) { - $pkgConstraint = new VersionConstraint('==', $candidateVersion); + $pkgConstraint = new Constraint('==', $candidateVersion); if ($constraint === null || $constraint->matches($pkgConstraint)) { return $requireFilter->matches($pkgConstraint) ? self::MATCH : self::MATCH_FILTERED; diff --git a/src/Composer/DependencyResolver/Problem.php b/src/Composer/DependencyResolver/Problem.php index 5d2117f2c..f4e5f1744 100644 --- a/src/Composer/DependencyResolver/Problem.php +++ b/src/Composer/DependencyResolver/Problem.php @@ -222,7 +222,7 @@ class Problem /** * Turns a constraint into text usable in a sentence describing a job * - * @param \Composer\Package\LinkConstraint\LinkConstraintInterface $constraint + * @param \Composer\Semver\Constraint\ConstraintInterface $constraint * @return string */ protected function constraintToText($constraint) diff --git a/src/Composer/DependencyResolver/Request.php b/src/Composer/DependencyResolver/Request.php index 0776f040e..10ffcb2c4 100644 --- a/src/Composer/DependencyResolver/Request.php +++ b/src/Composer/DependencyResolver/Request.php @@ -12,7 +12,7 @@ namespace Composer\DependencyResolver; -use Composer\Package\LinkConstraint\LinkConstraintInterface; +use Composer\Semver\Constraint\ConstraintInterface; /** * @author Nils Adermann @@ -26,17 +26,17 @@ class Request $this->jobs = array(); } - public function install($packageName, LinkConstraintInterface $constraint = null) + public function install($packageName, ConstraintInterface $constraint = null) { $this->addJob($packageName, 'install', $constraint); } - public function update($packageName, LinkConstraintInterface $constraint = null) + public function update($packageName, ConstraintInterface $constraint = null) { $this->addJob($packageName, 'update', $constraint); } - public function remove($packageName, LinkConstraintInterface $constraint = null) + public function remove($packageName, ConstraintInterface $constraint = null) { $this->addJob($packageName, 'remove', $constraint); } @@ -46,12 +46,12 @@ class Request * * These jobs will not be tempered with by the solver */ - public function fix($packageName, LinkConstraintInterface $constraint = null) + public function fix($packageName, ConstraintInterface $constraint = null) { $this->addJob($packageName, 'install', $constraint, true); } - protected function addJob($packageName, $cmd, LinkConstraintInterface $constraint = null, $fixed = false) + protected function addJob($packageName, $cmd, ConstraintInterface $constraint = null, $fixed = false) { $packageName = strtolower($packageName); diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 2e6f31898..e3c899880 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -24,7 +24,7 @@ use Composer\Util\RemoteFilesystem; use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Composer\EventDispatcher\EventDispatcher; use Composer\Autoload\AutoloadGenerator; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; /** * Creates a configured instance of composer. diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 3f208ea32..c94eedc7f 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -34,7 +34,7 @@ use Composer\Json\JsonFile; use Composer\Package\AliasPackage; use Composer\Package\CompletePackage; use Composer\Package\Link; -use Composer\Package\LinkConstraint\VersionConstraint; +use Composer\Semver\Constraint\Constraint; use Composer\Package\Locker; use Composer\Package\PackageInterface; use Composer\Package\RootPackageInterface; @@ -428,7 +428,7 @@ class Installer && $this->installationManager->isPackageInstalled($localRepo, $package) ) { $removedUnstablePackages[$package->getName()] = true; - $request->remove($package->getName(), new VersionConstraint('=', $package->getVersion())); + $request->remove($package->getName(), new Constraint('=', $package->getVersion())); } } } @@ -467,7 +467,7 @@ class Installer foreach ($currentPackages as $curPackage) { if ($curPackage->getName() === $candidate) { if (!$this->isUpdateable($curPackage) && !isset($removedUnstablePackages[$curPackage->getName()])) { - $constraint = new VersionConstraint('=', $curPackage->getVersion()); + $constraint = new Constraint('=', $curPackage->getVersion()); $request->install($curPackage->getName(), $constraint); } break; @@ -487,7 +487,7 @@ class Installer if (isset($aliases[$package->getName()][$version])) { $version = $aliases[$package->getName()][$version]['alias_normalized']; } - $constraint = new VersionConstraint('=', $version); + $constraint = new Constraint('=', $version); $constraint->setPrettyString($package->getPrettyVersion()); $request->install($package->getName(), $constraint); } @@ -712,7 +712,7 @@ class Installer $requires = array(); foreach ($lockedRepository->getPackages() as $package) { - $constraint = new VersionConstraint('=', $package->getVersion()); + $constraint = new Constraint('=', $package->getVersion()); $constraint->setPrettyString($package->getPrettyVersion()); $requires[$package->getName()] = $constraint; } @@ -774,7 +774,7 @@ class Installer { $request = new Request(); - $constraint = new VersionConstraint('=', $rootPackage->getVersion()); + $constraint = new Constraint('=', $rootPackage->getVersion()); $constraint->setPrettyString($rootPackage->getPrettyVersion()); $request->install($rootPackage->getName(), $constraint); @@ -788,7 +788,7 @@ class Installer // to prevent the solver trying to remove or update those $provided = $rootPackage->getProvides(); foreach ($fixedPackages as $package) { - $constraint = new VersionConstraint('=', $package->getVersion()); + $constraint = new Constraint('=', $package->getVersion()); $constraint->setPrettyString($package->getPrettyVersion()); // skip platform packages that are provided by the root package @@ -893,7 +893,7 @@ class Installer } // find similar packages (name/version) in all repositories - $matches = $pool->whatProvides($package->getName(), new VersionConstraint('=', $package->getVersion())); + $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion())); foreach ($matches as $index => $match) { // skip local packages if (!in_array($match->getRepository(), $repositories, true)) { @@ -1003,7 +1003,7 @@ class Installer foreach ($localRepo->getCanonicalPackages() as $package) { // find similar packages (name/version) in all repositories - $matches = $pool->whatProvides($package->getName(), new VersionConstraint('=', $package->getVersion())); + $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion())); foreach ($matches as $index => $match) { // skip local packages if (!in_array($match->getRepository(), $repositories, true)) { diff --git a/src/Composer/Package/AliasPackage.php b/src/Composer/Package/AliasPackage.php index f6aa98a4c..130de6bae 100644 --- a/src/Composer/Package/AliasPackage.php +++ b/src/Composer/Package/AliasPackage.php @@ -12,8 +12,8 @@ namespace Composer\Package; -use Composer\Package\LinkConstraint\VersionConstraint; -use Composer\Package\Version\VersionParser; +use Composer\Semver\Constraint\Constraint; +use Composer\Semver\VersionParser; /** * @author Jordi Boggiano @@ -174,14 +174,14 @@ class AliasPackage extends BasePackage implements CompletePackageInterface foreach ($links as $link) { // link is self.version, but must be replacing also the replaced version if ('self.version' === $link->getPrettyConstraint()) { - $newLinks[] = new Link($link->getSource(), $link->getTarget(), new VersionConstraint('=', $this->version), $linkType, $this->prettyVersion); + $newLinks[] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion); } } $links = array_merge($links, $newLinks); } else { foreach ($links as $index => $link) { if ('self.version' === $link->getPrettyConstraint()) { - $links[$index] = new Link($link->getSource(), $link->getTarget(), new VersionConstraint('=', $this->version), $linkType, $this->prettyVersion); + $links[$index] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion); } } } diff --git a/src/Composer/Package/Link.php b/src/Composer/Package/Link.php index e09f163eb..fb2662a6f 100644 --- a/src/Composer/Package/Link.php +++ b/src/Composer/Package/Link.php @@ -12,7 +12,7 @@ namespace Composer\Package; -use Composer\Package\LinkConstraint\LinkConstraintInterface; +use Composer\Semver\Constraint\ConstraintInterface; /** * Represents a link between two packages, represented by their names @@ -32,7 +32,7 @@ class Link protected $target; /** - * @var LinkConstraintInterface|null + * @var ConstraintInterface|null */ protected $constraint; @@ -49,13 +49,13 @@ class Link /** * Creates a new package link. * - * @param string $source - * @param string $target - * @param LinkConstraintInterface|null $constraint Constraint applying to the target of this link - * @param string $description Used to create a descriptive string representation - * @param string|null $prettyConstraint + * @param string $source + * @param string $target + * @param ConstraintInterface|null $constraint Constraint applying to the target of this link + * @param string $description Used to create a descriptive string representation + * @param string|null $prettyConstraint */ - public function __construct($source, $target, LinkConstraintInterface $constraint = null, $description = 'relates to', $prettyConstraint = null) + public function __construct($source, $target, ConstraintInterface $constraint = null, $description = 'relates to', $prettyConstraint = null) { $this->source = strtolower($source); $this->target = strtolower($target); @@ -81,7 +81,7 @@ class Link } /** - * @return LinkConstraintInterface|null + * @return ConstraintInterface|null */ public function getConstraint() { diff --git a/src/Composer/Package/Loader/ArrayLoader.php b/src/Composer/Package/Loader/ArrayLoader.php index 160b8000a..42398e41f 100644 --- a/src/Composer/Package/Loader/ArrayLoader.php +++ b/src/Composer/Package/Loader/ArrayLoader.php @@ -17,7 +17,7 @@ use Composer\Package\AliasPackage; use Composer\Package\Link; use Composer\Package\RootAliasPackage; use Composer\Package\RootPackageInterface; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; /** * @author Konstantin Kudryashiv diff --git a/src/Composer/Package/Loader/RootPackageLoader.php b/src/Composer/Package/Loader/RootPackageLoader.php index c084c846a..1266346db 100644 --- a/src/Composer/Package/Loader/RootPackageLoader.php +++ b/src/Composer/Package/Loader/RootPackageLoader.php @@ -17,7 +17,7 @@ use Composer\Package\AliasPackage; use Composer\Config; use Composer\Factory; use Composer\Package\Version\VersionGuesser; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; use Composer\Repository\RepositoryManager; use Composer\Util\ProcessExecutor; diff --git a/src/Composer/Package/Loader/ValidatingArrayLoader.php b/src/Composer/Package/Loader/ValidatingArrayLoader.php index 86386989c..4f01a680d 100644 --- a/src/Composer/Package/Loader/ValidatingArrayLoader.php +++ b/src/Composer/Package/Loader/ValidatingArrayLoader.php @@ -14,8 +14,8 @@ namespace Composer\Package\Loader; use Composer\Package; use Composer\Package\BasePackage; -use Composer\Package\LinkConstraint\VersionConstraint; -use Composer\Package\Version\VersionParser; +use Composer\Semver\Constraint\Constraint; +use Composer\Semver\VersionParser; use Composer\Repository\PlatformRepository; /** @@ -149,7 +149,7 @@ class ValidatingArrayLoader implements LoaderInterface } } - $unboundConstraint = new VersionConstraint('=', $this->versionParser->normalize('dev-master')); + $unboundConstraint = new Constraint('=', $this->versionParser->normalize('dev-master')); foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) { if ($this->validateArray($linkType) && isset($this->config[$linkType])) { diff --git a/src/Composer/Package/Package.php b/src/Composer/Package/Package.php index 0c98a0e56..7f813887e 100644 --- a/src/Composer/Package/Package.php +++ b/src/Composer/Package/Package.php @@ -12,7 +12,7 @@ namespace Composer\Package; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; use Composer\Util\ComposerMirror; /** diff --git a/src/Composer/Package/Version/VersionGuesser.php b/src/Composer/Package/Version/VersionGuesser.php index 34f997078..6f71dbe7d 100644 --- a/src/Composer/Package/Version/VersionGuesser.php +++ b/src/Composer/Package/Version/VersionGuesser.php @@ -15,6 +15,7 @@ namespace Composer\Package\Version; use Composer\Config; use Composer\Repository\Vcs\HgDriver; use Composer\IO\NullIO; +use Composer\Semver\VersionParser; use Composer\Util\Git as GitUtil; use Composer\Util\ProcessExecutor; use Composer\Util\Svn as SvnUtil; diff --git a/src/Composer/Package/Version/VersionSelector.php b/src/Composer/Package/Version/VersionSelector.php index 563ba056a..04b4cd28d 100644 --- a/src/Composer/Package/Version/VersionSelector.php +++ b/src/Composer/Package/Version/VersionSelector.php @@ -16,6 +16,7 @@ use Composer\DependencyResolver\Pool; use Composer\Package\PackageInterface; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Dumper\ArrayDumper; +use Composer\Semver\VersionParser; /** * Selects the best possible version for a package diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index 833b3e29b..be8d925cd 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -16,12 +16,12 @@ use Composer\Composer; use Composer\EventDispatcher\EventSubscriberInterface; use Composer\IO\IOInterface; use Composer\Package\Package; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; use Composer\Repository\RepositoryInterface; use Composer\Package\AliasPackage; use Composer\Package\PackageInterface; use Composer\Package\Link; -use Composer\Package\LinkConstraint\VersionConstraint; +use Composer\Semver\Constraint\Constraint; use Composer\DependencyResolver\Pool; /** @@ -131,7 +131,7 @@ class PluginManager } $currentPluginApiVersion = $this->getPluginApiVersion(); - $currentPluginApiConstraint = new VersionConstraint('==', $this->versionParser->normalize($currentPluginApiVersion)); + $currentPluginApiConstraint = new Constraint('==', $this->versionParser->normalize($currentPluginApiVersion)); if (!$requiresComposer->matches($currentPluginApiConstraint)) { $this->io->writeError('The "' . $package->getName() . '" plugin was skipped because it requires a Plugin API version ("' . $requiresComposer->getPrettyString() . '") that does not match your Composer installation ("' . $currentPluginApiVersion . '"). You may need to run composer update with the "--no-plugins" option.'); diff --git a/src/Composer/Repository/ArrayRepository.php b/src/Composer/Repository/ArrayRepository.php index a5023c1fe..5f9eaf406 100644 --- a/src/Composer/Repository/ArrayRepository.php +++ b/src/Composer/Repository/ArrayRepository.php @@ -15,9 +15,9 @@ namespace Composer\Repository; use Composer\Package\AliasPackage; use Composer\Package\PackageInterface; use Composer\Package\CompletePackageInterface; -use Composer\Package\Version\VersionParser; -use Composer\Package\LinkConstraint\LinkConstraintInterface; -use Composer\Package\LinkConstraint\VersionConstraint; +use Composer\Semver\VersionParser; +use Composer\Semver\Constraint\ConstraintInterface; +use Composer\Semver\Constraint\Constraint; /** * A repository implementation that simply stores packages in an array @@ -43,14 +43,14 @@ class ArrayRepository implements RepositoryInterface { $name = strtolower($name); - if (!$constraint instanceof LinkConstraintInterface) { + if (!$constraint instanceof ConstraintInterface) { $versionParser = new VersionParser(); $constraint = $versionParser->parseConstraints($constraint); } foreach ($this->getPackages() as $package) { if ($name === $package->getName()) { - $pkgConstraint = new VersionConstraint('==', $package->getVersion()); + $pkgConstraint = new Constraint('==', $package->getVersion()); if ($constraint->matches($pkgConstraint)) { return $package; } @@ -67,14 +67,14 @@ class ArrayRepository implements RepositoryInterface $name = strtolower($name); $packages = array(); - if (null !== $constraint && !$constraint instanceof LinkConstraintInterface) { + if (null !== $constraint && !$constraint instanceof ConstraintInterface) { $versionParser = new VersionParser(); $constraint = $versionParser->parseConstraints($constraint); } foreach ($this->getPackages() as $package) { if ($name === $package->getName()) { - $pkgConstraint = new VersionConstraint('==', $package->getVersion()); + $pkgConstraint = new Constraint('==', $package->getVersion()); if (null === $constraint || $constraint->matches($pkgConstraint)) { $packages[] = $package; } diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index f3b0642d0..632f3a03b 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -15,7 +15,7 @@ namespace Composer\Repository; use Composer\Package\Loader\ArrayLoader; use Composer\Package\PackageInterface; use Composer\Package\AliasPackage; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; use Composer\DependencyResolver\Pool; use Composer\Json\JsonFile; use Composer\Cache; @@ -25,8 +25,8 @@ use Composer\Util\RemoteFilesystem; use Composer\Plugin\PluginEvents; use Composer\Plugin\PreFileDownloadEvent; use Composer\EventDispatcher\EventDispatcher; -use Composer\Package\LinkConstraint\LinkConstraintInterface; -use Composer\Package\LinkConstraint\VersionConstraint; +use Composer\Semver\Constraint\ConstraintInterface; +use Composer\Semver\Constraint\Constraint; /** * @author Jordi Boggiano @@ -107,7 +107,7 @@ class ComposerRepository extends ArrayRepository } $name = strtolower($name); - if (!$constraint instanceof LinkConstraintInterface) { + if (!$constraint instanceof ConstraintInterface) { $versionParser = new VersionParser(); $constraint = $versionParser->parseConstraints($constraint); } @@ -117,7 +117,7 @@ class ComposerRepository extends ArrayRepository $packages = $this->whatProvides(new Pool('dev'), $providerName); foreach ($packages as $package) { if ($name === $package->getName()) { - $pkgConstraint = new VersionConstraint('==', $package->getVersion()); + $pkgConstraint = new Constraint('==', $package->getVersion()); if ($constraint->matches($pkgConstraint)) { return $package; } @@ -138,7 +138,7 @@ class ComposerRepository extends ArrayRepository // normalize name $name = strtolower($name); - if (null !== $constraint && !$constraint instanceof LinkConstraintInterface) { + if (null !== $constraint && !$constraint instanceof ConstraintInterface) { $versionParser = new VersionParser(); $constraint = $versionParser->parseConstraints($constraint); } @@ -150,7 +150,7 @@ class ComposerRepository extends ArrayRepository $candidates = $this->whatProvides(new Pool('dev'), $providerName); foreach ($candidates as $package) { if ($name === $package->getName()) { - $pkgConstraint = new VersionConstraint('==', $package->getVersion()); + $pkgConstraint = new Constraint('==', $package->getVersion()); if (null === $constraint || $constraint->matches($pkgConstraint)) { $packages[] = $package; } diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index 3b600ea36..18827f896 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -18,7 +18,7 @@ use Composer\Json\JsonFile; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Loader\LoaderInterface; use Composer\Package\Version\VersionGuesser; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; use Composer\Util\ProcessExecutor; /** diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 1f882eb80..e2519d9b9 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -13,13 +13,13 @@ namespace Composer\Repository; use Composer\IO\IOInterface; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; use Composer\Repository\Pear\ChannelReader; use Composer\Package\CompletePackage; use Composer\Repository\Pear\ChannelInfo; use Composer\EventDispatcher\EventDispatcher; use Composer\Package\Link; -use Composer\Package\LinkConstraint\VersionConstraint; +use Composer\Semver\Constraint\Constraint; use Composer\Util\RemoteFilesystem; use Composer\Config; @@ -120,7 +120,7 @@ class PearRepository extends ArrayRepository // cause we've know only repository channel alias if ($channelInfo->getName() == $packageDefinition->getChannelName()) { $composerPackageAlias = $this->buildComposerPackageName($channelInfo->getAlias(), $packageDefinition->getPackageName()); - $aliasConstraint = new VersionConstraint('==', $normalizedVersion); + $aliasConstraint = new Constraint('==', $normalizedVersion); $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint); } @@ -129,7 +129,7 @@ class PearRepository extends ArrayRepository && ($this->vendorAlias != 'pear-'.$channelInfo->getAlias() || $channelInfo->getName() != $packageDefinition->getChannelName()) ) { $composerPackageAlias = "{$this->vendorAlias}/{$packageDefinition->getPackageName()}"; - $aliasConstraint = new VersionConstraint('==', $normalizedVersion); + $aliasConstraint = new Constraint('==', $normalizedVersion); $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint); } diff --git a/src/Composer/Repository/PlatformRepository.php b/src/Composer/Repository/PlatformRepository.php index d7be746a2..44a70b83b 100644 --- a/src/Composer/Repository/PlatformRepository.php +++ b/src/Composer/Repository/PlatformRepository.php @@ -15,7 +15,7 @@ namespace Composer\Repository; use Composer\Config; use Composer\Package\PackageInterface; use Composer\Package\CompletePackage; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; use Composer\Plugin\PluginInterface; /** diff --git a/src/Composer/Repository/RepositoryInterface.php b/src/Composer/Repository/RepositoryInterface.php index aaba31a9e..0b2e8132a 100644 --- a/src/Composer/Repository/RepositoryInterface.php +++ b/src/Composer/Repository/RepositoryInterface.php @@ -38,8 +38,8 @@ interface RepositoryInterface extends \Countable /** * Searches for the first match of a package by name and version. * - * @param string $name package name - * @param string|\Composer\Package\LinkConstraint\LinkConstraintInterface $constraint package version or version constraint to match against + * @param string $name package name + * @param string|\Composer\Semver\Constraint\ConstraintInterface $constraint package version or version constraint to match against * * @return PackageInterface|null */ @@ -48,8 +48,8 @@ interface RepositoryInterface extends \Countable /** * Searches for all packages matching a name and optionally a version. * - * @param string $name package name - * @param string|\Composer\Package\LinkConstraint\LinkConstraintInterface $constraint package version or version constraint to match against + * @param string $name package name + * @param string|\Composer\Semver\Constraint\ConstraintInterface $constraint package version or version constraint to match against * * @return array */ diff --git a/src/Composer/Repository/RepositoryManager.php b/src/Composer/Repository/RepositoryManager.php index 9dd88b176..336a735b6 100644 --- a/src/Composer/Repository/RepositoryManager.php +++ b/src/Composer/Repository/RepositoryManager.php @@ -43,8 +43,8 @@ class RepositoryManager /** * Searches for a package by it's name and version in managed repositories. * - * @param string $name package name - * @param string|\Composer\Package\LinkConstraint\LinkConstraintInterface $constraint package version or version constraint to match against + * @param string $name package name + * @param string|\Composer\Semver\Constraint\ConstraintInterface $constraint package version or version constraint to match against * * @return PackageInterface|null */ @@ -60,8 +60,8 @@ class RepositoryManager /** * Searches for all packages matching a name and optionally a version in managed repositories. * - * @param string $name package name - * @param string|\Composer\Package\LinkConstraint\LinkConstraintInterface $constraint package version or version constraint to match against + * @param string $name package name + * @param string|\Composer\Semver\Constraint\ConstraintInterface $constraint package version or version constraint to match against * * @return array */ diff --git a/src/Composer/Repository/VcsRepository.php b/src/Composer/Repository/VcsRepository.php index bb9d76814..b6ebd3b35 100644 --- a/src/Composer/Repository/VcsRepository.php +++ b/src/Composer/Repository/VcsRepository.php @@ -14,7 +14,7 @@ namespace Composer\Repository; use Composer\Downloader\TransportException; use Composer\Repository\Vcs\VcsDriverInterface; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Loader\ValidatingArrayLoader; use Composer\Package\Loader\InvalidPackageException; diff --git a/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php b/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php index 993cbffe8..d694813c6 100644 --- a/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php +++ b/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php @@ -18,7 +18,7 @@ use Composer\DependencyResolver\DefaultPolicy; use Composer\DependencyResolver\Pool; use Composer\Package\Link; use Composer\Package\AliasPackage; -use Composer\Package\LinkConstraint\VersionConstraint; +use Composer\Semver\Constraint\Constraint; use Composer\TestCase; class DefaultPolicyTest extends TestCase @@ -158,7 +158,7 @@ class DefaultPolicyTest extends TestCase $this->pool->addRepository($this->repoImportant); $this->pool->addRepository($this->repo); - $packages = $this->pool->whatProvides('a', new VersionConstraint('=', '2.1.9999999.9999999-dev')); + $packages = $this->pool->whatProvides('a', new Constraint('=', '2.1.9999999.9999999-dev')); $literals = array(); foreach ($packages as $package) { $literals[] = $package->getId(); @@ -176,8 +176,8 @@ class DefaultPolicyTest extends TestCase $this->repo->addPackage($packageA = $this->getPackage('A', '1.0')); $this->repo->addPackage($packageB = $this->getPackage('B', '2.0')); - $packageA->setProvides(array(new Link('A', 'X', new VersionConstraint('==', '1.0'), 'provides'))); - $packageB->setProvides(array(new Link('B', 'X', new VersionConstraint('==', '1.0'), 'provides'))); + $packageA->setProvides(array(new Link('A', 'X', new Constraint('==', '1.0'), 'provides'))); + $packageB->setProvides(array(new Link('B', 'X', new Constraint('==', '1.0'), 'provides'))); $this->pool->addRepository($this->repo); @@ -194,7 +194,7 @@ class DefaultPolicyTest extends TestCase $this->repo->addPackage($packageA = $this->getPackage('A', '1.0')); $this->repo->addPackage($packageB = $this->getPackage('B', '2.0')); - $packageB->setReplaces(array(new Link('B', 'A', new VersionConstraint('==', '1.0'), 'replaces'))); + $packageB->setReplaces(array(new Link('B', 'A', new Constraint('==', '1.0'), 'replaces'))); $this->pool->addRepository($this->repo); @@ -212,8 +212,8 @@ class DefaultPolicyTest extends TestCase $this->repo->addPackage($packageB = $this->getPackage('vendor-b/replacer', '1.0')); $this->repo->addPackage($packageA = $this->getPackage('vendor-a/replacer', '1.0')); - $packageA->setReplaces(array(new Link('vendor-a/replacer', 'vendor-a/package', new VersionConstraint('==', '1.0'), 'replaces'))); - $packageB->setReplaces(array(new Link('vendor-b/replacer', 'vendor-a/package', new VersionConstraint('==', '1.0'), 'replaces'))); + $packageA->setReplaces(array(new Link('vendor-a/replacer', 'vendor-a/package', new Constraint('==', '1.0'), 'replaces'))); + $packageB->setReplaces(array(new Link('vendor-b/replacer', 'vendor-a/package', new Constraint('==', '1.0'), 'replaces'))); $this->pool->addRepository($this->repo); diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index e50b38b93..9d4d41462 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -19,7 +19,7 @@ use Composer\DependencyResolver\Solver; use Composer\DependencyResolver\SolverProblemsException; use Composer\Package\Link; use Composer\TestCase; -use Composer\Package\LinkConstraint\MultiConstraint; +use Composer\Semver\Constraint\MultiConstraint; class SolverTest extends TestCase { diff --git a/tests/Composer/Test/Package/CompletePackageTest.php b/tests/Composer/Test/Package/CompletePackageTest.php index de119ebaa..aa3127071 100644 --- a/tests/Composer/Test/Package/CompletePackageTest.php +++ b/tests/Composer/Test/Package/CompletePackageTest.php @@ -13,7 +13,7 @@ namespace Composer\Test\Package; use Composer\Package\Package; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; use Composer\TestCase; class CompletePackageTest extends TestCase diff --git a/tests/Composer/Test/Package/Dumper/ArrayDumperTest.php b/tests/Composer/Test/Package/Dumper/ArrayDumperTest.php index c9aa2b8a0..852d667e4 100644 --- a/tests/Composer/Test/Package/Dumper/ArrayDumperTest.php +++ b/tests/Composer/Test/Package/Dumper/ArrayDumperTest.php @@ -14,7 +14,7 @@ namespace Composer\Test\Package\Dumper; use Composer\Package\Dumper\ArrayDumper; use Composer\Package\Link; -use Composer\Package\LinkConstraint\VersionConstraint; +use Composer\Semver\Constraint\Constraint; class ArrayDumperTest extends \PHPUnit_Framework_TestCase { @@ -161,13 +161,13 @@ class ArrayDumperTest extends \PHPUnit_Framework_TestCase ), array( 'require', - array(new Link('foo', 'foo/bar', new VersionConstraint('=', '1.0.0.0'), 'requires', '1.0.0')), + array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')), 'requires', array('foo/bar' => '1.0.0'), ), array( 'require-dev', - array(new Link('foo', 'foo/bar', new VersionConstraint('=', '1.0.0.0'), 'requires (for development)', '1.0.0')), + array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires (for development)', '1.0.0')), 'devRequires', array('foo/bar' => '1.0.0'), ), @@ -182,13 +182,13 @@ class ArrayDumperTest extends \PHPUnit_Framework_TestCase ), array( 'require', - array(new Link('foo', 'foo/bar', new VersionConstraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new VersionConstraint('=', '1.0.0.0'), 'requires', '1.0.0')), + array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')), 'requires', array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0') ), array( 'require-dev', - array(new Link('foo', 'foo/bar', new VersionConstraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new VersionConstraint('=', '1.0.0.0'), 'requires', '1.0.0')), + array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')), 'devRequires', array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0') ), @@ -200,19 +200,19 @@ class ArrayDumperTest extends \PHPUnit_Framework_TestCase ), array( 'provide', - array(new Link('foo', 'foo/bar', new VersionConstraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new VersionConstraint('=', '1.0.0.0'), 'requires', '1.0.0')), + array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')), 'provides', array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0') ), array( 'replace', - array(new Link('foo', 'foo/bar', new VersionConstraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new VersionConstraint('=', '1.0.0.0'), 'requires', '1.0.0')), + array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')), 'replaces', array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0') ), array( 'conflict', - array(new Link('foo', 'foo/bar', new VersionConstraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new VersionConstraint('=', '1.0.0.0'), 'requires', '1.0.0')), + array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')), 'conflicts', array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0') ), diff --git a/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php b/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php index cec33fd94..e393d3536 100644 --- a/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php +++ b/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php @@ -16,7 +16,7 @@ use Composer\Config; use Composer\Package\Loader\RootPackageLoader; use Composer\Package\BasePackage; use Composer\Package\Version\VersionGuesser; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase { diff --git a/tests/Composer/Test/Package/Version/VersionGuesserTest.php b/tests/Composer/Test/Package/Version/VersionGuesserTest.php index 6f7f7ce83..84da8d2e9 100644 --- a/tests/Composer/Test/Package/Version/VersionGuesserTest.php +++ b/tests/Composer/Test/Package/Version/VersionGuesserTest.php @@ -14,7 +14,7 @@ namespace Composer\Test\Package\Version; use Composer\Config; use Composer\Package\Version\VersionGuesser; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; class VersionGuesserTest extends \PHPUnit_Framework_TestCase { diff --git a/tests/Composer/Test/Package/Version/VersionSelectorTest.php b/tests/Composer/Test/Package/Version/VersionSelectorTest.php index 6547e7056..a48cc805d 100644 --- a/tests/Composer/Test/Package/Version/VersionSelectorTest.php +++ b/tests/Composer/Test/Package/Version/VersionSelectorTest.php @@ -13,7 +13,7 @@ namespace Composer\Test\Package\Version; use Composer\Package\Version\VersionSelector; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; class VersionSelectorTest extends \PHPUnit_Framework_TestCase { diff --git a/tests/Composer/Test/Repository/ComposerRepositoryTest.php b/tests/Composer/Test/Repository/ComposerRepositoryTest.php index 6f21f9d9c..06fa58b6a 100644 --- a/tests/Composer/Test/Repository/ComposerRepositoryTest.php +++ b/tests/Composer/Test/Repository/ComposerRepositoryTest.php @@ -16,7 +16,7 @@ use Composer\IO\NullIO; use Composer\Test\Mock\FactoryMock; use Composer\TestCase; use Composer\Package\Loader\ArrayLoader; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; class ComposerRepositoryTest extends TestCase { diff --git a/tests/Composer/Test/Repository/PathRepositoryTest.php b/tests/Composer/Test/Repository/PathRepositoryTest.php index 1a5392c28..9dd7c1249 100644 --- a/tests/Composer/Test/Repository/PathRepositoryTest.php +++ b/tests/Composer/Test/Repository/PathRepositoryTest.php @@ -13,7 +13,7 @@ namespace Composer\Repository; use Composer\Package\Loader\ArrayLoader; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; use Composer\TestCase; use Composer\IO\NullIO; use Composer\Config; diff --git a/tests/Composer/Test/Repository/Pear/ChannelReaderTest.php b/tests/Composer/Test/Repository/Pear/ChannelReaderTest.php index c22250a04..1d9d39767 100644 --- a/tests/Composer/Test/Repository/Pear/ChannelReaderTest.php +++ b/tests/Composer/Test/Repository/Pear/ChannelReaderTest.php @@ -13,8 +13,8 @@ namespace Composer\Repository\Pear; use Composer\TestCase; -use Composer\Package\Version\VersionParser; -use Composer\Package\LinkConstraint\VersionConstraint; +use Composer\Semver\VersionParser; +use Composer\Semver\Constraint\Constraint; use Composer\Package\Link; use Composer\Package\CompletePackage; use Composer\Test\Mock\RemoteFilesystemMock; @@ -135,7 +135,7 @@ class ChannelReaderTest extends TestCase '*-ext-xml' => '*', )); $expectedPackage->setReplaces(array( - new Link('pear-test.loc/sample', 'pear-test/sample', new VersionConstraint('==', '1.0.0.1'), 'replaces', '== 1.0.0.1'), + new Link('pear-test.loc/sample', 'pear-test/sample', new Constraint('==', '1.0.0.1'), 'replaces', '== 1.0.0.1'), )); $this->assertCount(1, $packages); @@ -144,7 +144,7 @@ class ChannelReaderTest extends TestCase private function createConstraint($operator, $version) { - $constraint = new VersionConstraint($operator, $version); + $constraint = new Constraint($operator, $version); $constraint->setPrettyString($operator.' '.$version); return $constraint; diff --git a/tests/Composer/TestCase.php b/tests/Composer/TestCase.php index 4abf1a7ff..2057c09b8 100644 --- a/tests/Composer/TestCase.php +++ b/tests/Composer/TestCase.php @@ -12,9 +12,9 @@ namespace Composer; -use Composer\Package\Version\VersionParser; +use Composer\Semver\VersionParser; use Composer\Package\AliasPackage; -use Composer\Package\LinkConstraint\VersionConstraint; +use Composer\Semver\Constraint\Constraint; use Composer\Util\Filesystem; abstract class TestCase extends \PHPUnit_Framework_TestCase @@ -32,7 +32,7 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase protected function getVersionConstraint($operator, $version) { - $constraint = new VersionConstraint( + $constraint = new Constraint( $operator, self::getVersionParser()->normalize($version) ); From ddb1c1e05251d8fc2ae5d3eeb1d112c85690c857 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Thu, 24 Sep 2015 16:34:48 +0200 Subject: [PATCH 192/205] these 2 use parseNameVersionPairs --- src/Composer/Command/CreateProjectCommand.php | 2 +- src/Composer/Command/InitCommand.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index 4c93561eb..54cd63538 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -36,7 +36,7 @@ use Composer\Json\JsonFile; use Composer\Config\JsonConfigSource; use Composer\Util\Filesystem; use Composer\Util\RemoteFilesystem; -use Composer\Semver\VersionParser; +use Composer\Package\Version\VersionParser; /** * Install a package as new project into new directory. diff --git a/src/Composer/Command/InitCommand.php b/src/Composer/Command/InitCommand.php index fe5e1bda0..9e60d621c 100644 --- a/src/Composer/Command/InitCommand.php +++ b/src/Composer/Command/InitCommand.php @@ -16,10 +16,10 @@ use Composer\DependencyResolver\Pool; use Composer\Json\JsonFile; use Composer\Factory; use Composer\Package\BasePackage; +use Composer\Package\Version\VersionParser; use Composer\Package\Version\VersionSelector; use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; -use Composer\Semver\VersionParser; use Composer\Util\ProcessExecutor; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; From 3a289ed5c3ec4eb6f4e78f96a45eea41213f85f3 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Thu, 24 Sep 2015 16:35:54 +0200 Subject: [PATCH 193/205] regenerate lock with latest composer --- composer.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.lock b/composer.lock index 25dc03c27..8edea7f7d 100644 --- a/composer.lock +++ b/composer.lock @@ -5,6 +5,7 @@ "This file is @generated automatically" ], "hash": "af3956ae4c1a09e3e72cd66346a6176d", + "content-hash": "96817117d0ca449e7deff55c98eb7bdc", "packages": [ { "name": "composer/semver", From a1ad7fc435ec13fe5cf23e9e2a8199984fef5e38 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Thu, 24 Sep 2015 16:48:46 +0200 Subject: [PATCH 194/205] fix classname clashing cause of existing class in current namespace --- src/Composer/Package/Version/VersionGuesser.php | 6 +++--- src/Composer/Package/Version/VersionSelector.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Composer/Package/Version/VersionGuesser.php b/src/Composer/Package/Version/VersionGuesser.php index 6f71dbe7d..6cb3e678f 100644 --- a/src/Composer/Package/Version/VersionGuesser.php +++ b/src/Composer/Package/Version/VersionGuesser.php @@ -15,7 +15,7 @@ namespace Composer\Package\Version; use Composer\Config; use Composer\Repository\Vcs\HgDriver; use Composer\IO\NullIO; -use Composer\Semver\VersionParser; +use Composer\Semver\VersionParser as BaseVersionParser; use Composer\Util\Git as GitUtil; use Composer\Util\ProcessExecutor; use Composer\Util\Svn as SvnUtil; @@ -39,7 +39,7 @@ class VersionGuesser private $process; /** - * @var VersionParser + * @var BaseVersionParser */ private $versionParser; @@ -48,7 +48,7 @@ class VersionGuesser * @param ProcessExecutor $process * @param VersionParser $versionParser */ - public function __construct(Config $config, ProcessExecutor $process, VersionParser $versionParser) + public function __construct(Config $config, ProcessExecutor $process, BaseVersionParser $versionParser) { $this->config = $config; $this->process = $process; diff --git a/src/Composer/Package/Version/VersionSelector.php b/src/Composer/Package/Version/VersionSelector.php index 04b4cd28d..3874f2118 100644 --- a/src/Composer/Package/Version/VersionSelector.php +++ b/src/Composer/Package/Version/VersionSelector.php @@ -16,7 +16,7 @@ use Composer\DependencyResolver\Pool; use Composer\Package\PackageInterface; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Dumper\ArrayDumper; -use Composer\Semver\VersionParser; +use Composer\Semver\VersionParser as BaseVersionParser; /** * Selects the best possible version for a package @@ -131,7 +131,7 @@ class VersionSelector private function getParser() { if ($this->parser === null) { - $this->parser = new VersionParser(); + $this->parser = new BaseVersionParser(); } return $this->parser; From 0adcab7a19c42fbbc6ce2cdc3f3892f442e06941 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Thu, 24 Sep 2015 16:49:10 +0200 Subject: [PATCH 195/205] compile phar with semver included --- src/Composer/Compiler.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Composer/Compiler.php b/src/Composer/Compiler.php index b0448502c..9e2d2310e 100644 --- a/src/Composer/Compiler.php +++ b/src/Composer/Compiler.php @@ -119,6 +119,7 @@ class Compiler ->in(__DIR__.'/../../vendor/seld/cli-prompt/') ->in(__DIR__.'/../../vendor/justinrainbow/json-schema/') ->in(__DIR__.'/../../vendor/composer/spdx-licenses/') + ->in(__DIR__.'/../../vendor/composer/semver/') ->sort($finderSort) ; From 89717fa5934f9f19da4824346ceba960c7677098 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Fri, 25 Sep 2015 10:59:56 +0200 Subject: [PATCH 196/205] implement old linkconstraintinterface for BC --- src/Composer/Package/LinkConstraint/EmptyConstraint.php | 4 ++-- src/Composer/Package/LinkConstraint/MultiConstraint.php | 4 ++-- src/Composer/Package/LinkConstraint/SpecificConstraint.php | 2 +- src/Composer/Package/LinkConstraint/VersionConstraint.php | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Composer/Package/LinkConstraint/EmptyConstraint.php b/src/Composer/Package/LinkConstraint/EmptyConstraint.php index 43cc65163..09eb15ada 100644 --- a/src/Composer/Package/LinkConstraint/EmptyConstraint.php +++ b/src/Composer/Package/LinkConstraint/EmptyConstraint.php @@ -12,13 +12,13 @@ namespace Composer\Package\LinkConstraint; -use Composer\Semver\Constraint\EmptyConstraint as BaseEmptyConstraint; +use Composer\Semver\Constraint\EmptyConstraint as SemverEmptyConstraint; @trigger_error('The ' . __NAMESPACE__ . '\EmptyConstraint class is deprecated, use Composer\Semver\Constraint\EmptyConstraint instead.', E_USER_DEPRECATED); /** * @deprecated use Composer\Semver\Constraint\EmptyConstraint instead */ -class EmptyConstraint extends BaseEmptyConstraint +class EmptyConstraint extends SemverEmptyConstraint implements LinkConstraintInterface { } diff --git a/src/Composer/Package/LinkConstraint/MultiConstraint.php b/src/Composer/Package/LinkConstraint/MultiConstraint.php index 296076b18..6e091a430 100644 --- a/src/Composer/Package/LinkConstraint/MultiConstraint.php +++ b/src/Composer/Package/LinkConstraint/MultiConstraint.php @@ -12,13 +12,13 @@ namespace Composer\Package\LinkConstraint; -use Composer\Semver\Constraint\MultiConstraint as BaseMultiConstraint; +use Composer\Semver\Constraint\MultiConstraint as SemverMultiConstraint; @trigger_error('The ' . __NAMESPACE__ . '\MultiConstraint class is deprecated, use Composer\Semver\Constraint\MultiConstraint instead.', E_USER_DEPRECATED); /** * @deprecated use Composer\Semver\Constraint\MultiConstraint instead */ -class MultiConstraint extends BaseMultiConstraint +class MultiConstraint extends SemverMultiConstraint implements LinkConstraintInterface { } diff --git a/src/Composer/Package/LinkConstraint/SpecificConstraint.php b/src/Composer/Package/LinkConstraint/SpecificConstraint.php index 409f0a440..880873887 100644 --- a/src/Composer/Package/LinkConstraint/SpecificConstraint.php +++ b/src/Composer/Package/LinkConstraint/SpecificConstraint.php @@ -19,6 +19,6 @@ use Composer\Semver\Constraint\AbstractConstraint; /** * @deprecated use Composer\Semver\Constraint\AbstractConstraint instead */ -abstract class SpecificConstraint extends AbstractConstraint +abstract class SpecificConstraint extends AbstractConstraint implements LinkConstraintInterface { } diff --git a/src/Composer/Package/LinkConstraint/VersionConstraint.php b/src/Composer/Package/LinkConstraint/VersionConstraint.php index 45d471254..580016795 100644 --- a/src/Composer/Package/LinkConstraint/VersionConstraint.php +++ b/src/Composer/Package/LinkConstraint/VersionConstraint.php @@ -19,6 +19,6 @@ use Composer\Semver\Constraint\Constraint; /** * @deprecated use Composer\Semver\Constraint\Constraint instead */ -class VersionConstraint extends Constraint +class VersionConstraint extends Constraint implements LinkConstraintInterface { } From 1328d9c3b2fbe2d71079c5009b2d5204ce956c2e Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Fri, 25 Sep 2015 11:05:19 +0200 Subject: [PATCH 197/205] rename baseversionparser to semverversionparser and fix docblock as per @stof request --- src/Composer/Package/Version/VersionGuesser.php | 6 +++--- src/Composer/Package/Version/VersionParser.php | 13 +++++++++---- src/Composer/Package/Version/VersionSelector.php | 4 ++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Composer/Package/Version/VersionGuesser.php b/src/Composer/Package/Version/VersionGuesser.php index 6cb3e678f..6b9b020d4 100644 --- a/src/Composer/Package/Version/VersionGuesser.php +++ b/src/Composer/Package/Version/VersionGuesser.php @@ -15,7 +15,7 @@ namespace Composer\Package\Version; use Composer\Config; use Composer\Repository\Vcs\HgDriver; use Composer\IO\NullIO; -use Composer\Semver\VersionParser as BaseVersionParser; +use Composer\Semver\VersionParser as SemverVersionParser; use Composer\Util\Git as GitUtil; use Composer\Util\ProcessExecutor; use Composer\Util\Svn as SvnUtil; @@ -39,7 +39,7 @@ class VersionGuesser private $process; /** - * @var BaseVersionParser + * @var SemverVersionParser */ private $versionParser; @@ -48,7 +48,7 @@ class VersionGuesser * @param ProcessExecutor $process * @param VersionParser $versionParser */ - public function __construct(Config $config, ProcessExecutor $process, BaseVersionParser $versionParser) + public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser) { $this->config = $config; $this->process = $process; diff --git a/src/Composer/Package/Version/VersionParser.php b/src/Composer/Package/Version/VersionParser.php index 4c29599c8..00d1e669a 100644 --- a/src/Composer/Package/Version/VersionParser.php +++ b/src/Composer/Package/Version/VersionParser.php @@ -12,14 +12,19 @@ namespace Composer\Package\Version; -use Composer\Semver\VersionParser as BaseVersionParser; +use Composer\Semver\VersionParser as SemverVersionParser; -class VersionParser extends BaseVersionParser +class VersionParser extends SemverVersionParser { /** - * @param array $pairs + * Parses an array of strings representing package/version pairs. * - * @return array[] + * The parsing results in an array of arrays, each of which + * contain a 'name' key with value and optionally a 'version' key with value. + * + * @param array $pairs a set of package/version pairs separated by ":", "=" or " " + * + * @return array[] array of arrays containing a name and (if provided) a version */ public function parseNameVersionPairs(array $pairs) { diff --git a/src/Composer/Package/Version/VersionSelector.php b/src/Composer/Package/Version/VersionSelector.php index 3874f2118..a22cf2c70 100644 --- a/src/Composer/Package/Version/VersionSelector.php +++ b/src/Composer/Package/Version/VersionSelector.php @@ -16,7 +16,7 @@ use Composer\DependencyResolver\Pool; use Composer\Package\PackageInterface; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Dumper\ArrayDumper; -use Composer\Semver\VersionParser as BaseVersionParser; +use Composer\Semver\VersionParser as SemverVersionParser; /** * Selects the best possible version for a package @@ -131,7 +131,7 @@ class VersionSelector private function getParser() { if ($this->parser === null) { - $this->parser = new BaseVersionParser(); + $this->parser = new SemverVersionParser(); } return $this->parser; From e491b72a8c96e0595ca389b098132fa5272b141e Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Mon, 28 Sep 2015 10:38:16 +0200 Subject: [PATCH 198/205] only urlencode $ if filename is not local --- src/Composer/Repository/ComposerRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index f3b0642d0..5abe328ae 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -585,7 +585,7 @@ class ComposerRepository extends ArrayRepository } // url-encode $ signs in URLs as bad proxies choke on them - if ($pos = strpos($filename, '$')) { + if ($pos = strpos($filename, '$') && preg_match('{^https?://.*}i', $filename)) { $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos+1); } From b219abe8f634675ea62722ec2b2dcb525059f3ac Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Mon, 28 Sep 2015 10:59:26 +0200 Subject: [PATCH 199/205] @seldaek damn your assignment in expression --- src/Composer/Repository/ComposerRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 5abe328ae..2fce1e336 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -585,7 +585,7 @@ class ComposerRepository extends ArrayRepository } // url-encode $ signs in URLs as bad proxies choke on them - if ($pos = strpos($filename, '$') && preg_match('{^https?://.*}i', $filename)) { + if (($pos = strpos($filename, '$')) && preg_match('{^https?://.*}i', $filename)) { $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos+1); } From 96a8bc6c5bdfcdada2ff3786846b7ebda7aba060 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 28 Sep 2015 10:34:24 +0100 Subject: [PATCH 200/205] Update fixer config for latest master --- .php_cs | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/.php_cs b/.php_cs index ba9d1251a..0c6b9ead7 100644 --- a/.php_cs +++ b/.php_cs @@ -10,9 +10,32 @@ $finder = Symfony\CS\Finder\DefaultFinder::create() return Symfony\CS\Config\Config::create() ->setUsingCache(true) - ->level(Symfony\CS\FixerInterface::NONE_LEVEL) - ->fixers(array( - 'psr0', 'encoding', 'short_tag', 'braces', 'elseif', 'eof_ending', 'function_declaration', 'indentation', 'line_after_namespace', 'linefeed', 'lowercase_constants', 'lowercase_keywords', 'multiple_use', 'php_closing_tag', 'trailing_spaces', 'visibility', 'duplicate_semicolon', 'extra_empty_lines', 'include', 'namespace_no_leading_whitespace', 'object_operator', 'operators_spaces', 'phpdoc_params', 'return', 'single_array_no_trailing_comma', 'spaces_cast', 'standardize_not_equal', 'ternary_spaces', 'unused_use', 'whitespacy_lines', 'multiline_array_tailing_comma', + ->setRiskyAllowed(true) + ->setRules(array( + '@PSR2' => true, + 'duplicate_semicolon' => true, + 'extra_empty_lines' => true, + 'include' => true, + 'multiline_array_trailing_comma' => true, + 'namespace_no_leading_whitespace' => true, + 'object_operator' => true, + 'operators_spaces' => true, + 'phpdoc_align' => true, + 'phpdoc_indent' => true, + 'phpdoc_no_access' => true, + 'phpdoc_no_package' => true, + 'phpdoc_order' => true, + 'phpdoc_scalar' => true, + 'phpdoc_trim' => true, + 'phpdoc_type_to_var' => true, + 'psr0' => true, + 'return' => true, + 'single_array_no_trailing_comma' => true, + 'spaces_cast' => true, + 'standardize_not_equal' => true, + 'ternary_spaces' => true, + 'unused_use' => true, + 'whitespacy_lines' => true, )) ->finder($finder) ; From ce085826711a6354024203c6530ee0b56fea9c13 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 28 Sep 2015 10:51:14 +0100 Subject: [PATCH 201/205] Fix CS --- src/Composer/Autoload/AutoloadGenerator.php | 4 +- src/Composer/Autoload/ClassMapGenerator.php | 3 +- src/Composer/Command/ArchiveCommand.php | 1 - src/Composer/Command/ConfigCommand.php | 12 +-- src/Composer/Command/CreateProjectCommand.php | 4 +- src/Composer/Command/DiagnoseCommand.php | 8 +- src/Composer/Command/InitCommand.php | 10 +-- src/Composer/Command/ShowCommand.php | 2 +- src/Composer/Command/ValidateCommand.php | 2 +- src/Composer/Compiler.php | 2 +- src/Composer/Config.php | 8 +- src/Composer/Console/Application.php | 2 +- src/Composer/Console/HtmlOutputFormatter.php | 4 +- src/Composer/DependencyResolver/Pool.php | 10 +-- src/Composer/DependencyResolver/Request.php | 2 +- src/Composer/DependencyResolver/Rule.php | 1 + .../DependencyResolver/RuleWatchNode.php | 2 +- src/Composer/DependencyResolver/Solver.php | 2 +- src/Composer/Downloader/DownloadManager.php | 12 ++- src/Composer/Downloader/FileDownloader.php | 9 +-- src/Composer/Downloader/GitDownloader.php | 11 ++- .../Downloader/PearPackageExtractor.php | 3 +- .../Downloader/PerforceDownloader.php | 2 +- src/Composer/Downloader/SvnDownloader.php | 2 +- src/Composer/EventDispatcher/Event.php | 4 +- .../EventDispatcher/EventDispatcher.php | 18 ++--- src/Composer/Factory.php | 2 +- src/Composer/IO/BufferIO.php | 4 +- src/Composer/IO/ConsoleIO.php | 10 +-- src/Composer/IO/IOInterface.php | 14 ++-- src/Composer/Installer.php | 79 +++++++++---------- .../Installer/InstallationManager.php | 7 +- src/Composer/Json/JsonFile.php | 6 +- src/Composer/Json/JsonFormatter.php | 1 - src/Composer/Package/AliasPackage.php | 2 +- .../Package/Archiver/ArchiverInterface.php | 2 +- .../Package/Archiver/HgExcludeFilter.php | 2 +- src/Composer/Package/BasePackage.php | 2 +- src/Composer/Package/CompletePackage.php | 4 +- .../Package/CompletePackageInterface.php | 2 +- src/Composer/Package/Link.php | 2 +- src/Composer/Package/Locker.php | 3 +- src/Composer/Package/PackageInterface.php | 2 +- .../Package/Version/VersionGuesser.php | 2 +- src/Composer/Plugin/PluginManager.php | 6 +- .../Repository/ArtifactRepository.php | 4 +- .../Repository/ComposerRepository.php | 2 +- src/Composer/Repository/PathRepository.php | 9 +-- src/Composer/Repository/RepositoryManager.php | 2 +- .../Repository/Vcs/PerforceDriver.php | 2 +- .../Repository/Vcs/VcsDriverInterface.php | 5 +- src/Composer/Script/Event.php | 6 +- src/Composer/Util/ConfigValidator.php | 4 +- src/Composer/Util/Filesystem.php | 15 ++-- src/Composer/Util/Git.php | 6 +- src/Composer/Util/NoProxyPattern.php | 2 +- src/Composer/Util/Perforce.php | 4 +- src/Composer/Util/RemoteFilesystem.php | 46 +++++------ src/Composer/Util/StreamContextFactory.php | 2 +- src/Composer/Util/Svn.php | 13 ++- .../Test/Autoload/AutoloadGeneratorTest.php | 6 +- tests/Composer/Test/ConfigTest.php | 18 ++--- .../Test/DependencyResolver/SolverTest.php | 8 +- .../Downloader/PearPackageExtractorTest.php | 14 ++-- .../EventDispatcher/EventDispatcherTest.php | 6 +- tests/Composer/Test/InstallerTest.php | 4 +- .../Composer/Test/Json/ComposerSchemaTest.php | 4 +- .../Test/Json/JsonManipulatorTest.php | 56 ++++++------- .../Test/Json/JsonValidationExceptionTest.php | 2 +- .../Archiver/ArchivableFilesFinderTest.php | 3 +- .../Composer/Test/Package/BasePackageTest.php | 8 +- .../Test/Package/Dumper/ArrayDumperTest.php | 42 +++++----- .../Test/Package/Loader/ArrayLoaderTest.php | 7 +- .../Package/Loader/RootPackageLoaderTest.php | 4 +- .../Loader/ValidatingArrayLoaderTest.php | 50 ++++++------ tests/Composer/Test/Package/LockerTest.php | 8 +- .../Test/Plugin/PluginInstallerTest.php | 2 +- .../Repository/ComposerRepositoryTest.php | 8 +- .../Repository/FilesystemRepositoryTest.php | 4 +- .../Test/Repository/PathRepositoryTest.php | 3 - .../Repository/Pear/ChannelReaderTest.php | 8 +- .../Test/Repository/PearRepositoryTest.php | 16 ++-- tests/Composer/Test/Util/GitHubTest.php | 4 +- tests/Composer/Test/Util/PerforceTest.php | 18 ++--- .../Test/Util/StreamContextFactoryTest.php | 22 +++--- tests/Composer/Test/Util/SvnTest.php | 18 ++--- 86 files changed, 366 insertions(+), 391 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 4784aae12..0c32dc750 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -277,13 +277,13 @@ EOF; $includePathFilePath = $targetDir.'/include_paths.php'; if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) { file_put_contents($includePathFilePath, $includePathFileContents); - } else if (file_exists($includePathFilePath)){ + } elseif (file_exists($includePathFilePath)) { unlink($includePathFilePath); } $includeFilesFilePath = $targetDir.'/autoload_files.php'; if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) { file_put_contents($includeFilesFilePath, $includeFilesFileContents); - } else if (file_exists($includeFilesFilePath)) { + } elseif (file_exists($includeFilesFilePath)) { unlink($includeFilesFilePath); } file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix)); diff --git a/src/Composer/Autoload/ClassMapGenerator.php b/src/Composer/Autoload/ClassMapGenerator.php index e6ff636da..5484b7d41 100644 --- a/src/Composer/Autoload/ClassMapGenerator.php +++ b/src/Composer/Autoload/ClassMapGenerator.php @@ -49,9 +49,8 @@ class ClassMapGenerator * @param IOInterface $io IO object * @param string $namespace Optional namespace prefix to filter by * - * @return array A class map array - * * @throws \RuntimeException When the path is neither an existing file nor directory + * @return array A class map array */ public static function createMap($path, $whitelist = null, IOInterface $io = null, $namespace = null) { diff --git a/src/Composer/Command/ArchiveCommand.php b/src/Composer/Command/ArchiveCommand.php index 8114435b2..b8c439678 100644 --- a/src/Composer/Command/ArchiveCommand.php +++ b/src/Composer/Command/ArchiveCommand.php @@ -20,7 +20,6 @@ use Composer\Script\ScriptEvents; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Util\Filesystem; - use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; diff --git a/src/Composer/Command/ConfigCommand.php b/src/Composer/Command/ConfigCommand.php index 2b7fd4846..9620bec14 100644 --- a/src/Composer/Command/ConfigCommand.php +++ b/src/Composer/Command/ConfigCommand.php @@ -278,7 +278,7 @@ EOT 'use-include-path' => array($booleanValidator, $booleanNormalizer), 'preferred-install' => array( function ($val) { return in_array($val, array('auto', 'source', 'dist'), true); }, - function ($val) { return $val; } + function ($val) { return $val; }, ), 'store-auths' => array( function ($val) { return in_array($val, array('true', 'false', 'prompt'), true); }, @@ -288,7 +288,7 @@ EOT } return $val !== 'false' && (bool) $val; - } + }, ), 'notify-on-install' => array($booleanValidator, $booleanNormalizer), 'vendor-dir' => array('is_string', function ($val) { return $val; }), @@ -301,7 +301,7 @@ EOT 'cache-files-ttl' => array('is_numeric', 'intval'), 'cache-files-maxsize' => array( function ($val) { return preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val) > 0; }, - function ($val) { return $val; } + function ($val) { return $val; }, ), 'discard-changes' => array( function ($val) { return in_array($val, array('stash', 'true', 'false', '1', '0'), true); }, @@ -311,7 +311,7 @@ EOT } return $val !== 'false' && (bool) $val; - } + }, ), 'autoloader-suffix' => array('is_string', function ($val) { return $val === 'null' ? null : $val; }), 'optimize-autoloader' => array($booleanValidator, $booleanNormalizer), @@ -336,7 +336,7 @@ EOT }, function ($vals) { return $vals; - } + }, ), 'github-domains' => array( function ($vals) { @@ -348,7 +348,7 @@ EOT }, function ($vals) { return $vals; - } + }, ), ); diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index 54cd63538..2cae1414a 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -347,8 +347,8 @@ EOT * Updated preferSource or preferDist based on the preferredInstall config option * @param Config $config * @param InputInterface $input - * @param boolean $preferSource - * @param boolean $preferDist + * @param bool $preferSource + * @param bool $preferDist */ protected function updatePreferredOptions(Config $config, InputInterface $input, &$preferSource, &$preferDist, $keepVcsRequiresPreferSource = false) { diff --git a/src/Composer/Command/DiagnoseCommand.php b/src/Composer/Command/DiagnoseCommand.php index 30d38b0c1..afca401b6 100644 --- a/src/Composer/Command/DiagnoseCommand.php +++ b/src/Composer/Command/DiagnoseCommand.php @@ -264,7 +264,7 @@ EOT $url = $domain === 'github.com' ? 'https://api.'.$domain.'/user/repos' : 'https://'.$domain.'/api/v3/user/repos'; return $this->rfs->getContents($domain, $url, false, array( - 'retry-auth-failure' => false + 'retry-auth-failure' => false, )) ? true : 'Unexpected error'; } catch (\Exception $e) { if ($e instanceof TransportException && $e->getCode() === 401) { @@ -276,10 +276,10 @@ EOT } /** - * @param string $domain - * @param string $token - * @return array + * @param string $domain + * @param string $token * @throws TransportException + * @return array */ private function getGithubRateLimit($domain, $token = null) { diff --git a/src/Composer/Command/InitCommand.php b/src/Composer/Command/InitCommand.php index 9e60d621c..795d72958 100644 --- a/src/Composer/Command/InitCommand.php +++ b/src/Composer/Command/InitCommand.php @@ -148,7 +148,7 @@ EOT $io->writeError(array( '', $formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', true), - '' + '', )); // namespace @@ -284,7 +284,7 @@ EOT /** * @private - * @param string $author + * @param string $author * @return array */ public function parseAuthorString($author) @@ -293,7 +293,7 @@ EOT if ($this->isValidEmail($match['email'])) { return array( 'name' => trim($match['name']), - 'email' => $match['email'] + 'email' => $match['email'], ); } } @@ -368,7 +368,7 @@ EOT $io->writeError(array( '', sprintf('Found %s packages matching %s', count($matches), $package), - '' + '', )); $io->writeError($choices); @@ -591,8 +591,8 @@ EOT * * @param InputInterface $input * @param string $name - * @return string * @throws \InvalidArgumentException + * @return string */ private function findBestVersionForPackage(InputInterface $input, $name) { diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index 81bc93b3f..8aa6de5ca 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -245,8 +245,8 @@ EOT * @param RepositoryInterface $repos * @param string $name * @param string $version - * @return array array(CompletePackageInterface, array of versions) * @throws \InvalidArgumentException + * @return array array(CompletePackageInterface, array of versions) */ protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null) { diff --git a/src/Composer/Command/ValidateCommand.php b/src/Composer/Command/ValidateCommand.php index 54177576e..66902cbb2 100644 --- a/src/Composer/Command/ValidateCommand.php +++ b/src/Composer/Command/ValidateCommand.php @@ -42,7 +42,7 @@ class ValidateCommand extends Command new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'), new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'), new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'), - new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file', './composer.json') + new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file', './composer.json'), )) ->setHelp(<< 'composer', 'url' => 'https?://packagist.org', 'allow_ssl_downgrade' => true, - ) + ), ); private $config; @@ -68,7 +68,7 @@ class Config private $useEnvironment; /** - * @param boolean $useEnvironment Use COMPOSER_ environment variables to replace config settings + * @param bool $useEnvironment Use COMPOSER_ environment variables to replace config settings */ public function __construct($useEnvironment = true, $baseDir = null) { @@ -331,8 +331,8 @@ class Config * This should be used to read COMPOSER_ environment variables * that overload config values. * - * @param string $var - * @return string|boolean + * @param string $var + * @return string|bool */ private function getComposerEnv($var) { diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index 84e03f754..21bc22937 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -159,8 +159,8 @@ class Application extends BaseApplication /** * @param InputInterface $input - * @return string * @throws \RuntimeException + * @return string */ private function getNewWorkingDir(InputInterface $input) { diff --git a/src/Composer/Console/HtmlOutputFormatter.php b/src/Composer/Console/HtmlOutputFormatter.php index f5368b5fe..994fcbcd5 100644 --- a/src/Composer/Console/HtmlOutputFormatter.php +++ b/src/Composer/Console/HtmlOutputFormatter.php @@ -27,7 +27,7 @@ class HtmlOutputFormatter extends OutputFormatter 34 => 'blue', 35 => 'magenta', 36 => 'cyan', - 37 => 'white' + 37 => 'white', ); private static $availableBackgroundColors = array( 40 => 'black', @@ -37,7 +37,7 @@ class HtmlOutputFormatter extends OutputFormatter 44 => 'blue', 45 => 'magenta', 46 => 'cyan', - 47 => 'white' + 47 => 'white', ); private static $availableOptions = array( 1 => 'bold', diff --git a/src/Composer/DependencyResolver/Pool.php b/src/Composer/DependencyResolver/Pool.php index d5eac138e..96e46c531 100644 --- a/src/Composer/DependencyResolver/Pool.php +++ b/src/Composer/DependencyResolver/Pool.php @@ -150,11 +150,11 @@ class Pool implements \Countable } /** - * Retrieves the package object for a given package id. - * - * @param int $id - * @return PackageInterface - */ + * Retrieves the package object for a given package id. + * + * @param int $id + * @return PackageInterface + */ public function packageById($id) { return $this->packages[$id - 1]; diff --git a/src/Composer/DependencyResolver/Request.php b/src/Composer/DependencyResolver/Request.php index 10ffcb2c4..7eacdf1f6 100644 --- a/src/Composer/DependencyResolver/Request.php +++ b/src/Composer/DependencyResolver/Request.php @@ -59,7 +59,7 @@ class Request 'cmd' => $cmd, 'packageName' => $packageName, 'constraint' => $constraint, - 'fixed' => $fixed + 'fixed' => $fixed, ); } diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index 916addead..03de5ab84 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -62,6 +62,7 @@ class Rule public function getHash() { $data = unpack('ihash', md5(implode(',', $this->literals), true)); + return $data['hash']; } diff --git a/src/Composer/DependencyResolver/RuleWatchNode.php b/src/Composer/DependencyResolver/RuleWatchNode.php index 5cfd7d1e0..907cb4cc0 100644 --- a/src/Composer/DependencyResolver/RuleWatchNode.php +++ b/src/Composer/DependencyResolver/RuleWatchNode.php @@ -83,7 +83,7 @@ class RuleWatchNode /** * Given one watched literal, this method returns the other watched literal * - * @param int $literal The watched literal that should not be returned + * @param int $literal The watched literal that should not be returned * @return int A literal */ public function getOtherWatch($literal) diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index f8f316269..0568a4d2c 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -217,7 +217,7 @@ class Solver * Evaluates each term affected by the decision (linked through watches) * If we find unit rules we make new decisions based on them * - * @param integer $level + * @param int $level * @return Rule|null A rule on conflict, otherwise null. */ protected function propagate($level) diff --git a/src/Composer/Downloader/DownloadManager.php b/src/Composer/Downloader/DownloadManager.php index 5c0980725..4d2e9c8f4 100644 --- a/src/Composer/Downloader/DownloadManager.php +++ b/src/Composer/Downloader/DownloadManager.php @@ -103,10 +103,9 @@ class DownloadManager /** * Returns downloader for a specific installation type. * - * @param string $type installation type - * @return DownloaderInterface - * + * @param string $type installation type * @throws \InvalidArgumentException if downloader for provided type is not registered + * @return DownloaderInterface */ public function getDownloader($type) { @@ -121,12 +120,11 @@ class DownloadManager /** * Returns downloader for already installed package. * - * @param PackageInterface $package package instance - * @return DownloaderInterface|null - * + * @param PackageInterface $package package instance * @throws \InvalidArgumentException if package has no installation source specified * @throws \LogicException if specific downloader used to load package with - * wrong type + * wrong type + * @return DownloaderInterface|null */ public function getDownloaderForInstalledPackage(PackageInterface $package) { diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index 0a2c3a6e5..77a08cbf4 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -137,7 +137,7 @@ class FileDownloader implements DownloaderInterface break; } catch (TransportException $e) { // if we got an http response with a proper code, then requesting again will probably not help, abort - if ((0 !== $e->getCode() && !in_array($e->getCode(),array(500, 502, 503, 504))) || !$retries) { + if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) { throw $e; } if ($this->io->isVerbose()) { @@ -225,11 +225,10 @@ class FileDownloader implements DownloaderInterface /** * Process the download url * - * @param PackageInterface $package package the url is coming from - * @param string $url download url - * @return string url - * + * @param PackageInterface $package package the url is coming from + * @param string $url download url * @throws \RuntimeException If any problem with the url + * @return string url */ protected function processUrl(PackageInterface $package, $url) { diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index 82552c009..60a896256 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -209,13 +209,12 @@ class GitDownloader extends VcsDownloader /** * Updates the given path to the given commit ref * - * @param string $path - * @param string $reference - * @param string $branch - * @param \DateTime $date - * @return null|string if a string is returned, it is the commit reference that was checked out if the original could not be found - * + * @param string $path + * @param string $reference + * @param string $branch + * @param \DateTime $date * @throws \RuntimeException + * @return null|string if a string is returned, it is the commit reference that was checked out if the original could not be found */ protected function updateToCommit($path, $reference, $branch, $date) { diff --git a/src/Composer/Downloader/PearPackageExtractor.php b/src/Composer/Downloader/PearPackageExtractor.php index 1106d927f..44267d558 100644 --- a/src/Composer/Downloader/PearPackageExtractor.php +++ b/src/Composer/Downloader/PearPackageExtractor.php @@ -48,7 +48,6 @@ class PearPackageExtractor * @param array $vars used for replacement tasks * @throws \RuntimeException * @throws \UnexpectedValueException - * */ public function extractTo($target, array $roles = array('php' => '/', 'script' => '/bin'), $vars = array()) { @@ -130,9 +129,9 @@ class PearPackageExtractor * @param string $source string path to extracted files * @param array $roles array [role => roleRoot] relative root for files having that role * @param array $vars list of values can be used for replacement tasks + * @throws \RuntimeException * @return array array of 'source' => 'target', where source is location of file in the tarball (relative to source * path, and target is destination of file (also relative to $source path) - * @throws \RuntimeException */ private function buildCopyActions($source, array $roles, $vars) { diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index ae2769999..d99fc7997 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -43,7 +43,7 @@ class PerforceDownloader extends VcsDownloader private function getLabelFromSourceReference($ref) { - $pos = strpos($ref,'@'); + $pos = strpos($ref, '@'); if (false !== $pos) { return substr($ref, $pos + 1); } diff --git a/src/Composer/Downloader/SvnDownloader.php b/src/Composer/Downloader/SvnDownloader.php index a13d2310f..addf95d37 100644 --- a/src/Composer/Downloader/SvnDownloader.php +++ b/src/Composer/Downloader/SvnDownloader.php @@ -151,7 +151,7 @@ class SvnDownloader extends VcsDownloader */ protected function getCommitLogs($fromReference, $toReference, $path) { - if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference) ) { + if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference)) { // strip paths from references and only keep the actual revision $fromRevision = preg_replace('{.*@(\d+)$}', '$1', $fromReference); $toRevision = preg_replace('{.*@(\d+)$}', '$1', $toReference); diff --git a/src/Composer/EventDispatcher/Event.php b/src/Composer/EventDispatcher/Event.php index 38ae4f440..2091f6be0 100644 --- a/src/Composer/EventDispatcher/Event.php +++ b/src/Composer/EventDispatcher/Event.php @@ -35,7 +35,7 @@ class Event protected $flags; /** - * @var boolean Whether the event should not be passed to more listeners + * @var bool Whether the event should not be passed to more listeners */ private $propagationStopped = false; @@ -86,7 +86,7 @@ class Event /** * Checks if stopPropagation has been called * - * @return boolean Whether propagation has been stopped + * @return bool Whether propagation has been stopped */ public function isPropagationStopped() { diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index 0e00629c4..721e26a3f 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -136,10 +136,10 @@ class EventDispatcher * * @param Event $event The event object to pass to the event handlers/listeners. * @param string $additionalArgs - * @return int return code of the executed script if any, for php scripts a false return - * value is changed to 1, anything else to 0 * @throws \RuntimeException * @throws \Exception + * @return int return code of the executed script if any, for php scripts a false return + * value is changed to 1, anything else to 0 */ protected function doDispatch(Event $event) { @@ -212,8 +212,8 @@ class EventDispatcher } /** - * @param mixed $target - * @param Event $event + * @param mixed $target + * @param Event $event * @return Event|CommandEvent */ protected function checkListenerExpectedEvent($target, Event $event) @@ -260,7 +260,7 @@ class EventDispatcher * * @param string $eventName The event name - typically a constant * @param Callable $listener A callable expecting an event argument - * @param integer $priority A higher value represents a higher priority + * @param int $priority A higher value represents a higher priority */ protected function addListener($eventName, $listener, $priority = 0) { @@ -313,8 +313,8 @@ class EventDispatcher /** * Checks if an event has listeners registered * - * @param Event $event - * @return boolean + * @param Event $event + * @return bool */ public function hasEventListeners(Event $event) { @@ -355,8 +355,8 @@ class EventDispatcher /** * Checks if string given references a class path and method * - * @param string $callable - * @return boolean + * @param string $callable + * @return bool */ protected function isPhpScript($callable) { diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index e3c899880..683d58d27 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -37,8 +37,8 @@ use Composer\Semver\VersionParser; class Factory { /** - * @return string * @throws \RuntimeException + * @return string */ protected static function getHomeDir() { diff --git a/src/Composer/IO/BufferIO.php b/src/Composer/IO/BufferIO.php index 581680b7c..db3fb634b 100644 --- a/src/Composer/IO/BufferIO.php +++ b/src/Composer/IO/BufferIO.php @@ -23,8 +23,8 @@ use Symfony\Component\Console\Helper\HelperSet; class BufferIO extends ConsoleIO { /** - * @param string $input - * @param int $verbosity + * @param string $input + * @param int $verbosity * @param OutputFormatterInterface $formatter */ public function __construct( diff --git a/src/Composer/IO/ConsoleIO.php b/src/Composer/IO/ConsoleIO.php index e37b9f1ad..ae5b952ea 100644 --- a/src/Composer/IO/ConsoleIO.php +++ b/src/Composer/IO/ConsoleIO.php @@ -111,8 +111,8 @@ class ConsoleIO extends BaseIO /** * @param array $messages - * @param boolean $newline - * @param boolean $stderr + * @param bool $newline + * @param bool $stderr */ private function doWrite($messages, $newline, $stderr) { @@ -153,9 +153,9 @@ class ConsoleIO extends BaseIO /** * @param array $messages - * @param boolean $newline - * @param integer $size - * @param boolean $stderr + * @param bool $newline + * @param int $size + * @param bool $stderr */ private function doOverwrite($messages, $newline, $size, $stderr) { diff --git a/src/Composer/IO/IOInterface.php b/src/Composer/IO/IOInterface.php index 7dc9f5a09..b26700a8c 100644 --- a/src/Composer/IO/IOInterface.php +++ b/src/Composer/IO/IOInterface.php @@ -77,7 +77,7 @@ interface IOInterface * * @param string|array $messages The message as an array of lines or a single string * @param bool $newline Whether to add a newline or not - * @param integer $size The size of line + * @param int $size The size of line */ public function overwrite($messages, $newline = true, $size = null); @@ -86,7 +86,7 @@ interface IOInterface * * @param string|array $messages The message as an array of lines or a single string * @param bool $newline Whether to add a newline or not - * @param integer $size The size of line + * @param int $size The size of line */ public function overwriteError($messages, $newline = true, $size = null); @@ -96,9 +96,8 @@ interface IOInterface * @param string|array $question The question to ask * @param string $default The default answer if none is given by the user * - * @return string The user answer - * * @throws \RuntimeException If there is no data to read in the input stream + * @return string The user answer */ public function ask($question, $default = null); @@ -123,12 +122,11 @@ interface IOInterface * * @param string|array $question The question to ask * @param callback $validator A PHP callback - * @param null|integer $attempts Max number of times to ask before giving up (default of null means infinite) + * @param null|int $attempts Max number of times to ask before giving up (default of null means infinite) * @param string $default The default answer if none is given by the user * - * @return mixed - * * @throws \Exception When any of the validators return an error + * @return mixed */ public function askAndValidate($question, $validator, $attempts = null, $default = null); @@ -153,7 +151,7 @@ interface IOInterface * * @param string $repositoryName The unique name of repository * - * @return boolean + * @return bool */ public function hasAuthentication($repositoryName); diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index c94eedc7f..5f1299a97 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -160,9 +160,8 @@ class Installer /** * Run installation (or update) * - * @return int 0 on success or a positive error code on failure - * * @throws \Exception + * @return int 0 on success or a positive error code on failure */ public function run() { @@ -358,11 +357,11 @@ class Installer } /** - * @param RepositoryInterface $localRepo - * @param RepositoryInterface $installedRepo - * @param PlatformRepository $platformRepo - * @param array $aliases - * @param bool $withDevReqs + * @param RepositoryInterface $localRepo + * @param RepositoryInterface $installedRepo + * @param PlatformRepository $platformRepo + * @param array $aliases + * @param bool $withDevReqs * @return int */ protected function doInstall($localRepo, $installedRepo, $platformRepo, $aliases, $withDevReqs) @@ -700,8 +699,8 @@ class Installer } /** - * @param bool $withDevReqs - * @param RepositoryInterface|null $lockedRepository + * @param bool $withDevReqs + * @param RepositoryInterface|null $lockedRepository * @return Pool */ private function createPool($withDevReqs, RepositoryInterface $lockedRepository = null) @@ -766,8 +765,8 @@ class Installer } /** - * @param RootPackageInterface $rootPackage - * @param PlatformRepository $platformRepo + * @param RootPackageInterface $rootPackage + * @param PlatformRepository $platformRepo * @return Request */ private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo) @@ -804,16 +803,16 @@ class Installer } /** - * @param WritableRepositoryInterface $localRepo - * @param Pool $pool - * @param PolicyInterface $policy - * @param array $repositories - * @param RepositoryInterface $installedRepo - * @param RepositoryInterface $lockedRepository - * @param bool $installFromLock - * @param bool $withDevReqs - * @param string $task - * @param array|null $operations + * @param WritableRepositoryInterface $localRepo + * @param Pool $pool + * @param PolicyInterface $policy + * @param array $repositories + * @param RepositoryInterface $installedRepo + * @param RepositoryInterface $lockedRepository + * @param bool $installFromLock + * @param bool $withDevReqs + * @param string $task + * @param array|null $operations * @return array */ private function processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $installFromLock, $withDevReqs, $task, array $operations = null) @@ -948,8 +947,8 @@ class Installer /** * Loads the most "current" list of packages that are installed meaning from lock ideally or from installed repo as fallback - * @param bool $withDevReqs - * @param RepositoryInterface $installedRepo + * @param bool $withDevReqs + * @param RepositoryInterface $installedRepo * @return array */ private function getCurrentPackages($withDevReqs, $installedRepo) @@ -982,7 +981,7 @@ class Installer foreach ($aliases as $alias) { $normalizedAliases[$alias['package']][$alias['version']] = array( 'alias' => $alias['alias'], - 'alias_normalized' => $alias['alias_normalized'] + 'alias_normalized' => $alias['alias_normalized'], ); } @@ -1062,7 +1061,7 @@ class Installer } /** - * @param PackageInterface $package + * @param PackageInterface $package * @return bool */ private function isUpdateable(PackageInterface $package) @@ -1095,7 +1094,7 @@ class Installer } /** - * @param array $links + * @param array $links * @return array */ private function extractPlatformRequirements($links) @@ -1118,7 +1117,7 @@ class Installer * update whitelist themselves. * * @param RepositoryInterface $localRepo - * @param boolean $devMode + * @param bool $devMode * @param array $rootRequires An array of links to packages in require of the root package * @param array $rootDevRequires An array of links to packages in require-dev of the root package */ @@ -1251,7 +1250,7 @@ class Installer } /** - * @param RepositoryInterface $additionalInstalledRepository + * @param RepositoryInterface $additionalInstalledRepository * @return $this */ public function setAdditionalInstalledRepository(RepositoryInterface $additionalInstalledRepository) @@ -1264,7 +1263,7 @@ class Installer /** * Whether to run in drymode or not * - * @param boolean $dryRun + * @param bool $dryRun * @return Installer */ public function setDryRun($dryRun = true) @@ -1287,7 +1286,7 @@ class Installer /** * prefer source installation * - * @param boolean $preferSource + * @param bool $preferSource * @return Installer */ public function setPreferSource($preferSource = true) @@ -1300,7 +1299,7 @@ class Installer /** * prefer dist installation * - * @param boolean $preferDist + * @param bool $preferDist * @return Installer */ public function setPreferDist($preferDist = true) @@ -1349,7 +1348,7 @@ class Installer /** * update packages * - * @param boolean $update + * @param bool $update * @return Installer */ public function setUpdate($update = true) @@ -1362,7 +1361,7 @@ class Installer /** * enables dev packages * - * @param boolean $devMode + * @param bool $devMode * @return Installer */ public function setDevMode($devMode = true) @@ -1375,7 +1374,7 @@ class Installer /** * set whether to run autoloader or not * - * @param boolean $dumpAutoloader + * @param bool $dumpAutoloader * @return Installer */ public function setDumpAutoloader($dumpAutoloader = true) @@ -1388,7 +1387,7 @@ class Installer /** * set whether to run scripts or not * - * @param boolean $runScripts + * @param bool $runScripts * @return Installer */ public function setRunScripts($runScripts = true) @@ -1414,7 +1413,7 @@ class Installer /** * run in verbose mode * - * @param boolean $verbose + * @param bool $verbose * @return Installer */ public function setVerbose($verbose = true) @@ -1437,7 +1436,7 @@ class Installer /** * set ignore Platform Package requirements * - * @param boolean $ignorePlatformReqs + * @param bool $ignorePlatformReqs * @return Installer */ public function setIgnorePlatformRequirements($ignorePlatformReqs = false) @@ -1464,7 +1463,7 @@ class Installer /** * Should dependencies of whitelisted packages be updated recursively? * - * @param boolean $updateDependencies + * @param bool $updateDependencies * @return Installer */ public function setWhitelistDependencies($updateDependencies = true) @@ -1477,7 +1476,7 @@ class Installer /** * Should packages be preferred in a stable version when updating? * - * @param boolean $preferStable + * @param bool $preferStable * @return Installer */ public function setPreferStable($preferStable = true) @@ -1490,7 +1489,7 @@ class Installer /** * Should packages be preferred in a lowest version when updating? * - * @param boolean $preferLowest + * @param bool $preferLowest * @return Installer */ public function setPreferLowest($preferLowest = true) diff --git a/src/Composer/Installer/InstallationManager.php b/src/Composer/Installer/InstallationManager.php index a43acbbda..b774f83c9 100644 --- a/src/Composer/Installer/InstallationManager.php +++ b/src/Composer/Installer/InstallationManager.php @@ -89,9 +89,8 @@ class InstallationManager * * @param string $type package type * - * @return InstallerInterface - * * @throws \InvalidArgumentException if installer for provided type is not registered + * @return InstallerInterface */ public function getInstaller($type) { @@ -249,7 +248,7 @@ class InstallationManager 'header' => array('Content-type: application/x-www-form-urlencoded'), 'content' => http_build_query($params, '', '&'), 'timeout' => 3, - ) + ), ); $context = StreamContextFactory::getContext($url, $opts); @@ -273,7 +272,7 @@ class InstallationManager 'header' => array('Content-Type: application/json'), 'content' => json_encode($postData), 'timeout' => 6, - ) + ), ); $context = StreamContextFactory::getContext($repoUrl, $opts); diff --git a/src/Composer/Json/JsonFile.php b/src/Composer/Json/JsonFile.php index 1c51a4251..ee4f04e84 100644 --- a/src/Composer/Json/JsonFile.php +++ b/src/Composer/Json/JsonFile.php @@ -137,8 +137,8 @@ class JsonFile * Validates the schema of the current json file according to composer-schema.json rules * * @param int $schema a JsonFile::*_SCHEMA constant - * @return bool true on success * @throws JsonValidationException + * @return bool true on success */ public function validateSchema($schema = self::STRICT_SCHEMA) { @@ -218,7 +218,7 @@ class JsonFile /** * Throws an exception according to a given code with a customized message * - * @param int $code return code of json_last_error function + * @param int $code return code of json_last_error function * @throws \RuntimeException */ private static function throwEncodeError($code) @@ -269,10 +269,10 @@ class JsonFile * * @param string $json * @param string $file - * @return bool true on success * @throws \UnexpectedValueException * @throws JsonValidationException * @throws ParsingException + * @return bool true on success */ protected static function validateSyntax($json, $file = null) { diff --git a/src/Composer/Json/JsonFormatter.php b/src/Composer/Json/JsonFormatter.php index d109acae8..8e2005715 100644 --- a/src/Composer/Json/JsonFormatter.php +++ b/src/Composer/Json/JsonFormatter.php @@ -23,7 +23,6 @@ namespace Composer\Json; class JsonFormatter { /** - * * This code is based on the function found at: * http://recursive-design.com/blog/2008/03/11/format-json-with-php/ * diff --git a/src/Composer/Package/AliasPackage.php b/src/Composer/Package/AliasPackage.php index 130de6bae..8e1bb88fe 100644 --- a/src/Composer/Package/AliasPackage.php +++ b/src/Composer/Package/AliasPackage.php @@ -162,7 +162,7 @@ class AliasPackage extends BasePackage implements CompletePackageInterface } /** - * @param array $links + * @param array $links * @param string $linkType * @internal param string $prettyVersion * @return array diff --git a/src/Composer/Package/Archiver/ArchiverInterface.php b/src/Composer/Package/Archiver/ArchiverInterface.php index 72a06c1c9..a625f5c07 100644 --- a/src/Composer/Package/Archiver/ArchiverInterface.php +++ b/src/Composer/Package/Archiver/ArchiverInterface.php @@ -37,7 +37,7 @@ interface ArchiverInterface * @param string $format The archive format * @param string $sourceType The source type (git, svn, hg, etc.) * - * @return boolean true if the format is supported by the archiver + * @return bool true if the format is supported by the archiver */ public function supports($format, $sourceType); } diff --git a/src/Composer/Package/Archiver/HgExcludeFilter.php b/src/Composer/Package/Archiver/HgExcludeFilter.php index fa2327c5f..b9c81cdc1 100644 --- a/src/Composer/Package/Archiver/HgExcludeFilter.php +++ b/src/Composer/Package/Archiver/HgExcludeFilter.php @@ -26,7 +26,7 @@ class HgExcludeFilter extends BaseExcludeFilter /** * Either HG_IGNORE_REGEX or HG_IGNORE_GLOB - * @var integer + * @var int */ protected $patternMode; diff --git a/src/Composer/Package/BasePackage.php b/src/Composer/Package/BasePackage.php index 9b2a683ca..0369a36dd 100644 --- a/src/Composer/Package/BasePackage.php +++ b/src/Composer/Package/BasePackage.php @@ -161,7 +161,7 @@ abstract class BasePackage implements PackageInterface /** * checks if this package is a platform package * - * @return boolean + * @return bool */ public function isPlatform() { diff --git a/src/Composer/Package/CompletePackage.php b/src/Composer/Package/CompletePackage.php index 0de1609d0..0a926a4ce 100644 --- a/src/Composer/Package/CompletePackage.php +++ b/src/Composer/Package/CompletePackage.php @@ -172,7 +172,7 @@ class CompletePackage extends Package implements CompletePackageInterface } /** - * @return boolean + * @return bool */ public function isAbandoned() { @@ -180,7 +180,7 @@ class CompletePackage extends Package implements CompletePackageInterface } /** - * @param boolean|string $abandoned + * @param bool|string $abandoned */ public function setAbandoned($abandoned) { diff --git a/src/Composer/Package/CompletePackageInterface.php b/src/Composer/Package/CompletePackageInterface.php index 8263a6535..4036b3cec 100644 --- a/src/Composer/Package/CompletePackageInterface.php +++ b/src/Composer/Package/CompletePackageInterface.php @@ -82,7 +82,7 @@ interface CompletePackageInterface extends PackageInterface /** * Returns if the package is abandoned or not * - * @return boolean + * @return bool */ public function isAbandoned(); diff --git a/src/Composer/Package/Link.php b/src/Composer/Package/Link.php index fb2662a6f..e695822fd 100644 --- a/src/Composer/Package/Link.php +++ b/src/Composer/Package/Link.php @@ -110,7 +110,7 @@ class Link } /** - * @param PackageInterface $sourcePackage + * @param PackageInterface $sourcePackage * @return string */ public function getPrettyString(PackageInterface $sourcePackage) diff --git a/src/Composer/Package/Locker.php b/src/Composer/Package/Locker.php index a3c8baf32..dba5541be 100644 --- a/src/Composer/Package/Locker.php +++ b/src/Composer/Package/Locker.php @@ -245,7 +245,7 @@ class Locker $lock = array( '_readme' => array('This file locks the dependencies of your project to a known state', 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file', - 'This file is @gener'.'ated automatically'), + 'This file is @gener'.'ated automatically', ), 'hash' => $this->hash, 'content-hash' => $this->contentHash, 'packages' => null, @@ -426,6 +426,7 @@ class Locker } ksort($relevantContent); + return md5(json_encode($relevantContent)); } } diff --git a/src/Composer/Package/PackageInterface.php b/src/Composer/Package/PackageInterface.php index ba34619f1..c88771cfd 100644 --- a/src/Composer/Package/PackageInterface.php +++ b/src/Composer/Package/PackageInterface.php @@ -197,7 +197,7 @@ interface PackageInterface * * @see getPrettyVersion * - * @param bool $truncate If the source reference is a sha1 hash, truncate it + * @param bool $truncate If the source reference is a sha1 hash, truncate it * @return string version */ public function getFullPrettyVersion($truncate = true); diff --git a/src/Composer/Package/Version/VersionGuesser.php b/src/Composer/Package/Version/VersionGuesser.php index 6b9b020d4..4dd0be511 100644 --- a/src/Composer/Package/Version/VersionGuesser.php +++ b/src/Composer/Package/Version/VersionGuesser.php @@ -57,7 +57,7 @@ class VersionGuesser /** * @param array $packageConfig - * @param string $path Path to guess into + * @param string $path Path to guess into */ public function guessVersion(array $packageConfig, $path) { diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index be8d925cd..174055f4e 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -45,9 +45,9 @@ class PluginManager /** * Initializes plugin manager * - * @param IOInterface $io - * @param Composer $composer - * @param Composer $globalComposer + * @param IOInterface $io + * @param Composer $composer + * @param Composer $globalComposer */ public function __construct(IOInterface $io, Composer $composer, Composer $globalComposer = null) { diff --git a/src/Composer/Repository/ArtifactRepository.php b/src/Composer/Repository/ArtifactRepository.php index 94e634313..01d662212 100644 --- a/src/Composer/Repository/ArtifactRepository.php +++ b/src/Composer/Repository/ArtifactRepository.php @@ -78,7 +78,7 @@ class ArtifactRepository extends ArrayRepository /** * Find a file by name, returning the one that has the shortest path. * - * @param \ZipArchive $zip + * @param \ZipArchive $zip * @param $filename * @return bool|int */ @@ -141,7 +141,7 @@ class ArtifactRepository extends ArrayRepository $package['dist'] = array( 'type' => 'zip', 'url' => $file->getPathname(), - 'shasum' => sha1_file($file->getRealPath()) + 'shasum' => sha1_file($file->getRealPath()), ); $package = $this->loader->load($package); diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 2853a1ea0..ce73037a8 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -586,7 +586,7 @@ class ComposerRepository extends ArrayRepository // url-encode $ signs in URLs as bad proxies choke on them if (($pos = strpos($filename, '$')) && preg_match('{^https?://.*}i', $filename)) { - $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos+1); + $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos + 1); } $retries = 3; diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index 18827f896..294a7a187 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -16,7 +16,6 @@ use Composer\Config; use Composer\IO\IOInterface; use Composer\Json\JsonFile; use Composer\Package\Loader\ArrayLoader; -use Composer\Package\Loader\LoaderInterface; use Composer\Package\Version\VersionGuesser; use Composer\Semver\VersionParser; use Composer\Util\ProcessExecutor; @@ -74,9 +73,9 @@ class PathRepository extends ArrayRepository /** * Initializes path repository. * - * @param array $repoConfig + * @param array $repoConfig * @param IOInterface $io - * @param Config $config + * @param Config $config */ public function __construct(array $repoConfig, IOInterface $io, Config $config) { @@ -104,7 +103,7 @@ class PathRepository extends ArrayRepository foreach ($this->getUrlMatches() as $url) { $path = realpath($url) . '/'; $composerFilePath = $path.'composer.json'; - + if (!file_exists($composerFilePath)) { continue; } @@ -140,6 +139,6 @@ class PathRepository extends ArrayRepository */ private function getUrlMatches() { - return glob($this->url, GLOB_MARK|GLOB_ONLYDIR); + return glob($this->url, GLOB_MARK | GLOB_ONLYDIR); } } diff --git a/src/Composer/Repository/RepositoryManager.php b/src/Composer/Repository/RepositoryManager.php index 336a735b6..372dc8979 100644 --- a/src/Composer/Repository/RepositoryManager.php +++ b/src/Composer/Repository/RepositoryManager.php @@ -91,8 +91,8 @@ class RepositoryManager * * @param string $type repository type * @param array $config repository configuration - * @return RepositoryInterface * @throws \InvalidArgumentException if repository for provided type is not registered + * @return RepositoryInterface */ public function createRepository($type, $config) { diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index c7c225b27..01d4a52d8 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -119,7 +119,7 @@ class PerforceDriver extends VcsDriver 'type' => 'perforce', 'url' => $this->repoConfig['url'], 'reference' => $identifier, - 'p4user' => $this->perforce->getUser() + 'p4user' => $this->perforce->getUser(), ); return $source; diff --git a/src/Composer/Repository/Vcs/VcsDriverInterface.php b/src/Composer/Repository/Vcs/VcsDriverInterface.php index dd30baacd..307d63ef6 100644 --- a/src/Composer/Repository/Vcs/VcsDriverInterface.php +++ b/src/Composer/Repository/Vcs/VcsDriverInterface.php @@ -77,14 +77,13 @@ interface VcsDriverInterface * Return true if the repository has a composer file for a given identifier, * false otherwise. * - * @param string $identifier Any identifier to a specific branch/tag/commit - * @return boolean Whether the repository has a composer file for a given identifier. + * @param string $identifier Any identifier to a specific branch/tag/commit + * @return bool Whether the repository has a composer file for a given identifier. */ public function hasComposerFile($identifier); /** * Performs any cleanup necessary as the driver is not longer needed - * */ public function cleanup(); diff --git a/src/Composer/Script/Event.php b/src/Composer/Script/Event.php index bde7e3b6f..138f43c1a 100644 --- a/src/Composer/Script/Event.php +++ b/src/Composer/Script/Event.php @@ -35,7 +35,7 @@ class Event extends BaseEvent private $io; /** - * @var boolean Dev mode flag + * @var bool Dev mode flag */ private $devMode; @@ -45,7 +45,7 @@ class Event extends BaseEvent * @param string $name The event name * @param Composer $composer The composer object * @param IOInterface $io The IOInterface object - * @param boolean $devMode Whether or not we are in dev mode + * @param bool $devMode Whether or not we are in dev mode * @param array $args Arguments passed by the user * @param array $flags Optional flags to pass data not as argument */ @@ -80,7 +80,7 @@ class Event extends BaseEvent /** * Return the dev mode flag * - * @return boolean + * @return bool */ public function isDevMode() { diff --git a/src/Composer/Util/ConfigValidator.php b/src/Composer/Util/ConfigValidator.php index dfd662ea0..a7ddaca9b 100644 --- a/src/Composer/Util/ConfigValidator.php +++ b/src/Composer/Util/ConfigValidator.php @@ -38,8 +38,8 @@ class ConfigValidator /** * Validates the config, and returns the result. * - * @param string $file The path to the file - * @param integer $arrayLoaderValidationFlags Flags for ArrayLoader validation + * @param string $file The path to the file + * @param int $arrayLoaderValidationFlags Flags for ArrayLoader validation * * @return array a triple containing the errors, publishable errors, and warnings */ diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index c36347fb7..93b1a4010 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -88,10 +88,9 @@ class Filesystem * Uses the process component if proc_open is enabled on the PHP * installation. * - * @param string $directory - * @return bool - * + * @param string $directory * @throws \RuntimeException + * @return bool */ public function removeDirectory($directory) { @@ -174,10 +173,9 @@ class Filesystem /** * Attempts to unlink a file and in case of failure retries after 350ms on windows * - * @param string $path - * @return bool - * + * @param string $path * @throws \RuntimeException + * @return bool */ public function unlink($path) { @@ -200,10 +198,9 @@ class Filesystem /** * Attempts to rmdir a file and in case of failure retries after 350ms on windows * - * @param string $path - * @return bool - * + * @param string $path * @throws \RuntimeException + * @return bool */ public function rmdir($path) { diff --git a/src/Composer/Util/Git.php b/src/Composer/Util/Git.php index 5d84ebbf3..1d4a98294 100644 --- a/src/Composer/Util/Git.php +++ b/src/Composer/Util/Git.php @@ -105,9 +105,7 @@ class Git return; } } - } elseif ( // private non-github repo that failed to authenticate - $this->isAuthenticationFailure($url, $match) - ) { + } elseif ($this->isAuthenticationFailure($url, $match)) { // private non-github repo that failed to authenticate if (strpos($match[2], '@')) { list($authParts, $match[2]) = explode('@', $match[2], 2); } @@ -119,7 +117,7 @@ class Git $defaultUsername = null; if (isset($authParts) && $authParts) { if (false !== strpos($authParts, ':')) { - list($defaultUsername,) = explode(':', $authParts, 2); + list($defaultUsername, ) = explode(':', $authParts, 2); } else { $defaultUsername = $authParts; } diff --git a/src/Composer/Util/NoProxyPattern.php b/src/Composer/Util/NoProxyPattern.php index 4e5c0c76b..994149268 100644 --- a/src/Composer/Util/NoProxyPattern.php +++ b/src/Composer/Util/NoProxyPattern.php @@ -114,7 +114,7 @@ class NoProxyPattern * @param string $cidr IPv4 block in CIDR notation * @param string $ip IPv4 address * - * @return boolean + * @return bool */ private static function inCIDRBlock($cidr, $ip) { diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 8e79f87b3..c1eaeebe9 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -297,7 +297,7 @@ class Perforce } throw new \Exception('p4 command not found in path: ' . $errorOutput); } - throw new \Exception('Invalid user name: ' . $this->getUser() ); + throw new \Exception('Invalid user name: ' . $this->getUser()); } return true; @@ -305,7 +305,7 @@ class Perforce public function connectClient() { - $p4CreateClientCommand = $this->generateP4Command('client -i < ' . str_replace( " ", "\\ ", $this->getP4ClientSpec() )); + $p4CreateClientCommand = $this->generateP4Command('client -i < ' . str_replace(" ", "\\ ", $this->getP4ClientSpec())); $this->executeCommand($p4CreateClientCommand); } diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php index 12ec0fbfc..f3ad94a82 100644 --- a/src/Composer/Util/RemoteFilesystem.php +++ b/src/Composer/Util/RemoteFilesystem.php @@ -56,11 +56,11 @@ class RemoteFilesystem /** * Copy the remote file in local. * - * @param string $originUrl The origin URL - * @param string $fileUrl The file URL - * @param string $fileName the local filename - * @param boolean $progress Display the progression - * @param array $options Additional context options + * @param string $originUrl The origin URL + * @param string $fileUrl The file URL + * @param string $fileName the local filename + * @param bool $progress Display the progression + * @param array $options Additional context options * * @return bool true */ @@ -72,10 +72,10 @@ class RemoteFilesystem /** * Get the content. * - * @param string $originUrl The origin URL - * @param string $fileUrl The file URL - * @param boolean $progress Display the progression - * @param array $options Additional context options + * @param string $originUrl The origin URL + * @param string $fileUrl The file URL + * @param bool $progress Display the progression + * @param array $options Additional context options * * @return bool|string The content */ @@ -107,11 +107,11 @@ class RemoteFilesystem /** * Get file content or copy action. * - * @param string $originUrl The origin URL - * @param string $fileUrl The file URL - * @param array $additionalOptions context options - * @param string $fileName the local filename - * @param boolean $progress Display the progression + * @param string $originUrl The origin URL + * @param string $fileUrl The file URL + * @param array $additionalOptions context options + * @param string $fileName the local filename + * @param bool $progress Display the progression * * @throws TransportException|\Exception * @throws TransportException When the file could not be downloaded @@ -195,7 +195,7 @@ class RemoteFilesystem $this->degradedMode = true; $this->io->writeError(array( ''.$e->getMessage().'', - 'Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info' + 'Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info', )); return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress); @@ -253,7 +253,7 @@ class RemoteFilesystem $this->degradedMode = true; $this->io->writeError(array( 'Failed to decode response: '.$e->getMessage().'', - 'Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info' + 'Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info', )); return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress); @@ -303,7 +303,7 @@ class RemoteFilesystem $this->degradedMode = true; $this->io->writeError(array( ''.$e->getMessage().'', - 'Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info' + 'Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info', )); return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress); @@ -322,12 +322,12 @@ class RemoteFilesystem /** * Get notification action. * - * @param integer $notificationCode The notification code - * @param integer $severity The severity level + * @param int $notificationCode The notification code + * @param int $severity The severity level * @param string $message The message - * @param integer $messageCode The message code - * @param integer $bytesTransferred The loaded size - * @param integer $bytesMax The total size + * @param int $messageCode The message code + * @param int $bytesTransferred The loaded size + * @param int $bytesMax The total size * @throws TransportException */ protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax) @@ -436,7 +436,7 @@ class RemoteFilesystem php_uname('s'), php_uname('r'), $phpVersion - ) + ), ); if (extension_loaded('zlib')) { diff --git a/src/Composer/Util/StreamContextFactory.php b/src/Composer/Util/StreamContextFactory.php index ffeaf3f83..cd8c05d92 100644 --- a/src/Composer/Util/StreamContextFactory.php +++ b/src/Composer/Util/StreamContextFactory.php @@ -26,8 +26,8 @@ final class StreamContextFactory * @param string $url URL the context is to be used for * @param array $defaultOptions Options to merge with the default * @param array $defaultParams Parameters to specify on the context - * @return resource Default context * @throws \RuntimeException if https proxy required and OpenSSL uninstalled + * @return resource Default context */ public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array()) { diff --git a/src/Composer/Util/Svn.php b/src/Composer/Util/Svn.php index d5694b3be..4117499c8 100644 --- a/src/Composer/Util/Svn.php +++ b/src/Composer/Util/Svn.php @@ -54,7 +54,7 @@ class Svn protected $process; /** - * @var integer + * @var int */ protected $qtyAuthTries = 0; @@ -94,9 +94,8 @@ class Svn * @param string $path Target for a checkout * @param bool $verbose Output all output to the user * - * @return string - * * @throws \RuntimeException + * @return string */ public function execute($command, $url, $cwd = null, $path = null, $verbose = false) { @@ -147,7 +146,7 @@ class Svn } /** - * @param boolean $cacheCredentials + * @param bool $cacheCredentials */ public function setCacheCredentials($cacheCredentials) { @@ -157,8 +156,8 @@ class Svn /** * Repositories requests credentials, let's put them in. * - * @return \Composer\Util\Svn * @throws \RuntimeException + * @return \Composer\Util\Svn */ protected function doAuthDance() { @@ -229,8 +228,8 @@ class Svn /** * Get the password for the svn command. Can be empty. * - * @return string * @throws \LogicException + * @return string */ protected function getPassword() { @@ -244,8 +243,8 @@ class Svn /** * Get the username for the svn command. * - * @return string * @throws \LogicException + * @return string */ protected function getUsername() { diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index b5f6e930b..8c7727058 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -200,7 +200,7 @@ class AutoloadGeneratorTest extends TestCase $package->setDevAutoload(array( 'files' => array('devfiles/foo.php'), 'psr-0' => array( - 'Main' => 'tests/' + 'Main' => 'tests/', ), )); @@ -381,7 +381,7 @@ class AutoloadGeneratorTest extends TestCase $package->setAutoload(array( 'psr-0' => array('Prefix' => 'foo/bar/non/existing/'), - 'psr-4' => array('Prefix\\' => 'foo/bar/non/existing2/') + 'psr-4' => array('Prefix\\' => 'foo/bar/non/existing2/'), )); $this->repository->expects($this->once()) @@ -720,7 +720,7 @@ class AutoloadGeneratorTest extends TestCase $mainPackage = new Package('z', '1.0', '1.0'); $mainPackage->setAutoload(array( 'psr-0' => array('A\\B' => $this->workingDir.'/lib'), - 'classmap' => array($this->workingDir.'/src') + 'classmap' => array($this->workingDir.'/src'), )); $mainPackage->setRequires(array(new Link('z', 'a/a'))); diff --git a/tests/Composer/Test/ConfigTest.php b/tests/Composer/Test/ConfigTest.php index e50af5e87..bbcb1d37e 100644 --- a/tests/Composer/Test/ConfigTest.php +++ b/tests/Composer/Test/ConfigTest.php @@ -35,7 +35,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $data = array(); $data['local config inherits system defaults'] = array( array( - 'packagist' => array('type' => 'composer', 'url' => 'https?://packagist.org', 'allow_ssl_downgrade' => true) + 'packagist' => array('type' => 'composer', 'url' => 'https?://packagist.org', 'allow_ssl_downgrade' => true), ), array(), ); @@ -44,7 +44,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase array(), array( array('packagist' => false), - ) + ), ); $data['local config adds above defaults'] = array( @@ -62,7 +62,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $data['system config adds above core defaults'] = array( array( 'example.com' => array('type' => 'composer', 'url' => 'http://example.com'), - 'packagist' => array('type' => 'composer', 'url' => 'https?://packagist.org', 'allow_ssl_downgrade' => true) + 'packagist' => array('type' => 'composer', 'url' => 'https?://packagist.org', 'allow_ssl_downgrade' => true), ), array(), array( @@ -73,11 +73,11 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $data['local config can disable repos by name and re-add them anonymously to bring them above system config'] = array( array( 0 => array('type' => 'composer', 'url' => 'http://packagist.org'), - 'example.com' => array('type' => 'composer', 'url' => 'http://example.com') + 'example.com' => array('type' => 'composer', 'url' => 'http://example.com'), ), array( array('packagist' => false), - array('type' => 'composer', 'url' => 'http://packagist.org') + array('type' => 'composer', 'url' => 'http://packagist.org'), ), array( 'example.com' => array('type' => 'composer', 'url' => 'http://example.com'), @@ -87,10 +87,10 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $data['local config can override by name to bring a repo above system config'] = array( array( 'packagist' => array('type' => 'composer', 'url' => 'http://packagistnew.org'), - 'example.com' => array('type' => 'composer', 'url' => 'http://example.com') + 'example.com' => array('type' => 'composer', 'url' => 'http://example.com'), ), array( - 'packagist' => array('type' => 'composer', 'url' => 'http://packagistnew.org') + 'packagist' => array('type' => 'composer', 'url' => 'http://packagistnew.org'), ), array( 'example.com' => array('type' => 'composer', 'url' => 'http://example.com'), @@ -139,7 +139,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $config->merge(array('config' => array( 'bin-dir' => '$HOME/foo', 'cache-dir' => '/baz/', - 'vendor-dir' => 'vendor' + 'vendor-dir' => 'vendor', ))); $home = rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '\\/'); @@ -153,7 +153,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $config = new Config(false, '/foo/bar'); $config->merge(array('config' => array( 'bin-dir' => '{$vendor-dir}/foo', - 'vendor-dir' => 'vendor' + 'vendor-dir' => 'vendor', ))); $this->assertEquals('/foo/bar/vendor', $config->get('vendor-dir')); diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index 9d4d41462..2c67d7464 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -503,7 +503,7 @@ class SolverTest extends TestCase $this->repo->addPackage($packageX = $this->getPackage('X', '1.0')); $packageX->setRequires(array( 'a' => new Link('X', 'A', $this->getVersionConstraint('>=', '2.0.0.0'), 'requires'), - 'b' => new Link('X', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), 'requires') + 'b' => new Link('X', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), 'requires'), )); $this->repo->addPackage($packageA = $this->getPackage('A', '2.0.0')); @@ -522,7 +522,7 @@ class SolverTest extends TestCase $this->repo->addPackage($packageS = $this->getPackage('S', '2.0.0')); $packageS->setReplaces(array( 'a' => new Link('S', 'A', $this->getVersionConstraint('>=', '2.0.0.0'), 'replaces'), - 'b' => new Link('S', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), 'replaces') + 'b' => new Link('S', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), 'replaces'), )); $this->reposComplete(); @@ -850,13 +850,13 @@ class SolverTest extends TestCase $result[] = array( 'job' => 'update', 'from' => $operation->getInitialPackage(), - 'to' => $operation->getTargetPackage() + 'to' => $operation->getTargetPackage(), ); } else { $job = ('uninstall' === $operation->getJobType() ? 'remove' : 'install'); $result[] = array( 'job' => $job, - 'package' => $operation->getPackage() + 'package' => $operation->getPackage(), ); } } diff --git a/tests/Composer/Test/Downloader/PearPackageExtractorTest.php b/tests/Composer/Test/Downloader/PearPackageExtractorTest.php index 5429d109d..10ac27955 100644 --- a/tests/Composer/Test/Downloader/PearPackageExtractorTest.php +++ b/tests/Composer/Test/Downloader/PearPackageExtractorTest.php @@ -46,7 +46,7 @@ class PearPackageExtractorTest extends \PHPUnit_Framework_TestCase 'to' => 'PEAR/Frontend/Gtk/xpm/black_close_icon.xpm', 'role' => 'php', 'tasks' => array(), - ) + ), ); $this->assertSame($expectedFileActions, $fileActions); } @@ -69,7 +69,7 @@ class PearPackageExtractorTest extends \PHPUnit_Framework_TestCase 'to' => 'Net/URL.php', 'role' => 'php', 'tasks' => array(), - ) + ), ); $this->assertSame($expectedFileActions, $fileActions); } @@ -99,16 +99,16 @@ class PearPackageExtractorTest extends \PHPUnit_Framework_TestCase 'role' => 'php', 'tasks' => array(), ), - 'php/Test.php' => array ( + 'php/Test.php' => array( 'from' => 'Zend_Authentication-2.0.0beta4/php/Test.php', 'to' => '/php/Test.php', 'role' => 'script', - 'tasks' => array ( - array ( + 'tasks' => array( + array( 'from' => '@version@', 'to' => 'version', - ) - ) + ), + ), ), 'renamedFile.php' => array( 'from' => 'Zend_Authentication-2.0.0beta4/renamedFile.php', diff --git a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php index e0cb196cb..925772d42 100644 --- a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php +++ b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php @@ -28,7 +28,7 @@ class EventDispatcherTest extends TestCase { $io = $this->getMock('Composer\IO\IOInterface'); $dispatcher = $this->getDispatcherStubForListenersTest(array( - 'Composer\Test\EventDispatcher\EventDispatcherTest::call' + 'Composer\Test\EventDispatcher\EventDispatcherTest::call', ), $io); $io->expects($this->at(0)) @@ -50,7 +50,7 @@ class EventDispatcherTest extends TestCase { $io = $this->getMock('Composer\IO\IOInterface'); $dispatcher = $this->getDispatcherStubForListenersTest(array( - 'Composer\Test\EventDispatcher\EventDispatcherTest::expectsCommandEvent' + 'Composer\Test\EventDispatcher\EventDispatcherTest::expectsCommandEvent', ), $io); $this->assertEquals(1, $dispatcher->dispatchScript(ScriptEvents::POST_INSTALL_CMD, false)); @@ -60,7 +60,7 @@ class EventDispatcherTest extends TestCase { $io = $this->getMock('Composer\IO\IOInterface'); $dispatcher = $this->getDispatcherStubForListenersTest(array( - 'Composer\Test\EventDispatcher\EventDispatcherTest::expectsVariableEvent' + 'Composer\Test\EventDispatcher\EventDispatcherTest::expectsVariableEvent', ), $io); $this->assertEquals(1, $dispatcher->dispatchScript(ScriptEvents::POST_INSTALL_CMD, false)); diff --git a/tests/Composer/Test/InstallerTest.php b/tests/Composer/Test/InstallerTest.php index 336e1307c..5339b8ff3 100644 --- a/tests/Composer/Test/InstallerTest.php +++ b/tests/Composer/Test/InstallerTest.php @@ -107,7 +107,7 @@ class InstallerTest extends TestCase $a, new ArrayRepository(array($b)), array( - 'install' => array($b) + 'install' => array($b), ), ); @@ -127,7 +127,7 @@ class InstallerTest extends TestCase $a, new ArrayRepository(array($a, $b)), array( - 'install' => array($b) + 'install' => array($b), ), ); diff --git a/tests/Composer/Test/Json/ComposerSchemaTest.php b/tests/Composer/Test/Json/ComposerSchemaTest.php index cf44d4a84..51949797c 100644 --- a/tests/Composer/Test/Json/ComposerSchemaTest.php +++ b/tests/Composer/Test/Json/ComposerSchemaTest.php @@ -44,7 +44,7 @@ class ComposerSchemaTest extends \PHPUnit_Framework_TestCase $this->assertEquals(array( array( 'property' => 'minimum-stability', - 'message' => 'Does not match the regex pattern ^dev|alpha|beta|rc|RC|stable$' + 'message' => 'Does not match the regex pattern ^dev|alpha|beta|rc|RC|stable$', ), ), $this->check($json), 'empty string'); @@ -52,7 +52,7 @@ class ComposerSchemaTest extends \PHPUnit_Framework_TestCase $this->assertEquals(array( array( 'property' => 'minimum-stability', - 'message' => 'Does not match the regex pattern ^dev|alpha|beta|rc|RC|stable$' + 'message' => 'Does not match the regex pattern ^dev|alpha|beta|rc|RC|stable$', ), ), $this->check($json), 'dummy'); diff --git a/tests/Composer/Test/Json/JsonManipulatorTest.php b/tests/Composer/Test/Json/JsonManipulatorTest.php index 0e974ad35..fd6d49584 100644 --- a/tests/Composer/Test/Json/JsonManipulatorTest.php +++ b/tests/Composer/Test/Json/JsonManipulatorTest.php @@ -38,7 +38,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase " \"require\": {\n". " \"vendor/baz\": \"qux\"\n". " }\n". -"}\n" +"}\n", ), array( '{ @@ -53,7 +53,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase "vendor/baz": "qux" } } -' +', ), array( '{ @@ -68,7 +68,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase "vendor/baz": "qux" } } -' +', ), array( '{ @@ -87,7 +87,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase "vendor/baz": "qux" } } -' +', ), array( '{ @@ -107,7 +107,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase "vendor/baz": "qux" } } -' +', ), array( '{ @@ -127,7 +127,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase "vendor/baz": "qux" } } -' +', ), array( '{ @@ -159,7 +159,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase } }] } -' +', ), array( '{ @@ -188,7 +188,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase "foo": "qux" } } -' +', ), array( '{ @@ -207,7 +207,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase "foo": "qux" } } -' +', ), array( '{ @@ -229,7 +229,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase "foo": "qux" } } -' +', ), array( '{ @@ -277,7 +277,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase "foo": "qux" } } -' +', ), ); } @@ -311,7 +311,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase "vendor/baz": "qux" } } -' +', ), array( '{ @@ -329,7 +329,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase "foo": "bar" } } -' +', ), array( '{ @@ -401,7 +401,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase } } } -' +', ), 'works on simple ones last' => array( '{ @@ -426,7 +426,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase } } } -' +', ), 'works on simple ones unique' => array( '{ @@ -443,7 +443,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase "repositories": { } } -' +', ), 'works on simple ones middle' => array( '{ @@ -476,7 +476,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase } } } -' +', ), 'works on undefined ones' => array( '{ @@ -497,7 +497,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase } } } -' +', ), 'works on child having unmatched name' => array( '{ @@ -518,7 +518,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase } } } -' +', ), 'works on child having duplicate name' => array( '{ @@ -541,7 +541,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase } } } -' +', ), 'works on empty repos' => array( '{ @@ -549,19 +549,19 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase } }', 'bar', - true + true, ), 'works on empty repos2' => array( '{ "repositories": {} }', 'bar', - true + true, ), 'works on missing repos' => array( "{\n}", 'bar', - true + true, ), 'works on deep repos' => array( '{ @@ -577,7 +577,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase "repositories": { } } -' +', ), 'fails on deep repos with borked texts' => array( '{ @@ -588,7 +588,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase } }', 'bar', - false + false, ), 'fails on deep repos with borked texts2' => array( '{ @@ -599,7 +599,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase } }', 'bar', - false + false, ), 'fails on deep arrays with borked texts' => array( '{ @@ -610,7 +610,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase ] }', 'bar', - false + false, ), 'fails on deep arrays with borked texts2' => array( '{ @@ -621,7 +621,7 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase ] }', 'bar', - false + false, ), ); } diff --git a/tests/Composer/Test/Json/JsonValidationExceptionTest.php b/tests/Composer/Test/Json/JsonValidationExceptionTest.php index 76959d688..31ba9b7bf 100644 --- a/tests/Composer/Test/Json/JsonValidationExceptionTest.php +++ b/tests/Composer/Test/Json/JsonValidationExceptionTest.php @@ -36,7 +36,7 @@ class JsonValidationExceptionTest extends \PHPUnit_Framework_TestCase { return array( array('test message', array()), - array(null, null) + array(null, null), ); } } diff --git a/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php b/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php index 3c0c44abe..f395eba6e 100644 --- a/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php +++ b/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php @@ -14,7 +14,6 @@ namespace Composer\Test\Package\Archiver; use Composer\Package\Archiver\ArchivableFilesFinder; use Composer\Util\Filesystem; - use Symfony\Component\Process\Process; use Symfony\Component\Process\ExecutableFinder; @@ -287,7 +286,7 @@ class ArchivableFilesFinderTest extends \PHPUnit_Framework_TestCase * * @param string $process The name of the binary to test. * - * @return boolean True if the process is available, false otherwise. + * @return bool True if the process is available, false otherwise. */ protected function isProcessAvailable($process) { diff --git a/tests/Composer/Test/Package/BasePackageTest.php b/tests/Composer/Test/Package/BasePackageTest.php index d8d4ac8ed..c54762fca 100644 --- a/tests/Composer/Test/Package/BasePackageTest.php +++ b/tests/Composer/Test/Package/BasePackageTest.php @@ -54,22 +54,22 @@ class BasePackageTest extends \PHPUnit_Framework_TestCase array( 'sourceReference' => 'v2.1.0-RC2', 'truncate' => true, - 'expected' => 'PrettyVersion v2.1.0-RC2' + 'expected' => 'PrettyVersion v2.1.0-RC2', ), array( 'sourceReference' => 'bbf527a27356414bfa9bf520f018c5cb7af67c77', 'truncate' => true, - 'expected' => 'PrettyVersion bbf527a' + 'expected' => 'PrettyVersion bbf527a', ), array( 'sourceReference' => 'v1.0.0', 'truncate' => false, - 'expected' => 'PrettyVersion v1.0.0' + 'expected' => 'PrettyVersion v1.0.0', ), array( 'sourceReference' => 'bbf527a27356414bfa9bf520f018c5cb7af67c77', 'truncate' => false, - 'expected' => 'PrettyVersion bbf527a27356414bfa9bf520f018c5cb7af67c77' + 'expected' => 'PrettyVersion bbf527a27356414bfa9bf520f018c5cb7af67c77', ), ); diff --git a/tests/Composer/Test/Package/Dumper/ArrayDumperTest.php b/tests/Composer/Test/Package/Dumper/ArrayDumperTest.php index 852d667e4..c2c820fb1 100644 --- a/tests/Composer/Test/Package/Dumper/ArrayDumperTest.php +++ b/tests/Composer/Test/Package/Dumper/ArrayDumperTest.php @@ -45,7 +45,7 @@ class ArrayDumperTest extends \PHPUnit_Framework_TestCase array( 'name' => 'foo', 'version' => '1.0', - 'version_normalized' => '1.0.0.0' + 'version_normalized' => '1.0.0.0', ), $config ); @@ -100,7 +100,7 @@ class ArrayDumperTest extends \PHPUnit_Framework_TestCase return array( array( 'type', - 'library' + 'library', ), array( 'time', @@ -110,46 +110,46 @@ class ArrayDumperTest extends \PHPUnit_Framework_TestCase ), array( 'authors', - array('Nils Adermann ', 'Jordi Boggiano ') + array('Nils Adermann ', 'Jordi Boggiano '), ), array( 'homepage', - 'https://getcomposer.org' + 'https://getcomposer.org', ), array( 'description', - 'Dependency Manager' + 'Dependency Manager', ), array( 'keywords', array('package', 'dependency', 'autoload'), null, - array('autoload', 'dependency', 'package') + array('autoload', 'dependency', 'package'), ), array( 'bin', array('bin/composer'), - 'binaries' + 'binaries', ), array( 'license', - array('MIT') + array('MIT'), ), array( 'autoload', - array('psr-0' => array('Composer' => 'src/')) + array('psr-0' => array('Composer' => 'src/')), ), array( 'repositories', - array('packagist' => false) + array('packagist' => false), ), array( 'scripts', - array('post-update-cmd' => 'MyVendor\\MyClass::postUpdate') + array('post-update-cmd' => 'MyVendor\\MyClass::postUpdate'), ), array( 'extra', - array('class' => 'MyVendor\\Installer') + array('class' => 'MyVendor\\Installer'), ), array( 'archive', @@ -174,7 +174,7 @@ class ArrayDumperTest extends \PHPUnit_Framework_TestCase array( 'suggest', array('foo/bar' => 'very useful package'), - 'suggests' + 'suggests', ), array( 'support', @@ -184,43 +184,43 @@ class ArrayDumperTest extends \PHPUnit_Framework_TestCase 'require', array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')), 'requires', - array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0') + array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0'), ), array( 'require-dev', array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')), 'devRequires', - array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0') + array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0'), ), array( 'suggest', array('foo/bar' => 'very useful package', 'bar/baz' => 'another useful package'), 'suggests', - array('bar/baz' => 'another useful package', 'foo/bar' => 'very useful package') + array('bar/baz' => 'another useful package', 'foo/bar' => 'very useful package'), ), array( 'provide', array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')), 'provides', - array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0') + array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0'), ), array( 'replace', array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')), 'replaces', - array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0') + array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0'), ), array( 'conflict', array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')), 'conflicts', - array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0') + array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0'), ), array( 'transport-options', array('ssl' => array('local_cert' => '/opt/certs/test.pem')), - 'transportOptions' - ) + 'transportOptions', + ), ); } diff --git a/tests/Composer/Test/Package/Loader/ArrayLoaderTest.php b/tests/Composer/Test/Package/Loader/ArrayLoaderTest.php index b452a4095..10963b55b 100644 --- a/tests/Composer/Test/Package/Loader/ArrayLoaderTest.php +++ b/tests/Composer/Test/Package/Loader/ArrayLoaderTest.php @@ -17,7 +17,6 @@ use Composer\Package\Dumper\ArrayDumper; class ArrayLoaderTest extends \PHPUnit_Framework_TestCase { - /** * @var ArrayLoader */ @@ -124,7 +123,7 @@ class ArrayLoaderTest extends \PHPUnit_Framework_TestCase 'exclude' => array('/foo/bar', 'baz', '!/foo/bar/baz'), ), 'transport-options' => array('ssl' => array('local_cert' => '/opt/certs/test.pem')), - 'abandoned' => 'foo/bar' + 'abandoned' => 'foo/bar', ); $package = $this->loader->load($config); @@ -195,7 +194,7 @@ class ArrayLoaderTest extends \PHPUnit_Framework_TestCase $config = array( 'name' => 'A', 'version' => '1.2.3.4', - 'abandoned' => 'foo/bar' + 'abandoned' => 'foo/bar', ); $package = $this->loader->load($config); @@ -207,7 +206,7 @@ class ArrayLoaderTest extends \PHPUnit_Framework_TestCase { $config = array( 'name' => 'A', - 'version' => '1.2.3.4' + 'version' => '1.2.3.4', ); $package = $this->loader->load($config); diff --git a/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php b/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php index e393d3536..218d6e5ff 100644 --- a/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php +++ b/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php @@ -41,7 +41,7 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase 'foo/bar' => '~2.1.0-beta2', 'bar/baz' => '1.0.x-dev as 1.2.0', 'qux/quux' => '1.0.*@rc', - 'zux/complex' => '~1.0,>=1.0.2@dev' + 'zux/complex' => '~1.0,>=1.0.2@dev', ), 'minimum-stability' => 'alpha', )); @@ -83,8 +83,6 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase $this->assertEquals("No version set (parsed as 1.0.0)", $package->getPrettyVersion()); } - - public function testFeatureBranchPrettyVersion() { if (!function_exists('proc_open')) { diff --git a/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php b/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php index ab61b6c15..4668099bf 100644 --- a/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php +++ b/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php @@ -118,7 +118,7 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase array( 'type' => 'composer', 'url' => 'https://packagist.org/', - ) + ), ), 'config' => array( 'bin-dir' => 'bin', @@ -139,14 +139,14 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase 'branch-alias' => array( 'dev-master' => '2.0-dev', 'dev-old' => '1.0.x-dev', - '3.x-dev' => '3.1.x-dev' + '3.x-dev' => '3.1.x-dev', ), ), 'bin' => array( 'bin/foo', 'bin/bar', ), - 'transport-options' => array('ssl' => array('local_cert' => '/opt/certs/test.pem')) + 'transport-options' => array('ssl' => array('local_cert' => '/opt/certs/test.pem')), ), ), array( // test as array @@ -220,8 +220,8 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase 'name' => 'foo', ), array( - 'name : invalid value (foo), must match [A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*' - ) + 'name : invalid value (foo), must match [A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', + ), ), array( array( @@ -230,7 +230,7 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase ), array( 'homepage : should be a string, integer given', - ) + ), ), array( array( @@ -241,7 +241,7 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase ), array( 'support.source : invalid value, must be a string', - ) + ), ), array( array( @@ -249,8 +249,8 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase 'autoload' => 'strings', ), array( - 'autoload : should be an array, string given' - ) + 'autoload : should be an array, string given', + ), ), array( array( @@ -262,8 +262,8 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase ), ), array( - 'autoload : invalid value (psr0), must be one of psr-0, psr-4, classmap, files' - ) + 'autoload : invalid value (psr0), must be one of psr-0, psr-4, classmap, files', + ), ), array( array( @@ -271,8 +271,8 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase 'transport-options' => 'test', ), array( - 'transport-options : should be an array, string given' - ) + 'transport-options : should be an array, string given', + ), ), ); } @@ -286,8 +286,8 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase 'homepage' => 'foo:bar', ), array( - 'homepage : invalid value (foo:bar), must be an http/https URL' - ) + 'homepage : invalid value (foo:bar), must be an http/https URL', + ), ), array( array( @@ -304,7 +304,7 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase 'support.forum : invalid value (foo:bar), must be an http/https URL', 'support.issues : invalid value (foo:bar), must be an http/https URL', 'support.wiki : invalid value (foo:bar), must be an http/https URL', - ) + ), ), array( array( @@ -322,35 +322,35 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase 'require.bar/foo : unbound version constraints (dev-master) should be avoided', 'require.bar/hacked : unbound version constraints (@stable) should be avoided', ), - false + false, ), array( array( 'name' => 'foo/bar', 'extra' => array( 'branch-alias' => array( - '5.x-dev' => '3.1.x-dev' + '5.x-dev' => '3.1.x-dev', ), - ) + ), ), array( - 'extra.branch-alias.5.x-dev : the target branch (3.1.x-dev) is not a valid numeric alias for this version' + 'extra.branch-alias.5.x-dev : the target branch (3.1.x-dev) is not a valid numeric alias for this version', ), - false + false, ), array( array( 'name' => 'foo/bar', 'extra' => array( 'branch-alias' => array( - '5.x-dev' => '3.1-dev' + '5.x-dev' => '3.1-dev', ), - ) + ), ), array( - 'extra.branch-alias.5.x-dev : the target branch (3.1-dev) is not a valid numeric alias for this version' + 'extra.branch-alias.5.x-dev : the target branch (3.1-dev) is not a valid numeric alias for this version', ), - false + false, ), ); } diff --git a/tests/Composer/Test/Package/LockerTest.php b/tests/Composer/Test/Package/LockerTest.php index 2a45b1c66..79f82e74d 100644 --- a/tests/Composer/Test/Package/LockerTest.php +++ b/tests/Composer/Test/Package/LockerTest.php @@ -71,8 +71,8 @@ class LockerTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue(array( 'packages' => array( array('name' => 'pkg1', 'version' => '1.0.0-beta'), - array('name' => 'pkg2', 'version' => '0.1.10') - ) + array('name' => 'pkg2', 'version' => '0.1.10'), + ), ))); $repo = $locker->getLockedRepository(); @@ -127,12 +127,12 @@ class LockerTest extends \PHPUnit_Framework_TestCase ->with(array( '_readme' => array('This file locks the dependencies of your project to a known state', 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file', - 'This file is @gener'.'ated automatically'), + 'This file is @gener'.'ated automatically', ), 'hash' => $hash, 'content-hash' => $contentHash, 'packages' => array( array('name' => 'pkg1', 'version' => '1.0.0-beta'), - array('name' => 'pkg2', 'version' => '0.1.10') + array('name' => 'pkg2', 'version' => '0.1.10'), ), 'packages-dev' => array(), 'aliases' => array(), diff --git a/tests/Composer/Test/Plugin/PluginInstallerTest.php b/tests/Composer/Test/Plugin/PluginInstallerTest.php index 4af7197f7..b449d7e90 100644 --- a/tests/Composer/Test/Plugin/PluginInstallerTest.php +++ b/tests/Composer/Test/Plugin/PluginInstallerTest.php @@ -216,7 +216,7 @@ class PluginInstallerTest extends TestCase } /** - * @param string $newPluginApiVersion + * @param string $newPluginApiVersion * @param CompletePackage[] $plugins */ private function setPluginApiVersionWithPlugins($newPluginApiVersion, array $plugins = array()) diff --git a/tests/Composer/Test/Repository/ComposerRepositoryTest.php b/tests/Composer/Test/Repository/ComposerRepositoryTest.php index 06fa58b6a..3b35714df 100644 --- a/tests/Composer/Test/Repository/ComposerRepositoryTest.php +++ b/tests/Composer/Test/Repository/ComposerRepositoryTest.php @@ -75,8 +75,8 @@ class ComposerRepositoryTest extends TestCase array('foo/bar' => array( 'name' => 'foo/bar', 'versions' => array( - '1.0.0' => array('name' => 'foo/bar', 'version' => '1.0.0') - ) + '1.0.0' => array('name' => 'foo/bar', 'version' => '1.0.0'), + ), )), ), // New repository format @@ -110,7 +110,7 @@ class ComposerRepositoryTest extends TestCase $properties = array( 'cache' => $cache, 'loader' => new ArrayLoader(), - 'providerListing' => array('p/a.json' => array('sha256' => 'xxx')) + 'providerListing' => array('p/a.json' => array('sha256' => 'xxx')), ); foreach ($properties as $property => $value) { @@ -140,7 +140,7 @@ class ComposerRepositoryTest extends TestCase 'name' => 'a', 'version' => '0.6', )), - ) + ), ))); $pool = $this->getMock('Composer\DependencyResolver\Pool'); diff --git a/tests/Composer/Test/Repository/FilesystemRepositoryTest.php b/tests/Composer/Test/Repository/FilesystemRepositoryTest.php index fa1ec6d5b..6f8b71d20 100644 --- a/tests/Composer/Test/Repository/FilesystemRepositoryTest.php +++ b/tests/Composer/Test/Repository/FilesystemRepositoryTest.php @@ -26,7 +26,7 @@ class FilesystemRepositoryTest extends TestCase ->expects($this->once()) ->method('read') ->will($this->returnValue(array( - array('name' => 'package1', 'version' => '1.0.0-beta', 'type' => 'vendor') + array('name' => 'package1', 'version' => '1.0.0-beta', 'type' => 'vendor'), ))); $json ->expects($this->once()) @@ -94,7 +94,7 @@ class FilesystemRepositoryTest extends TestCase ->expects($this->once()) ->method('write') ->with(array( - array('name' => 'mypkg', 'type' => 'library', 'version' => '0.1.10', 'version_normalized' => '0.1.10.0') + array('name' => 'mypkg', 'type' => 'library', 'version' => '0.1.10', 'version_normalized' => '0.1.10.0'), )); $repository->addPackage($this->getPackage('mypkg', '0.1.10')); diff --git a/tests/Composer/Test/Repository/PathRepositoryTest.php b/tests/Composer/Test/Repository/PathRepositoryTest.php index 9dd7c1249..47b7ac24f 100644 --- a/tests/Composer/Test/Repository/PathRepositoryTest.php +++ b/tests/Composer/Test/Repository/PathRepositoryTest.php @@ -15,9 +15,6 @@ namespace Composer\Repository; use Composer\Package\Loader\ArrayLoader; use Composer\Semver\VersionParser; use Composer\TestCase; -use Composer\IO\NullIO; -use Composer\Config; -use Composer\Package\BasePackage; class PathRepositoryTest extends TestCase { diff --git a/tests/Composer/Test/Repository/Pear/ChannelReaderTest.php b/tests/Composer/Test/Repository/Pear/ChannelReaderTest.php index 1d9d39767..3e68282f4 100644 --- a/tests/Composer/Test/Repository/Pear/ChannelReaderTest.php +++ b/tests/Composer/Test/Repository/Pear/ChannelReaderTest.php @@ -106,18 +106,18 @@ class ChannelReaderTest extends TestCase 'ext', 'xml' ), - ) + ), ) ) - ) + ), ) - ) + ), ) ); $packages = $ref->invoke($reader, $channelInfo, new VersionParser()); - $expectedPackage = new CompletePackage('pear-test.loc/sample', '1.0.0.1' , '1.0.0.1'); + $expectedPackage = new CompletePackage('pear-test.loc/sample', '1.0.0.1', '1.0.0.1'); $expectedPackage->setType('pear-library'); $expectedPackage->setDistType('file'); $expectedPackage->setDescription('description'); diff --git a/tests/Composer/Test/Repository/PearRepositoryTest.php b/tests/Composer/Test/Repository/PearRepositoryTest.php index 7eaad13e7..f076d72cc 100644 --- a/tests/Composer/Test/Repository/PearRepositoryTest.php +++ b/tests/Composer/Test/Repository/PearRepositoryTest.php @@ -40,7 +40,7 @@ class PearRepositoryTest extends TestCase ); $repoConfig = array( - 'url' => $url + 'url' => $url, ); $this->createRepository($repoConfig); @@ -64,7 +64,7 @@ class PearRepositoryTest extends TestCase public function testRepositoryRead($url, array $expectedPackages) { $repoConfig = array( - 'url' => $url + 'url' => $url, ); if (!@file_get_contents('http://'.$url)) { @@ -88,37 +88,37 @@ class PearRepositoryTest extends TestCase 'pear.php.net', array( array('name' => 'pear-pear.php.net/PEAR', 'version' => '1.9.4'), - ) + ), ), array( 'pear.pdepend.org', array( array('name' => 'pear-pear.pdepend.org/PHP_Depend', 'version' => '1.0.5'), - ) + ), ), array( 'pear.phpmd.org', array( array('name' => 'pear-pear.phpmd.org/PHP_PMD', 'version' => '1.3.3'), - ) + ), ), array( 'pear.doctrine-project.org', array( array('name' => 'pear-pear.doctrine-project.org/DoctrineORM', 'version' => '2.2.2'), - ) + ), ), array( 'pear.symfony-project.com', array( array('name' => 'pear-pear.symfony-project.com/YAML', 'version' => '1.0.6'), - ) + ), ), array( 'pear.pirum-project.org', array( array('name' => 'pear-pear.pirum-project.org/Pirum', 'version' => '1.1.4'), - ) + ), ), ); } diff --git a/tests/Composer/Test/Util/GitHubTest.php b/tests/Composer/Test/Util/GitHubTest.php index 1363afd15..83d18dbe4 100644 --- a/tests/Composer/Test/Util/GitHubTest.php +++ b/tests/Composer/Test/Util/GitHubTest.php @@ -18,8 +18,8 @@ use RecursiveArrayIterator; use RecursiveIteratorIterator; /** -* @author Rob Bast -*/ + * @author Rob Bast + */ class GitHubTest extends \PHPUnit_Framework_TestCase { private $username = 'username'; diff --git a/tests/Composer/Test/Util/PerforceTest.php b/tests/Composer/Test/Util/PerforceTest.php index dc727096d..f4d12d1be 100644 --- a/tests/Composer/Test/Util/PerforceTest.php +++ b/tests/Composer/Test/Util/PerforceTest.php @@ -53,7 +53,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase 'depot' => self::TEST_DEPOT, 'branch' => self::TEST_BRANCH, 'p4user' => self::TEST_P4USER, - 'unique_perforce_client_name' => self::TEST_CLIENT_NAME + 'unique_perforce_client_name' => self::TEST_CLIENT_NAME, ); } @@ -222,9 +222,9 @@ class PerforceTest extends \PHPUnit_Framework_TestCase 'depot' => 'depot', 'branch' => 'branch', 'p4user' => 'user', - 'p4password' => 'TEST_PASSWORD' + 'p4password' => 'TEST_PASSWORD', ); - $this->perforce = new Perforce($repoConfig, 'port', 'path', $this->processExecutor, false, $this->getMockIOInterface(), 'TEST'); + $this->perforce = new Perforce($repoConfig, 'port', 'path', $this->processExecutor, false, $this->getMockIOInterface(), 'TEST'); $password = $this->perforce->queryP4Password(); $this->assertEquals('TEST_PASSWORD', $password); } @@ -476,7 +476,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase 'name' => 'test/perforce', 'description' => 'Basic project for testing', 'minimum-stability' => 'dev', - 'autoload' => array('psr-0' => array()) + 'autoload' => array('psr-0' => array()), ); $this->assertEquals($expected, $result); } @@ -517,7 +517,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase 'name' => 'test/perforce', 'description' => 'Basic project for testing', 'minimum-stability' => 'dev', - 'autoload' => array('psr-0' => array()) + 'autoload' => array('psr-0' => array()), ); $this->assertEquals($expected, $result); } @@ -546,7 +546,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase 'name' => 'test/perforce', 'description' => 'Basic project for testing', 'minimum-stability' => 'dev', - 'autoload' => array('psr-0' => array()) + 'autoload' => array('psr-0' => array()), ); $this->assertEquals($expected, $result); } @@ -588,7 +588,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase 'name' => 'test/perforce', 'description' => 'Basic project for testing', 'minimum-stability' => 'dev', - 'autoload' => array('psr-0' => array()) + 'autoload' => array('psr-0' => array()), ); $this->assertEquals($expected, $result); } @@ -662,7 +662,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase '"psr-0" : {', '}', '}', - '}' + '}', ); return implode($composer_json); @@ -688,7 +688,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase 'SubmitOptions: revertunchanged', PHP_EOL, 'LineEnd: local', - PHP_EOL + PHP_EOL, ); if ($withStream) { $expectedArray[] = 'Stream:'; diff --git a/tests/Composer/Test/Util/StreamContextFactoryTest.php b/tests/Composer/Test/Util/StreamContextFactoryTest.php index 2cc419670..590a868fd 100644 --- a/tests/Composer/Test/Util/StreamContextFactoryTest.php +++ b/tests/Composer/Test/Util/StreamContextFactoryTest.php @@ -52,11 +52,11 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase return array( array( $a = array('http' => array('follow_location' => 1, 'max_redirects' => 20)), array(), - array('options' => $a), array() + array('options' => $a), array(), ), array( $a = array('http' => array('method' => 'GET', 'max_redirects' => 20, 'follow_location' => 1)), array('http' => array('method' => 'GET')), - array('options' => $a, 'notification' => $f = function () {}), array('notification' => $f) + array('options' => $a, 'notification' => $f = function () {}), array('notification' => $f), ), ); } @@ -143,8 +143,8 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase 'follow_location' => 1, ), 'ssl' => array( 'SNI_enabled' => true, - 'SNI_server_name' => 'example.org' - ) + 'SNI_server_name' => 'example.org', + ), ); if (PHP_VERSION_ID >= 50600) { unset($expected['ssl']['SNI_server_name']); @@ -173,8 +173,8 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase 'follow_location' => 1, ), 'ssl' => array( 'SNI_enabled' => true, - 'SNI_server_name' => 'example.org' - ) + 'SNI_server_name' => 'example.org', + ), ); if (PHP_VERSION_ID >= 50600) { unset($expected['ssl']['SNI_server_name']); @@ -221,17 +221,17 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase { $options = array( 'http' => array( - 'header' => "X-Foo: bar\r\nContent-Type: application/json\r\nAuthorization: Basic aW52YWxpZA==" - ) + 'header' => "X-Foo: bar\r\nContent-Type: application/json\r\nAuthorization: Basic aW52YWxpZA==", + ), ); $expectedOptions = array( 'http' => array( 'header' => array( "X-Foo: bar", "Authorization: Basic aW52YWxpZA==", - "Content-Type: application/json" - ) - ) + "Content-Type: application/json", + ), + ), ); $context = StreamContextFactory::getContext('http://example.org', $options); $ctxoptions = stream_context_get_options($context); diff --git a/tests/Composer/Test/Util/SvnTest.php b/tests/Composer/Test/Util/SvnTest.php index b1f19ca1a..c54c9c504 100644 --- a/tests/Composer/Test/Util/SvnTest.php +++ b/tests/Composer/Test/Util/SvnTest.php @@ -60,9 +60,9 @@ class SvnTest extends \PHPUnit_Framework_TestCase $config->merge(array( 'config' => array( 'http-basic' => array( - 'svn.apache.org' => array('username' => 'foo', 'password' => 'bar') - ) - ) + 'svn.apache.org' => array('username' => 'foo', 'password' => 'bar'), + ), + ), )); $svn = new Svn($url, new NullIO, $config); @@ -81,9 +81,9 @@ class SvnTest extends \PHPUnit_Framework_TestCase array( 'config' => array( 'http-basic' => array( - 'svn.apache.org' => array('username' => 'foo', 'password' => 'bar') - ) - ) + 'svn.apache.org' => array('username' => 'foo', 'password' => 'bar'), + ), + ), ) ); @@ -104,9 +104,9 @@ class SvnTest extends \PHPUnit_Framework_TestCase array( 'config' => array( 'http-basic' => array( - 'svn.apache.org' => array('username' => 'foo', 'password' => 'bar') - ) - ) + 'svn.apache.org' => array('username' => 'foo', 'password' => 'bar'), + ), + ), ) ); From 2dbad30336812dac90e84a525fde88731cfd78ce Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 29 Sep 2015 20:57:26 +0200 Subject: [PATCH 202/205] fixes #4459 --- src/Composer/Command/ConfigCommand.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Composer/Command/ConfigCommand.php b/src/Composer/Command/ConfigCommand.php index 2b7fd4846..fb7c2bd39 100644 --- a/src/Composer/Command/ConfigCommand.php +++ b/src/Composer/Command/ConfigCommand.php @@ -475,13 +475,7 @@ EOT if (is_array($value) && (!is_numeric(key($value)) || ($key === 'repositories' && null === $k))) { $k .= preg_replace('{^config\.}', '', $key . '.'); $this->listConfiguration($value, $rawVal, $output, $k); - - if (substr_count($k, '.') > 1) { - $k = str_split($k, strrpos($k, '.', -2)); - $k = $k[0] . '.'; - } else { - $k = $origK; - } + $k = $origK; continue; } From 4f4d236be38d96bb137761e976b09d981639398d Mon Sep 17 00:00:00 2001 From: Sullivan SENECHAL Date: Thu, 1 Oct 2015 14:54:45 +0200 Subject: [PATCH 203/205] PackageInterface[] on RepositoryInterface php doc --- src/Composer/Repository/RepositoryInterface.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Composer/Repository/RepositoryInterface.php b/src/Composer/Repository/RepositoryInterface.php index 0b2e8132a..94e52af5f 100644 --- a/src/Composer/Repository/RepositoryInterface.php +++ b/src/Composer/Repository/RepositoryInterface.php @@ -51,14 +51,14 @@ interface RepositoryInterface extends \Countable * @param string $name package name * @param string|\Composer\Semver\Constraint\ConstraintInterface $constraint package version or version constraint to match against * - * @return array + * @return PackageInterface[] */ public function findPackages($name, $constraint = null); /** * Returns list of registered packages. * - * @return array + * @return PackageInterface[] */ public function getPackages(); From 7bd0c5abdd96ecc0ed402d95cb38d1190161986b Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Thu, 1 Oct 2015 15:05:17 +0200 Subject: [PATCH 204/205] itteratively expand key and attempt to match fixes #4459 (also) --- src/Composer/Command/ConfigCommand.php | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/Composer/Command/ConfigCommand.php b/src/Composer/Command/ConfigCommand.php index 2b7fd4846..5d3823b67 100644 --- a/src/Composer/Command/ConfigCommand.php +++ b/src/Composer/Command/ConfigCommand.php @@ -238,17 +238,19 @@ EOT } elseif (strpos($settingKey, '.')) { $bits = explode('.', $settingKey); $data = $data['config']; + $match = false; foreach ($bits as $bit) { - if (isset($data[$bit])) { - $data = $data[$bit]; - } elseif (isset($data[implode('.', $bits)])) { - // last bit can contain domain names and such so try to join whatever is left if it exists - $data = $data[implode('.', $bits)]; - break; - } else { - throw new \RuntimeException($settingKey.' is not defined'); + $key = isset($key) ? $key.'.'.$bit : $bit; + $match = false; + if (isset($data[$key])) { + $match = true; + $data = $data[$key]; + unset($key); } - array_shift($bits); + } + + if (!$match) { + throw new \RuntimeException($settingKey.' is not defined.'); } $value = $data; From 8cacb16cce08e333175d5f668596e737643251e4 Mon Sep 17 00:00:00 2001 From: 3onyc <3onyc@x3tech.com> Date: Sat, 3 Oct 2015 22:40:55 +0200 Subject: [PATCH 205/205] Typo: prefering -> preferring --- doc/articles/troubleshooting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/articles/troubleshooting.md b/doc/articles/troubleshooting.md index f0f55385d..a6f082ab7 100644 --- a/doc/articles/troubleshooting.md +++ b/doc/articles/troubleshooting.md @@ -193,7 +193,7 @@ If you have been pointed to this page, you want to check a few things: these fixed is raise awareness to the network engineers that have the power to fix it. To disable IPv6 on Linux, try using this command which appends a - rule prefering IPv4 over IPv6 to your config: + rule preferring IPv4 over IPv6 to your config: `sudo sh -c "echo 'precedence ::ffff:0:0/96 100' >> /etc/gai.conf"` - If none of the above helped, please report the error.