Merge branch 'master' into filter-packages
* master: (59 commits) Update deps Reuse repository manager and others directly from the Composer instance, refs #9057 Fix usage of create-project with local filesystem repos Fix return value Add support for multiple --repository additions in create-project, and make --add-repository delete the lock file, fixes #8853 Remove cygwin php handling in UAC elevation Clean up a little to make impl less invasive and to handle replacers/providers Supply event dispatcher in Create Project Command Avoid attempting to use /etc/xdg as base config home, fixes #9053, refs #9045 Create an issue @ Docker repository on tag Mark transaction classes internal, refs #8827 Prepare 1.10.9 release Remove highest/lowest builds for 1.10 maintenance branch Fix bitbucket detection of redirects to login page, fixes #9041 Fix doc comment Fixed spelling mistake Add Windows UAC elevation to self-update command GitLab: clarify interactive auth prompt Improve support for XDG and default to XDG config dir if both that and ~/.composer are available, fixes #9045 Fix #9033 - inconsistent behavior with minor-only flag ...pull/8850/head
commit
6ba0f3adf9
|
@ -81,6 +81,8 @@ jobs:
|
||||||
echo "::set-env name=SYMFONY_PHPUNIT_VERSION::6.5";
|
echo "::set-env name=SYMFONY_PHPUNIT_VERSION::6.5";
|
||||||
elif [ "${{ matrix.php-version }}" = "7.1" ]; then
|
elif [ "${{ matrix.php-version }}" = "7.1" ]; then
|
||||||
echo "::set-env name=SYMFONY_PHPUNIT_VERSION::7.5";
|
echo "::set-env name=SYMFONY_PHPUNIT_VERSION::7.5";
|
||||||
|
elif [ "${{ matrix.php-version }}" = "8.0" ]; then
|
||||||
|
echo "::set-env name=SYMFONY_PHPUNIT_VERSION::9.2";
|
||||||
else
|
else
|
||||||
echo "::set-env name=SYMFONY_PHPUNIT_VERSION::8.3";
|
echo "::set-env name=SYMFONY_PHPUNIT_VERSION::8.3";
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -56,3 +56,20 @@ jobs:
|
||||||
asset_path: ./composer.phar
|
asset_path: ./composer.phar
|
||||||
asset_name: composer.phar
|
asset_name: composer.phar
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
# This step requires a secret token with `pull` access to composer/docker. The default
|
||||||
|
# secrets.GITHUB_TOKEN is scoped to this repository only which is not sufficient.
|
||||||
|
- name: "Open issue @ Docker repository"
|
||||||
|
uses: actions/github-script@v2
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}
|
||||||
|
script: |
|
||||||
|
// github.ref value looks like 'refs/tags/TAG', cleanup
|
||||||
|
const tag = "${{ github.ref }}".replace(/refs\/tags\//, '');
|
||||||
|
// create new issue on Docker repository
|
||||||
|
github.issues.create({
|
||||||
|
owner: "${{ github.repository_owner }}",
|
||||||
|
repo: "docker",
|
||||||
|
title: `New Composer tag: ${ tag }`,
|
||||||
|
body: `https://github.com/${{ github.repository }}/releases/tag/${ tag }`,
|
||||||
|
});
|
||||||
|
|
29
CHANGELOG.md
29
CHANGELOG.md
|
@ -1,3 +1,14 @@
|
||||||
|
### [2.0.0-alpha2] 2020-06-24
|
||||||
|
|
||||||
|
* Added parallel installation of packages (requires OSX/Linux/WSL, and that `unzip` is present in PATH)
|
||||||
|
* Added optimization of constraints by compiling them to PHP code, which should reduce CPU time of updates
|
||||||
|
* Added handling of Ctrl-C on Windows for PHP 7.4+
|
||||||
|
* Added better support for default branch names other than `master`
|
||||||
|
* Added --format=summary flag to `license` command
|
||||||
|
* Fixed issue in platform check when requiring ext-zend-opcache
|
||||||
|
* Fixed inline aliases issues
|
||||||
|
* Fixed git integration issue when signatures are set to be shown by default
|
||||||
|
|
||||||
### [2.0.0-alpha1] 2020-06-03
|
### [2.0.0-alpha1] 2020-06-03
|
||||||
|
|
||||||
* Breaking: This is a major release and while we tried to keep things compatible for most users, you might want to have a look at the [UPGRADE](UPGRADE-2.0.md) guides
|
* Breaking: This is a major release and while we tried to keep things compatible for most users, you might want to have a look at the [UPGRADE](UPGRADE-2.0.md) guides
|
||||||
|
@ -35,9 +46,22 @@
|
||||||
* Fixed suggest output being very spammy, it now is only one line long and shows more rarely
|
* Fixed suggest output being very spammy, it now is only one line long and shows more rarely
|
||||||
* Fixed conflict rules like e.g. >=5 from matching dev-master, as it is not normalized to 9999999-dev internally anymore
|
* Fixed conflict rules like e.g. >=5 from matching dev-master, as it is not normalized to 9999999-dev internally anymore
|
||||||
|
|
||||||
|
### [1.10.9] 2020-07-16
|
||||||
|
|
||||||
|
* Fixed Bitbucket redirect loop when credentials are outdated
|
||||||
|
* Fixed GitLab auth prompt wording
|
||||||
|
* Fixed `self-update` handling of files requiring admin permissions to write to on Windows (it now does a UAC prompt)
|
||||||
|
* Fixed parsing issues in funding.yml files
|
||||||
|
|
||||||
|
### [1.10.8] 2020-06-24
|
||||||
|
|
||||||
|
* Fixed compatibility issue with git being configured to show signatures by default
|
||||||
|
* Fixed discarding of local changes when updating packages to include untracked files
|
||||||
|
* Several minor fixes
|
||||||
|
|
||||||
### [1.10.7] 2020-06-03
|
### [1.10.7] 2020-06-03
|
||||||
|
|
||||||
* Fix PHP 8 deprecations
|
* Fixed PHP 8 deprecations
|
||||||
* Fixed detection of pcntl_signal being in disabled_functions when pcntl_async_signal is allowed
|
* Fixed detection of pcntl_signal being in disabled_functions when pcntl_async_signal is allowed
|
||||||
|
|
||||||
### [1.10.6] 2020-05-06
|
### [1.10.6] 2020-05-06
|
||||||
|
@ -897,7 +921,10 @@
|
||||||
|
|
||||||
* Initial release
|
* Initial release
|
||||||
|
|
||||||
|
[2.0.0-alpha2]: https://github.com/composer/composer/compare/2.0.0-alpha1...2.0.0-alpha2
|
||||||
[2.0.0-alpha1]: https://github.com/composer/composer/compare/1.10.7...2.0.0-alpha1
|
[2.0.0-alpha1]: https://github.com/composer/composer/compare/1.10.7...2.0.0-alpha1
|
||||||
|
[1.10.9]: https://github.com/composer/composer/compare/1.10.8...1.10.9
|
||||||
|
[1.10.8]: https://github.com/composer/composer/compare/1.10.7...1.10.8
|
||||||
[1.10.7]: https://github.com/composer/composer/compare/1.10.6...1.10.7
|
[1.10.7]: https://github.com/composer/composer/compare/1.10.6...1.10.7
|
||||||
[1.10.6]: https://github.com/composer/composer/compare/1.10.5...1.10.6
|
[1.10.6]: https://github.com/composer/composer/compare/1.10.5...1.10.6
|
||||||
[1.10.5]: https://github.com/composer/composer/compare/1.10.4...1.10.5
|
[1.10.5]: https://github.com/composer/composer/compare/1.10.4...1.10.5
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
## For composer CLI users
|
## For composer CLI users
|
||||||
|
|
||||||
- The new platform-check feature means that Composer checks the runtime PHP version and available extensions to ensure they match the project dependencies. If a mismatch is found, it exits with error details to make sure problems are not overlooked. To avoid issues when deploying to production it is recommended to run `composer check-platform-reqs` with the production PHP process as part of your build or deployment process.
|
- The new platform-check feature means that Composer checks the runtime PHP version and available extensions to ensure they match the project dependencies. If a mismatch is found, it exits with error details to make sure problems are not overlooked. To avoid issues when deploying to production it is recommended to run `composer check-platform-reqs` with the production PHP process as part of your build or deployment process.
|
||||||
- If a packages exists in a higher priority repository, it will now be entirely ignored in lower priority repositories. See [repository priorities](https://getcomposer.org/repoprio) for details.
|
- If a package exists in a higher priority repository, it will now be entirely ignored in lower priority repositories. See [repository priorities](https://getcomposer.org/repoprio) for details.
|
||||||
- Invalid PSR-0 / PSR-4 class configurations will not autoload anymore in optimized-autoloader mode, as per the warnings introduced in 1.10
|
- Invalid PSR-0 / PSR-4 class configurations will not autoload anymore in optimized-autoloader mode, as per the warnings introduced in 1.10
|
||||||
|
- On linux systems supporting the XDG Base Directory Specification, Composer will now prefer using XDG_CONFIG_DIR/composer over ~/.composer if both are available (1.x used ~/.composer first)
|
||||||
- Package names now must comply to our [naming guidelines](doc/04-schema.md#name) or Composer will abort, as per the warnings introduced in 1.8.1
|
- Package names now must comply to our [naming guidelines](doc/04-schema.md#name) or Composer will abort, as per the warnings introduced in 1.8.1
|
||||||
- Deprecated --no-suggest flag as it is not needed anymore
|
- Deprecated --no-suggest flag as it is not needed anymore
|
||||||
- PEAR support (repository, downloader, etc.) has been removed
|
- PEAR support (repository, downloader, etc.) has been removed
|
||||||
|
@ -27,7 +28,7 @@
|
||||||
- packages are now wrapped into a `"packages"` top level key instead of the whole file being the package array
|
- packages are now wrapped into a `"packages"` top level key instead of the whole file being the package array
|
||||||
- packages now contain an `"installed-path"` key which lists where they were installed
|
- packages now contain an `"installed-path"` key which lists where they were installed
|
||||||
- there is a top level `"dev"` key which stores whether dev requirements were installed or not
|
- there is a top level `"dev"` key which stores whether dev requirements were installed or not
|
||||||
- `PreFileDownloadEvent` now receives an `HttpDownloader` instance instead of `RemoteFilesystem`, and that instance can not be overridden by listeners anymore
|
- `PreFileDownloadEvent` now receives an `HttpDownloader` instance instead of `RemoteFilesystem`, and that instance cannot be overridden by listeners anymore
|
||||||
- `VersionSelector::findBestCandidate`'s third argument (phpVersion) was removed in favor of passing in a complete PlatformRepository instance into the constructor
|
- `VersionSelector::findBestCandidate`'s third argument (phpVersion) was removed in favor of passing in a complete PlatformRepository instance into the constructor
|
||||||
- `InitCommand::determineRequirements`'s fourth argument (phpVersion) should now receive a complete PlatformRepository instance or null if platform requirements are to be ignored
|
- `InitCommand::determineRequirements`'s fourth argument (phpVersion) should now receive a complete PlatformRepository instance or null if platform requirements are to be ignored
|
||||||
- `IOInterface` now extends PSR-3's `LoggerInterface`, and has new `writeRaw` + `writeErrorRaw` methods
|
- `IOInterface` now extends PSR-3's `LoggerInterface`, and has new `writeRaw` + `writeErrorRaw` methods
|
||||||
|
@ -74,3 +75,9 @@ If your repository only has a small number of packages, and you want to avoid th
|
||||||
`"providers-api": "https://packagist.org/providers/%package%.json",`
|
`"providers-api": "https://packagist.org/providers/%package%.json",`
|
||||||
|
|
||||||
The providers-api is optional, but if you implement it it should return packages which provide a given package name, but not the package which has that name. For example https://packagist.org/providers/monolog/monolog.json lists some package which have a "provide" rule for monolog/monolog, but it does not list monolog/monolog itself.
|
The providers-api is optional, but if you implement it it should return packages which provide a given package name, but not the package which has that name. For example https://packagist.org/providers/monolog/monolog.json lists some package which have a "provide" rule for monolog/monolog, but it does not list monolog/monolog itself.
|
||||||
|
|
||||||
|
### list
|
||||||
|
|
||||||
|
This is also optional, it should accept an optional `?filter=xx` query param, which can contain `*` as wildcards matching any substring.
|
||||||
|
|
||||||
|
It must return an array of package names as `{"packageNames": ["a/b", "c/d"]}`. See https://packagist.org/packages/list.json?filter=composer/* for example.
|
||||||
|
|
|
@ -160,16 +160,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "composer/spdx-licenses",
|
"name": "composer/spdx-licenses",
|
||||||
"version": "1.5.3",
|
"version": "1.5.4",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/composer/spdx-licenses.git",
|
"url": "https://github.com/composer/spdx-licenses.git",
|
||||||
"reference": "0c3e51e1880ca149682332770e25977c70cf9dae"
|
"reference": "6946f785871e2314c60b4524851f3702ea4f2223"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/composer/spdx-licenses/zipball/0c3e51e1880ca149682332770e25977c70cf9dae",
|
"url": "https://api.github.com/repos/composer/spdx-licenses/zipball/6946f785871e2314c60b4524851f3702ea4f2223",
|
||||||
"reference": "0c3e51e1880ca149682332770e25977c70cf9dae",
|
"reference": "6946f785871e2314c60b4524851f3702ea4f2223",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -219,9 +219,23 @@
|
||||||
"support": {
|
"support": {
|
||||||
"irc": "irc://irc.freenode.org/composer",
|
"irc": "irc://irc.freenode.org/composer",
|
||||||
"issues": "https://github.com/composer/spdx-licenses/issues",
|
"issues": "https://github.com/composer/spdx-licenses/issues",
|
||||||
"source": "https://github.com/composer/spdx-licenses/tree/1.5.3"
|
"source": "https://github.com/composer/spdx-licenses/tree/1.5.4"
|
||||||
},
|
},
|
||||||
"time": "2020-02-14T07:44:31+00:00"
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://packagist.com",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/composer",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2020-07-15T15:35:07+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "composer/xdebug-handler",
|
"name": "composer/xdebug-handler",
|
||||||
|
@ -519,16 +533,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "seld/phar-utils",
|
"name": "seld/phar-utils",
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Seldaek/phar-utils.git",
|
"url": "https://github.com/Seldaek/phar-utils.git",
|
||||||
"reference": "8800503d56b9867d43d9c303b9cbcc26016e82f0"
|
"reference": "8674b1d84ffb47cc59a101f5d5a3b61e87d23796"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/8800503d56b9867d43d9c303b9cbcc26016e82f0",
|
"url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/8674b1d84ffb47cc59a101f5d5a3b61e87d23796",
|
||||||
"reference": "8800503d56b9867d43d9c303b9cbcc26016e82f0",
|
"reference": "8674b1d84ffb47cc59a101f5d5a3b61e87d23796",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -561,9 +575,9 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Seldaek/phar-utils/issues",
|
"issues": "https://github.com/Seldaek/phar-utils/issues",
|
||||||
"source": "https://github.com/Seldaek/phar-utils/tree/1.1.0"
|
"source": "https://github.com/Seldaek/phar-utils/tree/master"
|
||||||
},
|
},
|
||||||
"time": "2020-02-14T15:25:33+00:00"
|
"time": "2020-07-07T18:42:57+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
|
@ -796,16 +810,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-ctype",
|
"name": "symfony/polyfill-ctype",
|
||||||
"version": "v1.17.0",
|
"version": "v1.18.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||||
"reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9"
|
"reference": "1c302646f6efc070cd46856e600e5e0684d6b454"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
|
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/1c302646f6efc070cd46856e600e5e0684d6b454",
|
||||||
"reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
|
"reference": "1c302646f6efc070cd46856e600e5e0684d6b454",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -817,7 +831,11 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.17-dev"
|
"dev-master": "1.18-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "symfony/polyfill",
|
||||||
|
"url": "https://github.com/symfony/polyfill"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -851,7 +869,7 @@
|
||||||
"portable"
|
"portable"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.17.0"
|
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.18.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -867,20 +885,20 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2020-05-12T16:14:59+00:00"
|
"time": "2020-07-14T12:35:20+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-mbstring",
|
"name": "symfony/polyfill-mbstring",
|
||||||
"version": "v1.17.0",
|
"version": "v1.18.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||||
"reference": "fa79b11539418b02fc5e1897267673ba2c19419c"
|
"reference": "a6977d63bf9a0ad4c65cd352709e230876f9904a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fa79b11539418b02fc5e1897267673ba2c19419c",
|
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/a6977d63bf9a0ad4c65cd352709e230876f9904a",
|
||||||
"reference": "fa79b11539418b02fc5e1897267673ba2c19419c",
|
"reference": "a6977d63bf9a0ad4c65cd352709e230876f9904a",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -892,7 +910,11 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.17-dev"
|
"dev-master": "1.18-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "symfony/polyfill",
|
||||||
|
"url": "https://github.com/symfony/polyfill"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -927,7 +949,7 @@
|
||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.17.0"
|
"source": "https://github.com/symfony/polyfill-mbstring/tree/master"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -943,7 +965,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2020-05-12T16:47:27+00:00"
|
"time": "2020-07-14T12:35:20+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/process",
|
"name": "symfony/process",
|
||||||
|
|
|
@ -9,7 +9,7 @@ for you.
|
||||||
Composer is **not** a package manager in the same sense as Yum or Apt are. Yes,
|
Composer is **not** a package manager in the same sense as Yum or Apt are. Yes,
|
||||||
it deals with "packages" or libraries, but it manages them on a per-project
|
it deals with "packages" or libraries, but it manages them on a per-project
|
||||||
basis, installing them in a directory (e.g. `vendor`) inside your project. By
|
basis, installing them in a directory (e.g. `vendor`) inside your project. By
|
||||||
default it does not install anything globally. Thus, it is a dependency
|
default, it does not install anything globally. Thus, it is a dependency
|
||||||
manager. It does however support a "global" project for convenience via the
|
manager. It does however support a "global" project for convenience via the
|
||||||
[global](03-cli.md#global) command.
|
[global](03-cli.md#global) command.
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ versions, how versions relate to each other, and on version constraints.
|
||||||
|
|
||||||
> **Note:** If you are trying to require a package but Composer throws an error
|
> **Note:** If you are trying to require a package but Composer throws an error
|
||||||
> regarding package stability, the version you have specified may not meet your
|
> regarding package stability, the version you have specified may not meet your
|
||||||
> default minimum stability requirements. By default only stable releases are taken
|
> default minimum stability requirements. By default, only stable releases are taken
|
||||||
> into consideration when searching for valid package versions in your VCS.
|
> into consideration when searching for valid package versions in your VCS.
|
||||||
>
|
>
|
||||||
> You might run into this if you are trying to require dev, alpha, beta, or RC
|
> You might run into this if you are trying to require dev, alpha, beta, or RC
|
||||||
|
|
|
@ -26,14 +26,14 @@ In this case the project name is `acme/hello-world`, where `acme` is the vendor
|
||||||
name. Supplying a vendor name is mandatory.
|
name. Supplying a vendor name is mandatory.
|
||||||
|
|
||||||
> **Note:** If you don't know what to use as a vendor name, your GitHub
|
> **Note:** If you don't know what to use as a vendor name, your GitHub
|
||||||
> username is usually a good bet. While package names are case insensitive, the
|
> username is usually a good bet. While package names are case-insensitive, the
|
||||||
> convention is all lowercase and dashes for word separation.
|
> convention is all lowercase and dashes for word separation.
|
||||||
|
|
||||||
## Library Versioning
|
## Library Versioning
|
||||||
|
|
||||||
In the vast majority of cases, you will be maintaining your library using some
|
In the vast majority of cases, you will be maintaining your library using some
|
||||||
sort of version control system like git, svn, hg or fossil. In these cases,
|
sort of version control system like git, svn, hg or fossil. In these cases,
|
||||||
Composer infers versions from your VCS and you **should not** specify a version
|
Composer infers versions from your VCS, and you **should not** specify a version
|
||||||
in your `composer.json` file. (See the [Versions article](articles/versions.md)
|
in your `composer.json` file. (See the [Versions article](articles/versions.md)
|
||||||
to learn about how Composer uses VCS branches and tags to resolve version
|
to learn about how Composer uses VCS branches and tags to resolve version
|
||||||
constraints.)
|
constraints.)
|
||||||
|
@ -69,7 +69,7 @@ can help your team to always test against the same dependency versions.
|
||||||
However, this lock file will not have any effect on other projects that depend
|
However, this lock file will not have any effect on other projects that depend
|
||||||
on it. It only has an effect on the main project.
|
on it. It only has an effect on the main project.
|
||||||
|
|
||||||
If you do not want to commit the lock file and you are using git, add it to
|
If you do not want to commit the lock file, and you are using git, add it to
|
||||||
the `.gitignore`.
|
the `.gitignore`.
|
||||||
|
|
||||||
## Publishing to a VCS
|
## Publishing to a VCS
|
||||||
|
|
|
@ -185,7 +185,7 @@ php composer.phar update vendor/package:2.0.1 vendor/package2:3.0.*
|
||||||
* **--with-all-dependencies:** Update also dependencies of packages in the argument list, including those which are root requirements.
|
* **--with-all-dependencies:** Update also dependencies of packages in the argument list, including those which are root requirements.
|
||||||
* **--optimize-autoloader (-o):** Convert PSR-0/4 autoloading to classmap to get a faster
|
* **--optimize-autoloader (-o):** Convert PSR-0/4 autoloading to classmap to get a faster
|
||||||
autoloader. This is recommended especially for production, but can take
|
autoloader. This is recommended especially for production, but can take
|
||||||
a bit of time to run so it is currently not done by default.
|
a bit of time to run, so it is currently not done by default.
|
||||||
* **--classmap-authoritative (-a):** Autoload classes from the classmap only.
|
* **--classmap-authoritative (-a):** Autoload classes from the classmap only.
|
||||||
Implicitly enables `--optimize-autoloader`.
|
Implicitly enables `--optimize-autoloader`.
|
||||||
* **--apcu-autoloader:** Use APCu to cache found/not-found classes.
|
* **--apcu-autoloader:** Use APCu to cache found/not-found classes.
|
||||||
|
@ -252,7 +252,7 @@ If you do not specify a package, composer will prompt you to search for a packag
|
||||||
* **--sort-packages:** Keep packages sorted in `composer.json`.
|
* **--sort-packages:** Keep packages sorted in `composer.json`.
|
||||||
* **--optimize-autoloader (-o):** Convert PSR-0/4 autoloading to classmap to
|
* **--optimize-autoloader (-o):** Convert PSR-0/4 autoloading to classmap to
|
||||||
get a faster autoloader. This is recommended especially for production, but
|
get a faster autoloader. This is recommended especially for production, but
|
||||||
can take a bit of time to run so it is currently not done by default.
|
can take a bit of time to run, so it is currently not done by default.
|
||||||
* **--classmap-authoritative (-a):** Autoload classes from the classmap only.
|
* **--classmap-authoritative (-a):** Autoload classes from the classmap only.
|
||||||
Implicitly enables `--optimize-autoloader`.
|
Implicitly enables `--optimize-autoloader`.
|
||||||
* **--apcu-autoloader:** Use APCu to cache found/not-found classes.
|
* **--apcu-autoloader:** Use APCu to cache found/not-found classes.
|
||||||
|
@ -408,6 +408,7 @@ php composer.phar show monolog/monolog 1.0.2
|
||||||
* **--tree (-t):** List your dependencies as a tree. If you pass a package name it will show the dependency tree for that package.
|
* **--tree (-t):** List your dependencies as a tree. If you pass a package name it will show the dependency tree for that package.
|
||||||
* **--latest (-l):** List all installed packages including their latest version.
|
* **--latest (-l):** List all installed packages including their latest version.
|
||||||
* **--outdated (-o):** Implies --latest, but this lists *only* packages that have a newer version available.
|
* **--outdated (-o):** Implies --latest, but this lists *only* packages that have a newer version available.
|
||||||
|
* **--no-dev:** Filters dev dependencies from the package list.
|
||||||
* **--minor-only (-m):** Use with --latest. Only shows packages that have minor SemVer-compatible updates.
|
* **--minor-only (-m):** Use with --latest. Only shows packages that have minor SemVer-compatible updates.
|
||||||
* **--direct (-D):** Restricts the list of packages to your direct dependencies.
|
* **--direct (-D):** Restricts the list of packages to your direct dependencies.
|
||||||
* **--strict:** Return a non-zero exit code when there are outdated packages.
|
* **--strict:** Return a non-zero exit code when there are outdated packages.
|
||||||
|
@ -433,6 +434,7 @@ The color coding is as such:
|
||||||
* **--strict:** Returns non-zero exit code if any package is outdated.
|
* **--strict:** Returns non-zero exit code if any package is outdated.
|
||||||
* **--minor-only (-m):** Only shows packages that have minor SemVer-compatible updates.
|
* **--minor-only (-m):** Only shows packages that have minor SemVer-compatible updates.
|
||||||
* **--format (-f):** Lets you pick between text (default) or json output format.
|
* **--format (-f):** Lets you pick between text (default) or json output format.
|
||||||
|
* **--no-dev:** Do not show outdated dev dependencies.
|
||||||
|
|
||||||
## browse / home
|
## browse / home
|
||||||
|
|
||||||
|
@ -722,8 +724,9 @@ By default the command checks for the packages on packagist.org.
|
||||||
which will be used instead of packagist. Can be either an HTTP URL pointing
|
which will be used instead of packagist. Can be either an HTTP URL pointing
|
||||||
to a `composer` repository, a path to a local `packages.json` file, or a
|
to a `composer` repository, a path to a local `packages.json` file, or a
|
||||||
JSON string which similar to what the [repositories](04-schema.md#repositories)
|
JSON string which similar to what the [repositories](04-schema.md#repositories)
|
||||||
key accepts.
|
key accepts. You can use this multiple times to configure multiple repositories.
|
||||||
* **--add-repository:** Add the repository option to the composer.json.
|
* **--add-repository:** Add the custom repository in the composer.json. If a lock
|
||||||
|
file is present it will be deleted and an update will be run instead of install.
|
||||||
* **--dev:** Install packages listed in `require-dev`.
|
* **--dev:** Install packages listed in `require-dev`.
|
||||||
* **--no-dev:** Disables installation of require-dev packages.
|
* **--no-dev:** Disables installation of require-dev packages.
|
||||||
* **--no-scripts:** Disables the execution of the scripts defined in the root
|
* **--no-scripts:** Disables the execution of the scripts defined in the root
|
||||||
|
@ -763,7 +766,7 @@ performance.
|
||||||
* **--no-scripts:** Skips the execution of all scripts defined in `composer.json` file.
|
* **--no-scripts:** Skips the execution of all scripts defined in `composer.json` file.
|
||||||
* **--optimize (-o):** Convert PSR-0/4 autoloading to classmap to get a faster
|
* **--optimize (-o):** Convert PSR-0/4 autoloading to classmap to get a faster
|
||||||
autoloader. This is recommended especially for production, but can take
|
autoloader. This is recommended especially for production, but can take
|
||||||
a bit of time to run so it is currently not done by default.
|
a bit of time to run, so it is currently not done by default.
|
||||||
* **--classmap-authoritative (-a):** Autoload classes from the classmap only.
|
* **--classmap-authoritative (-a):** Autoload classes from the classmap only.
|
||||||
Implicitly enables `--optimize`.
|
Implicitly enables `--optimize`.
|
||||||
* **--apcu:** Use APCu to cache found/not-found classes.
|
* **--apcu:** Use APCu to cache found/not-found classes.
|
||||||
|
@ -781,7 +784,7 @@ Deletes all content from Composer's cache directories.
|
||||||
## licenses
|
## licenses
|
||||||
|
|
||||||
Lists the name, version and license of every package installed. Use
|
Lists the name, version and license of every package installed. Use
|
||||||
`--format=json` to get machine readable output.
|
`--format=json` to get machine-readable output.
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
|
@ -897,7 +900,7 @@ directory to something other than `vendor/bin`.
|
||||||
The `COMPOSER_CACHE_DIR` var allows you to change the Composer cache directory,
|
The `COMPOSER_CACHE_DIR` var allows you to change the Composer cache directory,
|
||||||
which is also configurable via the [`cache-dir`](06-config.md#cache-dir) option.
|
which is also configurable via the [`cache-dir`](06-config.md#cache-dir) option.
|
||||||
|
|
||||||
By default it points to `$COMPOSER_HOME/cache` on \*nix and macOS, and
|
By default, it points to `$COMPOSER_HOME/cache` on \*nix and macOS, and
|
||||||
`C:\Users\<user>\AppData\Local\Composer` (or `%LOCALAPPDATA%/Composer`) on Windows.
|
`C:\Users\<user>\AppData\Local\Composer` (or `%LOCALAPPDATA%/Composer`) on Windows.
|
||||||
|
|
||||||
### COMPOSER_CAFILE
|
### COMPOSER_CAFILE
|
||||||
|
@ -919,7 +922,7 @@ The `COMPOSER_HOME` var allows you to change the Composer home directory. This
|
||||||
is a hidden, global (per-user on the machine) directory that is shared between
|
is a hidden, global (per-user on the machine) directory that is shared between
|
||||||
all projects.
|
all projects.
|
||||||
|
|
||||||
By default it points to `C:\Users\<user>\AppData\Roaming\Composer` on Windows
|
By default, it points to `C:\Users\<user>\AppData\Roaming\Composer` on Windows
|
||||||
and `/Users/<user>/.composer` on macOS. On \*nix systems that follow the [XDG Base
|
and `/Users/<user>/.composer` on macOS. On \*nix systems that follow the [XDG Base
|
||||||
Directory Specifications](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html),
|
Directory Specifications](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html),
|
||||||
it points to `$XDG_CONFIG_HOME/composer`. On other \*nix systems, it points to
|
it points to `$XDG_CONFIG_HOME/composer`. On other \*nix systems, it points to
|
||||||
|
@ -964,8 +967,8 @@ commands) to finish executing. The default value is 300 seconds (5 minutes).
|
||||||
|
|
||||||
### COMPOSER_ROOT_VERSION
|
### COMPOSER_ROOT_VERSION
|
||||||
|
|
||||||
By setting this var you can specify the version of the root package, if it can
|
By setting this var you can specify the version of the root package, if it
|
||||||
not be guessed from VCS info and is not present in `composer.json`.
|
cannot be guessed from VCS info and is not present in `composer.json`.
|
||||||
|
|
||||||
### COMPOSER_VENDOR_DIR
|
### COMPOSER_VENDOR_DIR
|
||||||
|
|
||||||
|
@ -990,13 +993,13 @@ details.
|
||||||
|
|
||||||
### HTTP_PROXY_REQUEST_FULLURI
|
### HTTP_PROXY_REQUEST_FULLURI
|
||||||
|
|
||||||
If you use a proxy but it does not support the request_fulluri flag, then you
|
If you use a proxy, but it does not support the request_fulluri flag, then you
|
||||||
should set this env var to `false` or `0` to prevent Composer from setting the
|
should set this env var to `false` or `0` to prevent Composer from setting the
|
||||||
request_fulluri option.
|
request_fulluri option.
|
||||||
|
|
||||||
### HTTPS_PROXY_REQUEST_FULLURI
|
### HTTPS_PROXY_REQUEST_FULLURI
|
||||||
|
|
||||||
If you use a proxy but it does not support the request_fulluri flag for HTTPS
|
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.
|
||||||
|
|
||||||
|
@ -1019,7 +1022,7 @@ can also set it to `*` to ignore the proxy for all HTTP requests.
|
||||||
If set to `1`, disables network access (best effort). This can be used for debugging or
|
If set to `1`, disables network access (best effort). This can be used for debugging or
|
||||||
to run Composer on a plane or a starship with poor connectivity.
|
to run Composer on a plane or a starship with poor connectivity.
|
||||||
|
|
||||||
If set to `prime`, GitHub VCS repositories will prime the cache so it can then be used
|
If set to `prime`, GitHub VCS repositories will prime the cache, so it can then be used
|
||||||
fully offline with `1`.
|
fully offline with `1`.
|
||||||
|
|
||||||
← [Libraries](02-libraries.md) | [Schema](04-schema.md) →
|
← [Libraries](02-libraries.md) | [Schema](04-schema.md) →
|
||||||
|
|
|
@ -123,7 +123,7 @@ Optional.
|
||||||
|
|
||||||
### homepage
|
### homepage
|
||||||
|
|
||||||
An URL to the website of the project.
|
A URL to the website of the project.
|
||||||
|
|
||||||
Optional.
|
Optional.
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ An Example for disjunctive licenses:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively they can be separated with "or" and enclosed in parenthesis;
|
Alternatively they can be separated with "or" and enclosed in parentheses;
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
@ -192,8 +192,8 @@ Alternatively they can be separated with "or" and enclosed in parenthesis;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Similarly when multiple licenses need to be applied ("conjunctive license"),
|
Similarly, when multiple licenses need to be applied ("conjunctive license"),
|
||||||
they should be separated with "and" and enclosed in parenthesis.
|
they should be separated with "and" and enclosed in parentheses.
|
||||||
|
|
||||||
### authors
|
### authors
|
||||||
|
|
||||||
|
@ -265,8 +265,8 @@ development of new functionality.
|
||||||
|
|
||||||
Each entry consists of the following
|
Each entry consists of the following
|
||||||
|
|
||||||
* **type:** The type of funding or the platform through which funding can be provided, e.g. patreon, opencollective, tidelift or github.
|
* **type:** The type of funding, or the platform through which funding can be provided, e.g. patreon, opencollective, tidelift or github.
|
||||||
* **url:** URL to a website with details and a way to fund the package.
|
* **url:** URL to a website with details, and a way to fund the package.
|
||||||
|
|
||||||
An example:
|
An example:
|
||||||
|
|
||||||
|
@ -934,7 +934,7 @@ It can be boolean or a package name/URL pointing to a recommended alternative.
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
Use `"abandoned": true` to indicates this package is abandoned.
|
Use `"abandoned": true` to indicates this package is abandoned.
|
||||||
Use `"abandoned": "monolog/monolog"` to indicates this package is abandoned and the
|
Use `"abandoned": "monolog/monolog"` to indicates this package is abandoned, and the
|
||||||
recommended alternative is `monolog/monolog`.
|
recommended alternative is `monolog/monolog`.
|
||||||
|
|
||||||
Defaults to false.
|
Defaults to false.
|
||||||
|
@ -949,7 +949,7 @@ that will NOT be handled as feature branches. This is an array of strings.
|
||||||
If you have non-numeric branch names, for example like "latest", "current", "latest-stable"
|
If you have non-numeric branch names, for example like "latest", "current", "latest-stable"
|
||||||
or something, that do not look like a version number, then Composer handles such branches
|
or something, that do not look like a version number, then Composer handles such branches
|
||||||
as feature branches. This means it searches for parent branches, that look like a version
|
as feature branches. This means it searches for parent branches, that look like a version
|
||||||
or ends at special branches (like master) and the root package version number becomes the
|
or ends at special branches (like master), and the root package version number becomes the
|
||||||
version of the parent branch or at least master or something.
|
version of the parent branch or at least master or something.
|
||||||
|
|
||||||
To handle non-numeric named branches as versions instead of searching for a parent branch
|
To handle non-numeric named branches as versions instead of searching for a parent branch
|
||||||
|
|
|
@ -6,7 +6,7 @@ of repositories are available, and how they work.
|
||||||
## Concepts
|
## Concepts
|
||||||
|
|
||||||
Before we look at the different types of repositories that exist, we need to
|
Before we look at the different types of repositories that exist, we need to
|
||||||
understand some of the basic concepts that Composer is built on.
|
understand some basic concepts that Composer is built on.
|
||||||
|
|
||||||
### Package
|
### Package
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ be preferred.
|
||||||
A repository is a package source. It's a list of packages/versions. Composer
|
A repository is a package source. It's a list of packages/versions. Composer
|
||||||
will look in all your repositories to find the packages your project requires.
|
will look in all your repositories to find the packages your project requires.
|
||||||
|
|
||||||
By default only the Packagist.org repository is registered in Composer. You can
|
By default, only the Packagist.org repository is registered in Composer. You can
|
||||||
add more repositories to your project by declaring them in `composer.json`.
|
add more repositories to your project by declaring them in `composer.json`.
|
||||||
|
|
||||||
Repositories are only available to the root package and the repositories
|
Repositories are only available to the root package and the repositories
|
||||||
|
@ -122,7 +122,7 @@ It may include any of the other fields specified in the [schema](04-schema.md).
|
||||||
|
|
||||||
The `notify-batch` field allows you to specify a URL that will be called
|
The `notify-batch` field allows you to specify a URL that will be called
|
||||||
every time a user installs a package. The URL can be either an absolute path
|
every time a user installs a package. The URL can be either an absolute path
|
||||||
(that will use the same domain as the repository) or a fully qualified URL.
|
(that will use the same domain as the repository), or a fully qualified URL.
|
||||||
|
|
||||||
An example value:
|
An example value:
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ from these systems.
|
||||||
|
|
||||||
There are a few use cases for this. The most common one is maintaining your
|
There are a few use cases for this. The most common one is maintaining your
|
||||||
own fork of a third party library. If you are using a certain library for your
|
own fork of a third party library. If you are using a certain library for your
|
||||||
project and you decide to change something in the library, you will want your
|
project, and you decide to change something in the library, you will want your
|
||||||
project to use the patched version. If the library is on GitHub (this is the
|
project to use the patched version. If the library is on GitHub (this is the
|
||||||
case most of the time), you can simply fork it there and push your changes to
|
case most of the time), you can simply fork it there and push your changes to
|
||||||
your fork. After that you update the project's `composer.json`. All you have
|
your fork. After that you update the project's `composer.json`. All you have
|
||||||
|
@ -316,7 +316,7 @@ Please note:
|
||||||
|
|
||||||
#### BitBucket Driver Configuration
|
#### BitBucket Driver Configuration
|
||||||
|
|
||||||
The BitBucket driver uses OAuth to access your private repositories via the BitBucket REST APIs and you will need to create an OAuth consumer to use the driver, please refer to [Atlassian's Documentation](https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html). You will need to fill the callback url with something to satisfy BitBucket, but the address does not need to go anywhere and is not used by Composer.
|
The BitBucket driver uses OAuth to access your private repositories via the BitBucket REST APIs, and you will need to create an OAuth consumer to use the driver, please refer to [Atlassian's Documentation](https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html). You will need to fill the callback url with something to satisfy BitBucket, but the address does not need to go anywhere and is not used by Composer.
|
||||||
|
|
||||||
After creating an OAuth consumer in the BitBucket control panel, you need to setup your auth.json file with
|
After creating an OAuth consumer in the BitBucket control panel, you need to setup your auth.json file with
|
||||||
the credentials like this (more info [here](https://getcomposer.org/doc/06-config.md#bitbucket-oauth)):
|
the credentials like this (more info [here](https://getcomposer.org/doc/06-config.md#bitbucket-oauth)):
|
||||||
|
@ -437,7 +437,7 @@ Here is an example for the smarty template engine:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Typically you would leave the source part off, as you don't really need it.
|
Typically, you would leave the source part off, as you don't really need it.
|
||||||
|
|
||||||
> **Note**: This repository type has a few limitations and should be avoided
|
> **Note**: This repository type has a few limitations and should be avoided
|
||||||
> whenever possible:
|
> whenever possible:
|
||||||
|
|
|
@ -192,14 +192,14 @@ metadata for the `git`/`hg` types and to speed up installs.
|
||||||
|
|
||||||
## cache-files-ttl
|
## cache-files-ttl
|
||||||
|
|
||||||
Defaults to `15552000` (6 months). Composer caches all dist (zip, tar, ..)
|
Defaults to `15552000` (6 months). Composer caches all dist (zip, tar, ...)
|
||||||
packages that it downloads. Those are purged after six months of being unused by
|
packages that it downloads. Those are purged after six months of being unused by
|
||||||
default. This option allows you to tweak this duration (in seconds) or disable
|
default. This option allows you to tweak this duration (in seconds) or disable
|
||||||
it completely by setting it to 0.
|
it completely by setting it to 0.
|
||||||
|
|
||||||
## cache-files-maxsize
|
## cache-files-maxsize
|
||||||
|
|
||||||
Defaults to `300MiB`. Composer caches all dist (zip, tar, ..) packages that it
|
Defaults to `300MiB`. Composer caches all dist (zip, tar, ...) packages that it
|
||||||
downloads. When the garbage collection is periodically ran, this is the maximum
|
downloads. When the garbage collection is periodically ran, this is the maximum
|
||||||
size the cache will be able to use. Older (less used) files will be removed
|
size the cache will be able to use. Older (less used) files will be removed
|
||||||
first until the cache fits.
|
first until the cache fits.
|
||||||
|
|
|
@ -107,5 +107,5 @@ and alias it to `1.0.x-dev`.
|
||||||
> inline-aliased again in A's `composer.json`.
|
> inline-aliased again in A's `composer.json`.
|
||||||
|
|
||||||
> **Note:** Inline aliasing should be avoided, especially for published
|
> **Note:** Inline aliasing should be avoided, especially for published
|
||||||
> packages/libraries. If you found a bug, try and get your fix merged upstream.
|
> packages/libraries. If you found a bug, try to get your fix merged upstream.
|
||||||
> This helps to avoid issues for users of your package.
|
> This helps to avoid issues for users of your package.
|
||||||
|
|
|
@ -48,7 +48,7 @@ There are no real trade-offs with this method. It should always be enabled in
|
||||||
production.
|
production.
|
||||||
|
|
||||||
The only issue is it does not keep track of autoload misses (i.e. when
|
The only issue is it does not keep track of autoload misses (i.e. when
|
||||||
it can not find a given class), so those fallback to PSR-4 rules and can still
|
it cannot find a given class), so those fallback to PSR-4 rules and can still
|
||||||
result in slow filesystem checks. To solve this issue two Level 2 optimization
|
result in slow filesystem checks. To solve this issue two Level 2 optimization
|
||||||
options exist, and you can decide to enable either if you have a lot of
|
options exist, and you can decide to enable either if you have a lot of
|
||||||
class_exists checks that are done for classes that do not exist in your project.
|
class_exists checks that are done for classes that do not exist in your project.
|
||||||
|
@ -78,7 +78,7 @@ also means that in case a class is generated at runtime for some reason, it will
|
||||||
not be allowed to be autoloaded. If your project or any of your dependencies does that
|
not be allowed to be autoloaded. If your project or any of your dependencies does that
|
||||||
then you might experience "class not found" issues in production. Enable this with care.
|
then you might experience "class not found" issues in production. Enable this with care.
|
||||||
|
|
||||||
> Note: This can not be combined with Level 2/B optimizations. You have to choose one as
|
> Note: This cannot be combined with Level 2/B optimizations. You have to choose one as
|
||||||
> they address the same issue in different ways.
|
> they address the same issue in different ways.
|
||||||
|
|
||||||
## Optimization Level 2/B: APCu cache
|
## Optimization Level 2/B: APCu cache
|
||||||
|
@ -97,15 +97,15 @@ This option adds an APCu cache as a fallback for the class map. It will not
|
||||||
automatically generate the class map though, so you should still enable Level 1
|
automatically generate the class map though, so you should still enable Level 1
|
||||||
optimizations manually if you so desire.
|
optimizations manually if you so desire.
|
||||||
|
|
||||||
Whether a class is found or not, that fact is always cached in APCu so it can be
|
Whether a class is found or not, that fact is always cached in APCu, so it can be
|
||||||
returned quickly on the next request.
|
returned quickly on the next request.
|
||||||
|
|
||||||
### Trade-offs
|
### Trade-offs
|
||||||
|
|
||||||
This option requires APCu which may or may not be available to you. It also
|
This option requires APCu which may or may not be available to you. It also
|
||||||
uses APCu memory for autoloading purposes, but it is safe to use and can not
|
uses APCu memory for autoloading purposes, but it is safe to use and cannot
|
||||||
result in classes not being found like the authoritative class map
|
result in classes not being found like the authoritative class map
|
||||||
optimization above.
|
optimization above.
|
||||||
|
|
||||||
> Note: This can not be combined with Level 2/A optimizations. You have to choose one as
|
> Note: This cannot be combined with Level 2/A optimizations. You have to choose one as
|
||||||
> they address the same issue in different ways.
|
> they address the same issue in different ways.
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
## Synopsis
|
## Synopsis
|
||||||
|
|
||||||
At times it may be necessary for a package to require additional actions during
|
At times, it may be necessary for a package to require additional actions during
|
||||||
installation, such as installing packages outside of the default `vendor`
|
installation, such as installing packages outside of the default `vendor`
|
||||||
library.
|
library.
|
||||||
|
|
||||||
|
|
|
@ -159,7 +159,7 @@ Example: `~1.2`
|
||||||
|
|
||||||
### Caret Version Range (^)
|
### Caret Version Range (^)
|
||||||
|
|
||||||
The `^` operator behaves very similarly but it sticks closer to semantic
|
The `^` operator behaves very similarly, but it sticks closer to semantic
|
||||||
versioning, and will always allow non-breaking updates. For example `^1.2.3`
|
versioning, and will always allow non-breaking updates. For example `^1.2.3`
|
||||||
is equivalent to `>=1.2.3 <2.0.0` as none of the releases until 2.0 should
|
is equivalent to `>=1.2.3 <2.0.0` as none of the releases until 2.0 should
|
||||||
break backwards compatibility. For pre-1.0 versions it also acts with safety
|
break backwards compatibility. For pre-1.0 versions it also acts with safety
|
||||||
|
|
|
@ -5,7 +5,7 @@ A version constraint without an upper bound such as `*`, `>=3.4` or
|
||||||
This includes major versions breaking backward compatibility.
|
This includes major versions breaking backward compatibility.
|
||||||
|
|
||||||
Once a release of your package is tagged, you cannot tweak its dependencies
|
Once a release of your package is tagged, you cannot tweak its dependencies
|
||||||
anymore in case a dependency breaks BC - you have to do a new release but the
|
anymore in case a dependency breaks BC - you have to do a new release, but the
|
||||||
previous one stays broken.
|
previous one stays broken.
|
||||||
|
|
||||||
The only good alternative is to define an upper bound on your constraints,
|
The only good alternative is to define an upper bound on your constraints,
|
||||||
|
|
|
@ -24,7 +24,7 @@ their package's packages, etc, then resolve requirements. It could work, but it
|
||||||
slows down the initialization a lot since VCS repos can each take a few seconds,
|
slows down the initialization a lot since VCS repos can each take a few seconds,
|
||||||
and it could end up in a completely broken state since many versions of a package
|
and it could end up in a completely broken state since many versions of a package
|
||||||
could define the same packages inside a package repository, but with different
|
could define the same packages inside a package repository, but with different
|
||||||
dist/source. There are many many ways this could go wrong.
|
dist/source. There are many ways this could go wrong.
|
||||||
|
|
||||||
- Fetch the repositories of root package, then fetch the repositories of the
|
- Fetch the repositories of root package, then fetch the repositories of the
|
||||||
first level dependencies, then fetch the repositories of their dependencies, etc,
|
first level dependencies, then fetch the repositories of their dependencies, etc,
|
||||||
|
|
|
@ -1064,8 +1064,7 @@ INITIALIZER;
|
||||||
$path = preg_replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/')));
|
$path = preg_replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/')));
|
||||||
|
|
||||||
// add support for wildcards * and **
|
// add support for wildcards * and **
|
||||||
$path = str_replace('\\*\\*', '.+?', $path);
|
$path = strtr($path, array('\\*\\*' => '.+?', '\\*' => '[^/]+?'));
|
||||||
$path = str_replace('\\*', '[^/]+?', $path);
|
|
||||||
|
|
||||||
// add support for up-level relative paths
|
// add support for up-level relative paths
|
||||||
$updir = null;
|
$updir = null;
|
||||||
|
|
|
@ -41,6 +41,7 @@ use Composer\Util\Filesystem;
|
||||||
use Composer\Util\ProcessExecutor;
|
use Composer\Util\ProcessExecutor;
|
||||||
use Composer\Util\Loop;
|
use Composer\Util\Loop;
|
||||||
use Composer\Package\Version\VersionParser;
|
use Composer\Package\Version\VersionParser;
|
||||||
|
use Composer\EventDispatcher\EventDispatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install a package as new project into new directory.
|
* Install a package as new project into new directory.
|
||||||
|
@ -69,9 +70,9 @@ class CreateProjectCommand extends BaseCommand
|
||||||
new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'),
|
new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'),
|
||||||
new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
|
new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
|
||||||
new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
|
new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
|
||||||
new InputOption('repository', null, InputOption::VALUE_REQUIRED, 'Pick a different repository (as url or json config) to look for the package.'),
|
new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories to look the package up, either by URL or using JSON arrays'),
|
||||||
new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'DEPRECATED: Use --repository instead.'),
|
new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'DEPRECATED: Use --repository instead.'),
|
||||||
new InputOption('add-repository', null, InputOption::VALUE_NONE, 'Add the repository option to the composer.json.'),
|
new InputOption('add-repository', null, InputOption::VALUE_NONE, 'Add the custom repository in the composer.json. If a lock file is present it will be deleted and an update will be run instead of install.'),
|
||||||
new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
|
new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
|
||||||
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
|
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
|
||||||
new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
|
new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
|
||||||
|
@ -153,39 +154,51 @@ EOT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function installProject(IOInterface $io, Config $config, InputInterface $input, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repository = null, $disablePlugins = false, $noScripts = false, $noProgress = false, $noInstall = false, $ignorePlatformReqs = false, $secureHttp = true, $addRepository = false)
|
public function installProject(IOInterface $io, Config $config, InputInterface $input, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repositories = null, $disablePlugins = false, $noScripts = false, $noProgress = false, $noInstall = false, $ignorePlatformReqs = false, $secureHttp = true, $addRepository = false)
|
||||||
{
|
{
|
||||||
$oldCwd = getcwd();
|
$oldCwd = getcwd();
|
||||||
|
|
||||||
|
if ($repositories !== null && !is_array($repositories)) {
|
||||||
|
$repositories = (array) $repositories;
|
||||||
|
}
|
||||||
|
|
||||||
// we need to manually load the configuration to pass the auth credentials to the io interface!
|
// we need to manually load the configuration to pass the auth credentials to the io interface!
|
||||||
$io->loadConfiguration($config);
|
$io->loadConfiguration($config);
|
||||||
|
|
||||||
$this->suggestedPackagesReporter = new SuggestedPackagesReporter($io);
|
$this->suggestedPackagesReporter = new SuggestedPackagesReporter($io);
|
||||||
|
|
||||||
if ($packageName !== null) {
|
if ($packageName !== null) {
|
||||||
$installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repository, $disablePlugins, $noScripts, $noProgress, $ignorePlatformReqs, $secureHttp);
|
$installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repositories, $disablePlugins, $noScripts, $noProgress, $ignorePlatformReqs, $secureHttp);
|
||||||
} else {
|
} else {
|
||||||
$installedFromVcs = false;
|
$installedFromVcs = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($repositories !== null && $addRepository && is_file('composer.lock')) {
|
||||||
|
unlink('composer.lock');
|
||||||
|
}
|
||||||
|
|
||||||
$composer = Factory::create($io, null, $disablePlugins);
|
$composer = Factory::create($io, null, $disablePlugins);
|
||||||
|
|
||||||
// add the repository to the composer.json and use it for the install run later
|
// add the repository to the composer.json and use it for the install run later
|
||||||
if ($repository !== null && $addRepository) {
|
if ($repositories !== null && $addRepository) {
|
||||||
if ($composer->getLocker()->isLocked()) {
|
foreach ($repositories as $index => $repo) {
|
||||||
$io->writeError('<error>Adding a repository when creating a project that provides a composer.lock file is not supported</error>');
|
$repoConfig = RepositoryFactory::configFromString($io, $composer->getConfig(), $repo, true);
|
||||||
|
$composerJsonRepositoriesConfig = $composer->getConfig()->getRepositories();
|
||||||
|
$name = RepositoryFactory::generateRepositoryName($index, $repoConfig, $composerJsonRepositoriesConfig);
|
||||||
|
$configSource = new JsonConfigSource(new JsonFile('composer.json'));
|
||||||
|
|
||||||
return false;
|
if (
|
||||||
|
(isset($repoConfig['packagist']) && $repoConfig === array('packagist' => false))
|
||||||
|
|| (isset($repoConfig['packagist.org']) && $repoConfig === array('packagist.org' => false))
|
||||||
|
) {
|
||||||
|
$configSource->addRepository('packagist.org', false);
|
||||||
|
} else {
|
||||||
|
$configSource->addRepository($name, $repoConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
$repoConfig = RepositoryFactory::configFromString($io, $composer->getConfig(), $repository, true);
|
|
||||||
$composerJsonRepositoriesConfig = $composer->getConfig()->getRepositories();
|
|
||||||
$name = RepositoryFactory::generateRepositoryName(0, $repoConfig, $composerJsonRepositoriesConfig);
|
|
||||||
$configSource = new JsonConfigSource(new JsonFile('composer.json'));
|
|
||||||
$configSource->addRepository($name, $repoConfig);
|
|
||||||
|
|
||||||
$composer = Factory::create($io, null, $disablePlugins);
|
$composer = Factory::create($io, null, $disablePlugins);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$process = new ProcessExecutor($io);
|
$process = new ProcessExecutor($io);
|
||||||
$fs = new Filesystem($process);
|
$fs = new Filesystem($process);
|
||||||
|
@ -290,18 +303,12 @@ EOT
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function installRootPackage(IOInterface $io, Config $config, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repository = null, $disablePlugins = false, $noScripts = false, $noProgress = false, $ignorePlatformReqs = false, $secureHttp = true)
|
protected function installRootPackage(IOInterface $io, Config $config, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, array $repositories = null, $disablePlugins = false, $noScripts = false, $noProgress = false, $ignorePlatformReqs = false, $secureHttp = true)
|
||||||
{
|
{
|
||||||
if (!$secureHttp) {
|
if (!$secureHttp) {
|
||||||
$config->merge(array('config' => array('secure-http' => false)));
|
$config->merge(array('config' => array('secure-http' => false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null === $repository) {
|
|
||||||
$sourceRepo = new CompositeRepository(RepositoryFactory::defaultRepos($io, $config));
|
|
||||||
} else {
|
|
||||||
$sourceRepo = RepositoryFactory::fromString($io, $config, $repository, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$parser = new VersionParser();
|
$parser = new VersionParser();
|
||||||
$requirements = $parser->parseNameVersionPairs(array($packageName));
|
$requirements = $parser->parseNameVersionPairs(array($packageName));
|
||||||
$name = strtolower($requirements[0]['name']);
|
$name = strtolower($requirements[0]['name']);
|
||||||
|
@ -345,8 +352,25 @@ EOT
|
||||||
throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities)));
|
throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$composer = Factory::create($io, $config->all(), $disablePlugins);
|
||||||
|
$config = $composer->getConfig();
|
||||||
|
$rm = $composer->getRepositoryManager();
|
||||||
|
|
||||||
$repositorySet = new RepositorySet($stability);
|
$repositorySet = new RepositorySet($stability);
|
||||||
$repositorySet->addRepository($sourceRepo);
|
if (null === $repositories) {
|
||||||
|
$repositorySet->addRepository(new CompositeRepository(RepositoryFactory::defaultRepos($io, $config, $rm)));
|
||||||
|
} else {
|
||||||
|
foreach ($repositories as $repo) {
|
||||||
|
$repoConfig = RepositoryFactory::configFromString($io, $config, $repo, true);
|
||||||
|
if (
|
||||||
|
(isset($repoConfig['packagist']) && $repoConfig === array('packagist' => false))
|
||||||
|
|| (isset($repoConfig['packagist.org']) && $repoConfig === array('packagist.org' => false))
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$repositorySet->addRepository(RepositoryFactory::createRepo($io, $config, $repoConfig, $rm));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$platformOverrides = $config->get('platform') ?: array();
|
$platformOverrides = $config->get('platform') ?: array();
|
||||||
$platformRepo = new PlatformRepository(array(), $platformOverrides);
|
$platformRepo = new PlatformRepository(array(), $platformOverrides);
|
||||||
|
@ -388,8 +412,8 @@ EOT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// avoid displaying 9999999-dev as version if dev-master was selected
|
// avoid displaying 9999999-dev as version if default-branch was selected
|
||||||
if ($package instanceof AliasPackage && $package->getPrettyVersion() === VersionParser::DEV_MASTER_ALIAS) {
|
if ($package instanceof AliasPackage && $package->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
|
||||||
$package = $package->getAliasOf();
|
$package = $package->getAliasOf();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,15 +427,12 @@ EOT
|
||||||
$package = $package->getAliasOf();
|
$package = $package->getAliasOf();
|
||||||
}
|
}
|
||||||
|
|
||||||
$factory = new Factory();
|
$dm = $composer->getDownloadManager();
|
||||||
|
|
||||||
$httpDownloader = $factory->createHttpDownloader($io, $config);
|
|
||||||
$dm = $factory->createDownloadManager($io, $config, $httpDownloader, $process);
|
|
||||||
$dm->setPreferSource($preferSource)
|
$dm->setPreferSource($preferSource)
|
||||||
->setPreferDist($preferDist);
|
->setPreferDist($preferDist);
|
||||||
|
|
||||||
$projectInstaller = new ProjectInstaller($directory, $dm, $fs);
|
$projectInstaller = new ProjectInstaller($directory, $dm, $fs);
|
||||||
$im = $factory->createInstallationManager(new Loop($httpDownloader, $process), $io);
|
$im = $composer->getInstallationManager();
|
||||||
$im->setOutputProgress(!$noProgress);
|
$im->setOutputProgress(!$noProgress);
|
||||||
$im->addInstaller($projectInstaller);
|
$im->addInstaller($projectInstaller);
|
||||||
$im->execute(new InstalledFilesystemRepository(new JsonFile('php://memory')), array(new InstallOperation($package)));
|
$im->execute(new InstalledFilesystemRepository(new JsonFile('php://memory')), array(new InstallOperation($package)));
|
||||||
|
|
|
@ -14,6 +14,8 @@ namespace Composer\Command;
|
||||||
|
|
||||||
use Composer\Package\CompletePackageInterface;
|
use Composer\Package\CompletePackageInterface;
|
||||||
use Composer\Package\AliasPackage;
|
use Composer\Package\AliasPackage;
|
||||||
|
use Composer\Package\BasePackage;
|
||||||
|
use Composer\Semver\Constraint\MatchAllConstraint;
|
||||||
use Composer\Repository\CompositeRepository;
|
use Composer\Repository\CompositeRepository;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
@ -39,15 +41,38 @@ class FundCommand extends BaseCommand
|
||||||
$repo = $composer->getRepositoryManager()->getLocalRepository();
|
$repo = $composer->getRepositoryManager()->getLocalRepository();
|
||||||
$remoteRepos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
|
$remoteRepos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
|
||||||
$fundings = array();
|
$fundings = array();
|
||||||
|
|
||||||
|
$packagesToLoad = array();
|
||||||
foreach ($repo->getPackages() as $package) {
|
foreach ($repo->getPackages() as $package) {
|
||||||
if ($package instanceof AliasPackage) {
|
if ($package instanceof AliasPackage) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$latest = $remoteRepos->findPackage($package->getName(), 'dev-master');
|
$packagesToLoad[$package->getName()] = new MatchAllConstraint();
|
||||||
if ($latest instanceof CompletePackageInterface && $latest->getFunding()) {
|
}
|
||||||
$fundings = $this->insertFundingData($fundings, $latest);
|
|
||||||
|
// load all packages dev versions in parallel
|
||||||
|
$result = $remoteRepos->loadPackages($packagesToLoad, array('dev' => BasePackage::STABILITY_DEV), array());
|
||||||
|
|
||||||
|
// collect funding data from default branches
|
||||||
|
foreach ($result['packages'] as $package) {
|
||||||
|
if (
|
||||||
|
!$package instanceof AliasPackage
|
||||||
|
&& $package instanceof CompletePackageInterface
|
||||||
|
&& $package->isDefaultBranch()
|
||||||
|
&& $package->getFunding()
|
||||||
|
&& isset($packagesToLoad[$package->getName()])
|
||||||
|
) {
|
||||||
|
$fundings = $this->insertFundingData($fundings, $package);
|
||||||
|
unset($packagesToLoad[$package->getName()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// collect funding from installed packages if none was found in the default branch above
|
||||||
|
foreach ($repo->getPackages() as $package) {
|
||||||
|
if ($package instanceof AliasPackage || !isset($packagesToLoad[$package->getName()])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($package instanceof CompletePackageInterface && $package->getFunding()) {
|
if ($package instanceof CompletePackageInterface && $package->getFunding()) {
|
||||||
$fundings = $this->insertFundingData($fundings, $package);
|
$fundings = $this->insertFundingData($fundings, $package);
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ EOT
|
||||||
if ($repositories) {
|
if ($repositories) {
|
||||||
$config = Factory::createConfig($io);
|
$config = Factory::createConfig($io);
|
||||||
foreach ($repositories as $repo) {
|
foreach ($repositories as $repo) {
|
||||||
$options['repositories'][] = RepositoryFactory::configFromString($io, $config, $repo);
|
$options['repositories'][] = RepositoryFactory::configFromString($io, $config, $repo, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ EOT
|
||||||
$repos = array(new PlatformRepository);
|
$repos = array(new PlatformRepository);
|
||||||
$createDefaultPackagistRepo = true;
|
$createDefaultPackagistRepo = true;
|
||||||
foreach ($repositories as $repo) {
|
foreach ($repositories as $repo) {
|
||||||
$repoConfig = RepositoryFactory::configFromString($io, $config, $repo);
|
$repoConfig = RepositoryFactory::configFromString($io, $config, $repo, true);
|
||||||
if (
|
if (
|
||||||
(isset($repoConfig['packagist']) && $repoConfig === array('packagist' => false))
|
(isset($repoConfig['packagist']) && $repoConfig === array('packagist' => false))
|
||||||
|| (isset($repoConfig['packagist.org']) && $repoConfig === array('packagist.org' => false))
|
|| (isset($repoConfig['packagist.org']) && $repoConfig === array('packagist.org' => false))
|
||||||
|
|
|
@ -34,7 +34,7 @@ class LicensesCommand extends BaseCommand
|
||||||
->setName('licenses')
|
->setName('licenses')
|
||||||
->setDescription('Shows information about licenses of dependencies.')
|
->setDescription('Shows information about licenses of dependencies.')
|
||||||
->setDefinition(array(
|
->setDefinition(array(
|
||||||
new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
|
new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text, json or summary', 'text'),
|
||||||
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
|
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
|
||||||
))
|
))
|
||||||
->setHelp(
|
->setHelp(
|
||||||
|
@ -113,18 +113,21 @@ EOT
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'summary':
|
case 'summary':
|
||||||
$dependencies = array();
|
$usedLicenses = array();
|
||||||
foreach ($packages as $package) {
|
foreach ($packages as $package) {
|
||||||
$license = $package->getLicense();
|
$license = $package->getLicense();
|
||||||
$licenseName = $license[0];
|
$licenseName = $license[0];
|
||||||
if (!isset($dependencies[$licenseName])) {
|
if (!isset($usedLicenses[$licenseName])) {
|
||||||
$dependencies[$licenseName] = 0;
|
$usedLicenses[$licenseName] = 0;
|
||||||
}
|
}
|
||||||
$dependencies[$licenseName]++;
|
$usedLicenses[$licenseName]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort licenses so that the most used license will appear first
|
||||||
|
arsort($usedLicenses, SORT_NUMERIC);
|
||||||
|
|
||||||
$rows = array();
|
$rows = array();
|
||||||
foreach ($dependencies as $usedLicense => $numberOfDependencies) {
|
foreach ($usedLicenses as $usedLicense => $numberOfDependencies) {
|
||||||
$rows[] = array($usedLicense, $numberOfDependencies);
|
$rows[] = array($usedLicense, $numberOfDependencies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ class OutdatedCommand extends ShowCommand
|
||||||
new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
|
new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
|
||||||
new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
|
new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
|
||||||
new InputOption('ignore', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore specified package(s). Use it with the --outdated option if you don\'t want to be informed about new versions of some packages.'),
|
new InputOption('ignore', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore specified package(s). Use it with the --outdated option if you don\'t want to be informed about new versions of some packages.'),
|
||||||
|
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
|
||||||
))
|
))
|
||||||
->setHelp(
|
->setHelp(
|
||||||
<<<EOT
|
<<<EOT
|
||||||
|
@ -77,6 +78,9 @@ EOT
|
||||||
if ($input->getOption('minor-only')) {
|
if ($input->getOption('minor-only')) {
|
||||||
$args['--minor-only'] = true;
|
$args['--minor-only'] = true;
|
||||||
}
|
}
|
||||||
|
if ($input->getOption('no-dev')) {
|
||||||
|
$args['--no-dev'] = true;
|
||||||
|
}
|
||||||
$args['--format'] = $input->getOption('format');
|
$args['--format'] = $input->getOption('format');
|
||||||
$args['--ignore'] = $input->getOption('ignore');
|
$args['--ignore'] = $input->getOption('ignore');
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ use Composer\Composer;
|
||||||
use Composer\Factory;
|
use Composer\Factory;
|
||||||
use Composer\Config;
|
use Composer\Config;
|
||||||
use Composer\Util\Filesystem;
|
use Composer\Util\Filesystem;
|
||||||
|
use Composer\Util\Platform;
|
||||||
use Composer\SelfUpdate\Keys;
|
use Composer\SelfUpdate\Keys;
|
||||||
use Composer\SelfUpdate\Versions;
|
use Composer\SelfUpdate\Versions;
|
||||||
use Composer\IO\IOInterface;
|
use Composer\IO\IOInterface;
|
||||||
|
@ -106,6 +107,11 @@ EOT
|
||||||
return $this->fetchKeys($io, $config);
|
return $this->fetchKeys($io, $config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensure composer.phar location is accessible
|
||||||
|
if (!file_exists($localFilename)) {
|
||||||
|
throw new FilesystemException('Composer update failed: the "'.$localFilename.'" is not accessible');
|
||||||
|
}
|
||||||
|
|
||||||
// check if current dir is writable and if not try the cache dir from settings
|
// check if current dir is writable and if not try the cache dir from settings
|
||||||
$tmpDir = is_writable(dirname($localFilename)) ? dirname($localFilename) : $cacheDir;
|
$tmpDir = is_writable(dirname($localFilename)) ? dirname($localFilename) : $cacheDir;
|
||||||
|
|
||||||
|
@ -248,10 +254,8 @@ TAGSPUBKEY
|
||||||
$this->cleanBackups($rollbackDir);
|
$this->cleanBackups($rollbackDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($err = $this->setLocalPhar($localFilename, $tempFilename, $backupFile)) {
|
if (!$this->setLocalPhar($localFilename, $tempFilename, $backupFile)) {
|
||||||
@unlink($tempFilename);
|
@unlink($tempFilename);
|
||||||
$io->writeError('<error>The file is corrupted ('.$err->getMessage().').</error>');
|
|
||||||
$io->writeError('<error>Please re-run the self-update command to try again.</error>');
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -331,9 +335,7 @@ TAGSPUBKEY
|
||||||
|
|
||||||
$io = $this->getIO();
|
$io = $this->getIO();
|
||||||
$io->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
|
$io->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
|
||||||
if ($err = $this->setLocalPhar($localFilename, $oldFile)) {
|
if (!$this->setLocalPhar($localFilename, $oldFile)) {
|
||||||
$io->writeError('<error>The backup file was corrupted ('.$err->getMessage().').</error>');
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,37 +343,49 @@ TAGSPUBKEY
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $localFilename
|
* Checks if the downloaded/rollback phar is valid then moves it
|
||||||
* @param string $newFilename
|
*
|
||||||
* @param string $backupTarget
|
* @param string $localFilename The composer.phar location
|
||||||
* @throws \Exception
|
* @param string $newFilename The downloaded or backup phar
|
||||||
* @return \UnexpectedValueException|\PharException|null
|
* @param string $backupTarget The filename to use for the backup
|
||||||
|
* @throws \FilesystemException If the file cannot be moved
|
||||||
|
* @return bool Whether the phar is valid and has been moved
|
||||||
*/
|
*/
|
||||||
protected function setLocalPhar($localFilename, $newFilename, $backupTarget = null)
|
protected function setLocalPhar($localFilename, $newFilename, $backupTarget = null)
|
||||||
{
|
{
|
||||||
try {
|
$io = $this->getIO();
|
||||||
@chmod($newFilename, fileperms($localFilename));
|
@chmod($newFilename, fileperms($localFilename));
|
||||||
if (!ini_get('phar.readonly')) {
|
|
||||||
// test the phar validity
|
// check phar validity
|
||||||
$phar = new \Phar($newFilename);
|
if (!$this->validatePhar($newFilename, $error)) {
|
||||||
// free the variable to unlock the file
|
$io->writeError('<error>The '.($backupTarget ? 'update' : 'backup').' file is corrupted ('.$error.')</error>');
|
||||||
unset($phar);
|
|
||||||
|
if ($backupTarget) {
|
||||||
|
$io->writeError('<error>Please re-run the self-update command to try again.</error>');
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy current file into installations dir
|
return false;
|
||||||
if ($backupTarget && file_exists($localFilename)) {
|
}
|
||||||
|
|
||||||
|
// copy current file into backups dir
|
||||||
|
if ($backupTarget) {
|
||||||
@copy($localFilename, $backupTarget);
|
@copy($localFilename, $backupTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
rename($newFilename, $localFilename);
|
rename($newFilename, $localFilename);
|
||||||
|
|
||||||
return null;
|
return true;
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) {
|
// see if we can run this operation as an Admin on Windows
|
||||||
throw $e;
|
if (!is_writable(dirname($localFilename))
|
||||||
|
&& $io->isInteractive()
|
||||||
|
&& $this->isWindowsNonAdminUser()) {
|
||||||
|
return $this->tryAsWindowsAdmin($localFilename, $newFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $e;
|
$action = 'Composer '.($backupTarget ? 'update' : 'rollback');
|
||||||
|
throw new FilesystemException($action.' failed: "'.$localFilename.'" could not be written.'.PHP_EOL.$e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,4 +428,109 @@ TAGSPUBKEY
|
||||||
|
|
||||||
return $finder;
|
return $finder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the downloaded/backup phar file
|
||||||
|
*
|
||||||
|
* @param string $pharFile The downloaded or backup phar
|
||||||
|
* @param null|string $error Set by method on failure
|
||||||
|
*
|
||||||
|
* Code taken from getcomposer.org/installer. Any changes should be made
|
||||||
|
* there and replicated here
|
||||||
|
*
|
||||||
|
* @return bool If the operation succeeded
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
protected function validatePhar($pharFile, &$error)
|
||||||
|
{
|
||||||
|
if (ini_get('phar.readonly')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Test the phar validity
|
||||||
|
$phar = new \Phar($pharFile);
|
||||||
|
// Free the variable to unlock the file
|
||||||
|
unset($phar);
|
||||||
|
$result = true;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) {
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
$error = $e->getMessage();
|
||||||
|
$result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this is a non-admin Windows user account
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isWindowsNonAdminUser()
|
||||||
|
{
|
||||||
|
if (!Platform::isWindows()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fltmc.exe manages filter drivers and errors without admin privileges
|
||||||
|
exec('fltmc.exe filters', $output, $exitCode);
|
||||||
|
|
||||||
|
return $exitCode !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes a UAC prompt to update composer.phar as an admin
|
||||||
|
*
|
||||||
|
* Uses a .vbs script to elevate and run the cmd.exe move command.
|
||||||
|
*
|
||||||
|
* @param string $localFilename The composer.phar location
|
||||||
|
* @param string $newFilename The downloaded or backup phar
|
||||||
|
* @return bool Whether composer.phar has been updated
|
||||||
|
*/
|
||||||
|
protected function tryAsWindowsAdmin($localFilename, $newFilename)
|
||||||
|
{
|
||||||
|
$io = $this->getIO();
|
||||||
|
|
||||||
|
$io->writeError('<error>Unable to write "'.$localFilename.'". Access is denied.</error>');
|
||||||
|
$helpMessage = 'Please run the self-update command as an Administrator.';
|
||||||
|
$question = 'Complete this operation with Administrator privileges [<comment>Y,n</comment>]? ';
|
||||||
|
|
||||||
|
if (!$io->askConfirmation($question, false)) {
|
||||||
|
$io->writeError('<warning>Operation cancelled. '.$helpMessage.'</warning>');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tmpFile = tempnam(sys_get_temp_dir(), '');
|
||||||
|
$script = $tmpFile.'.vbs';
|
||||||
|
rename($tmpFile, $script);
|
||||||
|
|
||||||
|
$checksum = hash_file('sha256', $newFilename);
|
||||||
|
|
||||||
|
// cmd's internal move is fussy about backslashes
|
||||||
|
$source = str_replace('/', '\\', $newFilename);
|
||||||
|
$destination = str_replace('/', '\\', $localFilename);
|
||||||
|
|
||||||
|
$vbs = <<<EOT
|
||||||
|
Set UAC = CreateObject("Shell.Application")
|
||||||
|
UAC.ShellExecute "cmd.exe", "/c move /y ""$source"" ""$destination""", "", "runas", 0
|
||||||
|
Wscript.Sleep(300)
|
||||||
|
EOT;
|
||||||
|
|
||||||
|
file_put_contents($script, $vbs);
|
||||||
|
exec('"'.$script.'"');
|
||||||
|
@unlink($script);
|
||||||
|
|
||||||
|
// see if the file was moved
|
||||||
|
if ($result = (hash_file('sha256', $localFilename) === $checksum)) {
|
||||||
|
$io->writeError('<info>Operation succeeded.</info>');
|
||||||
|
} else {
|
||||||
|
$io->writeError('<error>Operation failed (file not written). '.$helpMessage.'</error>');
|
||||||
|
};
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ use Composer\Package\Version\VersionParser;
|
||||||
use Composer\Package\Version\VersionSelector;
|
use Composer\Package\Version\VersionSelector;
|
||||||
use Composer\Plugin\CommandEvent;
|
use Composer\Plugin\CommandEvent;
|
||||||
use Composer\Plugin\PluginEvents;
|
use Composer\Plugin\PluginEvents;
|
||||||
|
use Composer\Repository\InstalledArrayRepository;
|
||||||
use Composer\Repository\ComposerRepository;
|
use Composer\Repository\ComposerRepository;
|
||||||
use Composer\Repository\CompositeRepository;
|
use Composer\Repository\CompositeRepository;
|
||||||
use Composer\Repository\PlatformRepository;
|
use Composer\Repository\PlatformRepository;
|
||||||
|
@ -81,6 +82,7 @@ class ShowCommand extends BaseCommand
|
||||||
new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
|
new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
|
||||||
new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
|
new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
|
||||||
new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
|
new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
|
||||||
|
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
|
||||||
))
|
))
|
||||||
->setHelp(
|
->setHelp(
|
||||||
<<<EOT
|
<<<EOT
|
||||||
|
@ -175,7 +177,7 @@ EOT
|
||||||
$localRepo = $composer->getRepositoryManager()->getLocalRepository();
|
$localRepo = $composer->getRepositoryManager()->getLocalRepository();
|
||||||
$locker = $composer->getLocker();
|
$locker = $composer->getLocker();
|
||||||
if ($locker->isLocked()) {
|
if ($locker->isLocked()) {
|
||||||
$lockedRepo = $locker->getLockedRepository();
|
$lockedRepo = $locker->getLockedRepository(true);
|
||||||
$installedRepo = new InstalledRepository(array($lockedRepo, $localRepo, $platformRepo));
|
$installedRepo = new InstalledRepository(array($lockedRepo, $localRepo, $platformRepo));
|
||||||
} else {
|
} else {
|
||||||
$installedRepo = new InstalledRepository(array($localRepo, $platformRepo));
|
$installedRepo = new InstalledRepository(array($localRepo, $platformRepo));
|
||||||
|
@ -191,12 +193,22 @@ EOT
|
||||||
throw new \UnexpectedValueException('A valid composer.json and composer.lock files is required to run this command with --locked');
|
throw new \UnexpectedValueException('A valid composer.json and composer.lock files is required to run this command with --locked');
|
||||||
}
|
}
|
||||||
$locker = $composer->getLocker();
|
$locker = $composer->getLocker();
|
||||||
$lockedRepo = $locker->getLockedRepository();
|
$lockedRepo = $locker->getLockedRepository(true);
|
||||||
$installedRepo = new InstalledRepository(array($lockedRepo));
|
$installedRepo = new InstalledRepository(array($lockedRepo));
|
||||||
$repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
|
$repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
|
||||||
} else {
|
} else {
|
||||||
$repos = $installedRepo = new InstalledRepository(array($this->getComposer()->getRepositoryManager()->getLocalRepository()));
|
// --installed / default case
|
||||||
$rootPkg = $this->getComposer()->getPackage();
|
if (!$composer) {
|
||||||
|
$composer = $this->getComposer();
|
||||||
|
}
|
||||||
|
$rootPkg = $composer->getPackage();
|
||||||
|
$repos = $installedRepo = new InstalledRepository(array($composer->getRepositoryManager()->getLocalRepository()));
|
||||||
|
|
||||||
|
if ($input->getOption('no-dev')) {
|
||||||
|
$packages = $this->filterRequiredPackages($installedRepo, $rootPkg);
|
||||||
|
$repos = $installedRepo = new InstalledRepository(array(new InstalledArrayRepository(array_map(function ($pkg) { return clone $pkg; }, $packages))));
|
||||||
|
}
|
||||||
|
|
||||||
if (!$installedRepo->getPackages() && ($rootPkg->getRequires() || $rootPkg->getDevRequires())) {
|
if (!$installedRepo->getPackages() && ($rootPkg->getRequires() || $rootPkg->getDevRequires())) {
|
||||||
$io->writeError('<warning>No dependencies installed. Try running composer install or update.</warning>');
|
$io->writeError('<warning>No dependencies installed. Try running composer install or update.</warning>');
|
||||||
}
|
}
|
||||||
|
@ -248,7 +260,7 @@ EOT
|
||||||
} else {
|
} else {
|
||||||
$latestPackage = null;
|
$latestPackage = null;
|
||||||
if ($input->getOption('latest')) {
|
if ($input->getOption('latest')) {
|
||||||
$latestPackage = $this->findLatestPackage($package, $composer, $platformRepo);
|
$latestPackage = $this->findLatestPackage($package, $composer, $platformRepo, $input->getOption('minor-only'));
|
||||||
}
|
}
|
||||||
if ($input->getOption('outdated') && $input->getOption('strict') && $latestPackage && $latestPackage->getFullPrettyVersion() !== $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
|
if ($input->getOption('outdated') && $input->getOption('strict') && $latestPackage && $latestPackage->getFullPrettyVersion() !== $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
|
||||||
$exitCode = 1;
|
$exitCode = 1;
|
||||||
|
@ -299,8 +311,9 @@ EOT
|
||||||
|
|
||||||
// list packages
|
// list packages
|
||||||
$packages = array();
|
$packages = array();
|
||||||
|
$packageFilterRegex = null;
|
||||||
if (null !== $packageFilter) {
|
if (null !== $packageFilter) {
|
||||||
$packageFilter = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i';
|
$packageFilterRegex = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i';
|
||||||
}
|
}
|
||||||
|
|
||||||
$packageListFilter = array();
|
$packageListFilter = array();
|
||||||
|
@ -342,18 +355,16 @@ EOT
|
||||||
$type = 'available';
|
$type = 'available';
|
||||||
}
|
}
|
||||||
if ($repo instanceof ComposerRepository) {
|
if ($repo instanceof ComposerRepository) {
|
||||||
foreach ($repo->getPackageNames() as $name) {
|
foreach ($repo->getPackageNames($packageFilter) as $name) {
|
||||||
if (!$packageFilter || preg_match($packageFilter, $name)) {
|
|
||||||
$packages[$type][$name] = $name;
|
$packages[$type][$name] = $name;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
foreach ($repo->getPackages() as $package) {
|
foreach ($repo->getPackages() as $package) {
|
||||||
if (!isset($packages[$type][$package->getName()])
|
if (!isset($packages[$type][$package->getName()])
|
||||||
|| !is_object($packages[$type][$package->getName()])
|
|| !is_object($packages[$type][$package->getName()])
|
||||||
|| version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')
|
|| version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')
|
||||||
) {
|
) {
|
||||||
if (!$packageFilter || preg_match($packageFilter, $package->getName())) {
|
if (!$packageFilterRegex || preg_match($packageFilterRegex, $package->getName())) {
|
||||||
if (!$packageListFilter || in_array($package->getName(), $packageListFilter, true)) {
|
if (!$packageListFilter || in_array($package->getName(), $packageListFilter, true)) {
|
||||||
$packages[$type][$package->getName()] = $package;
|
$packages[$type][$package->getName()] = $package;
|
||||||
}
|
}
|
||||||
|
@ -568,6 +579,7 @@ EOT
|
||||||
$matchedPackage = null;
|
$matchedPackage = null;
|
||||||
$versions = array();
|
$versions = array();
|
||||||
$matches = $repositorySet->findPackages($name, $constraint);
|
$matches = $repositorySet->findPackages($name, $constraint);
|
||||||
|
$pool = $repositorySet->createPoolForPackage($name);
|
||||||
foreach ($matches as $index => $package) {
|
foreach ($matches as $index => $package) {
|
||||||
// select an exact match if it is in the installed repo and no specific version was required
|
// select an exact match if it is in the installed repo and no specific version was required
|
||||||
if (null === $version && $installedRepo->hasPackage($package)) {
|
if (null === $version && $installedRepo->hasPackage($package)) {
|
||||||
|
@ -578,8 +590,6 @@ EOT
|
||||||
$matches[$index] = $package->getId();
|
$matches[$index] = $package->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
$pool = $repositorySet->createPoolForPackage($name);
|
|
||||||
|
|
||||||
// select preferred package according to policy rules
|
// select preferred package according to policy rules
|
||||||
if (!$matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, $matches)) {
|
if (!$matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, $matches)) {
|
||||||
$matchedPackage = $pool->literalToPackage($preferred[0]);
|
$matchedPackage = $pool->literalToPackage($preferred[0]);
|
||||||
|
@ -1223,4 +1233,31 @@ EOT
|
||||||
|
|
||||||
return $this->repositorySet;
|
return $this->repositorySet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find package requires and child requires
|
||||||
|
*
|
||||||
|
* @param RepositoryInterface $repo
|
||||||
|
* @param PackageInterface $package
|
||||||
|
* @param array $bucket
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function filterRequiredPackages(RepositoryInterface $repo, PackageInterface $package, $bucket = array())
|
||||||
|
{
|
||||||
|
$requires = $package->getRequires();
|
||||||
|
|
||||||
|
foreach ($repo->getPackages() as $candidate) {
|
||||||
|
foreach ($candidate->getNames() as $name) {
|
||||||
|
if (isset($requires[$name])) {
|
||||||
|
if (!in_array($candidate, $bucket, true)) {
|
||||||
|
$bucket[] = $candidate;
|
||||||
|
$bucket = $this->filterRequiredPackages($repo, $candidate, $bucket);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bucket;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,13 @@ class Application extends BaseApplication
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$shutdownRegistered) {
|
if (!$shutdownRegistered) {
|
||||||
|
if (function_exists('pcntl_async_signals') && function_exists('pcntl_signal')) {
|
||||||
|
pcntl_async_signals(true);
|
||||||
|
pcntl_signal(SIGINT, function ($sig) {
|
||||||
|
exit(130);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
$shutdownRegistered = true;
|
$shutdownRegistered = true;
|
||||||
|
|
||||||
register_shutdown_function(function () {
|
register_shutdown_function(function () {
|
||||||
|
|
|
@ -23,6 +23,7 @@ use Composer\Semver\Constraint\Constraint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nils Adermann <naderman@naderman.de>
|
* @author Nils Adermann <naderman@naderman.de>
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class LocalRepoTransaction extends Transaction
|
class LocalRepoTransaction extends Transaction
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,6 +22,7 @@ use Composer\Test\Repository\ArrayRepositoryTest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nils Adermann <naderman@naderman.de>
|
* @author Nils Adermann <naderman@naderman.de>
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class LockTransaction extends Transaction
|
class LockTransaction extends Transaction
|
||||||
{
|
{
|
||||||
|
|
|
@ -189,4 +189,15 @@ class Pool implements \Countable
|
||||||
{
|
{
|
||||||
return \in_array($package, $this->unacceptableFixedPackages, true);
|
return \in_array($package, $this->unacceptableFixedPackages, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
$str = "Pool:\n";
|
||||||
|
|
||||||
|
foreach ($this->packages as $package) {
|
||||||
|
$str .= '- '.str_pad($package->id, 6, ' ', STR_PAD_LEFT).': '.$package->getName()."\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $str;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,9 +99,9 @@ class PoolBuilder
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int[] $acceptableStabilities array of stability => BasePackage::STABILITY_* value
|
* @param int[] $acceptableStabilities array of stability => BasePackage::STABILITY_* value
|
||||||
* @psalm-param array<string, int> $acceptableStabilities
|
* @psalm-param array<string, BasePackage::STABILITY_*> $acceptableStabilities
|
||||||
* @param int[] $stabilityFlags an array of package name => BasePackage::STABILITY_* value
|
* @param int[] $stabilityFlags an array of package name => BasePackage::STABILITY_* value
|
||||||
* @psalm-param array<string, int> $stabilityFlags
|
* @psalm-param array<string, BasePackage::STABILITY_*> $stabilityFlags
|
||||||
* @param array[] $rootAliases
|
* @param array[] $rootAliases
|
||||||
* @psalm-param array<string, array<string, array{alias: string, alias_normalized: string}>> $rootAliases
|
* @psalm-param array<string, array<string, array{alias: string, alias_normalized: string}>> $rootAliases
|
||||||
* @param string[] $rootReferences an array of package name => source reference
|
* @param string[] $rootReferences an array of package name => source reference
|
||||||
|
|
|
@ -329,14 +329,18 @@ class Problem
|
||||||
public static function getPackageList(array $packages, $isVerbose)
|
public static function getPackageList(array $packages, $isVerbose)
|
||||||
{
|
{
|
||||||
$prepared = array();
|
$prepared = array();
|
||||||
|
$hasDefaultBranch = array();
|
||||||
foreach ($packages as $package) {
|
foreach ($packages as $package) {
|
||||||
$prepared[$package->getName()]['name'] = $package->getPrettyName();
|
$prepared[$package->getName()]['name'] = $package->getPrettyName();
|
||||||
$prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion().($package instanceof AliasPackage ? ' (alias of '.$package->getAliasOf()->getPrettyVersion().')' : '');
|
$prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion().($package instanceof AliasPackage ? ' (alias of '.$package->getAliasOf()->getPrettyVersion().')' : '');
|
||||||
|
if ($package->isDefaultBranch()) {
|
||||||
|
$hasDefaultBranch[$package->getName()] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
foreach ($prepared as $name => $package) {
|
foreach ($prepared as $name => $package) {
|
||||||
// remove the implicit dev-master alias to avoid cruft in the display
|
// remove the implicit default branch alias to avoid cruft in the display
|
||||||
if (isset($package['versions'][VersionParser::DEV_MASTER_ALIAS]) && isset($package['versions']['dev-master'])) {
|
if (isset($package['versions'][VersionParser::DEFAULT_BRANCH_ALIAS]) && isset($hasDefaultBranch[$name])) {
|
||||||
unset($package['versions'][VersionParser::DEV_MASTER_ALIAS]);
|
unset($package['versions'][VersionParser::DEFAULT_BRANCH_ALIAS]);
|
||||||
}
|
}
|
||||||
|
|
||||||
uksort($package['versions'], 'version_compare');
|
uksort($package['versions'], 'version_compare');
|
||||||
|
|
|
@ -183,7 +183,7 @@ abstract class Rule
|
||||||
return 'Root composer.json requires '.$packageName.($constraint ? ' '.$constraint->getPrettyString() : '').' -> satisfiable by '.$this->formatPackagesUnique($pool, $packages, $isVerbose).'.';
|
return 'Root composer.json requires '.$packageName.($constraint ? ' '.$constraint->getPrettyString() : '').' -> satisfiable by '.$this->formatPackagesUnique($pool, $packages, $isVerbose).'.';
|
||||||
|
|
||||||
case self::RULE_FIXED:
|
case self::RULE_FIXED:
|
||||||
$package = $this->deduplicateMasterAlias($this->reasonData['package']);
|
$package = $this->deduplicateDefaultBranchAlias($this->reasonData['package']);
|
||||||
if ($this->reasonData['lockable']) {
|
if ($this->reasonData['lockable']) {
|
||||||
return $package->getPrettyName().' is locked to version '.$package->getPrettyVersion().' and an update of this package was not requested.';
|
return $package->getPrettyName().' is locked to version '.$package->getPrettyVersion().' and an update of this package was not requested.';
|
||||||
}
|
}
|
||||||
|
@ -191,14 +191,14 @@ abstract class Rule
|
||||||
return $package->getPrettyName().' is present at version '.$package->getPrettyVersion() . ' and cannot be modified by Composer';
|
return $package->getPrettyName().' is present at version '.$package->getPrettyVersion() . ' and cannot be modified by Composer';
|
||||||
|
|
||||||
case self::RULE_PACKAGE_CONFLICT:
|
case self::RULE_PACKAGE_CONFLICT:
|
||||||
$package1 = $this->deduplicateMasterAlias($pool->literalToPackage($literals[0]));
|
$package1 = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[0]));
|
||||||
$package2 = $this->deduplicateMasterAlias($pool->literalToPackage($literals[1]));
|
$package2 = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[1]));
|
||||||
|
|
||||||
return $package2->getPrettyString().' conflicts with '.$package1->getPrettyString().'.';
|
return $package2->getPrettyString().' conflicts with '.$package1->getPrettyString().'.';
|
||||||
|
|
||||||
case self::RULE_PACKAGE_REQUIRES:
|
case self::RULE_PACKAGE_REQUIRES:
|
||||||
$sourceLiteral = array_shift($literals);
|
$sourceLiteral = array_shift($literals);
|
||||||
$sourcePackage = $this->deduplicateMasterAlias($pool->literalToPackage($sourceLiteral));
|
$sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral));
|
||||||
|
|
||||||
$requires = array();
|
$requires = array();
|
||||||
foreach ($literals as $literal) {
|
foreach ($literals as $literal) {
|
||||||
|
@ -281,7 +281,7 @@ abstract class Rule
|
||||||
$group = $literal > 0 ? 'install' : 'don\'t install';
|
$group = $literal > 0 ? 'install' : 'don\'t install';
|
||||||
}
|
}
|
||||||
|
|
||||||
$groups[$group][] = $this->deduplicateMasterAlias($package);
|
$groups[$group][] = $this->deduplicateDefaultBranchAlias($package);
|
||||||
}
|
}
|
||||||
$ruleTexts = array();
|
$ruleTexts = array();
|
||||||
foreach ($groups as $group => $packages) {
|
foreach ($groups as $group => $packages) {
|
||||||
|
@ -295,10 +295,10 @@ abstract class Rule
|
||||||
case self::RULE_PACKAGE_ALIAS:
|
case self::RULE_PACKAGE_ALIAS:
|
||||||
$aliasPackage = $pool->literalToPackage($literals[0]);
|
$aliasPackage = $pool->literalToPackage($literals[0]);
|
||||||
// avoid returning content like "9999999-dev is an alias of dev-master" as it is useless
|
// avoid returning content like "9999999-dev is an alias of dev-master" as it is useless
|
||||||
if ($aliasPackage->getVersion() === VersionParser::DEV_MASTER_ALIAS) {
|
if ($aliasPackage->getVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
$package = $this->deduplicateMasterAlias($pool->literalToPackage($literals[1]));
|
$package = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[1]));
|
||||||
|
|
||||||
return $aliasPackage->getPrettyString() .' is an alias of '.$package->getPrettyString().' and thus requires it to be installed too.';
|
return $aliasPackage->getPrettyString() .' is an alias of '.$package->getPrettyString().' and thus requires it to be installed too.';
|
||||||
default:
|
default:
|
||||||
|
@ -342,9 +342,9 @@ abstract class Rule
|
||||||
return $names;
|
return $names;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function deduplicateMasterAlias(PackageInterface $package)
|
private function deduplicateDefaultBranchAlias(PackageInterface $package)
|
||||||
{
|
{
|
||||||
if ($package instanceof AliasPackage && $package->getPrettyVersion() === VersionParser::DEV_MASTER_ALIAS) {
|
if ($package instanceof AliasPackage && $package->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
|
||||||
$package = $package->getAliasOf();
|
$package = $package->getAliasOf();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace Composer\DependencyResolver;
|
||||||
use Composer\IO\IOInterface;
|
use Composer\IO\IOInterface;
|
||||||
use Composer\Package\PackageInterface;
|
use Composer\Package\PackageInterface;
|
||||||
use Composer\Repository\PlatformRepository;
|
use Composer\Repository\PlatformRepository;
|
||||||
|
use Composer\Semver\Constraint\MultiConstraint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nils Adermann <naderman@naderman.de>
|
* @author Nils Adermann <naderman@naderman.de>
|
||||||
|
@ -385,6 +386,11 @@ class Solver
|
||||||
$this->learnedPool[\count($this->learnedPool) - 1][] = $rule;
|
$this->learnedPool[\count($this->learnedPool) - 1][] = $rule;
|
||||||
|
|
||||||
foreach ($rule->getLiterals() as $literal) {
|
foreach ($rule->getLiterals() as $literal) {
|
||||||
|
// multiconflictrule is really a bunch of rules in one, so some may not have finished propagating yet
|
||||||
|
if ($rule instanceof MultiConflictRule && !$this->decisions->decided($literal)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// skip the one true literal
|
// skip the one true literal
|
||||||
if ($this->decisions->satisfy($literal)) {
|
if ($this->decisions->satisfy($literal)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -459,6 +465,35 @@ class Solver
|
||||||
$l1num++;
|
$l1num++;
|
||||||
$l1retry = true;
|
$l1retry = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$decision = $this->decisions->atOffset($decisionId);
|
||||||
|
$rule = $decision[Decisions::DECISION_REASON];
|
||||||
|
|
||||||
|
if ($rule instanceof MultiConflictRule) {
|
||||||
|
// there is only ever exactly one positive decision in a multiconflict rule
|
||||||
|
foreach ($rule->getLiterals() as $literal) {
|
||||||
|
if (!isset($seen[abs($literal)]) && $this->decisions->satisfy(-$literal)) {
|
||||||
|
$this->learnedPool[\count($this->learnedPool) - 1][] = $rule;
|
||||||
|
$l = $this->decisions->decisionLevel($literal);
|
||||||
|
if (1 === $l) {
|
||||||
|
$l1num++;
|
||||||
|
} elseif ($level === $l) {
|
||||||
|
$num++;
|
||||||
|
} else {
|
||||||
|
// not level1 or conflict level, add to new rule
|
||||||
|
$learnedLiterals[] = $literal;
|
||||||
|
|
||||||
|
if ($l > $ruleLevel) {
|
||||||
|
$ruleLevel = $l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$seen[abs($literal)] = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$l1retry = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$decision = $this->decisions->atOffset($decisionId);
|
$decision = $this->decisions->atOffset($decisionId);
|
||||||
|
|
|
@ -19,6 +19,7 @@ use Composer\Repository\PlatformRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nils Adermann <naderman@naderman.de>
|
* @author Nils Adermann <naderman@naderman.de>
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class Transaction
|
class Transaction
|
||||||
{
|
{
|
||||||
|
|
|
@ -69,18 +69,29 @@ class Factory
|
||||||
}
|
}
|
||||||
|
|
||||||
$userDir = self::getUserDir();
|
$userDir = self::getUserDir();
|
||||||
if (is_dir($userDir . '/.composer')) {
|
$dirs = array();
|
||||||
return $userDir . '/.composer';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self::useXdg()) {
|
if (self::useXdg()) {
|
||||||
// XDG Base Directory Specifications
|
// XDG Base Directory Specifications
|
||||||
$xdgConfig = getenv('XDG_CONFIG_HOME') ?: $userDir . '/.config';
|
$xdgConfig = getenv('XDG_CONFIG_HOME');
|
||||||
|
if (!$xdgConfig) {
|
||||||
return $xdgConfig . '/composer';
|
$xdgConfig = $userDir . '/.config';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $userDir . '/.composer';
|
$dirs[] = $xdgConfig . '/composer';
|
||||||
|
}
|
||||||
|
|
||||||
|
$dirs[] = $userDir . '/.composer';
|
||||||
|
|
||||||
|
// select first dir which exists of: $XDG_CONFIG_HOME/composer or ~/.composer
|
||||||
|
foreach ($dirs as $dir) {
|
||||||
|
if (is_dir($dir)) {
|
||||||
|
return $dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if none exists, we default to first defined one (XDG one if system uses it, or ~/.composer otherwise)
|
||||||
|
return $dirs[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -644,6 +655,10 @@ class Factory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_dir('/etc/xdg')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -176,7 +176,7 @@ class AliasPackage extends BasePackage implements CompletePackageInterface
|
||||||
{
|
{
|
||||||
// for self.version requirements, we use the original package's branch name instead, to avoid leaking the magic dev-master-alias to users
|
// for self.version requirements, we use the original package's branch name instead, to avoid leaking the magic dev-master-alias to users
|
||||||
$prettyVersion = $this->prettyVersion;
|
$prettyVersion = $this->prettyVersion;
|
||||||
if ($prettyVersion === VersionParser::DEV_MASTER_ALIAS) {
|
if ($prettyVersion === VersionParser::DEFAULT_BRANCH_ALIAS) {
|
||||||
$prettyVersion = $this->aliasOf->getPrettyVersion();
|
$prettyVersion = $this->aliasOf->getPrettyVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,8 +90,8 @@ class ArrayLoader implements LoaderInterface
|
||||||
if (isset($config['version_normalized'])) {
|
if (isset($config['version_normalized'])) {
|
||||||
$version = $config['version_normalized'];
|
$version = $config['version_normalized'];
|
||||||
|
|
||||||
// handling of existing repos which need to remain composer v1 compatible, in case the version_normalized contained VersionParser::DEV_MASTER_ALIAS, we renormalize it
|
// handling of existing repos which need to remain composer v1 compatible, in case the version_normalized contained VersionParser::DEFAULT_BRANCH_ALIAS, we renormalize it
|
||||||
if ($version === VersionParser::DEV_MASTER_ALIAS) {
|
if ($version === VersionParser::DEFAULT_BRANCH_ALIAS) {
|
||||||
$version = $this->versionParser->normalize($config['version']);
|
$version = $this->versionParser->normalize($config['version']);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -369,7 +369,7 @@ class ArrayLoader implements LoaderInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($config['default-branch']) && $config['default-branch'] === true) {
|
if (isset($config['default-branch']) && $config['default-branch'] === true) {
|
||||||
return VersionParser::DEV_MASTER_ALIAS;
|
return VersionParser::DEFAULT_BRANCH_ALIAS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,11 +110,6 @@ class RootPackageLoader extends ArrayLoader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$defaultBranch = $this->versionGuesser->getDefaultBranchName($cwd ?: getcwd());
|
|
||||||
if ($defaultBranch && $config['version'] === 'dev-'.$defaultBranch) {
|
|
||||||
$config['default-branch'] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$realPackage = $package = parent::load($config, $class);
|
$realPackage = $package = parent::load($config, $class);
|
||||||
if ($realPackage instanceof AliasPackage) {
|
if ($realPackage instanceof AliasPackage) {
|
||||||
$realPackage = $package->getAliasOf();
|
$realPackage = $package->getAliasOf();
|
||||||
|
|
|
@ -22,6 +22,12 @@ class StabilityFilter
|
||||||
/**
|
/**
|
||||||
* Checks if any of the provided package names in the given stability match the configured acceptable stability and flags
|
* Checks if any of the provided package names in the given stability match the configured acceptable stability and flags
|
||||||
*
|
*
|
||||||
|
* @param int[] $acceptableStabilities array of stability => BasePackage::STABILITY_* value
|
||||||
|
* @psalm-param array<string, BasePackage::STABILITY_*> $acceptableStabilities
|
||||||
|
* @param int[] $stabilityFlags an array of package name => BasePackage::STABILITY_* value
|
||||||
|
* @psalm-param array<string, BasePackage::STABILITY_*> $stabilityFlags
|
||||||
|
* @param string[] $names The package name(s) to check for stability flags
|
||||||
|
* @param string $stability one of 'stable', 'RC', 'beta', 'alpha' or 'dev'
|
||||||
* @return bool true if any package name is acceptable
|
* @return bool true if any package name is acceptable
|
||||||
*/
|
*/
|
||||||
public static function isPackageAcceptable(array $acceptableStabilities, array $stabilityFlags, $names, $stability)
|
public static function isPackageAcceptable(array $acceptableStabilities, array $stabilityFlags, $names, $stability)
|
||||||
|
|
|
@ -111,43 +111,6 @@ class VersionGuesser
|
||||||
return $versionData;
|
return $versionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to find name of default branch from VCS info
|
|
||||||
*
|
|
||||||
* @param string $path Path to guess into
|
|
||||||
*/
|
|
||||||
public function getDefaultBranchName($path)
|
|
||||||
{
|
|
||||||
if (version_compare(GitUtil::getVersion($this->process), '2.3.0-rc0', '>=')) {
|
|
||||||
GitUtil::cleanEnv();
|
|
||||||
$oldVal = getenv('GIT_SSH_COMMAND');
|
|
||||||
putenv("GIT_SSH_COMMAND=ssh".(Platform::isWindows() ? '.exe' : '')." -o StrictHostKeyChecking=yes");
|
|
||||||
$hasGitRemote = 0 === $this->process->execute('git remote show origin', $output, $path);
|
|
||||||
if ($oldVal) {
|
|
||||||
putenv("GIT_SSH_COMMAND=$oldVal");
|
|
||||||
} else {
|
|
||||||
putenv("GIT_SSH_COMMAND");
|
|
||||||
}
|
|
||||||
if ($hasGitRemote && preg_match('{^ HEAD branch: (.+)$}m', $output, $match)) {
|
|
||||||
return trim($match[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_dir($path.'/.git')) {
|
|
||||||
return 'master';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_dir($path.'/.hg')) {
|
|
||||||
return 'default';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_dir($path.'/.svn')) {
|
|
||||||
return 'trunk';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function guessGitVersion(array $packageConfig, $path)
|
private function guessGitVersion(array $packageConfig, $path)
|
||||||
{
|
{
|
||||||
GitUtil::cleanEnv();
|
GitUtil::cleanEnv();
|
||||||
|
@ -174,7 +137,7 @@ class VersionGuesser
|
||||||
} else {
|
} else {
|
||||||
$version = $this->versionParser->normalizeBranch($match[1]);
|
$version = $this->versionParser->normalizeBranch($match[1]);
|
||||||
$prettyVersion = 'dev-' . $match[1];
|
$prettyVersion = 'dev-' . $match[1];
|
||||||
$isFeatureBranch = 0 === strpos($version, 'dev-');
|
$isFeatureBranch = $this->isFeatureBranch($packageConfig, $match[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($match[2]) {
|
if ($match[2]) {
|
||||||
|
@ -247,7 +210,7 @@ class VersionGuesser
|
||||||
$version = $this->versionParser->normalizeBranch($branch);
|
$version = $this->versionParser->normalizeBranch($branch);
|
||||||
$isFeatureBranch = 0 === strpos($version, 'dev-');
|
$isFeatureBranch = 0 === strpos($version, 'dev-');
|
||||||
|
|
||||||
if (VersionParser::DEV_MASTER_ALIAS === $version) {
|
if (VersionParser::DEFAULT_BRANCH_ALIAS === $version) {
|
||||||
return array('version' => $version, 'commit' => null, 'pretty_version' => 'dev-'.$branch);
|
return array('version' => $version, 'commit' => null, 'pretty_version' => 'dev-'.$branch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,21 +245,18 @@ class VersionGuesser
|
||||||
$branch = preg_replace('{^dev-}', '', $version);
|
$branch = preg_replace('{^dev-}', '', $version);
|
||||||
$length = PHP_INT_MAX;
|
$length = PHP_INT_MAX;
|
||||||
|
|
||||||
$nonFeatureBranches = '';
|
|
||||||
if (!empty($packageConfig['non-feature-branches'])) {
|
|
||||||
$nonFeatureBranches = implode('|', $packageConfig['non-feature-branches']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// return directly, if branch is configured to be non-feature branch
|
// return directly, if branch is configured to be non-feature branch
|
||||||
if (preg_match('{^(' . $nonFeatureBranches . ')$}', $branch)) {
|
if (!$this->isFeatureBranch($packageConfig, $branch)) {
|
||||||
return array('version' => $version, 'pretty_version' => $prettyVersion);
|
return array('version' => $version, 'pretty_version' => $prettyVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
$defaultBranch = $this->getDefaultBranchName($path);
|
// sort numeric branches below named ones, to make sure if the branch has the same distance from main and 1.10 and 1.9 for example, main is picked
|
||||||
|
// and sort using natural sort so that 1.10 will appear before 1.9
|
||||||
|
rsort($branches, defined('SORT_NATURAL') ? SORT_NATURAL : SORT_REGULAR);
|
||||||
|
|
||||||
foreach ($branches as $candidate) {
|
foreach ($branches as $candidate) {
|
||||||
// do not compare against itself or other feature branches
|
// do not compare against itself or other feature branches
|
||||||
if ($candidate === $branch || !preg_match('{^(' . $nonFeatureBranches . ($defaultBranch ? '|'.preg_quote($defaultBranch) : '').'|master|main|latest|next|current|support|tip|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
|
if ($candidate === $branch || $this->isFeatureBranch($packageConfig, $candidate)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,7 +268,7 @@ class VersionGuesser
|
||||||
if (strlen($output) < $length) {
|
if (strlen($output) < $length) {
|
||||||
$length = strlen($output);
|
$length = strlen($output);
|
||||||
$version = $this->versionParser->normalizeBranch($candidate);
|
$version = $this->versionParser->normalizeBranch($candidate);
|
||||||
$prettyVersion = 'dev-' . $match[1];
|
$prettyVersion = 'dev-' . $candidate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -316,6 +276,16 @@ class VersionGuesser
|
||||||
return array('version' => $version, 'pretty_version' => $prettyVersion);
|
return array('version' => $version, 'pretty_version' => $prettyVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function isFeatureBranch(array $packageConfig, $branchName)
|
||||||
|
{
|
||||||
|
$nonFeatureBranches = '';
|
||||||
|
if (!empty($packageConfig['non-feature-branches'])) {
|
||||||
|
$nonFeatureBranches = implode('|', $packageConfig['non-feature-branches']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return !preg_match('{^(' . $nonFeatureBranches . '|master|main|latest|next|current|support|tip|trunk|default|develop|\d+\..+)$}', $branchName, $match);
|
||||||
|
}
|
||||||
|
|
||||||
private function guessFossilVersion(array $packageConfig, $path)
|
private function guessFossilVersion(array $packageConfig, $path)
|
||||||
{
|
{
|
||||||
$version = null;
|
$version = null;
|
||||||
|
|
|
@ -18,7 +18,7 @@ use Composer\Semver\Semver;
|
||||||
|
|
||||||
class VersionParser extends SemverVersionParser
|
class VersionParser extends SemverVersionParser
|
||||||
{
|
{
|
||||||
const DEV_MASTER_ALIAS = '9999999-dev';
|
const DEFAULT_BRANCH_ALIAS = '9999999-dev';
|
||||||
|
|
||||||
private static $constraints = array();
|
private static $constraints = array();
|
||||||
|
|
||||||
|
@ -72,8 +72,12 @@ class VersionParser extends SemverVersionParser
|
||||||
*/
|
*/
|
||||||
public static function isUpgrade($normalizedFrom, $normalizedTo)
|
public static function isUpgrade($normalizedFrom, $normalizedTo)
|
||||||
{
|
{
|
||||||
$normalizedFrom = str_replace(array('dev-master', 'dev-trunk', 'dev-default'), VersionParser::DEV_MASTER_ALIAS, $normalizedFrom);
|
if ($normalizedFrom === $normalizedTo) {
|
||||||
$normalizedTo = str_replace(array('dev-master', 'dev-trunk', 'dev-default'), VersionParser::DEV_MASTER_ALIAS, $normalizedTo);
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$normalizedFrom = str_replace(array('dev-master', 'dev-trunk', 'dev-default'), VersionParser::DEFAULT_BRANCH_ALIAS, $normalizedFrom);
|
||||||
|
$normalizedTo = str_replace(array('dev-master', 'dev-trunk', 'dev-default'), VersionParser::DEFAULT_BRANCH_ALIAS, $normalizedTo);
|
||||||
|
|
||||||
if (substr($normalizedFrom, 0, 4) === 'dev-' || substr($normalizedTo, 0, 4) === 'dev-') {
|
if (substr($normalizedFrom, 0, 4) === 'dev-' || substr($normalizedTo, 0, 4) === 'dev-') {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -196,9 +196,11 @@ class PluginManager
|
||||||
$className = substr($class, $separatorPos + 1);
|
$className = substr($class, $separatorPos + 1);
|
||||||
}
|
}
|
||||||
$code = preg_replace('{^((?:final\s+)?(?:\s*))class\s+('.preg_quote($className).')}mi', '$1class $2_composer_tmp'.self::$classCounter, $code, 1);
|
$code = preg_replace('{^((?:final\s+)?(?:\s*))class\s+('.preg_quote($className).')}mi', '$1class $2_composer_tmp'.self::$classCounter, $code, 1);
|
||||||
$code = str_replace('__FILE__', var_export($path, true), $code);
|
$code = strtr($code, array(
|
||||||
$code = str_replace('__DIR__', var_export(dirname($path), true), $code);
|
'__FILE__' => var_export($path, true),
|
||||||
$code = str_replace('__CLASS__', var_export($class, true), $code);
|
'__DIR__' => var_export(dirname($path), true),
|
||||||
|
'__CLASS__' => var_export($class, true),
|
||||||
|
));
|
||||||
$code = preg_replace('/^\s*<\?(php)?/i', '', $code, 1);
|
$code = preg_replace('/^\s*<\?(php)?/i', '', $code, 1);
|
||||||
eval($code);
|
eval($code);
|
||||||
$class .= '_composer_tmp'.self::$classCounter;
|
$class .= '_composer_tmp'.self::$classCounter;
|
||||||
|
|
|
@ -58,6 +58,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
protected $providersApiUrl;
|
protected $providersApiUrl;
|
||||||
protected $hasProviders = false;
|
protected $hasProviders = false;
|
||||||
protected $providersUrl;
|
protected $providersUrl;
|
||||||
|
protected $listUrl;
|
||||||
protected $availablePackages;
|
protected $availablePackages;
|
||||||
protected $lazyProvidersUrl;
|
protected $lazyProvidersUrl;
|
||||||
protected $providerListing;
|
protected $providerListing;
|
||||||
|
@ -288,33 +289,53 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
return parent::getPackages();
|
return parent::getPackages();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPackageNames()
|
public function getPackageNames($packageFilter = null)
|
||||||
{
|
{
|
||||||
// TODO add getPackageNames to the RepositoryInterface perhaps? With filtering capability embedded?
|
|
||||||
$hasProviders = $this->hasProviders();
|
$hasProviders = $this->hasProviders();
|
||||||
|
|
||||||
|
$packageFilterCb = function ($name) {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
if (null !== $packageFilter) {
|
||||||
|
$packageFilterRegex = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i';
|
||||||
|
$packageFilterCb = function ($name) use ($packageFilterRegex) {
|
||||||
|
return (bool) preg_match($packageFilterRegex, $name);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->lazyProvidersUrl) {
|
if ($this->lazyProvidersUrl) {
|
||||||
if (is_array($this->availablePackages)) {
|
if (is_array($this->availablePackages)) {
|
||||||
return array_keys($this->availablePackages);
|
return array_filter(array_keys($this->availablePackages), $packageFilterCb);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO implement new list API endpoint for those repos somehow?
|
if ($this->listUrl) {
|
||||||
|
$url = $this->listUrl;
|
||||||
|
if ($packageFilter) {
|
||||||
|
$url .= '?filter='.urlencode($packageFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $this->httpDownloader->get($url, $this->options)->decodeJson();
|
||||||
|
|
||||||
|
return $result['packageNames'];
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->hasPartialPackages()) {
|
if ($this->hasPartialPackages()) {
|
||||||
return array_keys($this->partialPackagesByName);
|
return array_filter(array_keys($this->partialPackagesByName), $packageFilterCb);
|
||||||
}
|
}
|
||||||
|
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($hasProviders) {
|
if ($hasProviders) {
|
||||||
return $this->getProviderNames();
|
return array_filter($this->getProviderNames(), $packageFilterCb);
|
||||||
}
|
}
|
||||||
|
|
||||||
$names = array();
|
$names = array();
|
||||||
foreach ($this->getPackages() as $package) {
|
foreach ($this->getPackages() as $package) {
|
||||||
|
if ($packageFilterCb($package->getName())) {
|
||||||
$names[] = $package->getPrettyName();
|
$names[] = $package->getPrettyName();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $names;
|
return $names;
|
||||||
}
|
}
|
||||||
|
@ -596,8 +617,8 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
if (!isset($versionsToLoad[$version['uid']])) {
|
if (!isset($versionsToLoad[$version['uid']])) {
|
||||||
if (!isset($version['version_normalized'])) {
|
if (!isset($version['version_normalized'])) {
|
||||||
$version['version_normalized'] = $this->versionParser->normalize($version['version']);
|
$version['version_normalized'] = $this->versionParser->normalize($version['version']);
|
||||||
} elseif ($version['version_normalized'] === VersionParser::DEV_MASTER_ALIAS) {
|
} elseif ($version['version_normalized'] === VersionParser::DEFAULT_BRANCH_ALIAS) {
|
||||||
// handling of existing repos which need to remain composer v1 compatible, in case the version_normalized contained VersionParser::DEV_MASTER_ALIAS, we renormalize it
|
// handling of existing repos which need to remain composer v1 compatible, in case the version_normalized contained VersionParser::DEFAULT_BRANCH_ALIAS, we renormalize it
|
||||||
$version['version_normalized'] = $this->versionParser->normalize($version['version']);
|
$version['version_normalized'] = $this->versionParser->normalize($version['version']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,6 +697,10 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
if ($acceptableStabilities === null || $stabilityFlags === null || StabilityFilter::isPackageAcceptable($acceptableStabilities, $stabilityFlags, array($name), 'dev')) {
|
if ($acceptableStabilities === null || $stabilityFlags === null || StabilityFilter::isPackageAcceptable($acceptableStabilities, $stabilityFlags, array($name), 'dev')) {
|
||||||
$packageNames[$name.'~dev'] = $constraint;
|
$packageNames[$name.'~dev'] = $constraint;
|
||||||
}
|
}
|
||||||
|
// if only dev stability is requested, we skip loading the non dev file
|
||||||
|
if (isset($acceptableStabilities['dev']) && count($acceptableStabilities) === 1 && count($stabilityFlags) === 0) {
|
||||||
|
unset($packageNames[$name]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($packageNames as $name => $constraint) {
|
foreach ($packageNames as $name => $constraint) {
|
||||||
|
@ -717,8 +742,8 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
foreach ($versions as $version) {
|
foreach ($versions as $version) {
|
||||||
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']);
|
||||||
} elseif ($version['version_normalized'] === VersionParser::DEV_MASTER_ALIAS) {
|
} elseif ($version['version_normalized'] === VersionParser::DEFAULT_BRANCH_ALIAS) {
|
||||||
// handling of existing repos which need to remain composer v1 compatible, in case the version_normalized contained VersionParser::DEV_MASTER_ALIAS, we renormalize it
|
// handling of existing repos which need to remain composer v1 compatible, in case the version_normalized contained VersionParser::DEFAULT_BRANCH_ALIAS, we renormalize it
|
||||||
$version['version_normalized'] = $repo->versionParser->normalize($version['version']);
|
$version['version_normalized'] = $repo->versionParser->normalize($version['version']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -862,6 +887,10 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
$this->hasProviders = true;
|
$this->hasProviders = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($data['list'])) {
|
||||||
|
$this->listUrl = $this->canonicalizeUrl($data['list']);
|
||||||
|
}
|
||||||
|
|
||||||
if (!empty($data['providers']) || !empty($data['providers-includes'])) {
|
if (!empty($data['providers']) || !empty($data['providers-includes'])) {
|
||||||
$this->hasProviders = true;
|
$this->hasProviders = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,11 +63,11 @@ class RepositoryFactory
|
||||||
* @param bool $allowFilesystem
|
* @param bool $allowFilesystem
|
||||||
* @return RepositoryInterface
|
* @return RepositoryInterface
|
||||||
*/
|
*/
|
||||||
public static function fromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
|
public static function fromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false, RepositoryManager $rm = null)
|
||||||
{
|
{
|
||||||
$repoConfig = static::configFromString($io, $config, $repository, $allowFilesystem);
|
$repoConfig = static::configFromString($io, $config, $repository, $allowFilesystem);
|
||||||
|
|
||||||
return static::createRepo($io, $config, $repoConfig);
|
return static::createRepo($io, $config, $repoConfig, $rm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,9 +76,11 @@ class RepositoryFactory
|
||||||
* @param array $repoConfig
|
* @param array $repoConfig
|
||||||
* @return RepositoryInterface
|
* @return RepositoryInterface
|
||||||
*/
|
*/
|
||||||
public static function createRepo(IOInterface $io, Config $config, array $repoConfig)
|
public static function createRepo(IOInterface $io, Config $config, array $repoConfig, RepositoryManager $rm = null)
|
||||||
{
|
{
|
||||||
|
if (!$rm) {
|
||||||
$rm = static::manager($io, $config, Factory::createHttpDownloader($io, $config));
|
$rm = static::manager($io, $config, Factory::createHttpDownloader($io, $config));
|
||||||
|
}
|
||||||
$repos = static::createRepos($rm, array($repoConfig));
|
$repos = static::createRepos($rm, array($repoConfig));
|
||||||
|
|
||||||
return reset($repos);
|
return reset($repos);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
namespace Composer\Repository;
|
namespace Composer\Repository;
|
||||||
|
|
||||||
use Composer\Package\PackageInterface;
|
use Composer\Package\PackageInterface;
|
||||||
|
use Composer\Package\BasePackage;
|
||||||
use Composer\Semver\Constraint\ConstraintInterface;
|
use Composer\Semver\Constraint\ConstraintInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,8 +71,10 @@ interface RepositoryInterface extends \Countable
|
||||||
* - The namesFound returned are names which should be considered as canonically found in this repository, that should not be looked up in any further lower priority repositories
|
* - The namesFound returned are names which should be considered as canonically found in this repository, that should not be looked up in any further lower priority repositories
|
||||||
*
|
*
|
||||||
* @param ConstraintInterface[] $packageNameMap package names pointing to constraints
|
* @param ConstraintInterface[] $packageNameMap package names pointing to constraints
|
||||||
* @param array $acceptableStabilities
|
* @param int[] $acceptableStabilities array of stability => BasePackage::STABILITY_* value
|
||||||
* @param array $stabilityFlags
|
* @psalm-param array<string, BasePackage::STABILITY_*> $acceptableStabilities
|
||||||
|
* @param int[] $stabilityFlags an array of package name => BasePackage::STABILITY_* value
|
||||||
|
* @psalm-param array<string, BasePackage::STABILITY_*> $stabilityFlags
|
||||||
*
|
*
|
||||||
* @return array [namesFound => string[], packages => PackageInterface[]]
|
* @return array [namesFound => string[], packages => PackageInterface[]]
|
||||||
* @psalm-return array{namesFound: string[], packages: PackageInterface[]}
|
* @psalm-return array{namesFound: string[], packages: PackageInterface[]}
|
||||||
|
|
|
@ -222,7 +222,17 @@ class GitDriver extends VcsDriver
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$process = new ProcessExecutor($io);
|
$gitUtil = new GitUtil($io, $config, new ProcessExecutor($io), new Filesystem());
|
||||||
return $process->execute('git ls-remote --heads ' . ProcessExecutor::escape($url), $output) === 0;
|
GitUtil::cleanEnv();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$gitUtil->runCommand(function ($url) {
|
||||||
|
return 'git ls-remote --heads ' . ProcessExecutor::escape($url);
|
||||||
|
}, $url, sys_get_temp_dir());
|
||||||
|
} catch (\RuntimeException $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,20 +214,19 @@ class GitHubDriver extends VcsDriver
|
||||||
$result = array();
|
$result = array();
|
||||||
$key = null;
|
$key = null;
|
||||||
foreach (preg_split('{\r?\n}', $funding) as $line) {
|
foreach (preg_split('{\r?\n}', $funding) as $line) {
|
||||||
$line = preg_replace('{#.*}', '', $line);
|
|
||||||
$line = trim($line);
|
$line = trim($line);
|
||||||
if (preg_match('{^(\w+)\s*:\s*(.+)$}', $line, $match)) {
|
if (preg_match('{^(\w+)\s*:\s*(.+)$}', $line, $match)) {
|
||||||
if (preg_match('{^\[.*\]$}', $match[2])) {
|
if (preg_match('{^\[(.*)\](?:\s*#.*)?$}', $match[2], $match2)) {
|
||||||
foreach (array_map('trim', preg_split('{[\'"]?\s*,\s*[\'"]?}', substr($match[2], 1, -1))) as $item) {
|
foreach (array_map('trim', preg_split('{[\'"]?\s*,\s*[\'"]?}', $match2[1])) as $item) {
|
||||||
$result[] = array('type' => $match[1], 'url' => trim($item, '"\' '));
|
$result[] = array('type' => $match[1], 'url' => trim($item, '"\' '));
|
||||||
}
|
}
|
||||||
} else {
|
} elseif (preg_match('{^([^#].*?)(\s+#.*)?$}', $match[2], $match2)) {
|
||||||
$result[] = array('type' => $match[1], 'url' => trim($match[2], '"\' '));
|
$result[] = array('type' => $match[1], 'url' => trim($match2[1], '"\' '));
|
||||||
}
|
}
|
||||||
$key = null;
|
$key = null;
|
||||||
} elseif (preg_match('{^(\w+)\s*:$}', $line, $match)) {
|
} elseif (preg_match('{^(\w+)\s*:\s*#\s*$}', $line, $match)) {
|
||||||
$key = $match[1];
|
$key = $match[1];
|
||||||
} elseif ($key && preg_match('{^-\s*(.+)$}', $line, $match)) {
|
} elseif ($key && preg_match('{^-\s*(.+)(\s+#.*)?$}', $line, $match)) {
|
||||||
$result[] = array('type' => $key, 'url' => trim($match[1], '"\' '));
|
$result[] = array('type' => $key, 'url' => trim($match[1], '"\' '));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,13 +291,6 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
||||||
$this->io->overwriteError($msg, false);
|
$this->io->overwriteError($msg, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($branch === 'trunk' && isset($branches['master'])) {
|
|
||||||
if ($isVeryVerbose) {
|
|
||||||
$this->io->writeError('<warning>Skipped branch '.$branch.', can not parse both master and trunk branches as they both resolve to '.VersionParser::DEV_MASTER_ALIAS.' internally</warning>');
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$parsedBranch = $this->validateBranch($branch)) {
|
if (!$parsedBranch = $this->validateBranch($branch)) {
|
||||||
if ($isVeryVerbose) {
|
if ($isVeryVerbose) {
|
||||||
$this->io->writeError('<warning>Skipped branch '.$branch.', invalid name</warning>');
|
$this->io->writeError('<warning>Skipped branch '.$branch.', invalid name</warning>');
|
||||||
|
@ -306,7 +299,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure branch packages have a dev flag
|
// make sure branch packages have a dev flag
|
||||||
if ('dev-' === substr($parsedBranch, 0, 4) || VersionParser::DEV_MASTER_ALIAS === $parsedBranch) {
|
if ('dev-' === substr($parsedBranch, 0, 4) || VersionParser::DEFAULT_BRANCH_ALIAS === $parsedBranch) {
|
||||||
$version = 'dev-' . $branch;
|
$version = 'dev-' . $branch;
|
||||||
} else {
|
} else {
|
||||||
$prefix = substr($branch, 0, 1) === 'v' ? 'v' : '';
|
$prefix = substr($branch, 0, 1) === 'v' ? 'v' : '';
|
||||||
|
|
|
@ -119,7 +119,7 @@ class GitLab
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', $this->config->getAuthConfigSource()->getName()));
|
$this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', $this->config->getAuthConfigSource()->getName()));
|
||||||
$this->io->writeError('To revoke access to this token you can visit '.$originUrl.'/profile/applications');
|
$this->io->writeError('To revoke access to this token you can visit '.$scheme.'://'.$originUrl.'/profile/applications');
|
||||||
|
|
||||||
$attemptCounter = 0;
|
$attemptCounter = 0;
|
||||||
|
|
||||||
|
@ -131,12 +131,17 @@ class GitLab
|
||||||
// 403 is max login attempts exceeded
|
// 403 is max login attempts exceeded
|
||||||
if (in_array($e->getCode(), array(403, 401))) {
|
if (in_array($e->getCode(), array(403, 401))) {
|
||||||
if (401 === $e->getCode()) {
|
if (401 === $e->getCode()) {
|
||||||
|
$response = json_decode($e->getResponse(), true);
|
||||||
|
if (isset($response['error']) && $response['error'] === 'invalid_grant') {
|
||||||
|
$this->io->writeError('Bad credentials. If you have two factor authentication enabled you will have to manually create a personal access token');
|
||||||
|
} else {
|
||||||
$this->io->writeError('Bad credentials.');
|
$this->io->writeError('Bad credentials.');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->io->writeError('Maximum number of login attempts exceeded. Please try again later.');
|
$this->io->writeError('Maximum number of login attempts exceeded. Please try again later.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->io->writeError('You can also manually create a personal token at '.$scheme.'://'.$originUrl.'/profile/personal_access_tokens');
|
$this->io->writeError('You can also manually create a personal access token enabling the "read_api" scope at '.$scheme.'://'.$originUrl.'/profile/personal_access_tokens');
|
||||||
$this->io->writeError('Add it using "composer config --global --auth gitlab-token.'.$originUrl.' <token>"');
|
$this->io->writeError('Add it using "composer config --global --auth gitlab-token.'.$originUrl.' <token>"');
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -351,7 +351,7 @@ class RemoteFilesystem
|
||||||
if ($originUrl === 'bitbucket.org'
|
if ($originUrl === 'bitbucket.org'
|
||||||
&& !$this->authHelper->isPublicBitBucketDownload($fileUrl)
|
&& !$this->authHelper->isPublicBitBucketDownload($fileUrl)
|
||||||
&& substr($fileUrl, -4) === '.zip'
|
&& substr($fileUrl, -4) === '.zip'
|
||||||
&& (!$locationHeader || substr($locationHeader, -4) !== '.zip')
|
&& (!$locationHeader || substr(parse_url($locationHeader, PHP_URL_PATH), -4) !== '.zip')
|
||||||
&& $contentType && preg_match('{^text/html\b}i', $contentType)
|
&& $contentType && preg_match('{^text/html\b}i', $contentType)
|
||||||
) {
|
) {
|
||||||
$result = false;
|
$result = false;
|
||||||
|
|
|
@ -100,7 +100,7 @@ class AllFunctionalTest extends TestCase
|
||||||
* @dataProvider getTestFiles
|
* @dataProvider getTestFiles
|
||||||
* @depends testBuildPhar
|
* @depends testBuildPhar
|
||||||
*/
|
*/
|
||||||
public function testIntegration(\SplFileInfo $testFile)
|
public function testIntegration($testFile)
|
||||||
{
|
{
|
||||||
$testData = $this->parseTestFile($testFile);
|
$testData = $this->parseTestFile($testFile);
|
||||||
|
|
||||||
|
@ -133,15 +133,15 @@ class AllFunctionalTest extends TestCase
|
||||||
{
|
{
|
||||||
$tests = array();
|
$tests = array();
|
||||||
foreach (Finder::create()->in(__DIR__.'/Fixtures/functional')->name('*.test')->files() as $file) {
|
foreach (Finder::create()->in(__DIR__.'/Fixtures/functional')->name('*.test')->files() as $file) {
|
||||||
$tests[] = array($file);
|
$tests[] = array($file->getRealPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $tests;
|
return $tests;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function parseTestFile(\SplFileInfo $file)
|
private function parseTestFile($file)
|
||||||
{
|
{
|
||||||
$tokens = preg_split('#(?:^|\n*)--([A-Z-]+)--\n#', file_get_contents($file->getRealPath()), null, PREG_SPLIT_DELIM_CAPTURE);
|
$tokens = preg_split('#(?:^|\n*)--([A-Z-]+)--\n#', file_get_contents($file), null, PREG_SPLIT_DELIM_CAPTURE);
|
||||||
$data = array();
|
$data = array();
|
||||||
$section = null;
|
$section = null;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,342 @@
|
||||||
|
--TEST--
|
||||||
|
Solver Bug Exception caused by analyze on mutli conflict rule reported in GitHub issue 7051 https://github.com/composer/composer/issues/7051
|
||||||
|
--COMPOSER--
|
||||||
|
{
|
||||||
|
"require": {
|
||||||
|
"illuminate/queue": "*",
|
||||||
|
"friendsofphp/php-cs-fixer": "*"
|
||||||
|
},
|
||||||
|
"repositories": {
|
||||||
|
"illuminate/queue": {
|
||||||
|
"type": "package",
|
||||||
|
"package": [
|
||||||
|
{
|
||||||
|
"name": "illuminate/queue",
|
||||||
|
"version": "v5.2.0",
|
||||||
|
"require": {
|
||||||
|
"illuminate/console": "5.2.*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"friendsofphp/php-cs-fixer": {
|
||||||
|
"type": "package",
|
||||||
|
"package": [
|
||||||
|
{
|
||||||
|
"name": "friendsofphp/php-cs-fixer",
|
||||||
|
"version": "v2.10.5",
|
||||||
|
"type": "application",
|
||||||
|
"require": {
|
||||||
|
"symfony/console": "^3.2 || ^4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "friendsofphp/php-cs-fixer",
|
||||||
|
"version": "v2.10.4",
|
||||||
|
"type": "application",
|
||||||
|
"require": {
|
||||||
|
"symfony/console": "^3.2 || ^4.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"illuminate/console": {
|
||||||
|
"type": "package",
|
||||||
|
"package": [
|
||||||
|
{
|
||||||
|
"name": "illuminate/console",
|
||||||
|
"version": "v5.2.26",
|
||||||
|
"require": {
|
||||||
|
"symfony/console": "2.8.*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "illuminate/console",
|
||||||
|
"version": "v5.2.25",
|
||||||
|
"require": {
|
||||||
|
"symfony/console": "3.1.*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/console": {
|
||||||
|
"type": "package",
|
||||||
|
"package": [
|
||||||
|
{
|
||||||
|
"name": "symfony/console",
|
||||||
|
"version": "v3.4.29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/console",
|
||||||
|
"version": "v3.4.28"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/console",
|
||||||
|
"version": "v3.3.18"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/console",
|
||||||
|
"version": "v3.3.17"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/console",
|
||||||
|
"version": "v3.2.14"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/console",
|
||||||
|
"version": "v3.2.13"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/console",
|
||||||
|
"version": "v3.1.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/console",
|
||||||
|
"version": "v3.1.9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/console",
|
||||||
|
"version": "v2.8.8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/console",
|
||||||
|
"version": "v2.8.7"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--RUN--
|
||||||
|
update
|
||||||
|
--EXPECT-OUTPUT--
|
||||||
|
Loading composer repositories with package information
|
||||||
|
Updating dependencies
|
||||||
|
Your requirements could not be resolved to an installable set of packages.
|
||||||
|
|
||||||
|
Problem 1
|
||||||
|
- Conclusion: don't install friendsofphp/php-cs-fixer v2.10.5, learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- Conclusion: don't install one of symfony/console[v3.1.10], friendsofphp/php-cs-fixer[v2.10.5] | install symfony/console[v3.4.29], learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- Conclusion: don't install one of symfony/console[v2.8.7], friendsofphp/php-cs-fixer[v2.10.5] | install symfony/console[v3.4.29], learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console[v3.4.29] | install symfony/console[v2.8.8], learned rules:
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Conclusion: don't install one of symfony/console[v2.8.8], friendsofphp/php-cs-fixer[v2.10.5], learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Conclusion: don't install symfony/console v3.4.29, learned rules:
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console[v3.4.29] | install symfony/console[v2.8.8], learned rules:
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Conclusion: don't install symfony/console v2.8.8, learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.4 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console v3.4.29, learned rules:
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console[v3.4.29] | install symfony/console[v2.8.8], learned rules:
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Root composer.json requires friendsofphp/php-cs-fixer * -> satisfiable by friendsofphp/php-cs-fixer[v2.10.4, v2.10.5].
|
||||||
|
- Conclusion: don't install friendsofphp/php-cs-fixer v2.10.5, learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- Conclusion: don't install one of symfony/console[v3.1.10], friendsofphp/php-cs-fixer[v2.10.5] | install symfony/console[v3.4.29], learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- Conclusion: don't install one of symfony/console[v2.8.7], friendsofphp/php-cs-fixer[v2.10.5] | install symfony/console[v3.4.29], learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console[v3.4.29] | install symfony/console[v2.8.8], learned rules:
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Conclusion: don't install one of symfony/console[v2.8.8], friendsofphp/php-cs-fixer[v2.10.5], learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Conclusion: don't install symfony/console v3.4.28, learned rules:
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console v2.8.8, learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.4 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console v3.4.29, learned rules:
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console[v3.4.29] | install symfony/console[v2.8.8], learned rules:
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Root composer.json requires friendsofphp/php-cs-fixer * -> satisfiable by friendsofphp/php-cs-fixer[v2.10.4, v2.10.5].
|
||||||
|
- Conclusion: don't install friendsofphp/php-cs-fixer v2.10.5, learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- Conclusion: don't install one of symfony/console[v3.1.10], friendsofphp/php-cs-fixer[v2.10.5] | install symfony/console[v3.4.29], learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- Conclusion: don't install one of symfony/console[v2.8.7], friendsofphp/php-cs-fixer[v2.10.5] | install symfony/console[v3.4.29], learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console[v3.4.29] | install symfony/console[v2.8.8], learned rules:
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Conclusion: don't install one of symfony/console[v2.8.8], friendsofphp/php-cs-fixer[v2.10.5], learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- Conclusion: don't install symfony/console v2.8.7, learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.4 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console v3.4.28, learned rules:
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console v2.8.8, learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.4 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console v3.4.29, learned rules:
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console[v3.4.29] | install symfony/console[v2.8.8], learned rules:
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Root composer.json requires friendsofphp/php-cs-fixer * -> satisfiable by friendsofphp/php-cs-fixer[v2.10.4, v2.10.5].
|
||||||
|
- Conclusion: don't install friendsofphp/php-cs-fixer v2.10.5, learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- Conclusion: don't install one of symfony/console[v3.1.10], friendsofphp/php-cs-fixer[v2.10.5] | install symfony/console[v3.4.29], learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- Conclusion: don't install one of symfony/console[v2.8.7], friendsofphp/php-cs-fixer[v2.10.5] | install symfony/console[v3.4.29], learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console[v3.4.29] | install symfony/console[v2.8.8], learned rules:
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Conclusion: don't install one of symfony/console[v2.8.8], friendsofphp/php-cs-fixer[v2.10.5], learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Conclusion: don't install symfony/console v3.4.29, learned rules:
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console[v3.4.29] | install symfony/console[v2.8.8], learned rules:
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Root composer.json requires friendsofphp/php-cs-fixer * -> satisfiable by friendsofphp/php-cs-fixer[v2.10.4, v2.10.5].
|
||||||
|
- Conclusion: don't install friendsofphp/php-cs-fixer v2.10.5, learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- Conclusion: don't install one of symfony/console[v3.1.10], friendsofphp/php-cs-fixer[v2.10.5] | install symfony/console[v3.4.29], learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- Conclusion: don't install one of symfony/console[v2.8.7], friendsofphp/php-cs-fixer[v2.10.5] | install symfony/console[v3.4.29], learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console[v3.4.29] | install symfony/console[v2.8.8], learned rules:
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Conclusion: don't install one of symfony/console[v2.8.8], friendsofphp/php-cs-fixer[v2.10.5], learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Root composer.json requires friendsofphp/php-cs-fixer * -> satisfiable by friendsofphp/php-cs-fixer[v2.10.4, v2.10.5].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.4 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- Conclusion: don't install symfony/console v3.1.10, learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.4 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console v3.4.28, learned rules:
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console v2.8.8, learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.4 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console v3.4.29, learned rules:
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Conclusion: don't install symfony/console[v3.4.29] | install symfony/console[v2.8.8], learned rules:
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Root composer.json requires friendsofphp/php-cs-fixer * -> satisfiable by friendsofphp/php-cs-fixer[v2.10.4, v2.10.5].
|
||||||
|
- Conclusion: don't install friendsofphp/php-cs-fixer v2.10.5, learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- Conclusion: don't install one of symfony/console[v3.1.10], friendsofphp/php-cs-fixer[v2.10.5] | install symfony/console[v3.4.29], learned rules:
|
||||||
|
%A
|
||||||
|
- Conclusion: don't install symfony/console[v3.4.29] | install symfony/console[v2.8.8], learned rules:
|
||||||
|
- illuminate/queue v5.2.0 requires illuminate/console 5.2.* -> satisfiable by illuminate/console[v5.2.25, v5.2.26].
|
||||||
|
- illuminate/console v5.2.25 requires symfony/console 3.1.* -> satisfiable by symfony/console[v3.1.9, v3.1.10].
|
||||||
|
- illuminate/console v5.2.26 requires symfony/console 2.8.* -> satisfiable by symfony/console[v2.8.7, v2.8.8].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
- Conclusion: don't install one of symfony/console[v2.8.8], friendsofphp/php-cs-fixer[v2.10.5], learned rules:
|
||||||
|
- friendsofphp/php-cs-fixer v2.10.5 requires symfony/console ^3.2 || ^4.0 -> satisfiable by symfony/console[v3.2.13, ..., v3.4.29].
|
||||||
|
- You can only install one version of a package, so only one of these can be installed: symfony/console[v2.8.7, v2.8.8, v3.1.9, ..., v3.4.29].
|
||||||
|
- Root composer.json requires illuminate/queue * -> satisfiable by illuminate/queue[v5.2.0].
|
||||||
|
--EXPECT--
|
||||||
|
|
||||||
|
--EXPECT-EXIT-CODE--
|
||||||
|
2
|
||||||
|
|
|
@ -3,10 +3,10 @@ Update mirrors updates URLs for all packages if they have changed without updati
|
||||||
|
|
||||||
a/a is dev and gets everything updated as it updates to a new ref
|
a/a is dev and gets everything updated as it updates to a new ref
|
||||||
b/b is a tag and gets everything updated by updating the package URL directly
|
b/b is a tag and gets everything updated by updating the package URL directly
|
||||||
c/c is a tag and not whitelisted and gets the new URL but keeps its old ref
|
c/c is a tag and not allowlisted for update and gets the new URL but keeps its old ref
|
||||||
d/d is dev but with a #ref so it should get URL updated but not the reference
|
d/d is dev but with a #ref so it should get URL updated but not the reference
|
||||||
e/e is dev and newly installed with a #ref so it should get the correct URL but with the #111 ref
|
e/e is dev and newly installed with a #ref so it should get the correct URL but with the #111 ref
|
||||||
e/e is dev but not whitelisted and gets the new URL but keeps its old ref
|
e/e is dev but not allowlisted for update and gets the new URL but keeps its old ref
|
||||||
g/g is dev and installed in a different ref than the #ref, so it gets updated and gets the new URL but not the new ref
|
g/g is dev and installed in a different ref than the #ref, so it gets updated and gets the new URL but not the new ref
|
||||||
--COMPOSER--
|
--COMPOSER--
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,10 +40,9 @@ class ComposerSchemaTest extends TestCase
|
||||||
public function testRequiredProperties()
|
public function testRequiredProperties()
|
||||||
{
|
{
|
||||||
$json = '{ }';
|
$json = '{ }';
|
||||||
$this->assertEquals(array(
|
$result = $this->check($json);
|
||||||
array('property' => 'name', 'message' => 'The property name is required', 'constraint' => 'required'),
|
$this->assertContains(array('property' => 'name', 'message' => 'The property name is required', 'constraint' => 'required'), $result);
|
||||||
array('property' => 'description', 'message' => 'The property description is required', 'constraint' => 'required'),
|
$this->assertContains(array('property' => 'description', 'message' => 'The property description is required', 'constraint' => 'required'), $result);
|
||||||
), $this->check($json));
|
|
||||||
|
|
||||||
$json = '{ "name": "vendor/package" }';
|
$json = '{ "name": "vendor/package" }';
|
||||||
$this->assertEquals(array(
|
$this->assertEquals(array(
|
||||||
|
|
|
@ -24,10 +24,4 @@ class VersionGuesserMock extends VersionGuesser
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDefaultBranchName($path)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,8 +105,6 @@ class RootPackageLoaderTest extends TestCase
|
||||||
'pretty_version' => '3.0-dev',
|
'pretty_version' => '3.0-dev',
|
||||||
'commit' => 'aabbccddee',
|
'commit' => 'aabbccddee',
|
||||||
));
|
));
|
||||||
$versionGuesser->getDefaultBranchName(Argument::cetera())
|
|
||||||
->willReturn('main');
|
|
||||||
$config = new Config;
|
$config = new Config;
|
||||||
$config->merge(array('repositories' => array('packagist' => false)));
|
$config->merge(array('repositories' => array('packagist' => false)));
|
||||||
$loader = new RootPackageLoader($manager->reveal(), $config, null, $versionGuesser->reveal());
|
$loader = new RootPackageLoader($manager->reveal(), $config, null, $versionGuesser->reveal());
|
||||||
|
@ -115,28 +113,6 @@ class RootPackageLoaderTest extends TestCase
|
||||||
$this->assertEquals('3.0-dev', $package->getPrettyVersion());
|
$this->assertEquals('3.0-dev', $package->getPrettyVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDefaultBranchIsSetForRootPackageInDefaultBranch()
|
|
||||||
{
|
|
||||||
// see #6845
|
|
||||||
$manager = $this->prophesize('\\Composer\\Repository\\RepositoryManager');
|
|
||||||
$versionGuesser = $this->prophesize('\\Composer\\Package\\Version\\VersionGuesser');
|
|
||||||
$versionGuesser->guessVersion(Argument::cetera())
|
|
||||||
->willReturn(array(
|
|
||||||
'name' => 'A',
|
|
||||||
'version' => 'dev-main',
|
|
||||||
'pretty_version' => 'dev-main',
|
|
||||||
'commit' => 'aabbccddee',
|
|
||||||
));
|
|
||||||
$versionGuesser->getDefaultBranchName(Argument::cetera())
|
|
||||||
->willReturn('main');
|
|
||||||
$config = new Config;
|
|
||||||
$config->merge(array('repositories' => array('packagist' => false)));
|
|
||||||
$loader = new RootPackageLoader($manager->reveal(), $config, null, $versionGuesser->reveal());
|
|
||||||
$package = $loader->load(array());
|
|
||||||
|
|
||||||
$this->assertTrue($package->isDefaultBranch());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testFeatureBranchPrettyVersion()
|
public function testFeatureBranchPrettyVersion()
|
||||||
{
|
{
|
||||||
if (!function_exists('proc_open')) {
|
if (!function_exists('proc_open')) {
|
||||||
|
@ -171,17 +147,6 @@ class RootPackageLoaderTest extends TestCase
|
||||||
$executor
|
$executor
|
||||||
->expects($this->at(1))
|
->expects($this->at(1))
|
||||||
->method('execute')
|
->method('execute')
|
||||||
->willReturnCallback(function ($command, &$output) use ($self) {
|
|
||||||
$self->assertEquals('git remote show origin', $command);
|
|
||||||
$output = " HEAD branch: master";
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
})
|
|
||||||
;
|
|
||||||
|
|
||||||
$executor
|
|
||||||
->expects($this->at(2))
|
|
||||||
->method('execute')
|
|
||||||
->willReturnCallback(function ($command, &$output) use ($self) {
|
->willReturnCallback(function ($command, &$output) use ($self) {
|
||||||
$self->assertEquals('git rev-list master..latest-production', $command);
|
$self->assertEquals('git rev-list master..latest-production', $command);
|
||||||
$output = "";
|
$output = "";
|
||||||
|
@ -195,8 +160,6 @@ class RootPackageLoaderTest extends TestCase
|
||||||
$loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($config, $executor, new VersionParser()));
|
$loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($config, $executor, new VersionParser()));
|
||||||
$package = $loader->load(array('require' => array('foo/bar' => 'self.version')));
|
$package = $loader->load(array('require' => array('foo/bar' => 'self.version')));
|
||||||
|
|
||||||
$this->assertEquals("9999999-dev", $package->getPrettyVersion());
|
|
||||||
$package = $package->getAliasOf();
|
|
||||||
$this->assertEquals("dev-master", $package->getPrettyVersion());
|
$this->assertEquals("dev-master", $package->getPrettyVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,7 @@ class VersionGuesserTest extends TestCase
|
||||||
$this->assertEquals($commitHash, $versionArray['commit']);
|
$this->assertEquals($commitHash, $versionArray['commit']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGuessVersionReadsAndRespectsDefaultBranchAsNonFeatureBranch()
|
public function testGuessVersionDoesNotSeeCustomDefaultBranchAsNonFeatureBranch()
|
||||||
{
|
{
|
||||||
$commitHash = '03a15d220da53c52eddd5f32ffca64a7b3801bea';
|
$commitHash = '03a15d220da53c52eddd5f32ffca64a7b3801bea';
|
||||||
$anotherCommitHash = '13a15d220da53c52eddd5f32ffca64a7b3801bea';
|
$anotherCommitHash = '13a15d220da53c52eddd5f32ffca64a7b3801bea';
|
||||||
|
@ -149,6 +149,7 @@ class VersionGuesserTest extends TestCase
|
||||||
|
|
||||||
$self = $this;
|
$self = $this;
|
||||||
|
|
||||||
|
// Assumption here is that arbitrary would be the default branch
|
||||||
$executor
|
$executor
|
||||||
->expects($this->at(0))
|
->expects($this->at(0))
|
||||||
->method('execute')
|
->method('execute')
|
||||||
|
@ -160,37 +161,13 @@ class VersionGuesserTest extends TestCase
|
||||||
})
|
})
|
||||||
;
|
;
|
||||||
|
|
||||||
$executor
|
|
||||||
->expects($this->at(1))
|
|
||||||
->method('execute')
|
|
||||||
->willReturnCallback(function ($command, &$output) use ($self) {
|
|
||||||
$self->assertEquals('git remote show origin', $command);
|
|
||||||
$output = " HEAD branch: arbitrary\r\n";
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
})
|
|
||||||
;
|
|
||||||
|
|
||||||
$executor
|
|
||||||
->expects($this->at(2))
|
|
||||||
->method('execute')
|
|
||||||
->willReturnCallback(function ($command, &$output, $path) use ($self, $anotherCommitHash) {
|
|
||||||
$self->assertEquals('git rev-list arbitrary..current', $command);
|
|
||||||
$output = "$anotherCommitHash\n";
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
})
|
|
||||||
;
|
|
||||||
|
|
||||||
$config = new Config;
|
$config = new Config;
|
||||||
$config->merge(array('repositories' => array('packagist' => false)));
|
$config->merge(array('repositories' => array('packagist' => false)));
|
||||||
$guesser = new VersionGuesser($config, $executor, new VersionParser());
|
$guesser = new VersionGuesser($config, $executor, new VersionParser());
|
||||||
$versionArray = $guesser->guessVersion(array('version' => 'self.version'), 'dummy/path');
|
$versionArray = $guesser->guessVersion(array('version' => 'self.version'), 'dummy/path');
|
||||||
|
|
||||||
$this->assertEquals("dev-arbitrary", $versionArray['version']);
|
$this->assertEquals("dev-current", $versionArray['version']);
|
||||||
$this->assertEquals($anotherCommitHash, $versionArray['commit']);
|
$this->assertEquals($anotherCommitHash, $versionArray['commit']);
|
||||||
$this->assertEquals("dev-current", $versionArray['feature_version']);
|
|
||||||
$this->assertEquals("dev-current", $versionArray['feature_pretty_version']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGuessVersionReadsAndRespectsNonFeatureBranchesConfigurationForArbitraryNaming()
|
public function testGuessVersionReadsAndRespectsNonFeatureBranchesConfigurationForArbitraryNaming()
|
||||||
|
@ -212,7 +189,7 @@ class VersionGuesserTest extends TestCase
|
||||||
->method('execute')
|
->method('execute')
|
||||||
->willReturnCallback(function ($command, &$output) use ($self, $commitHash, $anotherCommitHash) {
|
->willReturnCallback(function ($command, &$output) use ($self, $commitHash, $anotherCommitHash) {
|
||||||
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
|
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
|
||||||
$output = " arbitrary $commitHash Commit message\n* current $anotherCommitHash Another message\n";
|
$output = " arbitrary $commitHash Commit message\n* feature $anotherCommitHash Another message\n";
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
})
|
})
|
||||||
|
@ -221,19 +198,8 @@ class VersionGuesserTest extends TestCase
|
||||||
$executor
|
$executor
|
||||||
->expects($this->at(1))
|
->expects($this->at(1))
|
||||||
->method('execute')
|
->method('execute')
|
||||||
->willReturnCallback(function ($command, &$output) use ($self) {
|
|
||||||
$self->assertEquals('git remote show origin', $command);
|
|
||||||
$output = " HEAD branch: foo\r\n";
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
})
|
|
||||||
;
|
|
||||||
|
|
||||||
$executor
|
|
||||||
->expects($this->at(2))
|
|
||||||
->method('execute')
|
|
||||||
->willReturnCallback(function ($command, &$output, $path) use ($self, $anotherCommitHash) {
|
->willReturnCallback(function ($command, &$output, $path) use ($self, $anotherCommitHash) {
|
||||||
$self->assertEquals('git rev-list arbitrary..current', $command);
|
$self->assertEquals('git rev-list arbitrary..feature', $command);
|
||||||
$output = "$anotherCommitHash\n";
|
$output = "$anotherCommitHash\n";
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -247,8 +213,8 @@ class VersionGuesserTest extends TestCase
|
||||||
|
|
||||||
$this->assertEquals("dev-arbitrary", $versionArray['version']);
|
$this->assertEquals("dev-arbitrary", $versionArray['version']);
|
||||||
$this->assertEquals($anotherCommitHash, $versionArray['commit']);
|
$this->assertEquals($anotherCommitHash, $versionArray['commit']);
|
||||||
$this->assertEquals("dev-current", $versionArray['feature_version']);
|
$this->assertEquals("dev-feature", $versionArray['feature_version']);
|
||||||
$this->assertEquals("dev-current", $versionArray['feature_pretty_version']);
|
$this->assertEquals("dev-feature", $versionArray['feature_pretty_version']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGuessVersionReadsAndRespectsNonFeatureBranchesConfigurationForArbitraryNamingRegex()
|
public function testGuessVersionReadsAndRespectsNonFeatureBranchesConfigurationForArbitraryNamingRegex()
|
||||||
|
@ -270,7 +236,7 @@ class VersionGuesserTest extends TestCase
|
||||||
->method('execute')
|
->method('execute')
|
||||||
->willReturnCallback(function ($command, &$output) use ($self, $commitHash, $anotherCommitHash) {
|
->willReturnCallback(function ($command, &$output) use ($self, $commitHash, $anotherCommitHash) {
|
||||||
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
|
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
|
||||||
$output = " latest-testing $commitHash Commit message\n* current $anotherCommitHash Another message\n";
|
$output = " latest-testing $commitHash Commit message\n* feature $anotherCommitHash Another message\n";
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
})
|
})
|
||||||
|
@ -278,18 +244,8 @@ class VersionGuesserTest extends TestCase
|
||||||
$executor
|
$executor
|
||||||
->expects($this->at(1))
|
->expects($this->at(1))
|
||||||
->method('execute')
|
->method('execute')
|
||||||
->willReturnCallback(function ($command, &$output) use ($self) {
|
|
||||||
$self->assertEquals('git remote show origin', $command);
|
|
||||||
$output = " HEAD branch: foo\r\n";
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
})
|
|
||||||
;
|
|
||||||
$executor
|
|
||||||
->expects($this->at(2))
|
|
||||||
->method('execute')
|
|
||||||
->willReturnCallback(function ($command, &$output, $path) use ($self, $anotherCommitHash) {
|
->willReturnCallback(function ($command, &$output, $path) use ($self, $anotherCommitHash) {
|
||||||
$self->assertEquals('git rev-list latest-testing..current', $command);
|
$self->assertEquals('git rev-list latest-testing..feature', $command);
|
||||||
$output = "$anotherCommitHash\n";
|
$output = "$anotherCommitHash\n";
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -303,8 +259,8 @@ class VersionGuesserTest extends TestCase
|
||||||
|
|
||||||
$this->assertEquals("dev-latest-testing", $versionArray['version']);
|
$this->assertEquals("dev-latest-testing", $versionArray['version']);
|
||||||
$this->assertEquals($anotherCommitHash, $versionArray['commit']);
|
$this->assertEquals($anotherCommitHash, $versionArray['commit']);
|
||||||
$this->assertEquals("dev-current", $versionArray['feature_version']);
|
$this->assertEquals("dev-feature", $versionArray['feature_version']);
|
||||||
$this->assertEquals("dev-current", $versionArray['feature_pretty_version']);
|
$this->assertEquals("dev-feature", $versionArray['feature_pretty_version']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGuessVersionReadsAndRespectsNonFeatureBranchesConfigurationForArbitraryNamingWhenOnNonFeatureBranch()
|
public function testGuessVersionReadsAndRespectsNonFeatureBranchesConfigurationForArbitraryNamingWhenOnNonFeatureBranch()
|
||||||
|
@ -459,16 +415,6 @@ class VersionGuesserTest extends TestCase
|
||||||
$executor
|
$executor
|
||||||
->expects($this->at(1))
|
->expects($this->at(1))
|
||||||
->method('execute')
|
->method('execute')
|
||||||
->willReturnCallback(function ($command, &$output) use ($self) {
|
|
||||||
$self->assertEquals('git remote show origin', $command);
|
|
||||||
$output = " HEAD branch: foo\r\n";
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
})
|
|
||||||
;
|
|
||||||
$executor
|
|
||||||
->expects($this->at(2))
|
|
||||||
->method('execute')
|
|
||||||
->willReturnCallback(function ($command, &$output) use ($self) {
|
->willReturnCallback(function ($command, &$output) use ($self) {
|
||||||
$self->assertEquals('git describe --exact-match --tags', $command);
|
$self->assertEquals('git describe --exact-match --tags', $command);
|
||||||
$output = "v2.0.5-alpha2";
|
$output = "v2.0.5-alpha2";
|
||||||
|
@ -509,16 +455,6 @@ class VersionGuesserTest extends TestCase
|
||||||
$executor
|
$executor
|
||||||
->expects($this->at(1))
|
->expects($this->at(1))
|
||||||
->method('execute')
|
->method('execute')
|
||||||
->willReturnCallback(function ($command, &$output) use ($self) {
|
|
||||||
$self->assertEquals('git remote show origin', $command);
|
|
||||||
$output = " HEAD branch: foo\r\n";
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
})
|
|
||||||
;
|
|
||||||
$executor
|
|
||||||
->expects($this->at(2))
|
|
||||||
->method('execute')
|
|
||||||
->willReturnCallback(function ($command, &$output) use ($self) {
|
->willReturnCallback(function ($command, &$output) use ($self) {
|
||||||
$self->assertEquals('git describe --exact-match --tags', $command);
|
$self->assertEquals('git describe --exact-match --tags', $command);
|
||||||
$output = '1.0.0';
|
$output = '1.0.0';
|
||||||
|
|
|
@ -49,9 +49,9 @@ class VersionParserTest extends TestCase
|
||||||
return array(
|
return array(
|
||||||
array('0.9.0.0', '1.0.0.0', true),
|
array('0.9.0.0', '1.0.0.0', true),
|
||||||
array('1.0.0.0', '0.9.0.0', false),
|
array('1.0.0.0', '0.9.0.0', false),
|
||||||
array('1.0.0.0', VersionParser::DEV_MASTER_ALIAS, true),
|
array('1.0.0.0', VersionParser::DEFAULT_BRANCH_ALIAS, true),
|
||||||
array(VersionParser::DEV_MASTER_ALIAS, VersionParser::DEV_MASTER_ALIAS, true),
|
array(VersionParser::DEFAULT_BRANCH_ALIAS, VersionParser::DEFAULT_BRANCH_ALIAS, true),
|
||||||
array(VersionParser::DEV_MASTER_ALIAS, '1.0.0.0', false),
|
array(VersionParser::DEFAULT_BRANCH_ALIAS, '1.0.0.0', false),
|
||||||
array('1.0.0.0', 'dev-foo', true),
|
array('1.0.0.0', 'dev-foo', true),
|
||||||
array('dev-foo', 'dev-foo', true),
|
array('dev-foo', 'dev-foo', true),
|
||||||
array('dev-foo', '1.0.0.0', true),
|
array('dev-foo', '1.0.0.0', true),
|
||||||
|
|
Loading…
Reference in New Issue