From 627a832cc15f9321cbf97eb5692e515800b30f6f Mon Sep 17 00:00:00 2001 From: Patrick Reimers Date: Fri, 1 Mar 2019 19:39:07 +0100 Subject: [PATCH 01/48] Return non zero exit code on deprecation --- src/Composer/Package/Loader/ValidatingArrayLoader.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Composer/Package/Loader/ValidatingArrayLoader.php b/src/Composer/Package/Loader/ValidatingArrayLoader.php index 405e567f0..a8aa65331 100644 --- a/src/Composer/Package/Loader/ValidatingArrayLoader.php +++ b/src/Composer/Package/Loader/ValidatingArrayLoader.php @@ -195,7 +195,9 @@ class ValidatingArrayLoader implements LoaderInterface foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) { if ($this->validateArray($linkType) && isset($this->config[$linkType])) { foreach ($this->config[$linkType] as $package => $constraint) { - if (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) { + if ($err = self::hasPackageNamingError($package, true)) { + $this->warnings[] = 'Deprecation warning: '.$linkType.'.'.$err.' Make sure you fix this as Composer 2.0 will error.'; + } elseif (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) { $this->warnings[] = $linkType.'.'.$package.' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]'; } if (!is_string($constraint)) { From 5d14a95543d12436f3962b32357bafb6ae4bac8b Mon Sep 17 00:00:00 2001 From: Patrick Reimers Date: Fri, 1 Mar 2019 20:11:20 +0100 Subject: [PATCH 02/48] Add test for warning on deprecated naming --- .../Package/Loader/ValidatingArrayLoaderTest.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php b/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php index ebe6871fe..6de6d45fa 100644 --- a/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php +++ b/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php @@ -337,6 +337,18 @@ class ValidatingArrayLoaderTest extends TestCase ), false, ), + array( + array( + 'name' => 'foo/bar', + 'require' => array( + 'Foo/Baz' => '^1.0', + ), + ), + array( + 'Deprecation warning: require.Foo/Baz is invalid, it should not contain uppercase characters. Please use foo/baz instead. Make sure you fix this as Composer 2.0 will error.', + ), + false, + ), array( array( 'name' => 'foo/bar', From 8ae8d131d5c8635a6bd34063adfd340e29e3a158 Mon Sep 17 00:00:00 2001 From: Patrick Reimers Date: Tue, 5 Mar 2019 10:44:55 +0100 Subject: [PATCH 03/48] Add deprecation warning for name attribute --- src/Composer/Package/Loader/ValidatingArrayLoader.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Composer/Package/Loader/ValidatingArrayLoader.php b/src/Composer/Package/Loader/ValidatingArrayLoader.php index a8aa65331..43f23236b 100644 --- a/src/Composer/Package/Loader/ValidatingArrayLoader.php +++ b/src/Composer/Package/Loader/ValidatingArrayLoader.php @@ -49,6 +49,10 @@ class ValidatingArrayLoader implements LoaderInterface $this->warnings = array(); $this->config = $config; + if ($err = self::hasPackageNamingError($config['name'])) { + $this->warnings[] = 'Deprecation warning: Your package name '.$err.' Make sure you fix this as Composer 2.0 will error.'; + } + if ($this->strictName) { $this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true); } else { From dd1e80a38f7bb1ce759c127ec405a65f8d97c388 Mon Sep 17 00:00:00 2001 From: Patrick Reimers Date: Tue, 5 Mar 2019 10:53:43 +0100 Subject: [PATCH 04/48] Add tests for wrong package name. --- .../Loader/ValidatingArrayLoaderTest.php | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php b/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php index 6de6d45fa..2fc059f3c 100644 --- a/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php +++ b/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php @@ -298,6 +298,30 @@ class ValidatingArrayLoaderTest extends TestCase 'homepage : invalid value (foo:bar), must be an http/https URL', ), ), + array( + array( + 'name' => 'foo/bar.json', + ), + array( + 'Deprecation warning: Your package name foo/bar.json is invalid, package names can not end in .json, consider renaming it or perhaps using a -json suffix instead. Make sure you fix this as Composer 2.0 will error.', + ), + ), + array( + array( + 'name' => 'com1/foo', + ), + array( + 'Deprecation warning: Your package name com1/foo is reserved, package and vendor names can not match any of: nul, con, prn, aux, com1, com2, com3, com4, com5, com6, com7, com8, com9, lpt1, lpt2, lpt3, lpt4, lpt5, lpt6, lpt7, lpt8, lpt9. Make sure you fix this as Composer 2.0 will error.', + ), + ), + array( + array( + 'name' => 'Foo/Bar', + ), + array( + 'Deprecation warning: Your package name Foo/Bar is invalid, it should not contain uppercase characters. We suggest using foo/bar instead. Make sure you fix this as Composer 2.0 will error.', + ), + ), array( array( 'name' => 'foo/bar', From 88852fbf1adfc1ffeb91e2db7cbbe1aa7f0321f9 Mon Sep 17 00:00:00 2001 From: Jim Birch <5177009+thejimbirch@users.noreply.github.com> Date: Mon, 1 Apr 2019 09:04:32 -0400 Subject: [PATCH 05/48] Updates typo: nother-feature to another-feature --- 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 c1fb25551..e3da6c8ec 100644 --- a/doc/articles/versions.md +++ b/doc/articles/versions.md @@ -32,7 +32,7 @@ repository:* v1 v2 my-feature -nother-feature +another-feature ~/my-library$ git tag v1.0 From 971528916b5c955066a7bc677d94032fd4c99298 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Wed, 3 Apr 2019 10:33:58 +0200 Subject: [PATCH 06/48] fix regex for heredoc/nowdoc * take into account relaxed changes introduced in php 7.3 * see: https://github.com/php/php-src/commit/4887357269107ed669463c4b95bd755fbbb52490 * allow " as well as ', which was introduced in php 5.3 closes #8080 --- src/Composer/Autoload/ClassMapGenerator.php | 2 +- .../Test/Autoload/Fixtures/classmap/StripNoise.php | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Composer/Autoload/ClassMapGenerator.php b/src/Composer/Autoload/ClassMapGenerator.php index 5d937433b..f3245bca6 100644 --- a/src/Composer/Autoload/ClassMapGenerator.php +++ b/src/Composer/Autoload/ClassMapGenerator.php @@ -162,7 +162,7 @@ class ClassMapGenerator } // strip heredocs/nowdocs - $contents = preg_replace('{<<<\s*(\'?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\2(?=\r\n|\n|\r|;)}s', 'null', $contents); + $contents = preg_replace('{<<<\s*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r|\s*)\\2(?=\r\n|\n|\r|\s|;)}s', 'null', $contents); // strip strings $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents); // strip leading non-php code if needed diff --git a/tests/Composer/Test/Autoload/Fixtures/classmap/StripNoise.php b/tests/Composer/Test/Autoload/Fixtures/classmap/StripNoise.php index 4c344089b..3806791e3 100644 --- a/tests/Composer/Test/Autoload/Fixtures/classmap/StripNoise.php +++ b/tests/Composer/Test/Autoload/Fixtures/classmap/StripNoise.php @@ -33,12 +33,18 @@ class Fail5 } ANOTHER -. <<< 'ONEMORE' +. <<< "ONEMORE" class Fail6 { } -ONEMORE; +ONEMORE +. << Date: Wed, 3 Apr 2019 11:38:06 +0200 Subject: [PATCH 07/48] expand regex and testcases --- src/Composer/Autoload/ClassMapGenerator.php | 2 +- .../Autoload/Fixtures/classmap/StripNoise.php | 91 +++++++++++++------ 2 files changed, 63 insertions(+), 30 deletions(-) diff --git a/src/Composer/Autoload/ClassMapGenerator.php b/src/Composer/Autoload/ClassMapGenerator.php index f3245bca6..b7a3902df 100644 --- a/src/Composer/Autoload/ClassMapGenerator.php +++ b/src/Composer/Autoload/ClassMapGenerator.php @@ -162,7 +162,7 @@ class ClassMapGenerator } // strip heredocs/nowdocs - $contents = preg_replace('{<<<\s*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r|\s*)\\2(?=\r\n|\n|\r|\s|;)}s', 'null', $contents); + $contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\s+)\\2(?=\s+|[;,.)])}s', 'null', $contents); // strip strings $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents); // strip leading non-php code if needed diff --git a/tests/Composer/Test/Autoload/Fixtures/classmap/StripNoise.php b/tests/Composer/Test/Autoload/Fixtures/classmap/StripNoise.php index 3806791e3..8944360ee 100644 --- a/tests/Composer/Test/Autoload/Fixtures/classmap/StripNoise.php +++ b/tests/Composer/Test/Autoload/Fixtures/classmap/StripNoise.php @@ -7,48 +7,81 @@ namespace Foo; */ class StripNoise { - public function test() + public function test_heredoc() { - return <<'; + } + + public function test_simple_string() + { + return 'class FailSimpleString {}'; } } From 4ea8e48bf8830a83defcf31923cef95c89f66391 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Thu, 4 Apr 2019 08:45:08 +0200 Subject: [PATCH 08/48] leading whitespace is optional, but newline is not --- src/Composer/Autoload/ClassMapGenerator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Autoload/ClassMapGenerator.php b/src/Composer/Autoload/ClassMapGenerator.php index b7a3902df..1ecf96bfe 100644 --- a/src/Composer/Autoload/ClassMapGenerator.php +++ b/src/Composer/Autoload/ClassMapGenerator.php @@ -162,7 +162,7 @@ class ClassMapGenerator } // strip heredocs/nowdocs - $contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\s+)\\2(?=\s+|[;,.)])}s', 'null', $contents); + $contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)(?:\s*)\\2(?=\s+|[;,.)])}s', 'null', $contents); // strip strings $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents); // strip leading non-php code if needed From 043b33ed382b6232f8451a85ff1ab415c5a4e5eb Mon Sep 17 00:00:00 2001 From: Dane Powell Date: Sat, 6 Apr 2019 08:44:23 -0700 Subject: [PATCH 09/48] Fixes #8065: Sort plugins deterministically before loading. --- src/Composer/Autoload/AutoloadGenerator.php | 3 ++- src/Composer/Plugin/PluginManager.php | 11 ++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 7ea1a3444..2d4c481b1 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -28,6 +28,7 @@ use Composer\Script\ScriptEvents; */ class AutoloadGenerator { + /** * @var EventDispatcher */ @@ -959,7 +960,7 @@ INITIALIZER; * @param array $packageMap * @return array */ - protected function sortPackageMap(array $packageMap) + public function sortPackageMap(array $packageMap) { $packages = array(); $paths = array(); diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index e8f4b58c3..da9fb5c20 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -15,10 +15,10 @@ namespace Composer\Plugin; use Composer\Composer; use Composer\EventDispatcher\EventSubscriberInterface; use Composer\IO\IOInterface; +use Composer\Package\CompletePackage; use Composer\Package\Package; use Composer\Package\Version\VersionParser; use Composer\Repository\RepositoryInterface; -use Composer\Package\AliasPackage; use Composer\Package\PackageInterface; use Composer\Package\Link; use Composer\Semver\Constraint\Constraint; @@ -253,8 +253,13 @@ class PluginManager */ private function loadRepository(RepositoryInterface $repo) { - foreach ($repo->getPackages() as $package) { /** @var PackageInterface $package */ - if ($package instanceof AliasPackage) { + $packages = $repo->getPackages(); + $generator = $this->composer->getAutoloadGenerator(); + $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $this->composer->getPackage(), $packages); + $sortedPackageMap = array_reverse($generator->sortPackageMap($packageMap)); + foreach ($sortedPackageMap as $fullPackage) { + $package = $fullPackage[0]; /** @var PackageInterface $package */ + if (!($package instanceof CompletePackage)) { continue; } if ('composer-plugin' === $package->getType()) { From 3e6300b5e810aada05581769f25c07f30f1f5a75 Mon Sep 17 00:00:00 2001 From: Dane Powell Date: Sat, 6 Apr 2019 08:49:45 -0700 Subject: [PATCH 10/48] code style fix. --- src/Composer/Autoload/AutoloadGenerator.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 2d4c481b1..272c6b920 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -28,7 +28,6 @@ use Composer\Script\ScriptEvents; */ class AutoloadGenerator { - /** * @var EventDispatcher */ From a908e22a91895fc63cfa173667ef395b3b6f5447 Mon Sep 17 00:00:00 2001 From: Dane Powell Date: Sat, 6 Apr 2019 08:53:32 -0700 Subject: [PATCH 11/48] Fixed code style issues. --- src/Composer/Plugin/PluginManager.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index da9fb5c20..cca4efe54 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -255,7 +255,8 @@ class PluginManager { $packages = $repo->getPackages(); $generator = $this->composer->getAutoloadGenerator(); - $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $this->composer->getPackage(), $packages); + $rootPackage = $this->composer->getPackage(); /** @var PackageInterface $rootPackage */ + $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $rootPackage, $packages); $sortedPackageMap = array_reverse($generator->sortPackageMap($packageMap)); foreach ($sortedPackageMap as $fullPackage) { $package = $fullPackage[0]; /** @var PackageInterface $package */ From 5633a68689a9653dc04a81bd06a37fa83e3a9c17 Mon Sep 17 00:00:00 2001 From: Kevin Boyd Date: Mon, 8 Apr 2019 22:44:08 -0700 Subject: [PATCH 12/48] Add a helper to disable process timeouts The helper can be included in custom script definitions by calling "Composer\\Config::disableProcessTimeout". Example: { "scripts": { "watch": [ "Composer\\Config::disableProcessTimeout", "vendor/bin/long-running-script --watch" ] } } --- src/Composer/Config.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/Composer/Config.php b/src/Composer/Config.php index 4d8199ccc..7abca7dfa 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -16,6 +16,7 @@ use Composer\Config\ConfigSourceInterface; use Composer\Downloader\TransportException; use Composer\IO\IOInterface; use Composer\Util\Platform; +use Composer\Util\ProcessExecutor; /** * @author Jordi Boggiano @@ -459,4 +460,20 @@ class Config } } } + + /** + * Used by long-running custom scripts in composer.json + * + * "scripts": { + * "watch": [ + * "Composer\\Config::disableProcessTimeout", + * "vendor/bin/long-running-script --watch" + * ] + * } + */ + public static function disableProcessTimeout() + { + // Override global timeout set earlier by environment or config + ProcessExecutor::setTimeout(0); + } } From 17810b2621cea5f09436a395ed630fb29a6928e7 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 9 Apr 2019 12:47:24 +0200 Subject: [PATCH 13/48] Revert composer.json changes if update process throws, fixes #8062 --- src/Composer/Command/RequireCommand.php | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Composer/Command/RequireCommand.php b/src/Composer/Command/RequireCommand.php index 4cad91023..508514eb4 100644 --- a/src/Composer/Command/RequireCommand.php +++ b/src/Composer/Command/RequireCommand.php @@ -25,6 +25,7 @@ use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; +use Composer\IO\IOInterface; /** * @author Jérémy Romey @@ -160,16 +161,27 @@ EOT if ($input->getOption('no-update')) { return 0; } - $updateDevMode = !$input->getOption('update-no-dev'); - $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader'); - $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative'); - $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader'); + try { + return $this->doUpdate($input, $output, $io, $requirements); + } catch (\Exception $e) { + $this->revertComposerFile(false); + throw $e; + } + } + + private function doUpdate(InputInterface $input, OutputInterface $output, IOInterface $io, array $requirements) + { // Update packages $this->resetComposer(); $composer = $this->getComposer(true, $input->getOption('no-plugins')); $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress')); + $updateDevMode = !$input->getOption('update-no-dev'); + $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader'); + $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative'); + $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader'); + $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); From 12e683e2ee74ace0d3843307843762f4a8186d5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Mon, 25 Mar 2019 12:12:32 +0200 Subject: [PATCH 14/48] ext-imagick: support version string from ImageMagick 6.x --- src/Composer/Repository/PlatformRepository.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Composer/Repository/PlatformRepository.php b/src/Composer/Repository/PlatformRepository.php index 50cbb4649..3126f860a 100644 --- a/src/Composer/Repository/PlatformRepository.php +++ b/src/Composer/Repository/PlatformRepository.php @@ -166,8 +166,14 @@ class PlatformRepository extends ArrayRepository case 'imagick': $imagick = new \Imagick(); $imageMagickVersion = $imagick->getVersion(); - preg_match('/^ImageMagick ([\d.]+)-(\d+)/', $imageMagickVersion['versionString'], $matches); - $prettyVersion = "{$matches[1]}.{$matches[2]}"; + // 6.x: ImageMagick 6.2.9 08/24/06 Q16 http://www.imagemagick.org + // 7.x: ImageMagick 7.0.8-34 Q16 x86_64 2019-03-23 https://imagemagick.org + preg_match('/^ImageMagick ([\d.]+)(?:-(\d+))?/', $imageMagickVersion['versionString'], $matches); + if (isset($matches[2])) { + $prettyVersion = "{$matches[1]}.{$matches[2]}"; + } else { + $prettyVersion = $matches[1]; + } break; case 'libxml': From d2ab4f66fd79e9f3fe906a8c8b2c8c183819b27a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=BCrth?= Date: Thu, 21 Mar 2019 19:17:55 +0100 Subject: [PATCH 15/48] Extract job packageName & constraint to variables --- src/Composer/DependencyResolver/Problem.php | 67 +++++++++++---------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/src/Composer/DependencyResolver/Problem.php b/src/Composer/DependencyResolver/Problem.php index 0dcc938fd..bb497b549 100644 --- a/src/Composer/DependencyResolver/Problem.php +++ b/src/Composer/DependencyResolver/Problem.php @@ -81,8 +81,11 @@ class Problem $job = $reason['job']; - if (isset($job['constraint'])) { - $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']); + $packageName = $job['packageName']; + $constraint = $job['constraint']; + + if (isset($constraint)) { + $packages = $this->pool->whatProvides($packageName, $constraint); } else { $packages = array(); } @@ -90,9 +93,9 @@ class Problem if ($job && $job['cmd'] === 'install' && empty($packages)) { // handle php/hhvm - if ($job['packageName'] === 'php' || $job['packageName'] === 'php-64bit' || $job['packageName'] === 'hhvm') { + if ($packageName === 'php' || $packageName === 'php-64bit' || $packageName === 'hhvm') { $version = phpversion(); - $available = $this->pool->whatProvides($job['packageName']); + $available = $this->pool->whatProvides($packageName); if (count($available)) { $firstAvailable = reset($available); @@ -103,13 +106,13 @@ class Problem } } - $msg = "\n - This package requires ".$job['packageName'].$this->constraintToText($job['constraint']).' but '; + $msg = "\n - This package requires ".$packageName.$this->constraintToText($constraint).' but '; if (defined('HHVM_VERSION') || count($available)) { return $msg . 'your HHVM version does not satisfy that requirement.'; } - if ($job['packageName'] === 'hhvm') { + if ($packageName === 'hhvm') { return $msg . 'you are running this with PHP and not HHVM.'; } @@ -117,43 +120,43 @@ class Problem } // handle php extensions - if (0 === stripos($job['packageName'], 'ext-')) { - if (false !== strpos($job['packageName'], ' ')) { - return "\n - The requested PHP extension ".$job['packageName'].' should be required as '.str_replace(' ', '-', $job['packageName']).'.'; + if (0 === stripos($packageName, 'ext-')) { + if (false !== strpos($packageName, ' ')) { + return "\n - The requested PHP extension ".$packageName.' should be required as '.str_replace(' ', '-', $packageName).'.'; } - $ext = substr($job['packageName'], 4); + $ext = substr($packageName, 4); $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system'; - return "\n - The requested PHP extension ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.'; + return "\n - The requested PHP extension ".$packageName.$this->constraintToText($constraint).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.'; } // handle linked libs - if (0 === stripos($job['packageName'], 'lib-')) { - if (strtolower($job['packageName']) === 'lib-icu') { + if (0 === stripos($packageName, 'lib-')) { + if (strtolower($packageName) === 'lib-icu') { $error = extension_loaded('intl') ? 'has the wrong version installed, try upgrading the intl extension.' : 'is missing from your system, make sure the intl extension is loaded.'; - return "\n - The requested linked library ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error; + return "\n - The requested linked library ".$packageName.$this->constraintToText($constraint).' '.$error; } - return "\n - The requested linked library ".$job['packageName'].$this->constraintToText($job['constraint']).' has the wrong version installed or is missing from your system, make sure to load the extension providing it.'; + return "\n - The requested linked library ".$packageName.$this->constraintToText($constraint).' has the wrong version installed or is missing from your system, make sure to load the extension providing it.'; } - if (!preg_match('{^[A-Za-z0-9_./-]+$}', $job['packageName'])) { - $illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $job['packageName']); + if (!preg_match('{^[A-Za-z0-9_./-]+$}', $packageName)) { + $illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $packageName); - return "\n - The requested package ".$job['packageName'].' could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.'; + return "\n - The requested package ".$packageName.' could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.'; } - if ($providers = $this->pool->whatProvides($job['packageName'], $job['constraint'], true, true)) { - return "\n - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' is satisfiable by '.$this->getPackageList($providers).' but these conflict with your requirements or minimum-stability.'; + if ($providers = $this->pool->whatProvides($packageName, $constraint, true, true)) { + return "\n - The requested package ".$packageName.$this->constraintToText($constraint).' is satisfiable by '.$this->getPackageList($providers).' but these conflict with your requirements or minimum-stability.'; } - if ($providers = $this->pool->whatProvides($job['packageName'], null, true, true)) { - return "\n - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.'; + if ($providers = $this->pool->whatProvides($packageName, null, true, true)) { + return "\n - The requested package ".$packageName.$this->constraintToText($constraint).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.'; } - return "\n - The requested package ".$job['packageName'].' could not be found in any version, there may be a typo in the package name.'; + return "\n - The requested package ".$packageName.' could not be found in any version, there may be a typo in the package name.'; } } @@ -202,27 +205,29 @@ class Problem */ protected function jobToText($job) { + $packageName = $job['packageName']; + $constraint = $job['constraint']; switch ($job['cmd']) { case 'install': - $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']); + $packages = $this->pool->whatProvides($packageName, $constraint); if (!$packages) { - return 'No package found to satisfy install request for '.$job['packageName'].$this->constraintToText($job['constraint']); + return 'No package found to satisfy install request for '.$packageName.$this->constraintToText($constraint); } - return 'Installation request for '.$job['packageName'].$this->constraintToText($job['constraint']).' -> satisfiable by '.$this->getPackageList($packages).'.'; + return 'Installation request for '.$packageName.$this->constraintToText($constraint).' -> satisfiable by '.$this->getPackageList($packages).'.'; case 'update': - return 'Update request for '.$job['packageName'].$this->constraintToText($job['constraint']).'.'; + return 'Update request for '.$packageName.$this->constraintToText($constraint).'.'; case 'remove': - return 'Removal request for '.$job['packageName'].$this->constraintToText($job['constraint']).''; + return 'Removal request for '.$packageName.$this->constraintToText($constraint).''; } - if (isset($job['constraint'])) { - $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']); + if (isset($constraint)) { + $packages = $this->pool->whatProvides($packageName, $constraint); } else { $packages = array(); } - return 'Job(cmd='.$job['cmd'].', target='.$job['packageName'].', packages=['.$this->getPackageList($packages).'])'; + return 'Job(cmd='.$job['cmd'].', target='.$packageName.', packages=['.$this->getPackageList($packages).'])'; } protected function getPackageList($packages) From 974a3305ae0f3703c81927dc650b66d823fbf538 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 9 Apr 2019 17:41:09 +0200 Subject: [PATCH 16/48] Update changelog --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36ceddfc9..c079b6922 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +### [1.8.5] 2019-04-09 + + * HHVM 4.0 is no longer compatible with Composer. Please use PHP instead going forward. + * Added forward compatibility with upcoming 2.0 changes + * Fixed support for PHP 7.3-style heredoc/nowdoc syntax changes in autoload generation + * Fixed require command usage when combined with --ignore-platform-reqs + * Fixed and cleaned up various Windows junctions handling issues + ### [1.8.4] 2019-02-11 * Fixed long standing solver bug leading to odd solving issues in edge cases, see #7946 @@ -737,6 +745,7 @@ * Initial release +[1.8.5]: https://github.com/composer/composer/compare/1.8.4...1.8.5 [1.8.4]: https://github.com/composer/composer/compare/1.8.3...1.8.4 [1.8.3]: https://github.com/composer/composer/compare/1.8.2...1.8.3 [1.8.2]: https://github.com/composer/composer/compare/1.8.1...1.8.2 From de0251953d6196a5931fc991d9e2a595d20ac46c Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 9 Apr 2019 17:46:33 +0200 Subject: [PATCH 17/48] Update composer deps --- composer.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/composer.lock b/composer.lock index 05df052f8..849e32752 100644 --- a/composer.lock +++ b/composer.lock @@ -64,16 +64,16 @@ }, { "name": "composer/semver", - "version": "1.4.2", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" + "reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", - "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", + "url": "https://api.github.com/repos/composer/semver/zipball/46d9139568ccb8d9e7cdd4539cab7347568a5e2e", + "reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e", "shasum": "" }, "require": { @@ -122,28 +122,27 @@ "validation", "versioning" ], - "time": "2016-08-30T16:08:34+00:00" + "time": "2019-03-19T17:25:45+00:00" }, { "name": "composer/spdx-licenses", - "version": "1.5.0", + "version": "1.5.1", "source": { "type": "git", "url": "https://github.com/composer/spdx-licenses.git", - "reference": "7a9556b22bd9d4df7cad89876b00af58ef20d3a2" + "reference": "a1aa51cf3ab838b83b0867b14e56fc20fbd55b3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/7a9556b22bd9d4df7cad89876b00af58ef20d3a2", - "reference": "7a9556b22bd9d4df7cad89876b00af58ef20d3a2", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/a1aa51cf3ab838b83b0867b14e56fc20fbd55b3d", + "reference": "a1aa51cf3ab838b83b0867b14e56fc20fbd55b3d", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0" + "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5", - "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" + "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 7" }, "type": "library", "extra": { @@ -183,7 +182,7 @@ "spdx", "validator" ], - "time": "2018-11-01T09:45:54+00:00" + "time": "2019-03-26T10:23:26+00:00" }, { "name": "composer/xdebug-handler", @@ -1360,6 +1359,7 @@ "mock", "xunit" ], + "abandoned": true, "time": "2015-10-02T06:51:40+00:00" }, { From 266a41e0464c8ccf23949e3794189dc4ccf3caba Mon Sep 17 00:00:00 2001 From: Dane Powell Date: Tue, 9 Apr 2019 10:55:33 -0700 Subject: [PATCH 18/48] Refactor sortPackageMap to depend on separate sortPackage function. --- src/Composer/Autoload/AutoloadGenerator.php | 54 +++++++++++++++------ src/Composer/Plugin/PluginManager.php | 7 +-- src/Composer/Util/PackageSorter.php | 10 ++++ 3 files changed, 51 insertions(+), 20 deletions(-) create mode 100644 src/Composer/Util/PackageSorter.php diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 272c6b920..6fc602429 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -17,6 +17,7 @@ use Composer\EventDispatcher\EventDispatcher; use Composer\Installer\InstallationManager; use Composer\IO\IOInterface; use Composer\Package\AliasPackage; +use Composer\Package\Link; use Composer\Package\PackageInterface; use Composer\Repository\InstalledRepositoryInterface; use Composer\Util\Filesystem; @@ -956,27 +957,18 @@ INITIALIZER; * * Packages of equal weight retain the original order * - * @param array $packageMap + * @param array $packages * @return array */ - public function sortPackageMap(array $packageMap) - { - $packages = array(); - $paths = array(); + public function sortPackages(array $packages) { $usageList = array(); - foreach ($packageMap as $item) { - list($package, $path) = $item; - $name = $package->getName(); - $packages[$name] = $package; - $paths[$name] = $path; - - foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) { + foreach ($packages as $package) { /** @var PackageInterface $package */ + foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) { /** @var Link $link */ $target = $link->getTarget(); - $usageList[$target][] = $name; + $usageList[$target][] = $package->getName(); } } - $computing = array(); $computed = array(); $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) { @@ -1034,9 +1026,41 @@ INITIALIZER; $stable_sort($weightList); - $sortedPackageMap = array(); + $sortedPackages = array(); foreach (array_keys($weightList) as $name) { + $sortedPackages[] = $packages[$name]; + } + return $sortedPackages; + } + + /** + * Sorts packages by dependency weight + * + * Packages of equal weight retain the original order + * + * @param array $packageMap + * @return array + */ + public function sortPackageMap(array $packageMap) + { + $packages = array(); + $paths = array(); + + foreach ($packageMap as $item) { + list($package, $path) = $item; + $name = $package->getName(); + $packages[$name] = $package; + $paths[$name] = $path; + } + + $sortedPackages = $this->sortPackages($packages); + + + $sortedPackageMap = array(); + + foreach ($sortedPackages as $package) { + $name = $package->getName(); $sortedPackageMap[] = array($packages[$name], $paths[$name]); } diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index cca4efe54..3810992d0 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -255,11 +255,8 @@ class PluginManager { $packages = $repo->getPackages(); $generator = $this->composer->getAutoloadGenerator(); - $rootPackage = $this->composer->getPackage(); /** @var PackageInterface $rootPackage */ - $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $rootPackage, $packages); - $sortedPackageMap = array_reverse($generator->sortPackageMap($packageMap)); - foreach ($sortedPackageMap as $fullPackage) { - $package = $fullPackage[0]; /** @var PackageInterface $package */ + $sortedPackages = array_reverse($generator->sortPackages($packages)); + foreach ($sortedPackages as $package) { if (!($package instanceof CompletePackage)) { continue; } diff --git a/src/Composer/Util/PackageSorter.php b/src/Composer/Util/PackageSorter.php new file mode 100644 index 000000000..2899fc959 --- /dev/null +++ b/src/Composer/Util/PackageSorter.php @@ -0,0 +1,10 @@ + Date: Tue, 9 Apr 2019 10:58:36 -0700 Subject: [PATCH 19/48] Move sortPackages to static helper class. --- src/Composer/Autoload/AutoloadGenerator.php | 86 +-------------------- src/Composer/Plugin/PluginManager.php | 4 +- src/Composer/Util/PackageSorter.php | 82 ++++++++++++++++++++ 3 files changed, 86 insertions(+), 86 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 6fc602429..5637157e1 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -17,11 +17,11 @@ use Composer\EventDispatcher\EventDispatcher; use Composer\Installer\InstallationManager; use Composer\IO\IOInterface; use Composer\Package\AliasPackage; -use Composer\Package\Link; use Composer\Package\PackageInterface; use Composer\Repository\InstalledRepositoryInterface; use Composer\Util\Filesystem; use Composer\Script\ScriptEvents; +use Composer\Util\PackageSorter; /** * @author Igor Wiedler @@ -952,88 +952,6 @@ INITIALIZER; ); } - /** - * Sorts packages by dependency weight - * - * Packages of equal weight retain the original order - * - * @param array $packages - * @return array - */ - public function sortPackages(array $packages) { - $usageList = array(); - - foreach ($packages as $package) { /** @var PackageInterface $package */ - foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) { /** @var Link $link */ - $target = $link->getTarget(); - $usageList[$target][] = $package->getName(); - } - } - $computing = array(); - $computed = array(); - $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) { - // reusing computed importance - if (isset($computed[$name])) { - return $computed[$name]; - } - - // canceling circular dependency - if (isset($computing[$name])) { - return 0; - } - - $computing[$name] = true; - $weight = 0; - - if (isset($usageList[$name])) { - foreach ($usageList[$name] as $user) { - $weight -= 1 - $computeImportance($user); - } - } - - unset($computing[$name]); - $computed[$name] = $weight; - - return $weight; - }; - - $weightList = array(); - - foreach ($packages as $name => $package) { - $weight = $computeImportance($name); - $weightList[$name] = $weight; - } - - $stable_sort = function (&$array) { - static $transform, $restore; - - $i = 0; - - if (!$transform) { - $transform = function (&$v, $k) use (&$i) { - $v = array($v, ++$i, $k, $v); - }; - - $restore = function (&$v, $k) { - $v = $v[3]; - }; - } - - array_walk($array, $transform); - asort($array); - array_walk($array, $restore); - }; - - $stable_sort($weightList); - - $sortedPackages = array(); - - foreach (array_keys($weightList) as $name) { - $sortedPackages[] = $packages[$name]; - } - return $sortedPackages; - } - /** * Sorts packages by dependency weight * @@ -1054,7 +972,7 @@ INITIALIZER; $paths[$name] = $path; } - $sortedPackages = $this->sortPackages($packages); + $sortedPackages = PackageSorter::sortPackages($packages); $sortedPackageMap = array(); diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index 3810992d0..bb9b66d83 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -24,6 +24,7 @@ use Composer\Package\Link; use Composer\Semver\Constraint\Constraint; use Composer\DependencyResolver\Pool; use Composer\Plugin\Capability\Capability; +use Composer\Util\PackageSorter; /** * Plugin manager @@ -254,8 +255,7 @@ class PluginManager private function loadRepository(RepositoryInterface $repo) { $packages = $repo->getPackages(); - $generator = $this->composer->getAutoloadGenerator(); - $sortedPackages = array_reverse($generator->sortPackages($packages)); + $sortedPackages = array_reverse(PackageSorter::sortPackages($packages)); foreach ($sortedPackages as $package) { if (!($package instanceof CompletePackage)) { continue; diff --git a/src/Composer/Util/PackageSorter.php b/src/Composer/Util/PackageSorter.php index 2899fc959..8d8c9a06c 100644 --- a/src/Composer/Util/PackageSorter.php +++ b/src/Composer/Util/PackageSorter.php @@ -3,8 +3,90 @@ namespace Composer\Util; +use Composer\Package\Link; +use Composer\Package\PackageInterface; class PackageSorter { + /** + * Sorts packages by dependency weight + * + * Packages of equal weight retain the original order + * + * @param array $packages + * @return array + */ + public static function sortPackages(array $packages) { + $usageList = array(); + foreach ($packages as $package) { /** @var PackageInterface $package */ + foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) { /** @var Link $link */ + $target = $link->getTarget(); + $usageList[$target][] = $package->getName(); + } + } + $computing = array(); + $computed = array(); + $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) { + // reusing computed importance + if (isset($computed[$name])) { + return $computed[$name]; + } + + // canceling circular dependency + if (isset($computing[$name])) { + return 0; + } + + $computing[$name] = true; + $weight = 0; + + if (isset($usageList[$name])) { + foreach ($usageList[$name] as $user) { + $weight -= 1 - $computeImportance($user); + } + } + + unset($computing[$name]); + $computed[$name] = $weight; + + return $weight; + }; + + $weightList = array(); + + foreach ($packages as $name => $package) { + $weight = $computeImportance($name); + $weightList[$name] = $weight; + } + + $stable_sort = function (&$array) { + static $transform, $restore; + + $i = 0; + + if (!$transform) { + $transform = function (&$v, $k) use (&$i) { + $v = array($v, ++$i, $k, $v); + }; + + $restore = function (&$v) { + $v = $v[3]; + }; + } + + array_walk($array, $transform); + asort($array); + array_walk($array, $restore); + }; + + $stable_sort($weightList); + + $sortedPackages = array(); + + foreach (array_keys($weightList) as $name) { + $sortedPackages[] = $packages[$name]; + } + return $sortedPackages; + } } From 3501423eabe7348a6f0db9f547e7e211ff5a4210 Mon Sep 17 00:00:00 2001 From: Dane Powell Date: Tue, 9 Apr 2019 11:15:19 -0700 Subject: [PATCH 20/48] Undo previous change. --- 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 5637157e1..325fb2c87 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -960,7 +960,7 @@ INITIALIZER; * @param array $packageMap * @return array */ - public function sortPackageMap(array $packageMap) + protected function sortPackageMap(array $packageMap) { $packages = array(); $paths = array(); From dd40d74bf6041ddcefa1ebe46fb9117d031b1ccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=BCrth?= Date: Tue, 9 Apr 2019 18:28:45 +0200 Subject: [PATCH 21/48] Exclude more files from being exported --- .gitattributes | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitattributes b/.gitattributes index 32378b23e..51b431136 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10,3 +10,8 @@ # Exclude non-essential files from dist /tests export-ignore +.github export-ignore +.php_cs export-ignore +.travis.yml export-ignore +appveyor.yml export-ignore +phpunit.xml.dist export-ignore From a2b647a99eb92e123b7e36ab135baeb7b219207a Mon Sep 17 00:00:00 2001 From: ShiraNai7 Date: Thu, 11 Apr 2019 20:23:31 +0200 Subject: [PATCH 22/48] Handle absolute phar:// paths in autoload_static.php --- src/Composer/Autoload/AutoloadGenerator.php | 18 +++- .../Test/Autoload/AutoloadGeneratorTest.php | 41 +++++++++ .../Test/Autoload/Fixtures/autoload_phar.php | 13 +++ .../Autoload/Fixtures/autoload_phar_psr4.php | 13 +++ .../Fixtures/autoload_phar_static.php | 87 +++++++++++++++++++ 5 files changed, 168 insertions(+), 4 deletions(-) create mode 100644 tests/Composer/Test/Autoload/Fixtures/autoload_phar.php create mode 100644 tests/Composer/Test/Autoload/Fixtures/autoload_phar_psr4.php create mode 100644 tests/Composer/Test/Autoload/Fixtures/autoload_phar_static.php diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 7ea1a3444..4d04f7a2f 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -545,7 +545,7 @@ EOF; } } - if (preg_match('/\.phar.+$/', $path)) { + if (strpos($path, '.phar') !== false) { $baseDir = "'phar://' . " . $baseDir; } @@ -769,10 +769,14 @@ HEADER; $filesystem = new Filesystem(); $vendorPathCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/"; + $vendorPharPathCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/"; $appBaseDirCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/"; + $appBaseDirPharCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/"; $absoluteVendorPathCode = ' => ' . substr(var_export(rtrim($vendorDir, '\\/') . '/', true), 0, -1); + $absoluteVendorPharPathCode = ' => ' . substr(var_export(rtrim('phar://' . $vendorDir, '\\/') . '/', true), 0, -1); $absoluteAppBaseDirCode = ' => ' . substr(var_export(rtrim($baseDir, '\\/') . '/', true), 0, -1); + $absoluteAppBaseDirPharCode = ' => ' . substr(var_export(rtrim('phar://' . $baseDir, '\\/') . '/', true), 0, -1); $initializer = ''; $prefix = "\0Composer\Autoload\ClassLoader\0"; @@ -795,9 +799,15 @@ HEADER; // See https://bugs.php.net/68057 $staticPhpVersion = 70000; } - $value = var_export($value, true); - $value = str_replace($absoluteVendorPathCode, $vendorPathCode, $value); - $value = str_replace($absoluteAppBaseDirCode, $appBaseDirCode, $value); + $value = strtr( + var_export($value, true), + array( + $absoluteVendorPathCode => $vendorPathCode, + $absoluteVendorPharPathCode => $vendorPharPathCode, + $absoluteAppBaseDirCode => $appBaseDirCode, + $absoluteAppBaseDirPharCode => $appBaseDirPharCode, + ) + ); $value = ltrim(preg_replace('/^ */m', ' $0$0', $value)); $file .= sprintf(" public static $%s = %s;\n\n", $prop, $value); diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index c1605bf97..84ac16df7 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -486,6 +486,47 @@ class AutoloadGeneratorTest extends TestCase $this->assertFileExists($this->vendorDir.'/composer/autoload_classmap.php', "ClassMap file needs to be generated, even if empty."); } + public function testPharAutoload() + { + $package = new Package('a', '1.0', '1.0'); + $package->setRequires(array( + new Link('a', 'a/a'), + )); + + $package->setAutoload(array( + 'psr-0' => array( + 'Foo' => 'foo.phar', + 'Bar' => 'dir/bar.phar/src', + ), + 'psr-4' => array( + 'Baz\\' => 'baz.phar', + 'Qux\\' => 'dir/qux.phar/src', + ), + )); + + $vendorPackage = new Package('a/a', '1.0', '1.0'); + $vendorPackage->setAutoload(array( + 'psr-0' => array( + 'Lorem' => 'lorem.phar', + 'Ipsum' => 'dir/ipsum.phar/src', + ), + 'psr-4' => array( + 'Dolor\\' => 'dolor.phar', + 'Sit\\' => 'dir/sit.phar/src', + ), + )); + + $this->repository->expects($this->once()) + ->method('getCanonicalPackages') + ->will($this->returnValue(array($vendorPackage))); + + $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', true, 'Phar'); + + $this->assertAutoloadFiles('phar', $this->vendorDir . '/composer'); + $this->assertAutoloadFiles('phar_psr4', $this->vendorDir . '/composer', 'psr4'); + $this->assertAutoloadFiles('phar_static', $this->vendorDir . '/composer', 'static'); + } + public function testPSRToClassMapIgnoresNonExistingDir() { $package = new Package('a', '1.0', '1.0'); diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_phar.php b/tests/Composer/Test/Autoload/Fixtures/autoload_phar.php new file mode 100644 index 000000000..7654005f3 --- /dev/null +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_phar.php @@ -0,0 +1,13 @@ + array('phar://' . $vendorDir . '/a/a/lorem.phar'), + 'Ipsum' => array('phar://' . $vendorDir . '/a/a/dir/ipsum.phar/src'), + 'Foo' => array('phar://' . $baseDir . '/foo.phar'), + 'Bar' => array('phar://' . $baseDir . '/dir/bar.phar/src'), +); diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_phar_psr4.php b/tests/Composer/Test/Autoload/Fixtures/autoload_phar_psr4.php new file mode 100644 index 000000000..f6142a001 --- /dev/null +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_phar_psr4.php @@ -0,0 +1,13 @@ + array('phar://' . $vendorDir . '/a/a/dir/sit.phar/src'), + 'Qux\\' => array('phar://' . $baseDir . '/dir/qux.phar/src'), + 'Dolor\\' => array('phar://' . $vendorDir . '/a/a/dolor.phar'), + 'Baz\\' => array('phar://' . $baseDir . '/baz.phar'), +); diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_phar_static.php b/tests/Composer/Test/Autoload/Fixtures/autoload_phar_static.php new file mode 100644 index 000000000..486a5c0dc --- /dev/null +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_phar_static.php @@ -0,0 +1,87 @@ + + array ( + 'Sit\\' => 4, + ), + 'Q' => + array ( + 'Qux\\' => 4, + ), + 'D' => + array ( + 'Dolor\\' => 6, + ), + 'B' => + array ( + 'Baz\\' => 4, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'Sit\\' => + array ( + 0 => 'phar://' . __DIR__ . '/..' . '/a/a/dir/sit.phar/src', + ), + 'Qux\\' => + array ( + 0 => 'phar://' . __DIR__ . '/../..' . '/dir/qux.phar/src', + ), + 'Dolor\\' => + array ( + 0 => 'phar://' . __DIR__ . '/..' . '/a/a/dolor.phar', + ), + 'Baz\\' => + array ( + 0 => 'phar://' . __DIR__ . '/../..' . '/baz.phar', + ), + ); + + public static $prefixesPsr0 = array ( + 'L' => + array ( + 'Lorem' => + array ( + 0 => 'phar://' . __DIR__ . '/..' . '/a/a/lorem.phar', + ), + ), + 'I' => + array ( + 'Ipsum' => + array ( + 0 => 'phar://' . __DIR__ . '/..' . '/a/a/dir/ipsum.phar/src', + ), + ), + 'F' => + array ( + 'Foo' => + array ( + 0 => 'phar://' . __DIR__ . '/../..' . '/foo.phar', + ), + ), + 'B' => + array ( + 'Bar' => + array ( + 0 => 'phar://' . __DIR__ . '/../..' . '/dir/bar.phar/src', + ), + ), + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInitPhar::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInitPhar::$prefixDirsPsr4; + $loader->prefixesPsr0 = ComposerStaticInitPhar::$prefixesPsr0; + + }, null, ClassLoader::class); + } +} From 4e14ac7640eed7833b2aa780a84e5b068b465ecd Mon Sep 17 00:00:00 2001 From: Gregor Hyneck Date: Tue, 30 Apr 2019 13:46:17 +0200 Subject: [PATCH 23/48] Add documentation how to run plugins manually --- doc/articles/plugins.md | 5 +++++ doc/articles/scripts.md | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/articles/plugins.md b/doc/articles/plugins.md index 228cbac9e..86e24d87b 100644 --- a/doc/articles/plugins.md +++ b/doc/articles/plugins.md @@ -261,6 +261,11 @@ Now the `custom-plugin-command` is available alongside Composer commands. > _Composer commands are based on the [Symfony Console Component][10]._ +## Running plugins manually + +Plugins for an event can be run manually by the `run-script` command. This works the same way as +[running scripts manually](scripts.md#running-scripts-manually). + ## Using Plugins Plugin packages are automatically loaded as soon as they are installed and will diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index e0c27b10f..a3c3ab091 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -189,7 +189,7 @@ composer run-script [--dev] [--no-dev] script ``` For example `composer run-script post-install-cmd` will run any -**post-install-cmd** scripts that have been defined. +**post-install-cmd** scripts and [plugins](plugins.md) that have been defined. You can also give additional arguments to the script handler by appending `--` followed by the handler arguments. e.g. From e37ffb2a44df9cd8c7ab7c667a225a930db9698f Mon Sep 17 00:00:00 2001 From: Stephan Vock Date: Tue, 30 Apr 2019 16:38:03 +0100 Subject: [PATCH 24/48] Fix: Bitbucket getChangeDate throws exception for branches containing a slash --- src/Composer/Repository/Vcs/BitbucketDriver.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Composer/Repository/Vcs/BitbucketDriver.php b/src/Composer/Repository/Vcs/BitbucketDriver.php index 556ca5012..730edec3c 100644 --- a/src/Composer/Repository/Vcs/BitbucketDriver.php +++ b/src/Composer/Repository/Vcs/BitbucketDriver.php @@ -218,6 +218,13 @@ abstract class BitbucketDriver extends VcsDriver return $this->fallbackDriver->getChangeDate($identifier); } + if (strpos($identifier, '/') !== false) { + $branches = $this->getBranches(); + if (isset($branches[$identifier])) { + $identifier = $branches[$identifier]; + } + } + $resource = sprintf( 'https://api.bitbucket.org/2.0/repositories/%s/%s/commit/%s?fields=date', $this->owner, From 5d615a16d175fcbdb67a536ef9d6fc4e8a1f6f2b Mon Sep 17 00:00:00 2001 From: Kevin Boyd Date: Wed, 10 Apr 2019 10:44:35 -0700 Subject: [PATCH 25/48] Add documentation for Composer\\Config::disableProcessTimeout --- doc/06-config.md | 14 ++++++++++++++ doc/articles/scripts.md | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/doc/06-config.md b/doc/06-config.md index 87d73f8a1..f3afc4eb1 100644 --- a/doc/06-config.md +++ b/doc/06-config.md @@ -9,6 +9,20 @@ Defaults to `300`. The duration processes like git clones can run before Composer assumes they died out. You may need to make this higher if you have a slow connection or huge vendors. +To disable the process timeout on a custom command under `scripts`, a static +helper is available: + +```json +{ + "scripts": { + "test": [ + "Composer\\Config::disableProcessTimeout", + "phpunit" + ] + } +} +``` + ## use-include-path Defaults to `false`. If `true`, the Composer autoloader will also look for classes diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index e0c27b10f..52ed86073 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -221,6 +221,26 @@ to the `phpunit` script. > are easily accessible. In this example no matter if the `phpunit` binary is > actually in `vendor/bin/phpunit` or `bin/phpunit` it will be found and executed. +Although Composer is not intended to manage long-running processes and other +such aspects of PHP projects, it can sometimes be handy to disable the process +timeout on custom commands. This timeout defaults to 300 seconds and can be +overridden for all commands using the config key `process-timeout`, or for +specific commands using an argument to the `run-script` command. + +A static helper also exists that can disable the process timeout for a specific +script directly in composer.json: + +```json +{ + "scripts": { + "test": [ + "Composer\\Config::disableProcessTimeout", + "phpunit" + ] + } +} +``` + ## Referencing scripts To enable script re-use and avoid duplicates, you can call a script from another From 51753bc08ce443e42ec9893a2836a58b476b0653 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Wed, 8 May 2019 14:58:46 +0200 Subject: [PATCH 26/48] fixes #8131 --- src/Composer/Json/JsonManipulator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Json/JsonManipulator.php b/src/Composer/Json/JsonManipulator.php index 40c0c09a2..8fe6a9f0a 100644 --- a/src/Composer/Json/JsonManipulator.php +++ b/src/Composer/Json/JsonManipulator.php @@ -22,7 +22,7 @@ class JsonManipulator private static $DEFINES = '(?(DEFINE) (? -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? ) (? true | false | null ) - (? " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " ) + (? " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9A-Fa-f]{4} )* " ) (? \[ (?: (?&json) \s* (?: , (?&json) \s* )* )? \s* \] ) (? \s* (?&string) \s* : (?&json) \s* ) (? \{ (?: (?&pair) (?: , (?&pair) )* )? \s* \} ) From 080b0f27e9ac283345b6080ab0999ac49e3c24ac Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Wed, 8 May 2019 15:58:02 +0200 Subject: [PATCH 27/48] add missing testcase --- .../Test/Json/JsonManipulatorTest.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/Composer/Test/Json/JsonManipulatorTest.php b/tests/Composer/Test/Json/JsonManipulatorTest.php index 05de454ca..d8bc7c200 100644 --- a/tests/Composer/Test/Json/JsonManipulatorTest.php +++ b/tests/Composer/Test/Json/JsonManipulatorTest.php @@ -2374,6 +2374,26 @@ class JsonManipulatorTest extends TestCase "package/a": "*" } } +', $manipulator->getContents()); + } + + public function testEscapedUnicodeDoesNotCauseBacktrackLimitErrorGithubIssue8131() + { + $manipulator = new JsonManipulator('{ + "description": "Some U\u00F1icode", + "require": { + "foo/bar": "^1.0" + } +}'); + + $this->assertTrue($manipulator->addLink('require', 'foo/baz', '^1.0')); + $this->assertEquals('{ + "description": "Some U\u00F1icode", + "require": { + "foo/bar": "^1.0", + "foo/baz": "^1.0" + } +} ', $manipulator->getContents()); } } From 8288d2c456287d4ec2d746db1d285d6bd82d52ec Mon Sep 17 00:00:00 2001 From: Sam L Date: Wed, 1 May 2019 11:25:26 -0400 Subject: [PATCH 28/48] Display branches and tags if verbose is specified --- src/Composer/Repository/VcsRepository.php | 61 ++++++++++++----------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/src/Composer/Repository/VcsRepository.php b/src/Composer/Repository/VcsRepository.php index edd0dabf8..8d8bcbdca 100644 --- a/src/Composer/Repository/VcsRepository.php +++ b/src/Composer/Repository/VcsRepository.php @@ -30,7 +30,8 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt { protected $url; protected $packageName; - protected $verbose; + protected $isVerbose; + protected $isVeryVerbose; protected $io; protected $config; protected $versionParser; @@ -64,7 +65,8 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt $this->url = $repoConfig['url']; $this->io = $io; $this->type = isset($repoConfig['type']) ? $repoConfig['type'] : 'vcs'; - $this->verbose = $io->isVeryVerbose(); + $this->isVerbose = $io->isVerbose(); + $this->isVeryVerbose = $io->isVeryVerbose(); $this->config = $config; $this->repoConfig = $repoConfig; $this->versionCache = $versionCache; @@ -127,7 +129,8 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt { parent::initialize(); - $verbose = $this->verbose; + $isVerbose = $this->isVerbose; + $isVeryVerbose = $this->isVeryVerbose; $driver = $this->getDriver(); if (!$driver) { @@ -145,23 +148,23 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt $this->packageName = !empty($data['name']) ? $data['name'] : null; } } catch (\Exception $e) { - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError('Skipped parsing '.$driver->getRootIdentifier().', '.$e->getMessage().''); } } foreach ($driver->getTags() as $tag => $identifier) { $msg = 'Reading composer.json of ' . ($this->packageName ?: $this->url) . ' (' . $tag . ')'; - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError($msg); - } else { + } elseif ($isVerbose) { $this->io->overwriteError($msg, false); } // strip the release- prefix from tags if present $tag = str_replace('release-', '', $tag); - $cachedPackage = $this->getCachedPackageVersion($tag, $identifier, $verbose); + $cachedPackage = $this->getCachedPackageVersion($tag, $identifier, $isVerbose, $isVeryVerbose); if ($cachedPackage) { $this->addPackage($cachedPackage); @@ -173,7 +176,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt } if (!$parsedTag = $this->validateTag($tag)) { - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError('Skipped tag '.$tag.', invalid tag name'); } continue; @@ -181,7 +184,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt try { if (!$data = $driver->getComposerInformation($identifier)) { - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError('Skipped tag '.$tag.', no composer file'); } $this->emptyReferences[] = $identifier; @@ -203,7 +206,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt // broken package, version doesn't match tag if ($data['version_normalized'] !== $parsedTag) { - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError('Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json'); } continue; @@ -211,13 +214,13 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt $tagPackageName = isset($data['name']) ? $data['name'] : $this->packageName; if ($existingPackage = $this->findPackage($tagPackageName, $data['version_normalized'])) { - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError('Skipped tag '.$tag.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$data['version_normalized'].' internally'); } continue; } - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError('Importing tag '.$tag.' ('.$data['version_normalized'].')'); } @@ -226,35 +229,35 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt if ($e instanceof TransportException && $e->getCode() === 404) { $this->emptyReferences[] = $identifier; } - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError('Skipped tag '.$tag.', '.($e instanceof TransportException ? 'no composer file was found' : $e->getMessage()).''); } continue; } } - if (!$verbose) { + if (!$isVeryVerbose) { $this->io->overwriteError('', false); } $branches = $driver->getBranches(); foreach ($branches as $branch => $identifier) { $msg = 'Reading composer.json of ' . ($this->packageName ?: $this->url) . ' (' . $branch . ')'; - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError($msg); - } else { + } elseif ($isVerbose) { $this->io->overwriteError($msg, false); } if ($branch === 'trunk' && isset($branches['master'])) { - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError('Skipped branch '.$branch.', can not parse both master and trunk branches as they both resolve to 9999999-dev internally'); } continue; } if (!$parsedBranch = $this->validateBranch($branch)) { - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError('Skipped branch '.$branch.', invalid name'); } continue; @@ -268,7 +271,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt $version = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch); } - $cachedPackage = $this->getCachedPackageVersion($version, $identifier, $verbose); + $cachedPackage = $this->getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose); if ($cachedPackage) { $this->addPackage($cachedPackage); @@ -281,7 +284,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt try { if (!$data = $driver->getComposerInformation($identifier)) { - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError('Skipped branch '.$branch.', no composer file'); } $this->emptyReferences[] = $identifier; @@ -292,7 +295,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt $data['version'] = $version; $data['version_normalized'] = $parsedBranch; - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError('Importing branch '.$branch.' ('.$data['version'].')'); } @@ -306,12 +309,12 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt if ($e->getCode() === 404) { $this->emptyReferences[] = $identifier; } - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError('Skipped branch '.$branch.', no composer file was found'); } continue; } catch (\Exception $e) { - if (!$verbose) { + if (!$isVeryVerbose) { $this->io->writeError(''); } $this->branchErrorOccurred = true; @@ -322,7 +325,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt } $driver->cleanup(); - if (!$verbose) { + if (!$isVeryVerbose) { $this->io->overwriteError('', false); } @@ -367,7 +370,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt return false; } - private function getCachedPackageVersion($version, $identifier, $verbose) + private function getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose) { if (!$this->versionCache) { return; @@ -375,7 +378,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt $cachedPackage = $this->versionCache->getVersionPackage($version, $identifier); if ($cachedPackage === false) { - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError('Skipped '.$version.', no composer file (cached from ref '.$identifier.')'); } @@ -384,14 +387,14 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt if ($cachedPackage) { $msg = 'Found cached composer.json of ' . ($this->packageName ?: $this->url) . ' (' . $version . ')'; - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError($msg); - } else { + } elseif ($isVerbose) { $this->io->overwriteError($msg, false); } if ($existingPackage = $this->findPackage($cachedPackage['name'], $cachedPackage['version_normalized'])) { - if ($verbose) { + if ($isVeryVerbose) { $this->io->writeError('Skipped cached version '.$version.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$cachedPackage['version_normalized'].' internally'); } $cachedPackage = null; From c7519144105bf319fd7ce437f9733b3cdc443ce7 Mon Sep 17 00:00:00 2001 From: pfofi <7479939+pfofi@users.noreply.github.com> Date: Fri, 10 May 2019 13:55:31 +0200 Subject: [PATCH 29/48] Fix URL resolution for Composer repositories Composer was unable canonicalize URLs in non-HTTP(S) Composer repositories. For example it was not possible to use a `providers-url` in a repository loaded via the `file://` scheme. See also: #8115 --- .../Repository/ComposerRepository.php | 6 +- .../Repository/ComposerRepositoryTest.php | 67 +++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 38b865103..1b03885fe 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -562,7 +562,11 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito protected function canonicalizeUrl($url) { if ('/' === $url[0]) { - return preg_replace('{(https?://[^/]+).*}i', '$1' . $url, $this->url); + if (preg_match('{[^:]+://[^/]*}', $this->url, $matches)) { + return $matches[0] . $url; + } + + return $this->url; } return $url; diff --git a/tests/Composer/Test/Repository/ComposerRepositoryTest.php b/tests/Composer/Test/Repository/ComposerRepositoryTest.php index 3e29e8023..8e9216b35 100644 --- a/tests/Composer/Test/Repository/ComposerRepositoryTest.php +++ b/tests/Composer/Test/Repository/ComposerRepositoryTest.php @@ -204,4 +204,71 @@ class ComposerRepositoryTest extends TestCase $repository->search('foo', RepositoryInterface::SEARCH_FULLTEXT, 'library') ); } + + /** + * @dataProvider canonicalizeUrlProvider + * + * @param string $expected + * @param string $url + * @param string $repositoryUrl + */ + public function testCanonicalizeUrl($expected, $url, $repositoryUrl) + { + $repository = new ComposerRepository( + array('url' => $repositoryUrl), + new NullIO(), + FactoryMock::createConfig() + ); + + $object = new \ReflectionObject($repository); + + $method = $object->getMethod('canonicalizeUrl'); + $method->setAccessible(true); + + // ComposerRepository::__construct ensures that the repository URL has a + // protocol, so reset it here in order to test all cases. + $property = $object->getProperty('url'); + $property->setAccessible(true); + $property->setValue($repository, $repositoryUrl); + + $this->assertSame($expected, $method->invoke($repository, $url)); + } + + public function canonicalizeUrlProvider() + { + return array( + array( + 'https://example.org/path/to/file', + '/path/to/file', + 'https://example.org', + ), + array( + 'https://example.org/canonic_url', + 'https://example.org/canonic_url', + 'https://should-not-see-me.test', + ), + array( + 'file:///path/to/repository/file', + '/path/to/repository/file', + 'file:///path/to/repository', + ), + array( + // Assert that the repository URL is returned unchanged if it is + // not a URL. + // (Backward compatibility test) + 'invalid_repo_url', + '/path/to/file', + 'invalid_repo_url', + ), + array( + // Assert that URLs can contain sequences resembling pattern + // references as understood by preg_replace() without messing up + // the result. + // (Regression test) + 'https://example.org/path/to/unusual_$0_filename', + '/path/to/unusual_$0_filename', + 'https://example.org', + ), + ); + } } From e7f02be9ffec80384df5d49e463d9f127d6957bc Mon Sep 17 00:00:00 2001 From: pfofi <7479939+pfofi@users.noreply.github.com> Date: Sat, 11 May 2019 16:27:39 +0200 Subject: [PATCH 30/48] Anchor pattern --- 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 1b03885fe..8fc40c812 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -562,7 +562,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito protected function canonicalizeUrl($url) { if ('/' === $url[0]) { - if (preg_match('{[^:]+://[^/]*}', $this->url, $matches)) { + if (preg_match('{^[^:]+://[^/]*}', $this->url, $matches)) { return $matches[0] . $url; } From ce8afe1c95c2594fa0a26c0b13d95df05f993754 Mon Sep 17 00:00:00 2001 From: Guilherme Rossato Date: Mon, 13 May 2019 10:26:27 -0300 Subject: [PATCH 31/48] Document the alternatives to disable the default script timeout Mentioning and giving an example of the usage of the 4 options to disable the default script timeout of 300 seconds: 1. Static helper (already exists and kept). 2. Config key "process-timeout". 3. Environment variable "COMPOSER_PROCESS_TIMEOUT". 4. The "--timeout" parameter. --- doc/articles/scripts.md | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index 52ed86073..99ffd94dc 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -224,11 +224,13 @@ to the `phpunit` script. Although Composer is not intended to manage long-running processes and other such aspects of PHP projects, it can sometimes be handy to disable the process timeout on custom commands. This timeout defaults to 300 seconds and can be -overridden for all commands using the config key `process-timeout`, or for -specific commands using an argument to the `run-script` command. +overridden in a variety of ways depending on the desired effect: it's possible +to disable it for all command using the config key `process-timeout`, or for +a specific call using the `--timeout` parameter of the `run` (`run-scripts`) +command, or using a static helper for specific scripts. -A static helper also exists that can disable the process timeout for a specific -script directly in composer.json: +To disable the timeout for specific scripts with the static helper directly in +composer.json: ```json { @@ -241,6 +243,31 @@ script directly in composer.json: } ``` +To disable the timeout for every script on a given project, you can use the +composer.json configuration: + +```json +{ + "config": { + "process-timeout": 0 + } +} +``` + +It's also possible to set the global environment variable to disable the timeout +of all following scripts in the current terminal environment: + +``` +export COMPOSER_PROCESS_TIMEOUT=0 +``` + +To disable the timeout of a single script call, you must use the `run` composer +command and specify the `--timeout` parameter: + +``` +composer run test --timeout=0 +``` + ## Referencing scripts To enable script re-use and avoid duplicates, you can call a script from another From 1976da9ee951e1c7027b25b364d68b7b7aa10257 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 14 May 2019 10:18:13 +0200 Subject: [PATCH 32/48] modify text --- doc/articles/scripts.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index 99ffd94dc..18417bfef 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -224,10 +224,13 @@ to the `phpunit` script. Although Composer is not intended to manage long-running processes and other such aspects of PHP projects, it can sometimes be handy to disable the process timeout on custom commands. This timeout defaults to 300 seconds and can be -overridden in a variety of ways depending on the desired effect: it's possible -to disable it for all command using the config key `process-timeout`, or for -a specific call using the `--timeout` parameter of the `run` (`run-scripts`) -command, or using a static helper for specific scripts. +overridden in a variety of ways depending on the desired effect: + +- disable it for all commands using the config key `process-timeout`, +- disable it for the current or future invocations of composer using the + environment variable `COMPOSER_PROCESS_TIMEOUT`, +- for a specific invocation using the `--timeout` flag of the `run-script` command, +- using a static helper for specific scripts. To disable the timeout for specific scripts with the static helper directly in composer.json: From 7f34189f91a06531bb8a8a3afcb9cf88f03fdbc7 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 14 May 2019 10:19:37 +0200 Subject: [PATCH 33/48] use full command name, not abbreviated/alias --- doc/articles/scripts.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index 18417bfef..771093610 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -264,11 +264,11 @@ of all following scripts in the current terminal environment: export COMPOSER_PROCESS_TIMEOUT=0 ``` -To disable the timeout of a single script call, you must use the `run` composer +To disable the timeout of a single script call, you must use the `run-script` composer command and specify the `--timeout` parameter: ``` -composer run test --timeout=0 +composer run-script test --timeout=0 ``` ## Referencing scripts From d63bf33848f396c58c5e0de834cf15f9d7094b95 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 14 May 2019 10:20:32 +0200 Subject: [PATCH 34/48] flag should come before script name --- doc/articles/scripts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index 771093610..9516b82bc 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -268,7 +268,7 @@ To disable the timeout of a single script call, you must use the `run-script` co command and specify the `--timeout` parameter: ``` -composer run-script test --timeout=0 +composer run-script --timeout=0 test ``` ## Referencing scripts From faa7c5eea2de7e053f38c0726c01147531687361 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sun, 19 May 2019 20:52:53 +0200 Subject: [PATCH 35/48] Allow overriding self-update target file with envvar COMPOSER_SELF_UPDATE_TARGET Useful if Composer is provided on a read-only filesystems, to allow self-update to work with a different destination --- src/Composer/Command/SelfUpdateCommand.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index 78b27460e..226aafeb5 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -351,6 +351,10 @@ TAGSPUBKEY @copy($localFilename, $backupTarget); } + if ($targetFilename = getenv('COMPOSER_SELF_UPDATE_TARGET')) { + $localFilename = realpath($targetFilename) ?: $targetFilename; + } + rename($newFilename, $localFilename); return null; From bd6b758a1be2ffd722690e27e83a0ab685a06d37 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Wed, 29 May 2019 08:45:05 +0200 Subject: [PATCH 36/48] fixes #8159 expand interface and add missing methods to aliaspackage --- src/Composer/Package/AliasPackage.php | 10 ++++++++ src/Composer/Package/PackageInterface.php | 28 +++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/Composer/Package/AliasPackage.php b/src/Composer/Package/AliasPackage.php index 09ed4fb9b..89f197856 100644 --- a/src/Composer/Package/AliasPackage.php +++ b/src/Composer/Package/AliasPackage.php @@ -401,4 +401,14 @@ class AliasPackage extends BasePackage implements CompletePackageInterface { return parent::__toString().' (alias of '.$this->aliasOf->getVersion().')'; } + + public function setDistUrl($url) + { + return $this->aliasOf->setDistUrl($url); + } + + public function setDistType($type) + { + return $this->aliasOf->setDistType($type); + } } diff --git a/src/Composer/Package/PackageInterface.php b/src/Composer/Package/PackageInterface.php index 73d2ade41..cb16efa7e 100644 --- a/src/Composer/Package/PackageInterface.php +++ b/src/Composer/Package/PackageInterface.php @@ -358,4 +358,32 @@ interface PackageInterface * @return array */ public function getTransportOptions(); + + /** + * @param string $reference + * + * @return void + */ + public function setSourceReference($reference); + + /** + * @param string $url + * + * @return void + */ + public function setDistUrl($url); + + /** + * @param string $type + * + * @return void + */ + public function setDistType($type); + + /** + * @param string $reference + * + * @return void + */ + public function setDistReference($reference); } From 9d79c69199b348789981e99ee3cf192f36337e1d Mon Sep 17 00:00:00 2001 From: johnstevenson Date: Mon, 27 May 2019 19:54:30 +0100 Subject: [PATCH 37/48] Update xdebug-handler to 1.3.3 --- composer.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.lock b/composer.lock index 849e32752..08679183c 100644 --- a/composer.lock +++ b/composer.lock @@ -186,16 +186,16 @@ }, { "name": "composer/xdebug-handler", - "version": "1.3.2", + "version": "1.3.3", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "d17708133b6c276d6e42ef887a877866b909d892" + "reference": "46867cbf8ca9fb8d60c506895449eb799db1184f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/d17708133b6c276d6e42ef887a877866b909d892", - "reference": "d17708133b6c276d6e42ef887a877866b909d892", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/46867cbf8ca9fb8d60c506895449eb799db1184f", + "reference": "46867cbf8ca9fb8d60c506895449eb799db1184f", "shasum": "" }, "require": { @@ -226,7 +226,7 @@ "Xdebug", "performance" ], - "time": "2019-01-28T20:25:53+00:00" + "time": "2019-05-27T17:52:04+00:00" }, { "name": "justinrainbow/json-schema", From 82825ccc74b977a86010dc78a80502e0dd5dc5dd Mon Sep 17 00:00:00 2001 From: pfofi <7479939+pfofi@users.noreply.github.com> Date: Fri, 7 Jun 2019 09:13:11 +0200 Subject: [PATCH 38/48] Use possessive quantifiers --- 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 8fc40c812..9d5b727cc 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -562,7 +562,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito protected function canonicalizeUrl($url) { if ('/' === $url[0]) { - if (preg_match('{^[^:]+://[^/]*}', $this->url, $matches)) { + if (preg_match('{^[^:]++://[^/]*+}', $this->url, $matches)) { return $matches[0] . $url; } From 659c72f9c8db708ea6490b9daf8195e2ad7319ab Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 7 Jun 2019 13:11:53 +0200 Subject: [PATCH 39/48] Read classmap-authoritative and apcu-autoloader from project config when installing via create-project, fixes #8155 --- src/Composer/Command/CreateProjectCommand.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index 3702c3595..2985aa57a 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -184,7 +184,9 @@ EOT ->setRunScripts(!$noScripts) ->setIgnorePlatformRequirements($ignorePlatformReqs) ->setSuggestedPackagesReporter($this->suggestedPackagesReporter) - ->setOptimizeAutoloader($config->get('optimize-autoloader')); + ->setOptimizeAutoloader($config->get('optimize-autoloader')) + ->setClassMapAuthoritative($config->get('classmap-authoritative')) + ->setApcuAutoloader($config->get('apcu-autoloader')); if ($disablePlugins) { $installer->disablePlugins(); From 088fb56c3d6f1264760d495d40edf7569ee83068 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 7 Jun 2019 16:27:40 +0200 Subject: [PATCH 40/48] Fix display of HHVM warning appearing when HHVM is not in use, fixes #8138 --- src/Composer/DependencyResolver/Problem.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/DependencyResolver/Problem.php b/src/Composer/DependencyResolver/Problem.php index 073f64e2d..c7e529889 100644 --- a/src/Composer/DependencyResolver/Problem.php +++ b/src/Composer/DependencyResolver/Problem.php @@ -106,7 +106,7 @@ class Problem $msg = "\n - This package requires ".$job['packageName'].$this->constraintToText($job['constraint']).' but '; - if (defined('HHVM_VERSION') || count($available)) { + if (defined('HHVM_VERSION') || (count($available) && $job['packageName'] === 'hhvm')) { return $msg . 'your HHVM version does not satisfy that requirement.'; } From e7eecc6901698ea352bff11ccabe5a1b6a6122c6 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 7 Jun 2019 16:49:07 +0200 Subject: [PATCH 41/48] Add docs for COMPOSER_SELF_UPDATE_TARGET, refs #8151 --- doc/03-cli.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/03-cli.md b/doc/03-cli.md index 6460e9e1d..5fc527c49 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -917,6 +917,10 @@ if you use Composer as super user at all times like in docker containers. If set, the value is used as php's memory_limit. +### COMPOSER_SELF_UPDATE_TARGET + +If set, makes the self-update command write the new Composer phar file into that path instead of overwriting itself. Useful for updating Composer on read-only filesystem. + ### COMPOSER_MIRROR_PATH_REPOS If set to 1, this env changes the default path repository strategy to `mirror` instead From b4e5db1c7055ede2952cb8f77f03cc9aafe00f09 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 7 Jun 2019 17:24:34 +0200 Subject: [PATCH 42/48] Revert "Allow overriding self-update target file with envvar COMPOSER_SELF_UPDATE_TARGET" Revert "Add docs for COMPOSER_SELF_UPDATE_TARGET, refs #8151" This reverts commit e7eecc6901698ea352bff11ccabe5a1b6a6122c6. This reverts commit faa7c5eea2de7e053f38c0726c01147531687361. --- doc/03-cli.md | 4 ---- src/Composer/Command/SelfUpdateCommand.php | 4 ---- 2 files changed, 8 deletions(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index 5fc527c49..6460e9e1d 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -917,10 +917,6 @@ if you use Composer as super user at all times like in docker containers. If set, the value is used as php's memory_limit. -### COMPOSER_SELF_UPDATE_TARGET - -If set, makes the self-update command write the new Composer phar file into that path instead of overwriting itself. Useful for updating Composer on read-only filesystem. - ### COMPOSER_MIRROR_PATH_REPOS If set to 1, this env changes the default path repository strategy to `mirror` instead diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index 226aafeb5..78b27460e 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -351,10 +351,6 @@ TAGSPUBKEY @copy($localFilename, $backupTarget); } - if ($targetFilename = getenv('COMPOSER_SELF_UPDATE_TARGET')) { - $localFilename = realpath($targetFilename) ?: $targetFilename; - } - rename($newFilename, $localFilename); return null; From b73120cbbe16f758f3e9189d49970a8627211a9f Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 11 Jun 2019 15:02:45 +0200 Subject: [PATCH 43/48] Update changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c079b6922..a150aaad8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +### [1.8.6] 2019-06-11 + + * Fixed handling of backslash-escapes handling in compoesr.json when using the require command + * Fixed create-project not following classmap-authoritative and apcu-autoloader config values + * Fixed HHVM version warning showing up in some cases when it was not in use + ### [1.8.5] 2019-04-09 * HHVM 4.0 is no longer compatible with Composer. Please use PHP instead going forward. @@ -745,6 +751,7 @@ * Initial release +[1.8.6]: https://github.com/composer/composer/compare/1.8.5...1.8.6 [1.8.5]: https://github.com/composer/composer/compare/1.8.4...1.8.5 [1.8.4]: https://github.com/composer/composer/compare/1.8.3...1.8.4 [1.8.3]: https://github.com/composer/composer/compare/1.8.2...1.8.3 From 76da8d792eeae2e5e136c78454ed5bc9e8aee7d6 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 11 Jun 2019 15:08:33 +0200 Subject: [PATCH 44/48] Update deps --- composer.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/composer.lock b/composer.lock index febcdbe86..8b7b3cb57 100644 --- a/composer.lock +++ b/composer.lock @@ -436,7 +436,7 @@ }, { "name": "symfony/console", - "version": "v2.8.49", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/console.git", @@ -497,7 +497,7 @@ }, { "name": "symfony/debug", - "version": "v2.8.49", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", @@ -554,7 +554,7 @@ }, { "name": "symfony/filesystem", - "version": "v2.8.49", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", @@ -604,7 +604,7 @@ }, { "name": "symfony/finder", - "version": "v2.8.49", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", @@ -653,16 +653,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.10.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" + "reference": "82ebae02209c21113908c229e9883c419720738a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", - "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", + "reference": "82ebae02209c21113908c229e9883c419720738a", "shasum": "" }, "require": { @@ -674,7 +674,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "1.11-dev" } }, "autoload": { @@ -707,20 +707,20 @@ "polyfill", "portable" ], - "time": "2018-08-06T14:22:27+00:00" + "time": "2019-02-06T07:57:58+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.10.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "c79c051f5b3a46be09205c73b80b346e4153e494" + "reference": "fe5e94c604826c35a32fa832f35bd036b6799609" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494", - "reference": "c79c051f5b3a46be09205c73b80b346e4153e494", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609", + "reference": "fe5e94c604826c35a32fa832f35bd036b6799609", "shasum": "" }, "require": { @@ -732,7 +732,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "1.11-dev" } }, "autoload": { @@ -766,11 +766,11 @@ "portable", "shim" ], - "time": "2018-09-21T13:07:52+00:00" + "time": "2019-02-06T07:57:58+00:00" }, { "name": "symfony/process", - "version": "v2.8.49", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/process.git", @@ -1736,7 +1736,7 @@ }, { "name": "symfony/yaml", - "version": "v2.8.49", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", From 6c76310810ebdbdfd004441f42509fd2d6640907 Mon Sep 17 00:00:00 2001 From: "Theodore R. Smith" Date: Tue, 11 Jun 2019 09:35:51 -0500 Subject: [PATCH 45/48] [minor] Fixed a typo in the CHANGELOG.md. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a150aaad8..2e6075148 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ### [1.8.6] 2019-06-11 - * Fixed handling of backslash-escapes handling in compoesr.json when using the require command + * Fixed handling of backslash-escapes handling in composer.json when using the require command * Fixed create-project not following classmap-authoritative and apcu-autoloader config values * Fixed HHVM version warning showing up in some cases when it was not in use From 7399638e43fb7e7c361efe8ec38b0baf3fc49676 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 11 Jun 2019 13:33:05 +0200 Subject: [PATCH 46/48] fixes #8179 --- src/Composer/Repository/Vcs/HgDriver.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Composer/Repository/Vcs/HgDriver.php b/src/Composer/Repository/Vcs/HgDriver.php index 45f13d5fe..f943a8a0a 100644 --- a/src/Composer/Repository/Vcs/HgDriver.php +++ b/src/Composer/Repository/Vcs/HgDriver.php @@ -61,8 +61,9 @@ class HgDriver extends VcsDriver // clean up directory and do a fresh clone into it $fs->removeDirectory($this->repoDir); - $command = function ($url) { - return sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($this->repoDir)); + $repoDir = $this->repoDir; + $command = function ($url) use ($repoDir) { + return sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($repoDir)); }; $hgUtils->runCommand($command, $this->url, $this->repoDir); From 89d5d8f1824d66163ee04761567c11e81f814a61 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 21 Jun 2019 18:34:16 +0200 Subject: [PATCH 47/48] Free $solver asap --- 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 8573f3695..9583c3eb1 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -473,6 +473,8 @@ class Installer $solver = new Solver($policy, $pool, $installedRepo, $this->io); try { $operations = $solver->solve($request, $this->ignorePlatformReqs); + $ruleSetSize = $solver->getRuleSetSize(); + $solver = null; } catch (SolverProblemsException $e) { $this->io->writeError('Your requirements could not be resolved to an installable set of packages.', true, IOInterface::QUIET); $this->io->writeError($e->getMessage()); @@ -489,7 +491,7 @@ class Installer $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request, $operations); $this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies", true, IOInterface::VERBOSE); - $this->io->writeError("Analyzed ".$solver->getRuleSetSize()." rules to resolve dependencies", true, IOInterface::VERBOSE); + $this->io->writeError("Analyzed ".$ruleSetSize." rules to resolve dependencies", true, IOInterface::VERBOSE); // execute operations if (!$operations) { From 8da046e4e982b7a8c01b038b19242dc339847cd8 Mon Sep 17 00:00:00 2001 From: Stephan Vock Date: Sun, 23 Jun 2019 18:59:36 +0100 Subject: [PATCH 48/48] SVN: hide passwords for debug output --- src/Composer/Util/ProcessExecutor.php | 1 + .../Test/Util/ProcessExecutorTest.php | 20 ++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Composer/Util/ProcessExecutor.php b/src/Composer/Util/ProcessExecutor.php index f5e1ef610..d72a02981 100644 --- a/src/Composer/Util/ProcessExecutor.php +++ b/src/Composer/Util/ProcessExecutor.php @@ -51,6 +51,7 @@ class ProcessExecutor return '://'.$m['user'].':***@'; }, $command); + $safeCommand = preg_replace("{--password (.*[^\\\\]\') }", '--password \'***\' ', $safeCommand); $this->io->writeError('Executing command ('.($cwd ?: 'CWD').'): '.$safeCommand); } diff --git a/tests/Composer/Test/Util/ProcessExecutorTest.php b/tests/Composer/Test/Util/ProcessExecutorTest.php index e98898417..db16b8c02 100644 --- a/tests/Composer/Test/Util/ProcessExecutorTest.php +++ b/tests/Composer/Test/Util/ProcessExecutorTest.php @@ -61,11 +61,25 @@ class ProcessExecutorTest extends TestCase ProcessExecutor::setTimeout(60); } - public function testHidePasswords() + /** + * @dataProvider hidePasswordProvider + */ + public function testHidePasswords($command, $expectedCommandOutput) { $process = new ProcessExecutor($buffer = new BufferIO('', StreamOutput::VERBOSITY_DEBUG)); - $process->execute('echo https://foo:bar@example.org/ && echo http://foo@example.org && echo http://abcdef1234567890234578:x-oauth-token@github.com/', $output); - $this->assertEquals('Executing command (CWD): echo https://foo:***@example.org/ && echo http://foo@example.org && echo http://***:***@github.com/', trim($buffer->getOutput())); + $process->execute($command, $output); + $this->assertEquals('Executing command (CWD): ' . $expectedCommandOutput, trim($buffer->getOutput())); + } + + public function hidePasswordProvider() + { + return array( + array('echo https://foo:bar@example.org/', 'echo https://foo:***@example.org/'), + array('echo http://foo@example.org', 'echo http://foo@example.org'), + array('echo http://abcdef1234567890234578:x-oauth-token@github.com/', 'echo http://***:***@github.com/'), + array("svn ls --verbose --non-interactive --username 'foo' --password 'bar' 'https://foo.example.org/svn/'", "svn ls --verbose --non-interactive --username 'foo' --password '***' 'https://foo.example.org/svn/'"), + array("svn ls --verbose --non-interactive --username 'foo' --password 'bar \'bar' 'https://foo.example.org/svn/'", "svn ls --verbose --non-interactive --username 'foo' --password '***' 'https://foo.example.org/svn/'"), + ); } public function testDoesntHidePorts()