From 285ea67245692ec23529f47a2264cd2c95bad3d3 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 22 Jan 2026 14:08:50 +0100 Subject: [PATCH 01/11] 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 df01ad3a0d77..6c654cc212c3 100644 --- a/src/Composer/Composer.php +++ b/src/Composer/Composer.php @@ -51,10 +51,10 @@ class Composer extends PartialComposer * * @see getVersion() */ - public const VERSION = '2.9.4'; - public const BRANCH_ALIAS_VERSION = ''; - public const RELEASE_DATE = '2026-01-22 14:08:50'; - public const SOURCE_VERSION = ''; + public const VERSION = '@package_version@'; + public const BRANCH_ALIAS_VERSION = '@package_branch_alias_version@'; + public const RELEASE_DATE = '@release_date@'; + public const SOURCE_VERSION = '2.9.999-dev+source'; /** * Version number of the internal composer-runtime-api package From defa1bb2ee520c276d839613d9287fcf441c79e4 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 26 Jan 2026 09:57:34 +0100 Subject: [PATCH 02/11] Add info about downloading using gh util --- doc/faqs/how-to-install-composer-programmatically.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/faqs/how-to-install-composer-programmatically.md b/doc/faqs/how-to-install-composer-programmatically.md index 2433c048423b..ee017552f5dc 100644 --- a/doc/faqs/how-to-install-composer-programmatically.md +++ b/doc/faqs/how-to-install-composer-programmatically.md @@ -40,3 +40,14 @@ wget https://raw.githubusercontent.com/composer/getcomposer.org/f3108f64b4e1c1ce You may replace the commit hash by whatever the last commit hash is on https://github.com/composer/getcomposer.org/commits/main + +## Using the GitHub CLI util (`gh`) + +You can download and verify a `composer.phar` using the gh CLI utility as such: + +```shell +gh release --repo composer/composer download --pattern composer.phar +gh attestation verify --repo composer/composer composer.phar +``` + +Use the composer.phar as is or move it where needed afterwards. From 2102496eb4fdc04bfd64870e5ffb6e4599f5870a Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 28 Jan 2026 13:11:48 +0100 Subject: [PATCH 03/11] Revert "Work around issue with msys/rmdir on windows (#12726)" This reverts commit 4fa255cafa099309f2511fd8933710c1e9631112. --- src/Composer/Util/Filesystem.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index 1c515d7c3c11..0fbd2a1e468a 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -109,12 +109,6 @@ public function removeDirectory(string $directory) } if (Platform::isWindows()) { - // Work around bug on MSYS for safety if the path contains an equal sign, see https://github.com/composer/composer/issues/11568 - // TODO remove if https://github.com/symfony/symfony/issues/62921 is fixed and we can upgrade to a version with the fix - if (str_contains($directory, '=')) { - return $this->removeDirectoryPhp($directory); - } - $cmd = ['rmdir', '/S', '/Q', Platform::realpath($directory)]; } else { $cmd = ['rm', '-rf', $directory]; @@ -150,12 +144,6 @@ public function removeDirectoryAsync(string $directory) } if (Platform::isWindows()) { - // Work around bug on MSYS for safety if the path contains an equal sign, see https://github.com/composer/composer/issues/11568 - // TODO remove if https://github.com/symfony/symfony/issues/62921 is fixed and we can upgrade to a version with the fix - if (str_contains($directory, '=')) { - return \React\Promise\resolve($this->removeDirectoryPhp($directory)); - } - $cmd = ['rmdir', '/S', '/Q', Platform::realpath($directory)]; } else { $cmd = ['rm', '-rf', $directory]; From 9861166fb61724999a72ec5dbc947fed557d8763 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 28 Jan 2026 13:12:13 +0100 Subject: [PATCH 04/11] Update symfony/process to fix #12726 --- composer.lock | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index 0fd3612d1301..94d442b3df3e 100644 --- a/composer.lock +++ b/composer.lock @@ -1967,16 +1967,16 @@ }, { "name": "symfony/process", - "version": "v5.4.47", + "version": "v5.4.51", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "5d1662fb32ebc94f17ddb8d635454a776066733d" + "reference": "467bfc56f18f5ef6d5ccb09324d7e988c1c0a98f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/5d1662fb32ebc94f17ddb8d635454a776066733d", - "reference": "5d1662fb32ebc94f17ddb8d635454a776066733d", + "url": "https://api.github.com/repos/symfony/process/zipball/467bfc56f18f5ef6d5ccb09324d7e988c1c0a98f", + "reference": "467bfc56f18f5ef6d5ccb09324d7e988c1c0a98f", "shasum": "" }, "require": { @@ -2009,7 +2009,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.4.47" + "source": "https://github.com/symfony/process/tree/v5.4.51" }, "funding": [ { @@ -2020,12 +2020,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-06T11:36:42+00:00" + "time": "2026-01-26T15:53:37+00:00" }, { "name": "symfony/service-contracts", From 06c273b3de49a5d9a2fab7787c1cfd99590c94cc Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Thu, 29 Jan 2026 09:42:01 +0000 Subject: [PATCH 05/11] Add support for PIE list of download-url-methods (#12727) --- res/composer-schema.json | 26 +++++-- .../Package/Loader/ValidatingArrayLoader.php | 25 +++++-- src/Composer/Package/PackageInterface.php | 2 +- .../Loader/ValidatingArrayLoaderTest.php | 69 ++++++++++++++++++- 4 files changed, 110 insertions(+), 12 deletions(-) diff --git a/res/composer-schema.json b/res/composer-schema.json index 13dae646a680..c4661da5a526 100644 --- a/res/composer-schema.json +++ b/res/composer-schema.json @@ -324,10 +324,28 @@ "default": null }, "download-url-method": { - "type": "string", - "description": "If specified, this technique will be used to override the URL that PIE uses to download the asset. The default, if not specified, is composer-default.", - "enum": ["composer-default", "pre-packaged-source"], - "example": "composer-default" + "oneOf": [ + { + "type": "string", + "description": "If specified, this technique will be used to override the URL that PIE uses to download the asset. The default, if not specified, is composer-default.", + "deprecated": true, + "enum": ["composer-default", "pre-packaged-source", "pre-packaged-binary"], + "example": "composer-default", + "default": "composer-default" + }, + { + "type": "array", + "description": "Multiple techniques can be specified, in which case PIE will try each in turn until one succeeds. The first technique that succeeds will be used.", + "items": { + "type": "string", + "description": "If specified, this technique will be used to override the URL that PIE uses to download the asset. The default, if not specified, is composer-default.", + "enum": ["composer-default", "pre-packaged-source", "pre-packaged-binary"], + "example": ["pre-packaged-binary", "composer-default"] + }, + "minItems": 1, + "default": ["composer-default"] + } + ] }, "os-families": { "type": "array", diff --git a/src/Composer/Package/Loader/ValidatingArrayLoader.php b/src/Composer/Package/Loader/ValidatingArrayLoader.php index 9653e16322e0..80b03fc6fb19 100644 --- a/src/Composer/Package/Loader/ValidatingArrayLoader.php +++ b/src/Composer/Package/Loader/ValidatingArrayLoader.php @@ -302,12 +302,27 @@ public function load(array $config, string $class = 'Composer\Package\CompletePa } if (isset($phpExt['download-url-method'])) { - if (!is_string($phpExt['download-url-method'])) { - $this->errors[] = 'php-ext.download-url-method : should be a string, '.get_debug_type($phpExt['download-url-method']).' given'; - unset($phpExt['download-url-method']); - } elseif (!in_array($phpExt['download-url-method'], ['composer-default', 'pre-packaged-source'], true)) { - $this->errors[] = 'php-ext.download-url-method : invalid value ('.$phpExt['download-url-method'].'), must be one of composer-default, pre-packaged-source'; + if (!is_array($phpExt['download-url-method']) && !is_string($phpExt['download-url-method'])) { + $this->errors[] = 'php-ext.download-url-method : should be an array or a string, '.get_debug_type($phpExt['download-url-method']).' given'; unset($phpExt['download-url-method']); + } else { + $validDownloadUrlMethods = ['composer-default', 'pre-packaged-source', 'pre-packaged-binary']; + $definedDownloadUrlMethods = is_array($phpExt['download-url-method']) ? $phpExt['download-url-method'] : [$phpExt['download-url-method']]; + + if ([] === $definedDownloadUrlMethods) { + $this->errors[] = 'php-ext.download-url-method : must contain at least one element'; + unset($phpExt['download-url-method']); + } else { + foreach ($definedDownloadUrlMethods as $key => $downloadUrlMethod) { + if (!is_string($downloadUrlMethod)) { + $this->errors[] = 'php-ext.download-url-method.'.$key.' : should be a string, '.get_debug_type($downloadUrlMethod).' given'; + unset($phpExt['download-url-method']); + } elseif (!in_array($downloadUrlMethod, $validDownloadUrlMethods, true)) { + $this->errors[] = 'php-ext.download-url-method.'.$key.' : invalid value ('.$downloadUrlMethod.'), must be one of ' . implode(', ', $validDownloadUrlMethods); + unset($phpExt['download-url-method']); + } + } + } } } diff --git a/src/Composer/Package/PackageInterface.php b/src/Composer/Package/PackageInterface.php index adf1060be18f..0bfece430df7 100644 --- a/src/Composer/Package/PackageInterface.php +++ b/src/Composer/Package/PackageInterface.php @@ -23,7 +23,7 @@ * * @phpstan-type AutoloadRules array{psr-0?: array, psr-4?: array, classmap?: list, files?: list, exclude-from-classmap?: list} * @phpstan-type DevAutoloadRules array{psr-0?: array, psr-4?: array, classmap?: list, files?: list} - * @phpstan-type PhpExtConfig array{extension-name?: string, priority?: int, support-zts?: bool, support-nts?: bool, build-path?: string|null, download-url-method?: string, os-families?: non-empty-list, os-families-exclude?: non-empty-list, configure-options?: list} + * @phpstan-type PhpExtConfig array{extension-name?: string, priority?: int, support-zts?: bool, support-nts?: bool, build-path?: string|null, download-url-method?: string|list, os-families?: non-empty-list, os-families-exclude?: non-empty-list, configure-options?: list} */ interface PackageInterface { diff --git a/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php b/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php index 05a610d035e1..eea2db804521 100644 --- a/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php +++ b/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php @@ -242,6 +242,24 @@ public static function successProvider(): array ], ], ], + [ // valid php-ext with one download-url-method in a list + [ + 'name' => 'foo/bar', + 'type' => 'php-ext', + 'php-ext' => [ + 'download-url-method' => ['pre-packaged-binary'], + ], + ], + ], + [ // valid php-ext with multiple download-url-methods + [ + 'name' => 'foo/bar', + 'type' => 'php-ext', + 'php-ext' => [ + 'download-url-method' => ['pre-packaged-binary', 'pre-packaged-source', 'composer-default'], + ], + ], + ], ]; } @@ -537,7 +555,7 @@ public static function errorProvider(): array 'download-url-method' => 123, ], ], - ['php-ext.download-url-method : should be a string, int given'], + ['php-ext.download-url-method : should be an array or a string, int given'], ], [ [ @@ -547,7 +565,54 @@ public static function errorProvider(): array 'download-url-method' => 'invalid-method', ], ], - ['php-ext.download-url-method : invalid value (invalid-method), must be one of composer-default, pre-packaged-source'], + ['php-ext.download-url-method.0 : invalid value (invalid-method), must be one of composer-default, pre-packaged-source, pre-packaged-binary'], + ], + [ + [ + 'name' => 'foo/bar', + 'type' => 'php-ext', + 'php-ext' => [ + 'download-url-method' => [], + ], + ], + ['php-ext.download-url-method : must contain at least one element'], + ], + [ + [ + 'name' => 'foo/bar', + 'type' => 'php-ext', + 'php-ext' => [ + 'download-url-method' => [1, true, []], + ], + ], + [ + 'php-ext.download-url-method.0 : should be a string, int given', + 'php-ext.download-url-method.1 : should be a string, bool given', + 'php-ext.download-url-method.2 : should be a string, array given', + ], + ], + [ + [ + 'name' => 'foo/bar', + 'type' => 'php-ext', + 'php-ext' => [ + 'download-url-method' => ['invalid-method', 'composer-default'], + ], + ], + ['php-ext.download-url-method.0 : invalid value (invalid-method), must be one of composer-default, pre-packaged-source, pre-packaged-binary'], + ], + [ + [ + 'name' => 'foo/bar', + 'type' => 'php-ext', + 'php-ext' => [ + 'download-url-method' => ['invalid-method', 'another-invalid-method'], + ], + ], + [ + 'php-ext.download-url-method.0 : invalid value (invalid-method), must be one of composer-default, pre-packaged-source, pre-packaged-binary', + 'php-ext.download-url-method.1 : invalid value (another-invalid-method), must be one of composer-default, pre-packaged-source, pre-packaged-binary', + ], ], [ [ From e6022328165b2b3d663a5523029d6717887a78b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Jan 2026 10:42:13 +0100 Subject: [PATCH 06/11] Bump actions/checkout from 6.0.1 to 6.0.2 (#12729) Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.1 to 6.0.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8e8c483db84b4bee98b60c0593521ed34d9990e8...de0fac2e4500dabe0009e67214ff5f5447ce83dd) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/autoloader.yml | 2 +- .github/workflows/conductor.yaml | 2 +- .github/workflows/continuous-integration.yml | 4 ++-- .github/workflows/lint.yml | 2 +- .github/workflows/php32bit.yml | 2 +- .github/workflows/phpstan.yml | 2 +- .github/workflows/release.yml | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/autoloader.yml b/.github/workflows/autoloader.yml index e40bd3688f15..23a681fd9b6b 100644 --- a/.github/workflows/autoloader.yml +++ b/.github/workflows/autoloader.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: "Install Composer dependencies" run: "composer config platform --unset && composer install" diff --git a/.github/workflows/conductor.yaml b/.github/workflows/conductor.yaml index 6e524c3676eb..a5db05e6f05e 100644 --- a/.github/workflows/conductor.yaml +++ b/.github/workflows/conductor.yaml @@ -16,7 +16,7 @@ jobs: runs-on: "ubuntu-latest" steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # Install PHP. You can also replace this step by # reusing an existing workflow that sets up PHP. diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 0bcfd717a63c..821e57bc7af3 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -67,7 +67,7 @@ jobs: experimental: true steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # 2.36.0 with: @@ -138,7 +138,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # 2.36.0 with: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 07b673ab8705..ea8656b6fe62 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -24,7 +24,7 @@ jobs: - "nightly" steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # 2.36.0 with: diff --git a/.github/workflows/php32bit.yml b/.github/workflows/php32bit.yml index 5bb84889cd59..e09b818a914c 100644 --- a/.github/workflows/php32bit.yml +++ b/.github/workflows/php32bit.yml @@ -22,7 +22,7 @@ jobs: container: shivammathur/node:latest-i386 steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # 2.36.0 with: diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index fb39cc31367b..45d63bd025b1 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -32,7 +32,7 @@ jobs: fail-fast: false steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # 2.36.0 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f2f450ae7f6d..81cfbb37735f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: name: Upload Release Asset runs-on: ubuntu-latest steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # 2.36.0 with: From 4c49f46d57c58c7f1c0fa165078abeb8549b4441 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Jan 2026 10:42:19 +0100 Subject: [PATCH 07/11] Bump actions/attest-build-provenance from 3.1.0 to 3.2.0 (#12728) Bumps [actions/attest-build-provenance](https://github.com/actions/attest-build-provenance) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/attest-build-provenance/releases) - [Changelog](https://github.com/actions/attest-build-provenance/blob/main/RELEASE.md) - [Commits](https://github.com/actions/attest-build-provenance/compare/00014ed6ed5efc5b1ab7f7f34a39eb55d41aa4f8...96278af6caaf10aea03fd8d33a09a777ca52d62f) --- updated-dependencies: - dependency-name: actions/attest-build-provenance dependency-version: 3.2.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 81cfbb37735f..19ba58e6b8a2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,7 +42,7 @@ jobs: run: "php -d phar.readonly=0 bin/compile" - name: Generate build provenance attestation - uses: actions/attest-build-provenance@00014ed6ed5efc5b1ab7f7f34a39eb55d41aa4f8 # v3.1.0 + uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3.2.0 with: subject-path: '${{ github.workspace }}/composer.phar' From 5b44d62508c32906dedda4c9ee5429f2bbe5b7b0 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 29 Jan 2026 10:49:12 +0100 Subject: [PATCH 08/11] Fix detection of 7z when it is installed as 7za Fixes #12731 --- src/Composer/Command/DiagnoseCommand.php | 5 +++-- src/Composer/Downloader/ZipDownloader.php | 13 +++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Composer/Command/DiagnoseCommand.php b/src/Composer/Command/DiagnoseCommand.php index 521d614adf1b..d123861a1ac9 100644 --- a/src/Composer/Command/DiagnoseCommand.php +++ b/src/Composer/Command/DiagnoseCommand.php @@ -135,9 +135,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $bin7zip = ''; if ($hasSystem7zip = (bool) $finder->find('7z', null, ['C:\Program Files\7-Zip'])) { $bin7zip = '7z'; - } - if (!Platform::isWindows() && !$hasSystem7zip && $hasSystem7zip = (bool) $finder->find('7zz')) { + } elseif (!Platform::isWindows() && $hasSystem7zip = (bool) $finder->find('7zz')) { $bin7zip = '7zz'; + } elseif (!Platform::isWindows() && $hasSystem7zip = (bool) $finder->find('7za')) { + $bin7zip = '7za'; } $io->write( diff --git a/src/Composer/Downloader/ZipDownloader.php b/src/Composer/Downloader/ZipDownloader.php index 6ade3604e753..09b6538dd425 100644 --- a/src/Composer/Downloader/ZipDownloader.php +++ b/src/Composer/Downloader/ZipDownloader.php @@ -44,17 +44,18 @@ public function download(PackageInterface $package, string $path, ?PackageInterf if (null === self::$unzipCommands) { self::$unzipCommands = []; $finder = new ExecutableFinder; - if (Platform::isWindows() && ($cmd = $finder->find('7z', null, ['C:\Program Files\7-Zip']))) { + if (Platform::isWindows() && null !== ($cmd = $finder->find('7z', null, ['C:\Program Files\7-Zip']))) { self::$unzipCommands[] = ['7z', $cmd, 'x', '-bb0', '-y', '%file%', '-o%path%']; } - if ($cmd = $finder->find('unzip')) { + if (null !== ($cmd = $finder->find('unzip'))) { self::$unzipCommands[] = ['unzip', $cmd, '-qq', '%file%', '-d', '%path%']; } - if (!Platform::isWindows() && ($cmd = $finder->find('7z'))) { // 7z linux/macOS support is only used if unzip is not present + if (!Platform::isWindows() && null !== ($cmd = $finder->find('7z'))) { // 7z linux/macOS support is only used if unzip is not present self::$unzipCommands[] = ['7z', $cmd, 'x', '-bb0', '-y', '%file%', '-o%path%']; - } - if (!Platform::isWindows() && ($cmd = $finder->find('7zz'))) { // 7zz linux/macOS support is only used if unzip is not present + } elseif (!Platform::isWindows() && null !== ($cmd = $finder->find('7zz'))) { // 7zz linux/macOS support is only used if unzip is not present self::$unzipCommands[] = ['7zz', $cmd, 'x', '-bb0', '-y', '%file%', '-o%path%']; + } elseif (!Platform::isWindows() && null !== ($cmd = $finder->find('7za'))) { // 7za linux/macOS support is only used if unzip is not present + self::$unzipCommands[] = ['7za', $cmd, 'x', '-bb0', '-y', '%file%', '-o%path%']; } } @@ -132,7 +133,7 @@ private function extractWithSystemUnzip(PackageInterface $package, string $file, return strtr($value, $map); }, $command); - if (!$warned7ZipLinux && !Platform::isWindows() && in_array($executable, ['7z', '7zz'], true)) { + if (!$warned7ZipLinux && !Platform::isWindows() && in_array($executable, ['7z', '7zz', '7za'], true)) { $warned7ZipLinux = true; if (0 === $this->process->execute([$commandSpec[1]], $output)) { if (Preg::isMatchStrictGroups('{^\s*7-Zip(?: \[64\])? ([0-9.]+)}', $output, $match) && version_compare($match[1], '21.01', '<')) { From 3f0976b827fc81b991d502634f9b551cfe61603e Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 29 Jan 2026 11:37:57 +0100 Subject: [PATCH 09/11] Update baseline --- phpstan/baseline.neon | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/phpstan/baseline.neon b/phpstan/baseline.neon index 6280823cf369..bc0c4b549b43 100644 --- a/phpstan/baseline.neon +++ b/phpstan/baseline.neon @@ -735,16 +735,6 @@ parameters: count: 2 path: ../src/Composer/Command/ShowCommand.php - - - message: "#^Parameter \\#1 \\$string of function strlen expects string, string\\|false given\\.$#" - count: 1 - path: ../src/Composer/Command/ShowCommand.php - - - - message: "#^Parameter \\#1 \\$string of function substr expects string, string\\|false given\\.$#" - count: 1 - path: ../src/Composer/Command/ShowCommand.php - - message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, array\\\\>\\|string given\\.$#" count: 1 @@ -1310,21 +1300,11 @@ parameters: count: 1 path: ../src/Composer/Downloader/VcsDownloader.php - - - message: "#^Only booleans are allowed in &&, string\\|null given on the right side\\.$#" - count: 3 - path: ../src/Composer/Downloader/ZipDownloader.php - - message: "#^Only booleans are allowed in a negated boolean, array\\\\> given\\.$#" count: 2 path: ../src/Composer/Downloader/ZipDownloader.php - - - message: "#^Only booleans are allowed in an if condition, string\\|null given\\.$#" - count: 1 - path: ../src/Composer/Downloader/ZipDownloader.php - - message: "#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#" count: 1 From 6b54088098356bbb0631e875b9f35553758f00d5 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 29 Jan 2026 11:40:48 +0100 Subject: [PATCH 10/11] Update changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fab98491e358..71bb6a91dea2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +### [2.9.5] 2026-01-29 + + * Added support for new `pie` `download-url-methods` (#12727) + * Fixed detection of 7z when installed as 7za on some linux systems (#12731) + * Fixed warning because of the symfony/process CVE, 2.9.4 had a workaround already + ### [2.9.4] 2026-01-22 * Added active plugins to the diagnose command output (#12706) @@ -2118,6 +2124,7 @@ * Initial release +[2.9.5]: https://github.com/composer/composer/compare/2.9.4...2.9.5 [2.9.4]: https://github.com/composer/composer/compare/2.9.3...2.9.4 [2.9.3]: https://github.com/composer/composer/compare/2.9.2...2.9.3 [2.9.2]: https://github.com/composer/composer/compare/2.9.1...2.9.2 From 72a8f8e653710e18d83e5dd531eb5a71fc3223e6 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 29 Jan 2026 11:40:53 +0100 Subject: [PATCH 11/11] Release 2.9.5 --- 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 6c654cc212c3..3e8f92e0d636 100644 --- a/src/Composer/Composer.php +++ b/src/Composer/Composer.php @@ -51,10 +51,10 @@ class Composer extends PartialComposer * * @see getVersion() */ - public const VERSION = '@package_version@'; - public const BRANCH_ALIAS_VERSION = '@package_branch_alias_version@'; - public const RELEASE_DATE = '@release_date@'; - public const SOURCE_VERSION = '2.9.999-dev+source'; + public const VERSION = '2.9.5'; + public const BRANCH_ALIAS_VERSION = ''; + public const RELEASE_DATE = '2026-01-29 11:40:53'; + public const SOURCE_VERSION = ''; /** * Version number of the internal composer-runtime-api package