1
0
Fork 0

Merge branch '2.4'

pull/11113/head
Jordi Boggiano 2022-10-12 11:27:30 +02:00
commit 7df744531b
No known key found for this signature in database
GPG Key ID: 7BBD42C429EC80BC
39 changed files with 317 additions and 323 deletions

74
composer.lock generated
View File

@ -941,16 +941,16 @@
},
{
"name": "symfony/console",
"version": "v5.4.12",
"version": "v5.4.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "c072aa8f724c3af64e2c7a96b796a4863d24dba1"
"reference": "3f97f6c7b7e26848a90c0c0cfb91eeb2bb8618be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/c072aa8f724c3af64e2c7a96b796a4863d24dba1",
"reference": "c072aa8f724c3af64e2c7a96b796a4863d24dba1",
"url": "https://api.github.com/repos/symfony/console/zipball/3f97f6c7b7e26848a90c0c0cfb91eeb2bb8618be",
"reference": "3f97f6c7b7e26848a90c0c0cfb91eeb2bb8618be",
"shasum": ""
},
"require": {
@ -1020,7 +1020,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v5.4.12"
"source": "https://github.com/symfony/console/tree/v5.4.13"
},
"funding": [
{
@ -1036,7 +1036,7 @@
"type": "tidelift"
}
],
"time": "2022-08-17T13:18:05+00:00"
"time": "2022-08-26T13:50:20+00:00"
},
{
"name": "symfony/deprecation-contracts",
@ -1107,16 +1107,16 @@
},
{
"name": "symfony/filesystem",
"version": "v5.4.12",
"version": "v5.4.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "2d67c1f9a1937406a9be3171b4b22250c0a11447"
"reference": "ac09569844a9109a5966b9438fc29113ce77cf51"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/2d67c1f9a1937406a9be3171b4b22250c0a11447",
"reference": "2d67c1f9a1937406a9be3171b4b22250c0a11447",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/ac09569844a9109a5966b9438fc29113ce77cf51",
"reference": "ac09569844a9109a5966b9438fc29113ce77cf51",
"shasum": ""
},
"require": {
@ -1151,7 +1151,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v5.4.12"
"source": "https://github.com/symfony/filesystem/tree/v5.4.13"
},
"funding": [
{
@ -1167,7 +1167,7 @@
"type": "tidelift"
}
],
"time": "2022-08-02T13:48:16+00:00"
"time": "2022-09-21T19:53:16+00:00"
},
{
"name": "symfony/finder",
@ -1871,16 +1871,16 @@
},
{
"name": "symfony/string",
"version": "v5.4.12",
"version": "v5.4.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "2fc515e512d721bf31ea76bd02fe23ada4640058"
"reference": "2900c668a32138a34118740de3e4d5a701801f53"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/2fc515e512d721bf31ea76bd02fe23ada4640058",
"reference": "2fc515e512d721bf31ea76bd02fe23ada4640058",
"url": "https://api.github.com/repos/symfony/string/zipball/2900c668a32138a34118740de3e4d5a701801f53",
"reference": "2900c668a32138a34118740de3e4d5a701801f53",
"shasum": ""
},
"require": {
@ -1937,7 +1937,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v5.4.12"
"source": "https://github.com/symfony/string/tree/v5.4.13"
},
"funding": [
{
@ -1953,22 +1953,22 @@
"type": "tidelift"
}
],
"time": "2022-08-12T17:03:11+00:00"
"time": "2022-09-01T01:52:16+00:00"
}
],
"packages-dev": [
{
"name": "phpstan/phpstan",
"version": "1.8.5",
"version": "1.8.8",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "f6598a5ff12ca4499a836815e08b4d77a2ddeb20"
"reference": "08310ce271984587e2a4cda94e1ac66510a6ea07"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/f6598a5ff12ca4499a836815e08b4d77a2ddeb20",
"reference": "f6598a5ff12ca4499a836815e08b4d77a2ddeb20",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/08310ce271984587e2a4cda94e1ac66510a6ea07",
"reference": "08310ce271984587e2a4cda94e1ac66510a6ea07",
"shasum": ""
},
"require": {
@ -1998,7 +1998,7 @@
],
"support": {
"issues": "https://github.com/phpstan/phpstan/issues",
"source": "https://github.com/phpstan/phpstan/tree/1.8.5"
"source": "https://github.com/phpstan/phpstan/tree/1.8.8"
},
"funding": [
{
@ -2014,7 +2014,7 @@
"type": "tidelift"
}
],
"time": "2022-09-07T16:05:32+00:00"
"time": "2022-10-06T12:51:57+00:00"
},
{
"name": "phpstan/phpstan-deprecation-rules",
@ -2120,21 +2120,21 @@
},
{
"name": "phpstan/phpstan-strict-rules",
"version": "1.4.3",
"version": "1.4.4",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
"reference": "431b3d6e8040075de196680cd5bc95735987b4ae"
"reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/431b3d6e8040075de196680cd5bc95735987b4ae",
"reference": "431b3d6e8040075de196680cd5bc95735987b4ae",
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6",
"reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
"phpstan/phpstan": "^1.8.3"
"phpstan/phpstan": "^1.8.6"
},
"require-dev": {
"nikic/php-parser": "^4.13.0",
@ -2162,22 +2162,22 @@
"description": "Extra strict and opinionated rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.4.3"
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.4.4"
},
"time": "2022-08-26T15:05:46+00:00"
"time": "2022-09-21T11:38:17+00:00"
},
{
"name": "phpstan/phpstan-symfony",
"version": "1.2.13",
"version": "1.2.14",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-symfony.git",
"reference": "016e441a19a2af79ca0c60920ba0d61747b4e855"
"reference": "f7dd737329504115adaa987697a759a66dd2ee8a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/016e441a19a2af79ca0c60920ba0d61747b4e855",
"reference": "016e441a19a2af79ca0c60920ba0d61747b4e855",
"url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/f7dd737329504115adaa987697a759a66dd2ee8a",
"reference": "f7dd737329504115adaa987697a759a66dd2ee8a",
"shasum": ""
},
"require": {
@ -2233,9 +2233,9 @@
"description": "Symfony Framework extensions and rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-symfony/issues",
"source": "https://github.com/phpstan/phpstan-symfony/tree/1.2.13"
"source": "https://github.com/phpstan/phpstan-symfony/tree/1.2.14"
},
"time": "2022-08-28T13:34:45+00:00"
"time": "2022-10-05T11:19:29+00:00"
},
{
"name": "symfony/phpunit-bridge",

View File

@ -176,8 +176,9 @@ you can skip `--with` and instead use constraints with the partial update syntax
php composer.phar update vendor/package:2.0.1 vendor/package2:3.0.*
```
The custom constraint has to be a subset of the existing constraint you have,
and this feature is only available for your root package dependencies.
> **Note:** For packages also required in your composer.json the custom constraint
> must be a subset of the existing constraint. The composer.json constraints still
> apply and the composer.json is not modified by these temporary update constraints.
### Options

View File

@ -185,16 +185,6 @@ parameters:
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Parameter \\#1 \\$handle of function curl_close expects CurlHandle, resource given\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Parameter \\#1 \\$handle of function curl_getinfo expects CurlHandle, resource given\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Parameter \\#1 \\$haystack of function strpos expects string, string\\|null given\\.$#"
count: 1
@ -230,16 +220,6 @@ parameters:
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Parameter \\#2 \\$handle of function curl_multi_remove_handle expects CurlHandle, resource given\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Property Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:\\$jobs \\(array\\<array\\{url\\: string, origin\\: string, attributes\\: array\\{retryAuthFailure\\: bool, redirects\\: int\\<0, max\\>, retries\\: int\\<0, max\\>, storeAuth\\: 'prompt'\\|bool\\}, options\\: array, progress\\: array, curlHandle\\: resource, filename\\: string\\|null, headerHandle\\: resource, \\.\\.\\.\\}\\>\\) does not accept non\\-empty\\-array\\<array\\{url\\: string, origin\\: string, attributes\\: array\\{retryAuthFailure\\: bool, redirects\\: int\\<0, max\\>, retries\\: int\\<0, max\\>, storeAuth\\: 'prompt'\\|bool\\}, options\\: array, progress\\: array, curlHandle\\: resource, filename\\: string\\|null, headerHandle\\: resource, \\.\\.\\.\\}\\|array\\{url\\: string, origin\\: string, attributes\\: array\\{retryAuthFailure\\: bool, redirects\\: int\\<0, max\\>, retries\\: int\\<0, max\\>, storeAuth\\: 'prompt'\\|bool\\}, options\\: array, progress\\: array\\<\\('certinfo'\\|'connect_time'\\|'content_type'\\|'download_content…'\\|'filetime'\\|'header_size'\\|'http_code'\\|'http_version'\\|'local_ip'\\|'local_port'\\|'namelookup_time'\\|'pretransfer_time'\\|'primary_ip'\\|'primary_port'\\|'protocol'\\|'redirect_count'\\|'redirect_time'\\|'redirect_url'\\|'request_size'\\|'scheme'\\|'size_download'\\|'size_upload'\\|'speed_download'\\|'speed_upload'\\|'ssl_verify_result'\\|'ssl_verifyresult'\\|'starttransfer_time'\\|'total_time'\\|'upload_content…'\\|'url'\\), \\(array\\<int, array\\<string, string\\>\\>\\|float\\|int\\|string\\|null\\)\\>, curlHandle\\: CurlHandle, filename\\: string\\|null, headerHandle\\: resource, \\.\\.\\.\\}\\>\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Property Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:\\$multiHandle \\(resource\\|null\\) does not accept CurlMultiHandle\\.$#"
count: 1

View File

@ -350,16 +350,6 @@ parameters:
count: 1
path: ../src/Composer/Command/CreateProjectCommand.php
-
message: "#^Cannot access offset 'libz_version' on array\\|false\\.$#"
count: 1
path: ../src/Composer/Command/DiagnoseCommand.php
-
message: "#^Cannot access offset 'ssl_version' on array\\|false\\.$#"
count: 1
path: ../src/Composer/Command/DiagnoseCommand.php
-
message: "#^Cannot access offset 'version' on array\\|false\\.$#"
count: 1
@ -375,16 +365,6 @@ parameters:
count: 4
path: ../src/Composer/Command/DiagnoseCommand.php
-
message: "#^Only booleans are allowed in a negated boolean, array\\<string, bool\\|string\\> given\\.$#"
count: 1
path: ../src/Composer/Command/DiagnoseCommand.php
-
message: "#^Only booleans are allowed in a negated boolean, array\\<string, mixed\\> given\\.$#"
count: 1
path: ../src/Composer/Command/DiagnoseCommand.php
-
message: "#^Only booleans are allowed in a negated boolean, array\\<string\\>\\|string\\|false given\\.$#"
count: 1
@ -1715,11 +1695,6 @@ parameters:
count: 2
path: ../src/Composer/DependencyResolver/Transaction.php
-
message: "#^Parameter \\#2 \\$path of method Composer\\\\Downloader\\\\FileDownloader\\:\\:removeCleanupPath\\(\\) expects string, string\\|false given\\.$#"
count: 1
path: ../src/Composer/Downloader/ArchiveDownloader.php
-
message: "#^Call to function array_search\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
@ -1790,11 +1765,6 @@ parameters:
count: 1
path: ../src/Composer/Downloader/FileDownloader.php
-
message: "#^Cannot access offset 'cacheKey' on array\\{base\\: string, processed\\: string, cacheKey\\: string\\}\\|false\\.$#"
count: 1
path: ../src/Composer/Downloader/FileDownloader.php
-
message: "#^Foreach overwrites \\$path with its value variable\\.$#"
count: 1
@ -2170,11 +2140,6 @@ parameters:
count: 1
path: ../src/Composer/EventDispatcher/EventDispatcher.php
-
message: "#^Cannot access offset 1 on array\\{0\\: string, 1\\?\\: int\\}\\|int\\|string\\.$#"
count: 1
path: ../src/Composer/EventDispatcher/EventDispatcher.php
-
message: "#^Casting to bool something that's already bool\\.$#"
count: 1
@ -3055,11 +3020,6 @@ parameters:
count: 1
path: ../src/Composer/Package/Loader/ValidatingArrayLoader.php
-
message: "#^Cannot access offset 'scheme' on array\\{scheme\\?\\: string, host\\?\\: string, port\\?\\: int\\<0, 65535\\>, user\\?\\: string, pass\\?\\: string, path\\?\\: string, query\\?\\: string, fragment\\?\\: string\\}\\|false\\.$#"
count: 1
path: ../src/Composer/Package/Loader/ValidatingArrayLoader.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 8
@ -3410,11 +3370,6 @@ parameters:
count: 1
path: ../src/Composer/Repository/ArtifactRepository.php
-
message: "#^Cannot access offset 'path' on array\\{scheme\\?\\: string, host\\?\\: string, port\\?\\: int\\<0, 65535\\>, user\\?\\: string, pass\\?\\: string, path\\?\\: string, query\\?\\: string, fragment\\?\\: string\\}\\|false\\.$#"
count: 1
path: ../src/Composer/Repository/ComposerRepository.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 24
@ -4523,11 +4478,6 @@ parameters:
count: 3
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Offset \\(int\\|string\\) on array\\<array\\{url\\: string, origin\\: string, attributes\\: array\\{retryAuthFailure\\: bool, redirects\\: int\\<0, max\\>, retries\\: int\\<0, max\\>, storeAuth\\: 'prompt'\\|bool\\}, options\\: array, progress\\: array, curlHandle\\: resource, filename\\: string\\|null, headerHandle\\: resource, \\.\\.\\.\\}\\> in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Only booleans are allowed in &&, int given on the right side\\.$#"
count: 1
@ -4538,11 +4488,6 @@ parameters:
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Only booleans are allowed in a negated boolean, resource\\|false given\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Only booleans are allowed in a negated boolean, string given\\.$#"
count: 1
@ -4575,7 +4520,7 @@ parameters:
-
message: "#^Only booleans are allowed in an if condition, string\\|null given\\.$#"
count: 2
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
@ -4583,6 +4528,16 @@ parameters:
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Parameter \\#1 \\$ch of function curl_close expects resource, CurlHandle given\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Parameter \\#1 \\$ch of function curl_getinfo expects resource, CurlHandle given\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Parameter \\#1 \\$json of function json_decode expects string, string\\|null given\\.$#"
count: 1
@ -4638,6 +4593,11 @@ parameters:
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Parameter \\#2 \\$ch of function curl_multi_remove_handle expects resource, CurlHandle given\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Parameter \\#2 \\$subject of static method Composer\\\\Pcre\\\\Preg\\:\\:isMatch\\(\\) expects string, string\\|null given\\.$#"
count: 1
@ -4654,7 +4614,42 @@ parameters:
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Property Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:\\$jobs \\(array\\<array\\{url\\: string, origin\\: string, attributes\\: array\\{retryAuthFailure\\: bool, redirects\\: int\\<0, max\\>, retries\\: int\\<0, max\\>, storeAuth\\: 'prompt'\\|bool\\}, options\\: array, progress\\: array, curlHandle\\: resource, filename\\: string\\|null, headerHandle\\: resource, \\.\\.\\.\\}\\>\\) does not accept non\\-empty\\-array\\<array\\{url\\: string, origin\\: string, attributes\\: array\\{retryAuthFailure\\: bool, redirects\\: int\\<0, max\\>, retries\\: int\\<0, max\\>, storeAuth\\: 'prompt'\\|bool\\}, options\\: array, progress\\: array, curlHandle\\: resource, filename\\: string\\|null, headerHandle\\: resource, \\.\\.\\.\\}\\>\\.$#"
message: "#^Parameter \\$job of method Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:failResponse\\(\\) has invalid type CurlHandle\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Parameter \\$job of method Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:handleRedirect\\(\\) has invalid type CurlHandle\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Parameter \\$job of method Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:isAuthenticatedRetryNeeded\\(\\) has invalid type CurlHandle\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Parameter \\$job of method Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:rejectJob\\(\\) has invalid type CurlHandle\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Parameter \\$job of method Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:restartJob\\(\\) has invalid type CurlHandle\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Parameter \\$job of method Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:restartJobWithDelay\\(\\) has invalid type CurlHandle\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Property Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:\\$jobs \\(array\\<array\\{url\\: non\\-empty\\-string, origin\\: string, attributes\\: array\\{retryAuthFailure\\: bool, redirects\\: int\\<0, max\\>, retries\\: int\\<0, max\\>, storeAuth\\: 'prompt'\\|bool\\}, options\\: array, progress\\: array, curlHandle\\: CurlHandle, filename\\: string\\|null, headerHandle\\: resource, \\.\\.\\.\\}\\>\\) does not accept non\\-empty\\-array\\<array\\{url\\: non\\-empty\\-string, origin\\: string, attributes\\: array\\{retryAuthFailure\\: bool, redirects\\: int\\<0, max\\>, retries\\: int\\<0, max\\>, storeAuth\\: 'prompt'\\|bool\\}, options\\: array, progress\\: array, curlHandle\\: CurlHandle\\|resource, filename\\: string\\|null, headerHandle\\: resource, \\.\\.\\.\\}\\>\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Property Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:\\$jobs has unknown class CurlHandle as its type\\.$#"
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
@ -4668,16 +4663,6 @@ parameters:
count: 1
path: ../src/Composer/Util/Http/CurlDownloader.php
-
message: "#^Cannot access offset 'host' on array\\{scheme\\?\\: string, host\\?\\: string, port\\?\\: int\\<0, 65535\\>, user\\?\\: string, pass\\?\\: string, path\\?\\: string, query\\?\\: string, fragment\\?\\: string\\}\\|false\\.$#"
count: 1
path: ../src/Composer/Util/Http/ProxyHelper.php
-
message: "#^Cannot access offset 'user' on array\\{scheme\\?\\: string, host\\?\\: string, port\\?\\: int\\<0, 65535\\>, user\\?\\: string, pass\\?\\: string, path\\?\\: string, query\\?\\: string, fragment\\?\\: string\\}\\|false\\.$#"
count: 1
path: ../src/Composer/Util/Http/ProxyHelper.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
@ -4783,31 +4768,6 @@ parameters:
count: 4
path: ../src/Composer/Util/HttpDownloader.php
-
message: "#^Offset 'copyTo' does not exist on array\\{url\\: string, options\\?\\: array, copyTo\\?\\: string\\|null\\}\\.$#"
count: 2
path: ../src/Composer/Util/HttpDownloader.php
-
message: "#^Offset 'exception' does not exist on array\\{id\\: int, status\\: 4, request\\: array\\{url\\: string, options\\?\\: array, copyTo\\?\\: string\\|null\\}, sync\\: bool, origin\\: string, resolve\\?\\: callable\\(\\)\\: mixed, reject\\?\\: callable\\(\\)\\: mixed, curl_id\\?\\: int, \\.\\.\\.\\}\\.$#"
count: 1
path: ../src/Composer/Util/HttpDownloader.php
-
message: "#^Offset 'options' does not exist on array\\{url\\: string, options\\?\\: array, copyTo\\?\\: string\\|null\\}\\.$#"
count: 3
path: ../src/Composer/Util/HttpDownloader.php
-
message: "#^Offset 'reject' does not exist on array\\{id\\: int, status\\: 2, request\\: array\\{url\\: string, options\\?\\: array, copyTo\\?\\: string\\|null\\}, sync\\: bool, origin\\: string, resolve\\?\\: callable\\(\\)\\: mixed, reject\\?\\: callable\\(\\)\\: mixed, curl_id\\?\\: int, \\.\\.\\.\\}\\.$#"
count: 1
path: ../src/Composer/Util/HttpDownloader.php
-
message: "#^Offset 'resolve' does not exist on array\\{id\\: int, status\\: 2, request\\: array\\{url\\: string, options\\?\\: array, copyTo\\?\\: string\\|null\\}, sync\\: bool, origin\\: string, resolve\\?\\: callable\\(\\)\\: mixed, reject\\?\\: callable\\(\\)\\: mixed, curl_id\\?\\: int, \\.\\.\\.\\}\\.$#"
count: 1
path: ../src/Composer/Util/HttpDownloader.php
-
message: "#^Only booleans are allowed in a negated boolean, Composer\\\\Util\\\\Http\\\\CurlDownloader\\|null given\\.$#"
count: 1
@ -5188,11 +5148,6 @@ parameters:
count: 1
path: ../src/Composer/Util/StreamContextFactory.php
-
message: "#^Cannot access offset 'user' on array\\{scheme\\?\\: string, host\\?\\: string, port\\?\\: int\\<0, 65535\\>, user\\?\\: string, pass\\?\\: string, path\\?\\: string, query\\?\\: string, fragment\\?\\: string\\}\\|false\\.$#"
count: 1
path: ../src/Composer/Util/Svn.php
-
message: "#^Casting to bool something that's already \\*NEVER\\*\\.$#"
count: 1
@ -5258,11 +5213,6 @@ parameters:
count: 1
path: ../src/Composer/Util/TlsHelper.php
-
message: "#^Cannot access offset 'subject' on array\\|false\\.$#"
count: 1
path: ../src/Composer/Util/TlsHelper.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
@ -5676,11 +5626,6 @@ parameters:
count: 1
path: ../tests/Composer/Test/Json/JsonManipulatorTest.php
-
message: "#^Offset 'url' on array\\{url\\: string, options\\?\\: array, status\\?\\: int, body\\?\\: string, headers\\?\\: array\\<string\\>\\} on left side of \\?\\? always exists and is not nullable\\.$#"
count: 1
path: ../tests/Composer/Test/Mock/HttpDownloaderMock.php
-
message: "#^Composer\\\\Test\\\\Mock\\\\InstallationManagerMock\\:\\:__construct\\(\\) does not call parent constructor from Composer\\\\Installer\\\\InstallationManager\\.$#"
count: 1
@ -5691,11 +5636,6 @@ parameters:
count: 1
path: ../tests/Composer/Test/Mock/InstallationManagerMock.php
-
message: "#^Offset 'cmd' on array\\{cmd\\: array\\<int, string\\>\\|string, return\\?\\: int, stdout\\?\\: string, stderr\\?\\: string, callback\\?\\: callable\\(\\)\\: mixed\\} on left side of \\?\\? always exists and is not nullable\\.$#"
count: 1
path: ../tests/Composer/Test/Mock/ProcessExecutorMock.php
-
message: "#^Only booleans are allowed in an if condition, string given\\.$#"
count: 2

View File

@ -722,7 +722,7 @@ EOT
$out($iniMessage, 'comment');
}
return !$warnings && !$errors ? true : $output;
return count($warnings) === 0 && count($errors) === 0 ? true : $output;
}
/**

View File

@ -21,6 +21,7 @@ use Composer\Pcre\Preg;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Package\Version\VersionParser;
use Composer\Semver\Intervals;
use Composer\Util\HttpDownloader;
use Composer\Advisory\Auditor;
use Symfony\Component\Console\Helper\Table;
@ -147,16 +148,22 @@ EOT
}
}
$parser = new VersionParser;
$temporaryConstraints = [];
foreach ($reqs as $package => $constraint) {
$temporaryConstraints[strtolower($package)] = $parser->parseConstraints($constraint);
}
$rootPackage = $composer->getPackage();
$rootPackage->setReferences(RootPackageLoader::extractReferences($reqs, $rootPackage->getReferences()));
$rootPackage->setStabilityFlags(RootPackageLoader::extractStabilityFlags($reqs, $rootPackage->getMinimumStability(), $rootPackage->getStabilityFlags()));
$parser = new VersionParser;
$temporaryConstraints = [];
$rootRequirements = array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires());
foreach ($reqs as $package => $constraint) {
$package = strtolower($package);
$parsedConstraint = $parser->parseConstraints($constraint);
$temporaryConstraints[$package] = $parsedConstraint;
if (isset($rootRequirements[$package]) && !Intervals::haveIntersections($parsedConstraint, $rootRequirements[$package]->getConstraint())) {
throw new \InvalidArgumentException('The temporary constraint "'.$constraint.'" for "'.$package.'" must be a subset of the constraint in your composer.json ('.$rootRequirements[$package]->getPrettyConstraint().')');
}
}
if ($input->getOption('interactive')) {
$packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages);
}

View File

@ -235,6 +235,9 @@ class Application extends BaseApplication
false === $commandName
// list command requires plugin commands to show them
|| in_array($commandName, ['', 'list', 'help'], true)
// autocompletion requires plugin commands but if we are running as root without COMPOSER_ALLOW_SUPERUSER
// we'd rather not autocomplete plugins than abort autocompletion entirely, so we avoid loading plugins in this case
|| ($commandName === '_complete' && !$isNonAllowedRoot)
);
if ($mayNeedPluginCommand && !$this->disablePluginsByDefault && !$this->hasPluginCommands) {

View File

@ -123,7 +123,7 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
$retries = 3;
$distUrls = $package->getDistUrls();
/** @var array<array{base: string, processed: string, cacheKey: string}> $urls */
/** @var non-empty-array<array{base: non-empty-string, processed: non-empty-string, cacheKey: string}> $urls */
$urls = [];
foreach ($distUrls as $index => $url) {
$processedUrl = $this->processUrl($package, $url);
@ -151,7 +151,6 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
$accept = null;
$reject = null;
$download = function () use ($io, $output, $httpDownloader, $cache, $cacheKeyGenerator, $eventDispatcher, $package, $fileName, &$urls, &$accept, &$reject) {
/** @var array{base: string, processed: string, cacheKey: string} $url */
$url = reset($urls);
$index = key($urls);
@ -435,9 +434,9 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
* Process the download url
*
* @param PackageInterface $package package the url is coming from
* @param string $url download url
* @param non-empty-string $url download url
* @throws \RuntimeException If any problem with the url
* @return string url
* @return non-empty-string url
*/
protected function processUrl(PackageInterface $package, string $url): string
{

View File

@ -38,17 +38,17 @@ class Package extends BasePackage
protected $sourceUrl;
/** @var ?string */
protected $sourceReference;
/** @var ?array<int, array{url: string, preferred: bool}> */
/** @var ?array<int, array{url: non-empty-string, preferred: bool}> */
protected $sourceMirrors;
/** @var ?string */
/** @var ?non-empty-string */
protected $distType;
/** @var ?string */
/** @var ?non-empty-string */
protected $distUrl;
/** @var ?string */
protected $distReference;
/** @var ?string */
protected $distSha1Checksum;
/** @var ?array<int, array{url: string, preferred: bool}> */
/** @var ?array<int, array{url: non-empty-string, preferred: bool}> */
protected $distMirrors;
/** @var string */
protected $version;
@ -276,7 +276,7 @@ class Package extends BasePackage
*/
public function setDistType(?string $type): void
{
$this->distType = $type;
$this->distType = $type === '' ? null : $type;
}
/**
@ -288,11 +288,11 @@ class Package extends BasePackage
}
/**
* @param string $url
* @param string|null $url
*/
public function setDistUrl(?string $url): void
{
$this->distUrl = $url;
$this->distUrl = $url === '' ? null : $url;
}
/**
@ -658,9 +658,9 @@ class Package extends BasePackage
/**
* @param mixed[]|null $mirrors
*
* @return string[]
* @return non-empty-string[]
*
* @phpstan-param list<array{url: string, preferred: bool}>|null $mirrors
* @phpstan-param list<array{url: non-empty-string, preferred: bool}>|null $mirrors
*/
protected function getUrls(?string $url, ?array $mirrors, ?string $ref, ?string $type, string $urlType): array
{

View File

@ -141,12 +141,12 @@ interface PackageInterface
/**
* Returns the source mirrors of this package
*
* @return ?array<int, array{url: string, preferred: bool}>
* @return ?array<int, array{url: non-empty-string, preferred: bool}>
*/
public function getSourceMirrors(): ?array;
/**
* @param null|array<int, array{url: string, preferred: bool}> $mirrors
* @param null|array<int, array{url: non-empty-string, preferred: bool}> $mirrors
*/
public function setSourceMirrors(?array $mirrors): void;
@ -160,14 +160,14 @@ interface PackageInterface
/**
* Returns the url of the distribution archive of this version
*
* @return ?string
* @return ?non-empty-string
*/
public function getDistUrl(): ?string;
/**
* Returns the urls of the distribution archive of this version, including mirrors
*
* @return string[]
* @return non-empty-string[]
*/
public function getDistUrls(): array;
@ -188,12 +188,12 @@ interface PackageInterface
/**
* Returns the dist mirrors of this package
*
* @return ?array<int, array{url: string, preferred: bool}>
* @return ?array<int, array{url: non-empty-string, preferred: bool}>
*/
public function getDistMirrors(): ?array;
/**
* @param null|array<int, array{url: string, preferred: bool}> $mirrors
* @param null|array<int, array{url: non-empty-string, preferred: bool}> $mirrors
*/
public function setDistMirrors(?array $mirrors): void;

View File

@ -28,7 +28,7 @@ class PreFileDownloadEvent extends Event
private $httpDownloader;
/**
* @var string
* @var non-empty-string
*/
private $processedUrl;
@ -55,8 +55,9 @@ class PreFileDownloadEvent extends Event
/**
* Constructor.
*
* @param string $name The event name
* @param mixed $context
* @param string $name The event name
* @param mixed $context
* @param non-empty-string $processedUrl
*/
public function __construct(string $name, HttpDownloader $httpDownloader, string $processedUrl, string $type, $context = null)
{
@ -74,6 +75,8 @@ class PreFileDownloadEvent extends Event
/**
* Retrieves the processed URL that will be downloaded.
*
* @return non-empty-string
*/
public function getProcessedUrl(): string
{
@ -83,7 +86,7 @@ class PreFileDownloadEvent extends Event
/**
* Sets the processed URL that will be downloaded.
*
* @param string $processedUrl New processed URL
* @param non-empty-string $processedUrl New processed URL
*/
public function setProcessedUrl(string $processedUrl): void
{

View File

@ -55,9 +55,9 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
private $repoConfig;
/** @var mixed[] */
private $options;
/** @var string */
/** @var non-empty-string */
private $url;
/** @var string */
/** @var non-empty-string */
private $baseUrl;
/** @var IOInterface */
private $io;
@ -67,17 +67,17 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
private $loop;
/** @var Cache */
protected $cache;
/** @var ?string */
/** @var ?non-empty-string */
protected $notifyUrl = null;
/** @var ?string */
/** @var ?non-empty-string */
protected $searchUrl = null;
/** @var ?string a URL containing %package% which can be queried to get providers of a given name */
/** @var ?non-empty-string a URL containing %package% which can be queried to get providers of a given name */
protected $providersApiUrl = null;
/** @var bool */
protected $hasProviders = false;
/** @var ?string */
/** @var ?non-empty-string */
protected $providersUrl = null;
/** @var ?string */
/** @var ?non-empty-string */
protected $listUrl = null;
/** @var bool Indicates whether a comprehensive list of packages this repository might provide is expressed in the repository root. **/
protected $hasAvailablePackageList = false;
@ -85,7 +85,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
protected $availablePackages = null;
/** @var ?array<non-empty-string> */
protected $availablePackagePatterns = null;
/** @var ?string */
/** @var ?non-empty-string */
protected $lazyProvidersUrl = null;
/** @var ?array<string, array{sha256: string}> */
protected $providerListing;
@ -95,9 +95,9 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
private $allowSslDowngrade = false;
/** @var ?EventDispatcher */
private $eventDispatcher;
/** @var ?array<string, array<int, array{url: string, preferred: bool}>> */
/** @var ?array<string, array<int, array{url: non-empty-string, preferred: bool}>> */
private $sourceMirrors;
/** @var ?array<int, array{url: string, preferred: bool}> */
/** @var ?array<int, array{url: non-empty-string, preferred: bool}> */
private $distMirrors;
/** @var bool */
private $degradedMode = false;
@ -133,7 +133,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
/**
* @param array<string, mixed> $repoConfig
* @phpstan-param array{url: string, options?: mixed[], type?: 'composer', allow_ssl_downgrade?: bool} $repoConfig
* @phpstan-param array{url: non-empty-string, options?: mixed[], type?: 'composer', allow_ssl_downgrade?: bool} $repoConfig
*/
public function __construct(array $repoConfig, IOInterface $io, Config $config, HttpDownloader $httpDownloader, ?EventDispatcher $eventDispatcher = null)
{
@ -143,8 +143,11 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
$repoConfig['url'] = 'http://'.$repoConfig['url'];
}
$repoConfig['url'] = rtrim($repoConfig['url'], '/');
if ($repoConfig['url'] === '') {
throw new \InvalidArgumentException('The repository url must not be an empty string');
}
if (strpos($repoConfig['url'], 'https?') === 0) {
if (str_starts_with($repoConfig['url'], 'https?')) {
$repoConfig['url'] = (extension_loaded('openssl') ? 'https' : 'http') . substr($repoConfig['url'], 6);
}
@ -168,7 +171,9 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
$this->url = $match['proto'].'://repo.packagist.org';
}
$this->baseUrl = rtrim(Preg::replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/');
$baseUrl = rtrim(Preg::replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/');
assert($baseUrl !== '');
$this->baseUrl = $baseUrl;
$this->io = $io;
$this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($this->url)), 'a-z0-9.$~');
$this->cache->setReadOnly($config->get('cache-read-only'));
@ -1265,6 +1270,10 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
return $this->rootData = $data;
}
/**
* @param non-empty-string $url
* @return non-empty-string
*/
private function canonicalizeUrl(string $url): string
{
if ('/' === $url[0]) {
@ -1416,6 +1425,10 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
*/
protected function fetchFile(string $filename, ?string $cacheKey = null, ?string $sha256 = null, bool $storeLastModifiedTime = false)
{
if ('' === $filename) {
throw new \InvalidArgumentException('$filename should not be an empty string');
}
if (null === $cacheKey) {
$cacheKey = $filename;
$filename = $this->baseUrl.'/'.$filename;
@ -1519,6 +1532,10 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
*/
private function fetchFileIfLastModified(string $filename, string $cacheKey, string $lastModifiedTime)
{
if ('' === $filename) {
throw new \InvalidArgumentException('$filename should not be an empty string');
}
try {
$options = $this->options;
if ($this->eventDispatcher) {
@ -1578,6 +1595,10 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
private function asyncFetchFile(string $filename, string $cacheKey, ?string $lastModifiedTime = null): PromiseInterface
{
if ('' === $filename) {
throw new \InvalidArgumentException('$filename should not be an empty string');
}
if (isset($this->packagesNotFoundCache[$filename])) {
return \React\Promise\resolve(['packages' => []]);
}

View File

@ -21,6 +21,10 @@ use Composer\Pcre\Preg;
*/
class ComposerMirror
{
/**
* @param non-empty-string $mirrorUrl
* @return non-empty-string
*/
public static function processUrl(string $mirrorUrl, string $packageName, string $version, ?string $reference, ?string $type, ?string $prettyVersion = null): string
{
if ($reference) {
@ -35,9 +39,16 @@ class ComposerMirror
$to[] = $prettyVersion;
}
return str_replace($from, $to, $mirrorUrl);
$url = str_replace($from, $to, $mirrorUrl);
assert($url !== '');
return $url;
}
/**
* @param non-empty-string $mirrorUrl
* @return string
*/
public static function processGitUrl(string $mirrorUrl, string $packageName, string $url, ?string $type): string
{
if (Preg::isMatch('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) {
@ -55,6 +66,10 @@ class ComposerMirror
);
}
/**
* @param non-empty-string $mirrorUrl
* @return string
*/
public static function processHgUrl(string $mirrorUrl, string $packageName, string $url, string $type): string
{
return self::processGitUrl($mirrorUrl, $packageName, $url, $type);

View File

@ -29,7 +29,7 @@ use React\Promise\Promise;
* @author Jordi Boggiano <j.boggiano@seld.be>
* @author Nicolas Grekas <p@tchwork.com>
* @phpstan-type Attributes array{retryAuthFailure: bool, redirects: int<0, max>, retries: int<0, max>, storeAuth: 'prompt'|bool}
* @phpstan-type Job array{url: string, origin: string, attributes: Attributes, options: mixed[], progress: mixed[], curlHandle: resource, filename: string|null, headerHandle: resource, bodyHandle: resource, resolve: callable, reject: callable}
* @phpstan-type Job array{url: non-empty-string, origin: string, attributes: Attributes, options: mixed[], progress: mixed[], curlHandle: \CurlHandle, filename: string|null, headerHandle: resource, bodyHandle: resource, resolve: callable, reject: callable}
*/
class CurlDownloader
{
@ -125,6 +125,7 @@ class CurlDownloader
/**
* @param mixed[] $options
* @param non-empty-string $url
*
* @return int internal job id
*/
@ -143,16 +144,18 @@ class CurlDownloader
* @param mixed[] $options
*
* @param array{retryAuthFailure?: bool, redirects?: int<0, max>, retries?: int<0, max>, storeAuth?: 'prompt'|bool} $attributes
* @param non-empty-string $url
*
* @return int internal job id
*/
private function initDownload(callable $resolve, callable $reject, string $origin, string $url, array $options, ?string $copyTo = null, array $attributes = []): int
{
// set defaults in a PHPStan-happy way (array_merge is not well supported)
$attributes['retryAuthFailure'] = $attributes['retryAuthFailure'] ?? true;
$attributes['redirects'] = $attributes['redirects'] ?? 0;
$attributes['retries'] = $attributes['retries'] ?? 0;
$attributes['storeAuth'] = $attributes['storeAuth'] ?? false;
$attributes = array_merge([
'retryAuthFailure' => true,
'redirects' => 0,
'retries' => 0,
'storeAuth' => false,
], $attributes);
$originalOptions = $options;
@ -167,22 +170,24 @@ class CurlDownloader
throw new \RuntimeException('Failed to open a temp stream to store curl headers');
}
if ($copyTo) {
$errorMessage = '';
// @phpstan-ignore-next-line
set_error_handler(static function ($code, $msg) use (&$errorMessage): void {
if ($errorMessage) {
$errorMessage .= "\n";
}
$errorMessage .= Preg::replace('{^fopen\(.*?\): }', '', $msg);
});
$bodyHandle = fopen($copyTo.'~', 'w+b');
restore_error_handler();
if (!$bodyHandle) {
throw new TransportException('The "'.$url.'" file could not be written to '.$copyTo.': '.$errorMessage);
}
if ($copyTo !== null) {
$bodyTarget = $copyTo.'~';
} else {
$bodyHandle = @fopen('php://temp/maxmemory:524288', 'w+b');
$bodyTarget = 'php://temp/maxmemory:524288';
}
$errorMessage = '';
// @phpstan-ignore-next-line
set_error_handler(static function ($code, $msg) use (&$errorMessage): void {
if ($errorMessage) {
$errorMessage .= "\n";
}
$errorMessage .= Preg::replace('{^fopen\(.*?\): }', '', $msg);
});
$bodyHandle = fopen($bodyTarget, 'w+b');
restore_error_handler();
if (false === $bodyHandle) {
throw new TransportException('The "'.$url.'" file could not be written to '.($copyTo ?? 'a temporary file').': '.$errorMessage);
}
curl_setopt($curlHandle, CURLOPT_URL, $url);
@ -229,7 +234,9 @@ class CurlDownloader
// Always set CURLOPT_PROXY to enable/disable proxy handling
// Any proxy authorization is included in the proxy url
$proxy = $this->proxyManager->getProxyForRequest($url);
curl_setopt($curlHandle, CURLOPT_PROXY, $proxy->getUrl());
if ($proxy->getUrl() !== '') {
curl_setopt($curlHandle, CURLOPT_PROXY, $proxy->getUrl());
}
// Curl needs certificate locations for secure proxies.
// CURLOPT_PROXY_SSL_VERIFY_PEER/HOST are enabled by default
@ -373,8 +380,8 @@ class CurlDownloader
rewind($job['bodyHandle']);
$contents = stream_get_contents($job['bodyHandle']);
}
$response = new CurlResponse(['url' => $progress['url']], $statusCode, $headers, $contents, $progress);
$this->io->writeError('['.$statusCode.'] '.Url::sanitize($progress['url']), true, IOInterface::DEBUG);
$response = new CurlResponse(['url' => $job['url']], $statusCode, $headers, $contents, $progress);
$this->io->writeError('['.$statusCode.'] '.Url::sanitize($job['url']), true, IOInterface::DEBUG);
} else {
$maxFileSize = $job['options']['max_file_size'] ?? null;
rewind($job['bodyHandle']);
@ -389,8 +396,8 @@ class CurlDownloader
$contents = stream_get_contents($job['bodyHandle']);
}
$response = new CurlResponse(['url' => $progress['url']], $statusCode, $headers, $contents, $progress);
$this->io->writeError('['.$statusCode.'] '.Url::sanitize($progress['url']), true, IOInterface::DEBUG);
$response = new CurlResponse(['url' => $job['url']], $statusCode, $headers, $contents, $progress);
$this->io->writeError('['.$statusCode.'] '.Url::sanitize($job['url']), true, IOInterface::DEBUG);
}
fclose($job['bodyHandle']);
@ -456,9 +463,6 @@ class CurlDownloader
}
foreach ($this->jobs as $i => $curlHandle) {
if (!isset($this->jobs[$i])) {
continue;
}
$curlHandle = $this->jobs[$i]['curlHandle'];
$progress = array_diff_key(curl_getinfo($curlHandle), self::$timeInfo);
@ -569,6 +573,7 @@ class CurlDownloader
/**
* @param Job $job
* @param non-empty-string $url
*
* @param array{retryAuthFailure?: bool, redirects?: int<0, max>, storeAuth?: 'prompt'|bool, retries?: int<1, max>} $attributes
*/
@ -586,6 +591,7 @@ class CurlDownloader
/**
* @param Job $job
* @param non-empty-string $url
*
* @param array{retryAuthFailure?: bool, redirects?: int<0, max>, storeAuth?: 'prompt'|bool, retries: int<1, max>} $attributes
*/

View File

@ -74,6 +74,8 @@ class ProxyManager
/**
* Returns a RequestProxy instance for the request url
*
* @param non-empty-string $requestUrl
*/
public function getProxyForRequest(string $requestUrl): RequestProxy
{

View File

@ -17,7 +17,7 @@ use Composer\Pcre\Preg;
use Composer\Util\HttpDownloader;
/**
* @phpstan-import-type Request from HttpDownloader
* @phpstan-type Request array{url: non-empty-string, options?: mixed[], copyTo?: string|null}
*/
class Response
{
@ -31,7 +31,7 @@ class Response
private $body;
/**
* @param Request $request
* @param Request $request
* @param list<string> $headers
*/
public function __construct(array $request, ?int $code, array $headers, ?string $body)

View File

@ -27,7 +27,7 @@ use React\Promise\PromiseInterface;
/**
* @author Jordi Boggiano <j.boggiano@seld.be>
* @phpstan-type Request array{url: string, options?: mixed[], copyTo?: ?string}
* @phpstan-type Request array{url: non-empty-string, options: mixed[], copyTo: string|null}
* @phpstan-type Job array{id: int, status: int, request: Request, sync: bool, origin: string, resolve?: callable, reject?: callable, curl_id?: int, response?: Response, exception?: TransportException}
*/
class HttpDownloader
@ -104,6 +104,9 @@ class HttpDownloader
*/
public function get(string $url, array $options = [])
{
if ('' === $url) {
throw new \InvalidArgumentException('$url must not be an empty string');
}
[$job] = $this->addJob(['url' => $url, 'options' => $options, 'copyTo' => null], true);
$this->wait($job['id']);
@ -123,6 +126,9 @@ class HttpDownloader
*/
public function add(string $url, array $options = [])
{
if ('' === $url) {
throw new \InvalidArgumentException('$url must not be an empty string');
}
[, $promise] = $this->addJob(['url' => $url, 'options' => $options, 'copyTo' => null]);
return $promise;
@ -140,6 +146,9 @@ class HttpDownloader
*/
public function copy(string $url, string $to, array $options = [])
{
if ('' === $url) {
throw new \InvalidArgumentException('$url must not be an empty string');
}
[$job] = $this->addJob(['url' => $url, 'options' => $options, 'copyTo' => $to], true);
$this->wait($job['id']);
@ -158,6 +167,9 @@ class HttpDownloader
*/
public function addCopy(string $url, string $to, array $options = [])
{
if ('' === $url) {
throw new \InvalidArgumentException('$url must not be an empty string');
}
[, $promise] = $this->addJob(['url' => $url, 'options' => $options, 'copyTo' => $to]);
return $promise;
@ -295,6 +307,9 @@ class HttpDownloader
$job['status'] = self::STATUS_STARTED;
$this->runningJobs++;
assert(isset($job['resolve']));
assert(isset($job['reject']));
$resolve = $job['resolve'];
$reject = $job['reject'];
$url = $job['request']['url'];
@ -397,6 +412,7 @@ class HttpDownloader
}
if ($this->jobs[$index]['status'] === self::STATUS_FAILED) {
assert(isset($this->jobs[$index]['exception']));
throw $this->jobs[$index]['exception'];
}

View File

@ -38,7 +38,7 @@ class RemoteFilesystem
private $bytesMax;
/** @var string */
private $originUrl;
/** @var string */
/** @var non-empty-string */
private $fileUrl;
/** @var ?string */
private $fileName;
@ -98,7 +98,7 @@ class RemoteFilesystem
* Copy the remote file in local.
*
* @param string $originUrl The origin URL
* @param string $fileUrl The file URL
* @param non-empty-string $fileUrl The file URL
* @param string $fileName the local filename
* @param bool $progress Display the progression
* @param mixed[] $options Additional context options
@ -114,7 +114,7 @@ class RemoteFilesystem
* Get the content.
*
* @param string $originUrl The origin URL
* @param string $fileUrl The file URL
* @param non-empty-string $fileUrl The file URL
* @param bool $progress Display the progression
* @param mixed[] $options Additional context options
*
@ -206,7 +206,7 @@ class RemoteFilesystem
* Get file content or copy action.
*
* @param string $originUrl The origin URL
* @param string $fileUrl The file URL
* @param non-empty-string $fileUrl The file URL
* @param mixed[] $additionalOptions context options
* @param string $fileName the local filename
* @param bool $progress Display the progression

View File

@ -30,7 +30,7 @@ final class StreamContextFactory
/**
* Creates a context supporting HTTP proxies
*
* @param string $url URL the context is to be used for
* @param non-empty-string $url URL the context is to be used for
* @phpstan-param array{http?: array{follow_location?: int, max_redirects?: int, header?: string|array<string>}} $defaultOptions
* @param mixed[] $defaultOptions Options to merge with the default
* @param mixed[] $defaultParams Parameters to specify on the context
@ -57,6 +57,7 @@ final class StreamContextFactory
}
/**
* @param non-empty-string $url
* @param mixed[] $options
* @param bool $forCurl When true, will not add proxy values as these are handled separately
* @phpstan-return array{http: array{header: string[], proxy?: string, request_fulluri: bool}, ssl?: mixed[]}

View File

@ -21,7 +21,8 @@ use Composer\Pcre\Preg;
class Url
{
/**
* @return string the updated URL
* @param non-empty-string $url
* @return non-empty-string the updated URL
*/
public static function updateDistReference(Config $config, string $url, string $ref): string
{
@ -54,9 +55,15 @@ class Url
$url = Preg::replace('{(/api/v[34]/projects/[^/]+/repository/archive\.(?:zip|tar\.gz|tar\.bz2|tar)\?sha=).+$}i', '${1}'.$ref, $url);
}
assert($url !== '');
return $url;
}
/**
* @param non-empty-string $url
* @return non-empty-string
*/
public static function getOrigin(Config $config, string $url): string
{
if (0 === strpos($url, 'file://')) {
@ -87,7 +94,7 @@ class Url
&& !in_array($origin, $config->get('gitlab-domains'), true)
) {
foreach ($config->get('gitlab-domains') as $gitlabDomain) {
if (0 === strpos($gitlabDomain, $origin)) {
if ($gitlabDomain !== '' && str_starts_with($gitlabDomain, $origin)) {
return $gitlabDomain;
}
}

View File

@ -8,7 +8,7 @@ Installing double aliased package
"package": [
{
"name": "a/a", "version": "dev-master",
"dist": { "type": "file", "url": "" },
"dist": { "type": "file", "url": "https://example.org" },
"require": {
"b/b": "dev-master"
},
@ -17,7 +17,7 @@ Installing double aliased package
{
"name": "b/b", "version": "dev-foo",
"extra": { "branch-alias": { "dev-foo": "1.0.x-dev" } },
"dist": { "type": "file", "url": "" }
"dist": { "type": "file", "url": "https://example.org" }
}
]
}

View File

@ -8,7 +8,7 @@ Installs a dev package forcing it's reference
"package": [
{
"name": "a/a", "version": "dev-main",
"source": { "reference": "abc123", "url": "", "type": "git" },
"source": { "reference": "abc123", "url": "https://example.org", "type": "git" },
"default-branch": true
}
]

View File

@ -8,14 +8,14 @@ Updating a dev package selects its newest version but no providers
"package": [
{
"name": "a/replacer", "version": "dev-master",
"source": { "reference": "wrong", "url": "", "type": "git" },
"source": { "reference": "wrong", "url": "https://example.org", "type": "git" },
"replace": {
"a/installed": "dev-master"
}
},
{
"name": "a/installed", "version": "dev-master",
"source": { "reference": "newref", "url": "", "type": "git" }
"source": { "reference": "newref", "url": "https://example.org", "type": "git" }
}
]
}
@ -29,7 +29,7 @@ Updating a dev package selects its newest version but no providers
[
{
"name": "a/installed", "version": "dev-master",
"source": { "reference": "oldref", "url": "", "type": "git" }
"source": { "reference": "oldref", "url": "https://example.org", "type": "git" }
}
]
--RUN--

View File

@ -8,7 +8,7 @@ Updating a dev package to its latest ref should pick up new dependencies
"package": [
{
"name": "a/devpackage", "version": "dev-main",
"source": { "reference": "newref", "url": "", "type": "git" },
"source": { "reference": "newref", "url": "https://example.org", "type": "git" },
"require": {
"a/dependency": "*"
},
@ -16,7 +16,7 @@ Updating a dev package to its latest ref should pick up new dependencies
},
{
"name": "a/dependency", "version": "dev-main",
"source": { "reference": "ref", "url": "", "type": "git" },
"source": { "reference": "ref", "url": "https://example.org", "type": "git" },
"require": {},
"default-branch": true
}
@ -32,7 +32,7 @@ Updating a dev package to its latest ref should pick up new dependencies
[
{
"name": "a/devpackage", "version": "dev-main",
"source": { "reference": "oldref", "url": "", "type": "git" },
"source": { "reference": "oldref", "url": "https://example.org", "type": "git" },
"require": {},
"default-branch": true
}

View File

@ -8,23 +8,23 @@ Downgrading from unstable to more stable package should work even if already ins
"package": [
{
"name": "a/a", "version": "dev-master",
"source": { "reference": "abcd", "url": "", "type": "git" },
"source": { "reference": "abcd", "url": "https://example.org", "type": "git" },
"default-branch": true
},
{
"name": "a/a", "version": "1.0.0",
"source": { "reference": "1.0.0", "url": "", "type": "git" },
"dist": { "reference": "1.0.0", "url": "", "type": "zip", "shasum": "" }
"source": { "reference": "1.0.0", "url": "https://example.org", "type": "git" },
"dist": { "reference": "1.0.0", "url": "https://example.org", "type": "zip", "shasum": "" }
},
{
"name": "b/b", "version": "dev-master",
"source": { "reference": "abcd", "url": "", "type": "git" },
"source": { "reference": "abcd", "url": "https://example.org", "type": "git" },
"default-branch": true
},
{
"name": "b/b", "version": "1.0.0",
"source": { "reference": "1.0.0", "url": "", "type": "git" },
"dist": { "reference": "1.0.0", "url": "", "type": "zip", "shasum": "" }
"source": { "reference": "1.0.0", "url": "https://example.org", "type": "git" },
"dist": { "reference": "1.0.0", "url": "https://example.org", "type": "zip", "shasum": "" }
}
]
}
@ -38,12 +38,12 @@ Downgrading from unstable to more stable package should work even if already ins
[
{
"name": "a/a", "version": "dev-master",
"source": { "reference": "abcd", "url": "", "type": "git" },
"source": { "reference": "abcd", "url": "https://example.org", "type": "git" },
"default-branch": true
},
{
"name": "b/b", "version": "dev-master",
"source": { "reference": "abcd", "url": "", "type": "git" },
"source": { "reference": "abcd", "url": "https://example.org", "type": "git" },
"default-branch": true
}
]

View File

@ -9,12 +9,12 @@ Updates installed alias packages in dry-run mode
{
"name": "a/a", "version": "dev-master",
"require": { "b/b": "2.0.*" },
"source": { "reference": "abcdef", "url": "", "type": "git" },
"source": { "reference": "abcdef", "url": "https://example.org", "type": "git" },
"extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }
},
{
"name": "b/b", "version": "dev-master",
"source": { "reference": "123456", "url": "", "type": "git" },
"source": { "reference": "123456", "url": "https://example.org", "type": "git" },
"extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }
}
]
@ -30,12 +30,12 @@ Updates installed alias packages in dry-run mode
{
"name": "a/a", "version": "dev-master",
"require": { "b/b": "2.0.*" },
"source": { "reference": "abcdef", "url": "", "type": "git" },
"source": { "reference": "abcdef", "url": "https://example.org", "type": "git" },
"extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }
},
{
"name": "b/b", "version": "dev-master",
"source": { "reference": "123456", "url": "", "type": "git" },
"source": { "reference": "123456", "url": "https://example.org", "type": "git" },
"extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }
}
]

View File

@ -9,12 +9,12 @@ Updates installed alias packages
{
"name": "a/a", "version": "dev-master",
"require": { "b/b": "2.0.*" },
"source": { "reference": "abcdef", "url": "", "type": "git" },
"source": { "reference": "abcdef", "url": "https://example.org", "type": "git" },
"extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }
},
{
"name": "b/b", "version": "dev-master",
"source": { "reference": "123456", "url": "", "type": "git" },
"source": { "reference": "123456", "url": "https://example.org", "type": "git" },
"extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }
}
]
@ -30,12 +30,12 @@ Updates installed alias packages
{
"name": "a/a", "version": "dev-master",
"require": { "b/b": "2.0.*" },
"source": { "reference": "abcdef", "url": "", "type": "git" },
"source": { "reference": "abcdef", "url": "https://example.org", "type": "git" },
"extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }
},
{
"name": "b/b", "version": "dev-master",
"source": { "reference": "123456", "url": "", "type": "git" },
"source": { "reference": "123456", "url": "https://example.org", "type": "git" },
"extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }
}
]

View File

@ -8,7 +8,7 @@ Updating a dev package forcing it's reference, using dry run, should not do anyt
"package": [
{
"name": "a/a", "version": "dev-master",
"source": { "reference": "abc123", "url": "", "type": "git" }
"source": { "reference": "abc123", "url": "https://example.org", "type": "git" }
}
]
}
@ -21,8 +21,8 @@ Updating a dev package forcing it's reference, using dry run, should not do anyt
[
{
"name": "a/a", "version": "dev-master",
"source": { "reference": "def000", "url": "", "type": "git" },
"dist": { "reference": "def000", "url": "", "type": "zip", "shasum": "" }
"source": { "reference": "def000", "url": "https://example.org", "type": "git" },
"dist": { "reference": "def000", "url": "https://example.org", "type": "zip", "shasum": "" }
}
]
--RUN--

View File

@ -8,7 +8,7 @@ Updating a dev package forcing it's reference should not do anything if the refe
"package": [
{
"name": "a/a", "version": "dev-master",
"source": { "reference": "abc123", "url": "", "type": "git" }
"source": { "reference": "abc123", "url": "https://example.org", "type": "git" }
}
]
}
@ -21,8 +21,8 @@ Updating a dev package forcing it's reference should not do anything if the refe
[
{
"name": "a/a", "version": "dev-master",
"source": { "reference": "def000", "url": "", "type": "git" },
"dist": { "reference": "def000", "url": "", "type": "zip", "shasum": "" }
"source": { "reference": "def000", "url": "https://example.org", "type": "git" },
"dist": { "reference": "def000", "url": "https://example.org", "type": "zip", "shasum": "" }
}
]
--RUN--

View File

@ -8,7 +8,7 @@ Updating a dev package should update to the latest available reference
"package": [
{
"name": "a/a", "version": "dev-master",
"source": { "reference": "abc123", "url": "", "type": "git" }
"source": { "reference": "abc123", "url": "https://example.org", "type": "git" }
}
]
}
@ -21,8 +21,8 @@ Updating a dev package should update to the latest available reference
[
{
"name": "a/a", "version": "dev-master",
"source": { "reference": "def000", "url": "", "type": "git" },
"dist": { "reference": "def000", "url": "", "type": "zip", "shasum": "" }
"source": { "reference": "def000", "url": "https://example.org", "type": "git" },
"dist": { "reference": "def000", "url": "https://example.org", "type": "zip", "shasum": "" }
}
]
--RUN--

View File

@ -8,7 +8,7 @@ Updates a dev package forcing its reference
"package": [
{
"name": "a/a", "version": "dev-master",
"source": { "reference": "abc123", "url": "", "type": "git" }
"source": { "reference": "abc123", "url": "https://example.org", "type": "git" }
}
]
}
@ -21,7 +21,7 @@ Updates a dev package forcing its reference
[
{
"name": "a/a", "version": "dev-master",
"source": { "reference": "abc123", "url": "", "type": "git" }
"source": { "reference": "abc123", "url": "https://example.org", "type": "git" }
}
]
--RUN--

View File

@ -12,7 +12,7 @@ Installing locked dev packages should remove old dependencies
"packages": [
{
"name": "a/devpackage", "version": "dev-master",
"source": { "reference": "newref", "url": "", "type": "git" },
"source": { "reference": "newref", "url": "https://example.org", "type": "git" },
"require": {},
"default-branch": true
}
@ -28,7 +28,7 @@ Installing locked dev packages should remove old dependencies
[
{
"name": "a/devpackage", "version": "dev-master",
"source": { "reference": "oldref", "url": "", "type": "git" },
"source": { "reference": "oldref", "url": "https://example.org", "type": "git" },
"require": {
"a/dependency": "*"
},
@ -36,7 +36,7 @@ Installing locked dev packages should remove old dependencies
},
{
"name": "a/dependency", "version": "dev-master",
"source": { "reference": "ref", "url": "", "type": "git" },
"source": { "reference": "ref", "url": "https://example.org", "type": "git" },
"require": {},
"default-branch": true
}

View File

@ -24,7 +24,7 @@ use PHPUnit\Framework\AssertionFailedError;
class HttpDownloaderMock extends HttpDownloader
{
/**
* @var array<array{url: string, options: array<mixed>|null, status: int, body: string, headers: list<string>}>|null
* @var array<array{url: non-empty-string, options: array<mixed>|null, status: int, body: string, headers: list<string>}>|null
*/
private $expectations = null;
/**
@ -52,7 +52,7 @@ class HttpDownloaderMock extends HttpDownloader
}
/**
* @param array<array{url: string, options?: array<mixed>, status?: int, body?: string, headers?: array<string>}> $expectations
* @param array<array{url: non-empty-string, options?: array<mixed>, status?: int, body?: string, headers?: array<string>}> $expectations
* @param bool $strict set to true if you want to provide *all* expected http requests, and not just a subset you are interested in testing
* @param array{status?: int, body?: string, headers?: array<string>} $defaultHandler default URL handler for undefined requests if not in strict mode
*/
@ -64,23 +64,11 @@ class HttpDownloaderMock extends HttpDownloader
throw new \UnexpectedValueException('Unexpected keys in process execution step: '.implode(', ', array_keys($diff)));
}
// set defaults in a PHPStan-happy way (array_merge is not well supported)
$expect['url'] = $expect['url'] ?? $default['url'];
$expect['options'] = $expect['options'] ?? $default['options'];
$expect['status'] = $expect['status'] ?? $default['status'];
$expect['body'] = $expect['body'] ?? $default['body'];
$expect['headers'] = $expect['headers'] ?? $default['headers'];
return $expect;
return array_merge($default, $expect);
}, $expectations);
$this->strict = $strict;
// set defaults in a PHPStan-happy way (array_merge is not well supported)
$defaultHandler['status'] = $defaultHandler['status'] ?? $this->defaultHandler['status'];
$defaultHandler['body'] = $defaultHandler['body'] ?? $this->defaultHandler['body'];
$defaultHandler['headers'] = $defaultHandler['headers'] ?? $this->defaultHandler['headers'];
$this->defaultHandler = $defaultHandler;
$this->defaultHandler = array_merge($this->defaultHandler, $defaultHandler);
}
public function assertComplete(): void
@ -107,6 +95,10 @@ class HttpDownloaderMock extends HttpDownloader
public function get($fileUrl, $options = []): Response
{
if ('' === $fileUrl) {
throw new \LogicException('url cannot be an empty string');
}
$this->log[] = $fileUrl;
if (is_array($this->expectations) && count($this->expectations) > 0 && $fileUrl === $this->expectations[0]['url'] && ($this->expectations[0]['options'] === null || $options === $this->expectations[0]['options'])) {
@ -128,6 +120,7 @@ class HttpDownloaderMock extends HttpDownloader
/**
* @param string[] $headers
* @param non-empty-string $url
*/
private function respond(string $url, int $status, array $headers, string $body): Response
{

View File

@ -74,23 +74,11 @@ class ProcessExecutorMock extends ProcessExecutor
throw new \UnexpectedValueException('Unexpected keys in process execution step: '.implode(', ', array_keys($diff)));
}
// set defaults in a PHPStan-happy way (array_merge is not well supported)
$expect['cmd'] = $expect['cmd'] ?? $default['cmd'];
$expect['return'] = $expect['return'] ?? $default['return'];
$expect['stdout'] = $expect['stdout'] ?? $default['stdout'];
$expect['stderr'] = $expect['stderr'] ?? $default['stderr'];
$expect['callback'] = $expect['callback'] ?? $default['callback'];
return $expect;
return array_merge($default, $expect);
}, $expectations);
$this->strict = $strict;
// set defaults in a PHPStan-happy way (array_merge is not well supported)
$defaultHandler['return'] = $defaultHandler['return'] ?? $this->defaultHandler['return'];
$defaultHandler['stdout'] = $defaultHandler['stdout'] ?? $this->defaultHandler['stdout'];
$defaultHandler['stderr'] = $defaultHandler['stderr'] ?? $this->defaultHandler['stderr'];
$this->defaultHandler = $defaultHandler;
$this->defaultHandler = array_merge($this->defaultHandler, $defaultHandler);
}
public function assertComplete(): void

View File

@ -274,6 +274,8 @@ class ComposerRepositoryTest extends TestCase
/**
* @dataProvider provideCanonicalizeUrlTestCases
* @param non-empty-string $url
* @param non-empty-string $repositoryUrl
*/
public function testCanonicalizeUrl(string $expected, string $url, string $repositoryUrl): void
{

View File

@ -86,6 +86,8 @@ class GitLabDriverTest extends TestCase
/**
* @dataProvider provideInitializeUrls
* @param non-empty-string $url
* @param non-empty-string $apiUrl
*/
public function testInitialize(string $url, string $apiUrl): GitLabDriver
{
@ -126,6 +128,8 @@ JSON;
/**
* @dataProvider provideInitializeUrls
* @param non-empty-string $url
* @param non-empty-string $apiUrl
*/
public function testInitializePublicProject(string $url, string $apiUrl): GitLabDriver
{
@ -164,6 +168,8 @@ JSON;
/**
* @dataProvider provideInitializeUrls
* @param non-empty-string $url
* @param non-empty-string $apiUrl
*/
public function testInitializePublicProjectAsAnonymous(string $url, string $apiUrl): GitLabDriver
{

View File

@ -72,6 +72,7 @@ class ProxyManagerTest extends TestCase
*
* @param array<string, mixed> $server
* @param mixed[] $expectedOptions
* @param non-empty-string $url
*/
public function testGetProxyForRequest(array $server, string $url, string $expectedUrl, array $expectedOptions, bool $expectedSecure, string $expectedMessage): void
{

View File

@ -276,6 +276,7 @@ class RemoteFilesystemTest extends TestCase
* Tests that a BitBucket public download is correctly retrieved.
*
* @dataProvider provideBitbucketPublicDownloadUrls
* @param non-empty-string $url
*/
public function testBitBucketPublicDownload(string $url, string $contents): void
{
@ -297,6 +298,7 @@ class RemoteFilesystemTest extends TestCase
* Tests that a BitBucket public download is correctly retrieved when `bitbucket-oauth` is configured.
*
* @dataProvider provideBitbucketPublicDownloadUrls
* @param non-empty-string $url
*/
public function testBitBucketPublicDownloadWithAuthConfigured(string $url, string $contents): void
{

View File

@ -22,6 +22,7 @@ class UrlTest extends TestCase
* @dataProvider distRefsProvider
*
* @param array<string, mixed> $conf
* @param non-empty-string $url
*/
public function testUpdateDistReference(string $url, string $expectedUrl, array $conf = [], string $ref = 'newref'): void
{