From 2837585e47d4192fa3931aa09e9810bdab6487db Mon Sep 17 00:00:00 2001 From: John Stevenson Date: Thu, 12 May 2022 20:13:55 +0100 Subject: [PATCH 01/14] Fix cmd splitting paths on commas (#10775) --- src/Composer/Util/ProcessExecutor.php | 3 ++- tests/Composer/Test/Util/ProcessExecutorTest.php | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Composer/Util/ProcessExecutor.php b/src/Composer/Util/ProcessExecutor.php index 16352bbcf..ca181d7d3 100644 --- a/src/Composer/Util/ProcessExecutor.php +++ b/src/Composer/Util/ProcessExecutor.php @@ -490,7 +490,8 @@ class ProcessExecutor // New lines break cmd.exe command parsing $argument = strtr($argument, "\n", ' '); - $quote = strpbrk($argument, " \t") !== false; + // In addition to whitespace, commas need quoting to preserve paths + $quote = strpbrk($argument, " \t,") !== false; $argument = Preg::replace('/(\\\\*)"/', '$1$1\\"', $argument, -1, $dquotes); $meta = $dquotes || Preg::isMatch('/%[^%]+%|![^!]+!/', $argument); diff --git a/tests/Composer/Test/Util/ProcessExecutorTest.php b/tests/Composer/Test/Util/ProcessExecutorTest.php index ff2acd82e..13bf31cbc 100644 --- a/tests/Composer/Test/Util/ProcessExecutorTest.php +++ b/tests/Composer/Test/Util/ProcessExecutorTest.php @@ -178,6 +178,9 @@ class ProcessExecutorTest extends TestCase // no whitespace must not be quoted 'no-ws' => array('abc', 'abc', "'abc'"), + // commas must be quoted + 'comma' => array('a,bc', '"a,bc"', "'a,bc'"), + // double-quotes must be backslash-escaped 'dq' => array('a"bc', 'a\^"bc', "'a\"bc'"), From 76813a9cd0704278ec38e28fa8d1d9ea78e685b3 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 13 May 2022 14:58:25 +0100 Subject: [PATCH 02/14] CurlDownloader: detect max file size for gziped responses with missing content-length header (#10771) --- src/Composer/Util/Http/CurlDownloader.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Composer/Util/Http/CurlDownloader.php b/src/Composer/Util/Http/CurlDownloader.php index 051fca277..3799074f1 100644 --- a/src/Composer/Util/Http/CurlDownloader.php +++ b/src/Composer/Util/Http/CurlDownloader.php @@ -17,6 +17,7 @@ use Composer\Downloader\MaxFileSizeExceededException; use Composer\IO\IOInterface; use Composer\Downloader\TransportException; use Composer\Pcre\Preg; +use Composer\Util\Platform; use Composer\Util\StreamContextFactory; use Composer\Util\AuthHelper; use Composer\Util\Url; @@ -394,8 +395,19 @@ class CurlDownloader $response = new CurlResponse(array('url' => $progress['url']), $statusCode, $headers, $contents, $progress); $this->io->writeError('['.$statusCode.'] '.Url::sanitize($progress['url']), true, IOInterface::DEBUG); } else { + $maxFileSize = $job['options']['max_file_size'] ?? null; rewind($job['bodyHandle']); - $contents = stream_get_contents($job['bodyHandle']); + if ($maxFileSize !== null) { + $contents = stream_get_contents($job['bodyHandle'], $maxFileSize); + // Gzipped responses with missing Content-Length header cannot be detected during the file download + // because $progress['size_download'] refers to the gzipped size downloaded, not the actual file size + if ($contents !== false && Platform::strlen($contents) >= $maxFileSize) { + throw new MaxFileSizeExceededException('Maximum allowed download size reached. Downloaded ' . Platform::strlen($contents) . ' of allowed ' . $maxFileSize . ' bytes'); + } + } else { + $contents = stream_get_contents($job['bodyHandle']); + } + $response = new CurlResponse(array('url' => $progress['url']), $statusCode, $headers, $contents, $progress); $this->io->writeError('['.$statusCode.'] '.Url::sanitize($progress['url']), true, IOInterface::DEBUG); } From e496b1362fe559e8a3ee95ab2a7431caeb821457 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 20 May 2022 12:15:59 +0100 Subject: [PATCH 03/14] GitHub: add support for files >1MB to getFileContent (#10785) --- src/Composer/Repository/Vcs/GitHubDriver.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Composer/Repository/Vcs/GitHubDriver.php b/src/Composer/Repository/Vcs/GitHubDriver.php index 6e81bc584..0e60070bb 100644 --- a/src/Composer/Repository/Vcs/GitHubDriver.php +++ b/src/Composer/Repository/Vcs/GitHubDriver.php @@ -295,6 +295,13 @@ class GitHubDriver extends VcsDriver $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier); $resource = $this->getContents($resource)->decodeJson(); + + // The GitHub contents API only returns files up to 1MB as base64 encoded files + // larger files either need be fetched with a raw accept header or by using the git blob endpoint + if ((!isset($resource['content']) || $resource['content'] === '') && $resource['encoding'] === 'none' && isset($resource['git_url'])) { + $resource = $this->getContents($resource['git_url'])->decodeJson(); + } + if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) { throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier); } From 44a52e4157eb3a8c529204d6799ae7e0909d4de0 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 24 May 2022 14:32:18 +0200 Subject: [PATCH 04/14] Fix backtracking in name validation regex --- res/composer-schema.json | 2 +- src/Composer/Package/Loader/ValidatingArrayLoader.php | 2 +- tests/Composer/Test/Json/ComposerSchemaTest.php | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/res/composer-schema.json b/res/composer-schema.json index 166a80820..e4e460b89 100644 --- a/res/composer-schema.json +++ b/res/composer-schema.json @@ -6,7 +6,7 @@ "name": { "type": "string", "description": "Package name, including 'vendor-name/' prefix.", - "pattern": "^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$" + "pattern": "^[a-z0-9]([_.-]?[a-z0-9]++)*+/[a-z0-9](([_.]|-{1,2})?[a-z0-9]++)*+$" }, "description": { "type": "string", diff --git a/src/Composer/Package/Loader/ValidatingArrayLoader.php b/src/Composer/Package/Loader/ValidatingArrayLoader.php index 7fb2c3b79..f05ba512f 100644 --- a/src/Composer/Package/Loader/ValidatingArrayLoader.php +++ b/src/Composer/Package/Loader/ValidatingArrayLoader.php @@ -456,7 +456,7 @@ class ValidatingArrayLoader implements LoaderInterface return null; } - if (!Preg::isMatch('{^[a-z0-9](?:[_.-]?[a-z0-9]+)*/[a-z0-9](?:(?:[_.]?|-{0,2})[a-z0-9]+)*$}iD', $name)) { + if (!Preg::isMatch('{^[a-z0-9](?:[_.-]?[a-z0-9]++)*+/[a-z0-9](?:(?:[_.]|-{1,2})?[a-z0-9]++)*+$}iD', $name)) { return $name.' is invalid, it should have a vendor name, a forward slash, and a package name. The vendor and package name can be words separated by -, . or _. The complete name should match "^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$".'; } diff --git a/tests/Composer/Test/Json/ComposerSchemaTest.php b/tests/Composer/Test/Json/ComposerSchemaTest.php index e45da5df3..8c252a046 100644 --- a/tests/Composer/Test/Json/ComposerSchemaTest.php +++ b/tests/Composer/Test/Json/ComposerSchemaTest.php @@ -25,9 +25,9 @@ class ComposerSchemaTest extends TestCase $expectedError = array( array( 'property' => 'name', - 'message' => 'Does not match the regex pattern ^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$', + 'message' => 'Does not match the regex pattern ^[a-z0-9]([_.-]?[a-z0-9]++)*+/[a-z0-9](([_.]|-{1,2})?[a-z0-9]++)*+$', 'constraint' => 'pattern', - 'pattern' => '^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$', + 'pattern' => '^[a-z0-9]([_.-]?[a-z0-9]++)*+/[a-z0-9](([_.]|-{1,2})?[a-z0-9]++)*+$', ), ); From d131be009dea0c08d136493b1db1af807486db10 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 24 May 2022 14:46:47 +0200 Subject: [PATCH 05/14] Update deps --- composer.lock | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/composer.lock b/composer.lock index 718e800cd..d5437dabf 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "composer/ca-bundle", - "version": "1.3.1", + "version": "1.3.2", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b" + "reference": "fd5dd441932a7e10ca6e5b490e272d34c8430640" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b", - "reference": "4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/fd5dd441932a7e10ca6e5b490e272d34c8430640", + "reference": "fd5dd441932a7e10ca6e5b490e272d34c8430640", "shasum": "" }, "require": { @@ -64,7 +64,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.3.1" + "source": "https://github.com/composer/ca-bundle/tree/1.3.2" }, "funding": [ { @@ -80,7 +80,7 @@ "type": "tidelift" } ], - "time": "2021-10-28T20:44:15+00:00" + "time": "2022-05-24T11:56:16+00:00" }, { "name": "composer/metadata-minifier", @@ -305,16 +305,16 @@ }, { "name": "composer/spdx-licenses", - "version": "1.5.6", + "version": "1.5.7", "source": { "type": "git", "url": "https://github.com/composer/spdx-licenses.git", - "reference": "a30d487169d799745ca7280bc90fdfa693536901" + "reference": "c848241796da2abf65837d51dce1fae55a960149" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/a30d487169d799745ca7280bc90fdfa693536901", - "reference": "a30d487169d799745ca7280bc90fdfa693536901", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/c848241796da2abf65837d51dce1fae55a960149", + "reference": "c848241796da2abf65837d51dce1fae55a960149", "shasum": "" }, "require": { @@ -365,7 +365,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/spdx-licenses/issues", - "source": "https://github.com/composer/spdx-licenses/tree/1.5.6" + "source": "https://github.com/composer/spdx-licenses/tree/1.5.7" }, "funding": [ { @@ -381,7 +381,7 @@ "type": "tidelift" } ], - "time": "2021-11-18T10:14:14+00:00" + "time": "2022-05-23T07:37:50+00:00" }, { "name": "composer/xdebug-handler", @@ -451,16 +451,16 @@ }, { "name": "justinrainbow/json-schema", - "version": "5.2.11", + "version": "5.2.12", "source": { "type": "git", "url": "https://github.com/justinrainbow/json-schema.git", - "reference": "2ab6744b7296ded80f8cc4f9509abbff393399aa" + "reference": "ad87d5a5ca981228e0e205c2bc7dfb8e24559b60" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/2ab6744b7296ded80f8cc4f9509abbff393399aa", - "reference": "2ab6744b7296ded80f8cc4f9509abbff393399aa", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/ad87d5a5ca981228e0e205c2bc7dfb8e24559b60", + "reference": "ad87d5a5ca981228e0e205c2bc7dfb8e24559b60", "shasum": "" }, "require": { @@ -515,9 +515,9 @@ ], "support": { "issues": "https://github.com/justinrainbow/json-schema/issues", - "source": "https://github.com/justinrainbow/json-schema/tree/5.2.11" + "source": "https://github.com/justinrainbow/json-schema/tree/5.2.12" }, - "time": "2021-07-22T09:24:00+00:00" + "time": "2022-04-13T08:02:27+00:00" }, { "name": "psr/log", @@ -1682,5 +1682,5 @@ "platform-overrides": { "php": "5.3.9" }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.3.0" } From 865886e5c5d8d0fe1877da967ae6c087993c0a26 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 24 May 2022 17:35:50 +0200 Subject: [PATCH 06/14] Always show deprecation notices even if silenced --- src/Composer/Util/ErrorHandler.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Composer/Util/ErrorHandler.php b/src/Composer/Util/ErrorHandler.php index 80a0f9eed..5fa1a3dd3 100644 --- a/src/Composer/Util/ErrorHandler.php +++ b/src/Composer/Util/ErrorHandler.php @@ -38,8 +38,10 @@ class ErrorHandler */ public static function handle(int $level, string $message, string $file, int $line): bool { + $isDeprecationNotice = $level === E_DEPRECATED || $level === E_USER_DEPRECATED; + // error code is not included in error_reporting - if (!(error_reporting() & $level)) { + if (!$isDeprecationNotice && !(error_reporting() & $level)) { return true; } @@ -48,7 +50,7 @@ class ErrorHandler "\na legitimately suppressed error that you were not supposed to see."; } - if ($level !== E_DEPRECATED && $level !== E_USER_DEPRECATED) { + if (!$isDeprecationNotice) { throw new \ErrorException($message, 0, $level, $file, $line); } From 654ecc759a021d27c011519d74483b0ed5ba095c Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 24 May 2022 21:21:47 +0200 Subject: [PATCH 07/14] Check that symlink function exists before using it in path repo, fixes #10786 --- src/Composer/Downloader/PathDownloader.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Composer/Downloader/PathDownloader.php b/src/Composer/Downloader/PathDownloader.php index 5482bf43d..0a09fc4a8 100644 --- a/src/Composer/Downloader/PathDownloader.php +++ b/src/Composer/Downloader/PathDownloader.php @@ -279,6 +279,15 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter $allowedStrategies = array(self::STRATEGY_MIRROR); } + // Check we can use symlink() otherwise + if (!Platform::isWindows() && self::STRATEGY_SYMLINK === $currentStrategy && !function_exists('symlink')) { + if (!in_array(self::STRATEGY_MIRROR, $allowedStrategies, true)) { + throw new \RuntimeException('Your PHP has the symlink() function disabled which does not allow Composer to use symlinks and this path repository has symlink:true in its options so copying is not allowed'); + } + $currentStrategy = self::STRATEGY_MIRROR; + $allowedStrategies = array(self::STRATEGY_MIRROR); + } + return array($currentStrategy, $allowedStrategies); } From 25542aca7095edfb47467c0bf3f1e9f8c2707dbc Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 24 May 2022 21:26:37 +0200 Subject: [PATCH 08/14] Update baseline --- phpstan/baseline.neon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpstan/baseline.neon b/phpstan/baseline.neon index a3f616c0c..ac39f66e8 100644 --- a/phpstan/baseline.neon +++ b/phpstan/baseline.neon @@ -3472,7 +3472,7 @@ parameters: - message: "#^Call to function in_array\\(\\) with arguments 20, array\\{0\\: 10\\|20, 1\\?\\: 20\\} and true will always evaluate to true\\.$#" - count: 1 + count: 2 path: ../src/Composer/Downloader/PathDownloader.php - From 88e1f0f9b58e677a85ac2661f632926a439ee7e8 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 24 May 2022 21:32:36 +0200 Subject: [PATCH 09/14] Make sure repos are always initialized with a repo manager if possible, and make sure async is always enabled on the process executor, fixes #10783 (#10799) --- src/Composer/Command/ArchiveCommand.php | 2 +- .../Command/BaseDependencyCommand.php | 3 +- src/Composer/Command/HomeCommand.php | 2 +- src/Composer/Command/InitCommand.php | 7 +++- .../Command/PackageDiscoveryTrait.php | 2 +- src/Composer/Command/ShowCommand.php | 4 +- src/Composer/Repository/RepositoryFactory.php | 37 ++++++++++++++++--- .../DependencyResolver/PoolBuilderTest.php | 4 +- 8 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/Composer/Command/ArchiveCommand.php b/src/Composer/Command/ArchiveCommand.php index fa450a6da..a35f3aecf 100644 --- a/src/Composer/Command/ArchiveCommand.php +++ b/src/Composer/Command/ArchiveCommand.php @@ -159,7 +159,7 @@ EOT $localRepo = $composer->getRepositoryManager()->getLocalRepository(); $repo = new CompositeRepository(array_merge(array($localRepo), $composer->getRepositoryManager()->getRepositories())); } else { - $defaultRepos = RepositoryFactory::defaultRepos($this->getIO()); + $defaultRepos = RepositoryFactory::defaultReposWithDefaultManager($io); $io->writeError('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos))); $repo = new CompositeRepository($defaultRepos); } diff --git a/src/Composer/Command/BaseDependencyCommand.php b/src/Composer/Command/BaseDependencyCommand.php index 7222319ff..2d4dea40f 100644 --- a/src/Composer/Command/BaseDependencyCommand.php +++ b/src/Composer/Command/BaseDependencyCommand.php @@ -18,6 +18,7 @@ use Composer\Package\CompletePackageInterface; use Composer\Package\RootPackage; use Composer\Repository\InstalledArrayRepository; use Composer\Repository\CompositeRepository; +use Composer\Repository\RepositoryInterface; use Composer\Repository\RootPackageRepository; use Composer\Repository\InstalledRepository; use Composer\Repository\PlatformRepository; @@ -80,7 +81,7 @@ abstract class BaseDependencyCommand extends BaseCommand // If the version we ask for is not installed then we need to locate it in remote repos and add it. // This is needed for why-not to resolve conflicts from an uninstalled version against installed packages. if (!$installedRepo->findPackage($needle, $textConstraint)) { - $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO())); + $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO(), $composer->getConfig(), $composer->getRepositoryManager())); if ($match = $defaultRepos->findPackage($needle, $textConstraint)) { $installedRepo->addRepository(new InstalledArrayRepository(array(clone $match))); } diff --git a/src/Composer/Command/HomeCommand.php b/src/Composer/Command/HomeCommand.php index dad4e3a75..c4457ac4c 100644 --- a/src/Composer/Command/HomeCommand.php +++ b/src/Composer/Command/HomeCommand.php @@ -170,6 +170,6 @@ EOT ); } - return RepositoryFactory::defaultRepos($this->getIO()); + return RepositoryFactory::defaultReposWithDefaultManager($this->getIO()); } } diff --git a/src/Composer/Command/InitCommand.php b/src/Composer/Command/InitCommand.php index f923f6929..ae8bc6c9b 100644 --- a/src/Composer/Command/InitCommand.php +++ b/src/Composer/Command/InitCommand.php @@ -225,6 +225,9 @@ EOT $repositories = $input->getOption('repository'); if (count($repositories) > 0) { $config = Factory::createConfig($io); + $io->loadConfiguration($config); + $repoManager = RepositoryFactory::manager($io, $config); + $repos = array(new PlatformRepository); $createDefaultPackagistRepo = true; foreach ($repositories as $repo) { @@ -236,14 +239,14 @@ EOT $createDefaultPackagistRepo = false; continue; } - $repos[] = RepositoryFactory::createRepo($io, $config, $repoConfig); + $repos[] = RepositoryFactory::createRepo($io, $config, $repoConfig, $repoManager); } if ($createDefaultPackagistRepo) { $repos[] = RepositoryFactory::createRepo($io, $config, array( 'type' => 'composer', 'url' => 'https://repo.packagist.org', - )); + ), $repoManager); } $this->repos = new CompositeRepository($repos); diff --git a/src/Composer/Command/PackageDiscoveryTrait.php b/src/Composer/Command/PackageDiscoveryTrait.php index 99fb0f39b..5e210bd7c 100644 --- a/src/Composer/Command/PackageDiscoveryTrait.php +++ b/src/Composer/Command/PackageDiscoveryTrait.php @@ -47,7 +47,7 @@ trait PackageDiscoveryTrait if (null === $this->repos) { $this->repos = new CompositeRepository(array_merge( array(new PlatformRepository), - RepositoryFactory::defaultRepos($this->getIO()) + RepositoryFactory::defaultReposWithDefaultManager($this->getIO()) )); } diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index 0194662b7..72242073b 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -194,7 +194,7 @@ EOT $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories()); $installedRepo->addRepository($composer->getRepositoryManager()->getLocalRepository()); } else { - $defaultRepos = RepositoryFactory::defaultRepos($io); + $defaultRepos = RepositoryFactory::defaultReposWithDefaultManager($io); $repos = new CompositeRepository($defaultRepos); $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos))); } @@ -209,7 +209,7 @@ EOT } $repos = new CompositeRepository(array_merge(array(new FilterRepository($installedRepo, array('canonical' => false))), $composer->getRepositoryManager()->getRepositories())); } elseif ($input->getOption('all')) { - $defaultRepos = RepositoryFactory::defaultRepos($io); + $defaultRepos = RepositoryFactory::defaultReposWithDefaultManager($io); $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos))); $installedRepo = new InstalledRepository(array($platformRepo)); $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos)); diff --git a/src/Composer/Repository/RepositoryFactory.php b/src/Composer/Repository/RepositoryFactory.php index b31f77530..e24fa1596 100644 --- a/src/Composer/Repository/RepositoryFactory.php +++ b/src/Composer/Repository/RepositoryFactory.php @@ -80,7 +80,8 @@ class RepositoryFactory public static function createRepo(IOInterface $io, Config $config, array $repoConfig, RepositoryManager $rm = null): RepositoryInterface { if (!$rm) { - $rm = static::manager($io, $config, Factory::createHttpDownloader($io, $config)); + @trigger_error('Not passing a repository manager when calling createRepo is deprecated since Composer 2.3.6', E_USER_DEPRECATED); + $rm = static::manager($io, $config); } $repos = self::createRepos($rm, array($repoConfig)); @@ -95,14 +96,18 @@ class RepositoryFactory */ public static function defaultRepos(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null): array { - if (!$config) { + if (null === $rm) { + @trigger_error('Not passing a repository manager when calling defaultRepos is deprecated since Composer 2.3.6, use defaultReposWithDefaultManager() instead if you cannot get a manager.', E_USER_DEPRECATED); + } + + if (null === $config) { $config = Factory::createConfig($io); } - if ($io) { + if (null !== $io) { $io->loadConfiguration($config); } - if (!$rm) { - if (!$io) { + if (null === $rm) { + if (null === $io) { throw new \InvalidArgumentException('This function requires either an IOInterface or a RepositoryManager'); } $rm = static::manager($io, $config, Factory::createHttpDownloader($io, $config)); @@ -118,8 +123,16 @@ class RepositoryFactory * @param HttpDownloader $httpDownloader * @return RepositoryManager */ - public static function manager(IOInterface $io, Config $config, HttpDownloader $httpDownloader, EventDispatcher $eventDispatcher = null, ProcessExecutor $process = null): RepositoryManager + public static function manager(IOInterface $io, Config $config, HttpDownloader $httpDownloader = null, EventDispatcher $eventDispatcher = null, ProcessExecutor $process = null): RepositoryManager { + if ($httpDownloader === null) { + $httpDownloader = Factory::createHttpDownloader($io, $config); + } + if ($process === null) { + $process = new ProcessExecutor($io); + $process->enableAsync(); + } + $rm = new RepositoryManager($io, $config, $httpDownloader, $eventDispatcher, $process); $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository'); $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository'); @@ -140,6 +153,18 @@ class RepositoryFactory return $rm; } + /** + * @return RepositoryInterface[] + */ + public static function defaultReposWithDefaultManager(IOInterface $io): array + { + $manager = RepositoryFactory::manager($io, $config = Factory::createConfig($io)); + $io->loadConfiguration($config); + + return RepositoryFactory::defaultRepos($io, $config, $manager); + } + + /** * @param array $repoConfigs * diff --git a/tests/Composer/Test/DependencyResolver/PoolBuilderTest.php b/tests/Composer/Test/DependencyResolver/PoolBuilderTest.php index 7e6249113..316fd82b5 100644 --- a/tests/Composer/Test/DependencyResolver/PoolBuilderTest.php +++ b/tests/Composer/Test/DependencyResolver/PoolBuilderTest.php @@ -87,9 +87,11 @@ class PoolBuilderTest extends TestCase chdir(__DIR__.'/Fixtures/poolbuilder/'); $repositorySet = new RepositorySet($minimumStability, $stabilityFlags, $rootAliases, $rootReferences); + $config = new Config(false); + $rm = RepositoryFactory::manager($io = new NullIO(), $config); foreach ($packageRepos as $packages) { if (isset($packages['type'])) { - $repo = RepositoryFactory::createRepo(new NullIO, new Config(false), $packages); + $repo = RepositoryFactory::createRepo($io, $config, $packages, $rm); $repositorySet->addRepository($repo); continue; } From 10d3895f187b0be4346781eac5788e15753b2d7c Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 24 May 2022 22:14:17 +0200 Subject: [PATCH 10/14] Ensure that dotfiles can be excluded, fixes #8866 --- .../Test/Package/Archiver/ArchivableFilesFinderTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php b/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php index 6aad38c2c..bd5cffe05 100644 --- a/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php +++ b/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php @@ -43,6 +43,7 @@ class ArchivableFilesFinderTest extends TestCase ); $fileTree = array( + '.foo', 'A/prefixA.foo', 'A/prefixB.foo', 'A/prefixC.foo', @@ -109,6 +110,7 @@ class ArchivableFilesFinderTest extends TestCase '/prefixA.foo', 'prefixC.*', '!*/*/*/prefixC.foo', + '.*', ); $this->finder = new ArchivableFilesFinder($this->sources, $excludes); @@ -213,6 +215,7 @@ class ArchivableFilesFinderTest extends TestCase '/!important!.txt', '/!important_too!.txt', '/#weirdfile', + '/.foo', '/A/prefixA.foo', '/A/prefixB.foo', '/A/prefixC.foo', From 86dcc7ac23a548ae6ffcacff44e8ed304b7c4686 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 25 May 2022 21:36:44 +0200 Subject: [PATCH 11/14] Update changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ff872a26..ccca38d77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +### [2.2.13] 2022-05-25 + + * Fixed invalid credentials loop when setting up GitLab token (#10748) + * Fixed PHP 8.2 deprecations (#10766) + * Fixed lock file changes being output even when the lock file creation is disabled + * Fixed race condition when multiple requests asking for auth on the same hostname fired concurrently (#10763) + * Fixed quoting of commas on Windows (#10775) + * Fixed issue installing path repos with a disabled symlink function (#10786) + ### [2.2.12] 2022-04-13 * Security: Fixed command injection vulnerability in HgDriver/GitDriver (GHSA-x7cr-6qr6-2hh6 / CVE-2022-24828) @@ -1427,6 +1436,7 @@ * Initial release +[2.2.13]: https://github.com/composer/composer/compare/2.2.12...2.2.13 [2.2.12]: https://github.com/composer/composer/compare/2.2.11...2.2.12 [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 From de11c9819ac45659fb0fafb2e704912f9994ed60 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 25 May 2022 21:37:25 +0200 Subject: [PATCH 12/14] Release 2.2.13 --- 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..3f837a9bb 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.13'; + const BRANCH_ALIAS_VERSION = ''; + const RELEASE_DATE = '2022-05-25 21:37:25'; + const SOURCE_VERSION = ''; /** * Version number of the internal composer-runtime-api package From 5d353716d3baa636e48021e2c208a24265c3caff Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 25 May 2022 21:37:26 +0200 Subject: [PATCH 13/14] 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 3f837a9bb..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.13'; - const BRANCH_ALIAS_VERSION = ''; - const RELEASE_DATE = '2022-05-25 21:37:25'; - 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 From 5b067a1b298bf9485015df76b5cab0777a92b964 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 25 May 2022 22:02:22 +0200 Subject: [PATCH 14/14] Update phpstan to latest --- composer.lock | 12 ++++++------ src/Composer/Console/Application.php | 3 ++- src/Composer/DependencyResolver/RuleSetIterator.php | 4 ++-- src/Composer/Package/BasePackage.php | 1 - src/Composer/Util/Platform.php | 3 +++ 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/composer.lock b/composer.lock index 6c6c67a8c..5850e2813 100644 --- a/composer.lock +++ b/composer.lock @@ -1825,16 +1825,16 @@ "packages-dev": [ { "name": "phpstan/phpstan", - "version": "1.6.8", + "version": "1.7.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "d76498c5531232cb8386ceb6004f7e013138d3ba" + "reference": "e3baed2ee2ef322e0f9b8fe8f87fdbe024c7c719" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/d76498c5531232cb8386ceb6004f7e013138d3ba", - "reference": "d76498c5531232cb8386ceb6004f7e013138d3ba", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e3baed2ee2ef322e0f9b8fe8f87fdbe024c7c719", + "reference": "e3baed2ee2ef322e0f9b8fe8f87fdbe024c7c719", "shasum": "" }, "require": { @@ -1860,7 +1860,7 @@ "description": "PHPStan - PHP Static Analysis Tool", "support": { "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.6.8" + "source": "https://github.com/phpstan/phpstan/tree/1.7.1" }, "funding": [ { @@ -1880,7 +1880,7 @@ "type": "tidelift" } ], - "time": "2022-05-10T06:54:21+00:00" + "time": "2022-05-24T09:05:09+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index ba140a149..dac353a94 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -135,7 +135,8 @@ class Application extends BaseApplication $this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins'); $this->disableScriptsByDefault = $input->hasParameterOption('--no-scripts'); - if (Platform::getEnv('COMPOSER_NO_INTERACTION') || !Platform::isTty(defined('STDIN') ? STDIN : fopen('php://stdin', 'r'))) { + $stdin = defined('STDIN') ? STDIN : fopen('php://stdin', 'r'); + if (Platform::getEnv('COMPOSER_NO_INTERACTION') || $stdin === false || !Platform::isTty($stdin)) { $input->setInteractive(false); } diff --git a/src/Composer/DependencyResolver/RuleSetIterator.php b/src/Composer/DependencyResolver/RuleSetIterator.php index 3d30c5d7e..2bf67f55b 100644 --- a/src/Composer/DependencyResolver/RuleSetIterator.php +++ b/src/Composer/DependencyResolver/RuleSetIterator.php @@ -75,7 +75,7 @@ class RuleSetIterator implements \Iterator } $this->currentType = $this->types[$this->currentTypeOffset]; - } while (isset($this->types[$this->currentTypeOffset]) && !\count($this->rules[$this->currentType])); + } while (0 === \count($this->rules[$this->currentType])); } } @@ -95,7 +95,7 @@ class RuleSetIterator implements \Iterator } $this->currentType = $this->types[$this->currentTypeOffset]; - } while (isset($this->types[$this->currentTypeOffset]) && !\count($this->rules[$this->currentType])); + } while (0 === \count($this->rules[$this->currentType])); } public function valid(): bool diff --git a/src/Composer/Package/BasePackage.php b/src/Composer/Package/BasePackage.php index b815aec53..df9b3ce29 100644 --- a/src/Composer/Package/BasePackage.php +++ b/src/Composer/Package/BasePackage.php @@ -53,7 +53,6 @@ abstract class BasePackage implements PackageInterface * READ-ONLY: The package id, public for fast access in dependency solver * @var int * @internal - * @readonly */ public $id; /** @var string */ diff --git a/src/Composer/Util/Platform.php b/src/Composer/Util/Platform.php index be37ba621..d27bda08c 100644 --- a/src/Composer/Util/Platform.php +++ b/src/Composer/Util/Platform.php @@ -201,6 +201,9 @@ class Platform { if ($fd === null) { $fd = defined('STDOUT') ? STDOUT : fopen('php://stdout', 'w'); + if ($fd === false) { + return false; + } } // detect msysgit/mingw and assume this is a tty because detection