Merge branch 'master' into code-improvements

main
Jordi Boggiano 4 years ago committed by GitHub
commit 24abd233ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -75,17 +75,17 @@ jobs:
if: "!startsWith(matrix.os, 'windows')"
run: |
if [ "${{ matrix.php-version }}" = "5.3" ] || [ "${{ matrix.php-version }}" = "5.4" ] || [ "${{ matrix.php-version }}" = "5.5" ]; then
echo "::set-env name=SYMFONY_PHPUNIT_VERSION::4.8";
echo "SYMFONY_PHPUNIT_VERSION=4.8" >> $GITHUB_ENV;
elif [ "${{ matrix.php-version }}" = "5.6" ]; then
echo "::set-env name=SYMFONY_PHPUNIT_VERSION::5.7";
echo "SYMFONY_PHPUNIT_VERSION=5.7" >> $GITHUB_ENV;
elif [ "${{ matrix.php-version }}" = "7.0" ]; then
echo "::set-env name=SYMFONY_PHPUNIT_VERSION::6.5";
echo "SYMFONY_PHPUNIT_VERSION=6.5" >> $GITHUB_ENV;
elif [ "${{ matrix.php-version }}" = "7.1" ]; then
echo "::set-env name=SYMFONY_PHPUNIT_VERSION::7.5";
echo "SYMFONY_PHPUNIT_VERSION=7.5" >> $GITHUB_ENV;
elif [ "${{ matrix.php-version }}" = "8.0" ]; then
echo "::set-env name=SYMFONY_PHPUNIT_VERSION::9.3";
echo "SYMFONY_PHPUNIT_VERSION=9.3" >> $GITHUB_ENV;
else
echo "::set-env name=SYMFONY_PHPUNIT_VERSION::8.3";
echo "SYMFONY_PHPUNIT_VERSION=8.3" >> $GITHUB_ENV;
fi
- name: "Install PHP"
@ -99,11 +99,11 @@ jobs:
- name: "Handle lowest dependencies update"
if: "contains(matrix.dependencies, 'lowest')"
run: "echo \"::set-env name=COMPOSER_UPDATE_FLAGS::$COMPOSER_UPDATE_FLAGS --prefer-lowest\""
run: "echo \"COMPOSER_UPDATE_FLAGS=$COMPOSER_UPDATE_FLAGS --prefer-lowest\" >> $GITHUB_ENV"
- name: "Handle ignore-platform-reqs dependencies update"
if: "contains(matrix.dependencies, 'ignore')"
run: "echo \"::set-env name=COMPOSER_FLAGS::$COMPOSER_FLAGS --ignore-platform-req=php\""
run: "echo \"COMPOSER_FLAGS=$COMPOSER_FLAGS --ignore-platform-req=php\" >> $GITHUB_ENV"
- name: "Remove platform config to get latest dependencies for current PHP version when build is not locked"
run: "composer config platform --unset"

@ -11,6 +11,7 @@
- PEAR support (repository, downloader, etc.) has been removed
- `update` now lists changes to the lock file first (update step), and then the changes applied when installing the lock file to the vendor dir (install step)
- `HTTPS_PROXY_REQUEST_FULLURI` if not specified will now default to false as this seems to work better in most environments
- `dev-trunk`, `dev-master` and `dev-default` are no longer aliases for each other. The exact branch names are now preserved.
## For integrators and plugin authors
@ -28,7 +29,8 @@
- 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
- 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 cannot be overridden by listeners anymore
- Removed `OperationInterface::getReason` as the data was not accurate. There is no replacement available.
- `PreFileDownloadEvent` now receives an `HttpDownloader` instance instead of `RemoteFilesystem`, and that instance cannot be overridden by listeners anymore, you can however call setProcessedUrl or setCustomCacheKey.
- `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
- `IOInterface` now extends PSR-3's `LoggerInterface`, and has new `writeRaw` + `writeErrorRaw` methods
@ -44,8 +46,32 @@
- `prepare` (do user prompts or any checks which need to happen to make sure that install/update/remove will most likely succeed), `install` (should do the non-network part that `download` used to do) and `cleanup` (cleaning up anything that may be left over) were added as new steps in the package install flow
- All packages get first downloaded, then all together prepared, then all together installed/updated/uninstalled, then finally cleanup is called for all. Therefore for error recovery it is important to avoid failing during install/update/uninstall as much as possible, and risky things or user prompts should happen in the prepare step rather. In case of failure, cleanup() will be called so that changes can be undone as much as possible.
- If you used `RemoteFilesystem` you probably should use `HttpDownloader` instead now
- `PRE_DEPENDENCIES_SOLVING` and `POST_DEPENDENCIES_SOLVING` events have been removed, use the new `PRE_OPERATIONS_EXEC` or other existing events instead or talk to us if you think you really need this
- `PRE_DEPENDENCIES_SOLVING` and `POST_DEPENDENCIES_SOLVING` events have been removed, use the new `PRE_OPERATIONS_EXEC`, `PRE_POOL_CREATE` or other existing events instead or talk to us if you think you really need this. See below for more details.
- The bundled composer/semver is now the 3.x range, see release notes for [2.0](https://github.com/composer/semver/releases/tag/2.0.0) and [3.0](https://github.com/composer/semver/releases/tag/3.0.0) for the minor breaking changes there
- Run Composer with COMPOSER_DEBUG_EVENTS=1 set in the environment to show which events happen which might help you.
### Detailed differences in event flow during dependency resolution, composer updates and installs
#### Composer v1
- Composer resolves dependencies (dispatching PRE/POST_DEPENDENCIES_SOLVING)
- It then iterates over all packages one by one (dispatching PRE_PACKAGE_INSTALL/UPDATE/UNINSTALL, then PRE_FILE_DOWNLOAD if needed, then POST_PACKAGE_*)
- And finally writes the lock file at the end
#### Composer v2
The update and install process have been split up.
Update does:
- Composer resolves dependencies (dispatching PRE_POOL_CREATE)
- It then writes the lock file and that's the end of the update
Install then does:
- Dispatches PRE_OPERATIONS_EXEC with the full list of operations to be executed
- Downloads all the packages not in cache yet in parallel (dispatching PRE_FILE_DOWNLOAD for those not in cache yet)
- It then iterates over all packages and executes updates/installs/uninstalls in parallel (dispatching PRE_PACKAGE_INSTALL/UPDATE/UNINSTALL then POST_PACKAGE_* but one package started last may finish installing before another is done for example).
## For Composer repository implementors

12
composer.lock generated

@ -83,16 +83,16 @@
},
{
"name": "composer/semver",
"version": "3.2.0",
"version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "da7ce661431b17a71271cdf7f5437dc722133123"
"reference": "ebb714493b3a54f1dbbec6b15ab7bc9b3440e17b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/da7ce661431b17a71271cdf7f5437dc722133123",
"reference": "da7ce661431b17a71271cdf7f5437dc722133123",
"url": "https://api.github.com/repos/composer/semver/zipball/ebb714493b3a54f1dbbec6b15ab7bc9b3440e17b",
"reference": "ebb714493b3a54f1dbbec6b15ab7bc9b3440e17b",
"shasum": ""
},
"require": {
@ -144,7 +144,7 @@
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.2.0"
"source": "https://github.com/composer/semver/tree/3.2.1"
},
"funding": [
{
@ -160,7 +160,7 @@
"type": "tidelift"
}
],
"time": "2020-09-09T09:39:19+00:00"
"time": "2020-09-27T13:14:03+00:00"
},
{
"name": "composer/spdx-licenses",

@ -13,7 +13,10 @@ a logging library. If you have not yet installed Composer, refer to the
To start using Composer in your project, all you need is a `composer.json`
file. This file describes the dependencies of your project and may contain
other metadata as well.
other metadata as well. It typically should go in the top-most directory of
your project/VCS repository. You can technically run Composer anywhere but
if you want to publish a package to Packagist.org, it will have to be able
to find the file at the top of your VCS repository.
### The `require` key

@ -112,6 +112,8 @@ resolution.
* **--classmap-authoritative (-a):** Autoload classes from the classmap only.
Implicitly enables `--optimize-autoloader`.
* **--apcu-autoloader:** Use APCu to cache found/not-found classes.
* **--apcu-autoloader-prefix:** Use a custom prefix for the APCu autoloader cache.
Implicitly enables `--apcu-autoloader`.
* **--ignore-platform-reqs:** ignore all platform requirements (`php`, `hhvm`,
`lib-*` and `ext-*`) and force the installation even if the local machine does
not fulfill these.
@ -181,14 +183,16 @@ php composer.phar update vendor/package:2.0.1 vendor/package2:3.0.*
* **--no-scripts:** Skips execution of scripts defined in `composer.json`.
* **--no-progress:** Removes the progress display that can mess with some
terminals or scripts which don't handle backspace characters.
* **--with-dependencies:** Update also dependencies of packages in the argument list, except those which are root requirements.
* **--with-all-dependencies:** Update also dependencies of packages in the argument list, including those which are root requirements.
* **--with-dependencies (-w):** Update also dependencies of packages in the argument list, except those which are root requirements.
* **--with-all-dependencies (-W):** 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
autoloader. This is recommended especially for production, but 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.
Implicitly enables `--optimize-autoloader`.
* **--apcu-autoloader:** Use APCu to cache found/not-found classes.
* **--apcu-autoloader-prefix:** Use a custom prefix for the APCu autoloader cache.
Implicitly enables `--apcu-autoloader`.
* **--ignore-platform-reqs:** ignore all platform requirements (`php`, `hhvm`,
`lib-*` and `ext-*`) and force the installation even if the local machine does
not fulfill these.
@ -237,8 +241,8 @@ If you do not specify a package, composer will prompt you to search for a packag
* **--no-install:** Does not run the install step after updating the composer.lock file.
* **--no-scripts:** Skips execution of scripts defined in `composer.json`.
* **--update-no-dev:** Run the dependency update with the `--no-dev` option.
* **--update-with-dependencies:** Also update dependencies of the newly required packages, except those that are root requirements.
* **--update-with-all-dependencies:** Also update dependencies of the newly required packages, including those that are root requirements.
* **--update-with-dependencies (-w):** Also update dependencies of the newly required packages, except those that are root requirements.
* **--update-with-all-dependencies (-W):** Also update dependencies of the newly required packages, including those that are root requirements.
* **--ignore-platform-reqs:** ignore all platform requirements (`php`, `hhvm`,
`lib-*` and `ext-*`) and force the installation even if the local machine does
not fulfill these.
@ -256,6 +260,8 @@ If you do not specify a package, composer will prompt you to search for a packag
* **--classmap-authoritative (-a):** Autoload classes from the classmap only.
Implicitly enables `--optimize-autoloader`.
* **--apcu-autoloader:** Use APCu to cache found/not-found classes.
* **--apcu-autoloader-prefix:** Use a custom prefix for the APCu autoloader cache.
Implicitly enables `--apcu-autoloader`.
## remove
@ -278,7 +284,10 @@ uninstalled.
* **--no-install:** Does not run the install step after updating the composer.lock file.
* **--no-scripts:** Skips execution of scripts defined in `composer.json`.
* **--update-no-dev:** Run the dependency update with the --no-dev option.
* **--update-with-dependencies:** Also update dependencies of the removed packages.
* **--update-with-dependencies (-w):** Also update dependencies of the removed packages.
(Deprecrated, is now default behavior)
* **--update-with-all-dependencies (-W):** Allows all inherited dependencies to be updated,
including those that are root requirements.
* **--ignore-platform-reqs:** ignore all platform requirements (`php`, `hhvm`,
`lib-*` and `ext-*`) and force the installation even if the local machine does
not fulfill these.
@ -292,6 +301,8 @@ uninstalled.
* **--classmap-authoritative (-a):** Autoload classes from the classmap only.
Implicitly enables `--optimize-autoloader`.
* **--apcu-autoloader:** Use APCu to cache found/not-found classes.
* **--apcu-autoloader-prefix:** Use a custom prefix for the APCu autoloader cache.
Implicitly enables `--apcu-autoloader`.
## check-platform-reqs
@ -771,6 +782,8 @@ performance.
* **--classmap-authoritative (-a):** Autoload classes from the classmap only.
Implicitly enables `--optimize`.
* **--apcu:** Use APCu to cache found/not-found classes.
* **--apcu-prefix:** Use a custom prefix for the APCu autoloader cache.
Implicitly enables `--apcu`.
* **--no-dev:** Disables autoload-dev rules.
* **--ignore-platform-reqs:** ignore all `php`, `hhvm`, `lib-*` and `ext-*`
requirements and skip the [platform check](07-runtime.md#platform-check) for these.
@ -1026,4 +1039,9 @@ 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
fully offline with `1`.
### COMPOSER_DEBUG_EVENTS
If set to `1`, outputs information about events being dispatched, which can be
useful for plugin authors to identify what is firing when exactly.
← [Libraries](02-libraries.md) | [Schema](04-schema.md) →

@ -507,7 +507,7 @@ package repository definitions. It will fetch all the packages that are
`require`d and dump a `packages.json` that is your `composer` repository.
Check [the satis GitHub repository](https://github.com/composer/satis) and
the [Satis article](articles/handling-private-packages-with-satis.md) for more
the [handling private packages article](articles/handling-private-packages.md) for more
information.
### Artifact

@ -101,7 +101,8 @@ gitlab.com the domain names must be also specified with the
Defaults to `false`. If set to true all HTTPS URLs will be tried with HTTP
instead and no network level encryption is performed. Enabling this is a
security risk and is NOT recommended. The better way is to enable the
php_openssl extension in php.ini.
php_openssl extension in php.ini. Enabling this will implicitly disable the
`secure-http` option.
## secure-http

@ -0,0 +1,226 @@
<!--
tagline: Access privately hosted packages
-->
# Authentication for privately hosted packages
Your [private package server](handling-private-packages.md) is probably secured with one
or more authentication options. In order to allow your project to have access to these
packages you will have to tell Composer how to authenticate with the server that hosts the
package(s).
# Authentication principles
Whenever Composer encounters a protected Composer repository it will try to authenticate
using already defined credentials first. When none of those credentials apply it will prompt
for credentials and save them (or a token if Composer is able to retrieve one).
|type|Generated by Prompt?|
|---|---|
|[http-basic](#http-basic)|yes|
|[Inline http-basic](#inline-http-basic)|no|
|[Custom header](#custom-token-authentication)|no|
|[gitlab-oauth](#gitlab-oauth)|yes|
|[gitlab-token](#gitlab-token)|yes|
Sometimes automatic authentication is not possible, or you may want to predefine
authentication credentials.
Credentials can be stored on 3 different places; in an `auth.json` for the project, a global
`auth.json` or in the `composer.json` itself.
## Authentication in auth.json per project
In this authentication storage method, an `auth.json` file will be present in the same folder
as the projects' `composer.json` file. You can either create and edit this file using the
command line or manually edit or create it.
> **Note: Make sure the `auth.json` file is in `.gitignore`** to avoid
> leaking credentials into your git history.
## Global authentication credentials
If you don't want to supply credentials for every project you work on, storing your credentials
globally might be a better idea. These credentials are stored in a global `auth.json` in your
Composer home directory.
### Command line global credential editing
For all authentication methods it is possible to edit them using the command line;
- [http-basic](#command-line-http-basic)
- [Inline http-basic](#command-line-inline-http-basic)
- [gitlab-oauth](#command-line-gitlab-oauth)
- [gitlab-token](#command-line-gitlab-token)
### Manually editing global authentication credentials
> **Note:** It is not recommended to manually edit your authentication options as this might
> result in invalid json. Instead preferably use [the command line](#command-line-global-credential-editing).
To manually edit it, run:
```sh
composer config --global --editor [--auth]
```
For specific authentication implementations, see their sections;
- [http-basic](#manual-http-basic)
- [Inline http-basic](#manual-inline-http-basic)
- [custom header](#manual-custom-token-authentication)
- [gitlab-oauth](#manual-gitlab-oauth)
- [gitlab-token](#manual-gitlab-token)
Manually editing this file instead of using the command line may result in invalid json errors.
To fix this you need to open the file in an editor and fix the error. To find the location of
your global `auth.json`, execute:
```sh
composer config --global --list
```
And look for the `[home]` section. (It is by default `~/.composer` or `%APPDATA%/Composer` on Windows)
The folder will contain your global `auth.json` if it exists.
You can open this file in your favorite editor and fix the error.
## Authentication in composer.json file itself
> **Note:** **This is not recommended** as these credentials are visible
> to anyone who has access to the composer.json, either when it is shared through
> a version control system like git or when an attacker gains (read) access to
> your production server files.
It is also possible to add credentials to a `composer.json` on a per-project basis in the `config`
section or directly in the repository definition.
# Authentication methods
## http-basic
### Command line http-basic
```sh
composer config [--global] http-basic.example.org username password
```
### Manual http-basic
```sh
composer config [--global] --editor --auth
```
```json
{
"http-basic": {
"example.org": {
"username": "username",
"password": "password"
}
}
}
```
## Inline http-basic
For the inline http-basic authentication method the credentials are not stored in a separate
`auth.json` in the project or globally, but in the `composer.json` or global configuration
in the same place where the Composer repository definition is defined.
### Command line inline http-basic
```sh
composer config [--global] repositories composer.unique-name https://username:password@repo.example.org
```
### Manual inline http-basic
```sh
composer config [--global] --editor
```
```json
{
"repositories": [
{
"type": "composer",
"url": "https://username:password@example.org"
}
]
}
```
## Custom token authentication
### Manual custom token authentication
```sh
composer config [--global] --editor
```
```json
{
"repositories": [
{
"type": "composer",
"url": "https://example.org",
"options": {
"http": {
"header": [
"API-TOKEN: YOUR-API-TOKEN"
]
}
}
}
]
}
```
## gitlab-oauth
> **Note:** For the gitlab authentication to work on private gitlab instances, the
> [`gitlab-domains`](../06-config.md#gitlab-domains) section should also contain the url.
### Command line gitlab-oauth
```sh
composer config [--global] gitlab-oauth.example.org token
```
### Manual gitlab-oauth
```sh
composer config [--global] --editor --auth
```
```json
{
"gitlab-oauth": {
"example.org": "token"
}
}
```
## gitlab-token
> **Note:** For the gitlab authentication to work on private gitlab instances, the
> [`gitlab-domains`](../06-config.md#gitlab-domains) section should also contain the url.
### Command line gitlab-token
```sh
composer config [--global] gitlab-token.example.org token
```
### Manual gitlab-token
```sh
composer config [--global] --editor --auth
```
```json
{
"gitlab-token": {
"example.org": "token"
}
}
```

@ -213,23 +213,7 @@ Example using a custom HTTP Header field for token authentication:
### Authentication
When your private repositories are password protected, you can store the
authentication details permanently. The first time Composer needs to
authenticate against some domain it will prompt you for a username/password and
then you will be asked whether you want to store it.
The storage can be done either globally in the `COMPOSER_HOME/auth.json` file
(`COMPOSER_HOME` defaults to `~/.composer` or `%APPDATA%/Composer` on Windows)
or also in the project directory directly sitting besides your composer.json.
You can also configure these by hand using the config command if you need to
configure a production machine to be able to run non-interactive installs. For
example to enter credentials for example.org one could type:
composer config http-basic.example.org username password
That will store it in the current directory's auth.json, but if you want it
available globally you can use the `--global` (`-g`) flag.
Authentication can be handled in [several different ways](authentication-for-private-packages.md).
### Downloads

@ -1,59 +0,0 @@
<!--
tagline: Access privately hosted packages
-->
# HTTP basic authentication
Your [Satis or Private Packagist](handling-private-packages-with-satis.md) server
could be secured with http basic authentication. In order to allow your project
to have access to these packages you will have to tell composer how to
authenticate with your credentials.
The simplest way to provide your credentials is providing your set
of credentials inline with the repository specification such as:
```json
{
"repositories": [
{
"type": "composer",
"url": "https://extremely:secret@repo.example.org"
}
]
}
```
This will basically teach composer how to authenticate automatically
when reading packages from the provided composer repository.
This does not work for everybody especially when you don't want to
hard code your credentials into your composer.json. There is a second
way to provide these details and it is via interaction. If you don't
provide the authentication credentials composer will prompt you upon
connection to enter the username and password.
The third way if you want to pre-configure it is via an `auth.json` file
located in your `COMPOSER_HOME` or besides your `composer.json`.
The file should contain a set of hostnames followed each with their own
username/password pairs, for example:
```json
{
"http-basic": {
"repo.example1.org": {
"username": "my-username1",
"password": "my-secret-password1"
},
"repo.example2.org": {
"username": "my-username2",
"password": "my-secret-password2"
}
}
}
```
The main advantage of the auth.json file is that it can be gitignored so
that every developer in your team can place their own credentials in there,
which makes revocation of credentials much easier than if you all share the
same.

@ -94,6 +94,10 @@ and have it return an array. The array key must be the
[event name](https://getcomposer.org/doc/articles/scripts.md#event-names)
and the value is the name of the method in this class to be called.
> **Note:** If you don't know which event to listen to, you can run a Composer
> command with the COMPOSER_DEBUG_EVENTS=1 environment variable set, which might
> help you identify what event you are looking for.
```php
public static function getSubscribedEvents()
{
@ -223,7 +227,7 @@ class Plugin implements PluginInterface, Capable
### Command provider
The [`Composer\Plugin\Capability\CommandProvider`][9] capability allows to register
additional commands for Composer :
additional commands for Composer:
```php
<?php
@ -263,7 +267,7 @@ Now the `custom-plugin-command` is available alongside Composer commands.
## Running plugins manually
Plugins for an event can be run manually by the `run-script` command. This works the same way as
Plugins for an event can be run manually by the `run-script` command. This works the same way as
[running scripts manually](scripts.md#running-scripts-manually).
## Using Plugins

@ -351,7 +351,7 @@
},
"classmap": {
"type": "array",
"description": "This is an array of directories that contain classes to be included in the class-map generation process."
"description": "This is an array of paths that contain classes to be included in the class-map generation process."
},
"files": {
"type": "array",
@ -638,7 +638,7 @@
},
"classmap": {
"type": "array",
"description": "This is an array of directories that contain classes to be included in the class-map generation process."
"description": "This is an array of paths that contain classes to be included in the class-map generation process."
},
"files": {
"type": "array",

@ -57,6 +57,11 @@ class AutoloadGenerator
*/
private $apcu = false;
/**
* @var string|null
*/
private $apcuPrefix;
/**
* @var bool
*/
@ -92,11 +97,13 @@ class AutoloadGenerator
/**
* Whether or not generated autoloader considers APCu caching.
*
* @param bool $apcu
* @param bool $apcu
* @param string|null $apcuPrefix
*/
public function setApcu($apcu)
public function setApcu($apcu, $apcuPrefix = null)
{
$this->apcu = (bool) $apcu;
$this->apcuPrefix = $apcuPrefix !== null ? (string) $apcuPrefix : $apcuPrefix;
}
/**
@ -858,9 +865,9 @@ CLASSMAPAUTHORITATIVE;
}
if ($this->apcu) {
$apcuPrefix = substr(base64_encode(md5(uniqid('', true), true)), 0, -3);
$apcuPrefix = var_export(($this->apcuPrefix !== null ? $this->apcuPrefix : substr(base64_encode(md5(uniqid('', true), true)), 0, -3)), true);
$file .= <<<APCU
\$loader->setApcuPrefix('$apcuPrefix');
\$loader->setApcuPrefix($apcuPrefix);
APCU;
}

@ -172,7 +172,7 @@ EOT
$io->write(sprintf('PHP binary path: <comment>%s</comment>', PHP_BINARY));
}
$io->write(sprintf('OpenSSL version: <comment>%s</comment>', OPENSSL_VERSION_TEXT));
$io->write('OpenSSL version: ' . (defined('OPENSSL_VERSION_TEXT') ? '<comment>'.OPENSSL_VERSION_TEXT.'</comment>' : '<error>missing</error>'));
return $this->exitCode;
}

@ -34,6 +34,7 @@ class DumpAutoloadCommand extends BaseCommand
new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.'),
new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize`.'),
new InputOption('apcu', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
new InputOption('apcu-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu'),
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules.'),
new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'),
new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'),
@ -62,7 +63,8 @@ EOT
$optimize = $input->getOption('optimize') || $config->get('optimize-autoloader');
$authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
$apcu = $input->getOption('apcu') || $config->get('apcu-autoloader');
$apcuPrefix = $input->getOption('apcu-prefix');
$apcu = $apcuPrefix !== null || $input->getOption('apcu') || $config->get('apcu-autoloader');
if ($authoritative) {
$this->getIO()->write('<info>Generating optimized autoload files (authoritative)</info>');
@ -77,7 +79,7 @@ EOT
$generator = $composer->getAutoloadGenerator();
$generator->setDevMode(!$input->getOption('no-dev'));
$generator->setClassMapAuthoritative($authoritative);
$generator->setApcu($apcu);
$generator->setApcu($apcu, $apcuPrefix);
$generator->setRunScripts(!$input->getOption('no-scripts'));
$generator->setIgnorePlatformRequirements($ignorePlatformReqs);
$numberOfClasses = $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);

@ -75,6 +75,12 @@ EOT
return parent::run($input, $output);
}
// The COMPOSER env var should not apply to the global execution scope
if (getenv('COMPOSER')) {
putenv('COMPOSER');
unset($_SERVER['COMPOSER']);
}
// change to global dir
$config = Factory::createConfig();
$home = $config->get('home');

@ -457,10 +457,7 @@ EOT
$existingPackages[] = $package->getName();
}
}
foreach ($requires as $requiredPackage) {
$existingPackages[] = substr($requiredPackage, 0, strpos($requiredPackage, ' '));
}
unset($composer, $installedRepo, $requiredPackage);
unset($composer, $installedRepo);
$io = $this->getIO();
while (null !== $package = $io->ask('Search for a package: ')) {

@ -49,6 +49,7 @@ class InstallCommand extends BaseCommand
new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader'),
new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'),
new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'),
new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.'),
@ -102,7 +103,8 @@ EOT
$optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
$authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
$apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
$apcuPrefix = $input->getOption('apcu-autoloader-prefix');
$apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
$ignorePlatformReqs = $input->getOption('ignore-platform-reqs') ?: ($input->getOption('ignore-platform-req') ?: false);
@ -118,7 +120,7 @@ EOT
->setRunScripts(!$input->getOption('no-scripts'))
->setOptimizeAutoloader($optimize)
->setClassMapAuthoritative($authoritative)
->setApcuAutoloader($apcu)
->setApcuAutoloader($apcu, $apcuPrefix)
->setIgnorePlatformRequirements($ignorePlatformReqs)
;

@ -45,8 +45,8 @@ class RemoveCommand extends BaseCommand
new InputOption('no-install', null, InputOption::VALUE_NONE, 'Skip the install step after updating the composer.lock file.'),
new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies. (Deprecrated, is now default behavior)'),
new InputOption('update-with-all-dependencies', null, InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
new InputOption('update-with-dependencies', 'w', InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies. (Deprecrated, is now default behavior)'),
new InputOption('update-with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
new InputOption('with-all-dependencies', null, InputOption::VALUE_NONE, 'Alias for --update-with-all-dependencies'),
new InputOption('no-update-with-dependencies', null, InputOption::VALUE_NONE, 'Does not allow inherited dependencies to be updated with explicit dependencies.'),
new InputOption('unused', null, InputOption::VALUE_NONE, 'Remove all packages which are locked but not required by any other package.'),
@ -55,6 +55,7 @@ class RemoveCommand extends BaseCommand
new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader'),
))
->setHelp(
<<<EOT
@ -227,7 +228,8 @@ EOT
$updateDevMode = !$input->getOption('update-no-dev');
$optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
$authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
$apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
$apcuPrefix = $input->getOption('apcu-autoloader-prefix');
$apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
$updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE;
$flags = '';
@ -248,8 +250,8 @@ EOT
->setDevMode($updateDevMode)
->setOptimizeAutoloader($optimize)
->setClassMapAuthoritative($authoritative)
->setApcuAutoloader($apcu)
->setUpdate()
->setApcuAutoloader($apcu, $apcuPrefix)
->setUpdate(true)
->setInstall(!$input->getOption('no-install'))
->setUpdateAllowList($packages)
->setUpdateAllowTransitiveDependencies($updateAllowTransitiveDependencies)

@ -65,8 +65,8 @@ class RequireCommand extends InitCommand
new InputOption('no-install', null, InputOption::VALUE_NONE, 'Skip the install step after updating the composer.lock file.'),
new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated, except those that are root requirements.'),
new InputOption('update-with-all-dependencies', null, InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
new InputOption('update-with-dependencies', 'w', InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated, except those that are root requirements.'),
new InputOption('update-with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Alias for --update-with-dependencies'),
new InputOption('with-all-dependencies', null, InputOption::VALUE_NONE, 'Alias for --update-with-all-dependencies'),
new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'),
@ -77,6 +77,7 @@ class RequireCommand extends InitCommand
new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader'),
))
->setHelp(
<<<EOT
@ -269,7 +270,8 @@ EOT
$updateDevMode = !$input->getOption('update-no-dev');
$optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
$authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
$apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
$apcuPrefix = $input->getOption('apcu-autoloader-prefix');
$apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
$updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED;
$flags = '';
@ -301,8 +303,8 @@ EOT
->setRunScripts(!$input->getOption('no-scripts'))
->setOptimizeAutoloader($optimize)
->setClassMapAuthoritative($authoritative)
->setApcuAutoloader($apcu)
->setUpdate()
->setApcuAutoloader($apcu, $apcuPrefix)
->setUpdate(true)
->setInstall(!$input->getOption('no-install'))
->setUpdateAllowTransitiveDependencies($updateAllowTransitiveDependencies)
->setIgnorePlatformRequirements($ignorePlatformReqs)

@ -17,6 +17,7 @@ use Composer\DependencyResolver\DefaultPolicy;
use Composer\Json\JsonFile;
use Composer\Package\BasePackage;
use Composer\Package\CompletePackageInterface;
use Composer\Package\Link;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionParser;
use Composer\Package\Version\VersionSelector;
@ -613,8 +614,8 @@ EOT
$io = $this->getIO();
$this->printMeta($package, $versions, $installedRepo, $latestPackage ?: null);
$this->printLinks($package, 'requires');
$this->printLinks($package, 'devRequires', 'requires (dev)');
$this->printLinks($package, Link::TYPE_REQUIRE);
$this->printLinks($package, Link::TYPE_DEV_REQUIRE, 'requires (dev)');
if ($package->getSuggests()) {
$io->write("\n<info>suggests</info>");
@ -623,9 +624,9 @@ EOT
}
}
$this->printLinks($package, 'provides');
$this->printLinks($package, 'conflicts');
$this->printLinks($package, 'replaces');
$this->printLinks($package, Link::TYPE_PROVIDE);
$this->printLinks($package, Link::TYPE_CONFLICT);
$this->printLinks($package, Link::TYPE_REPLACE);
}
/**
@ -911,7 +912,7 @@ EOT
private function appendLinks($json, CompletePackageInterface $package)
{
foreach (array('requires', 'devRequires', 'provides', 'conflicts', 'replaces') as $linkType) {
foreach (Link::$TYPES as $linkType) {
$json = $this->appendLink($json, $package, $linkType);
}

@ -43,7 +43,7 @@ class StatusCommand extends BaseCommand
{
$this
->setName('status')
->setDescription('Shows a list of locally modified packages, for packages installed from source.')
->setDescription('Shows a list of locally modified packages.')
->setDefinition(array(
new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Show modified files for each directory that contains changes.'),
))

@ -54,12 +54,13 @@ class UpdateCommand extends BaseCommand
new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'DEPRECATED: This flag does not exist anymore.'),
new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Update also dependencies of packages in the argument list, except those which are root requirements.'),
new InputOption('with-all-dependencies', null, InputOption::VALUE_NONE, 'Update also dependencies of packages in the argument list, including those which are root requirements.'),
new InputOption('with-dependencies', 'w', InputOption::VALUE_NONE, 'Update also dependencies of packages in the argument list, except those which are root requirements.'),
new InputOption('with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Update also dependencies of packages in the argument list, including those which are root requirements.'),
new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'),
new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader'),
new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'),
new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'),
new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
@ -189,7 +190,8 @@ EOT
$optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
$authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
$apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
$apcuPrefix = $input->getOption('apcu-autoloader-prefix');
$apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
$updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED;
if ($input->getOption('with-all-dependencies')) {
@ -210,8 +212,8 @@ EOT
->setRunScripts(!$input->getOption('no-scripts'))
->setOptimizeAutoloader($optimize)
->setClassMapAuthoritative($authoritative)
->setApcuAutoloader($apcu)
->setUpdate()
->setApcuAutoloader($apcu, $apcuPrefix)
->setUpdate(true)
->setInstall(!$input->getOption('no-install'))
->setUpdateMirrors($updateMirrors)
->setUpdateAllowList($packages)

@ -253,6 +253,11 @@ class Config
case 'secure-http':
case 'use-github-api':
case 'lock':
// special case for secure-http
if ($key === 'secure-http' && $this->get('disable-tls') === true) {
return false;
}
return $this->config[$key] !== 'false' && (bool) $this->config[$key];
// ints without env var support

@ -19,7 +19,7 @@ use Composer\Package\PackageInterface;
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class InstallOperation extends SolverOperation
class InstallOperation implements OperationInterface
{
protected $package;
@ -27,12 +27,9 @@ class InstallOperation extends SolverOperation
* Initializes operation.
*
* @param PackageInterface $package package instance
* @param string $reason operation reason
*/
public function __construct(PackageInterface $package, $reason = null)
public function __construct(PackageInterface $package)
{
parent::__construct($reason);
$this->package = $package;
}

@ -20,7 +20,7 @@ use Composer\Package\PackageInterface;
*
* @author Nils Adermann <naderman@naderman.de>
*/
class MarkAliasInstalledOperation extends SolverOperation
class MarkAliasInstalledOperation implements OperationInterface
{
protected $package;
@ -28,12 +28,9 @@ class MarkAliasInstalledOperation extends SolverOperation
* Initializes operation.
*
* @param AliasPackage $package package instance
* @param string $reason operation reason
*/
public function __construct(AliasPackage $package, $reason = null)
public function __construct(AliasPackage $package)
{
parent::__construct($reason);
$this->package = $package;
}

@ -20,7 +20,7 @@ use Composer\Package\PackageInterface;
*
* @author Nils Adermann <naderman@naderman.de>
*/
class MarkAliasUninstalledOperation extends SolverOperation
class MarkAliasUninstalledOperation implements OperationInterface
{
protected $package;
@ -28,12 +28,9 @@ class MarkAliasUninstalledOperation extends SolverOperation
* Initializes operation.
*
* @param AliasPackage $package package instance
* @param string $reason operation reason
*/
public function __construct(AliasPackage $package, $reason = null)
public function __construct(AliasPackage $package)
{
parent::__construct($reason);
$this->package = $package;
}

@ -26,13 +26,6 @@ interface OperationInterface
*/
public function getOperationType();
/**
* Returns operation reason.
*
* @return string
*/
public function getReason();
/**
* Serializes the operation in a human readable format
*

@ -1,45 +0,0 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\DependencyResolver\Operation;
use Composer\Package\PackageInterface;
/**
* Abstract solver operation class.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
abstract class SolverOperation implements OperationInterface
{
protected $reason;
/**
* Initializes operation.
*
* @param string $reason operation reason
*/
public function __construct($reason = null)
{
$this->reason = $reason;
}
/**
* Returns operation reason.
*
* @return string
*/
public function getReason()
{
return $this->reason;
}
}

@ -19,7 +19,7 @@ use Composer\Package\PackageInterface;
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class UninstallOperation extends SolverOperation
class UninstallOperation implements OperationInterface
{
protected $package;
@ -27,12 +27,9 @@ class UninstallOperation extends SolverOperation
* Initializes operation.
*
* @param PackageInterface $package package instance
* @param string $reason operation reason
*/
public function __construct(PackageInterface $package, $reason = null)
public function __construct(PackageInterface $package)
{
parent::__construct($reason);
$this->package = $package;
}

@ -20,7 +20,7 @@ use Composer\Package\Version\VersionParser;
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class UpdateOperation extends SolverOperation
class UpdateOperation implements OperationInterface
{
protected $initialPackage;
protected $targetPackage;
@ -30,12 +30,9 @@ class UpdateOperation extends SolverOperation
*
* @param PackageInterface $initial initial package
* @param PackageInterface $target target package (updated)
* @param string $reason update reason
*/
public function __construct(PackageInterface $initial, PackageInterface $target, $reason = null)
public function __construct(PackageInterface $initial, PackageInterface $target)
{
parent::__construct($reason);
$this->initialPackage = $initial;
$this->targetPackage = $target;
}

@ -158,10 +158,10 @@ class Transaction
}
foreach ($removeMap as $name => $package) {
array_unshift($operations, new Operation\UninstallOperation($package, null));
array_unshift($operations, new Operation\UninstallOperation($package));
}
foreach ($removeAliasMap as $nameVersion => $package) {
$operations[] = new Operation\MarkAliasUninstalledOperation($package, null);
$operations[] = new Operation\MarkAliasUninstalledOperation($package);
}
$operations = $this->movePluginsToFront($operations);

@ -106,6 +106,12 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
throw new \InvalidArgumentException('The given package is missing url information');
}
$cacheKeyGenerator = function (PackageInterface $package, $key) {
$cacheKey = sha1($key);
return $package->getName().'/'.$cacheKey.'.'.$package->getDistType();
};
$retries = 3;
$urls = $package->getDistUrls();
foreach ($urls as $index => $url) {
@ -113,7 +119,11 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
$urls[$index] = array(
'base' => $url,
'processed' => $processedUrl,
'cacheKey' => $this->getCacheKey($package, $processedUrl)
// we use the complete download url here to avoid conflicting entries
// from different packages, which would potentially allow a given package
// in a third party repo to pre-populate the cache for the same package in
// packagist for example.
'cacheKey' => $cacheKeyGenerator($package, $processedUrl)
);
}
@ -130,12 +140,17 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
$accept = null;
$reject = null;
$download = function () use ($io, $output, $httpDownloader, $cache, $eventDispatcher, $package, $fileName, &$urls, &$accept, &$reject) {
$download = function () use ($io, $output, $httpDownloader, $cache, $cacheKeyGenerator, $eventDispatcher, $package, $fileName, &$urls, &$accept, &$reject) {
$url = reset($urls);
if ($eventDispatcher) {
$preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $httpDownloader, $url['processed'], 'package', $package);
$eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
if ($preFileDownloadEvent->getCustomCacheKey() !== null) {
$url['cacheKey'] = $cacheKeyGenerator($package, $preFileDownloadEvent->getCustomCacheKey());
} else if ($preFileDownloadEvent->getProcessedUrl() !== $url['processed']) {
$url['cacheKey'] = $cacheKeyGenerator($package, $preFileDownloadEvent->getProcessedUrl());
}
$url['processed'] = $preFileDownloadEvent->getProcessedUrl();
}
@ -398,17 +413,6 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
return $url;
}
private function getCacheKey(PackageInterface $package, $processedUrl)
{
// we use the complete download url here to avoid conflicting entries
// from different packages, which would potentially allow a given package
// in a third party repo to pre-populate the cache for the same package in
// packagist for example.
$cacheKey = sha1($processedUrl);
return $package->getName().'/'.$cacheKey.'.'.$package->getDistType();
}
/**
* {@inheritDoc}
* @throws \RuntimeException

@ -220,6 +220,9 @@ class ZipDownloader extends ArchiveDownloader
*
* @param string $file File to extract
* @param string $path Path where to extract file
*
* TODO v3 should make this private once we can drop PHP 5.3 support
* @protected
*/
public function extract(PackageInterface $package, $file, $path)
{

@ -144,6 +144,14 @@ class EventDispatcher
*/
protected function doDispatch(Event $event)
{
if (getenv('COMPOSER_DEBUG_EVENTS')) {
$details = null;
if ($event instanceof PackageEvent) {
$details = (string) $event->getOperation();
}
$this->io->writeError('Dispatching <info>'.$event->getName().'</info>'.($details ? ' ('.$details.')' : '').' event');
}
$listeners = $this->getListeners($event);
$this->pushEvent($event);

@ -263,14 +263,6 @@ class Factory
return new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter);
}
/**
* @deprecated Use Composer\Repository\RepositoryFactory::defaultRepos instead
*/
public static function createDefaultRepositories(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
{
return RepositoryFactory::defaultRepos($io, $config, $rm);
}
/**
* Creates a Composer instance
*
@ -608,7 +600,11 @@ class Factory
{
static $warned = false;
$disableTls = false;
if ($config && $config->get('disable-tls') === true) {
// allow running the config command if disable-tls is in the arg list, even if openssl is missing, to allow disabling it via the config command
if (isset($_SERVER['argv']) && in_array('disable-tls', $_SERVER['argv']) && (in_array('conf', $_SERVER['argv']) || in_array('config', $_SERVER['argv']))) {
$warned = true;
$disableTls = !extension_loaded('openssl');
} elseif ($config && $config->get('disable-tls') === true) {
if (!$warned) {
$io->writeError('<warning>You are running Composer with SSL/TLS protection disabled.</warning>');
}

@ -126,6 +126,7 @@ class Installer
protected $optimizeAutoloader = false;
protected $classMapAuthoritative = false;
protected $apcuAutoloader = false;
protected $apcuAutoloaderPrefix;
protected $devMode = false;
protected $dryRun = false;
protected $verbose = false;
@ -307,7 +308,7 @@ class Installer
$this->autoloadGenerator->setDevMode($this->devMode);
$this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative);
$this->autoloadGenerator->setApcu($this->apcuAutoloader);
$this->autoloadGenerator->setApcu($this->apcuAutoloader, $this->apcuAutoloaderPrefix);
$this->autoloadGenerator->setRunScripts($this->runScripts);
$this->autoloadGenerator->setIgnorePlatformRequirements($this->ignorePlatformReqs);
$this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader);
@ -1023,12 +1024,14 @@ class Installer
/**
* Whether or not generated autoloader considers APCu caching.
*
* @param bool $apcuAutoloader
* @param bool $apcuAutoloader
* @param string|null $apcuAutoloaderPrefix
* @return Installer
*/
public function setApcuAutoloader($apcuAutoloader = false)
public function setApcuAutoloader($apcuAutoloader = false, $apcuAutoloaderPrefix = null)
{
$this->apcuAutoloader = (bool) $apcuAutoloader;
$this->apcuAutoloader = $apcuAutoloader;
$this->apcuAutoloaderPrefix = $apcuAutoloaderPrefix;
return $this;
}

@ -57,7 +57,7 @@ class AliasPackage extends BasePackage implements CompletePackageInterface
$this->stability = VersionParser::parseStability($version);
$this->dev = $this->stability === 'dev';
foreach (array('requires', 'devRequires', 'conflicts', 'provides', 'replaces') as $type) {
foreach (Link::$TYPES as $type) {
$links = $aliasOf->{'get' . ucfirst($type)}();
$this->$type = $this->replaceSelfVersionDependencies($links, $type);
}
@ -180,7 +180,7 @@ class AliasPackage extends BasePackage implements CompletePackageInterface
$prettyVersion = $this->aliasOf->getPrettyVersion();
}
if (\in_array($linkType, array('conflicts', 'provides', 'replaces'), true)) {
if (\in_array($linkType, array(Link::TYPE_CONFLICT, Link::TYPE_PROVIDE, Link::TYPE_REPLACE), true)) {
$newLinks = array();
foreach ($links as $link) {
// link is self.version, but must be replacing also the replaced version
@ -193,7 +193,7 @@ class AliasPackage extends BasePackage implements CompletePackageInterface
} else {
foreach ($links as $index => $link) {
if ('self.version' === $link->getPrettyConstraint()) {
if ($linkType === 'requires') {
if ($linkType === Link::TYPE_REQUIRE) {
$this->hasSelfVersionRequires = true;
}
$links[$index] = new Link($link->getSource(), $link->getTarget(), $constraint = new Constraint('=', $this->version), $linkType, $prettyVersion);

@ -22,12 +22,15 @@ use Composer\Repository\PlatformRepository;
*/
abstract class BasePackage implements PackageInterface
{
/**
* @phpstan-var array<string, array{description: string, method: Link::TYPE_*}>
*/
public static $supportedLinkTypes = array(
'require' => array('description' => 'requires', 'method' => 'requires'),
'conflict' => array('description' => 'conflicts', 'method' => 'conflicts'),
'provide' => array('description' => 'provides', 'method' => 'provides'),
'replace' => array('description' => 'replaces', 'method' => 'replaces'),
'require-dev' => array('description' => 'requires (for development)', 'method' => 'devRequires'),
'require' => array('description' => 'requires', 'method' => Link::TYPE_REQUIRE),
'conflict' => array('description' => 'conflicts', 'method' => Link::TYPE_CONFLICT),
'provide' => array('description' => 'provides', 'method' => Link::TYPE_PROVIDE),
'replace' => array('description' => 'replaces', 'method' => Link::TYPE_REPLACE),
'require-dev' => array('description' => 'requires (for development)', 'method' => Link::TYPE_DEV_REQUIRE),
);
const STABILITY_STABLE = 0;

@ -21,6 +21,26 @@ use Composer\Semver\Constraint\ConstraintInterface;
*/
class Link
{
const TYPE_REQUIRE = 'requires';
const TYPE_DEV_REQUIRE = 'devRequires';
const TYPE_PROVIDE = 'provides';
const TYPE_CONFLICT = 'conflicts';
const TYPE_REPLACE = 'replaces';
/**
* Will be converted into a constant once the min PHP version allows this
*
* @internal
* @var string[]
*/
public static $TYPES = array(
self::TYPE_REQUIRE,
self::TYPE_DEV_REQUIRE,
self::TYPE_PROVIDE,
self::TYPE_CONFLICT,
self::TYPE_REPLACE,
);
/**
* @var string
*/
@ -38,6 +58,7 @@ class Link
/**
* @var string
* @phpstan-var self::TYPE_* $description
*/
protected $description;
@ -49,14 +70,20 @@ class Link
/**
* Creates a new package link.
*
* @param string $source
* @param string $target
* @param ConstraintInterface $constraint Constraint applying to the target of this link
* @param string $description Used to create a descriptive string representation
* @param string|null $prettyConstraint
* @param string $source
* @param string $target
* @param ConstraintInterface $constraint Constraint applying to the target of this link
* @param string $description Used to create a descriptive string representation
* @phpstan-param self::TYPE_* $description
* @param string|null $prettyConstraint
*/
public function __construct($source, $target, ConstraintInterface $constraint, $description = 'relates to', $prettyConstraint = null)
{
public function __construct(
$source,
$target,
ConstraintInterface $constraint,
$description = 'relates to',
$prettyConstraint = null
) {
$this->source = strtolower($source);
$this->target = strtolower($target);
$this->constraint = $constraint;

@ -295,10 +295,11 @@ class ArrayLoader implements LoaderInterface
}
/**
* @param string $source source package name
* @param string $sourceVersion source package version (pretty version ideally)
* @param string $description link description (e.g. requires, replaces, ..)
* @param array $links array of package name => constraint mappings
* @param string $source source package name
* @param string $sourceVersion source package version (pretty version ideally)
* @param string $description link description (e.g. requires, replaces, ..)
* @phpstan-param Link::TYPE_* $description
* @param array $links array of package name => constraint mappings
* @return Link[]
*/
public function parseLinks($source, $sourceVersion, $description, $links)

@ -179,7 +179,6 @@ class Locker
$packageByName[$package->getName()] = $package;
if ($package instanceof AliasPackage) {
$packages->addPackage($package->getAliasOf());
$packageByName[$package->getAliasOf()->getName()] = $package->getAliasOf();
}
}
@ -213,7 +212,7 @@ class Locker
$requirements = $this->loader->parseLinks(
'__root__',
'1.0.0',
'requires',
Link::TYPE_REQUIRE,
isset($lockData['platform']) ? $lockData['platform'] : array()
);
}
@ -222,7 +221,7 @@ class Locker
$devRequirements = $this->loader->parseLinks(
'__root__',
'1.0.0',
'requires',
Link::TYPE_REQUIRE,
isset($lockData['platform-dev']) ? $lockData['platform-dev'] : array()
);

@ -75,7 +75,7 @@ class RootAliasPackage extends AliasPackage implements RootPackageInterface
*/
public function setRequires(array $require)
{
$this->requires = $this->replaceSelfVersionDependencies($require, 'requires');
$this->requires = $this->replaceSelfVersionDependencies($require, Link::TYPE_REQUIRE);
$this->aliasOf->setRequires($require);
}
@ -85,7 +85,7 @@ class RootAliasPackage extends AliasPackage implements RootPackageInterface
*/
public function setDevRequires(array $devRequire)
{
$this->devRequires = $this->replaceSelfVersionDependencies($devRequire, 'devRequires');
$this->devRequires = $this->replaceSelfVersionDependencies($devRequire, Link::TYPE_DEV_REQUIRE);
$this->aliasOf->setDevRequires($devRequire);
}
@ -95,7 +95,7 @@ class RootAliasPackage extends AliasPackage implements RootPackageInterface
*/
public function setConflicts(array $conflicts)
{
$this->conflicts = $this->replaceSelfVersionDependencies($conflicts, 'conflicts');
$this->conflicts = $this->replaceSelfVersionDependencies($conflicts, Link::TYPE_CONFLICT);
$this->aliasOf->setConflicts($conflicts);
}
@ -104,7 +104,7 @@ class RootAliasPackage extends AliasPackage implements RootPackageInterface
*/
public function setProvides(array $provides)
{
$this->provides = $this->replaceSelfVersionDependencies($provides, 'provides');
$this->provides = $this->replaceSelfVersionDependencies($provides, Link::TYPE_PROVIDE);
$this->aliasOf->setProvides($provides);
}
@ -113,7 +113,7 @@ class RootAliasPackage extends AliasPackage implements RootPackageInterface
*/
public function setReplaces(array $replaces)
{
$this->replaces = $this->replaceSelfVersionDependencies($replaces, 'replaces');
$this->replaces = $this->replaceSelfVersionDependencies($replaces, Link::TYPE_REPLACE);
$this->aliasOf->setReplaces($replaces);
}

@ -120,7 +120,7 @@ class VersionGuesser
$isDetached = false;
// try to fetch current version from git branch
if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output, $path)) {
if (0 === $this->process->execute('git branch -a --no-color --no-abbrev -v', $output, $path)) {
$branches = array();
$isFeatureBranch = false;
@ -147,8 +147,8 @@ class VersionGuesser
}
}
if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
if ($branch && !preg_match('{^ *.+/HEAD }', $branch)) {
if (preg_match('{^(?:\* )? *((?:remotes/(?:origin|upstream)/)?[^\s/]+) *([a-f0-9]+) .*$}', $branch, $match)) {
$branches[] = $match[1];
}
}
@ -252,13 +252,25 @@ class VersionGuesser
return array('version' => $version, 'pretty_version' => $prettyVersion);
}
// 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
// sort local branches first then remote ones
// and 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);
usort($branches, function ($a, $b) {
$aRemote = 0 === strpos($a, 'remotes/');
$bRemote = 0 === strpos($b, 'remotes/');
if ($aRemote !== $bRemote) {
return $aRemote ? 1 : -1;
}
return strnatcasecmp($b, $a);
});
foreach ($branches as $candidate) {
$candidateVersion = preg_replace('{^remotes/\S+/}', '', $candidate);
// do not compare against itself or other feature branches
if ($candidate === $branch || $this->isFeatureBranch($packageConfig, $candidate)) {
if ($candidate === $branch || $this->isFeatureBranch($packageConfig, $candidateVersion)) {
continue;
}
@ -269,8 +281,11 @@ class VersionGuesser
if (strlen($output) < $length) {
$length = strlen($output);
$version = $this->versionParser->normalizeBranch($candidate);
$prettyVersion = 'dev-' . $candidate;
$version = $this->versionParser->normalizeBranch($candidateVersion);
$prettyVersion = 'dev-' . $candidateVersion;
if ($length === 0) {
break;
}
}
}
}

@ -32,6 +32,11 @@ class PreFileDownloadEvent extends Event
*/
private $processedUrl;
/**
* @var string|null
*/
private $customCacheKey;
/**
* @var string
*/
@ -88,6 +93,26 @@ class PreFileDownloadEvent extends Event
$this->processedUrl = $processedUrl;
}
/**
* Retrieves a custom package cache key for this download.
*
* @return string|null
*/
public function getCustomCacheKey()
{
return $this->customCacheKey;
}
/**
* Sets a custom package cache key for this download.
*
* @param string|null $customCacheKey New cache key
*/
public function setCustomCacheKey($customCacheKey)
{
$this->customCacheKey = $customCacheKey;
}
/**
* Returns the type of this download (package, metadata).
*

@ -15,6 +15,7 @@ namespace Composer\Repository;
use Composer\Package\Version\VersionParser;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\MatchAllConstraint;
use Composer\Package\AliasPackage;
use Composer\Package\RootPackageInterface;
use Composer\Package\Link;
@ -176,7 +177,7 @@ class InstalledRepository extends CompositeRepository
$platformPkg = $this->findPackage($link->getTarget(), '*');
$description = $platformPkg ? 'but '.$platformPkg->getPrettyVersion().' is installed' : 'but it is missing';
$results[] = array($package, new Link($package->getName(), $link->getTarget(), null, 'requires', $link->getPrettyConstraint().' '.$description), false);
$results[] = array($package, new Link($package->getName(), $link->getTarget(), new MatchAllConstraint, Link::TYPE_REQUIRE, $link->getPrettyConstraint().' '.$description), false);
continue;
}
@ -199,7 +200,7 @@ class InstalledRepository extends CompositeRepository
}
}
$results[] = array($package, $link, false);
$results[] = array($rootPackage, new Link($rootPackage->getName(), $link->getTarget(), null, 'does not require', 'but ' . $pkg->getPrettyVersion() . ' is installed'), false);
$results[] = array($rootPackage, new Link($rootPackage->getName(), $link->getTarget(), new MatchAllConstraint, 'does not require', 'but ' . $pkg->getPrettyVersion() . ' is installed'), false);
} else {
// no root so let's just print whatever we found
$results[] = array($package, $link, false);

@ -548,7 +548,9 @@ class PlatformRepository extends ArrayRepository
$ext->setDescription('The '.$name.' PHP extension'.$extraDescription);
if ($name === 'uuid') {
$ext->setReplaces(array(new Link('ext-uuid', 'lib-uuid', new Constraint('=', $version))));
$ext->setReplaces(array(
new Link('ext-uuid', 'lib-uuid', new Constraint('=', $version), Link::TYPE_REPLACE, $ext->getPrettyVersion())
));
}
$this->addPackage($ext);
@ -585,8 +587,8 @@ class PlatformRepository extends ArrayRepository
$lib = new CompletePackage('lib-'.$name, $version, $prettyVersion);
$lib->setDescription($description);
$links = function ($alias) use ($name, $version) {
return new Link('lib-'.$name, 'lib-'.$alias, new Constraint('=', $version));
$links = function ($alias) use ($name, $version, $lib) {
return new Link('lib-'.$name, 'lib-'.$alias, new Constraint('=', $version), Link::TYPE_REPLACE, $lib->getPrettyVersion());
};
$lib->setReplaces(array_map($links, $replaces));
$lib->setProvides(array_map($links, $provides));

@ -128,66 +128,4 @@ class ScriptEvents
* @var string
*/
const POST_ARCHIVE_CMD = 'post-archive-cmd';
/** Deprecated constants below */
/**
* The PRE_PACKAGE_INSTALL event occurs before a package is installed.
*
* The event listener method receives a Composer\Installer\PackageEvent instance.
*
* @deprecated Use Composer\Installer\PackageEvents::PRE_PACKAGE_INSTALL instead.
* @var string
*/
const PRE_PACKAGE_INSTALL = 'pre-package-install';
/**
* The POST_PACKAGE_INSTALL event occurs after a package is installed.
*
* The event listener method receives a Composer\Installer\PackageEvent instance.
*
* @deprecated Use Composer\Installer\PackageEvents::POST_PACKAGE_INSTALL instead.
* @var string
*/
const POST_PACKAGE_INSTALL = 'post-package-install';
/**
* The PRE_PACKAGE_UPDATE event occurs before a package is updated.
*
* The event listener method receives a Composer\Installer\PackageEvent instance.
*
* @deprecated Use Composer\Installer\PackageEvents::PRE_PACKAGE_UPDATE instead.
* @var string
*/
const PRE_PACKAGE_UPDATE = 'pre-package-update';
/**
* The POST_PACKAGE_UPDATE event occurs after a package is updated.
*
* The event listener method receives a Composer\Installer\PackageEvent instance.
*
* @deprecated Use Composer\Installer\PackageEvents::POST_PACKAGE_UPDATE instead.
* @var string
*/
const POST_PACKAGE_UPDATE = 'post-package-update';
/**
* The PRE_PACKAGE_UNINSTALL event occurs before a package has been uninstalled.
*
* The event listener method receives a Composer\Installer\PackageEvent instance.
*
* @deprecated Use Composer\Installer\PackageEvents::PRE_PACKAGE_UNINSTALL instead.
* @var string
*/
const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
/**
* The POST_PACKAGE_UNINSTALL event occurs after a package has been uninstalled.
*
* The event listener method receives a Composer\Installer\PackageEvent instance.
*
* @deprecated Use Composer\Installer\PackageEvents::POST_PACKAGE_UNINSTALL instead.
* @var string
*/
const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
}

@ -438,7 +438,7 @@ class AutoloadGeneratorTest extends TestCase
$b->setAutoload(array('psr-4' => array('B\\' => 'src/')));
$b->setReplaces(
array(new Link('b/b', 'b/c', new Constraint('==', '1.0'), 'replaces'))
array(new Link('b/b', 'b/c', new Constraint('==', '1.0'), Link::TYPE_REPLACE))
);
$this->repository->expects($this->once())
@ -823,6 +823,55 @@ EOF;
$this->assertStringContainsString('$loader->setApcuPrefix(', file_get_contents($this->vendorDir.'/composer/autoload_real.php'));
}
public function testClassMapAutoloadingAuthoritativeAndApcuPrefix()
{
$package = new Package('a', '1.0', '1.0');
$package->setRequires(array(
new Link('a', 'a/a', new MatchAllConstraint()),
new Link('a', 'b/b', new MatchAllConstraint()),
new Link('a', 'c/c', new MatchAllConstraint()),
));
$packages = array();
$packages[] = $a = new Package('a/a', '1.0', '1.0');
$packages[] = $b = new Package('b/b', '1.0', '1.0');
$packages[] = $c = new Package('c/c', '1.0', '1.0');
$a->setAutoload(array('psr-4' => array('' => 'src/')));
$b->setAutoload(array('psr-4' => array('' => './')));
$c->setAutoload(array('psr-4' => array('' => 'foo/')));
$this->repository->expects($this->once())
->method('getCanonicalPackages')
->will($this->returnValue($packages));
$this->fs->ensureDirectoryExists($this->vendorDir.'/composer');
$this->fs->ensureDirectoryExists($this->vendorDir.'/a/a/src');
$this->fs->ensureDirectoryExists($this->vendorDir.'/b/b');
$this->fs->ensureDirectoryExists($this->vendorDir.'/c/c/foo');
file_put_contents($this->vendorDir.'/a/a/src/ClassMapFoo.php', '<?php class ClassMapFoo {}');
file_put_contents($this->vendorDir.'/b/b/ClassMapBar.php', '<?php class ClassMapBar {}');
file_put_contents($this->vendorDir.'/c/c/foo/ClassMapBaz.php', '<?php class ClassMapBaz {}');
$this->generator->setClassMapAuthoritative(true);
$this->generator->setApcu(true, 'custom\'Prefix');
$this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, '_7');
$this->assertFileExists($this->vendorDir.'/composer/autoload_classmap.php', "ClassMap file needs to be generated.");
$this->assertEquals(
array(
'ClassMapBar' => $this->vendorDir.'/b/b/ClassMapBar.php',
'ClassMapBaz' => $this->vendorDir.'/c/c/foo/ClassMapBaz.php',
'ClassMapFoo' => $this->vendorDir.'/a/a/src/ClassMapFoo.php',
'Composer\\InstalledVersions' => $this->vendorDir.'/composer/InstalledVersions.php',
),
include $this->vendorDir.'/composer/autoload_classmap.php'
);
$this->assertAutoloadFiles('classmap8', $this->vendorDir.'/composer', 'classmap');
$this->assertStringContainsString('$loader->setClassMapAuthoritative(true);', file_get_contents($this->vendorDir.'/composer/autoload_real.php'));
$this->assertStringContainsString('$loader->setApcuPrefix(\'custom\\\'Prefix\');', file_get_contents($this->vendorDir.'/composer/autoload_real.php'));
}
public function testFilesAutoloadGeneration()
{
$package = new Package('a', '1.0', '1.0');

@ -192,8 +192,8 @@ class DefaultPolicyTest extends TestCase
$this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
$this->repo->addPackage($packageB = $this->getPackage('B', '2.0'));
$packageA->setProvides(array(new Link('A', 'X', new Constraint('==', '1.0'), 'provides')));
$packageB->setProvides(array(new Link('B', 'X', new Constraint('==', '1.0'), 'provides')));
$packageA->setProvides(array(new Link('A', 'X', new Constraint('==', '1.0'), Link::TYPE_PROVIDE)));
$packageB->setProvides(array(new Link('B', 'X', new Constraint('==', '1.0'), Link::TYPE_PROVIDE)));
$this->repositorySet->addRepository($this->repo);
@ -212,7 +212,7 @@ class DefaultPolicyTest extends TestCase
$this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
$this->repo->addPackage($packageB = $this->getPackage('B', '2.0'));
$packageB->setReplaces(array(new Link('B', 'A', new Constraint('==', '1.0'), 'replaces')));
$packageB->setReplaces(array(new Link('B', 'A', new Constraint('==', '1.0'), Link::TYPE_REPLACE)));
$this->repositorySet->addRepository($this->repo);
@ -232,8 +232,8 @@ class DefaultPolicyTest extends TestCase
$this->repo->addPackage($packageB = $this->getPackage('vendor-b/replacer', '1.0'));
$this->repo->addPackage($packageA = $this->getPackage('vendor-a/replacer', '1.0'));
$packageA->setReplaces(array(new Link('vendor-a/replacer', 'vendor-a/package', new Constraint('==', '1.0'), 'replaces')));
$packageB->setReplaces(array(new Link('vendor-b/replacer', 'vendor-a/package', new Constraint('==', '1.0'), 'replaces')));
$packageA->setReplaces(array(new Link('vendor-a/replacer', 'vendor-a/package', new Constraint('==', '1.0'), Link::TYPE_REPLACE)));
$packageB->setReplaces(array(new Link('vendor-b/replacer', 'vendor-a/package', new Constraint('==', '1.0'), Link::TYPE_REPLACE)));
$this->repositorySet->addRepository($this->repo);

@ -112,7 +112,7 @@ class SolverTest extends TestCase
$this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));
$this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1'));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('<', '1.1'), 'requires')));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('<', '1.1'), Link::TYPE_REQUIRE)));
$this->reposComplete();
@ -137,7 +137,7 @@ class SolverTest extends TestCase
$this->getVersionConstraint('<=', '1.3'),
$this->getVersionConstraint('<>', '1.3'),
$this->getVersionConstraint('!=', '1.2'),
)), 'requires'),
)), Link::TYPE_REQUIRE),
));
$this->reposComplete();
@ -157,11 +157,11 @@ class SolverTest extends TestCase
$this->repo->addPackage($packageC = $this->getPackage('C', '1.0'));
$packageB->setRequires(array(
'a' => new Link('B', 'A', $this->getVersionConstraint('>=', '1.0'), 'requires'),
'c' => new Link('B', 'C', $this->getVersionConstraint('>=', '1.0'), 'requires'),
'a' => new Link('B', 'A', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE),
'c' => new Link('B', 'C', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE),
));
$packageC->setRequires(array(
'a' => new Link('C', 'A', $this->getVersionConstraint('>=', '1.0'), 'requires'),
'a' => new Link('C', 'A', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE),
));
$this->reposComplete();
@ -205,7 +205,7 @@ class SolverTest extends TestCase
$this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1'));
$this->reposComplete();
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0.0.0'), 'requires')));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0.0.0'), Link::TYPE_REQUIRE)));
$this->request->fixPackage($packageA);
$this->request->requireName('B', $this->getVersionConstraint('=', '1.1.0.0'));
@ -235,8 +235,8 @@ class SolverTest extends TestCase
$this->repo->addPackage($newPackageA = $this->getPackage('A', '1.1'));
$this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1'));
$packageA->setRequires(array('b' => new Link('A', 'B', new MatchAllConstraint(), 'requires')));
$newPackageA->setRequires(array('b' => new Link('A', 'B', new MatchAllConstraint(), 'requires')));
$packageA->setRequires(array('b' => new Link('A', 'B', new MatchAllConstraint(), Link::TYPE_REQUIRE)));
$newPackageA->setRequires(array('b' => new Link('A', 'B', new MatchAllConstraint(), Link::TYPE_REQUIRE)));
$this->reposComplete();
@ -341,7 +341,7 @@ class SolverTest extends TestCase
$this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1'));
$this->repo->addPackage($packageC = $this->getPackage('C', '1.1'));
$this->repo->addPackage($this->getPackage('D', '1.0'));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('<', '1.1'), 'requires')));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('<', '1.1'), Link::TYPE_REQUIRE)));
$this->reposComplete();
@ -362,8 +362,8 @@ class SolverTest extends TestCase
$this->repo->addPackage($middlePackageB = $this->getPackage('B', '1.0'));
$this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1'));
$this->repo->addPackage($oldPackageB = $this->getPackage('B', '0.9'));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('<', '1.1'), 'requires')));
$packageA->setConflicts(array('b' => new Link('A', 'B', $this->getVersionConstraint('<', '1.0'), 'conflicts')));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('<', '1.1'), Link::TYPE_REQUIRE)));
$packageA->setConflicts(array('b' => new Link('A', 'B', $this->getVersionConstraint('<', '1.0'), Link::TYPE_CONFLICT)));
$this->reposComplete();
@ -409,8 +409,8 @@ class SolverTest extends TestCase
{
$this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
$this->repo->addPackage($packageQ = $this->getPackage('Q', '1.0'));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
$packageQ->setProvides(array('b' => new Link('Q', 'B', $this->getVersionConstraint('=', '1.0'), 'provides')));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE)));
$packageQ->setProvides(array('b' => new Link('Q', 'B', $this->getVersionConstraint('=', '1.0'), Link::TYPE_PROVIDE)));
$this->reposComplete();
@ -427,8 +427,8 @@ class SolverTest extends TestCase
$this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
$this->repo->addPackage($packageQ = $this->getPackage('Q', '1.0'));
$this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
$packageQ->setReplaces(array('b' => new Link('Q', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces')));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE)));
$packageQ->setReplaces(array('b' => new Link('Q', 'B', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REPLACE)));
$this->reposComplete();
@ -444,8 +444,8 @@ class SolverTest extends TestCase
{
$this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
$this->repo->addPackage($packageQ = $this->getPackage('Q', '1.0'));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
$packageQ->setReplaces(array('b' => new Link('Q', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces')));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE)));
$packageQ->setReplaces(array('b' => new Link('Q', 'B', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REPLACE)));
$this->reposComplete();
@ -461,8 +461,8 @@ class SolverTest extends TestCase
$this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
$this->repo->addPackage($packageQ = $this->getPackage('Q', '1.0'));
$this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
$packageQ->setReplaces(array('b' => new Link('Q', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces')));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE)));
$packageQ->setReplaces(array('b' => new Link('Q', 'B', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REPLACE)));
$this->reposComplete();
@ -479,27 +479,27 @@ class SolverTest extends TestCase
{
$this->repo->addPackage($packageX = $this->getPackage('X', '1.0'));
$packageX->setRequires(array(
'a' => new Link('X', 'A', $this->getVersionConstraint('>=', '2.0.0.0'), 'requires'),
'b' => new Link('X', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), 'requires'),
'a' => new Link('X', 'A', $this->getVersionConstraint('>=', '2.0.0.0'), Link::TYPE_REQUIRE),
'b' => new Link('X', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), Link::TYPE_REQUIRE),
));
$this->repo->addPackage($packageA = $this->getPackage('A', '2.0.0'));
$this->repo->addPackage($newPackageA = $this->getPackage('A', '2.1.0'));
$this->repo->addPackage($newPackageB = $this->getPackage('B', '2.1.0'));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), 'requires')));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), Link::TYPE_REQUIRE)));
// new package A depends on version of package B that does not exist
// => new package A is not installable
$newPackageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '2.2.0.0'), 'requires')));
$newPackageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '2.2.0.0'), Link::TYPE_REQUIRE)));
// add a package S replacing both A and B, so that S and B or S and A cannot be simultaneously installed
// but an alternative option for A and B both exists
// this creates a more difficult so solve conflict
$this->repo->addPackage($packageS = $this->getPackage('S', '2.0.0'));
$packageS->setReplaces(array(
'a' => new Link('S', 'A', $this->getVersionConstraint('>=', '2.0.0.0'), 'replaces'),
'b' => new Link('S', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), 'replaces'),
'a' => new Link('S', 'A', $this->getVersionConstraint('>=', '2.0.0.0'), Link::TYPE_REPLACE),
'b' => new Link('S', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), Link::TYPE_REPLACE),
));
$this->reposComplete();
@ -518,8 +518,8 @@ class SolverTest extends TestCase
$this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
$this->repo->addPackage($packageB1 = $this->getPackage('B', '0.9'));
$this->repo->addPackage($packageB2 = $this->getPackage('B', '1.1'));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
$packageB2->setRequires(array('a' => new Link('B', 'A', $this->getVersionConstraint('>=', '1.0'), 'requires')));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE)));
$packageB2->setRequires(array('a' => new Link('B', 'A', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE)));
$this->reposComplete();
@ -537,13 +537,13 @@ class SolverTest extends TestCase
$this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));
$this->repo->addPackage($packageC = $this->getPackage('C', '1.0'));
$this->repo->addPackage($packageD = $this->getPackage('D', '1.0'));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
$packageB->setRequires(array('virtual' => new Link('B', 'Virtual', $this->getVersionConstraint('>=', '1.0'), 'requires')));
$packageC->setProvides(array('virtual' => new Link('C', 'Virtual', $this->getVersionConstraint('==', '1.0'), 'provides')));
$packageD->setProvides(array('virtual' => new Link('D', 'Virtual', $this->getVersionConstraint('==', '1.0'), 'provides')));
$packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE)));
$packageB->setRequires(array('virtual' => new Link('B', 'Virtual', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE)));
$packageC->setProvides(array('virtual' => new Link('C', 'Virtual', $this->getVersionConstraint('==', '1.0'), Link::TYPE_PROVIDE)));
$packageD->setProvides(array('virtual' => new Link('D', 'Virtual', $this->getVersionConstraint('==', '1.0'), Link::TYPE_PROVIDE)));
$packageC->setRequires(array('a' => new Link('C', 'A', $this->getVersionConstraint('==', '1.0'), 'requires')));
$packageD->setRequires(array('a' => new Link('D', 'A', $this->getVersionConstraint('==', '1.0'), 'requires')));
$packageC->setRequires(array('a' => new Link('C', 'A', $this->getVersionConstraint('==', '1.0'), Link::TYPE_REQUIRE)));
$packageD->setRequires(array('a' => new Link('D', 'A', $this->getVersionConstraint('==', '1.0'), Link::TYPE_REQUIRE)));
$this->reposComplete();
@ -569,18 +569,18 @@ class SolverTest extends TestCase
$this->repo->addPackage($packageD2 = $this->getPackage('D', '1.1'));
$packageA->setRequires(array(
'b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires'),
'c' => new Link('A', 'C', $this->getVersionConstraint('>=', '1.0'), 'requires'),
'b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE),
'c' => new Link('A', 'C', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE),
));
$packageD->setReplaces(array(
'b' => new Link('D', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces'),
'c' => new Link('D', 'C', $this->getVersionConstraint('>=', '1.0'), 'replaces'),
'b' => new Link('D', 'B', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REPLACE),
'c' => new Link('D', 'C', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REPLACE),
));
$packageD2->setReplaces(array(
'b' => new Link('D', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces'),
'c' => new Link('D', 'C', $this->getVersionConstraint('>=', '1.0'), 'replaces'),
'b' => new Link('D', 'B', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REPLACE),
'c' => new Link('D', 'C', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REPLACE),
));
$this->reposComplete();
@ -605,19 +605,19 @@ class SolverTest extends TestCase
$this->repo->addPackage($packageD = $this->getPackage('D', '2.0.9'));
$packageC->setRequires(array(
'a' => new Link('C', 'A', $this->getVersionConstraint('>=', '2.0'), 'requires'),
'd' => new Link('C', 'D', $this->getVersionConstraint('>=', '2.0'), 'requires'),
'a' => new Link('C', 'A', $this->getVersionConstraint('>=', '2.0'), Link::TYPE_REQUIRE),
'd' => new Link('C', 'D', $this->getVersionConstraint('>=', '2.0'), Link::TYPE_REQUIRE),
));
$packageD->setRequires(array(
'a' => new Link('D', 'A', $this->getVersionConstraint('>=', '2.1'), 'requires'),
'b' => new Link('D', 'B', $this->getVersionConstraint('>=', '2.0-dev'), 'requires'),
'a' => new Link('D', 'A', $this->getVersionConstraint('>=', '2.1'), Link::TYPE_REQUIRE),
'b' => new Link('D', 'B', $this->getVersionConstraint('>=', '2.0-dev'), Link::TYPE_REQUIRE),
));
$packageB1->setRequires(array('a' => new Link('B', 'A', $this->getVersionConstraint('==', '2.1.0.0-dev'), 'requires')));
$packageB2->setRequires(array('a' => new Link('B', 'A', $this->getVersionConstraint('==', '2.1.0.0-dev'), 'requires')));
$packageB1->setRequires(array('a' => new Link('B', 'A', $this->getVersionConstraint('==', '2.1.0.0-dev'), Link::TYPE_REQUIRE)));
$packageB2->setRequires(array('a' => new Link('B', 'A', $this->getVersionConstraint('==', '2.1.0.0-dev'), Link::TYPE_REQUIRE)));
$packageB2->setReplaces(array('d' => new Link('B', 'D', $this->getVersionConstraint('==', '2.0.9.0'), 'replaces')));
$packageB2->setReplaces(array('d' => new Link('B', 'D', $this->getVersionConstraint('==', '2.0.9.0'), Link::TYPE_REPLACE)));
$this->reposComplete();
@ -634,7 +634,7 @@ class SolverTest extends TestCase
$this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
$this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));
$packageA->setConflicts(array(
'b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'conflicts'),
'b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_CONFLICT),
));
$this->reposComplete();
@ -668,7 +668,7 @@ class SolverTest extends TestCase
$this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));
$packageA->setRequires(array(
'b' => new Link('A', 'B', $this->getVersionConstraint('>=', '2.0'), 'requires'),
'b' => new Link('A', 'B', $this->getVersionConstraint('>=', '2.0'), Link::TYPE_REQUIRE),
));
$this->reposComplete();
@ -701,16 +701,16 @@ class SolverTest extends TestCase
$this->repo->addPackage($packageD = $this->getPackage('D', '1.0'));
$packageA->setRequires(array(
'b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires'),
'b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE),
));
$packageB->setRequires(array(
'c' => new Link('B', 'C', $this->getVersionConstraint('>=', '1.0'), 'requires'),
'c' => new Link('B', 'C', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE),
));
$packageC->setRequires(array(
'd' => new Link('C', 'D', $this->getVersionConstraint('>=', '1.0'), 'requires'),
'd' => new Link('C', 'D', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE),
));
$packageD->setRequires(array(
'b' => new Link('D', 'B', $this->getVersionConstraint('<', '1.0'), 'requires'),
'b' => new Link('D', 'B', $this->getVersionConstraint('<', '1.0'), Link::TYPE_REQUIRE),
));
$this->reposComplete();
@ -749,11 +749,11 @@ class SolverTest extends TestCase
$this->repo->addPackage($packageTwigBridge = $this->getPackage('symfony/twig-bridge', '2.0'));
$packageTwigBridge->setRequires(array(
'twig/twig' => new Link('symfony/twig-bridge', 'twig/twig', $this->getVersionConstraint('<', '2.0'), 'requires'),
'twig/twig' => new Link('symfony/twig-bridge', 'twig/twig', $this->getVersionConstraint('<', '2.0'), Link::TYPE_REQUIRE),
));
$packageSymfony->setReplaces(array(
'symfony/twig-bridge' => new Link('symfony/symfony', 'symfony/twig-bridge', $this->getVersionConstraint('==', '2.0'), 'replaces'),
'symfony/twig-bridge' => new Link('symfony/symfony', 'symfony/twig-bridge', $this->getVersionConstraint('==', '2.0'), Link::TYPE_REPLACE),
));
$this->reposComplete();
@ -774,10 +774,10 @@ class SolverTest extends TestCase
$this->repo->addPackage($packageA2 = $this->getPackage('A', '2.0'));
$packageA2->setRequires(array(
'b' => new Link('A', 'B', $this->getVersionConstraint('==', '2.0'), 'requires', '== 2.0'),
'b' => new Link('A', 'B', $this->getVersionConstraint('==', '2.0'), Link::TYPE_REQUIRE, '== 2.0'),
));
$packageB->setRequires(array(
'a' => new Link('B', 'A', $this->getVersionConstraint('>=', '2.0'), 'requires'),
'a' => new Link('B', 'A', $this->getVersionConstraint('>=', '2.0'), Link::TYPE_REQUIRE),
));
$this->repo->addPackage($packageA2Alias = $this->getAliasPackage($packageA2, '1.1'));
@ -799,7 +799,7 @@ class SolverTest extends TestCase
$this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));
$packageB->setRequires(array(
'a' => new Link('B', 'A', $this->getVersionConstraint('<', '2.0'), 'requires'),
'a' => new Link('B', 'A', $this->getVersionConstraint('<', '2.0'), Link::TYPE_REQUIRE),
));
$this->repo->addPackage($packageAAlias = $this->getAliasPackage($packageA, '1.1'));
@ -840,29 +840,29 @@ class SolverTest extends TestCase
$this->repo->addPackage($packageG3 = $this->getPackage('G', '3.0'));
$packageA->setRequires(array(
'b' => new Link('A', 'B', $this->getVersionConstraint('==', '1.0'), 'requires'),
'c' => new Link('A', 'C', $this->getVersionConstraint('>=', '1.0'), 'requires'),
'd' => new Link('A', 'D', $this->getVersionConstraint('==', '1.0'), 'requires'),
'b' => new Link('A', 'B', $this->getVersionConstraint('==', '1.0'), Link::TYPE_REQUIRE),
'c' => new Link('A', 'C', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE),
'd' => new Link('A', 'D', $this->getVersionConstraint('==', '1.0'), Link::TYPE_REQUIRE),
));
$packageB->setRequires(array(
'e' => new Link('B', 'E', $this->getVersionConstraint('==', '1.0'), 'requires'),
'e' => new Link('B', 'E', $this->getVersionConstraint('==', '1.0'), Link::TYPE_REQUIRE),
));
$packageC1->setRequires(array(
'f' => new Link('C', 'F', $this->getVersionConstraint('==', '1.0'), 'requires'),
'f' => new Link('C', 'F', $this->getVersionConstraint('==', '1.0'), Link::TYPE_REQUIRE),
));
$packageC2->setRequires(array(
'f' => new Link('C', 'F', $this->getVersionConstraint('==', '1.0'), 'requires'),
'g' => new Link('C', 'G', $this->getVersionConstraint('>=', '1.0'), 'requires'),
'f' => new Link('C', 'F', $this->getVersionConstraint('==', '1.0'), Link::TYPE_REQUIRE),
'g' => new Link('C', 'G', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE),
));
$packageD->setRequires(array(
'f' => new Link('D', 'F', $this->getVersionConstraint('>=', '1.0'), 'requires'),
'f' => new Link('D', 'F', $this->getVersionConstraint('>=', '1.0'), Link::TYPE_REQUIRE),
));
$packageE->setRequires(array(
'g' => new Link('E', 'G', $this->getVersionConstraint('<=', '2.0'), 'requires'),
'g' => new Link('E', 'G', $this->getVersionConstraint('<=', '2.0'), Link::TYPE_REQUIRE),
));
$this->reposComplete();

@ -45,10 +45,10 @@ class TransactionTest extends TestCase
);
$packageD->setRequires(array(
'f/f' => new Link('d/d', 'f/f', $this->getVersionConstraint('>', '0.2'), 'requires'),
'g/provider' => new Link('d/d', 'g/provider', $this->getVersionConstraint('>', '0.2'), 'requires'),
'f/f' => new Link('d/d', 'f/f', $this->getVersionConstraint('>', '0.2'), Link::TYPE_REQUIRE),
'g/provider' => new Link('d/d', 'g/provider', $this->getVersionConstraint('>', '0.2'), Link::TYPE_REQUIRE),
));
$packageG->setProvides(array('g/provider' => new Link('g/g', 'g/provider', $this->getVersionConstraint('==', '1.0.0'), 'provides')));
$packageG->setProvides(array('g/provider' => new Link('g/g', 'g/provider', $this->getVersionConstraint('==', '1.0.0'), Link::TYPE_PROVIDE)));
$expectedOperations = array(
array('job' => 'uninstall', 'package' => $packageC),

@ -124,7 +124,7 @@ class InstallationManagerTest extends TestCase
$manager->addInstaller($installer);
$package = $this->createPackageMock();
$operation = new InstallOperation($package, 'test');
$operation = new InstallOperation($package);
$package
->expects($this->once())
@ -153,7 +153,7 @@ class InstallationManagerTest extends TestCase
$initial = $this->createPackageMock();
$target = $this->createPackageMock();
$operation = new UpdateOperation($initial, $target, 'test');
$operation = new UpdateOperation($initial, $target);
$initial
->expects($this->once())
@ -221,7 +221,7 @@ class InstallationManagerTest extends TestCase
->method('install')
->with($this->repository, $target);
$operation = new UpdateOperation($initial, $target, 'test');
$operation = new UpdateOperation($initial, $target);
$manager->update($this->repository, $operation);
}
@ -232,7 +232,7 @@ class InstallationManagerTest extends TestCase
$manager->addInstaller($installer);
$package = $this->createPackageMock();
$operation = new UninstallOperation($package, 'test');
$operation = new UninstallOperation($package);
$package
->expects($this->once())

@ -145,11 +145,11 @@ class InstallerTest extends TestCase
$a = $this->getPackage('A', '1.0.0', 'Composer\Package\RootPackage');
$a->setRequires(array(
'b' => new Link('A', 'B', $v = $this->getVersionConstraint('=', '1.0.0'), 'requires', $v->getPrettyString()),
'b' => new Link('A', 'B', $v = $this->getVersionConstraint('=', '1.0.0'), Link::TYPE_REQUIRE, $v->getPrettyString()),
));
$b = $this->getPackage('B', '1.0.0');
$b->setRequires(array(
'a' => new Link('B', 'A', $v = $this->getVersionConstraint('=', '1.0.0'), 'requires', $v->getPrettyString()),
'a' => new Link('B', 'A', $v = $this->getVersionConstraint('=', '1.0.0'), Link::TYPE_REQUIRE, $v->getPrettyString()),
));
$cases[] = array(
@ -165,11 +165,11 @@ class InstallerTest extends TestCase
$a = $this->getPackage('A', '1.0.0', 'Composer\Package\RootPackage');
$a->setRequires(array(
'b' => new Link('A', 'B', $v = $this->getVersionConstraint('=', '1.0.0'), 'requires', $v->getPrettyString()),
'b' => new Link('A', 'B', $v = $this->getVersionConstraint('=', '1.0.0'), Link::TYPE_REQUIRE, $v->getPrettyString()),
));
$b = $this->getPackage('B', '1.0.0');
$b->setRequires(array(
'a' => new Link('B', 'A', $v = $this->getVersionConstraint('=', '1.0.0'), 'requires', $v->getPrettyString()),
'a' => new Link('B', 'A', $v = $this->getVersionConstraint('=', '1.0.0'), Link::TYPE_REQUIRE, $v->getPrettyString()),
));
$cases[] = array(

@ -172,7 +172,7 @@ class ArrayDumperTest extends TestCase
),
array(
'require',
array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')),
array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), Link::TYPE_REQUIRE, '1.0.0')),
'requires',
array('foo/bar' => '1.0.0'),
),
@ -197,13 +197,13 @@ class ArrayDumperTest extends TestCase
),
array(
'require',
array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')),
array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), Link::TYPE_REQUIRE, '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), Link::TYPE_REQUIRE, '1.0.0')),
'requires',
array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0'),
),
array(
'require-dev',
array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')),
array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), Link::TYPE_REQUIRE, '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), Link::TYPE_REQUIRE, '1.0.0')),
'devRequires',
array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0'),
),
@ -215,19 +215,19 @@ class ArrayDumperTest extends TestCase
),
array(
'provide',
array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')),
array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), Link::TYPE_REQUIRE, '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), Link::TYPE_REQUIRE, '1.0.0')),
'provides',
array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0'),
),
array(
'replace',
array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')),
array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), Link::TYPE_REQUIRE, '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), Link::TYPE_REQUIRE, '1.0.0')),
'replaces',
array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0'),
),
array(
'conflict',
array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), 'requires', '1.0.0')),
array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), Link::TYPE_REQUIRE, '1.0.0'), new Link('bar', 'bar/baz', new Constraint('=', '1.0.0.0'), Link::TYPE_REQUIRE, '1.0.0')),
'conflicts',
array('bar/baz' => '1.0.0', 'foo/bar' => '1.0.0'),
),

@ -137,7 +137,7 @@ class RootPackageLoaderTest extends TestCase
->expects($this->at(0))
->method('execute')
->willReturnCallback(function ($command, &$output) use ($self) {
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
$self->assertEquals('git branch -a --no-color --no-abbrev -v', $command);
$output = "* latest-production 38137d2f6c70e775e137b2d8a7a7d3eaebf7c7e5 Commit message\n master 4f6ed96b0bc363d2aa4404c3412de1c011f67c66 Commit message\n";
return 0;
@ -187,7 +187,7 @@ class RootPackageLoaderTest extends TestCase
->expects($this->at(0))
->method('execute')
->willReturnCallback(function ($command, &$output) use ($self) {
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
$self->assertEquals('git branch -a --no-color --no-abbrev -v', $command);
$output = "* latest-production 38137d2f6c70e775e137b2d8a7a7d3eaebf7c7e5 Commit message\n master 4f6ed96b0bc363d2aa4404c3412de1c011f67c66 Commit message\n";
return 0;

@ -48,7 +48,7 @@ class VersionGuesserTest extends TestCase
->expects($this->at($step))
->method('execute')
->willReturnCallback(function ($command, &$output) use ($self) {
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
$self->assertEquals('git branch -a --no-color --no-abbrev -v', $command);
return 128;
})
@ -116,7 +116,7 @@ class VersionGuesserTest extends TestCase
->expects($this->at(0))
->method('execute')
->willReturnCallback(function ($command, &$output) use ($self, $commitHash, $anotherCommitHash) {
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
$self->assertEquals('git branch -a --no-color --no-abbrev -v', $command);
$output = "* master $commitHash Commit message\n(no branch) $anotherCommitHash Commit message\n";
return 0;
@ -154,7 +154,7 @@ class VersionGuesserTest extends TestCase
->expects($this->at(0))
->method('execute')
->willReturnCallback(function ($command, &$output) use ($self, $commitHash, $anotherCommitHash) {
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
$self->assertEquals('git branch -a --no-color --no-abbrev -v', $command);
$output = " arbitrary $commitHash Commit message\n* current $anotherCommitHash Another message\n";
return 0;
@ -188,7 +188,7 @@ class VersionGuesserTest extends TestCase
->expects($this->at(0))
->method('execute')
->willReturnCallback(function ($command, &$output) use ($self, $commitHash, $anotherCommitHash) {
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
$self->assertEquals('git branch -a --no-color --no-abbrev -v', $command);
$output = " arbitrary $commitHash Commit message\n* feature $anotherCommitHash Another message\n";
return 0;
@ -235,7 +235,7 @@ class VersionGuesserTest extends TestCase
->expects($this->at(0))
->method('execute')
->willReturnCallback(function ($command, &$output) use ($self, $commitHash, $anotherCommitHash) {
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
$self->assertEquals('git branch -a --no-color --no-abbrev -v', $command);
$output = " latest-testing $commitHash Commit message\n* feature $anotherCommitHash Another message\n";
return 0;
@ -281,7 +281,7 @@ class VersionGuesserTest extends TestCase
->expects($this->at(0))
->method('execute')
->willReturnCallback(function ($command, &$output) use ($self, $commitHash, $anotherCommitHash) {
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
$self->assertEquals('git branch -a --no-color --no-abbrev -v', $command);
$output = "* latest-testing $commitHash Commit message\n current $anotherCommitHash Another message\n master $anotherCommitHash Another message\n";
return 0;
@ -316,7 +316,7 @@ class VersionGuesserTest extends TestCase
->expects($this->at(0))
->method('execute')
->willReturnCallback(function ($command, &$output) use ($self, $commitHash) {
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
$self->assertEquals('git branch -a --no-color --no-abbrev -v', $command);
$output = "* (no branch) $commitHash Commit message\n";
return 0;
@ -347,7 +347,7 @@ class VersionGuesserTest extends TestCase
->expects($this->at(0))
->method('execute')
->willReturnCallback(function ($command, &$output) use ($self, $commitHash) {
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
$self->assertEquals('git branch -a --no-color --no-abbrev -v', $command);
$output = "* (HEAD detached at FETCH_HEAD) $commitHash Commit message\n";
return 0;
@ -377,7 +377,7 @@ class VersionGuesserTest extends TestCase
->expects($this->at(0))
->method('execute')
->willReturnCallback(function ($command, &$output) use ($self, $commitHash) {
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
$self->assertEquals('git branch -a --no-color --no-abbrev -v', $command);
$output = "* (HEAD detached at 03a15d220) $commitHash Commit message\n";
return 0;
@ -406,7 +406,7 @@ class VersionGuesserTest extends TestCase
->expects($this->at(0))
->method('execute')
->willReturnCallback(function ($command, &$output) use ($self) {
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
$self->assertEquals('git branch -a --no-color --no-abbrev -v', $command);
$output = "* (HEAD detached at v2.0.5-alpha2) 433b98d4218c181bae01865901aac045585e8a1a Commit message\n";
return 0;
@ -446,7 +446,7 @@ class VersionGuesserTest extends TestCase
->expects($this->at(0))
->method('execute')
->willReturnCallback(function ($command, &$output) use ($self) {
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
$self->assertEquals('git branch -a --no-color --no-abbrev -v', $command);
$output = "* (HEAD detached at 1.0.0) c006f0c12bbbf197b5c071ffb1c0e9812bb14a4d Commit message\n";
return 0;
@ -487,7 +487,7 @@ class VersionGuesserTest extends TestCase
->expects($this->at(0))
->method('execute')
->willReturnCallback(function ($command, &$output) use ($self) {
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
$self->assertEquals('git branch -a --no-color --no-abbrev -v', $command);
$output = "* foo 03a15d220da53c52eddd5f32ffca64a7b3801bea Commit message\n";
return 0;
@ -517,7 +517,7 @@ class VersionGuesserTest extends TestCase
->expects($this->at(0))
->method('execute')
->willReturnCallback(function ($command, &$output) use ($self) {
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
$self->assertEquals('git branch -a --no-color --no-abbrev -v', $command);
$output = "* 1.5 03a15d220da53c52eddd5f32ffca64a7b3801bea Commit message\n";
return 0;
@ -532,4 +532,46 @@ class VersionGuesserTest extends TestCase
$this->assertEquals("1.5.x-dev", $versionData['pretty_version']);
$this->assertEquals("1.5.9999999.9999999-dev", $versionData['version']);
}
public function testRemoteBranchesAreSelected()
{
$executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor')
->setMethods(array('execute'))
->disableArgumentCloning()
->disableOriginalConstructor()
->getMock()
;
$self = $this;
$executor
->expects($this->at(0))
->method('execute')
->willReturnCallback(function ($command, &$output) use ($self) {
$self->assertEquals('git branch -a --no-color --no-abbrev -v', $command);
$output = "* feature-branch 03a15d220da53c52eddd5f32ffca64a7b3801bea Commit message\n".
"remotes/origin/1.5 03a15d220da53c52eddd5f32ffca64a7b3801bea Commit message\n";
return 0;
})
;
$executor
->expects($this->at(1))
->method('execute')
->willReturnCallback(function ($command, &$output, $path) use ($self) {
$self->assertEquals('git rev-list remotes/origin/1.5..feature-branch', $command);
$output = "\n";
return 0;
})
;
$config = new Config;
$config->merge(array('repositories' => array('packagist' => false)));
$guesser = new VersionGuesser($config, $executor, new VersionParser());
$versionData = $guesser->guessVersion(array('version' => 'self.version'), 'dummy/path');
$this->assertEquals("1.5.x-dev", $versionData['pretty_version']);
$this->assertEquals("1.5.9999999.9999999-dev", $versionData['version']);
}
}

@ -57,9 +57,9 @@ class VersionSelectorTest extends TestCase
$parser = new VersionParser;
$package1 = $this->createPackage('1.0.0');
$package1->setRequires(array('php' => new Link($packageName, 'php', $parser->parseConstraints('>=5.4'), 'requires', '>=5.4')));
$package1->setRequires(array('php' => new Link($packageName, 'php', $parser->parseConstraints('>=5.4'), Link::TYPE_REQUIRE, '>=5.4')));
$package2 = $this->createPackage('2.0.0');
$package2->setRequires(array('php' => new Link($packageName, 'php', $parser->parseConstraints('>=5.6'), 'requires', '>=5.6')));
$package2->setRequires(array('php' => new Link($packageName, 'php', $parser->parseConstraints('>=5.6'), Link::TYPE_REQUIRE, '>=5.6')));
$packages = array($package1, $package2);
$repositorySet->expects($this->any())
@ -83,9 +83,9 @@ class VersionSelectorTest extends TestCase
$parser = new VersionParser;
$package1 = $this->createPackage('1.0.0');
$package1->setRequires(array('ext-zip' => new Link($packageName, 'ext-zip', $parser->parseConstraints('^5.2'), 'requires', '^5.2')));
$package1->setRequires(array('ext-zip' => new Link($packageName, 'ext-zip', $parser->parseConstraints('^5.2'), Link::TYPE_REQUIRE, '^5.2')));
$package2 = $this->createPackage('2.0.0');
$package2->setRequires(array('ext-zip' => new Link($packageName, 'ext-zip', $parser->parseConstraints('^5.4'), 'requires', '^5.4')));
$package2->setRequires(array('ext-zip' => new Link($packageName, 'ext-zip', $parser->parseConstraints('^5.4'), Link::TYPE_REQUIRE, '^5.4')));
$packages = array($package1, $package2);
$repositorySet->expects($this->any())
@ -109,9 +109,9 @@ class VersionSelectorTest extends TestCase
$parser = new VersionParser;
$package1 = $this->createPackage('1.0.0');
$package1->setRequires(array('composer-runtime-api' => new Link($packageName, 'composer-runtime-api', $parser->parseConstraints('^1.0'), 'requires', '^1.0')));
$package1->setRequires(array('composer-runtime-api' => new Link($packageName, 'composer-runtime-api', $parser->parseConstraints('^1.0'), Link::TYPE_REQUIRE, '^1.0')));
$package2 = $this->createPackage('1.1.0');
$package2->setRequires(array('composer-runtime-api' => new Link($packageName, 'composer-runtime-api', $parser->parseConstraints('^2.0'), 'requires', '^2.0')));
$package2->setRequires(array('composer-runtime-api' => new Link($packageName, 'composer-runtime-api', $parser->parseConstraints('^2.0'), Link::TYPE_REQUIRE, '^2.0')));
$packages = array($package1, $package2);
$repositorySet->expects($this->any())

@ -44,7 +44,7 @@ class VcsRepositoryTest extends TestCase
self::$gitRepo = $this->getUniqueTmpDirectory();
if (!@chdir(self::$gitRepo)) {
$this->skipped = 'Could not create and move into the temp git repo '.self::$gitRepo;
$this->skipped = 'Could not move into the temp git repo '.self::$gitRepo;
return;
}

Loading…
Cancel
Save