Merge branch '2.0' into solve-without-installed
* 2.0: (101 commits) SVN: hide passwords for debug output Free $solver asap fixes #8179 [minor] Fixed a typo in the CHANGELOG.md. Update deps Update changelog Revert "Allow overriding self-update target file with envvar COMPOSER_SELF_UPDATE_TARGET" Revert "Add docs for COMPOSER_SELF_UPDATE_TARGET, refs #8151" Add docs for COMPOSER_SELF_UPDATE_TARGET, refs #8151 Fix display of HHVM warning appearing when HHVM is not in use, fixes #8138 Read classmap-authoritative and apcu-autoloader from project config when installing via create-project, fixes #8155 Use possessive quantifiers Update xdebug-handler to 1.3.3 fixes #8159 Allow overriding self-update target file with envvar COMPOSER_SELF_UPDATE_TARGET flag should come before script name use full command name, not abbreviated/alias modify text Document the alternatives to disable the default script timeout Anchor pattern Fix URL resolution for Composer repositories ...pull/7936/head
commit
9053d74282
|
@ -10,3 +10,8 @@
|
||||||
|
|
||||||
# Exclude non-essential files from dist
|
# Exclude non-essential files from dist
|
||||||
/tests export-ignore
|
/tests export-ignore
|
||||||
|
.github export-ignore
|
||||||
|
.php_cs export-ignore
|
||||||
|
.travis.yml export-ignore
|
||||||
|
appveyor.yml export-ignore
|
||||||
|
phpunit.xml.dist export-ignore
|
||||||
|
|
|
@ -25,8 +25,10 @@ matrix:
|
||||||
- php: 7.1
|
- php: 7.1
|
||||||
- php: 7.2
|
- php: 7.2
|
||||||
- php: 7.3
|
- php: 7.3
|
||||||
|
env: PHPSTAN=1
|
||||||
- php: 7.3
|
- php: 7.3
|
||||||
env: deps=high
|
env:
|
||||||
|
- deps=high
|
||||||
- php: nightly
|
- php: nightly
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
allow_failures:
|
allow_failures:
|
||||||
|
@ -58,6 +60,11 @@ before_script:
|
||||||
script:
|
script:
|
||||||
# run test suite directories in parallel using GNU parallel
|
# run test suite directories in parallel using GNU parallel
|
||||||
- ls -d tests/Composer/Test/* | grep -v TestCase.php | parallel --gnu --keep-order 'echo "Running {} tests"; ./vendor/bin/phpunit -c tests/complete.phpunit.xml --colors=always {} || (echo -e "\e[41mFAILED\e[0m {}" && exit 1);'
|
- ls -d tests/Composer/Test/* | grep -v TestCase.php | parallel --gnu --keep-order 'echo "Running {} tests"; ./vendor/bin/phpunit -c tests/complete.phpunit.xml --colors=always {} || (echo -e "\e[41mFAILED\e[0m {}" && exit 1);'
|
||||||
|
# Run PHPStan
|
||||||
|
- if [[ $PHPSTAN == "1" ]]; then
|
||||||
|
composer require --dev phpstan/phpstan-shim:^0.11 --ignore-platform-reqs &&
|
||||||
|
vendor/bin/phpstan.phar analyse src tests --configuration=phpstan/config.neon --autoload-file=phpstan/autoload.php;
|
||||||
|
fi
|
||||||
|
|
||||||
before_deploy:
|
before_deploy:
|
||||||
- php -d phar.readonly=0 bin/compile
|
- php -d phar.readonly=0 bin/compile
|
||||||
|
|
28
CHANGELOG.md
28
CHANGELOG.md
|
@ -1,3 +1,25 @@
|
||||||
|
### [1.8.6] 2019-06-11
|
||||||
|
|
||||||
|
* Fixed handling of backslash-escapes handling in composer.json when using the require command
|
||||||
|
* Fixed create-project not following classmap-authoritative and apcu-autoloader config values
|
||||||
|
* Fixed HHVM version warning showing up in some cases when it was not in use
|
||||||
|
|
||||||
|
### [1.8.5] 2019-04-09
|
||||||
|
|
||||||
|
* HHVM 4.0 is no longer compatible with Composer. Please use PHP instead going forward.
|
||||||
|
* Added forward compatibility with upcoming 2.0 changes
|
||||||
|
* Fixed support for PHP 7.3-style heredoc/nowdoc syntax changes in autoload generation
|
||||||
|
* Fixed require command usage when combined with --ignore-platform-reqs
|
||||||
|
* Fixed and cleaned up various Windows junctions handling issues
|
||||||
|
|
||||||
|
### [1.8.4] 2019-02-11
|
||||||
|
|
||||||
|
* Fixed long standing solver bug leading to odd solving issues in edge cases, see #7946
|
||||||
|
* Fixed HHVM support for upcoming releases
|
||||||
|
* Fixed unix proxy for binaries to be POSIX compatible instead of breaking some shells
|
||||||
|
* Fixed invalid deprecation warning for composer-plugin-api
|
||||||
|
* Fixed edge case issues with Windows junctions when working with path repositories
|
||||||
|
|
||||||
### [1.8.3] 2019-01-30
|
### [1.8.3] 2019-01-30
|
||||||
|
|
||||||
* Fixed regression when executing partial updates
|
* Fixed regression when executing partial updates
|
||||||
|
@ -729,6 +751,12 @@
|
||||||
|
|
||||||
* Initial release
|
* Initial release
|
||||||
|
|
||||||
|
[1.8.6]: https://github.com/composer/composer/compare/1.8.5...1.8.6
|
||||||
|
[1.8.5]: https://github.com/composer/composer/compare/1.8.4...1.8.5
|
||||||
|
[1.8.4]: https://github.com/composer/composer/compare/1.8.3...1.8.4
|
||||||
|
[1.8.3]: https://github.com/composer/composer/compare/1.8.2...1.8.3
|
||||||
|
[1.8.2]: https://github.com/composer/composer/compare/1.8.1...1.8.2
|
||||||
|
[1.8.1]: https://github.com/composer/composer/compare/1.8.0...1.8.1
|
||||||
[1.8.0]: https://github.com/composer/composer/compare/1.7.3...1.8.0
|
[1.8.0]: https://github.com/composer/composer/compare/1.7.3...1.8.0
|
||||||
[1.7.3]: https://github.com/composer/composer/compare/1.7.2...1.7.3
|
[1.7.3]: https://github.com/composer/composer/compare/1.7.2...1.7.3
|
||||||
[1.7.2]: https://github.com/composer/composer/compare/1.7.1...1.7.2
|
[1.7.2]: https://github.com/composer/composer/compare/1.7.1...1.7.2
|
||||||
|
|
|
@ -3,7 +3,7 @@ clone_depth: 5
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
# This sets the PHP version (from Chocolatey)
|
# This sets the PHP version (from Chocolatey)
|
||||||
PHPCI_CHOCO_VERSION: 7.2.9
|
PHPCI_CHOCO_VERSION: 7.3.1
|
||||||
PHPCI_CACHE: C:\tools\phpci
|
PHPCI_CACHE: C:\tools\phpci
|
||||||
PHPCI_PHP: C:\tools\phpci\php
|
PHPCI_PHP: C:\tools\phpci\php
|
||||||
PHPCI_COMPOSER: C:\tools\phpci\composer
|
PHPCI_COMPOSER: C:\tools\phpci\composer
|
||||||
|
|
|
@ -18,6 +18,11 @@ $xdebug = new XdebugHandler('Composer', '--ansi');
|
||||||
$xdebug->check();
|
$xdebug->check();
|
||||||
unset($xdebug);
|
unset($xdebug);
|
||||||
|
|
||||||
|
if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '4.0', '>=')) {
|
||||||
|
echo 'HHVM 4.0 has dropped support for Composer, please use PHP instead. Aborting.'.PHP_EOL;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (function_exists('ini_set')) {
|
if (function_exists('ini_set')) {
|
||||||
@ini_set('display_errors', 1);
|
@ini_set('display_errors', 1);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "composer/composer",
|
"name": "composer/composer",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"description": "Composer helps you declare, manage and install dependencies of PHP projects, ensuring you have the right stack everywhere.",
|
"description": "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"package",
|
"package",
|
||||||
"dependency",
|
"dependency",
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.9-dev"
|
"dev-master": "2.0-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "b078b12b2912d599e0c6904f64def484",
|
"content-hash": "280f5d5184039085b5f22236d267ae82",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "composer/ca-bundle",
|
"name": "composer/ca-bundle",
|
||||||
|
@ -64,16 +64,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "composer/semver",
|
"name": "composer/semver",
|
||||||
"version": "1.4.2",
|
"version": "1.5.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/composer/semver.git",
|
"url": "https://github.com/composer/semver.git",
|
||||||
"reference": "c7cb9a2095a074d131b65a8a0cd294479d785573"
|
"reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573",
|
"url": "https://api.github.com/repos/composer/semver/zipball/46d9139568ccb8d9e7cdd4539cab7347568a5e2e",
|
||||||
"reference": "c7cb9a2095a074d131b65a8a0cd294479d785573",
|
"reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -122,28 +122,27 @@
|
||||||
"validation",
|
"validation",
|
||||||
"versioning"
|
"versioning"
|
||||||
],
|
],
|
||||||
"time": "2016-08-30T16:08:34+00:00"
|
"time": "2019-03-19T17:25:45+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "composer/spdx-licenses",
|
"name": "composer/spdx-licenses",
|
||||||
"version": "1.5.0",
|
"version": "1.5.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/composer/spdx-licenses.git",
|
"url": "https://github.com/composer/spdx-licenses.git",
|
||||||
"reference": "7a9556b22bd9d4df7cad89876b00af58ef20d3a2"
|
"reference": "a1aa51cf3ab838b83b0867b14e56fc20fbd55b3d"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/composer/spdx-licenses/zipball/7a9556b22bd9d4df7cad89876b00af58ef20d3a2",
|
"url": "https://api.github.com/repos/composer/spdx-licenses/zipball/a1aa51cf3ab838b83b0867b14e56fc20fbd55b3d",
|
||||||
"reference": "7a9556b22bd9d4df7cad89876b00af58ef20d3a2",
|
"reference": "a1aa51cf3ab838b83b0867b14e56fc20fbd55b3d",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^5.3.2 || ^7.0"
|
"php": "^5.3.2 || ^7.0 || ^8.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5",
|
"phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 7"
|
||||||
"phpunit/phpunit-mock-objects": "2.3.0 || ^3.0"
|
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
|
@ -183,20 +182,20 @@
|
||||||
"spdx",
|
"spdx",
|
||||||
"validator"
|
"validator"
|
||||||
],
|
],
|
||||||
"time": "2018-11-01T09:45:54+00:00"
|
"time": "2019-03-26T10:23:26+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "composer/xdebug-handler",
|
"name": "composer/xdebug-handler",
|
||||||
"version": "1.3.2",
|
"version": "1.3.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/composer/xdebug-handler.git",
|
"url": "https://github.com/composer/xdebug-handler.git",
|
||||||
"reference": "d17708133b6c276d6e42ef887a877866b909d892"
|
"reference": "46867cbf8ca9fb8d60c506895449eb799db1184f"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/d17708133b6c276d6e42ef887a877866b909d892",
|
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/46867cbf8ca9fb8d60c506895449eb799db1184f",
|
||||||
"reference": "d17708133b6c276d6e42ef887a877866b909d892",
|
"reference": "46867cbf8ca9fb8d60c506895449eb799db1184f",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -227,27 +226,27 @@
|
||||||
"Xdebug",
|
"Xdebug",
|
||||||
"performance"
|
"performance"
|
||||||
],
|
],
|
||||||
"time": "2019-01-28T20:25:53+00:00"
|
"time": "2019-05-27T17:52:04+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "justinrainbow/json-schema",
|
"name": "justinrainbow/json-schema",
|
||||||
"version": "5.2.7",
|
"version": "5.2.8",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/justinrainbow/json-schema.git",
|
"url": "https://github.com/justinrainbow/json-schema.git",
|
||||||
"reference": "8560d4314577199ba51bf2032f02cd1315587c23"
|
"reference": "dcb6e1006bb5fd1e392b4daa68932880f37550d4"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/8560d4314577199ba51bf2032f02cd1315587c23",
|
"url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/dcb6e1006bb5fd1e392b4daa68932880f37550d4",
|
||||||
"reference": "8560d4314577199ba51bf2032f02cd1315587c23",
|
"reference": "dcb6e1006bb5fd1e392b4daa68932880f37550d4",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.3"
|
"php": ">=5.3.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"friendsofphp/php-cs-fixer": "^2.1",
|
"friendsofphp/php-cs-fixer": "~2.2.20",
|
||||||
"json-schema/json-schema-test-suite": "1.2.0",
|
"json-schema/json-schema-test-suite": "1.2.0",
|
||||||
"phpunit/phpunit": "^4.8.35"
|
"phpunit/phpunit": "^4.8.35"
|
||||||
},
|
},
|
||||||
|
@ -293,7 +292,7 @@
|
||||||
"json",
|
"json",
|
||||||
"schema"
|
"schema"
|
||||||
],
|
],
|
||||||
"time": "2018-02-14T22:26:30+00:00"
|
"time": "2019-01-14T23:55:14+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/log",
|
"name": "psr/log",
|
||||||
|
@ -481,7 +480,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v2.8.48",
|
"version": "v2.8.50",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/console.git",
|
"url": "https://github.com/symfony/console.git",
|
||||||
|
@ -542,7 +541,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/debug",
|
"name": "symfony/debug",
|
||||||
"version": "v2.8.48",
|
"version": "v2.8.50",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/debug.git",
|
"url": "https://github.com/symfony/debug.git",
|
||||||
|
@ -599,7 +598,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/filesystem",
|
"name": "symfony/filesystem",
|
||||||
"version": "v2.8.48",
|
"version": "v2.8.50",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/filesystem.git",
|
"url": "https://github.com/symfony/filesystem.git",
|
||||||
|
@ -649,7 +648,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/finder",
|
"name": "symfony/finder",
|
||||||
"version": "v2.8.48",
|
"version": "v2.8.50",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/finder.git",
|
"url": "https://github.com/symfony/finder.git",
|
||||||
|
@ -698,16 +697,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-ctype",
|
"name": "symfony/polyfill-ctype",
|
||||||
"version": "v1.10.0",
|
"version": "v1.11.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||||
"reference": "e3d826245268269cd66f8326bd8bc066687b4a19"
|
"reference": "82ebae02209c21113908c229e9883c419720738a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19",
|
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a",
|
||||||
"reference": "e3d826245268269cd66f8326bd8bc066687b4a19",
|
"reference": "82ebae02209c21113908c229e9883c419720738a",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -719,7 +718,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.9-dev"
|
"dev-master": "1.11-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -752,20 +751,20 @@
|
||||||
"polyfill",
|
"polyfill",
|
||||||
"portable"
|
"portable"
|
||||||
],
|
],
|
||||||
"time": "2018-08-06T14:22:27+00:00"
|
"time": "2019-02-06T07:57:58+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-mbstring",
|
"name": "symfony/polyfill-mbstring",
|
||||||
"version": "v1.10.0",
|
"version": "v1.11.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||||
"reference": "c79c051f5b3a46be09205c73b80b346e4153e494"
|
"reference": "fe5e94c604826c35a32fa832f35bd036b6799609"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
|
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609",
|
||||||
"reference": "c79c051f5b3a46be09205c73b80b346e4153e494",
|
"reference": "fe5e94c604826c35a32fa832f35bd036b6799609",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -777,7 +776,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.9-dev"
|
"dev-master": "1.11-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -811,11 +810,11 @@
|
||||||
"portable",
|
"portable",
|
||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
"time": "2018-09-21T13:07:52+00:00"
|
"time": "2019-02-06T07:57:58+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/process",
|
"name": "symfony/process",
|
||||||
"version": "v2.8.48",
|
"version": "v2.8.50",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/process.git",
|
"url": "https://github.com/symfony/process.git",
|
||||||
|
@ -1780,7 +1779,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/yaml",
|
"name": "symfony/yaml",
|
||||||
"version": "v2.8.48",
|
"version": "v2.8.50",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/yaml.git",
|
"url": "https://github.com/symfony/yaml.git",
|
||||||
|
|
|
@ -82,7 +82,7 @@ Now run `php bin/composer` in order to run Composer.
|
||||||
#### Globally
|
#### Globally
|
||||||
|
|
||||||
You can place the Composer PHAR anywhere you wish. If you put it in a directory
|
You can place the Composer PHAR anywhere you wish. If you put it in a directory
|
||||||
that is part of your `PATH`, you can access it globally. On unixy systems you
|
that is part of your `PATH`, you can access it globally. On Unix systems you
|
||||||
can even make it executable and invoke it without directly using the `php`
|
can even make it executable and invoke it without directly using the `php`
|
||||||
interpreter.
|
interpreter.
|
||||||
|
|
||||||
|
|
|
@ -920,6 +920,10 @@ If you use a proxy but it does not support the request_fulluri flag for HTTPS
|
||||||
requests, then you should set this env var to `false` or `0` to prevent Composer
|
requests, then you should set this env var to `false` or `0` to prevent Composer
|
||||||
from setting the request_fulluri option.
|
from setting the request_fulluri option.
|
||||||
|
|
||||||
|
### COMPOSER_SELF_UPDATE_TARGET
|
||||||
|
|
||||||
|
If set, makes the self-update command write the new Composer phar file into that path instead of overwriting itself. Useful for updating Composer on read-only filesystem.
|
||||||
|
|
||||||
### no_proxy or NO_PROXY
|
### no_proxy or NO_PROXY
|
||||||
|
|
||||||
If you are behind a proxy and would like to disable it for certain domains, you
|
If you are behind a proxy and would like to disable it for certain domains, you
|
||||||
|
|
|
@ -666,6 +666,10 @@ Instead of default fallback strategy you can force to use symlink with
|
||||||
mirroring can be useful when deploying or generating package from a
|
mirroring can be useful when deploying or generating package from a
|
||||||
monolithic repository.
|
monolithic repository.
|
||||||
|
|
||||||
|
> **Note:** On Windows, directory symlinks are implemented using NTFS junctions
|
||||||
|
> because they can be created by non-admin users. Mirroring will always be used
|
||||||
|
> on versions below Windows 7 or if `proc_open` has been disabled.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"repositories": [
|
"repositories": [
|
||||||
|
|
|
@ -9,6 +9,20 @@ Defaults to `300`. The duration processes like git clones can run before
|
||||||
Composer assumes they died out. You may need to make this higher if you have a
|
Composer assumes they died out. You may need to make this higher if you have a
|
||||||
slow connection or huge vendors.
|
slow connection or huge vendors.
|
||||||
|
|
||||||
|
To disable the process timeout on a custom command under `scripts`, a static
|
||||||
|
helper is available:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"test": [
|
||||||
|
"Composer\\Config::disableProcessTimeout",
|
||||||
|
"phpunit"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## use-include-path
|
## use-include-path
|
||||||
|
|
||||||
Defaults to `false`. If `true`, the Composer autoloader will also look for classes
|
Defaults to `false`. If `true`, the Composer autoloader will also look for classes
|
||||||
|
|
|
@ -261,6 +261,11 @@ Now the `custom-plugin-command` is available alongside Composer commands.
|
||||||
|
|
||||||
> _Composer commands are based on the [Symfony Console Component][10]._
|
> _Composer commands are based on the [Symfony Console Component][10]._
|
||||||
|
|
||||||
|
## Running plugins manually
|
||||||
|
|
||||||
|
Plugins for an event can be run manually by the `run-script` command. This works the same way as
|
||||||
|
[running scripts manually](scripts.md#running-scripts-manually).
|
||||||
|
|
||||||
## Using Plugins
|
## Using Plugins
|
||||||
|
|
||||||
Plugin packages are automatically loaded as soon as they are installed and will
|
Plugin packages are automatically loaded as soon as they are installed and will
|
||||||
|
|
|
@ -189,7 +189,7 @@ composer run-script [--dev] [--no-dev] script
|
||||||
```
|
```
|
||||||
|
|
||||||
For example `composer run-script post-install-cmd` will run any
|
For example `composer run-script post-install-cmd` will run any
|
||||||
**post-install-cmd** scripts that have been defined.
|
**post-install-cmd** scripts and [plugins](plugins.md) that have been defined.
|
||||||
|
|
||||||
You can also give additional arguments to the script handler by appending `--`
|
You can also give additional arguments to the script handler by appending `--`
|
||||||
followed by the handler arguments. e.g.
|
followed by the handler arguments. e.g.
|
||||||
|
@ -221,6 +221,56 @@ to the `phpunit` script.
|
||||||
> are easily accessible. In this example no matter if the `phpunit` binary is
|
> are easily accessible. In this example no matter if the `phpunit` binary is
|
||||||
> actually in `vendor/bin/phpunit` or `bin/phpunit` it will be found and executed.
|
> actually in `vendor/bin/phpunit` or `bin/phpunit` it will be found and executed.
|
||||||
|
|
||||||
|
Although Composer is not intended to manage long-running processes and other
|
||||||
|
such aspects of PHP projects, it can sometimes be handy to disable the process
|
||||||
|
timeout on custom commands. This timeout defaults to 300 seconds and can be
|
||||||
|
overridden in a variety of ways depending on the desired effect:
|
||||||
|
|
||||||
|
- disable it for all commands using the config key `process-timeout`,
|
||||||
|
- disable it for the current or future invocations of composer using the
|
||||||
|
environment variable `COMPOSER_PROCESS_TIMEOUT`,
|
||||||
|
- for a specific invocation using the `--timeout` flag of the `run-script` command,
|
||||||
|
- using a static helper for specific scripts.
|
||||||
|
|
||||||
|
To disable the timeout for specific scripts with the static helper directly in
|
||||||
|
composer.json:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"test": [
|
||||||
|
"Composer\\Config::disableProcessTimeout",
|
||||||
|
"phpunit"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To disable the timeout for every script on a given project, you can use the
|
||||||
|
composer.json configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"process-timeout": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
It's also possible to set the global environment variable to disable the timeout
|
||||||
|
of all following scripts in the current terminal environment:
|
||||||
|
|
||||||
|
```
|
||||||
|
export COMPOSER_PROCESS_TIMEOUT=0
|
||||||
|
```
|
||||||
|
|
||||||
|
To disable the timeout of a single script call, you must use the `run-script` composer
|
||||||
|
command and specify the `--timeout` parameter:
|
||||||
|
|
||||||
|
```
|
||||||
|
composer run-script --timeout=0 test
|
||||||
|
```
|
||||||
|
|
||||||
## Referencing scripts
|
## Referencing scripts
|
||||||
|
|
||||||
To enable script re-use and avoid duplicates, you can call a script from another
|
To enable script re-use and avoid duplicates, you can call a script from another
|
||||||
|
|
|
@ -32,7 +32,7 @@ repository:*
|
||||||
v1
|
v1
|
||||||
v2
|
v2
|
||||||
my-feature
|
my-feature
|
||||||
nother-feature
|
another-feature
|
||||||
|
|
||||||
~/my-library$ git tag
|
~/my-library$ git tag
|
||||||
v1.0
|
v1.0
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../src/bootstrap.php';
|
|
@ -0,0 +1,42 @@
|
||||||
|
parameters:
|
||||||
|
level: 0
|
||||||
|
excludes_analyse:
|
||||||
|
- 'tests/Composer/Test/Fixtures'
|
||||||
|
- 'tests/Composer/Test/Autoload/Fixtures'
|
||||||
|
- 'tests/Composer/Test/Plugin/Fixtures'
|
||||||
|
ignoreErrors:
|
||||||
|
# unused parameters
|
||||||
|
- '~^Constructor of class Composer\\Repository\\VcsRepository has an unused parameter \$dispatcher\.$~'
|
||||||
|
- '~^Constructor of class Composer\\Repository\\PearRepository has an unused parameter \$dispatcher\.$~'
|
||||||
|
- '~^Constructor of class Composer\\Util\\Http\\CurlDownloader has an unused parameter \$disableTls\.$~'
|
||||||
|
- '~^Constructor of class Composer\\Util\\Http\\CurlDownloader has an unused parameter \$options\.$~'
|
||||||
|
- '~^Constructor of class Composer\\Repository\\PearRepository has an unused parameter \$config\.$~'
|
||||||
|
|
||||||
|
# unused uses
|
||||||
|
- '~^Anonymous function has an unused use \$io\.$~'
|
||||||
|
- '~^Anonymous function has an unused use \$cache\.$~'
|
||||||
|
- '~^Anonymous function has an unused use \$path\.$~'
|
||||||
|
- '~^Anonymous function has an unused use \$fileName\.$~'
|
||||||
|
|
||||||
|
# ion cube is not installed
|
||||||
|
- '~^Function ioncube_loader_\w+ not found\.$~'
|
||||||
|
# rar is not installed
|
||||||
|
- '~^Call to static method open\(\) on an unknown class RarArchive\.$~'
|
||||||
|
# imagick is not installed
|
||||||
|
- '~^Instantiated class Imagick not found\.$~'
|
||||||
|
|
||||||
|
# variables from global scope
|
||||||
|
- '~^Undefined variable: \$vendorDir$~'
|
||||||
|
- '~^Undefined variable: \$baseDir$~'
|
||||||
|
|
||||||
|
# variable defined in eval
|
||||||
|
- '~^Undefined variable: \$res$~'
|
||||||
|
|
||||||
|
# always checked whether the class exists
|
||||||
|
- '~^Instantiated class Symfony\\Component\\Console\\Terminal not found\.$~'
|
||||||
|
- '~^Class Symfony\\Component\\Console\\Input\\StreamableInputInterface not found\.$~'
|
||||||
|
- '~^Call to an undefined static method Symfony\\Component\\Process\\Process::fromShellCommandline\(\).$~'
|
||||||
|
|
||||||
|
# parent call in test mocks
|
||||||
|
- '~^Composer\\Test\\Mock\\HttpDownloaderMock::__construct\(\) does not call parent constructor from Composer\\Util\\HttpDownloader\.$~'
|
||||||
|
- '~^Composer\\Test\\Mock\\InstallationManagerMock::__construct\(\) does not call parent constructor from Composer\\Installer\\InstallationManager\.$~'
|
|
@ -21,6 +21,7 @@ use Composer\Package\PackageInterface;
|
||||||
use Composer\Repository\InstalledRepositoryInterface;
|
use Composer\Repository\InstalledRepositoryInterface;
|
||||||
use Composer\Util\Filesystem;
|
use Composer\Util\Filesystem;
|
||||||
use Composer\Script\ScriptEvents;
|
use Composer\Script\ScriptEvents;
|
||||||
|
use Composer\Util\PackageSorter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
@ -545,7 +546,7 @@ EOF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preg_match('/\.phar.+$/', $path)) {
|
if (strpos($path, '.phar') !== false) {
|
||||||
$baseDir = "'phar://' . " . $baseDir;
|
$baseDir = "'phar://' . " . $baseDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -769,10 +770,14 @@ HEADER;
|
||||||
$filesystem = new Filesystem();
|
$filesystem = new Filesystem();
|
||||||
|
|
||||||
$vendorPathCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
|
$vendorPathCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
|
||||||
|
$vendorPharPathCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
|
||||||
$appBaseDirCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
|
$appBaseDirCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
|
||||||
|
$appBaseDirPharCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
|
||||||
|
|
||||||
$absoluteVendorPathCode = ' => ' . substr(var_export(rtrim($vendorDir, '\\/') . '/', true), 0, -1);
|
$absoluteVendorPathCode = ' => ' . substr(var_export(rtrim($vendorDir, '\\/') . '/', true), 0, -1);
|
||||||
|
$absoluteVendorPharPathCode = ' => ' . substr(var_export(rtrim('phar://' . $vendorDir, '\\/') . '/', true), 0, -1);
|
||||||
$absoluteAppBaseDirCode = ' => ' . substr(var_export(rtrim($baseDir, '\\/') . '/', true), 0, -1);
|
$absoluteAppBaseDirCode = ' => ' . substr(var_export(rtrim($baseDir, '\\/') . '/', true), 0, -1);
|
||||||
|
$absoluteAppBaseDirPharCode = ' => ' . substr(var_export(rtrim('phar://' . $baseDir, '\\/') . '/', true), 0, -1);
|
||||||
|
|
||||||
$initializer = '';
|
$initializer = '';
|
||||||
$prefix = "\0Composer\Autoload\ClassLoader\0";
|
$prefix = "\0Composer\Autoload\ClassLoader\0";
|
||||||
|
@ -795,9 +800,15 @@ HEADER;
|
||||||
// See https://bugs.php.net/68057
|
// See https://bugs.php.net/68057
|
||||||
$staticPhpVersion = 70000;
|
$staticPhpVersion = 70000;
|
||||||
}
|
}
|
||||||
$value = var_export($value, true);
|
$value = strtr(
|
||||||
$value = str_replace($absoluteVendorPathCode, $vendorPathCode, $value);
|
var_export($value, true),
|
||||||
$value = str_replace($absoluteAppBaseDirCode, $appBaseDirCode, $value);
|
array(
|
||||||
|
$absoluteVendorPathCode => $vendorPathCode,
|
||||||
|
$absoluteVendorPharPathCode => $vendorPharPathCode,
|
||||||
|
$absoluteAppBaseDirCode => $appBaseDirCode,
|
||||||
|
$absoluteAppBaseDirPharCode => $appBaseDirPharCode,
|
||||||
|
)
|
||||||
|
);
|
||||||
$value = ltrim(preg_replace('/^ */m', ' $0$0', $value));
|
$value = ltrim(preg_replace('/^ */m', ' $0$0', $value));
|
||||||
|
|
||||||
$file .= sprintf(" public static $%s = %s;\n\n", $prop, $value);
|
$file .= sprintf(" public static $%s = %s;\n\n", $prop, $value);
|
||||||
|
@ -963,80 +974,21 @@ INITIALIZER;
|
||||||
{
|
{
|
||||||
$packages = array();
|
$packages = array();
|
||||||
$paths = array();
|
$paths = array();
|
||||||
$usageList = array();
|
|
||||||
|
|
||||||
foreach ($packageMap as $item) {
|
foreach ($packageMap as $item) {
|
||||||
list($package, $path) = $item;
|
list($package, $path) = $item;
|
||||||
$name = $package->getName();
|
$name = $package->getName();
|
||||||
$packages[$name] = $package;
|
$packages[$name] = $package;
|
||||||
$paths[$name] = $path;
|
$paths[$name] = $path;
|
||||||
|
|
||||||
foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) {
|
|
||||||
$target = $link->getTarget();
|
|
||||||
$usageList[$target][] = $name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$computing = array();
|
$sortedPackages = PackageSorter::sortPackages($packages);
|
||||||
$computed = array();
|
|
||||||
$computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) {
|
|
||||||
// reusing computed importance
|
|
||||||
if (isset($computed[$name])) {
|
|
||||||
return $computed[$name];
|
|
||||||
}
|
|
||||||
|
|
||||||
// canceling circular dependency
|
|
||||||
if (isset($computing[$name])) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$computing[$name] = true;
|
|
||||||
$weight = 0;
|
|
||||||
|
|
||||||
if (isset($usageList[$name])) {
|
|
||||||
foreach ($usageList[$name] as $user) {
|
|
||||||
$weight -= 1 - $computeImportance($user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unset($computing[$name]);
|
|
||||||
$computed[$name] = $weight;
|
|
||||||
|
|
||||||
return $weight;
|
|
||||||
};
|
|
||||||
|
|
||||||
$weightList = array();
|
|
||||||
|
|
||||||
foreach ($packages as $name => $package) {
|
|
||||||
$weight = $computeImportance($name);
|
|
||||||
$weightList[$name] = $weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stable_sort = function (&$array) {
|
|
||||||
static $transform, $restore;
|
|
||||||
|
|
||||||
$i = 0;
|
|
||||||
|
|
||||||
if (!$transform) {
|
|
||||||
$transform = function (&$v, $k) use (&$i) {
|
|
||||||
$v = array($v, ++$i, $k, $v);
|
|
||||||
};
|
|
||||||
|
|
||||||
$restore = function (&$v, $k) {
|
|
||||||
$v = $v[3];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
array_walk($array, $transform);
|
|
||||||
asort($array);
|
|
||||||
array_walk($array, $restore);
|
|
||||||
};
|
|
||||||
|
|
||||||
$stable_sort($weightList);
|
|
||||||
|
|
||||||
$sortedPackageMap = array();
|
$sortedPackageMap = array();
|
||||||
|
|
||||||
foreach (array_keys($weightList) as $name) {
|
foreach ($sortedPackages as $package) {
|
||||||
|
$name = $package->getName();
|
||||||
$sortedPackageMap[] = array($packages[$name], $paths[$name]);
|
$sortedPackageMap[] = array($packages[$name], $paths[$name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,7 +162,7 @@ class ClassMapGenerator
|
||||||
}
|
}
|
||||||
|
|
||||||
// strip heredocs/nowdocs
|
// strip heredocs/nowdocs
|
||||||
$contents = preg_replace('{<<<\s*(\'?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\2(?=\r\n|\n|\r|;)}s', 'null', $contents);
|
$contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)(?:\s*)\\2(?=\s+|[;,.)])}s', 'null', $contents);
|
||||||
// strip strings
|
// strip strings
|
||||||
$contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
|
$contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
|
||||||
// strip leading non-php code if needed
|
// strip leading non-php code if needed
|
||||||
|
|
|
@ -189,7 +189,8 @@ class Cache
|
||||||
public function clear()
|
public function clear()
|
||||||
{
|
{
|
||||||
if ($this->enabled) {
|
if ($this->enabled) {
|
||||||
return $this->filesystem->removeDirectory($this->root);
|
$this->filesystem->emptyDirectory($this->root);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -57,6 +57,7 @@ package in the specified version and writes it to the specified directory.
|
||||||
|
|
||||||
<info>php composer.phar archive [--format=zip] [--dir=/foo] [package [version]]</info>
|
<info>php composer.phar archive [--format=zip] [--dir=/foo] [package [version]]</info>
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#archive
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -27,6 +27,8 @@ use Symfony\Component\Console\Command\Command;
|
||||||
/**
|
/**
|
||||||
* Base class for Composer commands
|
* Base class for Composer commands
|
||||||
*
|
*
|
||||||
|
* @method Application getApplication()
|
||||||
|
*
|
||||||
* @author Ryan Weaver <ryan@knplabs.com>
|
* @author Ryan Weaver <ryan@knplabs.com>
|
||||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
@ -46,7 +48,7 @@ abstract class BaseCommand extends Command
|
||||||
* @param bool $required
|
* @param bool $required
|
||||||
* @param bool|null $disablePlugins
|
* @param bool|null $disablePlugins
|
||||||
* @throws \RuntimeException
|
* @throws \RuntimeException
|
||||||
* @return Composer
|
* @return Composer|null
|
||||||
*/
|
*/
|
||||||
public function getComposer($required = true, $disablePlugins = null)
|
public function getComposer($required = true, $disablePlugins = null)
|
||||||
{
|
{
|
||||||
|
@ -173,7 +175,7 @@ abstract class BaseCommand extends Command
|
||||||
|
|
||||||
if ($input->getOption('prefer-source') || $input->getOption('prefer-dist') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'))) {
|
if ($input->getOption('prefer-source') || $input->getOption('prefer-dist') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'))) {
|
||||||
$preferSource = $input->getOption('prefer-source') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'));
|
$preferSource = $input->getOption('prefer-source') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'));
|
||||||
$preferDist = $input->getOption('prefer-dist');
|
$preferDist = (bool) $input->getOption('prefer-dist');
|
||||||
}
|
}
|
||||||
|
|
||||||
return array($preferSource, $preferDist);
|
return array($preferSource, $preferDist);
|
||||||
|
|
|
@ -32,6 +32,8 @@ class ClearCacheCommand extends BaseCommand
|
||||||
<<<EOT
|
<<<EOT
|
||||||
The <info>clear-cache</info> deletes all cached packages from composer's
|
The <info>clear-cache</info> deletes all cached packages from composer's
|
||||||
cache directory.
|
cache directory.
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#clear-cache-clearcache-
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -125,6 +125,8 @@ You can always pass more than one option. As an example, if you want to edit the
|
||||||
global config.json file.
|
global config.json file.
|
||||||
|
|
||||||
<comment>%command.full_name% --editor --global</comment>
|
<comment>%command.full_name% --editor --global</comment>
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#config
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
@ -226,7 +228,7 @@ EOT
|
||||||
}
|
}
|
||||||
|
|
||||||
$settingKey = $input->getArgument('setting-key');
|
$settingKey = $input->getArgument('setting-key');
|
||||||
if (!$settingKey) {
|
if (!$settingKey || !is_string($settingKey)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,7 @@ controlled code by appending the <info>'--prefer-source'</info> flag.
|
||||||
To install a package from another repository than the default one you
|
To install a package from another repository than the default one you
|
||||||
can pass the <info>'--repository=https://myrepository.org'</info> flag.
|
can pass the <info>'--repository=https://myrepository.org'</info> flag.
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#create-project
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
@ -183,7 +184,9 @@ EOT
|
||||||
->setRunScripts(!$noScripts)
|
->setRunScripts(!$noScripts)
|
||||||
->setIgnorePlatformRequirements($ignorePlatformReqs)
|
->setIgnorePlatformRequirements($ignorePlatformReqs)
|
||||||
->setSuggestedPackagesReporter($this->suggestedPackagesReporter)
|
->setSuggestedPackagesReporter($this->suggestedPackagesReporter)
|
||||||
->setOptimizeAutoloader($config->get('optimize-autoloader'));
|
->setOptimizeAutoloader($config->get('optimize-autoloader'))
|
||||||
|
->setClassMapAuthoritative($config->get('classmap-authoritative'))
|
||||||
|
->setApcuAutoloader($config->get('apcu-autoloader'));
|
||||||
|
|
||||||
if ($disablePlugins) {
|
if ($disablePlugins) {
|
||||||
$installer->disablePlugins();
|
$installer->disablePlugins();
|
||||||
|
|
|
@ -37,6 +37,7 @@ Displays detailed information about where a package is referenced.
|
||||||
|
|
||||||
<info>php composer.phar depends composer/composer</info>
|
<info>php composer.phar depends composer/composer</info>
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#depends-why-
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -55,6 +55,7 @@ The <info>diagnose</info> command checks common errors to help debugging problem
|
||||||
|
|
||||||
The process exit code will be 1 in case of warnings and 2 for errors.
|
The process exit code will be 1 in case of warnings and 2 for errors.
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#diagnose
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
@ -602,20 +603,6 @@ EOT
|
||||||
$text .= "Install either of them or recompile php without --disable-iconv";
|
$text .= "Install either of them or recompile php without --disable-iconv";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'unicode':
|
|
||||||
$text = PHP_EOL."The detect_unicode setting must be disabled.".PHP_EOL;
|
|
||||||
$text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
|
|
||||||
$text .= " detect_unicode = Off";
|
|
||||||
$displayIniMessage = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'suhosin':
|
|
||||||
$text = PHP_EOL."The suhosin.executor.include.whitelist setting is incorrect.".PHP_EOL;
|
|
||||||
$text .= "Add the following to the end of your `php.ini` or suhosin.ini (Example path [for Debian]: /etc/php5/cli/conf.d/suhosin.ini):".PHP_EOL;
|
|
||||||
$text .= " suhosin.executor.include.whitelist = phar ".$current;
|
|
||||||
$displayIniMessage = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'php':
|
case 'php':
|
||||||
$text = PHP_EOL."Your PHP ({$current}) is too old, you must upgrade to PHP 5.3.2 or higher.";
|
$text = PHP_EOL."Your PHP ({$current}) is too old, you must upgrade to PHP 5.3.2 or higher.";
|
||||||
break;
|
break;
|
||||||
|
@ -713,7 +700,7 @@ EOT
|
||||||
/**
|
/**
|
||||||
* Check if allow_url_fopen is ON
|
* Check if allow_url_fopen is ON
|
||||||
*
|
*
|
||||||
* @return bool|string
|
* @return true|string
|
||||||
*/
|
*/
|
||||||
private function checkConnectivity()
|
private function checkConnectivity()
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,6 +39,8 @@ class DumpAutoloadCommand extends BaseCommand
|
||||||
->setHelp(
|
->setHelp(
|
||||||
<<<EOT
|
<<<EOT
|
||||||
<info>php composer.phar dump-autoload</info>
|
<info>php composer.phar dump-autoload</info>
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#dump-autoload-dumpautoload-
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -36,6 +36,13 @@ class ExecCommand extends BaseCommand
|
||||||
'Arguments to pass to the binary. Use <info>--</info> to separate from composer arguments'
|
'Arguments to pass to the binary. Use <info>--</info> to separate from composer arguments'
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
|
->setHelp(
|
||||||
|
<<<EOT
|
||||||
|
Executes a vendored binary/script.
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#exec
|
||||||
|
EOT
|
||||||
|
)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ XDG_CONFIG_HOME or default to /home/<user>/.config/composer
|
||||||
Note: This path may vary depending on customizations to bin-dir in
|
Note: This path may vary depending on customizations to bin-dir in
|
||||||
composer.json or the environmental variable COMPOSER_BIN_DIR.
|
composer.json or the environmental variable COMPOSER_BIN_DIR.
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#global
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -49,6 +49,8 @@ homepage in your default browser.
|
||||||
|
|
||||||
To open the homepage by default, use -H or --homepage.
|
To open the homepage by default, use -H or --homepage.
|
||||||
To show instead of open the repository or homepage URL, use -s or --show.
|
To show instead of open the repository or homepage URL, use -s or --show.
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#browse-home
|
||||||
EOT
|
EOT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,7 @@ in the current directory.
|
||||||
|
|
||||||
<info>php composer.phar init</info>
|
<info>php composer.phar init</info>
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#init
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
@ -694,15 +695,22 @@ EOT
|
||||||
{
|
{
|
||||||
// find the latest version allowed in this repo set
|
// find the latest version allowed in this repo set
|
||||||
$versionSelector = new VersionSelector($this->getRepositorySet($input, $minimumStability));
|
$versionSelector = new VersionSelector($this->getRepositorySet($input, $minimumStability));
|
||||||
$package = $versionSelector->findBestCandidate($name, $requiredVersion, $phpVersion, $preferredStability);
|
$ignorePlatformReqs = $input->hasOption('ignore-platform-reqs') && $input->getOption('ignore-platform-reqs');
|
||||||
|
|
||||||
// retry without phpVersion if platform requirements are ignored in case nothing was found
|
// ignore phpVersion if platform requirements are ignored
|
||||||
if ($input->hasOption('ignore-platform-reqs') && $input->getOption('ignore-platform-reqs')) {
|
if ($ignorePlatformReqs) {
|
||||||
$phpVersion = null;
|
$phpVersion = null;
|
||||||
$package = $versionSelector->findBestCandidate($name, $requiredVersion, $phpVersion, $preferredStability);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$package = $versionSelector->findBestCandidate($name, $requiredVersion, $phpVersion, $preferredStability);
|
||||||
|
|
||||||
if (!$package) {
|
if (!$package) {
|
||||||
|
// platform packages can not be found in the pool in versions other than the local platform's has
|
||||||
|
// so if platform reqs are ignored we just take the user's word for it
|
||||||
|
if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
|
||||||
|
return array($name, $requiredVersion ?: '*');
|
||||||
|
}
|
||||||
|
|
||||||
// Check whether the PHP version was the problem
|
// Check whether the PHP version was the problem
|
||||||
if ($phpVersion && $versionSelector->findBestCandidate($name, $requiredVersion, null, $preferredStability)) {
|
if ($phpVersion && $versionSelector->findBestCandidate($name, $requiredVersion, null, $preferredStability)) {
|
||||||
throw new \InvalidArgumentException(sprintf(
|
throw new \InvalidArgumentException(sprintf(
|
||||||
|
|
|
@ -61,6 +61,7 @@ exist it will look for composer.json and do the same.
|
||||||
|
|
||||||
<info>php composer.phar install</info>
|
<info>php composer.phar install</info>
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#install-i
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -41,6 +41,7 @@ class LicensesCommand extends BaseCommand
|
||||||
The license command displays detailed information about the licenses of
|
The license command displays detailed information about the licenses of
|
||||||
the installed dependencies.
|
the installed dependencies.
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#licenses
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -50,7 +50,7 @@ The color coding (or signage if you have ANSI colors disabled) for dependency ve
|
||||||
may involve work.
|
may involve work.
|
||||||
- <highlight>red</highlight> (!): Dependency has a new version that is semver-compatible and you should upgrade it.
|
- <highlight>red</highlight> (!): Dependency has a new version that is semver-compatible and you should upgrade it.
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#outdated
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -37,6 +37,7 @@ Displays detailed information about why a package cannot be installed.
|
||||||
|
|
||||||
<info>php composer.phar prohibits composer/composer</info>
|
<info>php composer.phar prohibits composer/composer</info>
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#prohibits-why-not-
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -56,6 +56,7 @@ list of installed packages
|
||||||
|
|
||||||
<info>php composer.phar remove</info>
|
<info>php composer.phar remove</info>
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#remove
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -25,6 +25,7 @@ use Composer\Plugin\CommandEvent;
|
||||||
use Composer\Plugin\PluginEvents;
|
use Composer\Plugin\PluginEvents;
|
||||||
use Composer\Repository\CompositeRepository;
|
use Composer\Repository\CompositeRepository;
|
||||||
use Composer\Repository\PlatformRepository;
|
use Composer\Repository\PlatformRepository;
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Jérémy Romey <jeremy@free-agent.fr>
|
* @author Jérémy Romey <jeremy@free-agent.fr>
|
||||||
|
@ -73,6 +74,7 @@ If you do not specify a version constraint, composer will choose a suitable one
|
||||||
|
|
||||||
If you do not want to install the new dependencies immediately you can call it with --no-update
|
If you do not want to install the new dependencies immediately you can call it with --no-update
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#require
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
@ -159,15 +161,26 @@ EOT
|
||||||
if ($input->getOption('no-update')) {
|
if ($input->getOption('no-update')) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return $this->doUpdate($input, $output, $io, $requirements);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->revertComposerFile(false);
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function doUpdate(InputInterface $input, OutputInterface $output, IOInterface $io, array $requirements)
|
||||||
|
{
|
||||||
|
// Update packages
|
||||||
|
$this->resetComposer();
|
||||||
|
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
|
||||||
|
|
||||||
$updateDevMode = !$input->getOption('update-no-dev');
|
$updateDevMode = !$input->getOption('update-no-dev');
|
||||||
$optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
|
$optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
|
||||||
$authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
|
$authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
|
||||||
$apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
|
$apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
|
||||||
|
|
||||||
// Update packages
|
|
||||||
$this->resetComposer();
|
|
||||||
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
|
|
||||||
|
|
||||||
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
|
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
|
||||||
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
|
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,8 @@ class RunScriptCommand extends BaseCommand
|
||||||
The <info>run-script</info> command runs scripts defined in composer.json:
|
The <info>run-script</info> command runs scripts defined in composer.json:
|
||||||
|
|
||||||
<info>php composer.phar run-script post-update-cmd</info>
|
<info>php composer.phar run-script post-update-cmd</info>
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#run-script
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -48,6 +48,8 @@ class ScriptAliasCommand extends BaseCommand
|
||||||
The <info>run-script</info> command runs scripts defined in composer.json:
|
The <info>run-script</info> command runs scripts defined in composer.json:
|
||||||
|
|
||||||
<info>php composer.phar run-script post-update-cmd</info>
|
<info>php composer.phar run-script post-update-cmd</info>
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#run-script
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -49,6 +49,7 @@ class SearchCommand extends BaseCommand
|
||||||
The search command searches for packages by its name
|
The search command searches for packages by its name
|
||||||
<info>php composer.phar search symfony composer</info>
|
<info>php composer.phar search symfony composer</info>
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#search
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -60,6 +60,7 @@ versions of composer and if found, installs the latest.
|
||||||
|
|
||||||
<info>php composer.phar self-update</info>
|
<info>php composer.phar self-update</info>
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#self-update-selfupdate-
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -85,6 +85,7 @@ class ShowCommand extends BaseCommand
|
||||||
The show command displays detailed information about a package, or
|
The show command displays detailed information about a package, or
|
||||||
lists all packages available.
|
lists all packages available.
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#show
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
@ -823,7 +824,7 @@ EOT
|
||||||
/**
|
/**
|
||||||
* Display a package tree
|
* Display a package tree
|
||||||
*
|
*
|
||||||
* @param PackageInterface|string $package
|
* @param array|string $package
|
||||||
* @param array $packagesInTree
|
* @param array $packagesInTree
|
||||||
* @param string $previousTreeBar
|
* @param string $previousTreeBar
|
||||||
* @param int $level
|
* @param int $level
|
||||||
|
@ -835,7 +836,7 @@ EOT
|
||||||
$level = 1
|
$level = 1
|
||||||
) {
|
) {
|
||||||
$previousTreeBar = str_replace('├', '│', $previousTreeBar);
|
$previousTreeBar = str_replace('├', '│', $previousTreeBar);
|
||||||
if (isset($package['requires'])) {
|
if (is_array($package) && isset($package['requires'])) {
|
||||||
$requires = $package['requires'];
|
$requires = $package['requires'];
|
||||||
$treeBar = $previousTreeBar . ' ├';
|
$treeBar = $previousTreeBar . ' ├';
|
||||||
$i = 0;
|
$i = 0;
|
||||||
|
@ -968,7 +969,7 @@ EOT
|
||||||
* @param string $phpVersion
|
* @param string $phpVersion
|
||||||
* @param bool $minorOnly
|
* @param bool $minorOnly
|
||||||
*
|
*
|
||||||
* @return PackageInterface|null
|
* @return PackageInterface|false
|
||||||
*/
|
*/
|
||||||
private function findLatestPackage(PackageInterface $package, Composer $composer, $phpVersion, $minorOnly = false)
|
private function findLatestPackage(PackageInterface $package, Composer $composer, $phpVersion, $minorOnly = false)
|
||||||
{
|
{
|
||||||
|
|
|
@ -52,6 +52,7 @@ class StatusCommand extends BaseCommand
|
||||||
The status command displays a list of dependencies that have
|
The status command displays a list of dependencies that have
|
||||||
been modified locally.
|
been modified locally.
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#status
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -38,11 +38,15 @@ The <info>%command.name%</info> command shows a sorted list of suggested package
|
||||||
|
|
||||||
Enabling <info>-v</info> implies <info>--by-package --by-suggestion</info>, showing both lists.
|
Enabling <info>-v</info> implies <info>--by-package --by-suggestion</info>, showing both lists.
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#suggests
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
{
|
{
|
||||||
$lock = $this->getComposer()->getLocker()->getLockData();
|
$lock = $this->getComposer()->getLocker()->getLockData();
|
||||||
|
@ -117,7 +121,7 @@ EOT
|
||||||
$io->write(sprintf('<info>%s</info>', $suggestion));
|
$io->write(sprintf('<info>%s</info>', $suggestion));
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grouped by package
|
// Grouped by package
|
||||||
|
|
|
@ -81,6 +81,7 @@ from a specific vendor:
|
||||||
|
|
||||||
To select packages names interactively with auto-completion use <info>-i</info>.
|
To select packages names interactively with auto-completion use <info>-i</info>.
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#update-u
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
|
@ -55,6 +55,7 @@ Exit codes in case of errors are:
|
||||||
2 validation error(s)
|
2 validation error(s)
|
||||||
3 file unreadable or missing
|
3 file unreadable or missing
|
||||||
|
|
||||||
|
Read more at https://getcomposer.org/doc/03-cli.md#validate
|
||||||
EOT
|
EOT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,6 +194,7 @@ class Compiler
|
||||||
$content = str_replace('@package_version@', $this->version, $content);
|
$content = str_replace('@package_version@', $this->version, $content);
|
||||||
$content = str_replace('@package_branch_alias_version@', $this->branchAliasVersion, $content);
|
$content = str_replace('@package_branch_alias_version@', $this->branchAliasVersion, $content);
|
||||||
$content = str_replace('@release_date@', $this->versionDate->format('Y-m-d H:i:s'), $content);
|
$content = str_replace('@release_date@', $this->versionDate->format('Y-m-d H:i:s'), $content);
|
||||||
|
$content = preg_replace('{SOURCE_VERSION = \'[^\']+\';}', 'SOURCE_VERSION = \'\';', $content);
|
||||||
}
|
}
|
||||||
|
|
||||||
$phar->addFromString($path, $content);
|
$phar->addFromString($path, $content);
|
||||||
|
|
|
@ -29,10 +29,46 @@ use Composer\Package\Archiver\ArchiveManager;
|
||||||
*/
|
*/
|
||||||
class Composer
|
class Composer
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Examples of the following constants in the various configurations they can be in
|
||||||
|
*
|
||||||
|
* releases (phar):
|
||||||
|
* const VERSION = '1.8.2';
|
||||||
|
* const BRANCH_ALIAS_VERSION = '';
|
||||||
|
* const RELEASE_DATE = '2019-01-29 15:00:53';
|
||||||
|
* const SOURCE_VERSION = '';
|
||||||
|
*
|
||||||
|
* snapshot builds (phar):
|
||||||
|
* const VERSION = 'd3873a05650e168251067d9648845c220c50e2d7';
|
||||||
|
* const BRANCH_ALIAS_VERSION = '1.9-dev';
|
||||||
|
* const RELEASE_DATE = '2019-02-20 07:43:56';
|
||||||
|
* const SOURCE_VERSION = '';
|
||||||
|
*
|
||||||
|
* source (git clone):
|
||||||
|
* const VERSION = '@package_version@';
|
||||||
|
* const BRANCH_ALIAS_VERSION = '@package_branch_alias_version@';
|
||||||
|
* const RELEASE_DATE = '@release_date@';
|
||||||
|
* const SOURCE_VERSION = '1.8-dev+source';
|
||||||
|
*/
|
||||||
const VERSION = '@package_version@';
|
const VERSION = '@package_version@';
|
||||||
const BRANCH_ALIAS_VERSION = '@package_branch_alias_version@';
|
const BRANCH_ALIAS_VERSION = '@package_branch_alias_version@';
|
||||||
const RELEASE_DATE = '@release_date@';
|
const RELEASE_DATE = '@release_date@';
|
||||||
const SOURCE_VERSION = '2.0-source';
|
const SOURCE_VERSION = '2.0-dev+source';
|
||||||
|
|
||||||
|
public static function getVersion()
|
||||||
|
{
|
||||||
|
// no replacement done, this must be a source checkout
|
||||||
|
if (self::VERSION === '@package_version'.'@') {
|
||||||
|
return self::SOURCE_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we have a branch alias and version is a commit id, this must be a snapshot build
|
||||||
|
if (self::BRANCH_ALIAS_VERSION !== '' && preg_match('{^[a-f0-9]{40}$}', self::VERSION)) {
|
||||||
|
return self::BRANCH_ALIAS_VERSION.'+'.self::VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Package\RootPackageInterface
|
* @var Package\RootPackageInterface
|
||||||
|
|
|
@ -16,6 +16,7 @@ use Composer\Config\ConfigSourceInterface;
|
||||||
use Composer\Downloader\TransportException;
|
use Composer\Downloader\TransportException;
|
||||||
use Composer\IO\IOInterface;
|
use Composer\IO\IOInterface;
|
||||||
use Composer\Util\Platform;
|
use Composer\Util\Platform;
|
||||||
|
use Composer\Util\ProcessExecutor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
@ -459,4 +460,20 @@ class Config
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by long-running custom scripts in composer.json
|
||||||
|
*
|
||||||
|
* "scripts": {
|
||||||
|
* "watch": [
|
||||||
|
* "Composer\\Config::disableProcessTimeout",
|
||||||
|
* "vendor/bin/long-running-script --watch"
|
||||||
|
* ]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
public static function disableProcessTimeout()
|
||||||
|
{
|
||||||
|
// Override global timeout set earlier by environment or config
|
||||||
|
ProcessExecutor::setTimeout(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ interface ConfigSourceInterface
|
||||||
* Add a config setting
|
* Add a config setting
|
||||||
*
|
*
|
||||||
* @param string $name Name
|
* @param string $name Name
|
||||||
* @param string $value Value
|
* @param string|array $value Value
|
||||||
*/
|
*/
|
||||||
public function addConfigSetting($name, $value);
|
public function addConfigSetting($name, $value);
|
||||||
|
|
||||||
|
|
|
@ -259,7 +259,7 @@ class JsonConfigSource implements ConfigSourceInterface
|
||||||
*
|
*
|
||||||
* @param array $array
|
* @param array $array
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
* @return array
|
* @return int
|
||||||
*/
|
*/
|
||||||
private function arrayUnshiftRef(&$array, &$value)
|
private function arrayUnshiftRef(&$array, &$value)
|
||||||
{
|
{
|
||||||
|
|
|
@ -91,7 +91,7 @@ class Application extends BaseApplication
|
||||||
|
|
||||||
$this->io = new NullIO();
|
$this->io = new NullIO();
|
||||||
|
|
||||||
parent::__construct('Composer', Composer::VERSION);
|
parent::__construct('Composer', Composer::getVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -190,7 +190,7 @@ class Application extends BaseApplication
|
||||||
if (!$isProxyCommand) {
|
if (!$isProxyCommand) {
|
||||||
$io->writeError(sprintf(
|
$io->writeError(sprintf(
|
||||||
'Running %s (%s) with %s on %s',
|
'Running %s (%s) with %s on %s',
|
||||||
Composer::VERSION,
|
Composer::getVersion(),
|
||||||
Composer::RELEASE_DATE,
|
Composer::RELEASE_DATE,
|
||||||
defined('HHVM_VERSION') ? 'HHVM '.HHVM_VERSION : 'PHP '.PHP_VERSION,
|
defined('HHVM_VERSION') ? 'HHVM '.HHVM_VERSION : 'PHP '.PHP_VERSION,
|
||||||
function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknown OS'
|
function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknown OS'
|
||||||
|
@ -284,7 +284,7 @@ class Application extends BaseApplication
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
} catch (ScriptExecutionException $e) {
|
} catch (ScriptExecutionException $e) {
|
||||||
return $e->getCode();
|
return (int) $e->getCode();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->hintCommonErrors($e);
|
$this->hintCommonErrors($e);
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
|
@ -440,7 +440,7 @@ class Application extends BaseApplication
|
||||||
*/
|
*/
|
||||||
public function getLongVersion()
|
public function getLongVersion()
|
||||||
{
|
{
|
||||||
if (Composer::BRANCH_ALIAS_VERSION) {
|
if (Composer::BRANCH_ALIAS_VERSION && Composer::BRANCH_ALIAS_VERSION !== '@package_branch_alias_version'.'@') {
|
||||||
return sprintf(
|
return sprintf(
|
||||||
'<info>%s</info> version <comment>%s (%s)</comment> %s',
|
'<info>%s</info> version <comment>%s (%s)</comment> %s',
|
||||||
$this->getName(),
|
$this->getName(),
|
||||||
|
|
|
@ -24,8 +24,8 @@ class GenericRule extends Rule
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $literals
|
* @param array $literals
|
||||||
* @param int $reason A RULE_* constant describing the reason for generating this rule
|
* @param int|null $reason A RULE_* constant describing the reason for generating this rule
|
||||||
* @param Link|PackageInterface $reasonData
|
* @param Link|PackageInterface|int|null $reasonData
|
||||||
* @param array $job The job this rule was created from
|
* @param array $job The job this rule was created from
|
||||||
*/
|
*/
|
||||||
public function __construct(array $literals, $reason, $reasonData, $job = null)
|
public function __construct(array $literals, $reason, $reasonData, $job = null)
|
||||||
|
|
|
@ -48,7 +48,7 @@ class PoolBuilder
|
||||||
|
|
||||||
public function buildPool(array $repositories, array $rootAliases, Request $request)
|
public function buildPool(array $repositories, array $rootAliases, Request $request)
|
||||||
{
|
{
|
||||||
$this->pool = new Pool($this->filterRequires);
|
$pool = new Pool($this->filterRequires);
|
||||||
$this->rootAliases = $rootAliases;
|
$this->rootAliases = $rootAliases;
|
||||||
|
|
||||||
// TODO do we really want the request here? kind of want a root requirements thingy instead
|
// TODO do we really want the request here? kind of want a root requirements thingy instead
|
||||||
|
@ -137,13 +137,13 @@ class PoolBuilder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->pool->setPackages($this->packages, $this->priorities);
|
$pool->setPackages($this->packages, $this->priorities);
|
||||||
|
|
||||||
unset($this->aliasMap);
|
unset($this->aliasMap);
|
||||||
unset($this->loadedNames);
|
unset($this->loadedNames);
|
||||||
unset($this->nameConstraints);
|
unset($this->nameConstraints);
|
||||||
|
|
||||||
return $this->pool;
|
return $pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function loadPackage(PackageInterface $package, $repoIndex)
|
private function loadPackage(PackageInterface $package, $repoIndex)
|
||||||
|
@ -180,12 +180,12 @@ class PoolBuilder
|
||||||
if (!isset($this->loadedNames[$require])) {
|
if (!isset($this->loadedNames[$require])) {
|
||||||
$loadNames[$require] = null;
|
$loadNames[$require] = null;
|
||||||
}
|
}
|
||||||
if ($link->getConstraint()) {
|
if ($linkConstraint = $link->getConstraint()) {
|
||||||
if (!array_key_exists($require, $this->nameConstraints)) {
|
if (!array_key_exists($require, $this->nameConstraints)) {
|
||||||
$this->nameConstraints[$require] = new MultiConstraint(array($link->getConstraint()), false);
|
$this->nameConstraints[$require] = new MultiConstraint(array($linkConstraint), false);
|
||||||
} elseif ($this->nameConstraints[$require]) {
|
} elseif ($this->nameConstraints[$require]) {
|
||||||
// TODO addConstraint function?
|
// TODO addConstraint function?
|
||||||
$this->nameConstraints[$require] = new MultiConstraint(array_merge(array($link->getConstraint()), $this->nameConstraints[$require]->getConstraints()), false);
|
$this->nameConstraints[$require] = new MultiConstraint(array_merge(array($linkConstraint), $this->nameConstraints[$require]->getConstraints()), false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->nameConstraints[$require] = null;
|
$this->nameConstraints[$require] = null;
|
||||||
|
|
|
@ -79,11 +79,13 @@ class Problem
|
||||||
reset($reasons);
|
reset($reasons);
|
||||||
$reason = current($reasons);
|
$reason = current($reasons);
|
||||||
|
|
||||||
$rule = $reason['rule'];
|
|
||||||
$job = $reason['job'];
|
$job = $reason['job'];
|
||||||
|
|
||||||
if (isset($job['constraint'])) {
|
$packageName = $job['packageName'];
|
||||||
$packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
|
$constraint = $job['constraint'];
|
||||||
|
|
||||||
|
if (isset($constraint)) {
|
||||||
|
$packages = $this->pool->whatProvides($packageName, $constraint);
|
||||||
} else {
|
} else {
|
||||||
$packages = array();
|
$packages = array();
|
||||||
}
|
}
|
||||||
|
@ -91,9 +93,9 @@ class Problem
|
||||||
if ($job && $job['cmd'] === 'install' && empty($packages)) {
|
if ($job && $job['cmd'] === 'install' && empty($packages)) {
|
||||||
|
|
||||||
// handle php/hhvm
|
// handle php/hhvm
|
||||||
if ($job['packageName'] === 'php' || $job['packageName'] === 'php-64bit' || $job['packageName'] === 'hhvm') {
|
if ($packageName === 'php' || $packageName === 'php-64bit' || $packageName === 'hhvm') {
|
||||||
$version = phpversion();
|
$version = phpversion();
|
||||||
$available = $this->pool->whatProvides($job['packageName']);
|
$available = $this->pool->whatProvides($packageName);
|
||||||
|
|
||||||
if (count($available)) {
|
if (count($available)) {
|
||||||
$firstAvailable = reset($available);
|
$firstAvailable = reset($available);
|
||||||
|
@ -104,13 +106,13 @@ class Problem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$msg = "\n - This package requires ".$job['packageName'].$this->constraintToText($job['constraint']).' but ';
|
$msg = "\n - This package requires ".$packageName.$this->constraintToText($constraint).' but ';
|
||||||
|
|
||||||
if (defined('HHVM_VERSION') || count($available)) {
|
if (defined('HHVM_VERSION') || (count($available) && $packageName === 'hhvm')) {
|
||||||
return $msg . 'your HHVM version does not satisfy that requirement.';
|
return $msg . 'your HHVM version does not satisfy that requirement.';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($job['packageName'] === 'hhvm') {
|
if ($packageName === 'hhvm') {
|
||||||
return $msg . 'you are running this with PHP and not HHVM.';
|
return $msg . 'you are running this with PHP and not HHVM.';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,43 +120,43 @@ class Problem
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle php extensions
|
// handle php extensions
|
||||||
if (0 === stripos($job['packageName'], 'ext-')) {
|
if (0 === stripos($packageName, 'ext-')) {
|
||||||
if (false !== strpos($job['packageName'], ' ')) {
|
if (false !== strpos($packageName, ' ')) {
|
||||||
return "\n - The requested PHP extension ".$job['packageName'].' should be required as '.str_replace(' ', '-', $job['packageName']).'.';
|
return "\n - The requested PHP extension ".$packageName.' should be required as '.str_replace(' ', '-', $packageName).'.';
|
||||||
}
|
}
|
||||||
|
|
||||||
$ext = substr($job['packageName'], 4);
|
$ext = substr($packageName, 4);
|
||||||
$error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
|
$error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
|
||||||
|
|
||||||
return "\n - The requested PHP extension ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.';
|
return "\n - The requested PHP extension ".$packageName.$this->constraintToText($constraint).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.';
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle linked libs
|
// handle linked libs
|
||||||
if (0 === stripos($job['packageName'], 'lib-')) {
|
if (0 === stripos($packageName, 'lib-')) {
|
||||||
if (strtolower($job['packageName']) === 'lib-icu') {
|
if (strtolower($packageName) === 'lib-icu') {
|
||||||
$error = extension_loaded('intl') ? 'has the wrong version installed, try upgrading the intl extension.' : 'is missing from your system, make sure the intl extension is loaded.';
|
$error = extension_loaded('intl') ? 'has the wrong version installed, try upgrading the intl extension.' : 'is missing from your system, make sure the intl extension is loaded.';
|
||||||
|
|
||||||
return "\n - The requested linked library ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error;
|
return "\n - The requested linked library ".$packageName.$this->constraintToText($constraint).' '.$error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return "\n - The requested linked library ".$job['packageName'].$this->constraintToText($job['constraint']).' has the wrong version installed or is missing from your system, make sure to load the extension providing it.';
|
return "\n - The requested linked library ".$packageName.$this->constraintToText($constraint).' has the wrong version installed or is missing from your system, make sure to load the extension providing it.';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!preg_match('{^[A-Za-z0-9_./-]+$}', $job['packageName'])) {
|
if (!preg_match('{^[A-Za-z0-9_./-]+$}', $packageName)) {
|
||||||
$illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $job['packageName']);
|
$illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $packageName);
|
||||||
|
|
||||||
return "\n - The requested package ".$job['packageName'].' could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.';
|
return "\n - The requested package ".$packageName.' could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($providers = $this->pool->whatProvides($job['packageName'], $job['constraint'], true, true)) {
|
if ($providers = $this->pool->whatProvides($packageName, $constraint, true, true)) {
|
||||||
return "\n - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' is satisfiable by '.$this->getPackageList($providers).' but these conflict with your requirements or minimum-stability.';
|
return "\n - The requested package ".$packageName.$this->constraintToText($constraint).' is satisfiable by '.$this->getPackageList($providers).' but these conflict with your requirements or minimum-stability.';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($providers = $this->pool->whatProvides($job['packageName'], null, true, true)) {
|
if ($providers = $this->pool->whatProvides($packageName, null, true, true)) {
|
||||||
return "\n - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.';
|
return "\n - The requested package ".$packageName.$this->constraintToText($constraint).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.';
|
||||||
}
|
}
|
||||||
|
|
||||||
return "\n - The requested package ".$job['packageName'].' could not be found in any version, there may be a typo in the package name.';
|
return "\n - The requested package ".$packageName.' could not be found in any version, there may be a typo in the package name.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +182,7 @@ class Problem
|
||||||
* Store a reason descriptor but ignore duplicates
|
* Store a reason descriptor but ignore duplicates
|
||||||
*
|
*
|
||||||
* @param string $id A canonical identifier for the reason
|
* @param string $id A canonical identifier for the reason
|
||||||
* @param string $reason The reason descriptor
|
* @param string|array $reason The reason descriptor
|
||||||
*/
|
*/
|
||||||
protected function addReason($id, $reason)
|
protected function addReason($id, $reason)
|
||||||
{
|
{
|
||||||
|
@ -203,27 +205,29 @@ class Problem
|
||||||
*/
|
*/
|
||||||
protected function jobToText($job)
|
protected function jobToText($job)
|
||||||
{
|
{
|
||||||
|
$packageName = $job['packageName'];
|
||||||
|
$constraint = $job['constraint'];
|
||||||
switch ($job['cmd']) {
|
switch ($job['cmd']) {
|
||||||
case 'install':
|
case 'install':
|
||||||
$packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
|
$packages = $this->pool->whatProvides($packageName, $constraint);
|
||||||
if (!$packages) {
|
if (!$packages) {
|
||||||
return 'No package found to satisfy install request for '.$job['packageName'].$this->constraintToText($job['constraint']);
|
return 'No package found to satisfy install request for '.$packageName.$this->constraintToText($constraint);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'Installation request for '.$job['packageName'].$this->constraintToText($job['constraint']).' -> satisfiable by '.$this->getPackageList($packages).'.';
|
return 'Installation request for '.$packageName.$this->constraintToText($constraint).' -> satisfiable by '.$this->getPackageList($packages).'.';
|
||||||
case 'update':
|
case 'update':
|
||||||
return 'Update request for '.$job['packageName'].$this->constraintToText($job['constraint']).'.';
|
return 'Update request for '.$packageName.$this->constraintToText($constraint).'.';
|
||||||
case 'remove':
|
case 'remove':
|
||||||
return 'Removal request for '.$job['packageName'].$this->constraintToText($job['constraint']).'';
|
return 'Removal request for '.$packageName.$this->constraintToText($constraint).'';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($job['constraint'])) {
|
if (isset($constraint)) {
|
||||||
$packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
|
$packages = $this->pool->whatProvides($packageName, $constraint);
|
||||||
} else {
|
} else {
|
||||||
$packages = $this->pool->whatProvides($job['packageName'], null);
|
$packages = $this->pool->whatProvides($job['packageName'], null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'Job(cmd='.$job['cmd'].', target='.$job['packageName'].', packages=['.$this->getPackageList($packages).'])';
|
return 'Job(cmd='.$job['cmd'].', target='.$packageName.', packages=['.$this->getPackageList($packages).'])';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getPackageList($packages)
|
protected function getPackageList($packages)
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
namespace Composer\DependencyResolver;
|
namespace Composer\DependencyResolver;
|
||||||
|
|
||||||
use Composer\IO\IOInterface;
|
use Composer\IO\IOInterface;
|
||||||
|
use Composer\Package\PackageInterface;
|
||||||
use Composer\Repository\RepositoryInterface;
|
use Composer\Repository\RepositoryInterface;
|
||||||
use Composer\Repository\PlatformRepository;
|
use Composer\Repository\PlatformRepository;
|
||||||
use Composer\Repository\RepositorySet;
|
use Composer\Repository\RepositorySet;
|
||||||
|
@ -39,7 +40,7 @@ class Solver
|
||||||
protected $watchGraph;
|
protected $watchGraph;
|
||||||
/** @var Decisions */
|
/** @var Decisions */
|
||||||
protected $decisions;
|
protected $decisions;
|
||||||
/** @var Package[] */
|
/** @var PackageInterface[] */
|
||||||
protected $fixedMap;
|
protected $fixedMap;
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
|
@ -659,7 +660,7 @@ class Solver
|
||||||
/**
|
/**
|
||||||
* @todo this makes $disableRules always false; determine the rationale and possibly remove dead code?
|
* @todo this makes $disableRules always false; determine the rationale and possibly remove dead code?
|
||||||
*/
|
*/
|
||||||
$disableRules = array();
|
$disableRules = false;
|
||||||
|
|
||||||
$level = 1;
|
$level = 1;
|
||||||
$systemLevel = $level + 1;
|
$systemLevel = $level + 1;
|
||||||
|
|
|
@ -294,9 +294,7 @@ class DownloadManager
|
||||||
|
|
||||||
// if downloader type changed, or update failed and user asks for reinstall,
|
// if downloader type changed, or update failed and user asks for reinstall,
|
||||||
// we wipe the dir and do a new install instead of updating it
|
// we wipe the dir and do a new install instead of updating it
|
||||||
if ($initialDownloader) {
|
|
||||||
$initialDownloader->remove($initial, $targetDir);
|
$initialDownloader->remove($initial, $targetDir);
|
||||||
}
|
|
||||||
$this->install($target, $targetDir);
|
$this->install($target, $targetDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -362,7 +362,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
|
||||||
) {
|
) {
|
||||||
$command = sprintf('git checkout '.$force.'-B %s %s -- && git reset --hard %2$s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$reference));
|
$command = sprintf('git checkout '.$force.'-B %s %s -- && git reset --hard %2$s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$reference));
|
||||||
if (0 === $this->process->execute($command, $output, $path)) {
|
if (0 === $this->process->execute($command, $output, $path)) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,14 +380,14 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
|
||||||
) {
|
) {
|
||||||
$command = sprintf('git reset --hard %s --', ProcessExecutor::escape($reference));
|
$command = sprintf('git reset --hard %s --', ProcessExecutor::escape($reference));
|
||||||
if (0 === $this->process->execute($command, $output, $path)) {
|
if (0 === $this->process->execute($command, $output, $path)) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$command = sprintf($template, ProcessExecutor::escape($gitRef));
|
$command = sprintf($template, ProcessExecutor::escape($gitRef));
|
||||||
if (0 === $this->process->execute($command, $output, $path)) {
|
if (0 === $this->process->execute($command, $output, $path)) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reference was not found (prints "fatal: reference is not a tree: $ref")
|
// reference was not found (prints "fatal: reference is not a tree: $ref")
|
||||||
|
|
|
@ -28,6 +28,7 @@ use Composer\IO\IOInterface;
|
||||||
*/
|
*/
|
||||||
class GzipDownloader extends ArchiveDownloader
|
class GzipDownloader extends ArchiveDownloader
|
||||||
{
|
{
|
||||||
|
/** @var ProcessExecutor */
|
||||||
protected $process;
|
protected $process;
|
||||||
|
|
||||||
public function __construct(IOInterface $io, Config $config, HttpDownloader $downloader, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null)
|
public function __construct(IOInterface $io, Config $config, HttpDownloader $downloader, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null)
|
||||||
|
|
|
@ -91,6 +91,12 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter
|
||||||
$allowedStrategies = array(self::STRATEGY_MIRROR);
|
$allowedStrategies = array(self::STRATEGY_MIRROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check we can use junctions safely if we are on Windows
|
||||||
|
if (Platform::isWindows() && self::STRATEGY_SYMLINK === $currentStrategy && !$this->safeJunctions()) {
|
||||||
|
$currentStrategy = self::STRATEGY_MIRROR;
|
||||||
|
$allowedStrategies = array(self::STRATEGY_MIRROR);
|
||||||
|
}
|
||||||
|
|
||||||
$fileSystem = new Filesystem();
|
$fileSystem = new Filesystem();
|
||||||
$this->filesystem->removeDirectory($path);
|
$this->filesystem->removeDirectory($path);
|
||||||
|
|
||||||
|
@ -181,4 +187,25 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter
|
||||||
return $packageVersion['commit'];
|
return $packageVersion['commit'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if junctions can be created and safely used on Windows
|
||||||
|
*
|
||||||
|
* A PHP bug makes junction detection fragile, leading to possible data loss
|
||||||
|
* when removing a package. See https://bugs.php.net/bug.php?id=77552
|
||||||
|
*
|
||||||
|
* For safety we require a minimum version of Windows 7, so we can call the
|
||||||
|
* system rmdir which will preserve target content if given a junction.
|
||||||
|
*
|
||||||
|
* The PHP bug was fixed in 7.2.16 and 7.3.3 (requires at least Windows 7).
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function safeJunctions()
|
||||||
|
{
|
||||||
|
// We need to call mklink, and rmdir on Windows 7 (version 6.1)
|
||||||
|
return function_exists('proc_open') &&
|
||||||
|
(PHP_WINDOWS_VERSION_MAJOR > 6 ||
|
||||||
|
(PHP_WINDOWS_VERSION_MAJOR === 6 && PHP_WINDOWS_VERSION_MINOR >= 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ class PerforceDownloader extends VcsDownloader
|
||||||
*/
|
*/
|
||||||
public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
|
public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
|
||||||
{
|
{
|
||||||
$this->doDownload($target, $path, $url);
|
$this->doInstall($target, $path, $url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,7 +88,7 @@ class PerforceDownloader extends VcsDownloader
|
||||||
{
|
{
|
||||||
$this->io->writeError('Perforce driver does not check for local changes before overriding', true);
|
$this->io->writeError('Perforce driver does not check for local changes before overriding', true);
|
||||||
|
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -32,6 +32,7 @@ use RarArchive;
|
||||||
*/
|
*/
|
||||||
class RarDownloader extends ArchiveDownloader
|
class RarDownloader extends ArchiveDownloader
|
||||||
{
|
{
|
||||||
|
/** @var ProcessExecutor */
|
||||||
protected $process;
|
protected $process;
|
||||||
|
|
||||||
public function __construct(IOInterface $io, Config $config, HttpDownloader $downloader, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null)
|
public function __construct(IOInterface $io, Config $config, HttpDownloader $downloader, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null)
|
||||||
|
|
|
@ -28,6 +28,7 @@ use Composer\IO\IOInterface;
|
||||||
*/
|
*/
|
||||||
class XzDownloader extends ArchiveDownloader
|
class XzDownloader extends ArchiveDownloader
|
||||||
{
|
{
|
||||||
|
/** @var ProcessExecutor */
|
||||||
protected $process;
|
protected $process;
|
||||||
|
|
||||||
public function __construct(IOInterface $io, Config $config, HttpDownloader $downloader, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null)
|
public function __construct(IOInterface $io, Config $config, HttpDownloader $downloader, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null)
|
||||||
|
|
|
@ -33,7 +33,9 @@ class ZipDownloader extends ArchiveDownloader
|
||||||
private static $hasZipArchive;
|
private static $hasZipArchive;
|
||||||
private static $isWindows;
|
private static $isWindows;
|
||||||
|
|
||||||
|
/** @var ProcessExecutor */
|
||||||
protected $process;
|
protected $process;
|
||||||
|
/** @var ZipArchive|null */
|
||||||
private $zipArchiveObject;
|
private $zipArchiveObject;
|
||||||
|
|
||||||
public function __construct(IOInterface $io, Config $config, HttpDownloader $downloader, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null)
|
public function __construct(IOInterface $io, Config $config, HttpDownloader $downloader, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null)
|
||||||
|
|
|
@ -47,7 +47,7 @@ class EventDispatcher
|
||||||
protected $io;
|
protected $io;
|
||||||
protected $loader;
|
protected $loader;
|
||||||
protected $process;
|
protected $process;
|
||||||
protected $listeners;
|
protected $listeners = array();
|
||||||
private $eventStack;
|
private $eventStack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -173,6 +173,9 @@ class EventDispatcher
|
||||||
|
|
||||||
throw new \RuntimeException('Subscriber '.$className.'::'.$callable[1].' for event '.$event->getName().' is not callable, make sure the function is defined and public');
|
throw new \RuntimeException('Subscriber '.$className.'::'.$callable[1].' for event '.$event->getName().' is not callable, make sure the function is defined and public');
|
||||||
}
|
}
|
||||||
|
if (is_array($callable) && (is_string($callable[0]) || is_object($callable[0])) && is_string($callable[1])) {
|
||||||
|
$this->io->writeError(sprintf('> %s: %s', $event->getName(), (is_object($callable[0]) ? get_class($callable[0]) : $callable[0]).'->'.$callable[1] ), true, IOInterface::VERBOSE);
|
||||||
|
}
|
||||||
$event = $this->checkListenerExpectedEvent($callable, $event);
|
$event = $this->checkListenerExpectedEvent($callable, $event);
|
||||||
$return = false === call_user_func($callable, $event) ? 1 : 0;
|
$return = false === call_user_func($callable, $event) ? 1 : 0;
|
||||||
} elseif ($this->isComposerScript($callable)) {
|
} elseif ($this->isComposerScript($callable)) {
|
||||||
|
@ -197,6 +200,7 @@ class EventDispatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
/** @var InstallerEvent $event */
|
||||||
$return = $this->dispatch($scriptName, new Script\Event($scriptName, $event->getComposer(), $event->getIO(), $event->isDevMode(), $args, $flags));
|
$return = $this->dispatch($scriptName, new Script\Event($scriptName, $event->getComposer(), $event->getIO(), $event->isDevMode(), $args, $flags));
|
||||||
} catch (ScriptExecutionException $e) {
|
} catch (ScriptExecutionException $e) {
|
||||||
$this->io->writeError(sprintf('<error>Script %s was called via %s</error>', $callable, $event->getName()), true, IOInterface::QUIET);
|
$this->io->writeError(sprintf('<error>Script %s was called via %s</error>', $callable, $event->getName()), true, IOInterface::QUIET);
|
||||||
|
@ -365,6 +369,22 @@ class EventDispatcher
|
||||||
$this->listeners[$eventName][$priority][] = $listener;
|
$this->listeners[$eventName][$priority][] = $listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param callable|object $listener A callable or an object instance for which all listeners should be removed
|
||||||
|
*/
|
||||||
|
public function removeListener($listener)
|
||||||
|
{
|
||||||
|
foreach ($this->listeners as $eventName => $priorities) {
|
||||||
|
foreach ($priorities as $priority => $listeners) {
|
||||||
|
foreach ($listeners as $index => $candidate) {
|
||||||
|
if ($listener === $candidate || (is_array($candidate) && is_object($listener) && $candidate[0] === $listener)) {
|
||||||
|
unset($this->listeners[$eventName][$priority][$index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds object methods as listeners for the events in getSubscribedEvents
|
* Adds object methods as listeners for the events in getSubscribedEvents
|
||||||
*
|
*
|
||||||
|
@ -481,7 +501,7 @@ class EventDispatcher
|
||||||
*
|
*
|
||||||
* @param Event $event
|
* @param Event $event
|
||||||
* @throws \RuntimeException
|
* @throws \RuntimeException
|
||||||
* @return number
|
* @return int
|
||||||
*/
|
*/
|
||||||
protected function pushEvent(Event $event)
|
protected function pushEvent(Event $event)
|
||||||
{
|
{
|
||||||
|
|
|
@ -413,7 +413,7 @@ class Factory
|
||||||
/**
|
/**
|
||||||
* @param IOInterface $io IO instance
|
* @param IOInterface $io IO instance
|
||||||
* @param bool $disablePlugins Whether plugins should not be loaded
|
* @param bool $disablePlugins Whether plugins should not be loaded
|
||||||
* @return Composer
|
* @return Composer|null
|
||||||
*/
|
*/
|
||||||
public static function createGlobal(IOInterface $io, $disablePlugins = false)
|
public static function createGlobal(IOInterface $io, $disablePlugins = false)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,10 +14,9 @@ namespace Composer\IO;
|
||||||
|
|
||||||
use Composer\Config;
|
use Composer\Config;
|
||||||
use Composer\Util\ProcessExecutor;
|
use Composer\Util\ProcessExecutor;
|
||||||
use Psr\Log\LoggerInterface;
|
|
||||||
use Psr\Log\LogLevel;
|
use Psr\Log\LogLevel;
|
||||||
|
|
||||||
abstract class BaseIO implements IOInterface, LoggerInterface
|
abstract class BaseIO implements IOInterface
|
||||||
{
|
{
|
||||||
protected $authentications = array();
|
protected $authentications = array();
|
||||||
|
|
||||||
|
|
|
@ -13,13 +13,14 @@
|
||||||
namespace Composer\IO;
|
namespace Composer\IO;
|
||||||
|
|
||||||
use Composer\Config;
|
use Composer\Config;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Input/Output helper interface.
|
* The Input/Output helper interface.
|
||||||
*
|
*
|
||||||
* @author François Pluchino <francois.pluchino@opendisplay.com>
|
* @author François Pluchino <francois.pluchino@opendisplay.com>
|
||||||
*/
|
*/
|
||||||
interface IOInterface
|
interface IOInterface extends LoggerInterface
|
||||||
{
|
{
|
||||||
const QUIET = 1;
|
const QUIET = 1;
|
||||||
const NORMAL = 2;
|
const NORMAL = 2;
|
||||||
|
@ -107,7 +108,7 @@ interface IOInterface
|
||||||
* @param string $default The default answer if none is given by the user
|
* @param string $default The default answer if none is given by the user
|
||||||
*
|
*
|
||||||
* @throws \RuntimeException If there is no data to read in the input stream
|
* @throws \RuntimeException If there is no data to read in the input stream
|
||||||
* @return string The user answer
|
* @return string|null The user answer
|
||||||
*/
|
*/
|
||||||
public function ask($question, $default = null);
|
public function ask($question, $default = null);
|
||||||
|
|
||||||
|
@ -145,7 +146,7 @@ interface IOInterface
|
||||||
*
|
*
|
||||||
* @param string $question The question to ask
|
* @param string $question The question to ask
|
||||||
*
|
*
|
||||||
* @return string The answer
|
* @return string|null The answer
|
||||||
*/
|
*/
|
||||||
public function askAndHideAnswer($question);
|
public function askAndHideAnswer($question);
|
||||||
|
|
||||||
|
@ -160,7 +161,7 @@ interface IOInterface
|
||||||
* @param bool $multiselect Select more than one value separated by comma
|
* @param bool $multiselect Select more than one value separated by comma
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
* @return int|string|array The selected value or values (the key of the choices array)
|
* @return int|string|array|bool The selected value or values (the key of the choices array)
|
||||||
*/
|
*/
|
||||||
public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false);
|
public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false);
|
||||||
|
|
||||||
|
|
|
@ -399,6 +399,8 @@ class Installer
|
||||||
$solver = new Solver($policy, $pool, $this->io);
|
$solver = new Solver($policy, $pool, $this->io);
|
||||||
try {
|
try {
|
||||||
$lockTransaction = $solver->solve($request, $this->ignorePlatformReqs);
|
$lockTransaction = $solver->solve($request, $this->ignorePlatformReqs);
|
||||||
|
$ruleSetSize = $solver->getRuleSetSize();
|
||||||
|
$solver = null;
|
||||||
} catch (SolverProblemsException $e) {
|
} catch (SolverProblemsException $e) {
|
||||||
$this->io->writeError('<error>Your requirements could not be resolved to an installable set of packages.</error>', true, IOInterface::QUIET);
|
$this->io->writeError('<error>Your requirements could not be resolved to an installable set of packages.</error>', true, IOInterface::QUIET);
|
||||||
$this->io->writeError($e->getMessage());
|
$this->io->writeError($e->getMessage());
|
||||||
|
@ -413,7 +415,7 @@ class Installer
|
||||||
//$this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $this->devMode, $policy, $repositorySet, $lockedRepository, $request, $lockTransaction);
|
//$this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $this->devMode, $policy, $repositorySet, $lockedRepository, $request, $lockTransaction);
|
||||||
|
|
||||||
$this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies", true, IOInterface::VERBOSE);
|
$this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies", true, IOInterface::VERBOSE);
|
||||||
$this->io->writeError("Analyzed ".$solver->getRuleSetSize()." rules to resolve dependencies", true, IOInterface::VERBOSE);
|
$this->io->writeError("Analyzed ".$ruleSetSize." rules to resolve dependencies", true, IOInterface::VERBOSE);
|
||||||
|
|
||||||
if (!$lockTransaction->getOperations()) {
|
if (!$lockTransaction->getOperations()) {
|
||||||
$this->io->writeError('Nothing to modify in lock file');
|
$this->io->writeError('Nothing to modify in lock file');
|
||||||
|
@ -559,6 +561,7 @@ class Installer
|
||||||
$solver = new Solver($policy, $pool, $this->io);
|
$solver = new Solver($policy, $pool, $this->io);
|
||||||
try {
|
try {
|
||||||
$lockTransaction = $solver->solve($request, $this->ignorePlatformReqs);
|
$lockTransaction = $solver->solve($request, $this->ignorePlatformReqs);
|
||||||
|
$solver = null;
|
||||||
|
|
||||||
// installing the locked packages on this platfom resulted in lock modifying operations, there wasn't a conflict, but the lock file as-is seems to not work on this system
|
// installing the locked packages on this platfom resulted in lock modifying operations, there wasn't a conflict, but the lock file as-is seems to not work on this system
|
||||||
if (0 !== count($lockTransaction->getOperations())) {
|
if (0 !== count($lockTransaction->getOperations())) {
|
||||||
|
|
|
@ -48,7 +48,7 @@ interface InstallerInterface
|
||||||
*
|
*
|
||||||
* @param PackageInterface $package package instance
|
* @param PackageInterface $package package instance
|
||||||
* @param PackageInterface $prevPackage previous package instance in case of an update
|
* @param PackageInterface $prevPackage previous package instance in case of an update
|
||||||
* @return PromiseInterface
|
* @return PromiseInterface|null
|
||||||
*/
|
*/
|
||||||
public function download(PackageInterface $package, PackageInterface $prevPackage = null);
|
public function download(PackageInterface $package, PackageInterface $prevPackage = null);
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface
|
||||||
*
|
*
|
||||||
* @param IOInterface $io
|
* @param IOInterface $io
|
||||||
* @param Composer $composer
|
* @param Composer $composer
|
||||||
* @param string $type
|
* @param string|null $type
|
||||||
* @param Filesystem $filesystem
|
* @param Filesystem $filesystem
|
||||||
* @param BinaryInstaller $binaryInstaller
|
* @param BinaryInstaller $binaryInstaller
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -22,7 +22,7 @@ class JsonManipulator
|
||||||
private static $DEFINES = '(?(DEFINE)
|
private static $DEFINES = '(?(DEFINE)
|
||||||
(?<number> -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
|
(?<number> -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
|
||||||
(?<boolean> true | false | null )
|
(?<boolean> true | false | null )
|
||||||
(?<string> " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " )
|
(?<string> " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9A-Fa-f]{4} )* " )
|
||||||
(?<array> \[ (?: (?&json) \s* (?: , (?&json) \s* )* )? \s* \] )
|
(?<array> \[ (?: (?&json) \s* (?: , (?&json) \s* )* )? \s* \] )
|
||||||
(?<pair> \s* (?&string) \s* : (?&json) \s* )
|
(?<pair> \s* (?&string) \s* : (?&json) \s* )
|
||||||
(?<object> \{ (?: (?&pair) (?: , (?&pair) )* )? \s* \} )
|
(?<object> \{ (?: (?&pair) (?: , (?&pair) )* )? \s* \} )
|
||||||
|
|
|
@ -401,4 +401,14 @@ class AliasPackage extends BasePackage implements CompletePackageInterface
|
||||||
{
|
{
|
||||||
return parent::__toString().' (alias of '.$this->aliasOf->getVersion().')';
|
return parent::__toString().' (alias of '.$this->aliasOf->getVersion().')';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setDistUrl($url)
|
||||||
|
{
|
||||||
|
return $this->aliasOf->setDistUrl($url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDistType($type)
|
||||||
|
{
|
||||||
|
return $this->aliasOf->setDistType($type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,7 +239,7 @@ abstract class BasePackage implements PackageInterface
|
||||||
* Build a regexp from a package name, expanding * globs as required
|
* Build a regexp from a package name, expanding * globs as required
|
||||||
*
|
*
|
||||||
* @param string $whiteListedPattern
|
* @param string $whiteListedPattern
|
||||||
* @param bool $wrap Wrap the cleaned string by the given string
|
* @param string $wrap Wrap the cleaned string by the given string
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function packageNameToRegexp($whiteListedPattern, $wrap = '{^%s$}i')
|
public static function packageNameToRegexp($whiteListedPattern, $wrap = '{^%s$}i')
|
||||||
|
|
|
@ -62,32 +62,10 @@ class ArrayLoader implements LoaderInterface
|
||||||
|
|
||||||
public function loadPackages(array $versions, $class)
|
public function loadPackages(array $versions, $class)
|
||||||
{
|
{
|
||||||
static $uniqKeys = array('version', 'version_normalized', 'source', 'dist', 'time');
|
|
||||||
|
|
||||||
$packages = array();
|
$packages = array();
|
||||||
$linkCache = array();
|
$linkCache = array();
|
||||||
|
|
||||||
foreach ($versions as $version) {
|
foreach ($versions as $version) {
|
||||||
if (isset($version['versions'])) {
|
|
||||||
$baseVersion = $version;
|
|
||||||
foreach ($uniqKeys as $key) {
|
|
||||||
unset($baseVersion[$key.'s']);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($version['versions'] as $index => $dummy) {
|
|
||||||
$unpackedVersion = $baseVersion;
|
|
||||||
foreach ($uniqKeys as $key) {
|
|
||||||
$unpackedVersion[$key] = $version[$key.'s'][$index];
|
|
||||||
}
|
|
||||||
|
|
||||||
$package = $this->createObject($unpackedVersion, $class);
|
|
||||||
|
|
||||||
$this->configureCachedLinks($linkCache, $package, $unpackedVersion);
|
|
||||||
$package = $this->configureObject($package, $unpackedVersion);
|
|
||||||
|
|
||||||
$packages[] = $package;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$package = $this->createObject($version, $class);
|
$package = $this->createObject($version, $class);
|
||||||
|
|
||||||
$this->configureCachedLinks($linkCache, $package, $version);
|
$this->configureCachedLinks($linkCache, $package, $version);
|
||||||
|
@ -95,7 +73,6 @@ class ArrayLoader implements LoaderInterface
|
||||||
|
|
||||||
$packages[] = $package;
|
$packages[] = $package;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return $packages;
|
return $packages;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,10 @@ class ValidatingArrayLoader implements LoaderInterface
|
||||||
$this->warnings = array();
|
$this->warnings = array();
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
|
|
||||||
|
if ($err = self::hasPackageNamingError($config['name'])) {
|
||||||
|
$this->warnings[] = 'Deprecation warning: Your package name '.$err.' Make sure you fix this as Composer 2.0 will error.';
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->strictName) {
|
if ($this->strictName) {
|
||||||
$this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true);
|
$this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true);
|
||||||
} else {
|
} else {
|
||||||
|
@ -195,7 +199,9 @@ class ValidatingArrayLoader implements LoaderInterface
|
||||||
foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
|
foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
|
||||||
if ($this->validateArray($linkType) && isset($this->config[$linkType])) {
|
if ($this->validateArray($linkType) && isset($this->config[$linkType])) {
|
||||||
foreach ($this->config[$linkType] as $package => $constraint) {
|
foreach ($this->config[$linkType] as $package => $constraint) {
|
||||||
if (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) {
|
if ($err = self::hasPackageNamingError($package, true)) {
|
||||||
|
$this->warnings[] = 'Deprecation warning: '.$linkType.'.'.$err.' Make sure you fix this as Composer 2.0 will error.';
|
||||||
|
} elseif (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) {
|
||||||
$this->warnings[] = $linkType.'.'.$package.' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]';
|
$this->warnings[] = $linkType.'.'.$package.' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]';
|
||||||
}
|
}
|
||||||
if (!is_string($constraint)) {
|
if (!is_string($constraint)) {
|
||||||
|
|
|
@ -31,13 +31,21 @@ use Seld\JsonLint\ParsingException;
|
||||||
*/
|
*/
|
||||||
class Locker
|
class Locker
|
||||||
{
|
{
|
||||||
|
/** @var JsonFile */
|
||||||
private $lockFile;
|
private $lockFile;
|
||||||
|
/** @var RepositoryManager */
|
||||||
private $repositoryManager;
|
private $repositoryManager;
|
||||||
|
/** @var InstallationManager */
|
||||||
private $installationManager;
|
private $installationManager;
|
||||||
|
/** @var string */
|
||||||
private $hash;
|
private $hash;
|
||||||
|
/** @var string */
|
||||||
private $contentHash;
|
private $contentHash;
|
||||||
|
/** @var ArrayLoader */
|
||||||
private $loader;
|
private $loader;
|
||||||
|
/** @var ArrayDumper */
|
||||||
private $dumper;
|
private $dumper;
|
||||||
|
/** @var ProcessExecutor */
|
||||||
private $process;
|
private $process;
|
||||||
private $lockDataCache;
|
private $lockDataCache;
|
||||||
private $virtualFileWritten;
|
private $virtualFileWritten;
|
||||||
|
|
|
@ -76,7 +76,7 @@ interface PackageInterface
|
||||||
/**
|
/**
|
||||||
* Returns the package targetDir property
|
* Returns the package targetDir property
|
||||||
*
|
*
|
||||||
* @return string The package targetDir
|
* @return string|null The package targetDir
|
||||||
*/
|
*/
|
||||||
public function getTargetDir();
|
public function getTargetDir();
|
||||||
|
|
||||||
|
@ -358,4 +358,32 @@ interface PackageInterface
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getTransportOptions();
|
public function getTransportOptions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $reference
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setSourceReference($reference);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $url
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setDistUrl($url);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $type
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setDistType($type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $reference
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setDistReference($reference);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ use Composer\Repository\Vcs\HgDriver;
|
||||||
use Composer\IO\NullIO;
|
use Composer\IO\NullIO;
|
||||||
use Composer\Semver\VersionParser as SemverVersionParser;
|
use Composer\Semver\VersionParser as SemverVersionParser;
|
||||||
use Composer\Util\Git as GitUtil;
|
use Composer\Util\Git as GitUtil;
|
||||||
|
use Composer\Util\HttpDownloader;
|
||||||
use Composer\Util\ProcessExecutor;
|
use Composer\Util\ProcessExecutor;
|
||||||
use Composer\Util\Svn as SvnUtil;
|
use Composer\Util\Svn as SvnUtil;
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ class VersionSelector
|
||||||
* @param string $targetPackageVersion
|
* @param string $targetPackageVersion
|
||||||
* @param string $targetPhpVersion
|
* @param string $targetPhpVersion
|
||||||
* @param string $preferredStability
|
* @param string $preferredStability
|
||||||
* @return PackageInterface|bool
|
* @return PackageInterface|false
|
||||||
*/
|
*/
|
||||||
public function findBestCandidate($packageName, $targetPackageVersion = null, $targetPhpVersion = null, $preferredStability = 'stable')
|
public function findBestCandidate($packageName, $targetPackageVersion = null, $targetPhpVersion = null, $preferredStability = 'stable')
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,15 +15,16 @@ namespace Composer\Plugin;
|
||||||
use Composer\Composer;
|
use Composer\Composer;
|
||||||
use Composer\EventDispatcher\EventSubscriberInterface;
|
use Composer\EventDispatcher\EventSubscriberInterface;
|
||||||
use Composer\IO\IOInterface;
|
use Composer\IO\IOInterface;
|
||||||
|
use Composer\Package\CompletePackage;
|
||||||
use Composer\Package\Package;
|
use Composer\Package\Package;
|
||||||
use Composer\Package\Version\VersionParser;
|
use Composer\Package\Version\VersionParser;
|
||||||
use Composer\Repository\RepositoryInterface;
|
use Composer\Repository\RepositoryInterface;
|
||||||
use Composer\Package\AliasPackage;
|
|
||||||
use Composer\Package\PackageInterface;
|
use Composer\Package\PackageInterface;
|
||||||
use Composer\Package\Link;
|
use Composer\Package\Link;
|
||||||
use Composer\Repository\RepositorySet;
|
use Composer\Repository\RepositorySet;
|
||||||
use Composer\Semver\Constraint\Constraint;
|
use Composer\Semver\Constraint\Constraint;
|
||||||
use Composer\Plugin\Capability\Capability;
|
use Composer\Plugin\Capability\Capability;
|
||||||
|
use Composer\Util\PackageSorter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin manager
|
* Plugin manager
|
||||||
|
@ -253,8 +254,10 @@ class PluginManager
|
||||||
*/
|
*/
|
||||||
private function loadRepository(RepositoryInterface $repo)
|
private function loadRepository(RepositoryInterface $repo)
|
||||||
{
|
{
|
||||||
foreach ($repo->getPackages() as $package) { /** @var PackageInterface $package */
|
$packages = $repo->getPackages();
|
||||||
if ($package instanceof AliasPackage) {
|
$sortedPackages = array_reverse(PackageSorter::sortPackages($packages));
|
||||||
|
foreach ($sortedPackages as $package) {
|
||||||
|
if (!($package instanceof CompletePackage)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ('composer-plugin' === $package->getType()) {
|
if ('composer-plugin' === $package->getType()) {
|
||||||
|
|
|
@ -32,9 +32,11 @@ abstract class BaseRepository implements RepositoryInterface
|
||||||
|
|
||||||
$result = array();
|
$result = array();
|
||||||
foreach ($packages as $package) {
|
foreach ($packages as $package) {
|
||||||
if (array_key_exists($package->getName(), $packageMap) &&
|
if (
|
||||||
(!$packageMap[$package->getName()] || $packageMap[$package->getName()]->matches(new Constraint('==', $package->getVersion()))) &&
|
array_key_exists($package->getName(), $packageMap)
|
||||||
call_user_func($isPackageAcceptableCallable, $package->getNames(), $package->getStability())) {
|
&& (!$packageMap[$package->getName()] || $packageMap[$package->getName()]->matches(new Constraint('==', $package->getVersion())))
|
||||||
|
&& call_user_func($isPackageAcceptableCallable, $package->getNames(), $package->getStability())
|
||||||
|
) {
|
||||||
$result[spl_object_hash($package)] = $package;
|
$result[spl_object_hash($package)] = $package;
|
||||||
if ($package instanceof AliasPackage && !isset($result[spl_object_hash($package->getAliasOf())])) {
|
if ($package instanceof AliasPackage && !isset($result[spl_object_hash($package->getAliasOf())])) {
|
||||||
$result[spl_object_hash($package->getAliasOf())] = $package->getAliasOf();
|
$result[spl_object_hash($package->getAliasOf())] = $package->getAliasOf();
|
||||||
|
|
|
@ -19,6 +19,7 @@ use Composer\Package\Version\VersionParser;
|
||||||
use Composer\Json\JsonFile;
|
use Composer\Json\JsonFile;
|
||||||
use Composer\Cache;
|
use Composer\Cache;
|
||||||
use Composer\Config;
|
use Composer\Config;
|
||||||
|
use Composer\Composer;
|
||||||
use Composer\Factory;
|
use Composer\Factory;
|
||||||
use Composer\IO\IOInterface;
|
use Composer\IO\IOInterface;
|
||||||
use Composer\Util\HttpDownloader;
|
use Composer\Util\HttpDownloader;
|
||||||
|
@ -103,7 +104,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
|
|
||||||
$this->baseUrl = rtrim(preg_replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/');
|
$this->baseUrl = rtrim(preg_replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/');
|
||||||
$this->io = $io;
|
$this->io = $io;
|
||||||
$this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$');
|
$this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$~');
|
||||||
$this->versionParser = new VersionParser();
|
$this->versionParser = new VersionParser();
|
||||||
$this->loader = new ArrayLoader($this->versionParser);
|
$this->loader = new ArrayLoader($this->versionParser);
|
||||||
$this->httpDownloader = $httpDownloader;
|
$this->httpDownloader = $httpDownloader;
|
||||||
|
@ -139,9 +140,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$packages = $this->loadAsyncPackages(array($name => $constraint), function ($name, $stability) {
|
$packages = $this->loadAsyncPackages(array($name => $constraint));
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
return reset($packages);
|
return reset($packages);
|
||||||
}
|
}
|
||||||
|
@ -181,9 +180,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->loadAsyncPackages(array($name => $constraint ?: new EmptyConstraint()), function ($name, $stability) {
|
return $this->loadAsyncPackages(array($name => $constraint));
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($hasProviders) {
|
if ($hasProviders) {
|
||||||
|
@ -241,7 +238,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
$packageMap[$name] = new EmptyConstraint();
|
$packageMap[$name] = new EmptyConstraint();
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_values($this->loadAsyncPackages($packageMap, function ($name, $stability) { return true; }));
|
return array_values($this->loadAsyncPackages($packageMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \LogicException('Composer repositories that have lazy providers and no available-packages list can not load the complete list of packages, use getProviderNames instead.');
|
throw new \LogicException('Composer repositories that have lazy providers and no available-packages list can not load the complete list of packages, use getProviderNames instead.');
|
||||||
|
@ -313,9 +310,11 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add aliases of matched packages even if they did not match the constraint
|
||||||
foreach ($candidates as $candidate) {
|
foreach ($candidates as $candidate) {
|
||||||
if ($candidate instanceof AliasPackage) {
|
if ($candidate instanceof AliasPackage) {
|
||||||
if (isset($result[spl_object_hash($candidate->getAliasOf())])) {
|
if (isset($matches[spl_object_hash($candidate->getAliasOf())])) {
|
||||||
$matches[spl_object_hash($candidate)] = $candidate;
|
$matches[spl_object_hash($candidate)] = $candidate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -511,14 +510,16 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($versionsToLoad[$version['uid']])) {
|
if (!isset($versionsToLoad[$version['uid']])) {
|
||||||
if ($isPackageAcceptableCallable && !call_user_func($isPackageAcceptableCallable, $normalizedName, VersionParser::parseStability($version['version']))) {
|
if (!isset($version['version_normalized'])) {
|
||||||
continue;
|
$version['version_normalized'] = $this->versionParser->normalize($version['version']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->isVersionAcceptable($isPackageAcceptableCallable, null, $normalizedName, $version)) {
|
||||||
$versionsToLoad[$version['uid']] = $version;
|
$versionsToLoad[$version['uid']] = $version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// load acceptable packages in the providers
|
// load acceptable packages in the providers
|
||||||
$loadedPackages = $this->createPackages($versionsToLoad, 'Composer\Package\CompletePackage');
|
$loadedPackages = $this->createPackages($versionsToLoad, 'Composer\Package\CompletePackage');
|
||||||
|
@ -567,7 +568,10 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
$this->configurePackageTransportOptions($package);
|
$this->configurePackageTransportOptions($package);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function loadAsyncPackages(array $packageNames, $isPackageAcceptableCallable)
|
/**
|
||||||
|
* @param array $packageNames array of package name => ConstraintInterface|null - if a constraint is provided, only packages matching it will be loaded
|
||||||
|
*/
|
||||||
|
private function loadAsyncPackages(array $packageNames, $isPackageAcceptableCallable = null)
|
||||||
{
|
{
|
||||||
$this->loadRootServerFile();
|
$this->loadRootServerFile();
|
||||||
|
|
||||||
|
@ -579,16 +583,24 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
throw new \LogicException('loadAsyncPackages only supports v2 protocol composer repos with a metadata-url');
|
throw new \LogicException('loadAsyncPackages only supports v2 protocol composer repos with a metadata-url');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load ~dev variants as well if present
|
||||||
|
// TODO ideally there should be a flag set from the repositoryset/poolbuilder to know which packages should have the dev packages loaded
|
||||||
|
// so we can optimize away some requests entirely
|
||||||
|
foreach ($packageNames as $name => $constraint) {
|
||||||
|
$packageNames[$name.'~dev'] = $constraint;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($packageNames as $name => $constraint) {
|
foreach ($packageNames as $name => $constraint) {
|
||||||
$name = strtolower($name);
|
$name = strtolower($name);
|
||||||
|
|
||||||
|
$realName = preg_replace('{~dev$}', '', $name);
|
||||||
// skip platform packages, root package and composer-plugin-api
|
// skip platform packages, root package and composer-plugin-api
|
||||||
if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name || 'composer-plugin-api' === $name) {
|
if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $realName) || '__root__' === $realName || 'composer-plugin-api' === $realName) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$url = str_replace('%package%', $name, $this->lazyProvidersUrl);
|
$url = str_replace('%package%', $name, $this->lazyProvidersUrl);
|
||||||
$cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
|
$cacheKey = 'provider-'.strtr($name, '/', '~').'.json';
|
||||||
|
|
||||||
$lastModified = null;
|
$lastModified = null;
|
||||||
if ($contents = $this->cache->read($cacheKey)) {
|
if ($contents = $this->cache->read($cacheKey)) {
|
||||||
|
@ -597,16 +609,16 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
}
|
}
|
||||||
|
|
||||||
$promises[] = $this->asyncFetchFile($url, $cacheKey, $lastModified)
|
$promises[] = $this->asyncFetchFile($url, $cacheKey, $lastModified)
|
||||||
->then(function ($response) use (&$packages, $contents, $name, $constraint, $repo, $isPackageAcceptableCallable) {
|
->then(function ($response) use (&$packages, $contents, $realName, $constraint, $repo, $isPackageAcceptableCallable) {
|
||||||
if (true === $response) {
|
if (true === $response) {
|
||||||
$response = $contents;
|
$response = $contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($response['packages'][$name])) {
|
if (!isset($response['packages'][$realName])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$versions = $response['packages'][$name];
|
$versions = $response['packages'][$realName];
|
||||||
|
|
||||||
if (isset($response['minified']) && $response['minified'] === 'composer/2.0') {
|
if (isset($response['minified']) && $response['minified'] === 'composer/2.0') {
|
||||||
// TODO extract in other method
|
// TODO extract in other method
|
||||||
|
@ -635,37 +647,24 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
unset($expanded, $expandedVersion, $versionData);
|
unset($expanded, $expandedVersion, $versionData);
|
||||||
}
|
}
|
||||||
|
|
||||||
static $uniqKeys = array('version', 'version_normalized', 'source', 'dist', 'time');
|
|
||||||
$versionsToLoad = array();
|
$versionsToLoad = array();
|
||||||
foreach ($versions as $version) {
|
foreach ($versions as $version) {
|
||||||
if (isset($version['version_normalizeds'])) {
|
|
||||||
foreach ($version['version_normalizeds'] as $index => $normalizedVersion) {
|
|
||||||
if (!$repo->isVersionAcceptable($isPackageAcceptableCallable, $constraint, $name, $normalizedVersion)) {
|
|
||||||
foreach ($uniqKeys as $key) {
|
|
||||||
unset($version[$key.'s'][$index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (count($version['version_normalizeds'])) {
|
|
||||||
$versionsToLoad[] = $version;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!isset($version['version_normalized'])) {
|
if (!isset($version['version_normalized'])) {
|
||||||
$version['version_normalized'] = $repo->versionParser->normalize($version['version']);
|
$version['version_normalized'] = $repo->versionParser->normalize($version['version']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($repo->isVersionAcceptable($isPackageAcceptableCallable, $constraint, $name, $version['version_normalized'])) {
|
if ($repo->isVersionAcceptable($isPackageAcceptableCallable, $constraint, $realName, $version)) {
|
||||||
$versionsToLoad[] = $version;
|
$versionsToLoad[] = $version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$loadedPackages = $repo->createPackages($versionsToLoad, 'Composer\Package\CompletePackage');
|
$loadedPackages = $repo->createPackages($versionsToLoad, 'Composer\Package\CompletePackage');
|
||||||
foreach ($loadedPackages as $package) {
|
foreach ($loadedPackages as $package) {
|
||||||
$package->setRepository($repo);
|
$package->setRepository($repo);
|
||||||
|
|
||||||
$packages[spl_object_hash($package)] = $package;
|
$packages[spl_object_hash($package)] = $package;
|
||||||
|
|
||||||
if ($package instanceof AliasPackage && !isset($packages[spl_object_hash($package->getAliasOf())])) {
|
if ($package instanceof AliasPackage && !isset($packages[spl_object_hash($package->getAliasOf())])) {
|
||||||
|
$package->getAliasOf()->setRepository($repo);
|
||||||
$packages[spl_object_hash($package->getAliasOf())] = $package->getAliasOf();
|
$packages[spl_object_hash($package->getAliasOf())] = $package->getAliasOf();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -681,21 +680,32 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
/**
|
/**
|
||||||
* TODO v3 should make this private once we can drop PHP 5.3 support
|
* TODO v3 should make this private once we can drop PHP 5.3 support
|
||||||
*
|
*
|
||||||
|
* @param string $name package name (must be lowercased already)
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
public function isVersionAcceptable($isPackageAcceptableCallable, $constraint, $name, $versionNormalized)
|
public function isVersionAcceptable($isPackageAcceptableCallable, $constraint, $name, $versionData)
|
||||||
{
|
{
|
||||||
if (!call_user_func($isPackageAcceptableCallable, strtolower($name), VersionParser::parseStability($versionNormalized))) {
|
$versions = array($versionData['version_normalized']);
|
||||||
return false;
|
|
||||||
|
if ($alias = $this->loader->getBranchAlias($versionData)) {
|
||||||
|
$versions[] = $alias;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($constraint && !$constraint->matches(new Constraint('==', $versionNormalized))) {
|
foreach ($versions as $version) {
|
||||||
return false;
|
if ($isPackageAcceptableCallable && !call_user_func($isPackageAcceptableCallable, $name, VersionParser::parseStability($version))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($constraint && !$constraint->matches(new Constraint('==', $version))) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
protected function loadRootServerFile()
|
protected function loadRootServerFile()
|
||||||
{
|
{
|
||||||
if (null !== $this->rootData) {
|
if (null !== $this->rootData) {
|
||||||
|
@ -793,7 +803,11 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
private function canonicalizeUrl($url)
|
private function canonicalizeUrl($url)
|
||||||
{
|
{
|
||||||
if ('/' === $url[0]) {
|
if ('/' === $url[0]) {
|
||||||
return preg_replace('{(https?://[^/]+).*}i', '$1' . $url, $this->url);
|
if (preg_match('{^[^:]++://[^/]*+}', $this->url, $matches)) {
|
||||||
|
return $matches[0] . $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->url;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $url;
|
return $url;
|
||||||
|
@ -952,12 +966,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $response->decodeJson();
|
$data = $response->decodeJson();
|
||||||
if (!empty($data['warning'])) {
|
HttpDownloader::outputWarnings($this->io, $this->url, $data);
|
||||||
$this->io->writeError('<warning>Warning from '.$this->url.': '.$data['warning'].'</warning>');
|
|
||||||
}
|
|
||||||
if (!empty($data['info'])) {
|
|
||||||
$this->io->writeError('<info>Info from '.$this->url.': '.$data['info'].'</info>');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($cacheKey) {
|
if ($cacheKey) {
|
||||||
if ($storeLastModifiedTime) {
|
if ($storeLastModifiedTime) {
|
||||||
|
@ -1031,12 +1040,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $response->decodeJson();
|
$data = $response->decodeJson();
|
||||||
if (!empty($data['warning'])) {
|
HttpDownloader::outputWarnings($this->io, $this->url, $data);
|
||||||
$this->io->writeError('<warning>Warning from '.$this->url.': '.$data['warning'].'</warning>');
|
|
||||||
}
|
|
||||||
if (!empty($data['info'])) {
|
|
||||||
$this->io->writeError('<info>Info from '.$this->url.': '.$data['info'].'</info>');
|
|
||||||
}
|
|
||||||
|
|
||||||
$lastModifiedDate = $response->getHeader('last-modified');
|
$lastModifiedDate = $response->getHeader('last-modified');
|
||||||
$response->collect();
|
$response->collect();
|
||||||
|
@ -1101,12 +1105,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $response->decodeJson();
|
$data = $response->decodeJson();
|
||||||
if (!empty($data['warning'])) {
|
HttpDownloader::outputWarnings($io, $url, $data);
|
||||||
$io->writeError('<warning>Warning from '.$url.': '.$data['warning'].'</warning>');
|
|
||||||
}
|
|
||||||
if (!empty($data['info'])) {
|
|
||||||
$io->writeError('<info>Info from '.$url.': '.$data['info'].'</info>');
|
|
||||||
}
|
|
||||||
|
|
||||||
$lastModifiedDate = $response->getHeader('last-modified');
|
$lastModifiedDate = $response->getHeader('last-modified');
|
||||||
$response->collect();
|
$response->collect();
|
||||||
|
|
|
@ -51,6 +51,11 @@ class FilesystemRepository extends WritableArrayRepository
|
||||||
try {
|
try {
|
||||||
$packages = $this->file->read();
|
$packages = $this->file->read();
|
||||||
|
|
||||||
|
// forward compatibility for composer v2 installed.json
|
||||||
|
if (isset($packages['packages'])) {
|
||||||
|
$packages = $packages['packages'];
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_array($packages)) {
|
if (!is_array($packages)) {
|
||||||
throw new \UnexpectedValueException('Could not parse package list from the repository');
|
throw new \UnexpectedValueException('Could not parse package list from the repository');
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ abstract class BaseChannelReader
|
||||||
* @param string $origin server
|
* @param string $origin server
|
||||||
* @param string $path relative path to content
|
* @param string $path relative path to content
|
||||||
* @throws \UnexpectedValueException
|
* @throws \UnexpectedValueException
|
||||||
* @return \SimpleXMLElement
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function requestContent($origin, $path)
|
protected function requestContent($origin, $path)
|
||||||
{
|
{
|
||||||
|
|
|
@ -150,7 +150,7 @@ class ChannelRest10Reader extends BaseChannelReader
|
||||||
* @param string $baseUrl
|
* @param string $baseUrl
|
||||||
* @param string $packageName
|
* @param string $packageName
|
||||||
* @param string $version
|
* @param string $version
|
||||||
* @return DependencyInfo[]
|
* @return DependencyInfo
|
||||||
*/
|
*/
|
||||||
private function readPackageReleaseDependencies($baseUrl, $packageName, $version)
|
private function readPackageReleaseDependencies($baseUrl, $packageName, $version)
|
||||||
{
|
{
|
||||||
|
|
|
@ -97,7 +97,7 @@ class PearRepository extends ArrayRepository implements ConfigurableRepositoryIn
|
||||||
*
|
*
|
||||||
* @param ChannelInfo $channelInfo
|
* @param ChannelInfo $channelInfo
|
||||||
* @param SemverVersionParser $versionParser
|
* @param SemverVersionParser $versionParser
|
||||||
* @return CompletePackage
|
* @return CompletePackage[]
|
||||||
*/
|
*/
|
||||||
private function buildComposerPackages(ChannelInfo $channelInfo, SemverVersionParser $versionParser)
|
private function buildComposerPackages(ChannelInfo $channelInfo, SemverVersionParser $versionParser)
|
||||||
{
|
{
|
||||||
|
|
|
@ -166,8 +166,14 @@ class PlatformRepository extends ArrayRepository
|
||||||
case 'imagick':
|
case 'imagick':
|
||||||
$imagick = new \Imagick();
|
$imagick = new \Imagick();
|
||||||
$imageMagickVersion = $imagick->getVersion();
|
$imageMagickVersion = $imagick->getVersion();
|
||||||
preg_match('/^ImageMagick ([\d.]+)-(\d+)/', $imageMagickVersion['versionString'], $matches);
|
// 6.x: ImageMagick 6.2.9 08/24/06 Q16 http://www.imagemagick.org
|
||||||
|
// 7.x: ImageMagick 7.0.8-34 Q16 x86_64 2019-03-23 https://imagemagick.org
|
||||||
|
preg_match('/^ImageMagick ([\d.]+)(?:-(\d+))?/', $imageMagickVersion['versionString'], $matches);
|
||||||
|
if (isset($matches[2])) {
|
||||||
$prettyVersion = "{$matches[1]}.{$matches[2]}";
|
$prettyVersion = "{$matches[1]}.{$matches[2]}";
|
||||||
|
} else {
|
||||||
|
$prettyVersion = $matches[1];
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'libxml':
|
case 'libxml':
|
||||||
|
|
|
@ -78,8 +78,9 @@ interface RepositoryInterface extends \Countable
|
||||||
*
|
*
|
||||||
* @param string $query search query
|
* @param string $query search query
|
||||||
* @param int $mode a set of SEARCH_* constants to search on, implementations should do a best effort only
|
* @param int $mode a set of SEARCH_* constants to search on, implementations should do a best effort only
|
||||||
|
* @param string $type The type of package to search for. Defaults to all types of packages
|
||||||
*
|
*
|
||||||
* @return array[] an array of array('name' => '...', 'description' => '...')
|
* @return array[] an array of array('name' => '...', 'description' => '...')
|
||||||
*/
|
*/
|
||||||
public function search($query, $mode = 0);
|
public function search($query, $mode = 0, $type = null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,15 +125,9 @@ class RepositoryManager
|
||||||
|
|
||||||
$class = $this->repositoryClasses[$type];
|
$class = $this->repositoryClasses[$type];
|
||||||
|
|
||||||
$reflMethod = new \ReflectionMethod($class, '__construct');
|
|
||||||
$params = $reflMethod->getParameters();
|
|
||||||
if (isset($params[3]) && $params[3]->getClass() && $params[3]->getClass()->getName() === 'Composer\Util\HttpDownloader') {
|
|
||||||
return new $class($config, $this->io, $this->config, $this->httpDownloader, $this->eventDispatcher);
|
return new $class($config, $this->io, $this->config, $this->httpDownloader, $this->eventDispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new $class($config, $this->io, $this->config, $this->eventDispatcher);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores repository class for a specific installation type.
|
* Stores repository class for a specific installation type.
|
||||||
*
|
*
|
||||||
|
|
|
@ -125,6 +125,7 @@ abstract class BitbucketDriver extends VcsDriver
|
||||||
|
|
||||||
$composer = $this->getBaseComposerInformation($identifier);
|
$composer = $this->getBaseComposerInformation($identifier);
|
||||||
|
|
||||||
|
if ($composer) {
|
||||||
// specials for bitbucket
|
// specials for bitbucket
|
||||||
if (!isset($composer['support']['source'])) {
|
if (!isset($composer['support']['source'])) {
|
||||||
$label = array_search(
|
$label = array_search(
|
||||||
|
@ -170,6 +171,7 @@ abstract class BitbucketDriver extends VcsDriver
|
||||||
if (!isset($composer['homepage'])) {
|
if (!isset($composer['homepage'])) {
|
||||||
$composer['homepage'] = empty($this->website) ? $this->homeUrl : $this->website;
|
$composer['homepage'] = empty($this->website) ? $this->homeUrl : $this->website;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->infoCache[$identifier] = $composer;
|
$this->infoCache[$identifier] = $composer;
|
||||||
|
|
||||||
|
@ -217,6 +219,13 @@ abstract class BitbucketDriver extends VcsDriver
|
||||||
return $this->fallbackDriver->getChangeDate($identifier);
|
return $this->fallbackDriver->getChangeDate($identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strpos($identifier, '/') !== false) {
|
||||||
|
$branches = $this->getBranches();
|
||||||
|
if (isset($branches[$identifier])) {
|
||||||
|
$identifier = $branches[$identifier];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$resource = sprintf(
|
$resource = sprintf(
|
||||||
'https://api.bitbucket.org/2.0/repositories/%s/%s/commit/%s?fields=date',
|
'https://api.bitbucket.org/2.0/repositories/%s/%s/commit/%s?fields=date',
|
||||||
$this->owner,
|
$this->owner,
|
||||||
|
|
|
@ -154,8 +154,8 @@ class GitHubDriver extends VcsDriver
|
||||||
}
|
}
|
||||||
|
|
||||||
$composer = $this->getBaseComposerInformation($identifier);
|
$composer = $this->getBaseComposerInformation($identifier);
|
||||||
if ($composer) {
|
|
||||||
|
|
||||||
|
if ($composer) {
|
||||||
// specials for github
|
// specials for github
|
||||||
if (!isset($composer['support']['source'])) {
|
if (!isset($composer['support']['source'])) {
|
||||||
$label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier;
|
$label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier;
|
||||||
|
|
|
@ -66,8 +66,9 @@ class HgDriver extends VcsDriver
|
||||||
// clean up directory and do a fresh clone into it
|
// clean up directory and do a fresh clone into it
|
||||||
$fs->removeDirectory($this->repoDir);
|
$fs->removeDirectory($this->repoDir);
|
||||||
|
|
||||||
$command = function ($url) {
|
$repoDir = $this->repoDir;
|
||||||
return sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($this->repoDir));
|
$command = function ($url) use ($repoDir) {
|
||||||
|
return sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($repoDir));
|
||||||
};
|
};
|
||||||
|
|
||||||
$hgUtils->runCommand($command, $this->url, $this->repoDir);
|
$hgUtils->runCommand($command, $this->url, $this->repoDir);
|
||||||
|
|
|
@ -38,7 +38,7 @@ interface VcsDriverInterface
|
||||||
*
|
*
|
||||||
* @param string $file
|
* @param string $file
|
||||||
* @param string $identifier
|
* @param string $identifier
|
||||||
* @return string
|
* @return string|null
|
||||||
*/
|
*/
|
||||||
public function getFileContent($file, $identifier);
|
public function getFileContent($file, $identifier);
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ interface VcsDriverInterface
|
||||||
* Get the changedate for $identifier.
|
* Get the changedate for $identifier.
|
||||||
*
|
*
|
||||||
* @param string $identifier
|
* @param string $identifier
|
||||||
* @return \DateTime
|
* @return \DateTime|null
|
||||||
*/
|
*/
|
||||||
public function getChangeDate($identifier);
|
public function getChangeDate($identifier);
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ interface VcsDriverInterface
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $identifier Any identifier to a specific branch/tag/commit
|
* @param string $identifier Any identifier to a specific branch/tag/commit
|
||||||
* @return array With type, url reference and shasum keys.
|
* @return array|null With type, url reference and shasum keys.
|
||||||
*/
|
*/
|
||||||
public function getDist($identifier);
|
public function getDist($identifier);
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,8 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
||||||
{
|
{
|
||||||
protected $url;
|
protected $url;
|
||||||
protected $packageName;
|
protected $packageName;
|
||||||
protected $verbose;
|
protected $isVerbose;
|
||||||
|
protected $isVeryVerbose;
|
||||||
protected $io;
|
protected $io;
|
||||||
protected $config;
|
protected $config;
|
||||||
protected $versionParser;
|
protected $versionParser;
|
||||||
|
@ -47,6 +48,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
||||||
private $driver;
|
private $driver;
|
||||||
/** @var VersionCacheInterface */
|
/** @var VersionCacheInterface */
|
||||||
private $versionCache;
|
private $versionCache;
|
||||||
|
private $emptyReferences = array();
|
||||||
|
|
||||||
public function __construct(array $repoConfig, IOInterface $io, Config $config, HttpDownloader $httpDownloader, EventDispatcher $dispatcher = null, array $drivers = null, VersionCacheInterface $versionCache = null)
|
public function __construct(array $repoConfig, IOInterface $io, Config $config, HttpDownloader $httpDownloader, EventDispatcher $dispatcher = null, array $drivers = null, VersionCacheInterface $versionCache = null)
|
||||||
{
|
{
|
||||||
|
@ -67,7 +69,8 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
||||||
$this->url = $repoConfig['url'];
|
$this->url = $repoConfig['url'];
|
||||||
$this->io = $io;
|
$this->io = $io;
|
||||||
$this->type = isset($repoConfig['type']) ? $repoConfig['type'] : 'vcs';
|
$this->type = isset($repoConfig['type']) ? $repoConfig['type'] : 'vcs';
|
||||||
$this->verbose = $io->isVeryVerbose();
|
$this->isVerbose = $io->isVerbose();
|
||||||
|
$this->isVeryVerbose = $io->isVeryVerbose();
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
$this->repoConfig = $repoConfig;
|
$this->repoConfig = $repoConfig;
|
||||||
$this->versionCache = $versionCache;
|
$this->versionCache = $versionCache;
|
||||||
|
@ -123,11 +126,17 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
||||||
return $this->branchErrorOccurred;
|
return $this->branchErrorOccurred;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getEmptyReferences()
|
||||||
|
{
|
||||||
|
return $this->emptyReferences;
|
||||||
|
}
|
||||||
|
|
||||||
protected function initialize()
|
protected function initialize()
|
||||||
{
|
{
|
||||||
parent::initialize();
|
parent::initialize();
|
||||||
|
|
||||||
$verbose = $this->verbose;
|
$isVerbose = $this->isVerbose;
|
||||||
|
$isVeryVerbose = $this->isVeryVerbose;
|
||||||
|
|
||||||
$driver = $this->getDriver();
|
$driver = $this->getDriver();
|
||||||
if (!$driver) {
|
if (!$driver) {
|
||||||
|
@ -145,31 +154,35 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
||||||
$this->packageName = !empty($data['name']) ? $data['name'] : null;
|
$this->packageName = !empty($data['name']) ? $data['name'] : null;
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
if ($verbose) {
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError('<error>Skipped parsing '.$driver->getRootIdentifier().', '.$e->getMessage().'</error>');
|
$this->io->writeError('<error>Skipped parsing '.$driver->getRootIdentifier().', '.$e->getMessage().'</error>');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($driver->getTags() as $tag => $identifier) {
|
foreach ($driver->getTags() as $tag => $identifier) {
|
||||||
$msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $tag . '</comment>)';
|
$msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $tag . '</comment>)';
|
||||||
if ($verbose) {
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError($msg);
|
$this->io->writeError($msg);
|
||||||
} else {
|
} elseif ($isVerbose) {
|
||||||
$this->io->overwriteError($msg, false);
|
$this->io->overwriteError($msg, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// strip the release- prefix from tags if present
|
// strip the release- prefix from tags if present
|
||||||
$tag = str_replace('release-', '', $tag);
|
$tag = str_replace('release-', '', $tag);
|
||||||
|
|
||||||
$cachedPackage = $this->getCachedPackageVersion($tag, $identifier, $verbose);
|
$cachedPackage = $this->getCachedPackageVersion($tag, $identifier, $isVerbose, $isVeryVerbose);
|
||||||
if ($cachedPackage) {
|
if ($cachedPackage) {
|
||||||
$this->addPackage($cachedPackage);
|
$this->addPackage($cachedPackage);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
} elseif ($cachedPackage === false) {
|
||||||
|
$this->emptyReferences[] = $identifier;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$parsedTag = $this->validateTag($tag)) {
|
if (!$parsedTag = $this->validateTag($tag)) {
|
||||||
if ($verbose) {
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError('<warning>Skipped tag '.$tag.', invalid tag name</warning>');
|
$this->io->writeError('<warning>Skipped tag '.$tag.', invalid tag name</warning>');
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -177,9 +190,10 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!$data = $driver->getComposerInformation($identifier)) {
|
if (!$data = $driver->getComposerInformation($identifier)) {
|
||||||
if ($verbose) {
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError('<warning>Skipped tag '.$tag.', no composer file</warning>');
|
$this->io->writeError('<warning>Skipped tag '.$tag.', no composer file</warning>');
|
||||||
}
|
}
|
||||||
|
$this->emptyReferences[] = $identifier;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +212,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
||||||
|
|
||||||
// broken package, version doesn't match tag
|
// broken package, version doesn't match tag
|
||||||
if ($data['version_normalized'] !== $parsedTag) {
|
if ($data['version_normalized'] !== $parsedTag) {
|
||||||
if ($verbose) {
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError('<warning>Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json</warning>');
|
$this->io->writeError('<warning>Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json</warning>');
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -206,47 +220,50 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
||||||
|
|
||||||
$tagPackageName = isset($data['name']) ? $data['name'] : $this->packageName;
|
$tagPackageName = isset($data['name']) ? $data['name'] : $this->packageName;
|
||||||
if ($existingPackage = $this->findPackage($tagPackageName, $data['version_normalized'])) {
|
if ($existingPackage = $this->findPackage($tagPackageName, $data['version_normalized'])) {
|
||||||
if ($verbose) {
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError('<warning>Skipped tag '.$tag.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$data['version_normalized'].' internally</warning>');
|
$this->io->writeError('<warning>Skipped tag '.$tag.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$data['version_normalized'].' internally</warning>');
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($verbose) {
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError('Importing tag '.$tag.' ('.$data['version_normalized'].')');
|
$this->io->writeError('Importing tag '.$tag.' ('.$data['version_normalized'].')');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->addPackage($this->loader->load($this->preProcess($driver, $data, $identifier)));
|
$this->addPackage($this->loader->load($this->preProcess($driver, $data, $identifier)));
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
if ($verbose) {
|
if ($e instanceof TransportException && $e->getCode() === 404) {
|
||||||
|
$this->emptyReferences[] = $identifier;
|
||||||
|
}
|
||||||
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError('<warning>Skipped tag '.$tag.', '.($e instanceof TransportException ? 'no composer file was found' : $e->getMessage()).'</warning>');
|
$this->io->writeError('<warning>Skipped tag '.$tag.', '.($e instanceof TransportException ? 'no composer file was found' : $e->getMessage()).'</warning>');
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$verbose) {
|
if (!$isVeryVerbose) {
|
||||||
$this->io->overwriteError('', false);
|
$this->io->overwriteError('', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
$branches = $driver->getBranches();
|
$branches = $driver->getBranches();
|
||||||
foreach ($branches as $branch => $identifier) {
|
foreach ($branches as $branch => $identifier) {
|
||||||
$msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $branch . '</comment>)';
|
$msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $branch . '</comment>)';
|
||||||
if ($verbose) {
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError($msg);
|
$this->io->writeError($msg);
|
||||||
} else {
|
} elseif ($isVerbose) {
|
||||||
$this->io->overwriteError($msg, false);
|
$this->io->overwriteError($msg, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($branch === 'trunk' && isset($branches['master'])) {
|
if ($branch === 'trunk' && isset($branches['master'])) {
|
||||||
if ($verbose) {
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError('<warning>Skipped branch '.$branch.', can not parse both master and trunk branches as they both resolve to 9999999-dev internally</warning>');
|
$this->io->writeError('<warning>Skipped branch '.$branch.', can not parse both master and trunk branches as they both resolve to 9999999-dev internally</warning>');
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$parsedBranch = $this->validateBranch($branch)) {
|
if (!$parsedBranch = $this->validateBranch($branch)) {
|
||||||
if ($verbose) {
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError('<warning>Skipped branch '.$branch.', invalid name</warning>');
|
$this->io->writeError('<warning>Skipped branch '.$branch.', invalid name</warning>');
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -260,18 +277,23 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
||||||
$version = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch);
|
$version = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch);
|
||||||
}
|
}
|
||||||
|
|
||||||
$cachedPackage = $this->getCachedPackageVersion($version, $identifier, $verbose);
|
$cachedPackage = $this->getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose);
|
||||||
if ($cachedPackage) {
|
if ($cachedPackage) {
|
||||||
$this->addPackage($cachedPackage);
|
$this->addPackage($cachedPackage);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
} elseif ($cachedPackage === false) {
|
||||||
|
$this->emptyReferences[] = $identifier;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!$data = $driver->getComposerInformation($identifier)) {
|
if (!$data = $driver->getComposerInformation($identifier)) {
|
||||||
if ($verbose) {
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError('<warning>Skipped branch '.$branch.', no composer file</warning>');
|
$this->io->writeError('<warning>Skipped branch '.$branch.', no composer file</warning>');
|
||||||
}
|
}
|
||||||
|
$this->emptyReferences[] = $identifier;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +301,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
||||||
$data['version'] = $version;
|
$data['version'] = $version;
|
||||||
$data['version_normalized'] = $parsedBranch;
|
$data['version_normalized'] = $parsedBranch;
|
||||||
|
|
||||||
if ($verbose) {
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError('Importing branch '.$branch.' ('.$data['version'].')');
|
$this->io->writeError('Importing branch '.$branch.' ('.$data['version'].')');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,12 +312,15 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
||||||
}
|
}
|
||||||
$this->addPackage($package);
|
$this->addPackage($package);
|
||||||
} catch (TransportException $e) {
|
} catch (TransportException $e) {
|
||||||
if ($verbose) {
|
if ($e->getCode() === 404) {
|
||||||
|
$this->emptyReferences[] = $identifier;
|
||||||
|
}
|
||||||
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError('<warning>Skipped branch '.$branch.', no composer file was found</warning>');
|
$this->io->writeError('<warning>Skipped branch '.$branch.', no composer file was found</warning>');
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
if (!$verbose) {
|
if (!$isVeryVerbose) {
|
||||||
$this->io->writeError('');
|
$this->io->writeError('');
|
||||||
}
|
}
|
||||||
$this->branchErrorOccurred = true;
|
$this->branchErrorOccurred = true;
|
||||||
|
@ -306,7 +331,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
||||||
}
|
}
|
||||||
$driver->cleanup();
|
$driver->cleanup();
|
||||||
|
|
||||||
if (!$verbose) {
|
if (!$isVeryVerbose) {
|
||||||
$this->io->overwriteError('', false);
|
$this->io->overwriteError('', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,23 +376,31 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getCachedPackageVersion($version, $identifier, $verbose)
|
private function getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose)
|
||||||
{
|
{
|
||||||
if (!$this->versionCache) {
|
if (!$this->versionCache) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$cachedPackage = $this->versionCache->getVersionPackage($version, $identifier);
|
$cachedPackage = $this->versionCache->getVersionPackage($version, $identifier);
|
||||||
|
if ($cachedPackage === false) {
|
||||||
|
if ($isVeryVerbose) {
|
||||||
|
$this->io->writeError('<warning>Skipped '.$version.', no composer file (cached from ref '.$identifier.')</warning>');
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if ($cachedPackage) {
|
if ($cachedPackage) {
|
||||||
$msg = 'Found cached composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $version . '</comment>)';
|
$msg = 'Found cached composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $version . '</comment>)';
|
||||||
if ($verbose) {
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError($msg);
|
$this->io->writeError($msg);
|
||||||
} else {
|
} elseif ($isVerbose) {
|
||||||
$this->io->overwriteError($msg, false);
|
$this->io->overwriteError($msg, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($existingPackage = $this->findPackage($cachedPackage['name'], $cachedPackage['version_normalized'])) {
|
if ($existingPackage = $this->findPackage($cachedPackage['name'], $cachedPackage['version_normalized'])) {
|
||||||
if ($verbose) {
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError('<warning>Skipped cached version '.$version.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$cachedPackage['version_normalized'].' internally</warning>');
|
$this->io->writeError('<warning>Skipped cached version '.$version.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$cachedPackage['version_normalized'].' internally</warning>');
|
||||||
}
|
}
|
||||||
$cachedPackage = null;
|
$cachedPackage = null;
|
||||||
|
|
|
@ -17,7 +17,7 @@ interface VersionCacheInterface
|
||||||
/**
|
/**
|
||||||
* @param string $version
|
* @param string $version
|
||||||
* @param string $identifier
|
* @param string $identifier
|
||||||
* @return array Package version data
|
* @return array|null|false Package version data if found, false to indicate the identifier is known but has no package, null for an unknown identifier
|
||||||
*/
|
*/
|
||||||
public function getVersionPackage($version, $identifier);
|
public function getVersionPackage($version, $identifier);
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,12 +71,11 @@ class AuthHelper
|
||||||
* @param string $origin
|
* @param string $origin
|
||||||
* @param int $statusCode HTTP status code that triggered this call
|
* @param int $statusCode HTTP status code that triggered this call
|
||||||
* @param string|null $reason a message/description explaining why this was called
|
* @param string|null $reason a message/description explaining why this was called
|
||||||
* @param string $warning an authentication warning returned by the server as {"warning": ".."}, if present
|
|
||||||
* @param string[] $headers
|
* @param string[] $headers
|
||||||
* @return array containing retry (bool) and storeAuth (string|bool) keys, if retry is true the request should be
|
* @return array|null containing retry (bool) and storeAuth (string|bool) keys, if retry is true the request should be
|
||||||
* retried, if storeAuth is true then on a successful retry the authentication should be persisted to auth.json
|
* retried, if storeAuth is true then on a successful retry the authentication should be persisted to auth.json
|
||||||
*/
|
*/
|
||||||
public function promptAuthIfNeeded($url, $origin, $statusCode, $reason = null, $warning = null, $headers = array())
|
public function promptAuthIfNeeded($url, $origin, $statusCode, $reason = null, $headers = array())
|
||||||
{
|
{
|
||||||
$storeAuth = false;
|
$storeAuth = false;
|
||||||
$retry = false;
|
$retry = false;
|
||||||
|
@ -173,10 +172,6 @@ class AuthHelper
|
||||||
throw new TransportException("Invalid credentials for '" . $url . "', aborting.", $statusCode);
|
throw new TransportException("Invalid credentials for '" . $url . "', aborting.", $statusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->io->overwriteError('');
|
|
||||||
if ($warning) {
|
|
||||||
$this->io->writeError(' <warning>'.$warning.'</warning>');
|
|
||||||
}
|
|
||||||
$this->io->writeError(' Authentication required (<info>'.parse_url($url, PHP_URL_HOST).'</info>):');
|
$this->io->writeError(' Authentication required (<info>'.parse_url($url, PHP_URL_HOST).'</info>):');
|
||||||
$username = $this->io->ask(' Username: ');
|
$username = $this->io->ask(' Username: ');
|
||||||
$password = $this->io->askAndHideAnswer(' Password: ');
|
$password = $this->io->askAndHideAnswer(' Password: ');
|
||||||
|
|
|
@ -22,11 +22,17 @@ use Composer\Downloader\TransportException;
|
||||||
*/
|
*/
|
||||||
class Bitbucket
|
class Bitbucket
|
||||||
{
|
{
|
||||||
|
/** @var IOInterface */
|
||||||
private $io;
|
private $io;
|
||||||
|
/** @var Config */
|
||||||
private $config;
|
private $config;
|
||||||
|
/** @var ProcessExecutor */
|
||||||
private $process;
|
private $process;
|
||||||
|
/** @var HttpDownloader */
|
||||||
private $httpDownloader;
|
private $httpDownloader;
|
||||||
|
/** @var array */
|
||||||
private $token = array();
|
private $token = array();
|
||||||
|
/** @var int|null */
|
||||||
private $time;
|
private $time;
|
||||||
|
|
||||||
const OAUTH2_ACCESS_TOKEN_URL = 'https://bitbucket.org/site/oauth2/access_token';
|
const OAUTH2_ACCESS_TOKEN_URL = 'https://bitbucket.org/site/oauth2/access_token';
|
||||||
|
|
|
@ -23,6 +23,7 @@ use Symfony\Component\Finder\Finder;
|
||||||
*/
|
*/
|
||||||
class Filesystem
|
class Filesystem
|
||||||
{
|
{
|
||||||
|
/** @var ProcessExecutor */
|
||||||
private $processExecutor;
|
private $processExecutor;
|
||||||
|
|
||||||
public function __construct(ProcessExecutor $executor = null)
|
public function __construct(ProcessExecutor $executor = null)
|
||||||
|
@ -199,9 +200,15 @@ class Filesystem
|
||||||
*/
|
*/
|
||||||
public function unlink($path)
|
public function unlink($path)
|
||||||
{
|
{
|
||||||
if (!@$this->unlinkImplementation($path)) {
|
$unlinked = @$this->unlinkImplementation($path);
|
||||||
|
if (!$unlinked) {
|
||||||
// retry after a bit on windows since it tends to be touchy with mass removals
|
// retry after a bit on windows since it tends to be touchy with mass removals
|
||||||
if (!Platform::isWindows() || (usleep(350000) && !@$this->unlinkImplementation($path))) {
|
if (Platform::isWindows()) {
|
||||||
|
usleep(350000);
|
||||||
|
$unlinked = @$this->unlinkImplementation($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$unlinked) {
|
||||||
$error = error_get_last();
|
$error = error_get_last();
|
||||||
$message = 'Could not delete '.$path.': ' . @$error['message'];
|
$message = 'Could not delete '.$path.': ' . @$error['message'];
|
||||||
if (Platform::isWindows()) {
|
if (Platform::isWindows()) {
|
||||||
|
@ -224,9 +231,15 @@ class Filesystem
|
||||||
*/
|
*/
|
||||||
public function rmdir($path)
|
public function rmdir($path)
|
||||||
{
|
{
|
||||||
if (!@rmdir($path)) {
|
$deleted = @rmdir($path);
|
||||||
|
if (!$deleted) {
|
||||||
// retry after a bit on windows since it tends to be touchy with mass removals
|
// retry after a bit on windows since it tends to be touchy with mass removals
|
||||||
if (!Platform::isWindows() || (usleep(350000) && !@rmdir($path))) {
|
if (Platform::isWindows()) {
|
||||||
|
usleep(350000);
|
||||||
|
$deleted = @rmdir($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$deleted) {
|
||||||
$error = error_get_last();
|
$error = error_get_last();
|
||||||
$message = 'Could not delete '.$path.': ' . @$error['message'];
|
$message = 'Could not delete '.$path.': ' . @$error['message'];
|
||||||
if (Platform::isWindows()) {
|
if (Platform::isWindows()) {
|
||||||
|
@ -279,6 +292,7 @@ class Filesystem
|
||||||
$this->ensureDirectoryExists($target);
|
$this->ensureDirectoryExists($target);
|
||||||
|
|
||||||
$result = true;
|
$result = true;
|
||||||
|
/** @var RecursiveDirectoryIterator $ri */
|
||||||
foreach ($ri as $file) {
|
foreach ($ri as $file) {
|
||||||
$targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathName();
|
$targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathName();
|
||||||
if ($file->isDir()) {
|
if ($file->isDir()) {
|
||||||
|
@ -428,7 +442,7 @@ class Filesystem
|
||||||
*/
|
*/
|
||||||
public function isAbsolutePath($path)
|
public function isAbsolutePath($path)
|
||||||
{
|
{
|
||||||
return substr($path, 0, 1) === '/' || substr($path, 1, 1) === ':';
|
return substr($path, 0, 1) === '/' || substr($path, 1, 1) === ':' || substr($path, 0, 2) === '\\\\';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -525,6 +539,9 @@ class Filesystem
|
||||||
return $size;
|
return $size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ProcessExecutor
|
||||||
|
*/
|
||||||
protected function getProcess()
|
protected function getProcess()
|
||||||
{
|
{
|
||||||
return $this->processExecutor;
|
return $this->processExecutor;
|
||||||
|
@ -648,6 +665,20 @@ class Filesystem
|
||||||
/**
|
/**
|
||||||
* Returns whether the target directory is a Windows NTFS Junction.
|
* Returns whether the target directory is a Windows NTFS Junction.
|
||||||
*
|
*
|
||||||
|
* We test if the path is a directory and not an ordinary link, then check
|
||||||
|
* that the mode value returned from lstat (which gives the status of the
|
||||||
|
* link itself) is not a directory, by replicating the POSIX S_ISDIR test.
|
||||||
|
*
|
||||||
|
* This logic works because PHP does not set the mode value for a junction,
|
||||||
|
* since there is no universal file type flag for it. Unfortunately an
|
||||||
|
* uninitialized variable in PHP prior to 7.2.16 and 7.3.3 may cause a
|
||||||
|
* random value to be returned. See https://bugs.php.net/bug.php?id=77552
|
||||||
|
*
|
||||||
|
* If this random value passes the S_ISDIR test, then a junction will not be
|
||||||
|
* detected and a recursive delete operation could lead to loss of data in
|
||||||
|
* the target directory. Note that Windows rmdir can handle this situation
|
||||||
|
* and will only delete the junction (from Windows 7 onwards).
|
||||||
|
*
|
||||||
* @param string $junction Path to check.
|
* @param string $junction Path to check.
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
@ -659,22 +690,13 @@ class Filesystem
|
||||||
if (!is_dir($junction) || is_link($junction)) {
|
if (!is_dir($junction) || is_link($junction)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* According to MSDN at https://msdn.microsoft.com/en-us/library/14h5k7ff.aspx we can detect a junction now
|
// Important to clear all caches first
|
||||||
* using the 'mode' value from stat: "The _S_IFDIR bit is set if path specifies a directory; the _S_IFREG bit
|
|
||||||
* is set if path specifies an ordinary file or a device." We have just tested for a directory above, so if
|
|
||||||
* we have a directory that isn't one according to lstat(...) we must have a junction.
|
|
||||||
*
|
|
||||||
* #define _S_IFDIR 0x4000
|
|
||||||
* #define _S_IFREG 0x8000
|
|
||||||
*
|
|
||||||
* Stat cache should be cleared before to avoid accidentally reading wrong information from previous installs.
|
|
||||||
*/
|
|
||||||
clearstatcache(true, $junction);
|
clearstatcache(true, $junction);
|
||||||
clearstatcache(false);
|
|
||||||
$stat = lstat($junction);
|
$stat = lstat($junction);
|
||||||
|
|
||||||
return !($stat['mode'] & 0xC000);
|
// S_ISDIR test (S_IFDIR is 0x4000, S_IFMT is 0xF000 bitmask)
|
||||||
|
return $stat ? 0x4000 !== ($stat['mode'] & 0xF000) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -692,9 +714,7 @@ class Filesystem
|
||||||
if (!$this->isJunction($junction)) {
|
if (!$this->isJunction($junction)) {
|
||||||
throw new IOException(sprintf('%s is not a junction and thus cannot be removed as one', $junction));
|
throw new IOException(sprintf('%s is not a junction and thus cannot be removed as one', $junction));
|
||||||
}
|
}
|
||||||
$cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape($junction));
|
|
||||||
clearstatcache(true, $junction);
|
|
||||||
|
|
||||||
return ($this->getProcess()->execute($cmd, $output) === 0);
|
return $this->rmdir($junction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,13 @@ use Composer\Downloader\TransportException;
|
||||||
*/
|
*/
|
||||||
class GitHub
|
class GitHub
|
||||||
{
|
{
|
||||||
|
/** @var IOInterface */
|
||||||
protected $io;
|
protected $io;
|
||||||
|
/** @var Config */
|
||||||
protected $config;
|
protected $config;
|
||||||
|
/** @var ProcessExecutor */
|
||||||
protected $process;
|
protected $process;
|
||||||
|
/** @var HttpDownloader */
|
||||||
protected $httpDownloader;
|
protected $httpDownloader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue