From ecec0d00fc0e6b7162fb188cc8331b7bb673b8d1 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 1 Apr 2022 21:20:21 +0200 Subject: [PATCH 1/7] Fix generation of autoload rules in a dir that is missing to ensure it does not break (#10688) --- src/Composer/Autoload/AutoloadGenerator.php | 4 + .../Test/Autoload/AutoloadGeneratorTest.php | 105 +++++++++++++++--- 2 files changed, 96 insertions(+), 13 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index b31f9ed67..265b890d6 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -162,6 +162,7 @@ class AutoloadGenerator * @param string $suffix * @return int * @throws \Seld\JsonLint\ParsingException + * @throws \RuntimeException */ public function dump(Config $config, InstalledRepositoryInterface $localRepo, RootPackageInterface $rootPackage, InstallationManager $installationManager, $targetDir, $scanPsrPackages = false, $suffix = '') { @@ -1289,6 +1290,9 @@ INITIALIZER; } $resolvedPath = realpath($installPath . '/' . $updir); + if (false === $resolvedPath) { + continue; + } $autoloads[] = preg_quote(strtr($resolvedPath, '\\', '/')) . '/' . $path . '($|/)'; continue; } diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index c29121f21..1c7ca36f3 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -14,6 +14,7 @@ namespace Composer\Test\Autoload; use Composer\Autoload\AutoloadGenerator; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory; +use Composer\Package\CompletePackage; use Composer\Package\Link; use Composer\Package\Version\VersionParser; use Composer\Semver\Constraint\Constraint; @@ -775,8 +776,8 @@ EOF; include $this->vendorDir.'/composer/autoload_classmap.php' ); $this->assertAutoloadFiles('classmap5', $this->vendorDir.'/composer', 'classmap'); - $this->assertStringNotContainsString('$loader->setClassMapAuthoritative(true);', file_get_contents($this->vendorDir.'/composer/autoload_real.php')); - $this->assertStringNotContainsString('$loader->setApcuPrefix(', file_get_contents($this->vendorDir.'/composer/autoload_real.php')); + $this->assertStringNotContainsString('$loader->setClassMapAuthoritative(true);', (string) file_get_contents($this->vendorDir.'/composer/autoload_real.php')); + $this->assertStringNotContainsString('$loader->setApcuPrefix(', (string) file_get_contents($this->vendorDir.'/composer/autoload_real.php')); } public function testClassMapAutoloadingAuthoritativeAndApcu() @@ -824,8 +825,8 @@ EOF; ); $this->assertAutoloadFiles('classmap8', $this->vendorDir.'/composer', 'classmap'); - $this->assertStringContainsString('$loader->setClassMapAuthoritative(true);', file_get_contents($this->vendorDir.'/composer/autoload_real.php')); - $this->assertStringContainsString('$loader->setApcuPrefix(', file_get_contents($this->vendorDir.'/composer/autoload_real.php')); + $this->assertStringContainsString('$loader->setClassMapAuthoritative(true);', (string) file_get_contents($this->vendorDir.'/composer/autoload_real.php')); + $this->assertStringContainsString('$loader->setApcuPrefix(', (string) file_get_contents($this->vendorDir.'/composer/autoload_real.php')); } public function testClassMapAutoloadingAuthoritativeAndApcuPrefix() @@ -873,8 +874,8 @@ EOF; ); $this->assertAutoloadFiles('classmap8', $this->vendorDir.'/composer', 'classmap'); - $this->assertStringContainsString('$loader->setClassMapAuthoritative(true);', file_get_contents($this->vendorDir.'/composer/autoload_real.php')); - $this->assertStringContainsString('$loader->setApcuPrefix(\'custom\\\'Prefix\');', file_get_contents($this->vendorDir.'/composer/autoload_real.php')); + $this->assertStringContainsString('$loader->setClassMapAuthoritative(true);', (string) file_get_contents($this->vendorDir.'/composer/autoload_real.php')); + $this->assertStringContainsString('$loader->setApcuPrefix(\'custom\\\'Prefix\');', (string) file_get_contents($this->vendorDir.'/composer/autoload_real.php')); } public function testFilesAutoloadGeneration() @@ -1442,8 +1443,8 @@ EOF; $this->assertStringEqualsFile($vendorDir.'/composer/autoload_namespaces.php', $expectedNamespace); $this->assertStringEqualsFile($vendorDir.'/composer/autoload_psr4.php', $expectedPsr4); $this->assertStringEqualsFile($vendorDir.'/composer/autoload_classmap.php', $expectedClassmap); - $this->assertStringContainsString("\$vendorDir . '/b/b/bootstrap.php',\n", file_get_contents($vendorDir.'/composer/autoload_files.php')); - $this->assertStringContainsString("\$baseDir . '/test.php',\n", file_get_contents($vendorDir.'/composer/autoload_files.php')); + $this->assertStringContainsString("\$vendorDir . '/b/b/bootstrap.php',\n", (string) file_get_contents($vendorDir.'/composer/autoload_files.php')); + $this->assertStringContainsString("\$baseDir . '/test.php',\n", (string) file_get_contents($vendorDir.'/composer/autoload_files.php')); } public function testUpLevelRelativePaths() @@ -1527,7 +1528,85 @@ EOF; $this->assertStringEqualsFile($this->vendorDir.'/composer/autoload_namespaces.php', $expectedNamespace); $this->assertStringEqualsFile($this->vendorDir.'/composer/autoload_psr4.php', $expectedPsr4); $this->assertStringEqualsFile($this->vendorDir.'/composer/autoload_classmap.php', $expectedClassmap); - $this->assertStringContainsString("\$baseDir . '/../test.php',\n", file_get_contents($this->vendorDir.'/composer/autoload_files.php')); + $this->assertStringContainsString("\$baseDir . '/../test.php',\n", (string) file_get_contents($this->vendorDir.'/composer/autoload_files.php')); + } + + public function testAutoloadRulesInPackageThatDoesNotExistOnDisk() + { + $package = new RootPackage('root/a', '1.0', '1.0'); + $package->setRequires(array( + 'dep/a' => new Link('root/a', 'dep/a', new MatchAllConstraint(), 'requires'), + )); + $dep = new CompletePackage('dep/a', '1.0', '1.0'); + + $this->repository->expects($this->any()) + ->method('getCanonicalPackages') + ->will($this->returnValue(array($dep))); + + $dep->setAutoload(array( + 'psr-0' => array('Foo' => './src'), + )); + $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', true, '_19'); + + $expectedNamespace = <<<'EOF' + array($vendorDir . '/dep/a/src'), +); + +EOF; + $this->assertStringEqualsFile($this->vendorDir.'/composer/autoload_namespaces.php', $expectedNamespace); + + $dep->setAutoload(array( + 'psr-4' => array('Acme\Foo\\' => './src-psr4'), + )); + $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', true, '_19'); + + $expectedPsr4 = <<<'EOF' + array($vendorDir . '/dep/a/src-psr4'), +); + +EOF; + $this->assertStringEqualsFile($this->vendorDir.'/composer/autoload_psr4.php', $expectedPsr4); + + $dep->setAutoload(array( + 'classmap' => array('classmap'), + )); + try { + $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', true, '_19'); + } catch (\RuntimeException $e) { + $this->assertSame('Could not scan for classes inside "'.$this->vendorDir.'/dep/a/classmap" which does not appear to be a file nor a folder', $e->getMessage()); + } + + $dep->setAutoload(array( + 'files' => array('./test.php'), + )); + $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', true, '_19'); + $this->assertStringContainsString("\$vendorDir . '/dep/a/test.php',\n", (string) file_get_contents($this->vendorDir.'/composer/autoload_files.php')); + + $package->setAutoload(array( + 'exclude-from-classmap' => array('../excludedroot', 'root/excl'), + )); + $dep->setAutoload(array( + 'exclude-from-classmap' => array('../../excluded', 'foo/bar'), + )); + $map = $this->generator->buildPackageMap($this->im, $package, array($dep)); + $parsed = $this->generator->parseAutoloads($map, $package); + $this->assertSame(array(preg_quote(dirname($this->workingDir)).'/excludedroot($|/)', preg_quote($this->workingDir).'/root/excl($|/)'), $parsed['exclude-from-classmap']); } public function testEmptyPaths() @@ -1745,10 +1824,10 @@ EOF; if (null === $expectedFixture) { $this->assertFalse(file_exists($this->vendorDir . '/composer/platform_check.php')); - $this->assertStringNotContainsString("require __DIR__ . '/platform_check.php';", file_get_contents($this->vendorDir.'/composer/autoload_real.php')); + $this->assertStringNotContainsString("require __DIR__ . '/platform_check.php';", (string) file_get_contents($this->vendorDir.'/composer/autoload_real.php')); } else { $this->assertFileContentEquals(__DIR__ . '/Fixtures/platform/' . $expectedFixture . '.php', $this->vendorDir . '/composer/platform_check.php'); - $this->assertStringContainsString("require __DIR__ . '/platform_check.php';", file_get_contents($this->vendorDir.'/composer/autoload_real.php')); + $this->assertStringContainsString("require __DIR__ . '/platform_check.php';", (string) file_get_contents($this->vendorDir.'/composer/autoload_real.php')); } } @@ -1883,8 +1962,8 @@ EOF; public static function assertFileContentEquals($expected, $actual, $message = '', $canonicalize = false, $ignoreCase = false) { self::assertEqualsNormalized( - file_get_contents($expected), - file_get_contents($actual), + (string) file_get_contents($expected), + (string) file_get_contents($actual), $message ?: $expected.' equals '.$actual, 0, 10, From b7d9beaa434d965ccafd29e512baebc43ac2d148 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 1 Apr 2022 21:52:46 +0200 Subject: [PATCH 2/7] Update deps --- composer.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/composer.lock b/composer.lock index 948ce5956..718e800cd 100644 --- a/composer.lock +++ b/composer.lock @@ -224,16 +224,16 @@ }, { "name": "composer/semver", - "version": "3.3.1", + "version": "3.3.2", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "5d8e574bb0e69188786b8ef77d43341222a41a71" + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/5d8e574bb0e69188786b8ef77d43341222a41a71", - "reference": "5d8e574bb0e69188786b8ef77d43341222a41a71", + "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", "shasum": "" }, "require": { @@ -285,7 +285,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.3.1" + "source": "https://github.com/composer/semver/tree/3.3.2" }, "funding": [ { @@ -301,7 +301,7 @@ "type": "tidelift" } ], - "time": "2022-03-16T11:22:07+00:00" + "time": "2022-04-01T19:23:25+00:00" }, { "name": "composer/spdx-licenses", @@ -619,23 +619,23 @@ }, { "name": "seld/jsonlint", - "version": "1.8.9", + "version": "1.9.0", "source": { "type": "git", "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "d9a308b84277a7dd651ba89bf5ed37b88497b171" + "reference": "4211420d25eba80712bff236a98960ef68b866b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/d9a308b84277a7dd651ba89bf5ed37b88497b171", - "reference": "d9a308b84277a7dd651ba89bf5ed37b88497b171", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/4211420d25eba80712bff236a98960ef68b866b7", + "reference": "4211420d25eba80712bff236a98960ef68b866b7", "shasum": "" }, "require": { "php": "^5.3 || ^7.0 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^0.12.59", + "phpstan/phpstan": "^1.5", "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13" }, "bin": [ @@ -667,7 +667,7 @@ ], "support": { "issues": "https://github.com/Seldaek/jsonlint/issues", - "source": "https://github.com/Seldaek/jsonlint/tree/1.8.9" + "source": "https://github.com/Seldaek/jsonlint/tree/1.9.0" }, "funding": [ { @@ -679,7 +679,7 @@ "type": "tidelift" } ], - "time": "2022-03-31T11:30:35+00:00" + "time": "2022-04-01T13:37:23+00:00" }, { "name": "seld/phar-utils", From 956d44c339a836f6a649dd49c06cdbd030c36712 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 1 Apr 2022 21:53:41 +0200 Subject: [PATCH 3/7] Add --2.2 flag to self-update for 2.2 LTS as well as EOL marker support --- src/Composer/Command/SelfUpdateCommand.php | 9 +++++++-- src/Composer/SelfUpdate/Versions.php | 14 ++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index daf1b55ff..244c54aaa 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -59,6 +59,7 @@ class SelfUpdateCommand extends BaseCommand new InputOption('snapshot', null, InputOption::VALUE_NONE, 'Force an update to the snapshot channel'), new InputOption('1', null, InputOption::VALUE_NONE, 'Force an update to the stable channel, but only use 1.x versions'), new InputOption('2', null, InputOption::VALUE_NONE, 'Force an update to the stable channel, but only use 2.x versions'), + new InputOption('2.2', null, InputOption::VALUE_NONE, 'Force an update to the stable channel, but only use 2.2.x LTS versions'), new InputOption('set-channel-only', null, InputOption::VALUE_NONE, 'Only store the channel as the default one and then exit'), )) ->setHelp( @@ -182,8 +183,12 @@ EOT } } - if ($requestedChannel && is_numeric($requestedChannel) && strpos($latestStable['version'], $requestedChannel) !== 0) { - $io->writeError('Warning: You forced the install of '.$latestVersion.' via --'.$requestedChannel.', but '.$latestStable['version'].' is the latest stable version. Updating to it via composer self-update --stable is recommended.'); + $effectiveChannel = $requestedChannel === null ? $versionsUtil->getChannel() : $requestedChannel; + if (is_numeric($effectiveChannel) && strpos($latestStable['version'], $effectiveChannel) !== 0) { + $io->writeError('Warning: You forced the install of '.$latestVersion.' via --'.$effectiveChannel.', but '.$latestStable['version'].' is the latest stable version. Updating to it via composer self-update --stable is recommended.'); + } + if (isset($latest['eol'])) { + $io->writeError('Warning: Version '.$latestVersion.' is EOL / End of Life. '.$latestStable['version'].' is the latest stable version. Updating to it via composer self-update --stable is recommended.'); } if (Preg::isMatch('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) { diff --git a/src/Composer/SelfUpdate/Versions.php b/src/Composer/SelfUpdate/Versions.php index 9e617fb13..823f4a5b5 100644 --- a/src/Composer/SelfUpdate/Versions.php +++ b/src/Composer/SelfUpdate/Versions.php @@ -12,6 +12,7 @@ namespace Composer\SelfUpdate; +use Composer\Pcre\Preg; use Composer\Util\HttpDownloader; use Composer\Config; @@ -21,7 +22,7 @@ use Composer\Config; class Versions { /** @var string[] */ - public static $channels = array('stable', 'preview', 'snapshot', '1', '2'); + public static $channels = array('stable', 'preview', 'snapshot', '1', '2', '2.2'); /** @var HttpDownloader */ private $httpDownloader; @@ -29,7 +30,7 @@ class Versions private $config; /** @var string */ private $channel; - /** @var array> */ + /** @var array> */ private $versionsData; public function __construct(Config $config, HttpDownloader $httpDownloader) @@ -50,7 +51,7 @@ class Versions $channelFile = $this->config->get('home').'/update-channel'; if (file_exists($channelFile)) { $channel = trim(file_get_contents($channelFile)); - if (in_array($channel, array('stable', 'preview', 'snapshot'), true)) { + if (in_array($channel, array('stable', 'preview', 'snapshot', '2.2'), true)) { return $this->channel = $channel; } } @@ -71,13 +72,14 @@ class Versions $channelFile = $this->config->get('home').'/update-channel'; $this->channel = $channel; - file_put_contents($channelFile, (is_numeric($channel) ? 'stable' : $channel).PHP_EOL); + // rewrite '2' and '1' channels to stable for future self-updates, but LTS ones like '2.2' remain pinned + file_put_contents($channelFile, (Preg::isMatch('{^\d+$}D', $channel) ? 'stable' : $channel).PHP_EOL); } /** * @param string|null $channel * - * @return array{path: string, version: string, min-php: int} + * @return array{path: string, version: string, min-php: int, eol?: true} */ public function getLatest($channel = null) { @@ -93,7 +95,7 @@ class Versions } /** - * @return array> + * @return array> */ private function getVersionsData() { From 38efb57ba21d5a4d968adcc297e80b6f6a7bb8ea Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 1 Apr 2022 21:56:52 +0200 Subject: [PATCH 4/7] Fix type issues --- src/Composer/SelfUpdate/Versions.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Composer/SelfUpdate/Versions.php b/src/Composer/SelfUpdate/Versions.php index 823f4a5b5..284449417 100644 --- a/src/Composer/SelfUpdate/Versions.php +++ b/src/Composer/SelfUpdate/Versions.php @@ -30,8 +30,8 @@ class Versions private $config; /** @var string */ private $channel; - /** @var array> */ - private $versionsData; + /** @var array>|null */ + private $versionsData = null; public function __construct(Config $config, HttpDownloader $httpDownloader) { @@ -99,7 +99,7 @@ class Versions */ private function getVersionsData() { - if (!$this->versionsData) { + if (null === $this->versionsData) { if ($this->config->get('disable-tls') === true) { $protocol = 'http'; } else { From 864446e1b97e7cfef355176d893b50d7e716e18c Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 1 Apr 2022 22:00:45 +0200 Subject: [PATCH 5/7] Update changelog --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5334282f8..61acf5863 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +### [2.2.11] 2022-04-01 + + * Added missing config.bitbucket-oauth in composer-schema.json + * Added --2.2 flag to `self-update` to pin the Composer version to the 2.2 LTS range (#10682) + * Updated semver, jsonlint deps for minor fixes + * Fixed generation of autoload crashing if a package has a broken path (#10688) + * Removed dev-master=>dev-main alias from #10372 as it does not work when reloading from lock file and extracting dev deps (#10651) + ### [2.2.10] 2022-03-29 * Fixed Bitbucket authorization detection due to API changes (#10657) @@ -1412,6 +1420,7 @@ * Initial release +[2.2.11]: https://github.com/composer/composer/compare/2.2.10...2.2.11 [2.2.10]: https://github.com/composer/composer/compare/2.2.9...2.2.10 [2.2.9]: https://github.com/composer/composer/compare/2.2.8...2.2.9 [2.2.8]: https://github.com/composer/composer/compare/2.2.7...2.2.8 From 2f5bcf0480c13b4fa1ac490aa9344e4402507538 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 1 Apr 2022 22:00:52 +0200 Subject: [PATCH 6/7] Release 2.2.11 --- src/Composer/Composer.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Composer/Composer.php b/src/Composer/Composer.php index 624e02507..08fa50056 100644 --- a/src/Composer/Composer.php +++ b/src/Composer/Composer.php @@ -52,10 +52,10 @@ class Composer * const RELEASE_DATE = '@release_date@'; * const SOURCE_VERSION = '1.8-dev+source'; */ - const VERSION = '@package_version@'; - const BRANCH_ALIAS_VERSION = '@package_branch_alias_version@'; - const RELEASE_DATE = '@release_date@'; - const SOURCE_VERSION = '2.2.999-dev+source'; + const VERSION = '2.2.11'; + const BRANCH_ALIAS_VERSION = ''; + const RELEASE_DATE = '2022-04-01 22:00:52'; + const SOURCE_VERSION = ''; /** * Version number of the internal composer-runtime-api package From 95e09d3a814864c4988f466460e4120534b4ac36 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 1 Apr 2022 22:00:53 +0200 Subject: [PATCH 7/7] Reverting release version changes --- src/Composer/Composer.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Composer/Composer.php b/src/Composer/Composer.php index 08fa50056..624e02507 100644 --- a/src/Composer/Composer.php +++ b/src/Composer/Composer.php @@ -52,10 +52,10 @@ class Composer * const RELEASE_DATE = '@release_date@'; * const SOURCE_VERSION = '1.8-dev+source'; */ - const VERSION = '2.2.11'; - const BRANCH_ALIAS_VERSION = ''; - const RELEASE_DATE = '2022-04-01 22:00:52'; - const SOURCE_VERSION = ''; + const VERSION = '@package_version@'; + const BRANCH_ALIAS_VERSION = '@package_branch_alias_version@'; + const RELEASE_DATE = '@release_date@'; + const SOURCE_VERSION = '2.2.999-dev+source'; /** * Version number of the internal composer-runtime-api package