Merge remote-tracking branch 'parent/master'
Conflicts: src/Composer/Factory.phppull/1407/head
commit
b6df8549cd
29
.php_cs
29
.php_cs
|
@ -10,9 +10,32 @@ $finder = Symfony\CS\Finder\DefaultFinder::create()
|
|||
|
||||
return Symfony\CS\Config\Config::create()
|
||||
->setUsingCache(true)
|
||||
->level(Symfony\CS\FixerInterface::NONE_LEVEL)
|
||||
->fixers(array(
|
||||
'psr0', 'encoding', 'short_tag', 'braces', 'elseif', 'eof_ending', 'function_declaration', 'indentation', 'line_after_namespace', 'linefeed', 'lowercase_constants', 'lowercase_keywords', 'multiple_use', 'php_closing_tag', 'trailing_spaces', 'visibility', 'duplicate_semicolon', 'extra_empty_lines', 'include', 'namespace_no_leading_whitespace', 'object_operator', 'operators_spaces', 'phpdoc_params', 'return', 'single_array_no_trailing_comma', 'spaces_cast', 'standardize_not_equal', 'ternary_spaces', 'unused_use', 'whitespacy_lines', 'multiline_array_tailing_comma',
|
||||
->setRiskyAllowed(true)
|
||||
->setRules(array(
|
||||
'@PSR2' => true,
|
||||
'duplicate_semicolon' => true,
|
||||
'extra_empty_lines' => true,
|
||||
'include' => true,
|
||||
'multiline_array_trailing_comma' => true,
|
||||
'namespace_no_leading_whitespace' => true,
|
||||
'object_operator' => true,
|
||||
'operators_spaces' => true,
|
||||
'phpdoc_align' => true,
|
||||
'phpdoc_indent' => true,
|
||||
'phpdoc_no_access' => true,
|
||||
'phpdoc_no_package' => true,
|
||||
'phpdoc_order' => true,
|
||||
'phpdoc_scalar' => true,
|
||||
'phpdoc_trim' => true,
|
||||
'phpdoc_type_to_var' => true,
|
||||
'psr0' => true,
|
||||
'return' => true,
|
||||
'single_array_no_trailing_comma' => true,
|
||||
'spaces_cast' => true,
|
||||
'standardize_not_equal' => true,
|
||||
'ternary_spaces' => true,
|
||||
'unused_use' => true,
|
||||
'whitespacy_lines' => true,
|
||||
))
|
||||
->finder($finder)
|
||||
;
|
||||
|
|
|
@ -7,8 +7,9 @@ cache:
|
|||
- $HOME/.composer/cache
|
||||
|
||||
addons:
|
||||
apt_packages:
|
||||
- parallel
|
||||
apt:
|
||||
packages:
|
||||
- parallel
|
||||
|
||||
php:
|
||||
- 5.3.3
|
||||
|
|
|
@ -2,7 +2,7 @@ Contributing to Composer
|
|||
========================
|
||||
|
||||
Please note that this project is released with a
|
||||
[Contributor Code of Conduct](http://contributor-covenant.org/version/1/0/0/).
|
||||
[Contributor Code of Conduct](http://contributor-covenant.org/version/1/2/0/).
|
||||
By participating in this project you agree to abide by its terms.
|
||||
|
||||
Reporting Issues
|
||||
|
@ -42,6 +42,8 @@ Contributing policy
|
|||
Fork the project, create a feature branch, and send us a pull request.
|
||||
|
||||
To ensure a consistent code base, you should make sure the code follows
|
||||
the [PSR-2 Coding Standards](http://www.php-fig.org/psr/psr-2/).
|
||||
the [PSR-2 Coding Standards](http://www.php-fig.org/psr/psr-2/). You can also
|
||||
run [php-cs-fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer) with the
|
||||
configuration file that can be found in the project root directory.
|
||||
|
||||
If you would like to help, take a look at the [list of issues](https://github.com/composer/composer/issues).
|
||||
If you would like to help, take a look at the [list of open issues](https://github.com/composer/composer/issues).
|
||||
|
|
|
@ -6,7 +6,7 @@ Composer helps you declare, manage and install dependencies of PHP projects, ens
|
|||
See [https://getcomposer.org/](https://getcomposer.org/) for more information and documentation.
|
||||
|
||||
[![Build Status](https://travis-ci.org/composer/composer.svg?branch=master)](https://travis-ci.org/composer/composer)
|
||||
[![Dependency Status](https://www.versioneye.com/php/composer:composer/dev-master/badge.svg)](https://www.versioneye.com/php/composer:composer/dev-master)
|
||||
[![Dependency Status](https://www.versioneye.com/php/composer:composer/dev-master/badge.svg)](https://www.versioneye.com/php/composer:composer/dev-master)
|
||||
[![Reference Status](https://www.versioneye.com/php/composer:composer/reference_badge.svg?style=flat)](https://www.versioneye.com/php/composer:composer/references)
|
||||
|
||||
Installation / Usage
|
||||
|
@ -45,7 +45,6 @@ Updating Composer
|
|||
Running `php composer.phar self-update` or equivalent will update a phar
|
||||
install to the latest version.
|
||||
|
||||
|
||||
Community
|
||||
---------
|
||||
|
||||
|
@ -56,7 +55,7 @@ For support, Stack Overflow also offers a good collection of
|
|||
[Composer related questions](https://stackoverflow.com/questions/tagged/composer-php).
|
||||
|
||||
Please note that this project is released with a
|
||||
[Contributor Code of Conduct](http://contributor-covenant.org/version/1/0/0/).
|
||||
[Contributor Code of Conduct](http://contributor-covenant.org/version/1/2/0/).
|
||||
By participating in this project and its community you agree to abide by those terms.
|
||||
|
||||
Requirements
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
build: false
|
||||
shallow_clone: true
|
||||
platform: x86
|
||||
clone_folder: c:\projects\composer
|
||||
|
||||
cache:
|
||||
- c:\tools\php -> appveyor.yml
|
||||
|
||||
init:
|
||||
- SET PATH=C:\Program Files\OpenSSL;c:\tools\php;%PATH%
|
||||
- SET COMPOSER_NO_INTERACTION=1
|
||||
- SET PHP=1
|
||||
- SET ANSICON=121x90 (121x90)
|
||||
|
||||
install:
|
||||
- IF EXIST c:\tools\php (SET PHP=0)
|
||||
- IF %PHP%==1 cinst -y OpenSSL.Light
|
||||
- IF %PHP%==1 cinst -y php
|
||||
- cd c:\tools\php
|
||||
- IF %PHP%==1 copy php.ini-production php.ini /Y
|
||||
- IF %PHP%==1 echo date.timezone="UTC" >> php.ini
|
||||
- IF %PHP%==1 echo extension_dir=ext >> php.ini
|
||||
- IF %PHP%==1 echo extension=php_openssl.dll >> php.ini
|
||||
- IF %PHP%==1 echo extension=php_mbstring.dll >> php.ini
|
||||
- IF %PHP%==1 echo extension=php_fileinfo.dll >> php.ini
|
||||
- IF %PHP%==1 echo @php %%~dp0composer.phar %%* > composer.bat
|
||||
- appveyor DownloadFile https://getcomposer.org/composer.phar
|
||||
- cd c:\projects\composer
|
||||
- composer install --prefer-source --no-progress
|
||||
|
||||
test_script:
|
||||
- cd c:\projects\composer
|
||||
- vendor/bin/phpunit --colors=always
|
|
@ -1,9 +0,0 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../src/bootstrap.php';
|
||||
|
||||
use Composer\Util\SpdxLicensesUpdater;
|
||||
|
||||
$licenses = new SpdxLicensesUpdater;
|
||||
$licenses->update();
|
|
@ -23,11 +23,14 @@
|
|||
},
|
||||
"require": {
|
||||
"php": ">=5.3.2",
|
||||
"justinrainbow/json-schema": "~1.4",
|
||||
"justinrainbow/json-schema": "^1.4.4",
|
||||
"composer/spdx-licenses": "^1.0",
|
||||
"composer/semver": "^1.0",
|
||||
"seld/jsonlint": "~1.0",
|
||||
"symfony/console": "~2.5",
|
||||
"symfony/finder": "~2.2",
|
||||
"symfony/process": "~2.1",
|
||||
"symfony/filesystem": "~2.5",
|
||||
"seld/phar-utils": "~1.0",
|
||||
"seld/cli-prompt": "~1.0"
|
||||
},
|
||||
|
@ -35,7 +38,7 @@
|
|||
"phpunit/phpunit": "~4.5",
|
||||
"phpunit/phpunit-mock-objects": "2.3.0"
|
||||
},
|
||||
"_": "phpunit/phpunit-mock-objects required in 2.3.0 due to https://github.com/sebastianbergmann/phpunit-mock-objects/issues/223",
|
||||
"_": "phpunit/phpunit-mock-objects required in 2.3.0 due to https://github.com/sebastianbergmann/phpunit-mock-objects/issues/223 - needs hhvm 3.8+ on travis",
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "5.3.3"
|
||||
|
|
|
@ -4,24 +4,146 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "556ac817fc0b456bddc48918ef09930d",
|
||||
"hash": "af3956ae4c1a09e3e72cd66346a6176d",
|
||||
"content-hash": "96817117d0ca449e7deff55c98eb7bdc",
|
||||
"packages": [
|
||||
{
|
||||
"name": "justinrainbow/json-schema",
|
||||
"version": "1.4.1",
|
||||
"name": "composer/semver",
|
||||
"version": "1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/justinrainbow/json-schema.git",
|
||||
"reference": "2465fe486c864e30badaa4d005ebdf89dbc503f3"
|
||||
"url": "https://github.com/composer/semver.git",
|
||||
"reference": "d0e1ccc6d44ab318b758d709e19176037da6b1ba"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/2465fe486c864e30badaa4d005ebdf89dbc503f3",
|
||||
"reference": "2465fe486c864e30badaa4d005ebdf89dbc503f3",
|
||||
"url": "https://api.github.com/repos/composer/semver/zipball/d0e1ccc6d44ab318b758d709e19176037da6b1ba",
|
||||
"reference": "d0e1ccc6d44ab318b758d709e19176037da6b1ba",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
"php": ">=5.3.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.5",
|
||||
"phpunit/phpunit-mock-objects": "~2.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Composer\\Semver\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Rob Bast",
|
||||
"email": "rob.bast@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Nils Adermann",
|
||||
"email": "naderman@naderman.de",
|
||||
"homepage": "http://www.naderman.de"
|
||||
},
|
||||
{
|
||||
"name": "Jordi Boggiano",
|
||||
"email": "j.boggiano@seld.be",
|
||||
"homepage": "http://seld.be"
|
||||
}
|
||||
],
|
||||
"description": "Semver library that offers utilities, version constraint parsing and validation.",
|
||||
"keywords": [
|
||||
"semantic",
|
||||
"semver",
|
||||
"validation",
|
||||
"versioning"
|
||||
],
|
||||
"time": "2015-09-21 09:42:36"
|
||||
},
|
||||
{
|
||||
"name": "composer/spdx-licenses",
|
||||
"version": "1.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/spdx-licenses.git",
|
||||
"reference": "324b3530ac3e6277ff4bedf82a34fbf35836eb8d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/spdx-licenses/zipball/324b3530ac3e6277ff4bedf82a34fbf35836eb8d",
|
||||
"reference": "324b3530ac3e6277ff4bedf82a34fbf35836eb8d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.5",
|
||||
"phpunit/phpunit-mock-objects": "~2.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Composer\\Spdx\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Rob Bast",
|
||||
"email": "rob.bast@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Nils Adermann",
|
||||
"email": "naderman@naderman.de",
|
||||
"homepage": "http://www.naderman.de"
|
||||
},
|
||||
{
|
||||
"name": "Jordi Boggiano",
|
||||
"email": "j.boggiano@seld.be",
|
||||
"homepage": "http://seld.be"
|
||||
}
|
||||
],
|
||||
"description": "SPDX licenses list and validation library.",
|
||||
"keywords": [
|
||||
"license",
|
||||
"spdx",
|
||||
"validator"
|
||||
],
|
||||
"time": "2015-09-07 16:25:20"
|
||||
},
|
||||
{
|
||||
"name": "justinrainbow/json-schema",
|
||||
"version": "1.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/justinrainbow/json-schema.git",
|
||||
"reference": "a4bee9f4b344b66e0a0d96c7afae1e92edf385fe"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/a4bee9f4b344b66e0a0d96c7afae1e92edf385fe",
|
||||
"reference": "a4bee9f4b344b66e0a0d96c7afae1e92edf385fe",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"json-schema/json-schema-test-suite": "1.1.0",
|
||||
|
@ -38,8 +160,8 @@
|
|||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"JsonSchema": "src/"
|
||||
"psr-4": {
|
||||
"JsonSchema\\": "src/JsonSchema/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
|
@ -70,7 +192,7 @@
|
|||
"json",
|
||||
"schema"
|
||||
],
|
||||
"time": "2015-03-27 16:41:39"
|
||||
"time": "2015-09-08 22:28:04"
|
||||
},
|
||||
{
|
||||
"name": "seld/cli-prompt",
|
||||
|
@ -212,17 +334,17 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v2.6.9",
|
||||
"version": "v2.6.11",
|
||||
"target-dir": "Symfony/Component/Console",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/Console.git",
|
||||
"reference": "b5ec0c11a204718f2b656357f5505a8e578f30dd"
|
||||
"reference": "0e5e18ae09d3f5c06367759be940e9ed3f568359"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/Console/zipball/b5ec0c11a204718f2b656357f5505a8e578f30dd",
|
||||
"reference": "b5ec0c11a204718f2b656357f5505a8e578f30dd",
|
||||
"url": "https://api.github.com/repos/symfony/Console/zipball/0e5e18ae09d3f5c06367759be940e9ed3f568359",
|
||||
"reference": "0e5e18ae09d3f5c06367759be940e9ed3f568359",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -266,21 +388,71 @@
|
|||
],
|
||||
"description": "Symfony Console Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-05-29 14:42:58"
|
||||
"time": "2015-07-26 09:08:40"
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v2.6.11",
|
||||
"target-dir": "Symfony/Component/Filesystem",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/Filesystem.git",
|
||||
"reference": "823c035b1a5c13a4924e324d016eb07e70f94735"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/Filesystem/zipball/823c035b1a5c13a4924e324d016eb07e70f94735",
|
||||
"reference": "823c035b1a5c13a4924e324d016eb07e70f94735",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "~2.7"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.6-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Symfony\\Component\\Filesystem\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Filesystem Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-07-08 05:59:48"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v2.6.9",
|
||||
"version": "v2.6.11",
|
||||
"target-dir": "Symfony/Component/Finder",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/Finder.git",
|
||||
"reference": "ffedd3e0ff8155188155e9322fe21b9ee012ac14"
|
||||
"reference": "203a10f928ae30176deeba33512999233181dd28"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/Finder/zipball/ffedd3e0ff8155188155e9322fe21b9ee012ac14",
|
||||
"reference": "ffedd3e0ff8155188155e9322fe21b9ee012ac14",
|
||||
"url": "https://api.github.com/repos/symfony/Finder/zipball/203a10f928ae30176deeba33512999233181dd28",
|
||||
"reference": "203a10f928ae30176deeba33512999233181dd28",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -316,21 +488,21 @@
|
|||
],
|
||||
"description": "Symfony Finder Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-05-15 13:32:45"
|
||||
"time": "2015-07-09 16:02:48"
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v2.6.9",
|
||||
"version": "v2.6.11",
|
||||
"target-dir": "Symfony/Component/Process",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/Process.git",
|
||||
"reference": "7856d78ab6cce6e59d02d9e1a873441f6bd21306"
|
||||
"reference": "57f1e88bb5dafa449b83f9f265b11d52d517b3e9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/Process/zipball/7856d78ab6cce6e59d02d9e1a873441f6bd21306",
|
||||
"reference": "7856d78ab6cce6e59d02d9e1a873441f6bd21306",
|
||||
"url": "https://api.github.com/repos/symfony/Process/zipball/57f1e88bb5dafa449b83f9f265b11d52d517b3e9",
|
||||
"reference": "57f1e88bb5dafa449b83f9f265b11d52d517b3e9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -366,22 +538,22 @@
|
|||
],
|
||||
"description": "Symfony Process Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-05-15 13:32:45"
|
||||
"time": "2015-06-30 16:10:16"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "doctrine/instantiator",
|
||||
"version": "1.0.4",
|
||||
"version": "1.0.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/instantiator.git",
|
||||
"reference": "f976e5de371104877ebc89bd8fecb0019ed9c119"
|
||||
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/f976e5de371104877ebc89bd8fecb0019ed9c119",
|
||||
"reference": "f976e5de371104877ebc89bd8fecb0019ed9c119",
|
||||
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
|
||||
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -392,7 +564,7 @@
|
|||
"ext-pdo": "*",
|
||||
"ext-phar": "*",
|
||||
"phpunit/phpunit": "~4.0",
|
||||
"squizlabs/php_codesniffer": "2.0.*@ALPHA"
|
||||
"squizlabs/php_codesniffer": "~2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
|
@ -401,8 +573,8 @@
|
|||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Doctrine\\Instantiator\\": "src"
|
||||
"psr-4": {
|
||||
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
|
@ -422,7 +594,7 @@
|
|||
"constructor",
|
||||
"instantiate"
|
||||
],
|
||||
"time": "2014-10-13 12:58:55"
|
||||
"time": "2015-06-14 21:17:01"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-docblock",
|
||||
|
@ -475,16 +647,16 @@
|
|||
},
|
||||
{
|
||||
"name": "phpspec/prophecy",
|
||||
"version": "v1.4.1",
|
||||
"version": "v1.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpspec/prophecy.git",
|
||||
"reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373"
|
||||
"reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373",
|
||||
"reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373",
|
||||
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/4745ded9307786b730d7a60df5cb5a6c43cf95f7",
|
||||
"reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -531,20 +703,20 @@
|
|||
"spy",
|
||||
"stub"
|
||||
],
|
||||
"time": "2015-04-27 22:15:08"
|
||||
"time": "2015-08-13 10:07:40"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "2.1.5",
|
||||
"version": "2.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "be2286cb8c7e1773eded49d9719219e6f74f9e3e"
|
||||
"reference": "2d7c03c0e4e080901b8f33b2897b0577be18a13c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/be2286cb8c7e1773eded49d9719219e6f74f9e3e",
|
||||
"reference": "be2286cb8c7e1773eded49d9719219e6f74f9e3e",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2d7c03c0e4e080901b8f33b2897b0577be18a13c",
|
||||
"reference": "2d7c03c0e4e080901b8f33b2897b0577be18a13c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -552,7 +724,7 @@
|
|||
"phpunit/php-file-iterator": "~1.3",
|
||||
"phpunit/php-text-template": "~1.2",
|
||||
"phpunit/php-token-stream": "~1.3",
|
||||
"sebastian/environment": "~1.0",
|
||||
"sebastian/environment": "^1.3.2",
|
||||
"sebastian/version": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
|
@ -567,7 +739,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.1.x-dev"
|
||||
"dev-master": "2.2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -593,20 +765,20 @@
|
|||
"testing",
|
||||
"xunit"
|
||||
],
|
||||
"time": "2015-06-09 13:05:42"
|
||||
"time": "2015-08-04 03:42:39"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
"version": "1.4.0",
|
||||
"version": "1.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
|
||||
"reference": "a923bb15680d0089e2316f7a4af8f437046e96bb"
|
||||
"reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a923bb15680d0089e2316f7a4af8f437046e96bb",
|
||||
"reference": "a923bb15680d0089e2316f7a4af8f437046e96bb",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
|
||||
"reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -640,20 +812,20 @@
|
|||
"filesystem",
|
||||
"iterator"
|
||||
],
|
||||
"time": "2015-04-02 05:19:05"
|
||||
"time": "2015-06-21 13:08:43"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-text-template",
|
||||
"version": "1.2.0",
|
||||
"version": "1.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-text-template.git",
|
||||
"reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a"
|
||||
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a",
|
||||
"reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
|
||||
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -662,20 +834,17 @@
|
|||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"Text/"
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"include-path": [
|
||||
""
|
||||
],
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sb@sebastian-bergmann.de",
|
||||
"email": "sebastian@phpunit.de",
|
||||
"role": "lead"
|
||||
}
|
||||
],
|
||||
|
@ -684,20 +853,20 @@
|
|||
"keywords": [
|
||||
"template"
|
||||
],
|
||||
"time": "2014-01-30 17:20:04"
|
||||
"time": "2015-06-21 13:50:34"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-timer",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-timer.git",
|
||||
"reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c"
|
||||
"reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c",
|
||||
"reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b",
|
||||
"reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -706,13 +875,10 @@
|
|||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"PHP/"
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"include-path": [
|
||||
""
|
||||
],
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
|
@ -728,20 +894,20 @@
|
|||
"keywords": [
|
||||
"timer"
|
||||
],
|
||||
"time": "2013-08-02 07:42:54"
|
||||
"time": "2015-06-21 08:01:12"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-token-stream",
|
||||
"version": "1.4.1",
|
||||
"version": "1.4.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
|
||||
"reference": "eab81d02569310739373308137284e0158424330"
|
||||
"reference": "3ab72c62e550370a6cd5dc873e1a04ab57562f5b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330",
|
||||
"reference": "eab81d02569310739373308137284e0158424330",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3ab72c62e550370a6cd5dc873e1a04ab57562f5b",
|
||||
"reference": "3ab72c62e550370a6cd5dc873e1a04ab57562f5b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -777,20 +943,20 @@
|
|||
"keywords": [
|
||||
"tokenizer"
|
||||
],
|
||||
"time": "2015-04-08 04:46:07"
|
||||
"time": "2015-08-16 08:51:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "4.7.2",
|
||||
"version": "4.8.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "8e0c63329c8c4185296b8d357daa5c6bae43080f"
|
||||
"reference": "2246830f4a1a551c67933e4171bf2126dc29d357"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e0c63329c8c4185296b8d357daa5c6bae43080f",
|
||||
"reference": "8e0c63329c8c4185296b8d357daa5c6bae43080f",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2246830f4a1a551c67933e4171bf2126dc29d357",
|
||||
"reference": "2246830f4a1a551c67933e4171bf2126dc29d357",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -800,15 +966,15 @@
|
|||
"ext-reflection": "*",
|
||||
"ext-spl": "*",
|
||||
"php": ">=5.3.3",
|
||||
"phpspec/prophecy": "~1.3,>=1.3.1",
|
||||
"phpspec/prophecy": "^1.3.1",
|
||||
"phpunit/php-code-coverage": "~2.1",
|
||||
"phpunit/php-file-iterator": "~1.4",
|
||||
"phpunit/php-text-template": "~1.2",
|
||||
"phpunit/php-timer": "~1.0",
|
||||
"phpunit/php-timer": ">=1.0.6",
|
||||
"phpunit/phpunit-mock-objects": "~2.3",
|
||||
"sebastian/comparator": "~1.1",
|
||||
"sebastian/diff": "~1.2",
|
||||
"sebastian/environment": "~1.2",
|
||||
"sebastian/environment": "~1.3",
|
||||
"sebastian/exporter": "~1.2",
|
||||
"sebastian/global-state": "~1.0",
|
||||
"sebastian/version": "~1.0",
|
||||
|
@ -823,7 +989,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.7.x-dev"
|
||||
"dev-master": "4.8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -849,7 +1015,7 @@
|
|||
"testing",
|
||||
"xunit"
|
||||
],
|
||||
"time": "2015-06-06 08:36:08"
|
||||
"time": "2015-08-24 04:09:38"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit-mock-objects",
|
||||
|
@ -908,16 +1074,16 @@
|
|||
},
|
||||
{
|
||||
"name": "sebastian/comparator",
|
||||
"version": "1.1.1",
|
||||
"version": "1.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/comparator.git",
|
||||
"reference": "1dd8869519a225f7f2b9eb663e225298fade819e"
|
||||
"reference": "937efb279bd37a375bcadf584dec0726f84dbf22"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e",
|
||||
"reference": "1dd8869519a225f7f2b9eb663e225298fade819e",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22",
|
||||
"reference": "937efb279bd37a375bcadf584dec0726f84dbf22",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -931,7 +1097,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.1.x-dev"
|
||||
"dev-master": "1.2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -968,7 +1134,7 @@
|
|||
"compare",
|
||||
"equality"
|
||||
],
|
||||
"time": "2015-01-29 16:28:08"
|
||||
"time": "2015-07-26 15:48:44"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/diff",
|
||||
|
@ -1024,16 +1190,16 @@
|
|||
},
|
||||
{
|
||||
"name": "sebastian/environment",
|
||||
"version": "1.2.2",
|
||||
"version": "1.3.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/environment.git",
|
||||
"reference": "5a8c7d31914337b69923db26c4221b81ff5a196e"
|
||||
"reference": "6324c907ce7a52478eeeaede764f48733ef5ae44"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5a8c7d31914337b69923db26c4221b81ff5a196e",
|
||||
"reference": "5a8c7d31914337b69923db26c4221b81ff5a196e",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6324c907ce7a52478eeeaede764f48733ef5ae44",
|
||||
"reference": "6324c907ce7a52478eeeaede764f48733ef5ae44",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1070,20 +1236,20 @@
|
|||
"environment",
|
||||
"hhvm"
|
||||
],
|
||||
"time": "2015-01-01 10:01:08"
|
||||
"time": "2015-08-03 06:14:51"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/exporter",
|
||||
"version": "1.2.0",
|
||||
"version": "1.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/exporter.git",
|
||||
"reference": "84839970d05254c73cde183a721c7af13aede943"
|
||||
"reference": "7ae5513327cb536431847bcc0c10edba2701064e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943",
|
||||
"reference": "84839970d05254c73cde183a721c7af13aede943",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e",
|
||||
"reference": "7ae5513327cb536431847bcc0c10edba2701064e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1136,7 +1302,7 @@
|
|||
"export",
|
||||
"exporter"
|
||||
],
|
||||
"time": "2015-01-27 07:23:06"
|
||||
"time": "2015-06-21 07:55:53"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/global-state",
|
||||
|
@ -1191,16 +1357,16 @@
|
|||
},
|
||||
{
|
||||
"name": "sebastian/recursion-context",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/recursion-context.git",
|
||||
"reference": "3989662bbb30a29d20d9faa04a846af79b276252"
|
||||
"reference": "994d4a811bafe801fb06dccbee797863ba2792ba"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252",
|
||||
"reference": "3989662bbb30a29d20d9faa04a846af79b276252",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/994d4a811bafe801fb06dccbee797863ba2792ba",
|
||||
"reference": "994d4a811bafe801fb06dccbee797863ba2792ba",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1240,20 +1406,20 @@
|
|||
],
|
||||
"description": "Provides functionality to recursively process PHP variables",
|
||||
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
|
||||
"time": "2015-01-24 09:48:32"
|
||||
"time": "2015-06-21 08:04:50"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/version",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/version.git",
|
||||
"reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4"
|
||||
"reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ab931d46cd0d3204a91e1b9a40c4bc13032b58e4",
|
||||
"reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
|
||||
"reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
|
@ -1275,21 +1441,21 @@
|
|||
],
|
||||
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
|
||||
"homepage": "https://github.com/sebastianbergmann/version",
|
||||
"time": "2015-02-24 06:35:25"
|
||||
"time": "2015-06-21 13:59:46"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v2.6.9",
|
||||
"version": "v2.6.11",
|
||||
"target-dir": "Symfony/Component/Yaml",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/Yaml.git",
|
||||
"reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2"
|
||||
"reference": "c044d1744b8e91aaaa0d9bac683ab87ec7cbf359"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/Yaml/zipball/f157ab074e453ecd4c0fa775f721f6e67a99d9e2",
|
||||
"reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2",
|
||||
"url": "https://api.github.com/repos/symfony/Yaml/zipball/c044d1744b8e91aaaa0d9bac683ab87ec7cbf359",
|
||||
"reference": "c044d1744b8e91aaaa0d9bac683ab87ec7cbf359",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1325,7 +1491,7 @@
|
|||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-05-02 15:18:45"
|
||||
"time": "2015-07-26 08:59:42"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
|
|
153
doc/00-intro.md
153
doc/00-intro.md
|
@ -1,54 +1,41 @@
|
|||
# Introduction
|
||||
|
||||
Composer is a tool for dependency management in PHP. It allows you to declare
|
||||
the dependent libraries your project needs and it will install them in your
|
||||
project for you.
|
||||
the libraries your project depends on and it will manage (install/update) them
|
||||
for you.
|
||||
|
||||
## Dependency management
|
||||
|
||||
Composer is not a package manager. Yes, it deals with "packages" or libraries, but
|
||||
it manages them on a per-project basis, installing them in a directory (e.g. `vendor`)
|
||||
inside your project. By default it will never install anything globally. Thus,
|
||||
it is a dependency manager.
|
||||
Composer is **not** a package manager in the same sense as Yum or Apt are. Yes,
|
||||
it deals with "packages" or libraries, but it manages them on a per-project
|
||||
basis, installing them in a directory (e.g. `vendor`) inside your project. By
|
||||
default it will never install anything globally. Thus, it is a dependency
|
||||
manager.
|
||||
|
||||
This idea is not new and Composer is strongly inspired by node's [npm](https://npmjs.org/)
|
||||
and ruby's [bundler](http://bundler.io/). But there has not been such a tool
|
||||
for PHP.
|
||||
This idea is not new and Composer is strongly inspired by node's
|
||||
[npm](https://npmjs.org/) and ruby's [bundler](http://bundler.io/).
|
||||
|
||||
The problem that Composer solves is this:
|
||||
Suppose:
|
||||
|
||||
a) You have a project that depends on a number of libraries.
|
||||
|
||||
b) Some of those libraries depend on other libraries.
|
||||
|
||||
c) You declare the things you depend on.
|
||||
Composer:
|
||||
|
||||
d) Composer finds out which versions of which packages need to be installed, and
|
||||
c) Enables you to declare the libraries you depend on.
|
||||
|
||||
d) Finds out which versions of which packages can and need to be installed, and
|
||||
installs them (meaning it downloads them into your project).
|
||||
|
||||
## Declaring dependencies
|
||||
|
||||
Let's say you are creating a project, and you need a library that does logging.
|
||||
You decide to use [monolog](https://github.com/Seldaek/monolog). In order to
|
||||
add it to your project, all you need to do is create a `composer.json` file
|
||||
which describes the project's dependencies.
|
||||
|
||||
```json
|
||||
{
|
||||
"require": {
|
||||
"monolog/monolog": "1.2.*"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We are simply stating that our project requires some `monolog/monolog` package,
|
||||
any version beginning with `1.2`.
|
||||
See the [Basic usage](01-basic-usage.md) chapter for more details on declaring
|
||||
dependencies.
|
||||
|
||||
## System Requirements
|
||||
|
||||
Composer requires PHP 5.3.2+ to run. A few sensitive php settings and compile
|
||||
flags are also required, but when using the installer you will be warned about any
|
||||
incompatibilities.
|
||||
flags are also required, but when using the installer you will be warned about
|
||||
any incompatibilities.
|
||||
|
||||
To install packages from sources instead of simple zip archives, you will need
|
||||
git, svn or hg depending on how the package is version-controlled.
|
||||
|
@ -60,6 +47,12 @@ Linux and OSX.
|
|||
|
||||
### Downloading the Composer Executable
|
||||
|
||||
Composer offers a convenient installer that you can execute directly from the
|
||||
commandline. Feel free to [download this file](https://getcomposer.org/installer)
|
||||
or review it on [GitHub](https://github.com/composer/getcomposer.org/blob/master/web/installer)
|
||||
if you wish to know more about the inner workings of the installer. The source
|
||||
is plain PHP.
|
||||
|
||||
There are in short, two ways to install Composer. Locally as part of your
|
||||
project, or globally as a system wide executable.
|
||||
|
||||
|
@ -79,37 +72,54 @@ curl -sS https://getcomposer.org/installer | php
|
|||
php -r "readfile('https://getcomposer.org/installer');" | php
|
||||
```
|
||||
|
||||
The installer will just check a few PHP settings and then download `composer.phar`
|
||||
to your working directory. This file is the Composer binary. It is a PHAR (PHP
|
||||
archive), which is an archive format for PHP which can be run on the command
|
||||
line, amongst other things.
|
||||
The installer will just check a few PHP settings and then download
|
||||
`composer.phar` to your working directory. This file is the Composer binary. It
|
||||
is a PHAR (PHP archive), which is an archive format for PHP which can be run on
|
||||
the command line, amongst other things.
|
||||
|
||||
Now just run `php composer.phar` in order to run Composer.
|
||||
|
||||
You can install Composer to a specific directory by using the `--install-dir`
|
||||
option and providing a target directory (it can be an absolute or relative path):
|
||||
option and additionally (re)name it as well using the `--filename` option:
|
||||
|
||||
```sh
|
||||
curl -sS https://getcomposer.org/installer | php -- --install-dir=bin
|
||||
curl -sS https://getcomposer.org/installer | php -- --install-dir=bin --filename=composer
|
||||
```
|
||||
|
||||
Now just run `php bin/composer` in order to run Composer.
|
||||
|
||||
#### Globally
|
||||
|
||||
You can place this file anywhere you wish. If you put it in your `PATH`,
|
||||
you can access it globally. On unixy systems you can even make it
|
||||
executable and invoke it without `php`.
|
||||
You can place the Composer PHAR anywhere you wish. If you put it in a directory
|
||||
that is part of your `PATH`, you can access it globally. On unixy systems you
|
||||
can even make it executable and invoke it without directly using the `php`
|
||||
interpreter.
|
||||
|
||||
You can run these commands to easily access `composer` from anywhere on your system:
|
||||
Run these commands to globally install `composer` on your system:
|
||||
|
||||
```sh
|
||||
curl -sS https://getcomposer.org/installer | php
|
||||
mv composer.phar /usr/local/bin/composer
|
||||
```
|
||||
|
||||
> **Note:** If the above fails due to permissions, run the `mv` line
|
||||
> again with sudo.
|
||||
> **Note:** If the above fails due to permissions, run the `mv` line again
|
||||
> with sudo.
|
||||
|
||||
> **Note:** In OSX Yosemite the `/usr` directory does not exist by default. If you receive the error "/usr/local/bin/composer: No such file or directory" then you must create `/usr/local/bin/` manually before proceeding.
|
||||
A quick copy-paste version including sudo:
|
||||
|
||||
Then, just run `composer` in order to run Composer instead of `php composer.phar`.
|
||||
```sh
|
||||
curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer
|
||||
```
|
||||
|
||||
> **Note:** On some versions of OSX the `/usr` directory does not exist by
|
||||
> default. If you receive the error "/usr/local/bin/composer: No such file or
|
||||
> directory" then you must create the directory manually before proceeding:
|
||||
> `mkdir -p /usr/local/bin`.
|
||||
|
||||
> **Note:** For information on changing your PATH, please read the
|
||||
> [Wikipedia article](https://en.wikipedia.org/wiki/PATH_(variable)) and/or use Google.
|
||||
|
||||
Now just run `composer` in order to run Composer instead of `php composer.phar`.
|
||||
|
||||
## Installation - Windows
|
||||
|
||||
|
@ -117,24 +127,26 @@ Then, just run `composer` in order to run Composer instead of `php composer.phar
|
|||
|
||||
This is the easiest way to get Composer set up on your machine.
|
||||
|
||||
Download and run [Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe),
|
||||
it will install the latest Composer version and set up your PATH so that you can
|
||||
just call `composer` from any directory in your command line.
|
||||
Download and run
|
||||
[Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe). It will
|
||||
install the latest Composer version and set up your PATH so that you can just
|
||||
call `composer` from any directory in your command line.
|
||||
|
||||
> **Note:** Close your current terminal. Test usage with a new terminal:
|
||||
> That is important since the PATH only gets loaded when the terminal starts.
|
||||
> **Note:** Close your current terminal. Test usage with a new terminal: This is
|
||||
> important since the PATH only gets loaded when the terminal starts.
|
||||
|
||||
### Manual Installation
|
||||
|
||||
Change to a directory on your `PATH` and run the install snippet to download
|
||||
composer.phar:
|
||||
`composer.phar`:
|
||||
|
||||
```sh
|
||||
C:\Users\username>cd C:\bin
|
||||
C:\bin>php -r "readfile('https://getcomposer.org/installer');" | php
|
||||
```
|
||||
|
||||
> **Note:** If the above fails due to readfile, use the `http` url or enable php_openssl.dll in php.ini
|
||||
> **Note:** If the above fails due to readfile, use the `http` url or enable
|
||||
> php_openssl.dll in php.ini
|
||||
|
||||
Create a new `composer.bat` file alongside `composer.phar`:
|
||||
|
||||
|
@ -153,38 +165,7 @@ Composer version 27d8904
|
|||
|
||||
## Using Composer
|
||||
|
||||
We will now use Composer to install the dependencies of the project. If you
|
||||
don't have a `composer.json` file in the current directory please skip to the
|
||||
[Basic Usage](01-basic-usage.md) chapter.
|
||||
Now that you've installed Composer, you are ready to use it! Head on over to the
|
||||
next chapter for a short and simple demonstration.
|
||||
|
||||
To resolve and download dependencies, run the `install` command:
|
||||
|
||||
```sh
|
||||
php composer.phar install
|
||||
```
|
||||
|
||||
If you did a global install and do not have the phar in that directory
|
||||
run this instead:
|
||||
|
||||
```sh
|
||||
composer install
|
||||
```
|
||||
|
||||
Following the [example above](#declaring-dependencies), this will download
|
||||
monolog into the `vendor/monolog/monolog` directory.
|
||||
|
||||
## Autoloading
|
||||
|
||||
Besides downloading the library, Composer also prepares an autoload file that's
|
||||
capable of autoloading all of the classes in any of the libraries that it
|
||||
downloads. To use it, just add the following line to your code's bootstrap
|
||||
process:
|
||||
|
||||
```php
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
```
|
||||
|
||||
Woah! Now start using monolog! To keep learning more about Composer, keep
|
||||
reading the "Basic Usage" chapter.
|
||||
|
||||
[Basic Usage](01-basic-usage.md) →
|
||||
[Basic usage](01-basic-usage.md) →
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
# Basic usage
|
||||
|
||||
## Installing
|
||||
## Introduction
|
||||
|
||||
If you have not yet installed Composer, refer to the [Intro](00-intro.md) chapter.
|
||||
For our basic usage introduction, we will be installing `monolog/monolog`,
|
||||
a logging library. If you have not yet installed Composer, refer to the
|
||||
[Intro](00-intro.md) chapter.
|
||||
|
||||
> **Note:** for the sake of simplicity, this introduction will assume you
|
||||
> have performed a [local](00-intro.md#locally) install of Composer.
|
||||
|
||||
## `composer.json`: Project Setup
|
||||
|
||||
|
@ -10,14 +15,11 @@ 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.
|
||||
|
||||
The [JSON format](http://json.org/) is quite easy to write. It allows you to
|
||||
define nested structures.
|
||||
|
||||
### The `require` Key
|
||||
|
||||
The first (and often only) thing you specify in `composer.json` is the
|
||||
`require` key. You're simply telling Composer which packages your project
|
||||
depends on.
|
||||
[`require`](04-schema.md#require) key. You're simply telling Composer which
|
||||
packages your project depends on.
|
||||
|
||||
```json
|
||||
{
|
||||
|
@ -27,15 +29,16 @@ depends on.
|
|||
}
|
||||
```
|
||||
|
||||
As you can see, `require` takes an object that maps **package names** (e.g. `monolog/monolog`)
|
||||
to **package versions** (e.g. `1.0.*`).
|
||||
As you can see, [`require`](04-schema.md#require) takes an object that maps
|
||||
**package names** (e.g. `monolog/monolog`) to **version constraints** (e.g.
|
||||
`1.0.*`).
|
||||
|
||||
### Package Names
|
||||
|
||||
The package name consists of a vendor name and the project's name. Often these
|
||||
will be identical - the vendor name just exists to prevent naming clashes. It allows
|
||||
two different people to create a library named `json`, which would then just be
|
||||
named `igorw/json` and `seldaek/json`.
|
||||
will be identical - the vendor name just exists to prevent naming clashes. It
|
||||
allows two different people to create a library named `json`, which would then
|
||||
just be named `igorw/json` and `seldaek/json`.
|
||||
|
||||
Here we are requiring `monolog/monolog`, so the vendor name is the same as the
|
||||
project's name. For projects with a unique name this is recommended. It also
|
||||
|
@ -45,66 +48,26 @@ smaller decoupled parts.
|
|||
|
||||
### Package Versions
|
||||
|
||||
In the previous example we were requiring version [`1.0.*`](http://semver.mwl.be/#?package=monolog%2Fmonolog&version=1.0.*) of monolog. This
|
||||
means any version in the `1.0` development branch. It would match `1.0.0`,
|
||||
`1.0.2` or `1.0.20`.
|
||||
In the previous example we were requiring version
|
||||
[`1.0.*`](http://semver.mwl.be/#?package=monolog%2Fmonolog&version=1.0.*) of
|
||||
Monolog. This means any version in the `1.0` development branch. It is the
|
||||
equivalent of saying versions that match `>=1.0 <1.1`.
|
||||
|
||||
Version constraints can be specified in a few different ways.
|
||||
|
||||
Name | Example | Description
|
||||
-------------- | ------------------------------------------------------------------------ | -----------
|
||||
Exact version | `1.0.2` | You can specify the exact version of a package.
|
||||
Range | `>=1.0` `>=1.0 <2.0` <code>>=1.0 <1.1 || >=1.2</code> | By using comparison operators you can specify ranges of valid versions. Valid operators are `>`, `>=`, `<`, `<=`, `!=`. <br />You can define multiple ranges. Ranges separated by a space (<code> </code>) or comma (`,`) will be treated as a **logical AND**. A double pipe (<code>||</code>) will be treated as a **logical OR**. AND has higher precedence than OR.
|
||||
Hyphen Range | `1.0 - 2.0` | Inclusive set of versions. Partial versions on the right include are completed with a wildcard. For example `1.0 - 2.0` is equivalent to `>=1.0.0 <2.1` as the `2.0` becomes `2.0.*`. On the other hand `1.0.0 - 2.1.0` is equivalent to `>=1.0.0 <=2.1.0`.
|
||||
Wildcard | `1.0.*` | You can specify a pattern with a `*` wildcard. `1.0.*` is the equivalent of `>=1.0 <1.1`.
|
||||
Tilde Operator | `~1.2` | Very useful for projects that follow semantic versioning. `~1.2` is equivalent to `>=1.2 <2.0`. For more details, read the next section below.
|
||||
Caret Operator | `^1.2.3` | Very useful for projects that follow semantic versioning. `^1.2.3` is equivalent to `>=1.2.3 <2.0`. For more details, read the next section below.
|
||||
|
||||
### Next Significant Release (Tilde and Caret Operators)
|
||||
|
||||
The `~` operator is best explained by example: `~1.2` is equivalent to
|
||||
`>=1.2 <2.0.0`, while `~1.2.3` is equivalent to `>=1.2.3 <1.3.0`. As you can see
|
||||
it is mostly useful for projects respecting [semantic
|
||||
versioning](http://semver.org/). A common usage would be to mark the minimum
|
||||
minor version you depend on, like `~1.2` (which allows anything up to, but not
|
||||
including, 2.0). Since in theory there should be no backwards compatibility
|
||||
breaks until 2.0, that works well. Another way of looking at it is that using
|
||||
`~` specifies a minimum version, but allows the last digit specified to go up.
|
||||
|
||||
The `^` operator behaves very similarly but it sticks closer to semantic
|
||||
versioning, and will always allow non-breaking updates. For example `^1.2.3`
|
||||
is equivalent to `>=1.2.3 <2.0.0` as none of the releases until 2.0 should
|
||||
break backwards compatibility. For pre-1.0 versions it also acts with safety
|
||||
in mind and treats `^0.3` as `>=0.3.0 <0.4.0`
|
||||
|
||||
> **Note:** Though `2.0-beta.1` is strictly before `2.0`, a version constraint
|
||||
> like `~1.2` would not install it. As said above `~1.2` only means the `.2`
|
||||
> can change but the `1.` part is fixed.
|
||||
|
||||
> **Note:** The `~` operator has an exception on its behavior for the major
|
||||
> release number. This means for example that `~1` is the same as `~1.0` as
|
||||
> it will not allow the major number to increase trying to keep backwards
|
||||
> compatibility.
|
||||
Version constraints can be specified in several ways, read
|
||||
[versions](articles/versions.md) for more in-depth information on this topic.
|
||||
|
||||
### Stability
|
||||
|
||||
By default only stable releases are taken into consideration. If you would like
|
||||
to also get RC, beta, alpha or dev versions of your dependencies you can do
|
||||
so using [stability flags](04-schema.md#package-links). To change that for all
|
||||
packages instead of doing per dependency you can also use the
|
||||
By default only stable releases are taken into consideration. If you would
|
||||
like to also get RC, beta, alpha or dev versions of your dependencies you can
|
||||
do so using [stability flags](04-schema.md#package-links). To change that for
|
||||
all packages instead of doing per dependency you can also use the
|
||||
[minimum-stability](04-schema.md#minimum-stability) setting.
|
||||
|
||||
### Test version constraints
|
||||
|
||||
You can test version constraints using [semver.mwl.be](http://semver.mwl.be). Fill in
|
||||
a package name and it will autofill the default version constraint which Composer would add
|
||||
to your `composer.json` file. You can adjust the version constraint and the tool will highlight
|
||||
all releases that match.
|
||||
|
||||
## Installing Dependencies
|
||||
|
||||
To fetch the defined dependencies into your local project, just run the
|
||||
`install` command of `composer.phar`.
|
||||
To install the defined dependencies for your project, just run the
|
||||
[`install`](03-cli.md#install) command.
|
||||
|
||||
```sh
|
||||
php composer.phar install
|
||||
|
@ -113,14 +76,14 @@ php composer.phar install
|
|||
This will find the latest version of `monolog/monolog` that matches the
|
||||
supplied version constraint and download it into the `vendor` directory.
|
||||
It's a convention to put third party code into a directory named `vendor`.
|
||||
In case of monolog it will put it into `vendor/monolog/monolog`.
|
||||
In case of Monolog it will put it into `vendor/monolog/monolog`.
|
||||
|
||||
> **Tip:** If you are using git for your project, you probably want to add
|
||||
> `vendor` into your `.gitignore`. You really don't want to add all of that
|
||||
> `vendor` in your `.gitignore`. You really don't want to add all of that
|
||||
> code to your repository.
|
||||
|
||||
Another thing that the `install` command does is it adds a `composer.lock`
|
||||
file into your project root.
|
||||
You will notice the [`install`](03-cli.md#install) command also created a
|
||||
`composer.lock` file.
|
||||
|
||||
## `composer.lock` - The Lock File
|
||||
|
||||
|
@ -128,82 +91,82 @@ After installing the dependencies, Composer writes the list of the exact
|
|||
versions it installed into a `composer.lock` file. This locks the project
|
||||
to those specific versions.
|
||||
|
||||
**Commit your application's `composer.lock` (along with `composer.json`) into version control.**
|
||||
**Commit your application's `composer.lock` (along with `composer.json`)
|
||||
into version control.**
|
||||
|
||||
This is important because the `install` command checks if a lock file is present,
|
||||
and if it is, it downloads the versions specified there (regardless of what `composer.json`
|
||||
says).
|
||||
This is important because the [`install`](03-cli.md#install) command checks
|
||||
if a lock file is present, and if it is, it downloads the versions specified
|
||||
there (regardless of what `composer.json` says).
|
||||
|
||||
This means that anyone who sets up the project will download the exact
|
||||
same version of the dependencies. Your CI server, production machines, other
|
||||
developers in your team, everything and everyone runs on the same dependencies, which
|
||||
mitigates the potential for bugs affecting only some parts of the deployments. Even if you
|
||||
develop alone, in six months when reinstalling the project you can feel confident the
|
||||
dependencies installed are still working even if your dependencies released
|
||||
many new versions since then.
|
||||
This means that anyone who sets up the project will download the exact same
|
||||
version of the dependencies. Your CI server, production machines, other
|
||||
developers in your team, everything and everyone runs on the same dependencies,
|
||||
which mitigates the potential for bugs affecting only some parts of the
|
||||
deployments. Even if you develop alone, in six months when reinstalling the
|
||||
project you can feel confident the dependencies installed are still working even
|
||||
if your dependencies released many new versions since then.
|
||||
|
||||
If no `composer.lock` file exists, Composer will read the dependencies and
|
||||
versions from `composer.json` and create the lock file after executing the `update` or the `install`
|
||||
command.
|
||||
versions from `composer.json` and create the lock file after executing the
|
||||
[`update`](03-cli.md#update) or the [`install`](03-cli.md#install) command.
|
||||
|
||||
This means that if any of the dependencies get a new version, you won't get the updates
|
||||
automatically. To update to the new version, use the `update` command. This will fetch
|
||||
the latest matching versions (according to your `composer.json` file) and also update
|
||||
the lock file with the new version.
|
||||
This means that if any of the dependencies get a new version, you won't get the
|
||||
updates automatically. To update to the new version, use the
|
||||
[`update`](03-cli.md#update) command. This will fetch the latest matching
|
||||
versions (according to your `composer.json` file) and also update the lock file
|
||||
with the new version.
|
||||
|
||||
```sh
|
||||
php composer.phar update
|
||||
```
|
||||
> **Note:** Composer will display a Warning when executing an `install` command if
|
||||
`composer.lock` and `composer.json` are not synchronized.
|
||||
|
||||
> **Note:** Composer will display a Warning when executing an `install` command
|
||||
> if `composer.lock` and `composer.json` are not synchronized.
|
||||
|
||||
If you only want to install or update one dependency, you can whitelist them:
|
||||
|
||||
```sh
|
||||
php composer.phar update monolog/monolog [...]
|
||||
```
|
||||
|
||||
> **Note:** For libraries it is not necessarily recommended to commit the lock file,
|
||||
> see also: [Libraries - Lock file](02-libraries.md#lock-file).
|
||||
> **Note:** For libraries it is not necessary to commit the lock
|
||||
> file, see also: [Libraries - Lock file](02-libraries.md#lock-file).
|
||||
|
||||
## Packagist
|
||||
|
||||
[Packagist](https://packagist.org/) is the main Composer repository. A Composer
|
||||
repository is basically a package source: a place where you can get packages
|
||||
from. Packagist aims to be the central repository that everybody uses. This
|
||||
means that you can automatically `require` any package that is available
|
||||
there.
|
||||
means that you can automatically `require` any package that is available there.
|
||||
|
||||
If you go to the [packagist website](https://packagist.org/) (packagist.org),
|
||||
If you go to the [Packagist website](https://packagist.org/) (packagist.org),
|
||||
you can browse and search for packages.
|
||||
|
||||
Any open source project using Composer should publish their packages on
|
||||
packagist. A library doesn't need to be on packagist to be used by Composer,
|
||||
but it makes life quite a bit simpler.
|
||||
Any open source project using Composer is recommended to publish their packages
|
||||
on Packagist. A library doesn't need to be on Packagist to be used by Composer,
|
||||
but it enables discovery and adoption by other developers more quickly.
|
||||
|
||||
## Autoloading
|
||||
|
||||
For libraries that specify autoload information, Composer generates a
|
||||
`vendor/autoload.php` file. You can simply include this file and you
|
||||
will get autoloading for free.
|
||||
`vendor/autoload.php` file. You can simply include this file and you will get
|
||||
autoloading for free.
|
||||
|
||||
```php
|
||||
require 'vendor/autoload.php';
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
```
|
||||
|
||||
This makes it really easy to use third party code. For example: If your
|
||||
project depends on monolog, you can just start using classes from it, and they
|
||||
will be autoloaded.
|
||||
This makes it really easy to use third party code. For example: If your project
|
||||
depends on Monolog, you can just start using classes from it, and they will be
|
||||
autoloaded.
|
||||
|
||||
```php
|
||||
$log = new Monolog\Logger('name');
|
||||
$log->pushHandler(new Monolog\Handler\StreamHandler('app.log', Monolog\Logger::WARNING));
|
||||
|
||||
$log->addWarning('Foo');
|
||||
```
|
||||
|
||||
You can even add your own code to the autoloader by adding an `autoload` field
|
||||
to `composer.json`.
|
||||
You can even add your own code to the autoloader by adding an
|
||||
[`autoload`](04-schema.md#autoload) field to `composer.json`.
|
||||
|
||||
```json
|
||||
{
|
||||
|
@ -220,24 +183,25 @@ You define a mapping from namespaces to directories. The `src` directory would
|
|||
be in your project root, on the same level as `vendor` directory is. An example
|
||||
filename would be `src/Foo.php` containing an `Acme\Foo` class.
|
||||
|
||||
After adding the `autoload` field, you have to re-run `dump-autoload` to re-generate
|
||||
the `vendor/autoload.php` file.
|
||||
After adding the [`autoload`](04-schema.md#autoload) field, you have to re-run
|
||||
[`dump-autoload`](03-cli.md#dump-autoload) to re-generate the
|
||||
`vendor/autoload.php` file.
|
||||
|
||||
Including that file will also return the autoloader instance, so you can store
|
||||
the return value of the include call in a variable and add more namespaces.
|
||||
This can be useful for autoloading classes in a test suite, for example.
|
||||
|
||||
```php
|
||||
$loader = require 'vendor/autoload.php';
|
||||
$loader = require __DIR__ . '/vendor/autoload.php';
|
||||
$loader->add('Acme\\Test\\', __DIR__);
|
||||
```
|
||||
|
||||
In addition to PSR-4 autoloading, classmap is also supported. This allows
|
||||
classes to be autoloaded even if they do not conform to PSR-4. See the
|
||||
[autoload reference](04-schema.md#autoload) for more details.
|
||||
In addition to PSR-4 autoloading, Composer also supports PSR-0, classmap and
|
||||
files autoloading. See the [`autoload`](04-schema.md#autoload) reference for
|
||||
more information.
|
||||
|
||||
> **Note:** Composer provides its own autoloader. If you don't want to use
|
||||
that one, you can just include `vendor/composer/autoload_*.php` files,
|
||||
which return associative arrays allowing you to configure your own autoloader.
|
||||
> **Note:** Composer provides its own autoloader. If you don't want to use that
|
||||
> one, you can just include `vendor/composer/autoload_*.php` files, which return
|
||||
> associative arrays allowing you to configure your own autoloader.
|
||||
|
||||
← [Intro](00-intro.md) | [Libraries](02-libraries.md) →
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
# Libraries
|
||||
|
||||
This chapter will tell you how to make your library installable through Composer.
|
||||
This chapter will tell you how to make your library installable through
|
||||
Composer.
|
||||
|
||||
## Every project is a package
|
||||
|
||||
As soon as you have a `composer.json` in a directory, that directory is a
|
||||
package. When you add a `require` to a project, you are making a package that
|
||||
depends on other packages. The only difference between your project and
|
||||
libraries is that your project is a package without a name.
|
||||
package. When you add a [`require`](04-schema.md#require) to a project, you are
|
||||
making a package that depends on other packages. The only difference between
|
||||
your project and libraries is that your project is a package without a name.
|
||||
|
||||
In order to make that package installable you need to give it a name. You do
|
||||
this by adding a `name` to `composer.json`:
|
||||
this by adding the [`name`](04-schema.md#name) property in `composer.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
|
@ -21,12 +22,12 @@ this by adding a `name` to `composer.json`:
|
|||
}
|
||||
```
|
||||
|
||||
In this case the project name is `acme/hello-world`, where `acme` is the
|
||||
vendor name. Supplying a vendor name is mandatory.
|
||||
In this case the project name is `acme/hello-world`, where `acme` is the vendor
|
||||
name. Supplying a vendor name is mandatory.
|
||||
|
||||
> **Note:** If you don't know what to use as a vendor name, your GitHub
|
||||
username is usually a good bet. While package names are case insensitive, the
|
||||
convention is all lowercase and dashes for word separation.
|
||||
> username is usually a good bet. While package names are case insensitive, the
|
||||
> convention is all lowercase and dashes for word separation.
|
||||
|
||||
## Platform packages
|
||||
|
||||
|
@ -50,15 +51,14 @@ includes PHP itself, PHP extensions and some system libraries.
|
|||
PHP. The following are available: `curl`, `iconv`, `icu`, `libxml`,
|
||||
`openssl`, `pcre`, `uuid`, `xsl`.
|
||||
|
||||
You can use `composer show --platform` to get a list of your locally available
|
||||
platform packages.
|
||||
You can use [`show --platform`](03-cli.md#show) to get a list of your locally
|
||||
available platform packages.
|
||||
|
||||
## Specifying the version
|
||||
|
||||
You need to specify the package's version some way. When you publish your
|
||||
package on Packagist, it is able to infer the version from the VCS (git, svn,
|
||||
hg) information, so in that case you do not have to specify it, and it is
|
||||
recommended not to. See [tags](#tags) and [branches](#branches) to see how
|
||||
When you publish your package on Packagist, it is able to infer the version
|
||||
from the VCS (git, svn, hg) information. This means you don't have to
|
||||
explicitly declare it. Read [tags](#tags) and [branches](#branches) to see how
|
||||
version numbers are extracted from these.
|
||||
|
||||
If you are creating packages by hand and really have to specify it explicitly,
|
||||
|
@ -76,9 +76,9 @@ you can just add a `version` field:
|
|||
### Tags
|
||||
|
||||
For every tag that looks like a version, a package version of that tag will be
|
||||
created. It should match 'X.Y.Z' or 'vX.Y.Z', with an optional suffix
|
||||
of `-patch` (`-p`), `-alpha` (`-a`), `-beta` (`-b`) or `-RC`. The suffixes
|
||||
can also be followed by a number.
|
||||
created. It should match 'X.Y.Z' or 'vX.Y.Z', with an optional suffix of
|
||||
`-patch` (`-p`), `-alpha` (`-a`), `-beta` (`-b`) or `-RC`. The suffix can also
|
||||
be followed by a number.
|
||||
|
||||
Here are a few examples of valid tag names:
|
||||
|
||||
|
@ -89,19 +89,20 @@ Here are a few examples of valid tag names:
|
|||
- v2.0.0-alpha
|
||||
- v2.0.4-p1
|
||||
|
||||
> **Note:** Even if your tag is prefixed with `v`, a [version constraint](01-basic-usage.md#package-versions)
|
||||
> in a `require` statement has to be specified without prefix
|
||||
> (e.g. tag `v1.0.0` will result in version `1.0.0`).
|
||||
> **Note:** Even if your tag is prefixed with `v`, a
|
||||
> [version constraint](01-basic-usage.md#package-versions) in a `require`
|
||||
> statement has to be specified without prefix (e.g. tag `v1.0.0` will result
|
||||
> in version `1.0.0`).
|
||||
|
||||
### Branches
|
||||
|
||||
For every branch, a package development version will be created. If the branch
|
||||
name looks like a version, the version will be `{branchname}-dev`. For example,
|
||||
the branch `2.0` will get the `2.0.x-dev` version (the `.x` is added for technical
|
||||
reasons, to make sure it is recognized as a branch). The `2.0.x` branch would also
|
||||
be valid and be turned into `2.0.x-dev` as well. If the branch does not look
|
||||
like a version, it will be `dev-{branchname}`. `master` results in a
|
||||
`dev-master` version.
|
||||
the branch `2.0` will get the `2.0.x-dev` version (the `.x` is added for
|
||||
technical reasons, to make sure it is recognized as a branch). The `2.0.x`
|
||||
branch would also be valid and be turned into `2.0.x-dev` as well. If the
|
||||
branch does not look like a version, it will be `dev-{branchname}`. `master`
|
||||
results in a `dev-master` version.
|
||||
|
||||
Here are some examples of version branch names:
|
||||
|
||||
|
@ -116,8 +117,8 @@ Here are some examples of version branch names:
|
|||
### Aliases
|
||||
|
||||
It is possible to alias branch names to versions. For example, you could alias
|
||||
`dev-master` to `1.0.x-dev`, which would allow you to require `1.0.x-dev` in all
|
||||
the packages.
|
||||
`dev-master` to `1.0.x-dev`, which would allow you to require `1.0.x-dev` in
|
||||
all the packages.
|
||||
|
||||
See [Aliases](articles/aliases.md) for more information.
|
||||
|
||||
|
@ -133,7 +134,7 @@ the `.gitignore`.
|
|||
|
||||
## Publishing to a VCS
|
||||
|
||||
Once you have a vcs repository (version control system, e.g. git) containing a
|
||||
Once you have a VCS repository (version control system, e.g. git) containing a
|
||||
`composer.json` file, your library is already composer-installable. In this
|
||||
example we will publish the `acme/hello-world` library on GitHub under
|
||||
`github.com/username/hello-world`.
|
||||
|
@ -180,11 +181,11 @@ For more details on how package repositories work and what other types are
|
|||
available, see [Repositories](05-repositories.md).
|
||||
|
||||
That's all. You can now install the dependencies by running Composer's
|
||||
`install` command!
|
||||
[`install`](03-cli.md#install) command!
|
||||
|
||||
**Recap:** Any git/svn/hg repository containing a `composer.json` can be added
|
||||
to your project by specifying the package repository and declaring the
|
||||
dependency in the `require` field.
|
||||
dependency in the [`require`](04-schema.md#require) field.
|
||||
|
||||
## Publishing to packagist
|
||||
|
||||
|
@ -196,15 +197,16 @@ repository for `monolog/monolog`. How did that work? The answer is Packagist.
|
|||
|
||||
[Packagist](https://packagist.org/) is the main package repository for
|
||||
Composer, and it is enabled by default. Anything that is published on
|
||||
Packagist is available automatically through Composer. Since monolog
|
||||
[is on packagist](https://packagist.org/packages/monolog/monolog), we can depend
|
||||
on it without having to specify any additional repositories.
|
||||
Packagist is available automatically through Composer. Since
|
||||
[Monolog is on Packagist](https://packagist.org/packages/monolog/monolog), we
|
||||
can depend on it without having to specify any additional repositories.
|
||||
|
||||
If we wanted to share `hello-world` with the world, we would publish it on
|
||||
Packagist as well. Doing so is really easy.
|
||||
|
||||
You simply hit the big "Submit Package" button and sign up. Then you submit
|
||||
the URL to your VCS repository, at which point Packagist will start crawling
|
||||
it. Once it is done, your package will be available to anyone.
|
||||
You simply visit [Packagist](https://packagist.org) and hit the "Submit". This
|
||||
will prompt you to sign up if you haven't already, and then allows you to
|
||||
submit the URL to your VCS repository, at which point Packagist will start
|
||||
crawling it. Once it is done, your package will be available to anyone!
|
||||
|
||||
← [Basic usage](01-basic-usage.md) | [Command-line interface](03-cli.md) →
|
||||
|
|
|
@ -87,7 +87,7 @@ resolution.
|
|||
installing a package, you can use `--dry-run`. This will simulate the
|
||||
installation and show you what would happen.
|
||||
* **--dev:** Install packages listed in `require-dev` (this is the default behavior).
|
||||
* **--no-dev:** Skip installing packages listed in `require-dev`. The autoloader
|
||||
* **--no-dev:** Skip installing packages listed in `require-dev`. The autoloader
|
||||
generation skips the `autoload-dev` rules.
|
||||
* **--no-autoloader:** Skips autoloader generation.
|
||||
* **--no-scripts:** Skips execution of scripts defined in `composer.json`.
|
||||
|
@ -97,6 +97,8 @@ resolution.
|
|||
* **--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`.
|
||||
|
||||
## update
|
||||
|
||||
|
@ -140,9 +142,11 @@ php composer.phar update vendor/*
|
|||
* **--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`.
|
||||
* **--lock:** Only updates the lock file hash to suppress warning about the
|
||||
lock file being out of date.
|
||||
* **--with-dependencies** Add also all dependencies of whitelisted packages to the whitelist.
|
||||
* **--with-dependencies:** Add also all dependencies of whitelisted packages to the whitelist.
|
||||
* **--prefer-stable:** Prefer stable versions of dependencies.
|
||||
* **--prefer-lowest:** Prefer lowest versions of dependencies. Useful for testing minimal
|
||||
versions of requirements, generally used with `--prefer-stable`.
|
||||
|
@ -177,9 +181,15 @@ php composer.phar require vendor/package:2.* vendor/package2:dev-master
|
|||
* **--no-update:** Disables the automatic update of the dependencies.
|
||||
* **--no-progress:** Removes the progress display that can mess with some
|
||||
terminals or scripts which don't handle backspace characters.
|
||||
* **--update-no-dev** Run the dependency update with the --no-dev option.
|
||||
* **--update-with-dependencies** Also update dependencies of the newly
|
||||
* **--update-no-dev:** Run the dependency update with the `--no-dev` option.
|
||||
* **--update-with-dependencies:** Also update dependencies of the newly
|
||||
required packages.
|
||||
* **--sort-packages:** Keep packages sorted in `composer.json`.
|
||||
* **--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`.
|
||||
|
||||
## remove
|
||||
|
||||
|
@ -201,8 +211,13 @@ uninstalled.
|
|||
* **--no-update:** Disables the automatic update of the dependencies.
|
||||
* **--no-progress:** Removes the progress display that can mess with some
|
||||
terminals or scripts which don't handle backspace characters.
|
||||
* **--update-no-dev** Run the dependency update with the --no-dev option.
|
||||
* **--update-with-dependencies** Also update dependencies of the removed packages.
|
||||
* **--update-no-dev:** Run the dependency update with the --no-dev option.
|
||||
* **--update-with-dependencies:** Also update dependencies of the removed packages.
|
||||
* **--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`.
|
||||
|
||||
## global
|
||||
|
||||
|
@ -294,6 +309,18 @@ in your browser.
|
|||
|
||||
* **--homepage (-H):** Open the homepage instead of the repository URL.
|
||||
|
||||
## suggests
|
||||
|
||||
Lists all packages suggested by currently installed set of packages. You can
|
||||
optionally pass one or multiple package names in the format of `vendor/package`
|
||||
to limit output to suggestions made by those packages only.
|
||||
|
||||
### Options
|
||||
|
||||
* **--no-dev:** Excludes suggestions from `require-dev` packages.
|
||||
* **--verbose (-v):** Increased verbosity adds suggesting package name and
|
||||
reason for suggestion.
|
||||
|
||||
## depends
|
||||
|
||||
The `depends` command tells you which other packages depend on a certain
|
||||
|
@ -327,7 +354,9 @@ php composer.phar validate
|
|||
|
||||
### Options
|
||||
|
||||
* **--no-check-all:** Whether or not Composer does a complete validation.
|
||||
* **--no-check-all:** Do not emit a warning if requirements in `composer.json` use unbound version constraints.
|
||||
* **--no-check-lock:** Do not emit an error if `composer.lock` exists and is not up to date.
|
||||
* **--no-check-publish:** Do not emit an error if `composer.json` is unsuitable for publishing as a package on Packagist but is otherwise valid.
|
||||
|
||||
## status
|
||||
|
||||
|
@ -375,7 +404,7 @@ sudo composer self-update
|
|||
### Options
|
||||
|
||||
* **--rollback (-r):** Rollback to the last version you had installed.
|
||||
* **--clean-backups:** Delete old backups during an update. This makes the
|
||||
* **--clean-backups:** Delete old backups during an update. This makes the
|
||||
current version of Composer the only backup available after the update.
|
||||
|
||||
## config
|
||||
|
@ -490,6 +519,8 @@ performance.
|
|||
* **--optimize (-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`.
|
||||
* **--no-dev:** Disables autoload-dev rules.
|
||||
|
||||
## clear-cache
|
||||
|
@ -568,6 +599,8 @@ For example:
|
|||
COMPOSER=composer-other.json php composer.phar install
|
||||
```
|
||||
|
||||
The generated lock file will use the same name: `composer-other.lock` in this example.
|
||||
|
||||
### COMPOSER_ROOT_VERSION
|
||||
|
||||
By setting this var you can specify the version of the root package, if it can
|
||||
|
|
|
@ -263,6 +263,10 @@ custom repository has priority over packagist. If you want to rename the
|
|||
package, you should do so in the default (often master) branch and not in a
|
||||
feature branch, since the package name is taken from the default branch.
|
||||
|
||||
Also note that the override will not work if you change the `name` property
|
||||
in your forked repository's composer.json file as this needs to match the
|
||||
original for the override to work.
|
||||
|
||||
If other dependencies rely on the package you forked, it is possible to
|
||||
inline-alias it so that it matches a constraint that it otherwise would not.
|
||||
For more information [see the aliases article](articles/aliases.md).
|
||||
|
@ -602,6 +606,42 @@ imported. When an archive with a newer version is added in the artifact folder
|
|||
and you run `update`, that version will be imported as well and Composer will
|
||||
update to the latest version.
|
||||
|
||||
### Path
|
||||
|
||||
In addition to the artifact repository, you can use the path one, which allows
|
||||
you to depend on a relative directory. This can be especially useful when dealing
|
||||
with monolith repositories.
|
||||
|
||||
For instance, if you have the following directory structure in your repository:
|
||||
```
|
||||
- apps
|
||||
\_ my-app
|
||||
\_ composer.json
|
||||
- packages
|
||||
\_ my-package
|
||||
\_ composer.json
|
||||
```
|
||||
|
||||
Then, to add the package `my/package` as a dependency, in your `apps/my-app/composer.json`
|
||||
file, you can use the following configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"repositories": [
|
||||
{
|
||||
"type": "path",
|
||||
"url": "../../packages/my-package"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"my/package": "*@dev"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **Note:** Repository paths can also contain wildcards like ``*`` and ``?``.
|
||||
> For details, see the [PHP glob function](http://php.net/glob).
|
||||
|
||||
## Disabling Packagist
|
||||
|
||||
You can disable the default Packagist repository by adding this to your
|
||||
|
|
|
@ -46,6 +46,11 @@ A list of domain names and username/passwords to authenticate against them. For
|
|||
example using `{"example.org": {"username": "alice", "password": "foo"}` as the
|
||||
value of this option will let Composer authenticate against example.org.
|
||||
|
||||
> **Note:** Authentication-related config options like `http-basic` and
|
||||
> `github-oauth` can also be specified inside a `auth.json` file that goes
|
||||
> besides your `composer.json`. That way you can gitignore it and every
|
||||
> developer can place their own credentials in there.
|
||||
|
||||
## platform
|
||||
|
||||
Lets you fake platform packages (PHP and extensions) so that you can emulate a
|
||||
|
@ -100,7 +105,7 @@ first until the cache fits.
|
|||
|
||||
## prepend-autoloader
|
||||
|
||||
Defaults to `true`. If false, the Composer autoloader will not be prepended to
|
||||
Defaults to `true`. If `false`, the Composer autoloader will not be prepended to
|
||||
existing autoloaders. This is sometimes required to fix interoperability issues
|
||||
with other autoloaders.
|
||||
|
||||
|
@ -111,13 +116,12 @@ autoloader. When null a random one will be generated.
|
|||
|
||||
## optimize-autoloader
|
||||
|
||||
Defaults to `false`. Always optimize when dumping the autoloader.
|
||||
Defaults to `false`. If `true`, always optimize when dumping the autoloader.
|
||||
|
||||
## classmap-authoritative
|
||||
|
||||
Defaults to `false`. If `true`, the Composer autoloader will not scan the
|
||||
filesystem for classes that are not found in the class map. Implies
|
||||
'optimize-autoloader'.
|
||||
Defaults to `false`. If `true`, the Composer autoloader will only load classes
|
||||
from the classmap. Implies `optimize-autoloader`.
|
||||
|
||||
## github-domains
|
||||
|
||||
|
@ -126,7 +130,7 @@ used for GitHub Enterprise setups.
|
|||
|
||||
## github-expose-hostname
|
||||
|
||||
Defaults to `true`. If set to `false`, the OAuth tokens created to access the
|
||||
Defaults to `true`. If `false`, the OAuth tokens created to access the
|
||||
github API will have a date instead of the machine hostname.
|
||||
|
||||
## notify-on-install
|
||||
|
@ -164,9 +168,4 @@ Example:
|
|||
}
|
||||
```
|
||||
|
||||
> **Note:** Authentication-related config options like `http-basic` and
|
||||
> `github-oauth` can also be specified inside a `auth.json` file that goes
|
||||
> besides your `composer.json`. That way you can gitignore it and every
|
||||
> developer can place their own credentials in there.
|
||||
|
||||
← [Repositories](05-repositories.md) | [Community](07-community.md) →
|
||||
|
|
|
@ -73,7 +73,7 @@ constraint if you want really specific versions.
|
|||
```
|
||||
|
||||
Once you've done this, you just run `php bin/satis build <configuration file> <build dir>`.
|
||||
For example `php bin/satis build config.json web/` would read the `config.json`
|
||||
For example `php bin/satis build satis.json web/` would read the `satis.json`
|
||||
file and build a static repository inside the `web/` directory.
|
||||
|
||||
When you ironed out that process, what you would typically do is run this
|
||||
|
|
|
@ -23,34 +23,34 @@ Composer fires the following named events during its execution process:
|
|||
### Command Events
|
||||
|
||||
- **pre-install-cmd**: occurs before the `install` command is executed.
|
||||
- **post-install-cmd**: occurs after the `install` command is executed.
|
||||
- **post-install-cmd**: occurs after the `install` command has been executed.
|
||||
- **pre-update-cmd**: occurs before the `update` command is executed.
|
||||
- **post-update-cmd**: occurs after the `update` command is executed.
|
||||
- **post-update-cmd**: occurs after the `update` command has been executed.
|
||||
- **pre-status-cmd**: occurs before the `status` command is executed.
|
||||
- **post-status-cmd**: occurs after the `status` command is executed.
|
||||
- **post-status-cmd**: occurs after the `status` command has been executed.
|
||||
- **pre-archive-cmd**: occurs before the `archive` command is executed.
|
||||
- **post-archive-cmd**: occurs after the `archive` command is executed.
|
||||
- **post-archive-cmd**: occurs after the `archive` command has been executed.
|
||||
- **pre-autoload-dump**: occurs before the autoloader is dumped, either
|
||||
during `install`/`update`, or via the `dump-autoload` command.
|
||||
- **post-autoload-dump**: occurs after the autoloader is dumped, either
|
||||
- **post-autoload-dump**: occurs after the autoloader has been dumped, either
|
||||
during `install`/`update`, or via the `dump-autoload` command.
|
||||
- **post-root-package-install**: occurs after the root package has been
|
||||
installed, during the `create-project` command.
|
||||
- **post-create-project-cmd**: occurs after the `create-project` command is
|
||||
executed.
|
||||
- **post-create-project-cmd**: occurs after the `create-project` command has
|
||||
been executed.
|
||||
|
||||
### Installer Events
|
||||
|
||||
- **pre-dependencies-solving**: occurs before the dependencies are resolved.
|
||||
- **post-dependencies-solving**: occurs after the dependencies are resolved.
|
||||
- **post-dependencies-solving**: occurs after the dependencies have been resolved.
|
||||
|
||||
### Package Events
|
||||
|
||||
- **pre-package-install**: occurs before a package is installed.
|
||||
- **post-package-install**: occurs after a package is installed.
|
||||
- **post-package-install**: occurs after a package has been installed.
|
||||
- **pre-package-update**: occurs before a package is updated.
|
||||
- **post-package-update**: occurs after a package is updated.
|
||||
- **pre-package-uninstall**: occurs before a package has been uninstalled.
|
||||
- **post-package-update**: occurs after a package has been updated.
|
||||
- **pre-package-uninstall**: occurs before a package is uninstalled.
|
||||
- **post-package-uninstall**: occurs after a package has been uninstalled.
|
||||
|
||||
### Plugin Events
|
||||
|
@ -82,6 +82,10 @@ For any given event:
|
|||
and command-line executable commands.
|
||||
- PHP classes containing defined callbacks must be autoloadable via Composer's
|
||||
autoload functionality.
|
||||
- Callbacks can only autoload classes from psr-0, psr-4 and classmap
|
||||
definitions. If a defined callback relies on functions defined outside of a
|
||||
class, the callback itself is responsible for loading the file containing these
|
||||
functions.
|
||||
|
||||
Script definition example:
|
||||
|
||||
|
@ -96,7 +100,10 @@ Script definition example:
|
|||
"MyVendor\\MyClass::warmCache",
|
||||
"phpunit -c app/"
|
||||
],
|
||||
"post-create-project-cmd" : [
|
||||
"post-autoload-dump": [
|
||||
"MyVendor\\MyClass::postAutoloadDump"
|
||||
],
|
||||
"post-create-project-cmd": [
|
||||
"php -r \"copy('config/local-example.php', 'config/local.php');\""
|
||||
]
|
||||
}
|
||||
|
@ -122,6 +129,14 @@ class MyClass
|
|||
// do stuff
|
||||
}
|
||||
|
||||
public static function postAutoloadDump(Event $event)
|
||||
{
|
||||
$vendorDir = $event->getComposer()->getConfig()->get('vendor-dir');
|
||||
require $vendorDir . '/autoload.php';
|
||||
|
||||
some_function_from_an_autoloaded_file();
|
||||
}
|
||||
|
||||
public static function postPackageInstall(PackageEvent $event)
|
||||
{
|
||||
$installedPackage = $event->getOperation()->getPackage();
|
||||
|
|
|
@ -43,6 +43,10 @@ This is a list of common pitfalls on using Composer, and how to avoid them.
|
|||
5. If you are updating to a recently published version of a package, be aware that
|
||||
Packagist has a delay of up to 1 minute before new packages are visible to Composer.
|
||||
|
||||
6. If you are updating a single package, it may depend on newer versions itself.
|
||||
In this case add the `--with-dependencies` argument **or** add all dependencies which
|
||||
need an update to the command.
|
||||
|
||||
## Package not found on travis-ci.org
|
||||
|
||||
1. Check the ["Package not found"](#package-not-found) item above.
|
||||
|
@ -61,13 +65,13 @@ This is a list of common pitfalls on using Composer, and how to avoid them.
|
|||
## Package not found in a Jenkins-build
|
||||
|
||||
1. Check the ["Package not found"](#package-not-found) item above.
|
||||
2. Reason for failing is similar to the problem which can occur on travis-ci.org: The
|
||||
git-clone / checkout within Jenkins leaves the branch in a "detached HEAD"-state. As
|
||||
a result, Composer is not able to identify the version of the current checked out branch
|
||||
and may not be able to resolve a cyclic dependency. To solve this problem, you can use
|
||||
the "Additional Behaviours" -> "Check out to specific local branch" in your Git-settings
|
||||
for your Jenkins-job, where your "local branch" shall be the same branch as you are
|
||||
checking out. Using this, the checkout will not be in detached state any more and cyclic
|
||||
2. Reason for failing is similar to the problem which can occur on travis-ci.org: The
|
||||
git-clone / checkout within Jenkins leaves the branch in a "detached HEAD"-state. As
|
||||
a result, Composer is not able to identify the version of the current checked out branch
|
||||
and may not be able to resolve a cyclic dependency. To solve this problem, you can use
|
||||
the "Additional Behaviours" -> "Check out to specific local branch" in your Git-settings
|
||||
for your Jenkins-job, where your "local branch" shall be the same branch as you are
|
||||
checking out. Using this, the checkout will not be in detached state any more and cyclic
|
||||
dependency is recognized correctly.
|
||||
|
||||
## Need to override a package version
|
||||
|
@ -168,3 +172,28 @@ To enable the swap you can use for example:
|
|||
/sbin/mkswap /var/swap.1
|
||||
/sbin/swapon /var/swap.1
|
||||
```
|
||||
|
||||
## Degraded Mode
|
||||
|
||||
Due to some intermittent issues on Travis and other systems, we introduced a
|
||||
degraded network mode which helps Composer finish successfully but disables
|
||||
a few optimizations. This is enabled automatically when an issue is first
|
||||
detected. If you see this issue sporadically you probably don't have to worry
|
||||
(a slow or overloaded network can also cause those time outs), but if it
|
||||
appears repeatedly you might want to look at the options below to identify
|
||||
and resolve it.
|
||||
|
||||
If you have been pointed to this page, you want to check a few things:
|
||||
|
||||
- If you are using ESET antivirus, go in "Advanced Settings" and disable "HTTP-scanner"
|
||||
under "web access protection"
|
||||
- If you are using IPv6, try disabling it. If that solves your issues, get in touch
|
||||
with your ISP or server host, the problem is not at the Packagist level but in the
|
||||
routing rules between you and Packagist (i.e. the internet at large). The best way to get
|
||||
these fixed is raise awareness to the network engineers that have the power to fix it.
|
||||
|
||||
To disable IPv6 on Linux, try using this command which appends a
|
||||
rule preferring IPv4 over IPv6 to your config:
|
||||
|
||||
`sudo sh -c "echo 'precedence ::ffff:0:0/96 100' >> /etc/gai.conf"`
|
||||
- If none of the above helped, please report the error.
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
<!--
|
||||
tagline: Version constraints explained.
|
||||
-->
|
||||
|
||||
# Versions
|
||||
|
||||
## Basic Constraints
|
||||
|
||||
### Exact
|
||||
|
||||
You can specify the exact version of a package. This will tell Composer to
|
||||
install this version and this version only. If other dependencies require
|
||||
a different version, the solver will ultimately fail and abort any install
|
||||
or update procedures.
|
||||
|
||||
Example: `1.0.2`
|
||||
|
||||
### Range
|
||||
|
||||
By using comparison operators you can specify ranges of valid versions. Valid
|
||||
operators are `>`, `>=`, `<`, `<=`, `!=`.
|
||||
|
||||
You can define multiple ranges. Ranges separated by a space (<code> </code>)
|
||||
or comma (`,`) will be treated as a **logical AND**. A double pipe (`||`)
|
||||
will be treated as a **logical OR**. AND has higher precedence than OR.
|
||||
|
||||
> **Note:** Be careful when using unbounded ranges as you might end up
|
||||
> unexpectedly installing versions that break backwards compatibility.
|
||||
> Consider using the [caret](#caret) operator instead for safety.
|
||||
|
||||
Examples:
|
||||
|
||||
* `>=1.0`
|
||||
* `>=1.0 <2.0`
|
||||
* `>=1.0 <1.1 || >=1.2`
|
||||
|
||||
### Range (Hyphen)
|
||||
|
||||
Inclusive set of versions. Partial versions on the right include are completed
|
||||
with a wildcard. For example `1.0 - 2.0` is equivalent to `>=1.0.0 <2.1` as the
|
||||
`2.0` becomes `2.0.*`. On the other hand `1.0.0 - 2.1.0` is equivalent to
|
||||
`>=1.0.0 <=2.1.0`.
|
||||
|
||||
Example: `1.0 - 2.0`
|
||||
|
||||
### Wildcard
|
||||
|
||||
You can specify a pattern with a `*` wildcard. `1.0.*` is the equivalent of
|
||||
`>=1.0 <1.1`.
|
||||
|
||||
Example: `1.0.*`
|
||||
|
||||
## Next Significant Release Operators
|
||||
|
||||
### Tilde
|
||||
|
||||
The `~` operator is best explained by example: `~1.2` is equivalent to
|
||||
`>=1.2 <2.0.0`, while `~1.2.3` is equivalent to `>=1.2.3 <1.3.0`. As you can see
|
||||
it is mostly useful for projects respecting [semantic
|
||||
versioning](http://semver.org/). A common usage would be to mark the minimum
|
||||
minor version you depend on, like `~1.2` (which allows anything up to, but not
|
||||
including, 2.0). Since in theory there should be no backwards compatibility
|
||||
breaks until 2.0, that works well. Another way of looking at it is that using
|
||||
`~` specifies a minimum version, but allows the last digit specified to go up.
|
||||
|
||||
Example: `~1.2`
|
||||
|
||||
> **Note:** Though `2.0-beta.1` is strictly before `2.0`, a version constraint
|
||||
> like `~1.2` would not install it. As said above `~1.2` only means the `.2`
|
||||
> can change but the `1.` part is fixed.
|
||||
|
||||
> **Note:** The `~` operator has an exception on its behavior for the major
|
||||
> release number. This means for example that `~1` is the same as `~1.0` as
|
||||
> it will not allow the major number to increase trying to keep backwards
|
||||
> compatibility.
|
||||
|
||||
### Caret
|
||||
|
||||
The `^` operator behaves very similarly but it sticks closer to semantic
|
||||
versioning, and will always allow non-breaking updates. For example `^1.2.3`
|
||||
is equivalent to `>=1.2.3 <2.0.0` as none of the releases until 2.0 should
|
||||
break backwards compatibility. For pre-1.0 versions it also acts with safety
|
||||
in mind and treats `^0.3` as `>=0.3.0 <0.4.0`.
|
||||
|
||||
This is the recommended operator for maximum interoperability when writing
|
||||
library code.
|
||||
|
||||
Example: `^1.2.3`
|
||||
|
||||
## Stability
|
||||
|
||||
If you are using a constraint that does not explicitly define a stability,
|
||||
Composer will default internally to `-dev` or `-stable`, depending on the
|
||||
operator(s) used. This happens transparently.
|
||||
|
||||
If you wish to explicitly consider only the stable release in the comparison,
|
||||
add the suffix `-stable`.
|
||||
|
||||
Examples:
|
||||
|
||||
Constraint | Internally
|
||||
------------------- | ------------------------
|
||||
`1.2.3` | `=1.2.3.0-stable`
|
||||
`>1.2` | `>1.2.0.0-stable`
|
||||
`>=1.2` | `>=1.2.0.0-dev`
|
||||
`>=1.2-stable` | `>=1.2.0.0-stable`
|
||||
`<1.3` | `<1.3.0.0-dev`
|
||||
`<=1.3` | `<=1.3.0.0-stable`
|
||||
`1 - 2` | `>=1.0.0.0-dev <3.0.0.0-dev`
|
||||
`~1.3` | `>=1.3.0.0-dev <2.0.0.0-dev`
|
||||
`1.4.*` | `>=1.4.0.0-dev <1.5.0.0-dev`
|
||||
|
||||
## Test version constraints
|
||||
|
||||
You can test version constraints using [semver.mwl.be](http://semver.mwl.be).
|
||||
Fill in a package name and it will autofill the default version constraint
|
||||
which Composer would add to your `composer.json` file. You can adjust the
|
||||
version constraint and the tool will highlight all releases that match.
|
File diff suppressed because it is too large
Load Diff
|
@ -38,8 +38,16 @@ class AutoloadGenerator
|
|||
*/
|
||||
private $io;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $devMode = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
public function __construct(EventDispatcher $eventDispatcher, IOInterface $io = null)
|
||||
{
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
|
@ -51,8 +59,23 @@ class AutoloadGenerator
|
|||
$this->devMode = (boolean) $devMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not generated autoloader considers the class map
|
||||
* authoritative.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = (boolean) $classMapAuthoritative;
|
||||
}
|
||||
|
||||
public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '')
|
||||
{
|
||||
if ($this->classMapAuthoritative) {
|
||||
// Force scanPsr0Packages when classmap is authoritative
|
||||
$scanPsr0Packages = true;
|
||||
}
|
||||
$this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, array(), array(
|
||||
'optimize' => (bool) $scanPsr0Packages,
|
||||
));
|
||||
|
@ -63,7 +86,6 @@ class AutoloadGenerator
|
|||
$vendorPath = $filesystem->normalizePath(realpath($config->get('vendor-dir')));
|
||||
$useGlobalIncludePath = (bool) $config->get('use-include-path');
|
||||
$prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true';
|
||||
$classMapAuthoritative = $config->get('classmap-authoritative');
|
||||
$targetDir = $vendorPath.'/'.$targetDir;
|
||||
$filesystem->ensureDirectoryExists($targetDir);
|
||||
|
||||
|
@ -174,10 +196,21 @@ EOF;
|
|||
// flatten array
|
||||
$classMap = array();
|
||||
if ($scanPsr0Packages) {
|
||||
$namespacesToScan = array();
|
||||
|
||||
// Scan the PSR-0/4 directories for class files, and add them to the class map
|
||||
foreach (array('psr-0', 'psr-4') as $psrType) {
|
||||
foreach ($autoloads[$psrType] as $namespace => $paths) {
|
||||
foreach ($paths as $dir) {
|
||||
$namespacesToScan[$namespace][] = array('paths' => $paths, 'type' => $psrType);
|
||||
}
|
||||
}
|
||||
|
||||
krsort($namespacesToScan);
|
||||
|
||||
foreach ($namespacesToScan as $namespace => $groups) {
|
||||
foreach ($groups as $group) {
|
||||
$psrType = $group['type'];
|
||||
foreach ($group['paths'] as $dir) {
|
||||
$dir = $filesystem->normalizePath($filesystem->isAbsolutePath($dir) ? $dir : $basePath.'/'.$dir);
|
||||
if (!is_dir($dir)) {
|
||||
continue;
|
||||
|
@ -190,9 +223,14 @@ EOF;
|
|||
|
||||
$namespaceFilter = $namespace === '' ? null : $namespace;
|
||||
foreach (ClassMapGenerator::createMap($dir, $whitelist, $this->io, $namespaceFilter) as $class => $path) {
|
||||
$pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n";
|
||||
if (!isset($classMap[$class])) {
|
||||
$path = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
|
||||
$classMap[$class] = $path.",\n";
|
||||
$classMap[$class] = $pathCode;
|
||||
} elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) {
|
||||
$this->io->writeError(
|
||||
'<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
|
||||
' was found in both "'.str_replace(array('$vendorDir . \'', "',\n"), array($vendorPath, ''), $classMap[$class]).'" and "'.$path.'", the first will be used.</warning>'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -202,8 +240,15 @@ EOF;
|
|||
|
||||
foreach ($autoloads['classmap'] as $dir) {
|
||||
foreach (ClassMapGenerator::createMap($dir, null, $this->io) as $class => $path) {
|
||||
$path = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
|
||||
$classMap[$class] = $path.",\n";
|
||||
$pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n";
|
||||
if (!isset($classMap[$class])) {
|
||||
$classMap[$class] = $pathCode;
|
||||
} elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) {
|
||||
$this->io->writeError(
|
||||
'<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
|
||||
' was found in both "'.str_replace(array('$vendorDir . \'', "',\n"), array($vendorPath, ''), $classMap[$class]).'" and "'.$path.'", the first will be used.</warning>'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,23 +274,23 @@ EOF;
|
|||
file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile);
|
||||
file_put_contents($targetDir.'/autoload_psr4.php', $psr4File);
|
||||
file_put_contents($targetDir.'/autoload_classmap.php', $classmapFile);
|
||||
if ($includePathFile = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
|
||||
file_put_contents($targetDir.'/include_paths.php', $includePathFile);
|
||||
$includePathFilePath = $targetDir.'/include_paths.php';
|
||||
if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
|
||||
file_put_contents($includePathFilePath, $includePathFileContents);
|
||||
} elseif (file_exists($includePathFilePath)) {
|
||||
unlink($includePathFilePath);
|
||||
}
|
||||
if ($includeFilesFile = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
|
||||
file_put_contents($targetDir.'/autoload_files.php', $includeFilesFile);
|
||||
$includeFilesFilePath = $targetDir.'/autoload_files.php';
|
||||
if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
|
||||
file_put_contents($includeFilesFilePath, $includeFilesFileContents);
|
||||
} elseif (file_exists($includeFilesFilePath)) {
|
||||
unlink($includeFilesFilePath);
|
||||
}
|
||||
file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
|
||||
file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFile, $targetDirLoader, (bool) $includeFilesFile, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $classMapAuthoritative));
|
||||
file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader));
|
||||
|
||||
// use stream_copy_to_stream instead of copy
|
||||
// to work around https://bugs.php.net/bug.php?id=64634
|
||||
$sourceLoader = fopen(__DIR__.'/ClassLoader.php', 'r');
|
||||
$targetLoader = fopen($targetDir.'/ClassLoader.php', 'w+');
|
||||
stream_copy_to_stream($sourceLoader, $targetLoader);
|
||||
fclose($sourceLoader);
|
||||
fclose($targetLoader);
|
||||
unset($sourceLoader, $targetLoader);
|
||||
$this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php');
|
||||
$this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE');
|
||||
|
||||
$this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, array(), array(
|
||||
'optimize' => (bool) $scanPsr0Packages,
|
||||
|
@ -310,7 +355,7 @@ EOF;
|
|||
|
||||
$psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $mainPackage);
|
||||
$psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage);
|
||||
$classmap = $this->parseAutoloadsType($sortedPackageMap, 'classmap', $mainPackage);
|
||||
$classmap = $this->parseAutoloadsType(array_reverse($sortedPackageMap), 'classmap', $mainPackage);
|
||||
$files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage);
|
||||
|
||||
krsort($psr0);
|
||||
|
@ -453,7 +498,7 @@ return ComposerAutoloaderInit$suffix::getLoader();
|
|||
AUTOLOAD;
|
||||
}
|
||||
|
||||
protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $classMapAuthoritative)
|
||||
protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader)
|
||||
{
|
||||
// TODO the class ComposerAutoloaderInit should be revert to a closure
|
||||
// when APC has been fixed:
|
||||
|
@ -530,7 +575,7 @@ PSR4;
|
|||
CLASSMAP;
|
||||
}
|
||||
|
||||
if ($classMapAuthoritative) {
|
||||
if ($this->classMapAuthoritative) {
|
||||
$file .= <<<'CLASSMAPAUTHORITATIVE'
|
||||
$loader->setClassMapAuthoritative(true);
|
||||
|
||||
|
@ -727,4 +772,20 @@ FOOTER;
|
|||
|
||||
return $sortedPackageMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy file using stream_copy_to_stream to work around https://bugs.php.net/bug.php?id=6463
|
||||
*
|
||||
* @param string $source
|
||||
* @param string $target
|
||||
*/
|
||||
protected function safeCopy($source, $target)
|
||||
{
|
||||
$source = fopen($source, 'r');
|
||||
$target = fopen($target, 'w+');
|
||||
|
||||
stream_copy_to_stream($source, $target);
|
||||
fclose($source);
|
||||
fclose($target);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -351,7 +351,7 @@ class ClassLoader
|
|||
foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
|
||||
if (is_file($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
@ -361,7 +361,7 @@ class ClassLoader
|
|||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
@ -380,7 +380,7 @@ class ClassLoader
|
|||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
@ -390,7 +390,7 @@ class ClassLoader
|
|||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,9 +49,8 @@ class ClassMapGenerator
|
|||
* @param IOInterface $io IO object
|
||||
* @param string $namespace Optional namespace prefix to filter by
|
||||
*
|
||||
* @return array A class map array
|
||||
*
|
||||
* @throws \RuntimeException When the path is neither an existing file nor directory
|
||||
* @return array A class map array
|
||||
*/
|
||||
public static function createMap($path, $whitelist = null, IOInterface $io = null, $namespace = null)
|
||||
{
|
||||
|
@ -91,7 +90,7 @@ class ClassMapGenerator
|
|||
|
||||
if (!isset($map[$class])) {
|
||||
$map[$class] = $filePath;
|
||||
} elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) {
|
||||
} elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) {
|
||||
$io->writeError(
|
||||
'<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
|
||||
' was found in both "'.$map[$class].'" and "'.$filePath.'", the first will be used.</warning>'
|
||||
|
|
|
@ -43,10 +43,12 @@ class Cache
|
|||
$this->whitelist = $whitelist;
|
||||
$this->filesystem = $filesystem ?: new Filesystem();
|
||||
|
||||
if (!is_dir($this->root)) {
|
||||
if (!@mkdir($this->root, 0777, true)) {
|
||||
$this->enabled = false;
|
||||
}
|
||||
if (
|
||||
(!is_dir($this->root) && !@mkdir($this->root, 0777, true))
|
||||
|| !is_writable($this->root)
|
||||
) {
|
||||
$this->io->writeError('<warning>Cannot create cache directory ' . $this->root . ', or directory is not writable. Proceeding without cache</warning>');
|
||||
$this->enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,6 +88,9 @@ class Cache
|
|||
try {
|
||||
return file_put_contents($this->root . $file, $contents);
|
||||
} catch (\ErrorException $e) {
|
||||
if ($this->io->isDebug()) {
|
||||
$this->io->writeError('<warning>Failed to write into cache: '.$e->getMessage().'</warning>');
|
||||
}
|
||||
if (preg_match('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) {
|
||||
// Remove partial file.
|
||||
unlink($this->root . $file);
|
||||
|
|
|
@ -19,7 +19,7 @@ use Composer\Repository\CompositeRepository;
|
|||
use Composer\Script\ScriptEvents;
|
||||
use Composer\Plugin\CommandEvent;
|
||||
use Composer\Plugin\PluginEvents;
|
||||
|
||||
use Composer\Util\Filesystem;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
@ -105,7 +105,12 @@ EOT
|
|||
}
|
||||
|
||||
$io->writeError('<info>Creating the archive into "'.$dest.'".</info>');
|
||||
$archiveManager->archive($package, $format, $dest);
|
||||
$packagePath = $archiveManager->archive($package, $format, $dest);
|
||||
$fs = new Filesystem;
|
||||
$shortPath = $fs->findShortestPath(getcwd(), $packagePath, true);
|
||||
|
||||
$io->writeError('Created: ', false);
|
||||
$io->write(strlen($shortPath) < strlen($packagePath) ? $shortPath : $packagePath);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ class ConfigCommand extends Command
|
|||
new InputOption('auth', 'a', InputOption::VALUE_NONE, 'Affect auth config file (only used for --editor)'),
|
||||
new InputOption('unset', null, InputOption::VALUE_NONE, 'Unset the given setting-key'),
|
||||
new InputOption('list', 'l', InputOption::VALUE_NONE, 'List configuration settings'),
|
||||
new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json', 'composer.json'),
|
||||
new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json'),
|
||||
new InputOption('absolute', null, InputOption::VALUE_NONE, 'Returns absolute paths when fetching *-dir config values instead of relative'),
|
||||
new InputArgument('setting-key', null, 'Setting key'),
|
||||
new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value'),
|
||||
|
@ -129,7 +129,7 @@ EOT
|
|||
{
|
||||
parent::initialize($input, $output);
|
||||
|
||||
if ($input->getOption('global') && 'composer.json' !== $input->getOption('file')) {
|
||||
if ($input->getOption('global') && null !== $input->getOption('file')) {
|
||||
throw new \RuntimeException('--file and --global can not be combined');
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ EOT
|
|||
// passed in a file to use
|
||||
$configFile = $input->getOption('global')
|
||||
? ($this->config->get('home') . '/config.json')
|
||||
: $input->getOption('file');
|
||||
: ($input->getOption('file') ?: trim(getenv('COMPOSER')) ?: 'composer.json');
|
||||
|
||||
// create global composer.json if this was invoked using `composer global config`
|
||||
if ($configFile === 'composer.json' && !file_exists($configFile) && realpath(getcwd()) === realpath($this->config->get('home'))) {
|
||||
|
@ -151,7 +151,7 @@ EOT
|
|||
|
||||
$authConfigFile = $input->getOption('global')
|
||||
? ($this->config->get('home') . '/auth.json')
|
||||
: dirname(realpath($input->getOption('file'))) . '/auth.json';
|
||||
: dirname(realpath($configFile)) . '/auth.json';
|
||||
|
||||
$this->authConfigFile = new JsonFile($authConfigFile);
|
||||
$this->authConfigSource = new JsonConfigSource($this->authConfigFile, true);
|
||||
|
@ -238,17 +238,19 @@ EOT
|
|||
} elseif (strpos($settingKey, '.')) {
|
||||
$bits = explode('.', $settingKey);
|
||||
$data = $data['config'];
|
||||
$match = false;
|
||||
foreach ($bits as $bit) {
|
||||
if (isset($data[$bit])) {
|
||||
$data = $data[$bit];
|
||||
} elseif (isset($data[implode('.', $bits)])) {
|
||||
// last bit can contain domain names and such so try to join whatever is left if it exists
|
||||
$data = $data[implode('.', $bits)];
|
||||
break;
|
||||
} else {
|
||||
throw new \RuntimeException($settingKey.' is not defined');
|
||||
$key = isset($key) ? $key.'.'.$bit : $bit;
|
||||
$match = false;
|
||||
if (isset($data[$key])) {
|
||||
$match = true;
|
||||
$data = $data[$key];
|
||||
unset($key);
|
||||
}
|
||||
array_shift($bits);
|
||||
}
|
||||
|
||||
if (!$match) {
|
||||
throw new \RuntimeException($settingKey.' is not defined.');
|
||||
}
|
||||
|
||||
$value = $data;
|
||||
|
@ -278,7 +280,7 @@ EOT
|
|||
'use-include-path' => array($booleanValidator, $booleanNormalizer),
|
||||
'preferred-install' => array(
|
||||
function ($val) { return in_array($val, array('auto', 'source', 'dist'), true); },
|
||||
function ($val) { return $val; }
|
||||
function ($val) { return $val; },
|
||||
),
|
||||
'store-auths' => array(
|
||||
function ($val) { return in_array($val, array('true', 'false', 'prompt'), true); },
|
||||
|
@ -288,7 +290,7 @@ EOT
|
|||
}
|
||||
|
||||
return $val !== 'false' && (bool) $val;
|
||||
}
|
||||
},
|
||||
),
|
||||
'notify-on-install' => array($booleanValidator, $booleanNormalizer),
|
||||
'vendor-dir' => array('is_string', function ($val) { return $val; }),
|
||||
|
@ -301,7 +303,7 @@ EOT
|
|||
'cache-files-ttl' => array('is_numeric', 'intval'),
|
||||
'cache-files-maxsize' => array(
|
||||
function ($val) { return preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val) > 0; },
|
||||
function ($val) { return $val; }
|
||||
function ($val) { return $val; },
|
||||
),
|
||||
'discard-changes' => array(
|
||||
function ($val) { return in_array($val, array('stash', 'true', 'false', '1', '0'), true); },
|
||||
|
@ -311,7 +313,7 @@ EOT
|
|||
}
|
||||
|
||||
return $val !== 'false' && (bool) $val;
|
||||
}
|
||||
},
|
||||
),
|
||||
'autoloader-suffix' => array('is_string', function ($val) { return $val === 'null' ? null : $val; }),
|
||||
'optimize-autoloader' => array($booleanValidator, $booleanNormalizer),
|
||||
|
@ -336,7 +338,7 @@ EOT
|
|||
},
|
||||
function ($vals) {
|
||||
return $vals;
|
||||
}
|
||||
},
|
||||
),
|
||||
'github-domains' => array(
|
||||
function ($vals) {
|
||||
|
@ -348,7 +350,7 @@ EOT
|
|||
},
|
||||
function ($vals) {
|
||||
return $vals;
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -464,6 +466,7 @@ EOT
|
|||
protected function listConfiguration(array $contents, array $rawContents, OutputInterface $output, $k = null)
|
||||
{
|
||||
$origK = $k;
|
||||
$io = $this->getIO();
|
||||
foreach ($contents as $key => $value) {
|
||||
if ($k === null && !in_array($key, array('config', 'repositories'))) {
|
||||
continue;
|
||||
|
@ -474,13 +477,7 @@ EOT
|
|||
if (is_array($value) && (!is_numeric(key($value)) || ($key === 'repositories' && null === $k))) {
|
||||
$k .= preg_replace('{^config\.}', '', $key . '.');
|
||||
$this->listConfiguration($value, $rawVal, $output, $k);
|
||||
|
||||
if (substr_count($k, '.') > 1) {
|
||||
$k = str_split($k, strrpos($k, '.', -2));
|
||||
$k = $k[0] . '.';
|
||||
} else {
|
||||
$k = $origK;
|
||||
}
|
||||
$k = $origK;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
@ -498,9 +495,9 @@ EOT
|
|||
}
|
||||
|
||||
if (is_string($rawVal) && $rawVal != $value) {
|
||||
$this->getIO()->write('[<comment>' . $k . $key . '</comment>] <info>' . $rawVal . ' (' . $value . ')</info>');
|
||||
$io->write('[<comment>' . $k . $key . '</comment>] <info>' . $rawVal . ' (' . $value . ')</info>');
|
||||
} else {
|
||||
$this->getIO()->write('[<comment>' . $k . $key . '</comment>] <info>' . $value . '</info>');
|
||||
$io->write('[<comment>' . $k . $key . '</comment>] <info>' . $value . '</info>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,16 +100,17 @@ EOT
|
|||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$config = Factory::createConfig();
|
||||
$io = $this->getIO();
|
||||
|
||||
$this->updatePreferredOptions($config, $input, $preferSource, $preferDist, true);
|
||||
|
||||
if ($input->getOption('no-custom-installers')) {
|
||||
$this->getIO()->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
|
||||
$io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
|
||||
$input->setOption('no-plugins', true);
|
||||
}
|
||||
|
||||
return $this->installProject(
|
||||
$this->getIO(),
|
||||
$io,
|
||||
$config,
|
||||
$input->getArgument('package'),
|
||||
$input->getArgument('directory'),
|
||||
|
@ -290,15 +291,15 @@ EOT
|
|||
|
||||
// handler Ctrl+C for unix-like systems
|
||||
if (function_exists('pcntl_signal')) {
|
||||
declare(ticks = 100);
|
||||
pcntl_signal(SIGINT, function() use ($directory) {
|
||||
declare (ticks = 100);
|
||||
pcntl_signal(SIGINT, function () use ($directory) {
|
||||
$fs = new Filesystem();
|
||||
$fs->removeDirectory($directory);
|
||||
exit(130);
|
||||
});
|
||||
}
|
||||
|
||||
$io->writeError('<info>Installing ' . $package->getName() . ' (' . VersionParser::formatVersion($package, false) . ')</info>');
|
||||
$io->writeError('<info>Installing ' . $package->getName() . ' (' . $package->getFullPrettyVersion(false) . ')</info>');
|
||||
|
||||
if ($disablePlugins) {
|
||||
$io->writeError('<info>Plugins have been disabled.</info>');
|
||||
|
@ -346,8 +347,8 @@ EOT
|
|||
* Updated preferSource or preferDist based on the preferredInstall config option
|
||||
* @param Config $config
|
||||
* @param InputInterface $input
|
||||
* @param boolean $preferSource
|
||||
* @param boolean $preferDist
|
||||
* @param bool $preferSource
|
||||
* @param bool $preferDist
|
||||
*/
|
||||
protected function updatePreferredOptions(Config $config, InputInterface $input, &$preferSource, &$preferDist, $keepVcsRequiresPreferSource = false)
|
||||
{
|
||||
|
|
|
@ -81,6 +81,7 @@ EOT
|
|||
|
||||
$messages = array();
|
||||
$outputPackages = array();
|
||||
$io = $this->getIO();
|
||||
foreach ($repo->getPackages() as $package) {
|
||||
foreach ($types as $type) {
|
||||
foreach ($package->{'get'.$linkTypes[$type][0]}() as $link) {
|
||||
|
@ -96,9 +97,9 @@ EOT
|
|||
|
||||
if ($messages) {
|
||||
sort($messages);
|
||||
$this->getIO()->write($messages);
|
||||
$io->write($messages);
|
||||
} else {
|
||||
$this->getIO()->writeError('<info>There is no installed package depending on "'.$needle.'".</info>');
|
||||
$io->writeError('<info>There is no installed package depending on "'.$needle.'".</info>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,12 +57,13 @@ EOT
|
|||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$composer = $this->getComposer(false);
|
||||
$io = $this->getIO();
|
||||
|
||||
if ($composer) {
|
||||
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output);
|
||||
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
|
||||
|
||||
$this->getIO()->write('Checking composer.json: ', false);
|
||||
$io->write('Checking composer.json: ', false);
|
||||
$this->outputResult($this->checkComposerSchema());
|
||||
}
|
||||
|
||||
|
@ -72,44 +73,44 @@ EOT
|
|||
$config = Factory::createConfig();
|
||||
}
|
||||
|
||||
$this->rfs = new RemoteFilesystem($this->getIO(), $config);
|
||||
$this->process = new ProcessExecutor($this->getIO());
|
||||
$this->rfs = new RemoteFilesystem($io, $config);
|
||||
$this->process = new ProcessExecutor($io);
|
||||
|
||||
$this->getIO()->write('Checking platform settings: ', false);
|
||||
$io->write('Checking platform settings: ', false);
|
||||
$this->outputResult($this->checkPlatform());
|
||||
|
||||
$this->getIO()->write('Checking git settings: ', false);
|
||||
$io->write('Checking git settings: ', false);
|
||||
$this->outputResult($this->checkGit());
|
||||
|
||||
$this->getIO()->write('Checking http connectivity to packagist: ', false);
|
||||
$io->write('Checking http connectivity to packagist: ', false);
|
||||
$this->outputResult($this->checkHttp('http'));
|
||||
|
||||
$this->getIO()->write('Checking https connectivity to packagist: ', false);
|
||||
$io->write('Checking https connectivity to packagist: ', false);
|
||||
$this->outputResult($this->checkHttp('https'));
|
||||
|
||||
$opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org'));
|
||||
if (!empty($opts['http']['proxy'])) {
|
||||
$this->getIO()->write('Checking HTTP proxy: ', false);
|
||||
$io->write('Checking HTTP proxy: ', false);
|
||||
$this->outputResult($this->checkHttpProxy());
|
||||
$this->getIO()->write('Checking HTTP proxy support for request_fulluri: ', false);
|
||||
$io->write('Checking HTTP proxy support for request_fulluri: ', false);
|
||||
$this->outputResult($this->checkHttpProxyFullUriRequestParam());
|
||||
$this->getIO()->write('Checking HTTPS proxy support for request_fulluri: ', false);
|
||||
$io->write('Checking HTTPS proxy support for request_fulluri: ', false);
|
||||
$this->outputResult($this->checkHttpsProxyFullUriRequestParam());
|
||||
}
|
||||
|
||||
if ($oauth = $config->get('github-oauth')) {
|
||||
foreach ($oauth as $domain => $token) {
|
||||
$this->getIO()->write('Checking '.$domain.' oauth access: ', false);
|
||||
$io->write('Checking '.$domain.' oauth access: ', false);
|
||||
$this->outputResult($this->checkGithubOauth($domain, $token));
|
||||
}
|
||||
} else {
|
||||
$this->getIO()->write('Checking github.com rate limit: ', false);
|
||||
$io->write('Checking github.com rate limit: ', false);
|
||||
try {
|
||||
$rate = $this->getGithubRateLimit('github.com');
|
||||
$this->outputResult(true);
|
||||
if (10 > $rate['remaining']) {
|
||||
$this->getIO()->write('<warning>WARNING</warning>');
|
||||
$this->getIO()->write(sprintf(
|
||||
$io->write('<warning>WARNING</warning>');
|
||||
$io->write(sprintf(
|
||||
'<comment>Github has a rate limit on their API. '
|
||||
. 'You currently have <options=bold>%u</options=bold> '
|
||||
. 'out of <options=bold>%u</options=bold> requests left.' . PHP_EOL
|
||||
|
@ -128,10 +129,10 @@ EOT
|
|||
}
|
||||
}
|
||||
|
||||
$this->getIO()->write('Checking disk free space: ', false);
|
||||
$io->write('Checking disk free space: ', false);
|
||||
$this->outputResult($this->checkDiskSpace($config));
|
||||
|
||||
$this->getIO()->write('Checking composer version: ', false);
|
||||
$io->write('Checking composer version: ', false);
|
||||
$this->outputResult($this->checkVersion());
|
||||
|
||||
return $this->failures;
|
||||
|
@ -263,7 +264,7 @@ EOT
|
|||
$url = $domain === 'github.com' ? 'https://api.'.$domain.'/user/repos' : 'https://'.$domain.'/api/v3/user/repos';
|
||||
|
||||
return $this->rfs->getContents($domain, $url, false, array(
|
||||
'retry-auth-failure' => false
|
||||
'retry-auth-failure' => false,
|
||||
)) ? true : 'Unexpected error';
|
||||
} catch (\Exception $e) {
|
||||
if ($e instanceof TransportException && $e->getCode() === 401) {
|
||||
|
@ -275,10 +276,10 @@ EOT
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $domain
|
||||
* @param string $token
|
||||
* @return array
|
||||
* @param string $domain
|
||||
* @param string $token
|
||||
* @throws TransportException
|
||||
* @return array
|
||||
*/
|
||||
private function getGithubRateLimit($domain, $token = null)
|
||||
{
|
||||
|
@ -295,7 +296,7 @@ EOT
|
|||
|
||||
private function checkDiskSpace($config)
|
||||
{
|
||||
$minSpaceFree = 1024*1024;
|
||||
$minSpaceFree = 1024 * 1024;
|
||||
if ((($df = @disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
|
||||
|| (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
|
||||
) {
|
||||
|
@ -322,15 +323,16 @@ EOT
|
|||
*/
|
||||
private function outputResult($result)
|
||||
{
|
||||
$io = $this->getIO();
|
||||
if (true === $result) {
|
||||
$this->getIO()->write('<info>OK</info>');
|
||||
$io->write('<info>OK</info>');
|
||||
} else {
|
||||
$this->failures++;
|
||||
$this->getIO()->write('<error>FAIL</error>');
|
||||
$io->write('<error>FAIL</error>');
|
||||
if ($result instanceof \Exception) {
|
||||
$this->getIO()->write('['.get_class($result).'] '.$result->getMessage());
|
||||
$io->write('['.get_class($result).'] '.$result->getMessage());
|
||||
} elseif ($result) {
|
||||
$this->getIO()->write(trim($result));
|
||||
$io->write(trim($result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ class DumpAutoloadCommand extends Command
|
|||
->setDescription('Dumps the autoloader')
|
||||
->setDefinition(array(
|
||||
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('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules.'),
|
||||
))
|
||||
->setHelp(<<<EOT
|
||||
|
@ -52,9 +53,10 @@ EOT
|
|||
$package = $composer->getPackage();
|
||||
$config = $composer->getConfig();
|
||||
|
||||
$optimize = $input->getOption('optimize') || $config->get('optimize-autoloader') || $config->get('classmap-authoritative');
|
||||
$optimize = $input->getOption('optimize') || $config->get('optimize-autoloader');
|
||||
$authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
|
||||
|
||||
if ($optimize) {
|
||||
if ($optimize || $authoritative) {
|
||||
$this->getIO()->writeError('<info>Generating optimized autoload files</info>');
|
||||
} else {
|
||||
$this->getIO()->writeError('<info>Generating autoload files</info>');
|
||||
|
@ -62,6 +64,7 @@ EOT
|
|||
|
||||
$generator = $composer->getAutoloadGenerator();
|
||||
$generator->setDevMode(!$input->getOption('no-dev'));
|
||||
$generator->setClassMapAuthoritative($authoritative);
|
||||
$generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ namespace Composer\Command;
|
|||
|
||||
use Composer\Factory;
|
||||
use Composer\Package\CompletePackageInterface;
|
||||
use Composer\Repository\CompositeRepository;
|
||||
use Composer\Repository\RepositoryInterface;
|
||||
use Composer\Repository\ArrayRepository;
|
||||
use Composer\Util\ProcessExecutor;
|
||||
|
@ -58,6 +57,7 @@ EOT
|
|||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$repos = $this->initializeRepos();
|
||||
$io = $this->getIO();
|
||||
$return = 0;
|
||||
|
||||
foreach ($input->getArgument('packages') as $packageName) {
|
||||
|
@ -75,12 +75,12 @@ EOT
|
|||
|
||||
if (!$packageExists) {
|
||||
$return = 1;
|
||||
$this->getIO()->writeError('<warning>Package '.$packageName.' not found</warning>');
|
||||
$io->writeError('<warning>Package '.$packageName.' not found</warning>');
|
||||
}
|
||||
|
||||
if (!$handled) {
|
||||
$return = 1;
|
||||
$this->getIO()->writeError('<warning>'.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.'</warning>');
|
||||
$io->writeError('<warning>'.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.'</warning>');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,10 +16,10 @@ use Composer\DependencyResolver\Pool;
|
|||
use Composer\Json\JsonFile;
|
||||
use Composer\Factory;
|
||||
use Composer\Package\BasePackage;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Package\Version\VersionSelector;
|
||||
use Composer\Repository\CompositeRepository;
|
||||
use Composer\Repository\PlatformRepository;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Util\ProcessExecutor;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
@ -106,11 +106,12 @@ EOT
|
|||
|
||||
$file = new JsonFile('composer.json');
|
||||
$json = $file->encode($options);
|
||||
$io = $this->getIO();
|
||||
|
||||
if ($input->isInteractive()) {
|
||||
$this->getIO()->writeError(array('', $json, ''));
|
||||
if (!$this->getIO()->askConfirmation('Do you confirm generation [<comment>yes</comment>]? ', true)) {
|
||||
$this->getIO()->writeError('<error>Command aborted</error>');
|
||||
$io->writeError(array('', $json, ''));
|
||||
if (!$io->askConfirmation('Do you confirm generation [<comment>yes</comment>]? ', true)) {
|
||||
$io->writeError('<error>Command aborted</error>');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -128,7 +129,7 @@ EOT
|
|||
if (!$this->hasVendorIgnore($ignoreFile)) {
|
||||
$question = 'Would you like the <info>vendor</info> directory added to your <info>.gitignore</info> [<comment>yes</comment>]? ';
|
||||
|
||||
if ($this->getIO()->askConfirmation($question, true)) {
|
||||
if ($io->askConfirmation($question, true)) {
|
||||
$this->addVendorIgnore($ignoreFile);
|
||||
}
|
||||
}
|
||||
|
@ -141,17 +142,17 @@ EOT
|
|||
protected function interact(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$git = $this->getGitConfig();
|
||||
|
||||
$io = $this->getIO();
|
||||
$formatter = $this->getHelperSet()->get('formatter');
|
||||
|
||||
$this->getIO()->writeError(array(
|
||||
$io->writeError(array(
|
||||
'',
|
||||
$formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', true),
|
||||
''
|
||||
'',
|
||||
));
|
||||
|
||||
// namespace
|
||||
$this->getIO()->writeError(array(
|
||||
$io->writeError(array(
|
||||
'',
|
||||
'This command will guide you through creating your composer.json config.',
|
||||
'',
|
||||
|
@ -181,7 +182,7 @@ EOT
|
|||
}
|
||||
}
|
||||
|
||||
$name = $this->getIO()->askAndValidate(
|
||||
$name = $io->askAndValidate(
|
||||
'Package name (<vendor>/<name>) [<comment>'.$name.'</comment>]: ',
|
||||
function ($value) use ($name) {
|
||||
if (null === $value) {
|
||||
|
@ -202,7 +203,7 @@ EOT
|
|||
$input->setOption('name', $name);
|
||||
|
||||
$description = $input->getOption('description') ?: false;
|
||||
$description = $this->getIO()->ask(
|
||||
$description = $io->ask(
|
||||
'Description [<comment>'.$description.'</comment>]: ',
|
||||
$description
|
||||
);
|
||||
|
@ -215,7 +216,7 @@ EOT
|
|||
}
|
||||
|
||||
$self = $this;
|
||||
$author = $this->getIO()->askAndValidate(
|
||||
$author = $io->askAndValidate(
|
||||
'Author [<comment>'.$author.'</comment>]: ',
|
||||
function ($value) use ($self, $author) {
|
||||
$value = $value ?: $author;
|
||||
|
@ -229,7 +230,7 @@ EOT
|
|||
$input->setOption('author', $author);
|
||||
|
||||
$minimumStability = $input->getOption('stability') ?: null;
|
||||
$minimumStability = $this->getIO()->askAndValidate(
|
||||
$minimumStability = $io->askAndValidate(
|
||||
'Minimum Stability [<comment>'.$minimumStability.'</comment>]: ',
|
||||
function ($value) use ($self, $minimumStability) {
|
||||
if (null === $value) {
|
||||
|
@ -251,31 +252,31 @@ EOT
|
|||
$input->setOption('stability', $minimumStability);
|
||||
|
||||
$type = $input->getOption('type') ?: false;
|
||||
$type = $this->getIO()->ask(
|
||||
$type = $io->ask(
|
||||
'Package Type [<comment>'.$type.'</comment>]: ',
|
||||
$type
|
||||
);
|
||||
$input->setOption('type', $type);
|
||||
|
||||
$license = $input->getOption('license') ?: false;
|
||||
$license = $this->getIO()->ask(
|
||||
$license = $io->ask(
|
||||
'License [<comment>'.$license.'</comment>]: ',
|
||||
$license
|
||||
);
|
||||
$input->setOption('license', $license);
|
||||
|
||||
$this->getIO()->writeError(array('', 'Define your dependencies.', ''));
|
||||
$io->writeError(array('', 'Define your dependencies.', ''));
|
||||
|
||||
$question = 'Would you like to define your dependencies (require) interactively [<comment>yes</comment>]? ';
|
||||
$requirements = array();
|
||||
if ($this->getIO()->askConfirmation($question, true)) {
|
||||
if ($io->askConfirmation($question, true)) {
|
||||
$requirements = $this->determineRequirements($input, $output, $input->getOption('require'));
|
||||
}
|
||||
$input->setOption('require', $requirements);
|
||||
|
||||
$question = 'Would you like to define your dev dependencies (require-dev) interactively [<comment>yes</comment>]? ';
|
||||
$devRequirements = array();
|
||||
if ($this->getIO()->askConfirmation($question, true)) {
|
||||
if ($io->askConfirmation($question, true)) {
|
||||
$devRequirements = $this->determineRequirements($input, $output, $input->getOption('require-dev'));
|
||||
}
|
||||
$input->setOption('require-dev', $devRequirements);
|
||||
|
@ -283,7 +284,7 @@ EOT
|
|||
|
||||
/**
|
||||
* @private
|
||||
* @param string $author
|
||||
* @param string $author
|
||||
* @return array
|
||||
*/
|
||||
public function parseAuthorString($author)
|
||||
|
@ -292,7 +293,7 @@ EOT
|
|||
if ($this->isValidEmail($match['email'])) {
|
||||
return array(
|
||||
'name' => trim($match['name']),
|
||||
'email' => $match['email']
|
||||
'email' => $match['email'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -325,6 +326,7 @@ EOT
|
|||
if ($requires) {
|
||||
$requires = $this->normalizeRequirements($requires);
|
||||
$result = array();
|
||||
$io = $this->getIO();
|
||||
|
||||
foreach ($requires as $requirement) {
|
||||
if (!isset($requirement['version'])) {
|
||||
|
@ -332,7 +334,7 @@ EOT
|
|||
$version = $this->findBestVersionForPackage($input, $requirement['name']);
|
||||
$requirement['version'] = $version;
|
||||
|
||||
$this->getIO()->writeError(sprintf(
|
||||
$io->writeError(sprintf(
|
||||
'Using version <info>%s</info> for <info>%s</info>',
|
||||
$requirement['version'],
|
||||
$requirement['name']
|
||||
|
@ -346,7 +348,8 @@ EOT
|
|||
}
|
||||
|
||||
$versionParser = new VersionParser();
|
||||
while (null !== $package = $this->getIO()->ask('Search for a package: ')) {
|
||||
$io = $this->getIO();
|
||||
while (null !== $package = $io->ask('Search for a package: ')) {
|
||||
$matches = $this->findPackages($package);
|
||||
|
||||
if (count($matches)) {
|
||||
|
@ -362,14 +365,14 @@ EOT
|
|||
|
||||
// no match, prompt which to pick
|
||||
if (!$exactMatch) {
|
||||
$this->getIO()->writeError(array(
|
||||
$io->writeError(array(
|
||||
'',
|
||||
sprintf('Found <info>%s</info> packages matching <info>%s</info>', count($matches), $package),
|
||||
''
|
||||
'',
|
||||
));
|
||||
|
||||
$this->getIO()->writeError($choices);
|
||||
$this->getIO()->writeError('');
|
||||
$io->writeError($choices);
|
||||
$io->writeError('');
|
||||
|
||||
$validator = function ($selection) use ($matches, $versionParser) {
|
||||
if ('' === $selection) {
|
||||
|
@ -399,7 +402,7 @@ EOT
|
|||
throw new \Exception('Not a valid selection');
|
||||
};
|
||||
|
||||
$package = $this->getIO()->askAndValidate(
|
||||
$package = $io->askAndValidate(
|
||||
'Enter package # to add, or the complete package name if it is not listed: ',
|
||||
$validator,
|
||||
3,
|
||||
|
@ -415,7 +418,7 @@ EOT
|
|||
return $input ?: false;
|
||||
};
|
||||
|
||||
$constraint = $this->getIO()->askAndValidate(
|
||||
$constraint = $io->askAndValidate(
|
||||
'Enter the version constraint to require (or leave blank to use the latest version): ',
|
||||
$validator,
|
||||
3,
|
||||
|
@ -425,7 +428,7 @@ EOT
|
|||
if (false === $constraint) {
|
||||
$constraint = $this->findBestVersionForPackage($input, $package);
|
||||
|
||||
$this->getIO()->writeError(sprintf(
|
||||
$io->writeError(sprintf(
|
||||
'Using version <info>%s</info> for <info>%s</info>',
|
||||
$constraint,
|
||||
$package
|
||||
|
@ -588,8 +591,8 @@ EOT
|
|||
*
|
||||
* @param InputInterface $input
|
||||
* @param string $name
|
||||
* @return string
|
||||
* @throws \InvalidArgumentException
|
||||
* @return string
|
||||
*/
|
||||
private function findBestVersionForPackage(InputInterface $input, $name)
|
||||
{
|
||||
|
|
|
@ -46,6 +46,7 @@ class InstallCommand extends Command
|
|||
new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
|
||||
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('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore 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.'),
|
||||
))
|
||||
|
@ -64,24 +65,24 @@ EOT
|
|||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$io = $this->getIO();
|
||||
if ($args = $input->getArgument('packages')) {
|
||||
$this->getIO()->writeError('<error>Invalid argument '.implode(' ', $args).'. Use "composer require '.implode(' ', $args).'" instead to add packages to your composer.json.</error>');
|
||||
$io->writeError('<error>Invalid argument '.implode(' ', $args).'. Use "composer require '.implode(' ', $args).'" instead to add packages to your composer.json.</error>');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ($input->getOption('no-custom-installers')) {
|
||||
$this->getIO()->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
|
||||
$io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
|
||||
$input->setOption('no-plugins', true);
|
||||
}
|
||||
|
||||
if ($input->getOption('dev')) {
|
||||
$this->getIO()->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
|
||||
$io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
|
||||
}
|
||||
|
||||
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
|
||||
$composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
|
||||
$io = $this->getIO();
|
||||
|
||||
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output);
|
||||
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
|
||||
|
@ -110,7 +111,8 @@ EOT
|
|||
$preferDist = $input->getOption('prefer-dist');
|
||||
}
|
||||
|
||||
$optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader') || $config->get('classmap-authoritative');
|
||||
$optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
|
||||
$authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
|
||||
|
||||
$install
|
||||
->setDryRun($input->getOption('dry-run'))
|
||||
|
@ -121,6 +123,7 @@ EOT
|
|||
->setDumpAutoloader(!$input->getOption('no-autoloader'))
|
||||
->setRunScripts(!$input->getOption('no-scripts'))
|
||||
->setOptimizeAutoloader($optimize)
|
||||
->setClassMapAuthoritative($authoritative)
|
||||
->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
|
||||
;
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
namespace Composer\Command;
|
||||
|
||||
use Composer\Json\JsonFile;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Plugin\CommandEvent;
|
||||
use Composer\Plugin\PluginEvents;
|
||||
use Composer\Package\PackageInterface;
|
||||
|
@ -56,8 +55,6 @@ EOT
|
|||
$root = $composer->getPackage();
|
||||
$repo = $composer->getRepositoryManager()->getLocalRepository();
|
||||
|
||||
$versionParser = new VersionParser;
|
||||
|
||||
if ($input->getOption('no-dev')) {
|
||||
$packages = $this->filterRequiredPackages($repo, $root);
|
||||
} else {
|
||||
|
@ -65,14 +62,15 @@ EOT
|
|||
}
|
||||
|
||||
ksort($packages);
|
||||
$io = $this->getIO();
|
||||
|
||||
switch ($format = $input->getOption('format')) {
|
||||
case 'text':
|
||||
$this->getIO()->write('Name: <comment>'.$root->getPrettyName().'</comment>');
|
||||
$this->getIO()->write('Version: <comment>'.$versionParser->formatVersion($root).'</comment>');
|
||||
$this->getIO()->write('Licenses: <comment>'.(implode(', ', $root->getLicense()) ?: 'none').'</comment>');
|
||||
$this->getIO()->write('Dependencies:');
|
||||
$this->getIO()->write('');
|
||||
$io->write('Name: <comment>'.$root->getPrettyName().'</comment>');
|
||||
$io->write('Version: <comment>'.$root->getFullPrettyVersion().'</comment>');
|
||||
$io->write('Licenses: <comment>'.(implode(', ', $root->getLicense()) ?: 'none').'</comment>');
|
||||
$io->write('Dependencies:');
|
||||
$io->write('');
|
||||
|
||||
$table = new Table($output);
|
||||
$table->setStyle('compact');
|
||||
|
@ -82,7 +80,7 @@ EOT
|
|||
foreach ($packages as $package) {
|
||||
$table->addRow(array(
|
||||
$package->getPrettyName(),
|
||||
$versionParser->formatVersion($package),
|
||||
$package->getFullPrettyVersion(),
|
||||
implode(', ', $package->getLicense()) ?: 'none',
|
||||
));
|
||||
}
|
||||
|
@ -92,14 +90,14 @@ EOT
|
|||
case 'json':
|
||||
foreach ($packages as $package) {
|
||||
$dependencies[$package->getPrettyName()] = array(
|
||||
'version' => $versionParser->formatVersion($package),
|
||||
'version' => $package->getFullPrettyVersion(),
|
||||
'license' => $package->getLicense(),
|
||||
);
|
||||
}
|
||||
|
||||
$this->getIO()->write(JsonFile::encode(array(
|
||||
$io->write(JsonFile::encode(array(
|
||||
'name' => $root->getPrettyName(),
|
||||
'version' => $versionParser->formatVersion($root),
|
||||
'version' => $root->getFullPrettyVersion(),
|
||||
'license' => $root->getLicense(),
|
||||
'dependencies' => $dependencies,
|
||||
)));
|
||||
|
|
|
@ -42,6 +42,8 @@ class RemoveCommand extends Command
|
|||
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.'),
|
||||
new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- 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`.'),
|
||||
))
|
||||
->setHelp(<<<EOT
|
||||
The <info>remove</info> command removes a package from the current
|
||||
|
@ -68,19 +70,20 @@ EOT
|
|||
|
||||
$type = $input->getOption('dev') ? 'require-dev' : 'require';
|
||||
$altType = !$input->getOption('dev') ? 'require-dev' : 'require';
|
||||
$io = $this->getIO();
|
||||
|
||||
foreach ($packages as $package) {
|
||||
if (isset($composer[$type][$package])) {
|
||||
$json->removeLink($type, $package);
|
||||
} elseif (isset($composer[$altType][$package])) {
|
||||
$this->getIO()->writeError('<warning>'.$package.' could not be found in '.$type.' but it is present in '.$altType.'</warning>');
|
||||
if ($this->getIO()->isInteractive()) {
|
||||
if ($this->getIO()->askConfirmation('Do you want to remove it from '.$altType.' [<comment>yes</comment>]? ', true)) {
|
||||
$io->writeError('<warning>'.$package.' could not be found in '.$type.' but it is present in '.$altType.'</warning>');
|
||||
if ($io->isInteractive()) {
|
||||
if ($io->askConfirmation('Do you want to remove it from '.$altType.' [<comment>yes</comment>]? ', true)) {
|
||||
$json->removeLink($altType, $package);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->getIO()->writeError('<warning>'.$package.' is not required in your composer.json and has not been removed</warning>');
|
||||
$io->writeError('<warning>'.$package.' is not required in your composer.json and has not been removed</warning>');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,7 +94,6 @@ EOT
|
|||
// Update packages
|
||||
$composer = $this->getComposer();
|
||||
$composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
|
||||
$io = $this->getIO();
|
||||
|
||||
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output);
|
||||
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
|
||||
|
@ -99,9 +101,14 @@ EOT
|
|||
$install = Installer::create($io, $composer);
|
||||
|
||||
$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');
|
||||
|
||||
$install
|
||||
->setVerbose($input->getOption('verbose'))
|
||||
->setDevMode($updateDevMode)
|
||||
->setOptimizeAutoloader($optimize)
|
||||
->setClassMapAuthoritative($authoritative)
|
||||
->setUpdate(true)
|
||||
->setUpdateWhitelist($packages)
|
||||
->setWhitelistDependencies($input->getOption('update-with-dependencies'))
|
||||
|
@ -110,7 +117,7 @@ EOT
|
|||
|
||||
$status = $install->run();
|
||||
if ($status !== 0) {
|
||||
$this->getIO()->writeError("\n".'<error>Removal failed, reverting '.$file.' to its original content.</error>');
|
||||
$io->writeError("\n".'<error>Removal failed, reverting '.$file.' to its original content.</error>');
|
||||
file_put_contents($jsonFile->getPath(), $composerBackup);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ use Composer\Factory;
|
|||
use Composer\Installer;
|
||||
use Composer\Json\JsonFile;
|
||||
use Composer\Json\JsonManipulator;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Semver\VersionParser;
|
||||
use Composer\Plugin\CommandEvent;
|
||||
use Composer\Plugin\PluginEvents;
|
||||
use Composer\Repository\CompositeRepository;
|
||||
|
@ -48,6 +48,8 @@ class RequireCommand extends InitCommand
|
|||
new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies.'),
|
||||
new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
|
||||
new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages when adding/updating a new dependency'),
|
||||
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`.'),
|
||||
))
|
||||
->setHelp(<<<EOT
|
||||
The require command adds required packages to your composer.json and installs them.
|
||||
|
@ -64,20 +66,21 @@ EOT
|
|||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$file = Factory::getComposerFile();
|
||||
$io = $this->getIO();
|
||||
|
||||
$newlyCreated = !file_exists($file);
|
||||
if (!file_exists($file) && !file_put_contents($file, "{\n}\n")) {
|
||||
$this->getIO()->writeError('<error>'.$file.' could not be created.</error>');
|
||||
$io->writeError('<error>'.$file.' could not be created.</error>');
|
||||
|
||||
return 1;
|
||||
}
|
||||
if (!is_readable($file)) {
|
||||
$this->getIO()->writeError('<error>'.$file.' is not readable.</error>');
|
||||
$io->writeError('<error>'.$file.' is not readable.</error>');
|
||||
|
||||
return 1;
|
||||
}
|
||||
if (!is_writable($file)) {
|
||||
$this->getIO()->writeError('<error>'.$file.' is not writable.</error>');
|
||||
$io->writeError('<error>'.$file.' is not writable.</error>');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -126,18 +129,19 @@ EOT
|
|||
$json->write($composerDefinition);
|
||||
}
|
||||
|
||||
$this->getIO()->writeError('<info>'.$file.' has been '.($newlyCreated ? 'created' : 'updated').'</info>');
|
||||
$io->writeError('<info>'.$file.' has been '.($newlyCreated ? 'created' : 'updated').'</info>');
|
||||
|
||||
if ($input->getOption('no-update')) {
|
||||
return 0;
|
||||
}
|
||||
$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');
|
||||
|
||||
// Update packages
|
||||
$this->resetComposer();
|
||||
$composer = $this->getComposer();
|
||||
$composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
|
||||
$io = $this->getIO();
|
||||
|
||||
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
|
||||
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
|
||||
|
@ -149,6 +153,8 @@ EOT
|
|||
->setPreferSource($input->getOption('prefer-source'))
|
||||
->setPreferDist($input->getOption('prefer-dist'))
|
||||
->setDevMode($updateDevMode)
|
||||
->setOptimizeAutoloader($optimize)
|
||||
->setClassMapAuthoritative($authoritative)
|
||||
->setUpdate(true)
|
||||
->setUpdateWhitelist(array_keys($requirements))
|
||||
->setWhitelistDependencies($input->getOption('update-with-dependencies'))
|
||||
|
@ -158,10 +164,10 @@ EOT
|
|||
$status = $install->run();
|
||||
if ($status !== 0) {
|
||||
if ($newlyCreated) {
|
||||
$this->getIO()->writeError("\n".'<error>Installation failed, deleting '.$file.'.</error>');
|
||||
$io->writeError("\n".'<error>Installation failed, deleting '.$file.'.</error>');
|
||||
unlink($json->getPath());
|
||||
} else {
|
||||
$this->getIO()->writeError("\n".'<error>Installation failed, reverting '.$file.' to its original content.</error>');
|
||||
$io->writeError("\n".'<error>Installation failed, reverting '.$file.' to its original content.</error>');
|
||||
file_put_contents($json->getPath(), $composerBackup);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,9 +104,10 @@ EOT
|
|||
return 0;
|
||||
}
|
||||
|
||||
$this->getIO()->writeError('<info>scripts:</info>');
|
||||
$io = $this->getIO();
|
||||
$io->writeError('<info>scripts:</info>');
|
||||
foreach ($scripts as $name => $script) {
|
||||
$this->getIO()->write(' ' . $name);
|
||||
$io->write(' ' . $name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -56,13 +56,14 @@ EOT
|
|||
{
|
||||
// init repos
|
||||
$platformRepo = new PlatformRepository;
|
||||
$io = $this->getIO();
|
||||
if ($composer = $this->getComposer(false)) {
|
||||
$localRepo = $composer->getRepositoryManager()->getLocalRepository();
|
||||
$installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
|
||||
$repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
|
||||
} else {
|
||||
$defaultRepos = Factory::createDefaultRepositories($this->getIO());
|
||||
$this->getIO()->writeError('No composer.json found in the current directory, showing packages from ' . implode(', ', array_keys($defaultRepos)));
|
||||
$defaultRepos = Factory::createDefaultRepositories($io);
|
||||
$io->writeError('No composer.json found in the current directory, showing packages from ' . implode(', ', array_keys($defaultRepos)));
|
||||
$installedRepo = $platformRepo;
|
||||
$repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
|
||||
}
|
||||
|
@ -78,7 +79,7 @@ EOT
|
|||
$results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags);
|
||||
|
||||
foreach ($results as $result) {
|
||||
$this->getIO()->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
|
||||
$io->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,8 @@ EOT
|
|||
{
|
||||
$baseUrl = (extension_loaded('openssl') ? 'https' : 'http') . '://' . self::HOMEPAGE;
|
||||
$config = Factory::createConfig();
|
||||
$remoteFilesystem = new RemoteFilesystem($this->getIO(), $config);
|
||||
$io = $this->getIO();
|
||||
$remoteFilesystem = new RemoteFilesystem($io, $config);
|
||||
$cacheDir = $config->get('cache-dir');
|
||||
$rollbackDir = $config->get('data-dir');
|
||||
$localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
|
||||
|
@ -84,13 +85,13 @@ EOT
|
|||
$updateVersion = $input->getArgument('version') ?: $latestVersion;
|
||||
|
||||
if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) {
|
||||
$this->getIO()->writeError('<error>You can not update to a specific SHA-1 as those phars are not available for download</error>');
|
||||
$io->writeError('<error>You can not update to a specific SHA-1 as those phars are not available for download</error>');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (Composer::VERSION === $updateVersion) {
|
||||
$this->getIO()->writeError('<info>You are already using composer version '.$updateVersion.'.</info>');
|
||||
$io->writeError('<info>You are already using composer version '.$updateVersion.'.</info>');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -104,11 +105,11 @@ EOT
|
|||
self::OLD_INSTALL_EXT
|
||||
);
|
||||
|
||||
$this->getIO()->writeError(sprintf("Updating to version <info>%s</info>.", $updateVersion));
|
||||
$io->writeError(sprintf("Updating to version <info>%s</info>.", $updateVersion));
|
||||
$remoteFilename = $baseUrl . (preg_match('{^[0-9a-f]{40}$}', $updateVersion) ? '/composer.phar' : "/download/{$updateVersion}/composer.phar");
|
||||
$remoteFilesystem->copy(self::HOMEPAGE, $remoteFilename, $tempFilename, !$input->getOption('no-progress'));
|
||||
if (!file_exists($tempFilename)) {
|
||||
$this->getIO()->writeError('<error>The download of the new composer version failed for an unexpected reason</error>');
|
||||
$io->writeError('<error>The download of the new composer version failed for an unexpected reason</error>');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -120,22 +121,22 @@ EOT
|
|||
$fs = new Filesystem;
|
||||
foreach ($finder as $file) {
|
||||
$file = (string) $file;
|
||||
$this->getIO()->writeError('<info>Removing: '.$file.'</info>');
|
||||
$io->writeError('<info>Removing: '.$file.'</info>');
|
||||
$fs->remove($file);
|
||||
}
|
||||
}
|
||||
|
||||
if ($err = $this->setLocalPhar($localFilename, $tempFilename, $backupFile)) {
|
||||
$this->getIO()->writeError('<error>The file is corrupted ('.$err->getMessage().').</error>');
|
||||
$this->getIO()->writeError('<error>Please re-run the self-update command to try again.</error>');
|
||||
$io->writeError('<error>The file is corrupted ('.$err->getMessage().').</error>');
|
||||
$io->writeError('<error>Please re-run the self-update command to try again.</error>');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (file_exists($backupFile)) {
|
||||
$this->getIO()->writeError('Use <info>composer self-update --rollback</info> to return to version '.Composer::VERSION);
|
||||
$io->writeError('Use <info>composer self-update --rollback</info> to return to version '.Composer::VERSION);
|
||||
} else {
|
||||
$this->getIO()->writeError('<warning>A backup of the current version could not be written to '.$backupFile.', no rollback possible</warning>');
|
||||
$io->writeError('<warning>A backup of the current version could not be written to '.$backupFile.', no rollback possible</warning>');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,9 +161,10 @@ EOT
|
|||
}
|
||||
|
||||
$oldFile = $rollbackDir . "/{$rollbackVersion}" . self::OLD_INSTALL_EXT;
|
||||
$this->getIO()->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
|
||||
$io = $this->getIO();
|
||||
$io->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
|
||||
if ($err = $this->setLocalPhar($localFilename, $oldFile)) {
|
||||
$this->getIO()->writeError('<error>The backup file was corrupted ('.$err->getMessage().') and has been removed.</error>');
|
||||
$io->writeError('<error>The backup file was corrupted ('.$err->getMessage().') and has been removed.</error>');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ use Composer\DependencyResolver\Pool;
|
|||
use Composer\DependencyResolver\DefaultPolicy;
|
||||
use Composer\Factory;
|
||||
use Composer\Package\CompletePackageInterface;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Semver\VersionParser;
|
||||
use Composer\Plugin\CommandEvent;
|
||||
use Composer\Plugin\PluginEvents;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
@ -28,7 +28,7 @@ use Composer\Repository\CompositeRepository;
|
|||
use Composer\Repository\ComposerRepository;
|
||||
use Composer\Repository\PlatformRepository;
|
||||
use Composer\Repository\RepositoryInterface;
|
||||
use Composer\Util\SpdxLicense;
|
||||
use Composer\Spdx\SpdxLicenses;
|
||||
|
||||
/**
|
||||
* @author Robert Schönthal <seroscho@googlemail.com>
|
||||
|
@ -71,6 +71,7 @@ EOT
|
|||
$platformRepo = new PlatformRepository;
|
||||
|
||||
$composer = $this->getComposer(false);
|
||||
$io = $this->getIO();
|
||||
if ($input->getOption('self')) {
|
||||
$package = $this->getComposer()->getPackage();
|
||||
$repos = $installedRepo = new ArrayRepository(array($package));
|
||||
|
@ -83,17 +84,17 @@ EOT
|
|||
if ($composer) {
|
||||
$repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
|
||||
} else {
|
||||
$defaultRepos = Factory::createDefaultRepositories($this->getIO());
|
||||
$defaultRepos = Factory::createDefaultRepositories($io);
|
||||
$repos = new CompositeRepository($defaultRepos);
|
||||
$this->getIO()->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
|
||||
$io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
|
||||
}
|
||||
} elseif ($composer) {
|
||||
$localRepo = $composer->getRepositoryManager()->getLocalRepository();
|
||||
$installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
|
||||
$repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
|
||||
} else {
|
||||
$defaultRepos = Factory::createDefaultRepositories($this->getIO());
|
||||
$this->getIO()->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
|
||||
$defaultRepos = Factory::createDefaultRepositories($io);
|
||||
$io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
|
||||
$installedRepo = $platformRepo;
|
||||
$repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
|
||||
}
|
||||
|
@ -120,9 +121,9 @@ EOT
|
|||
$this->printLinks($package, 'requires');
|
||||
$this->printLinks($package, 'devRequires', 'requires (dev)');
|
||||
if ($package->getSuggests()) {
|
||||
$this->getIO()->write("\n<info>suggests</info>");
|
||||
$io->write("\n<info>suggests</info>");
|
||||
foreach ($package->getSuggests() as $suggested => $reason) {
|
||||
$this->getIO()->write($suggested . ' <comment>' . $reason . '</comment>');
|
||||
$io->write($suggested . ' <comment>' . $reason . '</comment>');
|
||||
}
|
||||
}
|
||||
$this->printLinks($package, 'provides');
|
||||
|
@ -173,7 +174,7 @@ EOT
|
|||
foreach (array('<info>platform</info>:' => true, '<comment>available</comment>:' => false, '<info>installed</info>:' => true) as $type => $showVersion) {
|
||||
if (isset($packages[$type])) {
|
||||
if ($tree) {
|
||||
$this->getIO()->write($type);
|
||||
$io->write($type);
|
||||
}
|
||||
ksort($packages[$type]);
|
||||
|
||||
|
@ -181,7 +182,7 @@ EOT
|
|||
foreach ($packages[$type] as $package) {
|
||||
if (is_object($package)) {
|
||||
$nameLength = max($nameLength, strlen($package->getPrettyName()));
|
||||
$versionLength = max($versionLength, strlen($this->versionParser->formatVersion($package)));
|
||||
$versionLength = max($versionLength, strlen($package->getFullPrettyVersion()));
|
||||
} else {
|
||||
$nameLength = max($nameLength, $package);
|
||||
}
|
||||
|
@ -197,7 +198,7 @@ EOT
|
|||
}
|
||||
|
||||
if ($input->getOption('path') && null === $composer) {
|
||||
$this->getIO()->writeError('No composer.json found in the current directory, disabling "path" option');
|
||||
$io->writeError('No composer.json found in the current directory, disabling "path" option');
|
||||
$input->setOption('path', false);
|
||||
}
|
||||
|
||||
|
@ -209,7 +210,7 @@ EOT
|
|||
$output->write($indent . str_pad($package->getPrettyName(), $nameLength, ' '), false);
|
||||
|
||||
if ($writeVersion) {
|
||||
$output->write(' ' . str_pad($this->versionParser->formatVersion($package), $versionLength, ' '), false);
|
||||
$output->write(' ' . str_pad($package->getFullPrettyVersion(), $versionLength, ' '), false);
|
||||
}
|
||||
|
||||
if ($writeDescription) {
|
||||
|
@ -228,10 +229,10 @@ EOT
|
|||
} else {
|
||||
$output->write($indent . $package);
|
||||
}
|
||||
$this->getIO()->write('');
|
||||
$io->write('');
|
||||
}
|
||||
if ($tree) {
|
||||
$this->getIO()->write('');
|
||||
$io->write('');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -244,8 +245,8 @@ EOT
|
|||
* @param RepositoryInterface $repos
|
||||
* @param string $name
|
||||
* @param string $version
|
||||
* @return array array(CompletePackageInterface, array of versions)
|
||||
* @throws \InvalidArgumentException
|
||||
* @return array array(CompletePackageInterface, array of versions)
|
||||
*/
|
||||
protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null)
|
||||
{
|
||||
|
@ -291,53 +292,54 @@ EOT
|
|||
*/
|
||||
protected function printMeta(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo)
|
||||
{
|
||||
$this->getIO()->write('<info>name</info> : ' . $package->getPrettyName());
|
||||
$this->getIO()->write('<info>descrip.</info> : ' . $package->getDescription());
|
||||
$this->getIO()->write('<info>keywords</info> : ' . join(', ', $package->getKeywords() ?: array()));
|
||||
$io = $this->getIO();
|
||||
$io->write('<info>name</info> : ' . $package->getPrettyName());
|
||||
$io->write('<info>descrip.</info> : ' . $package->getDescription());
|
||||
$io->write('<info>keywords</info> : ' . join(', ', $package->getKeywords() ?: array()));
|
||||
$this->printVersions($package, $versions, $installedRepo);
|
||||
$this->getIO()->write('<info>type</info> : ' . $package->getType());
|
||||
$io->write('<info>type</info> : ' . $package->getType());
|
||||
$this->printLicenses($package);
|
||||
$this->getIO()->write('<info>source</info> : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
|
||||
$this->getIO()->write('<info>dist</info> : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
|
||||
$this->getIO()->write('<info>names</info> : ' . implode(', ', $package->getNames()));
|
||||
$io->write('<info>source</info> : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
|
||||
$io->write('<info>dist</info> : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
|
||||
$io->write('<info>names</info> : ' . implode(', ', $package->getNames()));
|
||||
|
||||
if ($package->isAbandoned()) {
|
||||
$replacement = ($package->getReplacementPackage() !== null)
|
||||
? ' The author suggests using the ' . $package->getReplacementPackage(). ' package instead.'
|
||||
: null;
|
||||
|
||||
$this->getIO()->writeError(
|
||||
$io->writeError(
|
||||
sprintf('<warning>Attention: This package is abandoned and no longer maintained.%s</warning>', $replacement)
|
||||
);
|
||||
}
|
||||
|
||||
if ($package->getSupport()) {
|
||||
$this->getIO()->write("\n<info>support</info>");
|
||||
$io->write("\n<info>support</info>");
|
||||
foreach ($package->getSupport() as $type => $value) {
|
||||
$this->getIO()->write('<comment>' . $type . '</comment> : '.$value);
|
||||
$io->write('<comment>' . $type . '</comment> : '.$value);
|
||||
}
|
||||
}
|
||||
|
||||
if ($package->getAutoload()) {
|
||||
$this->getIO()->write("\n<info>autoload</info>");
|
||||
$io->write("\n<info>autoload</info>");
|
||||
foreach ($package->getAutoload() as $type => $autoloads) {
|
||||
$this->getIO()->write('<comment>' . $type . '</comment>');
|
||||
$io->write('<comment>' . $type . '</comment>');
|
||||
|
||||
if ($type === 'psr-0') {
|
||||
foreach ($autoloads as $name => $path) {
|
||||
$this->getIO()->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
|
||||
$io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
|
||||
}
|
||||
} elseif ($type === 'psr-4') {
|
||||
foreach ($autoloads as $name => $path) {
|
||||
$this->getIO()->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
|
||||
$io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
|
||||
}
|
||||
} elseif ($type === 'classmap') {
|
||||
$this->getIO()->write(implode(', ', $autoloads));
|
||||
$io->write(implode(', ', $autoloads));
|
||||
}
|
||||
}
|
||||
if ($package->getIncludePaths()) {
|
||||
$this->getIO()->write('<comment>include-path</comment>');
|
||||
$this->getIO()->write(implode(', ', $package->getIncludePaths()));
|
||||
$io->write('<comment>include-path</comment>');
|
||||
$io->write(implode(', ', $package->getIncludePaths()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -374,11 +376,12 @@ EOT
|
|||
protected function printLinks(CompletePackageInterface $package, $linkType, $title = null)
|
||||
{
|
||||
$title = $title ?: $linkType;
|
||||
$io = $this->getIO();
|
||||
if ($links = $package->{'get'.ucfirst($linkType)}()) {
|
||||
$this->getIO()->write("\n<info>" . $title . "</info>");
|
||||
$io->write("\n<info>" . $title . "</info>");
|
||||
|
||||
foreach ($links as $link) {
|
||||
$this->getIO()->write($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
|
||||
$io->write($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -390,12 +393,13 @@ EOT
|
|||
*/
|
||||
protected function printLicenses(CompletePackageInterface $package)
|
||||
{
|
||||
$spdxLicense = new SpdxLicense;
|
||||
$spdxLicenses = new SpdxLicenses();
|
||||
|
||||
$licenses = $package->getLicense();
|
||||
$io = $this->getIO();
|
||||
|
||||
foreach ($licenses as $licenseId) {
|
||||
$license = $spdxLicense->getLicenseByIdentifier($licenseId); // keys: 0 fullname, 1 osi, 2 url
|
||||
$license = $spdxLicenses->getLicenseByIdentifier($licenseId); // keys: 0 fullname, 1 osi, 2 url
|
||||
|
||||
if (!$license) {
|
||||
$out = $licenseId;
|
||||
|
@ -408,7 +412,7 @@ EOT
|
|||
}
|
||||
}
|
||||
|
||||
$this->getIO()->write('<info>license</info> : ' . $out);
|
||||
$io->write('<info>license</info> : ' . $out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ EOT
|
|||
$composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_STATUS_CMD, true);
|
||||
|
||||
$errors = array();
|
||||
$io = $this->getIO();
|
||||
|
||||
// list packages
|
||||
foreach ($installedRepo->getPackages() as $package) {
|
||||
|
@ -68,6 +69,10 @@ EOT
|
|||
if ($downloader instanceof ChangeReportInterface) {
|
||||
$targetDir = $im->getInstallPath($package);
|
||||
|
||||
if (is_link($targetDir)) {
|
||||
$errors[$targetDir] = $targetDir . ' is a symbolic link.';
|
||||
}
|
||||
|
||||
if ($changes = $downloader->getLocalChanges($package, $targetDir)) {
|
||||
$errors[$targetDir] = $changes;
|
||||
}
|
||||
|
@ -76,9 +81,9 @@ EOT
|
|||
|
||||
// output errors/warnings
|
||||
if (!$errors) {
|
||||
$this->getIO()->writeError('<info>No local changes</info>');
|
||||
$io->writeError('<info>No local changes</info>');
|
||||
} else {
|
||||
$this->getIO()->writeError('<error>You have changes in the following dependencies:</error>');
|
||||
$io->writeError('<error>You have changes in the following dependencies:</error>');
|
||||
}
|
||||
|
||||
foreach ($errors as $path => $changes) {
|
||||
|
@ -86,15 +91,15 @@ EOT
|
|||
$indentedChanges = implode("\n", array_map(function ($line) {
|
||||
return ' ' . ltrim($line);
|
||||
}, explode("\n", $changes)));
|
||||
$this->getIO()->write('<info>'.$path.'</info>:');
|
||||
$this->getIO()->write($indentedChanges);
|
||||
$io->write('<info>'.$path.'</info>:');
|
||||
$io->write($indentedChanges);
|
||||
} else {
|
||||
$this->getIO()->write($path);
|
||||
$io->write($path);
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors && !$input->getOption('verbose')) {
|
||||
$this->getIO()->writeError('Use --verbose (-v) to see modified files');
|
||||
$io->writeError('Use --verbose (-v) to see modified files');
|
||||
}
|
||||
|
||||
// Dispatch post-status-command
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
<?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\Command;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class SuggestsCommand extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('suggests')
|
||||
->setDescription('Show package suggestions')
|
||||
->setDefinition(array(
|
||||
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'),
|
||||
new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.'),
|
||||
))
|
||||
->setHelp(<<<EOT
|
||||
|
||||
The <info>%command.name%</info> command shows suggested packages.
|
||||
|
||||
With <info>-v</info> you also see which package suggested it and why.
|
||||
|
||||
EOT
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$lock = $this->getComposer()->getLocker()->getLockData();
|
||||
|
||||
if (empty($lock)) {
|
||||
throw new \RuntimeException('Lockfile seems to be empty?');
|
||||
}
|
||||
|
||||
$packages = $lock['packages'];
|
||||
|
||||
if (!$input->getOption('no-dev')) {
|
||||
$packages += $lock['packages-dev'];
|
||||
}
|
||||
|
||||
$filter = $input->getArgument('packages');
|
||||
|
||||
foreach ($packages as $package) {
|
||||
if (empty($package['suggest'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!empty($filter) && !in_array($package['name'], $filter)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->printSuggestions($packages, $package['name'], $package['suggest']);
|
||||
}
|
||||
}
|
||||
|
||||
protected function printSuggestions($installed, $source, $suggestions)
|
||||
{
|
||||
foreach ($suggestions as $suggestion => $reason) {
|
||||
foreach ($installed as $package) {
|
||||
if ($package['name'] === $suggestion) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($reason)) {
|
||||
$reason = '*';
|
||||
}
|
||||
|
||||
$this->printSuggestion($source, $suggestion, $reason);
|
||||
}
|
||||
}
|
||||
|
||||
protected function printSuggestion($package, $suggestion, $reason)
|
||||
{
|
||||
$io = $this->getIO();
|
||||
|
||||
if ($io->isVerbose()) {
|
||||
$io->write(sprintf('<comment>%s</comment> suggests <info>%s</info>: %s', $package, $suggestion, $reason));
|
||||
} else {
|
||||
$io->write(sprintf('<info>%s</info>', $suggestion));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -47,6 +47,7 @@ class UpdateCommand extends Command
|
|||
new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also all dependencies of whitelisted packages to the whitelist.'),
|
||||
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('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
|
||||
new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
|
||||
new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
|
||||
|
@ -74,18 +75,18 @@ EOT
|
|||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$io = $this->getIO();
|
||||
if ($input->getOption('no-custom-installers')) {
|
||||
$this->getIO()->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
|
||||
$io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
|
||||
$input->setOption('no-plugins', true);
|
||||
}
|
||||
|
||||
if ($input->getOption('dev')) {
|
||||
$this->getIO()->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
|
||||
$io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
|
||||
}
|
||||
|
||||
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
|
||||
$composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
|
||||
$io = $this->getIO();
|
||||
|
||||
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
|
||||
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
|
||||
|
@ -114,7 +115,8 @@ EOT
|
|||
$preferDist = $input->getOption('prefer-dist');
|
||||
}
|
||||
|
||||
$optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader') || $config->get('classmap-authoritative');
|
||||
$optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
|
||||
$authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
|
||||
|
||||
$install
|
||||
->setDryRun($input->getOption('dry-run'))
|
||||
|
@ -125,6 +127,7 @@ EOT
|
|||
->setDumpAutoloader(!$input->getOption('no-autoloader'))
|
||||
->setRunScripts(!$input->getOption('no-scripts'))
|
||||
->setOptimizeAutoloader($optimize)
|
||||
->setClassMapAuthoritative($authoritative)
|
||||
->setUpdate(true)
|
||||
->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $input->getArgument('packages'))
|
||||
->setWhitelistDependencies($input->getOption('with-dependencies'))
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
namespace Composer\Command;
|
||||
|
||||
use Composer\Factory;
|
||||
use Composer\Package\Loader\ValidatingArrayLoader;
|
||||
use Composer\Util\ConfigValidator;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
|
@ -34,14 +35,22 @@ class ValidateCommand extends Command
|
|||
{
|
||||
$this
|
||||
->setName('validate')
|
||||
->setDescription('Validates a composer.json')
|
||||
->setDescription('Validates a composer.json and composer.lock')
|
||||
->setDefinition(array(
|
||||
new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not make a complete validation'),
|
||||
new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'),
|
||||
new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'),
|
||||
new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file', './composer.json')
|
||||
new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'),
|
||||
new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'),
|
||||
new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file', './composer.json'),
|
||||
))
|
||||
->setHelp(<<<EOT
|
||||
The validate command validates a given composer.json
|
||||
The validate command validates a given composer.json and composer.lock
|
||||
|
||||
Exit codes in case of errors are:
|
||||
1 validation warning(s), only when --strict is given
|
||||
2 validation error(s)
|
||||
3 file unreadable or missing
|
||||
|
||||
EOT
|
||||
);
|
||||
|
@ -56,35 +65,86 @@ EOT
|
|||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$file = $input->getArgument('file');
|
||||
$io = $this->getIO();
|
||||
|
||||
if (!file_exists($file)) {
|
||||
$this->getIO()->writeError('<error>' . $file . ' not found.</error>');
|
||||
$io->writeError('<error>' . $file . ' not found.</error>');
|
||||
|
||||
return 1;
|
||||
return 3;
|
||||
}
|
||||
if (!is_readable($file)) {
|
||||
$this->getIO()->writeError('<error>' . $file . ' is not readable.</error>');
|
||||
$io->writeError('<error>' . $file . ' is not readable.</error>');
|
||||
|
||||
return 1;
|
||||
return 3;
|
||||
}
|
||||
|
||||
$validator = new ConfigValidator($this->getIO());
|
||||
$validator = new ConfigValidator($io);
|
||||
$checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL;
|
||||
$checkPublish = !$input->getOption('no-check-publish');
|
||||
$checkLock = !$input->getOption('no-check-lock');
|
||||
$isStrict = $input->getOption('strict');
|
||||
list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
|
||||
|
||||
// output errors/warnings
|
||||
$lockErrors = array();
|
||||
$composer = Factory::create($io, $file);
|
||||
$locker = $composer->getLocker();
|
||||
if ($locker->isLocked() && !$locker->isFresh()) {
|
||||
$lockErrors[] = 'The lock file is not up to date with the latest changes in composer.json.';
|
||||
}
|
||||
|
||||
$this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, true);
|
||||
|
||||
$exitCode = $errors || ($publishErrors && $checkPublish) || ($lockErrors && $checkLock) ? 2 : ($isStrict && $warnings ? 1 : 0);
|
||||
|
||||
if ($input->getOption('with-dependencies')) {
|
||||
$localRepo = $composer->getRepositoryManager()->getLocalRepository();
|
||||
foreach ($localRepo->getPackages() as $package) {
|
||||
$path = $composer->getInstallationManager()->getInstallPath($package);
|
||||
$file = $path . '/composer.json';
|
||||
if (is_dir($path) && file_exists($file)) {
|
||||
list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
|
||||
$this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors);
|
||||
|
||||
$depCode = $errors || ($publishErrors && $checkPublish) ? 2 : ($isStrict && $warnings ? 1 : 0);
|
||||
$exitCode = max($depCode, $exitCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $exitCode;
|
||||
}
|
||||
|
||||
private function outputResult($io, $name, &$errors, &$warnings, $checkPublish = false, $publishErrors = array(), $checkLock = false, $lockErrors = array(), $printSchemaUrl = false)
|
||||
{
|
||||
if (!$errors && !$publishErrors && !$warnings) {
|
||||
$this->getIO()->write('<info>' . $file . ' is valid</info>');
|
||||
$io->write('<info>' . $name . ' is valid</info>');
|
||||
} elseif (!$errors && !$publishErrors) {
|
||||
$this->getIO()->writeError('<info>' . $file . ' is valid, but with a few warnings</info>');
|
||||
$this->getIO()->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
|
||||
$io->writeError('<info>' . $name . ' is valid, but with a few warnings</info>');
|
||||
if ($printSchemaUrl) {
|
||||
$io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
|
||||
}
|
||||
} elseif (!$errors) {
|
||||
$this->getIO()->writeError('<info>' . $file . ' is valid for simple usage with composer but has</info>');
|
||||
$this->getIO()->writeError('<info>strict errors that make it unable to be published as a package:</info>');
|
||||
$this->getIO()->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
|
||||
$io->writeError('<info>' . $name . ' is valid for simple usage with composer but has</info>');
|
||||
$io->writeError('<info>strict errors that make it unable to be published as a package:</info>');
|
||||
if ($printSchemaUrl) {
|
||||
$io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
|
||||
}
|
||||
} else {
|
||||
$this->getIO()->writeError('<error>' . $file . ' is invalid, the following errors/warnings were found:</error>');
|
||||
$io->writeError('<error>' . $name . ' is invalid, the following errors/warnings were found:</error>');
|
||||
}
|
||||
|
||||
// If checking publish errors, display them as errors, otherwise just show them as warnings
|
||||
if ($checkPublish) {
|
||||
$errors = array_merge($errors, $publishErrors);
|
||||
} else {
|
||||
$warnings = array_merge($warnings, $publishErrors);
|
||||
}
|
||||
|
||||
// If checking lock errors, display them as errors, otherwise just show them as warnings
|
||||
if ($checkLock) {
|
||||
$errors = array_merge($errors, $lockErrors);
|
||||
} else {
|
||||
$warnings = array_merge($warnings, $lockErrors);
|
||||
}
|
||||
|
||||
$messages = array(
|
||||
|
@ -92,19 +152,10 @@ EOT
|
|||
'warning' => $warnings,
|
||||
);
|
||||
|
||||
// If checking publish errors, display them errors, otherwise just show them as warnings
|
||||
if ($checkPublish) {
|
||||
$messages['error'] = array_merge($messages['error'], $publishErrors);
|
||||
} else {
|
||||
$messages['warning'] = array_merge($messages['warning'], $publishErrors);
|
||||
}
|
||||
|
||||
foreach ($messages as $style => $msgs) {
|
||||
foreach ($msgs as $msg) {
|
||||
$this->getIO()->writeError('<' . $style . '>' . $msg . '</' . $style . '>');
|
||||
$io->writeError('<' . $style . '>' . $msg . '</' . $style . '>');
|
||||
}
|
||||
}
|
||||
|
||||
return $errors || ($publishErrors && $checkPublish) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
namespace Composer;
|
||||
|
||||
use Composer\Json\JsonFile;
|
||||
use Composer\Spdx\SpdxLicenses;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Seld\PharUtils\Timestamps;
|
||||
|
@ -32,8 +33,8 @@ class Compiler
|
|||
/**
|
||||
* Compiles composer into a single phar file
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
* @param string $pharFile The full path to the file to create
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function compile($pharFile = 'composer.phar')
|
||||
{
|
||||
|
@ -95,7 +96,8 @@ class Compiler
|
|||
$finder = new Finder();
|
||||
$finder->files()
|
||||
->name('*.json')
|
||||
->in(__DIR__ . '/../../res')
|
||||
->in(__DIR__.'/../../res')
|
||||
->in(SpdxLicenses::getResourcesDir())
|
||||
->sort($finderSort)
|
||||
;
|
||||
|
||||
|
@ -116,6 +118,8 @@ class Compiler
|
|||
->in(__DIR__.'/../../vendor/seld/jsonlint/')
|
||||
->in(__DIR__.'/../../vendor/seld/cli-prompt/')
|
||||
->in(__DIR__.'/../../vendor/justinrainbow/json-schema/')
|
||||
->in(__DIR__.'/../../vendor/composer/spdx-licenses/')
|
||||
->in(__DIR__.'/../../vendor/composer/semver/')
|
||||
->sort($finderSort)
|
||||
;
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
namespace Composer;
|
||||
|
||||
use Composer\Config\ConfigSourceInterface;
|
||||
use Composer\Plugin\PluginInterface;
|
||||
|
||||
/**
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
|
@ -59,7 +58,7 @@ class Config
|
|||
'type' => 'composer',
|
||||
'url' => 'https?://packagist.org',
|
||||
'allow_ssl_downgrade' => true,
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
private $config;
|
||||
|
@ -70,7 +69,7 @@ class Config
|
|||
private $useEnvironment;
|
||||
|
||||
/**
|
||||
* @param boolean $useEnvironment Use COMPOSER_ environment variables to replace config settings
|
||||
* @param bool $useEnvironment Use COMPOSER_ environment variables to replace config settings
|
||||
*/
|
||||
public function __construct($useEnvironment = true, $baseDir = null)
|
||||
{
|
||||
|
@ -183,7 +182,7 @@ class Config
|
|||
return $val;
|
||||
}
|
||||
|
||||
return ($flags & self::RELATIVE_PATHS == 1) ? $val : $this->realpath($val);
|
||||
return ($flags & self::RELATIVE_PATHS == self::RELATIVE_PATHS) ? $val : $this->realpath($val);
|
||||
|
||||
case 'cache-ttl':
|
||||
return (int) $this->config[$key];
|
||||
|
@ -334,8 +333,8 @@ class Config
|
|||
* This should be used to read COMPOSER_ environment variables
|
||||
* that overload config values.
|
||||
*
|
||||
* @param string $var
|
||||
* @return string|boolean
|
||||
* @param string $var
|
||||
* @return string|bool
|
||||
*/
|
||||
private function getComposerEnv($var)
|
||||
{
|
||||
|
|
|
@ -89,9 +89,10 @@ class Application extends BaseApplication
|
|||
{
|
||||
$this->io = new ConsoleIO($input, $output, $this->getHelperSet());
|
||||
ErrorHandler::register($this->io);
|
||||
$io = $this->getIO();
|
||||
|
||||
if (PHP_VERSION_ID < 50302) {
|
||||
$this->getIO()->writeError('<warning>Composer only officially supports PHP 5.3.2 and above, you will most likely encounter problems with your PHP '.PHP_VERSION.', upgrading is strongly recommended.</warning>');
|
||||
$io->writeError('<warning>Composer only officially supports PHP 5.3.2 and above, you will most likely encounter problems with your PHP '.PHP_VERSION.', upgrading is strongly recommended.</warning>');
|
||||
}
|
||||
|
||||
if (defined('COMPOSER_DEV_WARNING_TIME')) {
|
||||
|
@ -104,7 +105,7 @@ class Application extends BaseApplication
|
|||
}
|
||||
if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
|
||||
if (time() > COMPOSER_DEV_WARNING_TIME) {
|
||||
$this->getIO()->writeError(sprintf('<warning>Warning: This development build of composer is over 60 days old. It is recommended to update it by running "%s self-update" to get the latest version.</warning>', $_SERVER['PHP_SELF']));
|
||||
$io->writeError(sprintf('<warning>Warning: This development build of composer is over 60 days old. It is recommended to update it by running "%s self-update" to get the latest version.</warning>', $_SERVER['PHP_SELF']));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -117,8 +118,8 @@ class Application extends BaseApplication
|
|||
if ($newWorkDir = $this->getNewWorkingDir($input)) {
|
||||
$oldWorkingDir = getcwd();
|
||||
chdir($newWorkDir);
|
||||
if ($this->getIO()->isDebug() >= 4) {
|
||||
$this->getIO()->writeError('Changed CWD to ' . getcwd());
|
||||
if ($io->isDebug() >= 4) {
|
||||
$io->writeError('Changed CWD to ' . getcwd());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,7 +130,7 @@ class Application extends BaseApplication
|
|||
foreach ($composer['scripts'] as $script => $dummy) {
|
||||
if (!defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
|
||||
if ($this->has($script)) {
|
||||
$this->getIO()->writeError('<warning>A script named '.$script.' would override a native Composer function and has been skipped</warning>');
|
||||
$io->writeError('<warning>A script named '.$script.' would override a native Composer function and has been skipped</warning>');
|
||||
} else {
|
||||
$this->add(new Command\ScriptAliasCommand($script));
|
||||
}
|
||||
|
@ -150,7 +151,7 @@ class Application extends BaseApplication
|
|||
}
|
||||
|
||||
if (isset($startTime)) {
|
||||
$this->getIO()->writeError('<info>Memory usage: '.round(memory_get_usage() / 1024 / 1024, 2).'MB (peak: '.round(memory_get_peak_usage() / 1024 / 1024, 2).'MB), time: '.round(microtime(true) - $startTime, 2).'s');
|
||||
$io->writeError('<info>Memory usage: '.round(memory_get_usage() / 1024 / 1024, 2).'MB (peak: '.round(memory_get_peak_usage() / 1024 / 1024, 2).'MB), time: '.round(microtime(true) - $startTime, 2).'s');
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
@ -158,8 +159,8 @@ class Application extends BaseApplication
|
|||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @return string
|
||||
* @throws \RuntimeException
|
||||
* @return string
|
||||
*/
|
||||
private function getNewWorkingDir(InputInterface $input)
|
||||
{
|
||||
|
@ -176,30 +177,32 @@ class Application extends BaseApplication
|
|||
*/
|
||||
public function renderException($exception, $output)
|
||||
{
|
||||
$io = $this->getIO();
|
||||
|
||||
try {
|
||||
$composer = $this->getComposer(false, true);
|
||||
if ($composer) {
|
||||
$config = $composer->getConfig();
|
||||
|
||||
$minSpaceFree = 1024*1024;
|
||||
$minSpaceFree = 1024 * 1024;
|
||||
if ((($df = @disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
|
||||
|| (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
|
||||
|| (($df = @disk_free_space($dir = sys_get_temp_dir())) !== false && $df < $minSpaceFree)
|
||||
) {
|
||||
$this->getIO()->writeError('<error>The disk hosting '.$dir.' is full, this may be the cause of the following exception</error>');
|
||||
$io->writeError('<error>The disk hosting '.$dir.' is full, this may be the cause of the following exception</error>');
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
if (defined('PHP_WINDOWS_VERSION_BUILD') && false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) {
|
||||
$this->getIO()->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>');
|
||||
$this->getIO()->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#-the-system-cannot-find-the-path-specified-windows- for details</error>');
|
||||
$io->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>');
|
||||
$io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#-the-system-cannot-find-the-path-specified-windows- for details</error>');
|
||||
}
|
||||
|
||||
if (false !== strpos($exception->getMessage(), 'fork failed - Cannot allocate memory')) {
|
||||
$this->getIO()->writeError('<error>The following exception is caused by a lack of memory and not having swap configured</error>');
|
||||
$this->getIO()->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>');
|
||||
$io->writeError('<error>The following exception is caused by a lack of memory and not having swap configured</error>');
|
||||
$io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>');
|
||||
}
|
||||
|
||||
if ($output instanceof ConsoleOutputInterface) {
|
||||
|
@ -272,6 +275,7 @@ class Application extends BaseApplication
|
|||
$commands[] = new Command\SearchCommand();
|
||||
$commands[] = new Command\ValidateCommand();
|
||||
$commands[] = new Command\ShowCommand();
|
||||
$commands[] = new Command\SuggestsCommand();
|
||||
$commands[] = new Command\RequireCommand();
|
||||
$commands[] = new Command\DumpAutoloadCommand();
|
||||
$commands[] = new Command\StatusCommand();
|
||||
|
|
|
@ -27,7 +27,7 @@ class HtmlOutputFormatter extends OutputFormatter
|
|||
34 => 'blue',
|
||||
35 => 'magenta',
|
||||
36 => 'cyan',
|
||||
37 => 'white'
|
||||
37 => 'white',
|
||||
);
|
||||
private static $availableBackgroundColors = array(
|
||||
40 => 'black',
|
||||
|
@ -37,7 +37,7 @@ class HtmlOutputFormatter extends OutputFormatter
|
|||
44 => 'blue',
|
||||
45 => 'magenta',
|
||||
46 => 'cyan',
|
||||
47 => 'white'
|
||||
47 => 'white',
|
||||
);
|
||||
private static $availableOptions = array(
|
||||
1 => 'bold',
|
||||
|
@ -60,6 +60,7 @@ class HtmlOutputFormatter extends OutputFormatter
|
|||
$formatted = parent::format($message);
|
||||
|
||||
$clearEscapeCodes = '(?:39|49|0|22|24|25|27|28)';
|
||||
|
||||
return preg_replace_callback("{\033\[([0-9;]+)m(.*?)\033\[(?:".$clearEscapeCodes.";)*?".$clearEscapeCodes."m}s", array($this, 'formatHtml'), $formatted);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Composer\DependencyResolver;
|
|||
use Composer\Package\PackageInterface;
|
||||
use Composer\Package\AliasPackage;
|
||||
use Composer\Package\BasePackage;
|
||||
use Composer\Package\LinkConstraint\VersionConstraint;
|
||||
use Composer\Semver\Constraint\Constraint;
|
||||
|
||||
/**
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
|
@ -38,8 +38,8 @@ class DefaultPolicy implements PolicyInterface
|
|||
return BasePackage::$stabilities[$stabA] < BasePackage::$stabilities[$stabB];
|
||||
}
|
||||
|
||||
$constraint = new VersionConstraint($operator, $b->getVersion());
|
||||
$version = new VersionConstraint('==', $a->getVersion());
|
||||
$constraint = new Constraint($operator, $b->getVersion());
|
||||
$version = new Constraint('==', $a->getVersion());
|
||||
|
||||
return $constraint->matchSpecific($version, true);
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ class DefaultPolicy implements PolicyInterface
|
|||
foreach ($source->getReplaces() as $link) {
|
||||
if ($link->getTarget() === $target->getName()
|
||||
// && (null === $link->getConstraint() ||
|
||||
// $link->getConstraint()->matches(new VersionConstraint('==', $target->getVersion())))) {
|
||||
// $link->getConstraint()->matches(new Constraint('==', $target->getVersion())))) {
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
namespace Composer\DependencyResolver\Operation;
|
||||
|
||||
use Composer\Package\AliasPackage;
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
* Solver install operation.
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
namespace Composer\DependencyResolver\Operation;
|
||||
|
||||
use Composer\Package\AliasPackage;
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
* Solver install operation.
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
namespace Composer\DependencyResolver\Operation;
|
||||
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
|
@ -46,6 +45,6 @@ abstract class SolverOperation implements OperationInterface
|
|||
|
||||
protected function formatVersion(PackageInterface $package)
|
||||
{
|
||||
return VersionParser::formatVersion($package);
|
||||
return $package->getFullPrettyVersion();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,10 +14,10 @@ namespace Composer\DependencyResolver;
|
|||
|
||||
use Composer\Package\BasePackage;
|
||||
use Composer\Package\AliasPackage;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Package\LinkConstraint\LinkConstraintInterface;
|
||||
use Composer\Package\LinkConstraint\VersionConstraint;
|
||||
use Composer\Package\LinkConstraint\EmptyConstraint;
|
||||
use Composer\Semver\VersionParser;
|
||||
use Composer\Semver\Constraint\ConstraintInterface;
|
||||
use Composer\Semver\Constraint\Constraint;
|
||||
use Composer\Semver\Constraint\EmptyConstraint;
|
||||
use Composer\Repository\RepositoryInterface;
|
||||
use Composer\Repository\CompositeRepository;
|
||||
use Composer\Repository\ComposerRepository;
|
||||
|
@ -31,7 +31,7 @@ use Composer\Package\PackageInterface;
|
|||
* @author Nils Adermann <naderman@naderman.de>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
class Pool
|
||||
class Pool implements \Countable
|
||||
{
|
||||
const MATCH_NAME = -1;
|
||||
const MATCH_NONE = 0;
|
||||
|
@ -150,27 +150,35 @@ class Pool
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieves the package object for a given package id.
|
||||
*
|
||||
* @param int $id
|
||||
* @return PackageInterface
|
||||
*/
|
||||
* Retrieves the package object for a given package id.
|
||||
*
|
||||
* @param int $id
|
||||
* @return PackageInterface
|
||||
*/
|
||||
public function packageById($id)
|
||||
{
|
||||
return $this->packages[$id - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how many packages have been loaded into the pool
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->packages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches all packages providing the given package name and match the constraint
|
||||
*
|
||||
* @param string $name The package name to be searched for
|
||||
* @param LinkConstraintInterface $constraint A constraint that all returned
|
||||
* packages must match or null to return all
|
||||
* @param bool $mustMatchName Whether the name of returned packages
|
||||
* must match the given name
|
||||
* @return PackageInterface[] A set of packages
|
||||
* @param string $name The package name to be searched for
|
||||
* @param ConstraintInterface $constraint A constraint that all returned
|
||||
* packages must match or null to return all
|
||||
* @param bool $mustMatchName Whether the name of returned packages
|
||||
* must match the given name
|
||||
* @return PackageInterface[] A set of packages
|
||||
*/
|
||||
public function whatProvides($name, LinkConstraintInterface $constraint = null, $mustMatchName = false)
|
||||
public function whatProvides($name, ConstraintInterface $constraint = null, $mustMatchName = false)
|
||||
{
|
||||
$key = ((int) $mustMatchName).$constraint;
|
||||
if (isset($this->providerCache[$name][$key])) {
|
||||
|
@ -309,12 +317,12 @@ class Pool
|
|||
* Checks if the package matches the given constraint directly or through
|
||||
* provided or replaced packages
|
||||
*
|
||||
* @param array|PackageInterface $candidate
|
||||
* @param string $name Name of the package to be matched
|
||||
* @param LinkConstraintInterface $constraint The constraint to verify
|
||||
* @return int One of the MATCH* constants of this class or 0 if there is no match
|
||||
* @param array|PackageInterface $candidate
|
||||
* @param string $name Name of the package to be matched
|
||||
* @param ConstraintInterface $constraint The constraint to verify
|
||||
* @return int One of the MATCH* constants of this class or 0 if there is no match
|
||||
*/
|
||||
private function match($candidate, $name, LinkConstraintInterface $constraint = null)
|
||||
private function match($candidate, $name, ConstraintInterface $constraint = null)
|
||||
{
|
||||
$candidateName = $candidate->getName();
|
||||
$candidateVersion = $candidate->getVersion();
|
||||
|
@ -328,7 +336,7 @@ class Pool
|
|||
}
|
||||
|
||||
if ($candidateName === $name) {
|
||||
$pkgConstraint = new VersionConstraint('==', $candidateVersion);
|
||||
$pkgConstraint = new Constraint('==', $candidateVersion);
|
||||
|
||||
if ($constraint === null || $constraint->matches($pkgConstraint)) {
|
||||
return $requireFilter->matches($pkgConstraint) ? self::MATCH : self::MATCH_FILTERED;
|
||||
|
|
|
@ -47,7 +47,7 @@ class Problem
|
|||
*/
|
||||
public function addRule(Rule $rule)
|
||||
{
|
||||
$this->addReason($rule->getId(), array(
|
||||
$this->addReason(spl_object_hash($rule), array(
|
||||
'rule' => $rule,
|
||||
'job' => $rule->getJob(),
|
||||
));
|
||||
|
@ -87,8 +87,12 @@ class Problem
|
|||
}
|
||||
|
||||
if ($job && $job['cmd'] === 'install' && empty($packages)) {
|
||||
|
||||
// handle php/hhvm
|
||||
if ($job['packageName'] === 'php' || $job['packageName'] === 'php-64bit' || $job['packageName'] === 'hhvm') {
|
||||
$available = $this->pool->whatProvides($job['packageName']);
|
||||
$version = count($available) ? $available[0]->getPrettyVersion() : phpversion();
|
||||
|
||||
$msg = "\n - This package requires ".$job['packageName'].$this->constraintToText($job['constraint']).' but ';
|
||||
|
||||
if (defined('HHVM_VERSION')) {
|
||||
|
@ -97,7 +101,7 @@ class Problem
|
|||
return $msg . 'you are running this with PHP and not HHVM.';
|
||||
}
|
||||
|
||||
return $msg . 'your PHP version ('. phpversion().') does not satisfy that requirement.';
|
||||
return $msg . 'your PHP version ('. $version .') does not satisfy that requirement.';
|
||||
}
|
||||
|
||||
// handle php extensions
|
||||
|
@ -218,7 +222,7 @@ class Problem
|
|||
/**
|
||||
* Turns a constraint into text usable in a sentence describing a job
|
||||
*
|
||||
* @param \Composer\Package\LinkConstraint\LinkConstraintInterface $constraint
|
||||
* @param \Composer\Semver\Constraint\ConstraintInterface $constraint
|
||||
* @return string
|
||||
*/
|
||||
protected function constraintToText($constraint)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
namespace Composer\DependencyResolver;
|
||||
|
||||
use Composer\Package\LinkConstraint\LinkConstraintInterface;
|
||||
use Composer\Semver\Constraint\ConstraintInterface;
|
||||
|
||||
/**
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
|
@ -26,17 +26,17 @@ class Request
|
|||
$this->jobs = array();
|
||||
}
|
||||
|
||||
public function install($packageName, LinkConstraintInterface $constraint = null)
|
||||
public function install($packageName, ConstraintInterface $constraint = null)
|
||||
{
|
||||
$this->addJob($packageName, 'install', $constraint);
|
||||
}
|
||||
|
||||
public function update($packageName, LinkConstraintInterface $constraint = null)
|
||||
public function update($packageName, ConstraintInterface $constraint = null)
|
||||
{
|
||||
$this->addJob($packageName, 'update', $constraint);
|
||||
}
|
||||
|
||||
public function remove($packageName, LinkConstraintInterface $constraint = null)
|
||||
public function remove($packageName, ConstraintInterface $constraint = null)
|
||||
{
|
||||
$this->addJob($packageName, 'remove', $constraint);
|
||||
}
|
||||
|
@ -46,12 +46,12 @@ class Request
|
|||
*
|
||||
* These jobs will not be tempered with by the solver
|
||||
*/
|
||||
public function fix($packageName, LinkConstraintInterface $constraint = null)
|
||||
public function fix($packageName, ConstraintInterface $constraint = null)
|
||||
{
|
||||
$this->addJob($packageName, 'install', $constraint, true);
|
||||
}
|
||||
|
||||
protected function addJob($packageName, $cmd, LinkConstraintInterface $constraint = null, $fixed = false)
|
||||
protected function addJob($packageName, $cmd, ConstraintInterface $constraint = null, $fixed = false)
|
||||
{
|
||||
$packageName = strtolower($packageName);
|
||||
|
||||
|
@ -59,7 +59,7 @@ class Request
|
|||
'cmd' => $cmd,
|
||||
'packageName' => $packageName,
|
||||
'constraint' => $constraint,
|
||||
'fixed' => $fixed
|
||||
'fixed' => $fixed,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,63 +29,51 @@ class Rule
|
|||
const RULE_LEARNED = 12;
|
||||
const RULE_PACKAGE_ALIAS = 13;
|
||||
|
||||
const BITFIELD_TYPE = 0;
|
||||
const BITFIELD_REASON = 8;
|
||||
const BITFIELD_DISABLED = 16;
|
||||
|
||||
/**
|
||||
* READ-ONLY: The literals this rule consists of.
|
||||
* @var array
|
||||
*/
|
||||
public $literals;
|
||||
|
||||
protected $disabled;
|
||||
protected $type;
|
||||
protected $id;
|
||||
protected $reason;
|
||||
protected $bitfield;
|
||||
protected $reasonData;
|
||||
|
||||
protected $job;
|
||||
|
||||
protected $ruleHash;
|
||||
|
||||
public function __construct(array $literals, $reason, $reasonData, $job = null)
|
||||
{
|
||||
// sort all packages ascending by id
|
||||
sort($literals);
|
||||
|
||||
$this->literals = $literals;
|
||||
$this->reason = $reason;
|
||||
$this->reasonData = $reasonData;
|
||||
|
||||
$this->disabled = false;
|
||||
if ($job) {
|
||||
$this->job = $job;
|
||||
}
|
||||
|
||||
$this->job = $job;
|
||||
|
||||
$this->type = -1;
|
||||
|
||||
$this->ruleHash = substr(md5(implode(',', $this->literals)), 0, 5);
|
||||
$this->bitfield = (0 << self::BITFIELD_DISABLED) |
|
||||
($reason << self::BITFIELD_REASON) |
|
||||
(255 << self::BITFIELD_TYPE);
|
||||
}
|
||||
|
||||
public function getHash()
|
||||
{
|
||||
return $this->ruleHash;
|
||||
}
|
||||
$data = unpack('ihash', md5(implode(',', $this->literals), true));
|
||||
|
||||
public function setId($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
return $data['hash'];
|
||||
}
|
||||
|
||||
public function getJob()
|
||||
{
|
||||
return $this->job;
|
||||
return isset($this->job) ? $this->job : null;
|
||||
}
|
||||
|
||||
public function getReason()
|
||||
{
|
||||
return $this->reason;
|
||||
return ($this->bitfield & (255 << self::BITFIELD_REASON)) >> self::BITFIELD_REASON;
|
||||
}
|
||||
|
||||
public function getReasonData()
|
||||
|
@ -95,11 +83,11 @@ class Rule
|
|||
|
||||
public function getRequiredPackage()
|
||||
{
|
||||
if ($this->reason === self::RULE_JOB_INSTALL) {
|
||||
if ($this->getReason() === self::RULE_JOB_INSTALL) {
|
||||
return $this->reasonData;
|
||||
}
|
||||
|
||||
if ($this->reason === self::RULE_PACKAGE_REQUIRES) {
|
||||
if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
|
||||
return $this->reasonData->getTarget();
|
||||
}
|
||||
}
|
||||
|
@ -114,10 +102,6 @@ class Rule
|
|||
*/
|
||||
public function equals(Rule $rule)
|
||||
{
|
||||
if ($this->ruleHash !== $rule->ruleHash) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (count($this->literals) != count($rule->literals)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -133,32 +117,32 @@ class Rule
|
|||
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_TYPE)) | ((255 & $type) << self::BITFIELD_TYPE);
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
return ($this->bitfield & (255 << self::BITFIELD_TYPE)) >> self::BITFIELD_TYPE;
|
||||
}
|
||||
|
||||
public function disable()
|
||||
{
|
||||
$this->disabled = true;
|
||||
$this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_DISABLED)) | (1 << self::BITFIELD_DISABLED);
|
||||
}
|
||||
|
||||
public function enable()
|
||||
{
|
||||
$this->disabled = false;
|
||||
$this->bitfield = $this->bitfield & ~(255 << self::BITFIELD_DISABLED);
|
||||
}
|
||||
|
||||
public function isDisabled()
|
||||
{
|
||||
return $this->disabled;
|
||||
return (bool) (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
|
||||
}
|
||||
|
||||
public function isEnabled()
|
||||
{
|
||||
return !$this->disabled;
|
||||
return !(($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -184,7 +168,7 @@ class Rule
|
|||
$ruleText .= $pool->literalToPrettyString($literal, $installedMap);
|
||||
}
|
||||
|
||||
switch ($this->reason) {
|
||||
switch ($this->getReason()) {
|
||||
case self::RULE_INTERNAL_ALLOW_UPDATE:
|
||||
return $ruleText;
|
||||
|
||||
|
@ -216,16 +200,17 @@ class Rule
|
|||
} else {
|
||||
$targetName = $this->reasonData->getTarget();
|
||||
|
||||
// handle php extensions
|
||||
if ($targetName === 'php' || $targetName === 'php-64bit' || $targetName === 'hhvm') {
|
||||
// handle php/hhvm
|
||||
if (defined('HHVM_VERSION')) {
|
||||
$text .= ' -> your HHVM version does not satisfy that requirement.';
|
||||
} elseif ($targetName === 'hhvm') {
|
||||
$text .= ' -> you are running this with PHP and not HHVM.';
|
||||
} else {
|
||||
$text .= ' -> your PHP version ('. phpversion().') does not satisfy that requirement.';
|
||||
$text .= ' -> your PHP version ('. phpversion() .') or "config.platform.php" value does not satisfy that requirement.';
|
||||
}
|
||||
} elseif (0 === strpos($targetName, 'ext-')) {
|
||||
// handle php extensions
|
||||
$ext = substr($targetName, 4);
|
||||
$error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ class RuleSet implements \IteratorAggregate, \Countable
|
|||
public $ruleById;
|
||||
|
||||
protected static $types = array(
|
||||
-1 => 'UNKNOWN',
|
||||
255 => 'UNKNOWN',
|
||||
self::TYPE_PACKAGE => 'PACKAGE',
|
||||
self::TYPE_JOB => 'JOB',
|
||||
self::TYPE_LEARNED => 'LEARNED',
|
||||
|
@ -66,7 +66,6 @@ class RuleSet implements \IteratorAggregate, \Countable
|
|||
$this->ruleById[$this->nextRuleId] = $rule;
|
||||
$rule->setType($type);
|
||||
|
||||
$rule->setId($this->nextRuleId);
|
||||
$this->nextRuleId++;
|
||||
|
||||
$hash = $rule->getHash();
|
||||
|
@ -131,7 +130,7 @@ class RuleSet implements \IteratorAggregate, \Countable
|
|||
public function getTypes()
|
||||
{
|
||||
$types = self::$types;
|
||||
unset($types[-1]);
|
||||
unset($types[255]);
|
||||
|
||||
return array_keys($types);
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ class RuleWatchNode
|
|||
/**
|
||||
* Given one watched literal, this method returns the other watched literal
|
||||
*
|
||||
* @param int The watched literal that should not be returned
|
||||
* @param int $literal The watched literal that should not be returned
|
||||
* @return int A literal
|
||||
*/
|
||||
public function getOtherWatch($literal)
|
||||
|
|
|
@ -50,6 +50,11 @@ class Solver
|
|||
$this->ruleSetGenerator = new RuleSetGenerator($policy, $pool);
|
||||
}
|
||||
|
||||
public function getRuleSetSize()
|
||||
{
|
||||
return count($this->rules);
|
||||
}
|
||||
|
||||
// aka solver_makeruledecisions
|
||||
private function makeAssertionRuleDecisions()
|
||||
{
|
||||
|
@ -212,7 +217,7 @@ class Solver
|
|||
* Evaluates each term affected by the decision (linked through watches)
|
||||
* If we find unit rules we make new decisions based on them
|
||||
*
|
||||
* @param integer $level
|
||||
* @param int $level
|
||||
* @return Rule|null A rule on conflict, otherwise null.
|
||||
*/
|
||||
protected function propagate($level)
|
||||
|
@ -314,7 +319,7 @@ class Solver
|
|||
|
||||
$this->rules->add($newRule, RuleSet::TYPE_LEARNED);
|
||||
|
||||
$this->learnedWhy[$newRule->getId()] = $why;
|
||||
$this->learnedWhy[spl_object_hash($newRule)] = $why;
|
||||
|
||||
$ruleNode = new RuleWatchNode($newRule);
|
||||
$ruleNode->watch2OnHighest($this->decisions);
|
||||
|
@ -449,7 +454,7 @@ class Solver
|
|||
|
||||
private function analyzeUnsolvableRule($problem, $conflictRule)
|
||||
{
|
||||
$why = $conflictRule->getId();
|
||||
$why = spl_object_hash($conflictRule);
|
||||
|
||||
if ($conflictRule->getType() == RuleSet::TYPE_LEARNED) {
|
||||
$learnedWhy = $this->learnedWhy[$why];
|
||||
|
@ -567,7 +572,7 @@ class Solver
|
|||
private function enableDisableLearnedRules()
|
||||
{
|
||||
foreach ($this->rules->getIteratorFor(RuleSet::TYPE_LEARNED) as $rule) {
|
||||
$why = $this->learnedWhy[$rule->getId()];
|
||||
$why = $this->learnedWhy[spl_object_hash($rule)];
|
||||
$problemRules = $this->learnedPool[$why];
|
||||
|
||||
$foundDisabled = false;
|
||||
|
|
|
@ -32,7 +32,7 @@ class SolverProblemsException extends \RuntimeException
|
|||
{
|
||||
$text = "\n";
|
||||
foreach ($this->problems as $i => $problem) {
|
||||
$text .= " Problem ".($i+1).$problem->getPrettyString($this->installedMap)."\n";
|
||||
$text .= " Problem ".($i + 1).$problem->getPrettyString($this->installedMap)."\n";
|
||||
}
|
||||
|
||||
if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) {
|
||||
|
|
|
@ -77,7 +77,11 @@ abstract class ArchiveDownloader extends FileDownloader
|
|||
|
||||
// retry downloading if we have an invalid zip file
|
||||
if ($retries && $e instanceof \UnexpectedValueException && class_exists('ZipArchive') && $e->getCode() === \ZipArchive::ER_NOZIP) {
|
||||
$this->io->writeError(' Invalid zip file, retrying...');
|
||||
if ($this->io->isDebug()) {
|
||||
$this->io->writeError(' Invalid zip file ('.$e->getMessage().'), retrying...');
|
||||
} else {
|
||||
$this->io->writeError(' Invalid zip file, retrying...');
|
||||
}
|
||||
usleep(500000);
|
||||
continue;
|
||||
}
|
||||
|
@ -115,7 +119,7 @@ abstract class ArchiveDownloader extends FileDownloader
|
|||
// update api archives to the proper reference
|
||||
$url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $package->getDistReference();
|
||||
}
|
||||
} else if ($package->getDistReference() && strpos($url, 'bitbucket.org')) {
|
||||
} elseif ($package->getDistReference() && strpos($url, 'bitbucket.org')) {
|
||||
if (preg_match('{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i', $url, $match)) {
|
||||
// update Bitbucket archives to the proper reference
|
||||
$url = 'https://bitbucket.org/' . $match[1] . '/'. $match[2] . '/get/' . $package->getDistReference() . '.' . $match[4];
|
||||
|
|
|
@ -103,10 +103,9 @@ class DownloadManager
|
|||
/**
|
||||
* Returns downloader for a specific installation type.
|
||||
*
|
||||
* @param string $type installation type
|
||||
* @return DownloaderInterface
|
||||
*
|
||||
* @param string $type installation type
|
||||
* @throws \InvalidArgumentException if downloader for provided type is not registered
|
||||
* @return DownloaderInterface
|
||||
*/
|
||||
public function getDownloader($type)
|
||||
{
|
||||
|
@ -121,12 +120,11 @@ class DownloadManager
|
|||
/**
|
||||
* Returns downloader for already installed package.
|
||||
*
|
||||
* @param PackageInterface $package package instance
|
||||
* @return DownloaderInterface|null
|
||||
*
|
||||
* @param PackageInterface $package package instance
|
||||
* @throws \InvalidArgumentException if package has no installation source specified
|
||||
* @throws \LogicException if specific downloader used to load package with
|
||||
* wrong type
|
||||
* wrong type
|
||||
* @return DownloaderInterface|null
|
||||
*/
|
||||
public function getDownloaderForInstalledPackage(PackageInterface $package)
|
||||
{
|
||||
|
|
|
@ -16,7 +16,6 @@ use Composer\Config;
|
|||
use Composer\Cache;
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Plugin\PluginEvents;
|
||||
use Composer\Plugin\PreFileDownloadEvent;
|
||||
use Composer\EventDispatcher\EventDispatcher;
|
||||
|
@ -81,7 +80,7 @@ class FileDownloader implements DownloaderInterface
|
|||
throw new \InvalidArgumentException('The given package is missing url information');
|
||||
}
|
||||
|
||||
$this->io->writeError(" - Installing <info>" . $package->getName() . "</info> (<comment>" . VersionParser::formatVersion($package) . "</comment>)");
|
||||
$this->io->writeError(" - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
|
||||
|
||||
$urls = $package->getDistUrls();
|
||||
while ($url = array_shift($urls)) {
|
||||
|
@ -138,7 +137,7 @@ class FileDownloader implements DownloaderInterface
|
|||
break;
|
||||
} catch (TransportException $e) {
|
||||
// if we got an http response with a proper code, then requesting again will probably not help, abort
|
||||
if ((0 !== $e->getCode() && !in_array($e->getCode(),array(500, 502, 503, 504))) || !$retries) {
|
||||
if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) {
|
||||
throw $e;
|
||||
}
|
||||
if ($this->io->isVerbose()) {
|
||||
|
@ -205,7 +204,7 @@ class FileDownloader implements DownloaderInterface
|
|||
*/
|
||||
public function remove(PackageInterface $package, $path)
|
||||
{
|
||||
$this->io->writeError(" - Removing <info>" . $package->getName() . "</info> (<comment>" . VersionParser::formatVersion($package) . "</comment>)");
|
||||
$this->io->writeError(" - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
|
||||
if (!$this->filesystem->removeDirectory($path)) {
|
||||
throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
|
||||
}
|
||||
|
@ -226,11 +225,10 @@ class FileDownloader implements DownloaderInterface
|
|||
/**
|
||||
* Process the download url
|
||||
*
|
||||
* @param PackageInterface $package package the url is coming from
|
||||
* @param string $url download url
|
||||
* @return string url
|
||||
*
|
||||
* @param PackageInterface $package package the url is coming from
|
||||
* @param string $url download url
|
||||
* @throws \RuntimeException If any problem with the url
|
||||
* @return string url
|
||||
*/
|
||||
protected function processUrl(PackageInterface $package, $url)
|
||||
{
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
namespace Composer\Downloader;
|
||||
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\Util\GitHub;
|
||||
use Composer\Util\Git as GitUtil;
|
||||
use Composer\Util\ProcessExecutor;
|
||||
use Composer\IO\IOInterface;
|
||||
|
@ -82,7 +81,7 @@ class GitDownloader extends VcsDownloader
|
|||
$command = 'git remote set-url composer %s && git fetch composer && git fetch --tags composer';
|
||||
|
||||
$commandCallable = function ($url) use ($command) {
|
||||
return sprintf($command, ProcessExecutor::escape ($url));
|
||||
return sprintf($command, ProcessExecutor::escape($url));
|
||||
};
|
||||
|
||||
$this->gitUtil->runCommand($commandCallable, $url, $path);
|
||||
|
@ -150,7 +149,7 @@ class GitDownloader extends VcsDownloader
|
|||
}
|
||||
|
||||
while (true) {
|
||||
switch ($this->io->ask(' <info>Discard changes [y,n,v,'.($update ? 's,' : '').'?]?</info> ', '?')) {
|
||||
switch ($this->io->ask(' <info>Discard changes [y,n,v,d,'.($update ? 's,' : '').'?]?</info> ', '?')) {
|
||||
case 'y':
|
||||
$this->discardChanges($path);
|
||||
break 2;
|
||||
|
@ -170,6 +169,10 @@ class GitDownloader extends VcsDownloader
|
|||
$this->io->writeError($changes);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
$this->viewDiff($path);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
default:
|
||||
help:
|
||||
|
@ -177,6 +180,7 @@ class GitDownloader extends VcsDownloader
|
|||
' y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
|
||||
' n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
|
||||
' v - view modified files',
|
||||
' d - view local modifications (diff)',
|
||||
));
|
||||
if ($update) {
|
||||
$this->io->writeError(' s - stash changes and try to reapply them after the update');
|
||||
|
@ -205,13 +209,12 @@ class GitDownloader extends VcsDownloader
|
|||
/**
|
||||
* Updates the given path to the given commit ref
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $reference
|
||||
* @param string $branch
|
||||
* @param \DateTime $date
|
||||
* @return null|string if a string is returned, it is the commit reference that was checked out if the original could not be found
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $reference
|
||||
* @param string $branch
|
||||
* @param \DateTime $date
|
||||
* @throws \RuntimeException
|
||||
* @return null|string if a string is returned, it is the commit reference that was checked out if the original could not be found
|
||||
*/
|
||||
protected function updateToCommit($path, $reference, $branch, $date)
|
||||
{
|
||||
|
@ -327,6 +330,20 @@ class GitDownloader extends VcsDownloader
|
|||
$this->hasStashedChanges = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function viewDiff($path)
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
if (0 !== $this->process->execute('git diff HEAD', $output, $path)) {
|
||||
throw new \RuntimeException("Could not view diff\n\n:".$this->process->getErrorOutput());
|
||||
}
|
||||
|
||||
$this->io->writeError($output);
|
||||
}
|
||||
|
||||
protected function normalizePath($path)
|
||||
{
|
||||
if (defined('PHP_WINDOWS_VERSION_MAJOR') && strlen($path) > 0) {
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
<?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\Downloader;
|
||||
|
||||
use Composer\Package\PackageInterface;
|
||||
use Symfony\Component\Filesystem\Exception\IOException;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
/**
|
||||
* Download a package from a local path.
|
||||
*
|
||||
* @author Samuel Roze <samuel.roze@gmail.com>
|
||||
* @author Johann Reinke <johann.reinke@gmail.com>
|
||||
*/
|
||||
class PathDownloader extends FileDownloader
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function download(PackageInterface $package, $path)
|
||||
{
|
||||
$fileSystem = new Filesystem();
|
||||
$this->filesystem->removeDirectory($path);
|
||||
|
||||
$this->io->writeError(sprintf(
|
||||
' - Installing <info>%s</info> (<comment>%s</comment>)',
|
||||
$package->getName(),
|
||||
$package->getFullPrettyVersion()
|
||||
));
|
||||
|
||||
$url = $package->getDistUrl();
|
||||
$realUrl = realpath($url);
|
||||
if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) {
|
||||
throw new \RuntimeException(sprintf(
|
||||
'Path "%s" is not found',
|
||||
$url
|
||||
));
|
||||
}
|
||||
|
||||
try {
|
||||
$shortestPath = $this->filesystem->findShortestPath($path, $realUrl);
|
||||
$fileSystem->symlink($shortestPath, $path);
|
||||
$this->io->writeError(sprintf(' Symlinked from %s', $url));
|
||||
} catch (IOException $e) {
|
||||
$fileSystem->mirror($realUrl, $path);
|
||||
$this->io->writeError(sprintf(' Mirrored from %s', $url));
|
||||
}
|
||||
|
||||
$this->io->writeError('');
|
||||
}
|
||||
}
|
|
@ -48,7 +48,6 @@ class PearPackageExtractor
|
|||
* @param array $vars used for replacement tasks
|
||||
* @throws \RuntimeException
|
||||
* @throws \UnexpectedValueException
|
||||
*
|
||||
*/
|
||||
public function extractTo($target, array $roles = array('php' => '/', 'script' => '/bin'), $vars = array())
|
||||
{
|
||||
|
@ -130,9 +129,9 @@ class PearPackageExtractor
|
|||
* @param string $source string path to extracted files
|
||||
* @param array $roles array [role => roleRoot] relative root for files having that role
|
||||
* @param array $vars list of values can be used for replacement tasks
|
||||
* @throws \RuntimeException
|
||||
* @return array array of 'source' => 'target', where source is location of file in the tarball (relative to source
|
||||
* path, and target is destination of file (also relative to $source path)
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
private function buildCopyActions($source, array $roles, $vars)
|
||||
{
|
||||
|
|
|
@ -43,7 +43,7 @@ class PerforceDownloader extends VcsDownloader
|
|||
|
||||
private function getLabelFromSourceReference($ref)
|
||||
{
|
||||
$pos = strpos($ref,'@');
|
||||
$pos = strpos($ref, '@');
|
||||
if (false !== $pos) {
|
||||
return substr($ref, $pos + 1);
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ class SvnDownloader extends VcsDownloader
|
|||
*/
|
||||
protected function getCommitLogs($fromReference, $toReference, $path)
|
||||
{
|
||||
if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference) ) {
|
||||
if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference)) {
|
||||
// strip paths from references and only keep the actual revision
|
||||
$fromRevision = preg_replace('{.*@(\d+)$}', '$1', $fromReference);
|
||||
$toRevision = preg_replace('{.*@(\d+)$}', '$1', $toReference);
|
||||
|
|
|
@ -14,7 +14,6 @@ namespace Composer\Downloader;
|
|||
|
||||
use Composer\Config;
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Util\ProcessExecutor;
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\Util\Filesystem;
|
||||
|
@ -54,7 +53,7 @@ abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterfa
|
|||
throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information');
|
||||
}
|
||||
|
||||
$this->io->writeError(" - Installing <info>" . $package->getName() . "</info> (<comment>" . VersionParser::formatVersion($package) . "</comment>)");
|
||||
$this->io->writeError(" - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
|
||||
$this->filesystem->emptyDirectory($path);
|
||||
|
||||
$urls = $package->getSourceUrls();
|
||||
|
@ -100,8 +99,8 @@ abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterfa
|
|||
}
|
||||
$name .= ' '.$initial->getPrettyVersion();
|
||||
} else {
|
||||
$from = VersionParser::formatVersion($initial);
|
||||
$to = VersionParser::formatVersion($target);
|
||||
$from = $initial->getFullPrettyVersion();
|
||||
$to = $target->getFullPrettyVersion();
|
||||
}
|
||||
|
||||
$this->io->writeError(" - Updating <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>)");
|
||||
|
|
|
@ -35,7 +35,7 @@ class Event
|
|||
protected $flags;
|
||||
|
||||
/**
|
||||
* @var boolean Whether the event should not be passed to more listeners
|
||||
* @var bool Whether the event should not be passed to more listeners
|
||||
*/
|
||||
private $propagationStopped = false;
|
||||
|
||||
|
@ -86,7 +86,7 @@ class Event
|
|||
/**
|
||||
* Checks if stopPropagation has been called
|
||||
*
|
||||
* @return boolean Whether propagation has been stopped
|
||||
* @return bool Whether propagation has been stopped
|
||||
*/
|
||||
public function isPropagationStopped()
|
||||
{
|
||||
|
|
|
@ -21,6 +21,7 @@ use Composer\Composer;
|
|||
use Composer\DependencyResolver\Operation\OperationInterface;
|
||||
use Composer\Repository\CompositeRepository;
|
||||
use Composer\Script;
|
||||
use Composer\Script\CommandEvent;
|
||||
use Composer\Script\PackageEvent;
|
||||
use Composer\Util\ProcessExecutor;
|
||||
|
||||
|
@ -135,10 +136,10 @@ class EventDispatcher
|
|||
*
|
||||
* @param Event $event The event object to pass to the event handlers/listeners.
|
||||
* @param string $additionalArgs
|
||||
* @return int return code of the executed script if any, for php scripts a false return
|
||||
* value is changed to 1, anything else to 0
|
||||
* @throws \RuntimeException
|
||||
* @throws \Exception
|
||||
* @return int return code of the executed script if any, for php scripts a false return
|
||||
* value is changed to 1, anything else to 0
|
||||
*/
|
||||
protected function doDispatch(Event $event)
|
||||
{
|
||||
|
@ -170,8 +171,14 @@ class EventDispatcher
|
|||
throw $e;
|
||||
}
|
||||
} else {
|
||||
$args = implode(' ', array_map(array('Composer\Util\ProcessExecutor','escape'), $event->getArguments()));
|
||||
if (0 !== ($exitCode = $this->process->execute($callable . ($args === '' ? '' : ' '.$args)))) {
|
||||
$args = implode(' ', array_map(array('Composer\Util\ProcessExecutor', 'escape'), $event->getArguments()));
|
||||
$exec = $callable . ($args === '' ? '' : ' '.$args);
|
||||
if ($this->io->isVerbose()) {
|
||||
$this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec));
|
||||
} else {
|
||||
$this->io->writeError(sprintf('> %s', $exec));
|
||||
}
|
||||
if (0 !== ($exitCode = $this->process->execute($exec))) {
|
||||
$this->io->writeError(sprintf('<error>Script %s handling the %s event returned with an error</error>', $callable, $event->getName()));
|
||||
|
||||
throw new \RuntimeException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
|
||||
|
@ -195,12 +202,18 @@ class EventDispatcher
|
|||
{
|
||||
$event = $this->checkListenerExpectedEvent(array($className, $methodName), $event);
|
||||
|
||||
if ($this->io->isVerbose()) {
|
||||
$this->io->writeError(sprintf('> %s: %s::%s', $event->getName(), $className, $methodName));
|
||||
} else {
|
||||
$this->io->writeError(sprintf('> %s::%s', $className, $methodName));
|
||||
}
|
||||
|
||||
return $className::$methodName($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $target
|
||||
* @param Event $event
|
||||
* @param mixed $target
|
||||
* @param Event $event
|
||||
* @return Event|CommandEvent
|
||||
*/
|
||||
protected function checkListenerExpectedEvent($target, Event $event)
|
||||
|
@ -247,7 +260,7 @@ class EventDispatcher
|
|||
*
|
||||
* @param string $eventName The event name - typically a constant
|
||||
* @param Callable $listener A callable expecting an event argument
|
||||
* @param integer $priority A higher value represents a higher priority
|
||||
* @param int $priority A higher value represents a higher priority
|
||||
*/
|
||||
protected function addListener($eventName, $listener, $priority = 0)
|
||||
{
|
||||
|
@ -300,8 +313,8 @@ class EventDispatcher
|
|||
/**
|
||||
* Checks if an event has listeners registered
|
||||
*
|
||||
* @param Event $event
|
||||
* @return boolean
|
||||
* @param Event $event
|
||||
* @return bool
|
||||
*/
|
||||
public function hasEventListeners(Event $event)
|
||||
{
|
||||
|
@ -342,8 +355,8 @@ class EventDispatcher
|
|||
/**
|
||||
* Checks if string given references a class path and method
|
||||
*
|
||||
* @param string $callable
|
||||
* @return boolean
|
||||
* @param string $callable
|
||||
* @return bool
|
||||
*/
|
||||
protected function isPhpScript($callable)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@ use Composer\Config\JsonConfigSource;
|
|||
use Composer\Json\JsonFile;
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\Package\Archiver;
|
||||
use Composer\Package\Version\VersionGuesser;
|
||||
use Composer\Repository\RepositoryManager;
|
||||
use Composer\Repository\WritableRepositoryInterface;
|
||||
use Composer\Util\ProcessExecutor;
|
||||
|
@ -23,7 +24,7 @@ use Composer\Util\RemoteFilesystem;
|
|||
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
|
||||
use Composer\EventDispatcher\EventDispatcher;
|
||||
use Composer\Autoload\AutoloadGenerator;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Semver\VersionParser;
|
||||
|
||||
/**
|
||||
* Creates a configured instance of composer.
|
||||
|
@ -373,7 +374,8 @@ class Factory
|
|||
|
||||
// load package
|
||||
$parser = new VersionParser;
|
||||
$loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, new ProcessExecutor($io));
|
||||
$guesser = new VersionGuesser($config, new ProcessExecutor($io), $parser);
|
||||
$loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser);
|
||||
$package = $loader->load($localConfig);
|
||||
$composer->setPackage($package);
|
||||
|
||||
|
@ -415,7 +417,7 @@ class Factory
|
|||
$lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION)
|
||||
? substr($composerFile, 0, -4).'lock'
|
||||
: $composerFile . '.lock';
|
||||
$locker = new Package\Locker($io, new JsonFile($lockFile, new RemoteFilesystem($io, $config)), $rm, $im, md5_file($composerFile));
|
||||
$locker = new Package\Locker($io, new JsonFile($lockFile, new RemoteFilesystem($io, $config)), $rm, $im, file_get_contents($composerFile));
|
||||
$composer->setLocker($locker);
|
||||
}
|
||||
|
||||
|
@ -440,6 +442,7 @@ class Factory
|
|||
$rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository');
|
||||
$rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository');
|
||||
$rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository');
|
||||
$rm->setRepositoryClass('path', 'Composer\Repository\PathRepository');
|
||||
|
||||
return $rm;
|
||||
}
|
||||
|
@ -512,6 +515,7 @@ class Factory
|
|||
$dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $eventDispatcher, $cache));
|
||||
$dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache));
|
||||
$dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache));
|
||||
$dm->setDownloader('path', new Downloader\PathDownloader($io, $config, $eventDispatcher, $cache));
|
||||
|
||||
return $dm;
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ use Symfony\Component\Console\Helper\HelperSet;
|
|||
class BufferIO extends ConsoleIO
|
||||
{
|
||||
/**
|
||||
* @param string $input
|
||||
* @param int $verbosity
|
||||
* @param string $input
|
||||
* @param int $verbosity
|
||||
* @param OutputFormatterInterface $formatter
|
||||
*/
|
||||
public function __construct(
|
||||
|
|
|
@ -18,7 +18,6 @@ use Symfony\Component\Console\Output\OutputInterface;
|
|||
use Symfony\Component\Console\Helper\HelperSet;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Symfony\Component\Process\ExecutableFinder;
|
||||
|
||||
/**
|
||||
* The Input/Output helper.
|
||||
|
@ -112,8 +111,8 @@ class ConsoleIO extends BaseIO
|
|||
|
||||
/**
|
||||
* @param array $messages
|
||||
* @param boolean $newline
|
||||
* @param boolean $stderr
|
||||
* @param bool $newline
|
||||
* @param bool $stderr
|
||||
*/
|
||||
private function doWrite($messages, $newline, $stderr)
|
||||
{
|
||||
|
@ -154,9 +153,9 @@ class ConsoleIO extends BaseIO
|
|||
|
||||
/**
|
||||
* @param array $messages
|
||||
* @param boolean $newline
|
||||
* @param integer $size
|
||||
* @param boolean $stderr
|
||||
* @param bool $newline
|
||||
* @param int $size
|
||||
* @param bool $stderr
|
||||
*/
|
||||
private function doOverwrite($messages, $newline, $size, $stderr)
|
||||
{
|
||||
|
|
|
@ -77,7 +77,7 @@ interface IOInterface
|
|||
*
|
||||
* @param string|array $messages The message as an array of lines or a single string
|
||||
* @param bool $newline Whether to add a newline or not
|
||||
* @param integer $size The size of line
|
||||
* @param int $size The size of line
|
||||
*/
|
||||
public function overwrite($messages, $newline = true, $size = null);
|
||||
|
||||
|
@ -86,7 +86,7 @@ interface IOInterface
|
|||
*
|
||||
* @param string|array $messages The message as an array of lines or a single string
|
||||
* @param bool $newline Whether to add a newline or not
|
||||
* @param integer $size The size of line
|
||||
* @param int $size The size of line
|
||||
*/
|
||||
public function overwriteError($messages, $newline = true, $size = null);
|
||||
|
||||
|
@ -96,9 +96,8 @@ interface IOInterface
|
|||
* @param string|array $question The question to ask
|
||||
* @param string $default The default answer if none is given by the user
|
||||
*
|
||||
* @return string The user answer
|
||||
*
|
||||
* @throws \RuntimeException If there is no data to read in the input stream
|
||||
* @return string The user answer
|
||||
*/
|
||||
public function ask($question, $default = null);
|
||||
|
||||
|
@ -123,12 +122,11 @@ interface IOInterface
|
|||
*
|
||||
* @param string|array $question The question to ask
|
||||
* @param callback $validator A PHP callback
|
||||
* @param null|integer $attempts Max number of times to ask before giving up (default of null means infinite)
|
||||
* @param null|int $attempts Max number of times to ask before giving up (default of null means infinite)
|
||||
* @param string $default The default answer if none is given by the user
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Exception When any of the validators return an error
|
||||
* @return mixed
|
||||
*/
|
||||
public function askAndValidate($question, $validator, $attempts = null, $default = null);
|
||||
|
||||
|
@ -153,7 +151,7 @@ interface IOInterface
|
|||
*
|
||||
* @param string $repositoryName The unique name of repository
|
||||
*
|
||||
* @return boolean
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAuthentication($repositoryName);
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ use Composer\DependencyResolver\Operation\UpdateOperation;
|
|||
use Composer\DependencyResolver\Operation\InstallOperation;
|
||||
use Composer\DependencyResolver\Operation\UninstallOperation;
|
||||
use Composer\DependencyResolver\Operation\OperationInterface;
|
||||
use Composer\DependencyResolver\PolicyInterface;
|
||||
use Composer\DependencyResolver\Pool;
|
||||
use Composer\DependencyResolver\Request;
|
||||
use Composer\DependencyResolver\Rule;
|
||||
|
@ -33,7 +34,7 @@ use Composer\Json\JsonFile;
|
|||
use Composer\Package\AliasPackage;
|
||||
use Composer\Package\CompletePackage;
|
||||
use Composer\Package\Link;
|
||||
use Composer\Package\LinkConstraint\VersionConstraint;
|
||||
use Composer\Semver\Constraint\Constraint;
|
||||
use Composer\Package\Locker;
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\Package\RootPackageInterface;
|
||||
|
@ -43,6 +44,7 @@ use Composer\Repository\InstalledFilesystemRepository;
|
|||
use Composer\Repository\PlatformRepository;
|
||||
use Composer\Repository\RepositoryInterface;
|
||||
use Composer\Repository\RepositoryManager;
|
||||
use Composer\Repository\WritableRepositoryInterface;
|
||||
use Composer\Script\ScriptEvents;
|
||||
|
||||
/**
|
||||
|
@ -101,6 +103,7 @@ class Installer
|
|||
protected $preferSource = false;
|
||||
protected $preferDist = false;
|
||||
protected $optimizeAutoloader = false;
|
||||
protected $classMapAuthoritative = false;
|
||||
protected $devMode = false;
|
||||
protected $dryRun = false;
|
||||
protected $verbose = false;
|
||||
|
@ -157,9 +160,8 @@ class Installer
|
|||
/**
|
||||
* Run installation (or update)
|
||||
*
|
||||
* @return int 0 on success or a positive error code on failure
|
||||
*
|
||||
* @throws \Exception
|
||||
* @return int 0 on success or a positive error code on failure
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
|
@ -333,6 +335,7 @@ class Installer
|
|||
}
|
||||
|
||||
$this->autoloadGenerator->setDevMode($this->devMode);
|
||||
$this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative);
|
||||
$this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader);
|
||||
}
|
||||
|
||||
|
@ -344,13 +347,23 @@ class Installer
|
|||
|
||||
$vendorDir = $this->config->get('vendor-dir');
|
||||
if (is_dir($vendorDir)) {
|
||||
touch($vendorDir);
|
||||
// suppress errors as this fails sometimes on OSX for no apparent reason
|
||||
// see https://github.com/composer/composer/issues/4070#issuecomment-129792748
|
||||
@touch($vendorDir);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RepositoryInterface $localRepo
|
||||
* @param RepositoryInterface $installedRepo
|
||||
* @param PlatformRepository $platformRepo
|
||||
* @param array $aliases
|
||||
* @param bool $withDevReqs
|
||||
* @return int
|
||||
*/
|
||||
protected function doInstall($localRepo, $installedRepo, $platformRepo, $aliases, $withDevReqs)
|
||||
{
|
||||
// init vars
|
||||
|
@ -414,7 +427,7 @@ class Installer
|
|||
&& $this->installationManager->isPackageInstalled($localRepo, $package)
|
||||
) {
|
||||
$removedUnstablePackages[$package->getName()] = true;
|
||||
$request->remove($package->getName(), new VersionConstraint('=', $package->getVersion()));
|
||||
$request->remove($package->getName(), new Constraint('=', $package->getVersion()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -453,7 +466,7 @@ class Installer
|
|||
foreach ($currentPackages as $curPackage) {
|
||||
if ($curPackage->getName() === $candidate) {
|
||||
if (!$this->isUpdateable($curPackage) && !isset($removedUnstablePackages[$curPackage->getName()])) {
|
||||
$constraint = new VersionConstraint('=', $curPackage->getVersion());
|
||||
$constraint = new Constraint('=', $curPackage->getVersion());
|
||||
$request->install($curPackage->getName(), $constraint);
|
||||
}
|
||||
break;
|
||||
|
@ -473,7 +486,7 @@ class Installer
|
|||
if (isset($aliases[$package->getName()][$version])) {
|
||||
$version = $aliases[$package->getName()][$version]['alias_normalized'];
|
||||
}
|
||||
$constraint = new VersionConstraint('=', $version);
|
||||
$constraint = new Constraint('=', $version);
|
||||
$constraint->setPrettyString($package->getPrettyVersion());
|
||||
$request->install($package->getName(), $constraint);
|
||||
}
|
||||
|
@ -511,6 +524,11 @@ class Installer
|
|||
return max(1, $e->getCode());
|
||||
}
|
||||
|
||||
if ($this->io->isVerbose()) {
|
||||
$this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies");
|
||||
$this->io->writeError("Analyzed ".$solver->getRuleSetSize()." rules to resolve dependencies");
|
||||
}
|
||||
|
||||
// force dev packages to be updated if we update or install from a (potentially new) lock
|
||||
$operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $installFromLock, $withDevReqs, 'force-updates', $operations);
|
||||
|
||||
|
@ -552,7 +570,8 @@ class Installer
|
|||
if ('update' === $operation->getJobType()
|
||||
&& $operation->getTargetPackage()->isDev()
|
||||
&& $operation->getTargetPackage()->getVersion() === $operation->getInitialPackage()->getVersion()
|
||||
&& $operation->getTargetPackage()->getSourceReference() === $operation->getInitialPackage()->getSourceReference()
|
||||
&& (!$operation->getTargetPackage()->getSourceReference() || $operation->getTargetPackage()->getSourceReference() === $operation->getInitialPackage()->getSourceReference())
|
||||
&& (!$operation->getTargetPackage()->getDistReference() || $operation->getTargetPackage()->getDistReference() === $operation->getInitialPackage()->getDistReference())
|
||||
) {
|
||||
if ($this->io->isDebug()) {
|
||||
$this->io->writeError(' - Skipping update of '. $operation->getTargetPackage()->getPrettyName().' to the same reference-locked version');
|
||||
|
@ -608,7 +627,7 @@ class Installer
|
|||
|
||||
if (!$this->dryRun) {
|
||||
// force source/dist urls to be updated for all packages
|
||||
$operations = $this->processPackageUrls($pool, $policy, $localRepo, $repositories);
|
||||
$this->processPackageUrls($pool, $policy, $localRepo, $repositories);
|
||||
$localRepo->write();
|
||||
}
|
||||
|
||||
|
@ -679,6 +698,11 @@ class Installer
|
|||
return array_merge($uninstOps, $operations);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $withDevReqs
|
||||
* @param RepositoryInterface|null $lockedRepository
|
||||
* @return Pool
|
||||
*/
|
||||
private function createPool($withDevReqs, RepositoryInterface $lockedRepository = null)
|
||||
{
|
||||
if (!$this->update && $this->locker->isLocked()) { // install from lock
|
||||
|
@ -687,7 +711,7 @@ class Installer
|
|||
|
||||
$requires = array();
|
||||
foreach ($lockedRepository->getPackages() as $package) {
|
||||
$constraint = new VersionConstraint('=', $package->getVersion());
|
||||
$constraint = new Constraint('=', $package->getVersion());
|
||||
$constraint->setPrettyString($package->getPrettyVersion());
|
||||
$requires[$package->getName()] = $constraint;
|
||||
}
|
||||
|
@ -717,6 +741,9 @@ class Installer
|
|||
return new Pool($minimumStability, $stabilityFlags, $rootConstraints);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DefaultPolicy
|
||||
*/
|
||||
private function createPolicy()
|
||||
{
|
||||
$preferStable = null;
|
||||
|
@ -737,11 +764,16 @@ class Installer
|
|||
return new DefaultPolicy($preferStable, $preferLowest);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RootPackageInterface $rootPackage
|
||||
* @param PlatformRepository $platformRepo
|
||||
* @return Request
|
||||
*/
|
||||
private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo)
|
||||
{
|
||||
$request = new Request();
|
||||
|
||||
$constraint = new VersionConstraint('=', $rootPackage->getVersion());
|
||||
$constraint = new Constraint('=', $rootPackage->getVersion());
|
||||
$constraint->setPrettyString($rootPackage->getPrettyVersion());
|
||||
$request->install($rootPackage->getName(), $constraint);
|
||||
|
||||
|
@ -755,7 +787,7 @@ class Installer
|
|||
// to prevent the solver trying to remove or update those
|
||||
$provided = $rootPackage->getProvides();
|
||||
foreach ($fixedPackages as $package) {
|
||||
$constraint = new VersionConstraint('=', $package->getVersion());
|
||||
$constraint = new Constraint('=', $package->getVersion());
|
||||
$constraint->setPrettyString($package->getPrettyVersion());
|
||||
|
||||
// skip platform packages that are provided by the root package
|
||||
|
@ -770,6 +802,19 @@ class Installer
|
|||
return $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WritableRepositoryInterface $localRepo
|
||||
* @param Pool $pool
|
||||
* @param PolicyInterface $policy
|
||||
* @param array $repositories
|
||||
* @param RepositoryInterface $installedRepo
|
||||
* @param RepositoryInterface $lockedRepository
|
||||
* @param bool $installFromLock
|
||||
* @param bool $withDevReqs
|
||||
* @param string $task
|
||||
* @param array|null $operations
|
||||
* @return array
|
||||
*/
|
||||
private function processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $installFromLock, $withDevReqs, $task, array $operations = null)
|
||||
{
|
||||
if ($task === 'force-updates' && null === $operations) {
|
||||
|
@ -847,7 +892,7 @@ class Installer
|
|||
}
|
||||
|
||||
// find similar packages (name/version) in all repositories
|
||||
$matches = $pool->whatProvides($package->getName(), new VersionConstraint('=', $package->getVersion()));
|
||||
$matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
|
||||
foreach ($matches as $index => $match) {
|
||||
// skip local packages
|
||||
if (!in_array($match->getRepository(), $repositories, true)) {
|
||||
|
@ -902,6 +947,9 @@ class Installer
|
|||
|
||||
/**
|
||||
* Loads the most "current" list of packages that are installed meaning from lock ideally or from installed repo as fallback
|
||||
* @param bool $withDevReqs
|
||||
* @param RepositoryInterface $installedRepo
|
||||
* @return array
|
||||
*/
|
||||
private function getCurrentPackages($withDevReqs, $installedRepo)
|
||||
{
|
||||
|
@ -917,6 +965,9 @@ class Installer
|
|||
return $installedRepo->getPackages();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getRootAliases()
|
||||
{
|
||||
if (!$this->update && $this->locker->isLocked()) {
|
||||
|
@ -930,13 +981,19 @@ class Installer
|
|||
foreach ($aliases as $alias) {
|
||||
$normalizedAliases[$alias['package']][$alias['version']] = array(
|
||||
'alias' => $alias['alias'],
|
||||
'alias_normalized' => $alias['alias_normalized']
|
||||
'alias_normalized' => $alias['alias_normalized'],
|
||||
);
|
||||
}
|
||||
|
||||
return $normalizedAliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Pool $pool
|
||||
* @param PolicyInterface $policy
|
||||
* @param WritableRepositoryInterface $localRepo
|
||||
* @param array $repositories
|
||||
*/
|
||||
private function processPackageUrls($pool, $policy, $localRepo, $repositories)
|
||||
{
|
||||
if (!$this->update) {
|
||||
|
@ -945,7 +1002,7 @@ class Installer
|
|||
|
||||
foreach ($localRepo->getCanonicalPackages() as $package) {
|
||||
// find similar packages (name/version) in all repositories
|
||||
$matches = $pool->whatProvides($package->getName(), new VersionConstraint('=', $package->getVersion()));
|
||||
$matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
|
||||
foreach ($matches as $index => $match) {
|
||||
// skip local packages
|
||||
if (!in_array($match->getRepository(), $repositories, true)) {
|
||||
|
@ -967,7 +1024,15 @@ class Installer
|
|||
$newPackage = $pool->literalToPackage($matches[0]);
|
||||
|
||||
// update the dist and source URLs
|
||||
$package->setSourceUrl($newPackage->getSourceUrl());
|
||||
$sourceUrl = $package->getSourceUrl();
|
||||
$newSourceUrl = $newPackage->getSourceUrl();
|
||||
|
||||
if ($sourceUrl !== $newSourceUrl) {
|
||||
$package->setSourceType($newPackage->getSourceType());
|
||||
$package->setSourceUrl($newSourceUrl);
|
||||
$package->setSourceReference($newPackage->getSourceReference());
|
||||
}
|
||||
|
||||
// only update dist url for github/bitbucket dists as they use a combination of dist url + dist reference to install
|
||||
// but for other urls this is ambiguous and could result in bad outcomes
|
||||
if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}', $newPackage->getDistUrl())) {
|
||||
|
@ -977,6 +1042,10 @@ class Installer
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PlatformRepository $platformRepo
|
||||
* @param array $aliases
|
||||
*/
|
||||
private function aliasPlatformPackages(PlatformRepository $platformRepo, $aliases)
|
||||
{
|
||||
foreach ($aliases as $package => $versions) {
|
||||
|
@ -991,6 +1060,10 @@ class Installer
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PackageInterface $package
|
||||
* @return bool
|
||||
*/
|
||||
private function isUpdateable(PackageInterface $package)
|
||||
{
|
||||
if (!$this->updateWhitelist) {
|
||||
|
@ -1020,6 +1093,10 @@ class Installer
|
|||
return "{^" . $cleanedWhiteListedPattern . "$}i";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $links
|
||||
* @return array
|
||||
*/
|
||||
private function extractPlatformRequirements($links)
|
||||
{
|
||||
$platformReqs = array();
|
||||
|
@ -1040,7 +1117,7 @@ class Installer
|
|||
* update whitelist themselves.
|
||||
*
|
||||
* @param RepositoryInterface $localRepo
|
||||
* @param boolean $devMode
|
||||
* @param bool $devMode
|
||||
* @param array $rootRequires An array of links to packages in require of the root package
|
||||
* @param array $rootDevRequires An array of links to packages in require-dev of the root package
|
||||
*/
|
||||
|
@ -1172,6 +1249,10 @@ class Installer
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RepositoryInterface $additionalInstalledRepository
|
||||
* @return $this
|
||||
*/
|
||||
public function setAdditionalInstalledRepository(RepositoryInterface $additionalInstalledRepository)
|
||||
{
|
||||
$this->additionalInstalledRepository = $additionalInstalledRepository;
|
||||
|
@ -1182,7 +1263,7 @@ class Installer
|
|||
/**
|
||||
* Whether to run in drymode or not
|
||||
*
|
||||
* @param boolean $dryRun
|
||||
* @param bool $dryRun
|
||||
* @return Installer
|
||||
*/
|
||||
public function setDryRun($dryRun = true)
|
||||
|
@ -1205,7 +1286,7 @@ class Installer
|
|||
/**
|
||||
* prefer source installation
|
||||
*
|
||||
* @param boolean $preferSource
|
||||
* @param bool $preferSource
|
||||
* @return Installer
|
||||
*/
|
||||
public function setPreferSource($preferSource = true)
|
||||
|
@ -1218,7 +1299,7 @@ class Installer
|
|||
/**
|
||||
* prefer dist installation
|
||||
*
|
||||
* @param boolean $preferDist
|
||||
* @param bool $preferDist
|
||||
* @return Installer
|
||||
*/
|
||||
public function setPreferDist($preferDist = true)
|
||||
|
@ -1237,6 +1318,29 @@ class Installer
|
|||
public function setOptimizeAutoloader($optimizeAutoloader = false)
|
||||
{
|
||||
$this->optimizeAutoloader = (boolean) $optimizeAutoloader;
|
||||
if (!$this->optimizeAutoloader) {
|
||||
// Force classMapAuthoritative off when not optimizing the
|
||||
// autoloader
|
||||
$this->setClassMapAuthoritative(false);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not generated autoloader considers the class map
|
||||
* authoritative.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
* @return Installer
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative = false)
|
||||
{
|
||||
$this->classMapAuthoritative = (boolean) $classMapAuthoritative;
|
||||
if ($this->classMapAuthoritative) {
|
||||
// Force optimizeAutoloader when classmap is authoritative
|
||||
$this->setOptimizeAutoloader(true);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -1244,7 +1348,7 @@ class Installer
|
|||
/**
|
||||
* update packages
|
||||
*
|
||||
* @param boolean $update
|
||||
* @param bool $update
|
||||
* @return Installer
|
||||
*/
|
||||
public function setUpdate($update = true)
|
||||
|
@ -1257,7 +1361,7 @@ class Installer
|
|||
/**
|
||||
* enables dev packages
|
||||
*
|
||||
* @param boolean $devMode
|
||||
* @param bool $devMode
|
||||
* @return Installer
|
||||
*/
|
||||
public function setDevMode($devMode = true)
|
||||
|
@ -1270,7 +1374,7 @@ class Installer
|
|||
/**
|
||||
* set whether to run autoloader or not
|
||||
*
|
||||
* @param boolean $dumpAutoloader
|
||||
* @param bool $dumpAutoloader
|
||||
* @return Installer
|
||||
*/
|
||||
public function setDumpAutoloader($dumpAutoloader = true)
|
||||
|
@ -1283,7 +1387,7 @@ class Installer
|
|||
/**
|
||||
* set whether to run scripts or not
|
||||
*
|
||||
* @param boolean $runScripts
|
||||
* @param bool $runScripts
|
||||
* @return Installer
|
||||
*/
|
||||
public function setRunScripts($runScripts = true)
|
||||
|
@ -1309,7 +1413,7 @@ class Installer
|
|||
/**
|
||||
* run in verbose mode
|
||||
*
|
||||
* @param boolean $verbose
|
||||
* @param bool $verbose
|
||||
* @return Installer
|
||||
*/
|
||||
public function setVerbose($verbose = true)
|
||||
|
@ -1332,7 +1436,7 @@ class Installer
|
|||
/**
|
||||
* set ignore Platform Package requirements
|
||||
*
|
||||
* @param boolean $ignorePlatformReqs
|
||||
* @param bool $ignorePlatformReqs
|
||||
* @return Installer
|
||||
*/
|
||||
public function setIgnorePlatformRequirements($ignorePlatformReqs = false)
|
||||
|
@ -1359,7 +1463,7 @@ class Installer
|
|||
/**
|
||||
* Should dependencies of whitelisted packages be updated recursively?
|
||||
*
|
||||
* @param boolean $updateDependencies
|
||||
* @param bool $updateDependencies
|
||||
* @return Installer
|
||||
*/
|
||||
public function setWhitelistDependencies($updateDependencies = true)
|
||||
|
@ -1372,7 +1476,7 @@ class Installer
|
|||
/**
|
||||
* Should packages be preferred in a stable version when updating?
|
||||
*
|
||||
* @param boolean $preferStable
|
||||
* @param bool $preferStable
|
||||
* @return Installer
|
||||
*/
|
||||
public function setPreferStable($preferStable = true)
|
||||
|
@ -1385,7 +1489,7 @@ class Installer
|
|||
/**
|
||||
* Should packages be preferred in a lowest version when updating?
|
||||
*
|
||||
* @param boolean $preferLowest
|
||||
* @param bool $preferLowest
|
||||
* @return Installer
|
||||
*/
|
||||
public function setPreferLowest($preferLowest = true)
|
||||
|
|
|
@ -89,9 +89,8 @@ class InstallationManager
|
|||
*
|
||||
* @param string $type package type
|
||||
*
|
||||
* @return InstallerInterface
|
||||
*
|
||||
* @throws \InvalidArgumentException if installer for provided type is not registered
|
||||
* @return InstallerInterface
|
||||
*/
|
||||
public function getInstaller($type)
|
||||
{
|
||||
|
@ -249,7 +248,7 @@ class InstallationManager
|
|||
'header' => array('Content-type: application/x-www-form-urlencoded'),
|
||||
'content' => http_build_query($params, '', '&'),
|
||||
'timeout' => 3,
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
$context = StreamContextFactory::getContext($url, $opts);
|
||||
|
@ -273,7 +272,7 @@ class InstallationManager
|
|||
'header' => array('Content-Type: application/json'),
|
||||
'content' => json_encode($postData),
|
||||
'timeout' => 6,
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
$context = StreamContextFactory::getContext($repoUrl, $opts);
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace Composer\Installer;
|
|||
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\Repository\InstalledRepositoryInterface;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Interface for the package installation manager.
|
||||
|
|
|
@ -266,6 +266,11 @@ class LibraryInstaller implements InstallerInterface
|
|||
$this->filesystem->unlink($link.'.bat');
|
||||
}
|
||||
}
|
||||
|
||||
// attempt removing the bin dir in case it is left empty
|
||||
if ((is_dir($this->binDir)) && ($this->filesystem->isDirEmpty($this->binDir))) {
|
||||
@rmdir($this->binDir);
|
||||
}
|
||||
}
|
||||
|
||||
protected function initializeVendorDir()
|
||||
|
|
|
@ -18,7 +18,6 @@ use Composer\DependencyResolver\Operation\OperationInterface;
|
|||
use Composer\DependencyResolver\PolicyInterface;
|
||||
use Composer\DependencyResolver\Pool;
|
||||
use Composer\DependencyResolver\Request;
|
||||
use Composer\EventDispatcher\Event;
|
||||
use Composer\Repository\CompositeRepository;
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
namespace Composer\Installer;
|
||||
|
||||
use Composer\Composer;
|
||||
use Composer\Package\Package;
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\Repository\InstalledRepositoryInterface;
|
||||
use Composer\Package\PackageInterface;
|
||||
|
@ -27,7 +26,6 @@ use Composer\Package\PackageInterface;
|
|||
class PluginInstaller extends LibraryInstaller
|
||||
{
|
||||
private $installationManager;
|
||||
private static $classCounter = 0;
|
||||
|
||||
/**
|
||||
* Initializes Plugin installer.
|
||||
|
|
|
@ -137,8 +137,8 @@ class JsonFile
|
|||
* Validates the schema of the current json file according to composer-schema.json rules
|
||||
*
|
||||
* @param int $schema a JsonFile::*_SCHEMA constant
|
||||
* @return bool true on success
|
||||
* @throws JsonValidationException
|
||||
* @return bool true on success
|
||||
*/
|
||||
public function validateSchema($schema = self::STRICT_SCHEMA)
|
||||
{
|
||||
|
@ -218,7 +218,7 @@ class JsonFile
|
|||
/**
|
||||
* Throws an exception according to a given code with a customized message
|
||||
*
|
||||
* @param int $code return code of json_last_error function
|
||||
* @param int $code return code of json_last_error function
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
private static function throwEncodeError($code)
|
||||
|
@ -269,10 +269,10 @@ class JsonFile
|
|||
*
|
||||
* @param string $json
|
||||
* @param string $file
|
||||
* @return bool true on success
|
||||
* @throws \UnexpectedValueException
|
||||
* @throws JsonValidationException
|
||||
* @throws ParsingException
|
||||
* @return bool true on success
|
||||
*/
|
||||
protected static function validateSyntax($json, $file = null)
|
||||
{
|
||||
|
|
|
@ -23,7 +23,6 @@ namespace Composer\Json;
|
|||
class JsonFormatter
|
||||
{
|
||||
/**
|
||||
*
|
||||
* This code is based on the function found at:
|
||||
* http://recursive-design.com/blog/2008/03/11/format-json-with-php/
|
||||
*
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
|
||||
namespace Composer\Package;
|
||||
|
||||
use Composer\Package\LinkConstraint\VersionConstraint;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Semver\Constraint\Constraint;
|
||||
use Composer\Semver\VersionParser;
|
||||
|
||||
/**
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
|
@ -162,7 +162,7 @@ class AliasPackage extends BasePackage implements CompletePackageInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* @param array $links
|
||||
* @param array $links
|
||||
* @param string $linkType
|
||||
* @internal param string $prettyVersion
|
||||
* @return array
|
||||
|
@ -174,14 +174,14 @@ class AliasPackage extends BasePackage implements CompletePackageInterface
|
|||
foreach ($links as $link) {
|
||||
// link is self.version, but must be replacing also the replaced version
|
||||
if ('self.version' === $link->getPrettyConstraint()) {
|
||||
$newLinks[] = new Link($link->getSource(), $link->getTarget(), new VersionConstraint('=', $this->version), $linkType, $this->prettyVersion);
|
||||
$newLinks[] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
|
||||
}
|
||||
}
|
||||
$links = array_merge($links, $newLinks);
|
||||
} else {
|
||||
foreach ($links as $index => $link) {
|
||||
if ('self.version' === $link->getPrettyConstraint()) {
|
||||
$links[$index] = new Link($link->getSource(), $link->getTarget(), new VersionConstraint('=', $this->version), $linkType, $this->prettyVersion);
|
||||
$links[$index] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
namespace Composer\Package\Archiver;
|
||||
|
||||
use Composer\Util\Filesystem;
|
||||
|
||||
use Symfony\Component\Finder;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
/**
|
||||
* A Symfony Finder wrapper which locates files that should go into archives
|
||||
|
@ -27,7 +26,7 @@ use Symfony\Component\Finder;
|
|||
class ArchivableFilesFinder extends \FilterIterator
|
||||
{
|
||||
/**
|
||||
* @var Symfony\Component\Finder\Finder
|
||||
* @var Finder
|
||||
*/
|
||||
protected $finder;
|
||||
|
||||
|
@ -49,7 +48,7 @@ class ArchivableFilesFinder extends \FilterIterator
|
|||
new ComposerExcludeFilter($sources, $excludes),
|
||||
);
|
||||
|
||||
$this->finder = new Finder\Finder();
|
||||
$this->finder = new Finder();
|
||||
|
||||
$filter = function (\SplFileInfo $file) use ($sources, $filters, $fs) {
|
||||
if ($file->isLink() && strpos($file->getLinkTarget(), $sources) !== 0) {
|
||||
|
|
|
@ -37,7 +37,7 @@ interface ArchiverInterface
|
|||
* @param string $format The archive format
|
||||
* @param string $sourceType The source type (git, svn, hg, etc.)
|
||||
*
|
||||
* @return boolean true if the format is supported by the archiver
|
||||
* @return bool true if the format is supported by the archiver
|
||||
*/
|
||||
public function supports($format, $sourceType);
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ abstract class BaseExcludeFilter
|
|||
protected function generatePattern($rule)
|
||||
{
|
||||
$negate = false;
|
||||
$pattern = '#';
|
||||
$pattern = '{';
|
||||
|
||||
if (strlen($rule) && $rule[0] === '!') {
|
||||
$negate = true;
|
||||
|
@ -143,6 +143,6 @@ abstract class BaseExcludeFilter
|
|||
// remove delimiters as well as caret (^) and dollar sign ($) from the regex
|
||||
$pattern .= substr(Finder\Glob::toRegex($rule), 2, -2) . '(?=$|/)';
|
||||
|
||||
return array($pattern . '#', $negate, false);
|
||||
return array($pattern . '}', $negate, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ class HgExcludeFilter extends BaseExcludeFilter
|
|||
|
||||
/**
|
||||
* Either HG_IGNORE_REGEX or HG_IGNORE_GLOB
|
||||
* @var integer
|
||||
* @var int
|
||||
*/
|
||||
protected $patternMode;
|
||||
|
||||
|
|
|
@ -161,7 +161,7 @@ abstract class BasePackage implements PackageInterface
|
|||
/**
|
||||
* checks if this package is a platform package
|
||||
*
|
||||
* @return boolean
|
||||
* @return bool
|
||||
*/
|
||||
public function isPlatform()
|
||||
{
|
||||
|
@ -206,6 +206,23 @@ abstract class BasePackage implements PackageInterface
|
|||
return $this->getPrettyName().' '.$this->getPrettyVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getFullPrettyVersion($truncate = true)
|
||||
{
|
||||
if (!$this->isDev() || !in_array($this->getSourceType(), array('hg', 'git'))) {
|
||||
return $this->getPrettyVersion();
|
||||
}
|
||||
|
||||
// if source reference is a sha1 hash -- truncate
|
||||
if ($truncate && strlen($this->getSourceReference()) === 40) {
|
||||
return $this->getPrettyVersion() . ' ' . substr($this->getSourceReference(), 0, 7);
|
||||
}
|
||||
|
||||
return $this->getPrettyVersion() . ' ' . $this->getSourceReference();
|
||||
}
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
$this->repository = null;
|
||||
|
|
|
@ -172,7 +172,7 @@ class CompletePackage extends Package implements CompletePackageInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
* @return bool
|
||||
*/
|
||||
public function isAbandoned()
|
||||
{
|
||||
|
@ -180,7 +180,7 @@ class CompletePackage extends Package implements CompletePackageInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* @param boolean|string $abandoned
|
||||
* @param bool|string $abandoned
|
||||
*/
|
||||
public function setAbandoned($abandoned)
|
||||
{
|
||||
|
|
|
@ -82,7 +82,7 @@ interface CompletePackageInterface extends PackageInterface
|
|||
/**
|
||||
* Returns if the package is abandoned or not
|
||||
*
|
||||
* @return boolean
|
||||
* @return bool
|
||||
*/
|
||||
public function isAbandoned();
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
namespace Composer\Package;
|
||||
|
||||
use Composer\Package\LinkConstraint\LinkConstraintInterface;
|
||||
use Composer\Semver\Constraint\ConstraintInterface;
|
||||
|
||||
/**
|
||||
* Represents a link between two packages, represented by their names
|
||||
|
@ -32,7 +32,7 @@ class Link
|
|||
protected $target;
|
||||
|
||||
/**
|
||||
* @var LinkConstraintInterface|null
|
||||
* @var ConstraintInterface|null
|
||||
*/
|
||||
protected $constraint;
|
||||
|
||||
|
@ -49,13 +49,13 @@ class Link
|
|||
/**
|
||||
* Creates a new package link.
|
||||
*
|
||||
* @param string $source
|
||||
* @param string $target
|
||||
* @param LinkConstraintInterface|null $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|null $constraint Constraint applying to the target of this link
|
||||
* @param string $description Used to create a descriptive string representation
|
||||
* @param string|null $prettyConstraint
|
||||
*/
|
||||
public function __construct($source, $target, LinkConstraintInterface $constraint = null, $description = 'relates to', $prettyConstraint = null)
|
||||
public function __construct($source, $target, ConstraintInterface $constraint = null, $description = 'relates to', $prettyConstraint = null)
|
||||
{
|
||||
$this->source = strtolower($source);
|
||||
$this->target = strtolower($target);
|
||||
|
@ -81,7 +81,7 @@ class Link
|
|||
}
|
||||
|
||||
/**
|
||||
* @return LinkConstraintInterface|null
|
||||
* @return ConstraintInterface|null
|
||||
*/
|
||||
public function getConstraint()
|
||||
{
|
||||
|
@ -110,7 +110,7 @@ class Link
|
|||
}
|
||||
|
||||
/**
|
||||
* @param PackageInterface $sourcePackage
|
||||
* @param PackageInterface $sourcePackage
|
||||
* @return string
|
||||
*/
|
||||
public function getPrettyString(PackageInterface $sourcePackage)
|
||||
|
|
|
@ -12,36 +12,13 @@
|
|||
|
||||
namespace Composer\Package\LinkConstraint;
|
||||
|
||||
use Composer\Semver\Constraint\EmptyConstraint as SemverEmptyConstraint;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\EmptyConstraint class is deprecated, use Composer\Semver\Constraint\EmptyConstraint instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Defines an absence of constraints
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @deprecated use Composer\Semver\Constraint\EmptyConstraint instead
|
||||
*/
|
||||
class EmptyConstraint implements LinkConstraintInterface
|
||||
class EmptyConstraint extends SemverEmptyConstraint implements LinkConstraintInterface
|
||||
{
|
||||
protected $prettyString;
|
||||
|
||||
public function matches(LinkConstraintInterface $provider)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setPrettyString($prettyString)
|
||||
{
|
||||
$this->prettyString = $prettyString;
|
||||
}
|
||||
|
||||
public function getPrettyString()
|
||||
{
|
||||
if ($this->prettyString) {
|
||||
return $this->prettyString;
|
||||
}
|
||||
|
||||
return $this->__toString();
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return '[]';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,15 +12,13 @@
|
|||
|
||||
namespace Composer\Package\LinkConstraint;
|
||||
|
||||
use Composer\Semver\Constraint\ConstraintInterface;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\LinkConstraintInterface interface is deprecated, use Composer\Semver\Constraint\ConstraintInterface instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Defines a constraint on a link between two packages.
|
||||
*
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
* @deprecated use Composer\Semver\Constraint\ConstraintInterface instead
|
||||
*/
|
||||
interface LinkConstraintInterface
|
||||
interface LinkConstraintInterface extends ConstraintInterface
|
||||
{
|
||||
public function matches(LinkConstraintInterface $provider);
|
||||
public function setPrettyString($prettyString);
|
||||
public function getPrettyString();
|
||||
public function __toString();
|
||||
}
|
||||
|
|
|
@ -12,72 +12,13 @@
|
|||
|
||||
namespace Composer\Package\LinkConstraint;
|
||||
|
||||
use Composer\Semver\Constraint\MultiConstraint as SemverMultiConstraint;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\MultiConstraint class is deprecated, use Composer\Semver\Constraint\MultiConstraint instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Defines a conjunctive or disjunctive set of constraints on the target of a package link
|
||||
*
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @deprecated use Composer\Semver\Constraint\MultiConstraint instead
|
||||
*/
|
||||
class MultiConstraint implements LinkConstraintInterface
|
||||
class MultiConstraint extends SemverMultiConstraint implements LinkConstraintInterface
|
||||
{
|
||||
protected $constraints;
|
||||
protected $prettyString;
|
||||
protected $conjunctive;
|
||||
|
||||
/**
|
||||
* Sets operator and version to compare a package with
|
||||
*
|
||||
* @param array $constraints A set of constraints
|
||||
* @param bool $conjunctive Whether the constraints should be treated as conjunctive or disjunctive
|
||||
*/
|
||||
public function __construct(array $constraints, $conjunctive = true)
|
||||
{
|
||||
$this->constraints = $constraints;
|
||||
$this->conjunctive = $conjunctive;
|
||||
}
|
||||
|
||||
public function matches(LinkConstraintInterface $provider)
|
||||
{
|
||||
if (false === $this->conjunctive) {
|
||||
foreach ($this->constraints as $constraint) {
|
||||
if ($constraint->matches($provider)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($this->constraints as $constraint) {
|
||||
if (!$constraint->matches($provider)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setPrettyString($prettyString)
|
||||
{
|
||||
$this->prettyString = $prettyString;
|
||||
}
|
||||
|
||||
public function getPrettyString()
|
||||
{
|
||||
if ($this->prettyString) {
|
||||
return $this->prettyString;
|
||||
}
|
||||
|
||||
return $this->__toString();
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
$constraints = array();
|
||||
foreach ($this->constraints as $constraint) {
|
||||
$constraints[] = $constraint->__toString();
|
||||
}
|
||||
|
||||
return '['.implode($this->conjunctive ? ' ' : ' || ', $constraints).']';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,42 +12,13 @@
|
|||
|
||||
namespace Composer\Package\LinkConstraint;
|
||||
|
||||
use Composer\Semver\Constraint\AbstractConstraint;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\SpecificConstraint abstract class is deprecated, use Composer\Semver\Constraint\AbstractConstraint instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Provides a common basis for specific package link constraints
|
||||
*
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
* @deprecated use Composer\Semver\Constraint\AbstractConstraint instead
|
||||
*/
|
||||
abstract class SpecificConstraint implements LinkConstraintInterface
|
||||
abstract class SpecificConstraint extends AbstractConstraint implements LinkConstraintInterface
|
||||
{
|
||||
protected $prettyString;
|
||||
|
||||
public function matches(LinkConstraintInterface $provider)
|
||||
{
|
||||
if ($provider instanceof MultiConstraint) {
|
||||
// turn matching around to find a match
|
||||
return $provider->matches($this);
|
||||
} elseif ($provider instanceof $this) {
|
||||
return $this->matchSpecific($provider);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setPrettyString($prettyString)
|
||||
{
|
||||
$this->prettyString = $prettyString;
|
||||
}
|
||||
|
||||
public function getPrettyString()
|
||||
{
|
||||
if ($this->prettyString) {
|
||||
return $this->prettyString;
|
||||
}
|
||||
|
||||
return $this->__toString();
|
||||
}
|
||||
|
||||
// implementations must implement a method of this format:
|
||||
// not declared abstract here because type hinting violates parameter coherence (TODO right word?)
|
||||
// public function matchSpecific(<SpecificConstraintType> $provider);
|
||||
}
|
||||
|
|
|
@ -12,113 +12,13 @@
|
|||
|
||||
namespace Composer\Package\LinkConstraint;
|
||||
|
||||
use Composer\Semver\Constraint\Constraint;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\VersionConstraint class is deprecated, use Composer\Semver\Constraint\Constraint instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Constrains a package link based on package version
|
||||
*
|
||||
* Version numbers must be compatible with version_compare
|
||||
*
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
* @deprecated use Composer\Semver\Constraint\Constraint instead
|
||||
*/
|
||||
class VersionConstraint extends SpecificConstraint
|
||||
class VersionConstraint extends Constraint implements LinkConstraintInterface
|
||||
{
|
||||
private $operator;
|
||||
private $version;
|
||||
|
||||
/**
|
||||
* Sets operator and version to compare a package with
|
||||
*
|
||||
* @param string $operator A comparison operator
|
||||
* @param string $version A version to compare to
|
||||
*/
|
||||
public function __construct($operator, $version)
|
||||
{
|
||||
if ('=' === $operator) {
|
||||
$operator = '==';
|
||||
}
|
||||
|
||||
if ('<>' === $operator) {
|
||||
$operator = '!=';
|
||||
}
|
||||
|
||||
$this->operator = $operator;
|
||||
$this->version = $version;
|
||||
}
|
||||
|
||||
public function versionCompare($a, $b, $operator, $compareBranches = false)
|
||||
{
|
||||
$aIsBranch = 'dev-' === substr($a, 0, 4);
|
||||
$bIsBranch = 'dev-' === substr($b, 0, 4);
|
||||
if ($aIsBranch && $bIsBranch) {
|
||||
return $operator == '==' && $a === $b;
|
||||
}
|
||||
|
||||
// when branches are not comparable, we make sure dev branches never match anything
|
||||
if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return version_compare($a, $b, $operator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param VersionConstraint $provider
|
||||
* @param bool $compareBranches
|
||||
* @return bool
|
||||
*/
|
||||
public function matchSpecific(VersionConstraint $provider, $compareBranches = false)
|
||||
{
|
||||
static $cache = array();
|
||||
if (isset($cache[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches])) {
|
||||
return $cache[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches];
|
||||
}
|
||||
|
||||
return $cache[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches] =
|
||||
$this->doMatchSpecific($provider, $compareBranches);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param VersionConstraint $provider
|
||||
* @param bool $compareBranches
|
||||
* @return bool
|
||||
*/
|
||||
private function doMatchSpecific(VersionConstraint $provider, $compareBranches = false)
|
||||
{
|
||||
$noEqualOp = str_replace('=', '', $this->operator);
|
||||
$providerNoEqualOp = str_replace('=', '', $provider->operator);
|
||||
|
||||
$isEqualOp = '==' === $this->operator;
|
||||
$isNonEqualOp = '!=' === $this->operator;
|
||||
$isProviderEqualOp = '==' === $provider->operator;
|
||||
$isProviderNonEqualOp = '!=' === $provider->operator;
|
||||
|
||||
// '!=' operator is match when other operator is not '==' operator or version is not match
|
||||
// these kinds of comparisons always have a solution
|
||||
if ($isNonEqualOp || $isProviderNonEqualOp) {
|
||||
return !$isEqualOp && !$isProviderEqualOp
|
||||
|| $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
|
||||
}
|
||||
|
||||
// an example for the condition is <= 2.0 & < 1.0
|
||||
// these kinds of comparisons always have a solution
|
||||
if ($this->operator != '==' && $noEqualOp == $providerNoEqualOp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->versionCompare($provider->version, $this->version, $this->operator, $compareBranches)) {
|
||||
// special case, e.g. require >= 1.0 and provide < 1.0
|
||||
// 1.0 >= 1.0 but 1.0 is outside of the provided interval
|
||||
if ($provider->version == $this->version && $provider->operator == $providerNoEqualOp && $this->operator != $noEqualOp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->operator.' '.$this->version;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,9 +14,10 @@ namespace Composer\Package\Loader;
|
|||
|
||||
use Composer\Package;
|
||||
use Composer\Package\AliasPackage;
|
||||
use Composer\Package\Link;
|
||||
use Composer\Package\RootAliasPackage;
|
||||
use Composer\Package\RootPackageInterface;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Semver\VersionParser;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kudryashiv <ever.zet@gmail.com>
|
||||
|
@ -115,7 +116,7 @@ class ArrayLoader implements LoaderInterface
|
|||
if (isset($config[$type])) {
|
||||
$method = 'set'.ucfirst($opts['method']);
|
||||
$package->{$method}(
|
||||
$this->versionParser->parseLinks(
|
||||
$this->parseLinks(
|
||||
$package->getName(),
|
||||
$package->getPrettyVersion(),
|
||||
$opts['description'],
|
||||
|
@ -147,7 +148,7 @@ class ArrayLoader implements LoaderInterface
|
|||
}
|
||||
|
||||
if (!empty($config['time'])) {
|
||||
$time = preg_match('/^\d+$/D', $config['time']) ? '@'.$config['time'] : $config['time'];
|
||||
$time = preg_match('/^\d++$/D', $config['time']) ? '@'.$config['time'] : $config['time'];
|
||||
|
||||
try {
|
||||
$date = new \DateTime($time, new \DateTimeZone('UTC'));
|
||||
|
@ -216,6 +217,29 @@ class ArrayLoader implements LoaderInterface
|
|||
return $package;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @return Link[]
|
||||
*/
|
||||
public function parseLinks($source, $sourceVersion, $description, $links)
|
||||
{
|
||||
$res = array();
|
||||
foreach ($links as $target => $constraint) {
|
||||
if ('self.version' === $constraint) {
|
||||
$parsedConstraint = $this->versionParser->parseConstraints($sourceVersion);
|
||||
} else {
|
||||
$parsedConstraint = $this->versionParser->parseConstraints($constraint);
|
||||
}
|
||||
|
||||
$res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint);
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a branch alias (dev-master => 1.0.x-dev for example) if it exists
|
||||
*
|
||||
|
|
|
@ -16,13 +16,10 @@ use Composer\Package\BasePackage;
|
|||
use Composer\Package\AliasPackage;
|
||||
use Composer\Config;
|
||||
use Composer\Factory;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Package\Version\VersionGuesser;
|
||||
use Composer\Semver\VersionParser;
|
||||
use Composer\Repository\RepositoryManager;
|
||||
use Composer\Repository\Vcs\HgDriver;
|
||||
use Composer\IO\NullIO;
|
||||
use Composer\Util\ProcessExecutor;
|
||||
use Composer\Util\Git as GitUtil;
|
||||
use Composer\Util\Svn as SvnUtil;
|
||||
|
||||
/**
|
||||
* ArrayLoader built for the sole purpose of loading the root package
|
||||
|
@ -33,16 +30,28 @@ use Composer\Util\Svn as SvnUtil;
|
|||
*/
|
||||
class RootPackageLoader extends ArrayLoader
|
||||
{
|
||||
/**
|
||||
* @var RepositoryManager
|
||||
*/
|
||||
private $manager;
|
||||
private $config;
|
||||
private $process;
|
||||
|
||||
public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, ProcessExecutor $process = null)
|
||||
/**
|
||||
* @var Config
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @var VersionGuesser
|
||||
*/
|
||||
private $versionGuesser;
|
||||
|
||||
public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, VersionGuesser $versionGuesser = null)
|
||||
{
|
||||
parent::__construct($parser);
|
||||
|
||||
$this->manager = $manager;
|
||||
$this->config = $config;
|
||||
$this->process = $process ?: new ProcessExecutor();
|
||||
parent::__construct($parser);
|
||||
$this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor(), $this->versionParser);
|
||||
}
|
||||
|
||||
public function load(array $config, $class = 'Composer\Package\RootPackage')
|
||||
|
@ -56,7 +65,7 @@ class RootPackageLoader extends ArrayLoader
|
|||
if (getenv('COMPOSER_ROOT_VERSION')) {
|
||||
$version = getenv('COMPOSER_ROOT_VERSION');
|
||||
} else {
|
||||
$version = $this->guessVersion($config);
|
||||
$version = $this->versionGuesser->guessVersion($config, getcwd());
|
||||
}
|
||||
|
||||
if (!$version) {
|
||||
|
@ -176,172 +185,4 @@ class RootPackageLoader extends ArrayLoader
|
|||
|
||||
return $references;
|
||||
}
|
||||
|
||||
private function guessVersion(array $config)
|
||||
{
|
||||
if (function_exists('proc_open')) {
|
||||
$version = $this->guessGitVersion($config);
|
||||
if (null !== $version) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
$version = $this->guessHgVersion($config);
|
||||
if (null !== $version) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
return $this->guessSvnVersion($config);
|
||||
}
|
||||
}
|
||||
|
||||
private function guessGitVersion(array $config)
|
||||
{
|
||||
GitUtil::cleanEnv();
|
||||
|
||||
// try to fetch current version from git tags
|
||||
if (0 === $this->process->execute('git describe --exact-match --tags', $output)) {
|
||||
try {
|
||||
return $this->versionParser->normalize(trim($output));
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
// try to fetch current version from git branch
|
||||
if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output)) {
|
||||
$branches = array();
|
||||
$isFeatureBranch = false;
|
||||
$version = null;
|
||||
|
||||
// find current branch and collect all branch names
|
||||
foreach ($this->process->splitLines($output) as $branch) {
|
||||
if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
|
||||
if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ') {
|
||||
$version = 'dev-'.$match[2];
|
||||
$isFeatureBranch = true;
|
||||
} else {
|
||||
$version = $this->versionParser->normalizeBranch($match[1]);
|
||||
$isFeatureBranch = 0 === strpos($version, 'dev-');
|
||||
if ('9999999-dev' === $version) {
|
||||
$version = 'dev-'.$match[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
|
||||
if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
|
||||
$branches[] = $match[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isFeatureBranch) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
// try to find the best (nearest) version branch to assume this feature's version
|
||||
$version = $this->guessFeatureVersion($config, $version, $branches, 'git rev-list %candidate%..%branch%');
|
||||
|
||||
return $version;
|
||||
}
|
||||
}
|
||||
|
||||
private function guessHgVersion(array $config)
|
||||
{
|
||||
// try to fetch current version from hg branch
|
||||
if (0 === $this->process->execute('hg branch', $output)) {
|
||||
$branch = trim($output);
|
||||
$version = $this->versionParser->normalizeBranch($branch);
|
||||
$isFeatureBranch = 0 === strpos($version, 'dev-');
|
||||
|
||||
if ('9999999-dev' === $version) {
|
||||
$version = 'dev-'.$branch;
|
||||
}
|
||||
|
||||
if (!$isFeatureBranch) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
// re-use the HgDriver to fetch branches (this properly includes bookmarks)
|
||||
$config = array('url' => getcwd());
|
||||
$driver = new HgDriver($config, new NullIO(), $this->config, $this->process);
|
||||
$branches = array_keys($driver->getBranches());
|
||||
|
||||
// try to find the best (nearest) version branch to assume this feature's version
|
||||
$version = $this->guessFeatureVersion($config, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"');
|
||||
|
||||
return $version;
|
||||
}
|
||||
}
|
||||
|
||||
private function guessFeatureVersion(array $config, $version, array $branches, $scmCmdline)
|
||||
{
|
||||
// ignore feature branches if they have no branch-alias or self.version is used
|
||||
// and find the branch they came from to use as a version instead
|
||||
if ((isset($config['extra']['branch-alias']) && !isset($config['extra']['branch-alias'][$version]))
|
||||
|| strpos(json_encode($config), '"self.version"')
|
||||
) {
|
||||
$branch = preg_replace('{^dev-}', '', $version);
|
||||
$length = PHP_INT_MAX;
|
||||
|
||||
$nonFeatureBranches = '';
|
||||
if (!empty($config['non-feature-branches'])) {
|
||||
$nonFeatureBranches = implode('|', $config['non-feature-branches']);
|
||||
}
|
||||
|
||||
foreach ($branches as $candidate) {
|
||||
// return directly, if branch is configured to be non-feature branch
|
||||
if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
// do not compare against other feature branches
|
||||
if ($candidate === $branch || !preg_match('{^(master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline);
|
||||
if (0 !== $this->process->execute($cmdLine, $output)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strlen($output) < $length) {
|
||||
$length = strlen($output);
|
||||
$version = $this->versionParser->normalizeBranch($candidate);
|
||||
if ('9999999-dev' === $version) {
|
||||
$version = 'dev-'.$match[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $version;
|
||||
}
|
||||
|
||||
private function guessSvnVersion(array $config)
|
||||
{
|
||||
SvnUtil::cleanEnv();
|
||||
|
||||
// try to fetch current version from svn
|
||||
if (0 === $this->process->execute('svn info --xml', $output)) {
|
||||
$trunkPath = isset($config['trunk-path']) ? preg_quote($config['trunk-path'], '#') : 'trunk';
|
||||
$branchesPath = isset($config['branches-path']) ? preg_quote($config['branches-path'], '#') : 'branches';
|
||||
$tagsPath = isset($config['tags-path']) ? preg_quote($config['tags-path'], '#') : 'tags';
|
||||
|
||||
$urlPattern = '#<url>.*/('.$trunkPath.'|('.$branchesPath.'|'. $tagsPath .')/(.*))</url>#';
|
||||
|
||||
if (preg_match($urlPattern, $output, $matches)) {
|
||||
if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) {
|
||||
// we are in a branches path
|
||||
$version = $this->versionParser->normalizeBranch($matches[3]);
|
||||
if ('9999999-dev' === $version) {
|
||||
$version = 'dev-'.$matches[3];
|
||||
}
|
||||
|
||||
return $version;
|
||||
}
|
||||
|
||||
return $this->versionParser->normalize(trim($matches[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@ namespace Composer\Package\Loader;
|
|||
|
||||
use Composer\Package;
|
||||
use Composer\Package\BasePackage;
|
||||
use Composer\Package\LinkConstraint\VersionConstraint;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Semver\Constraint\Constraint;
|
||||
use Composer\Semver\VersionParser;
|
||||
use Composer\Repository\PlatformRepository;
|
||||
|
||||
/**
|
||||
|
@ -149,7 +149,7 @@ class ValidatingArrayLoader implements LoaderInterface
|
|||
}
|
||||
}
|
||||
|
||||
$unboundConstraint = new VersionConstraint('=', $this->versionParser->normalize('dev-master'));
|
||||
$unboundConstraint = new Constraint('=', $this->versionParser->normalize('dev-master'));
|
||||
|
||||
foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
|
||||
if ($this->validateArray($linkType) && isset($this->config[$linkType])) {
|
||||
|
|
|
@ -19,9 +19,9 @@ use Composer\Util\ProcessExecutor;
|
|||
use Composer\Repository\ArrayRepository;
|
||||
use Composer\Package\Dumper\ArrayDumper;
|
||||
use Composer\Package\Loader\ArrayLoader;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Util\Git as GitUtil;
|
||||
use Composer\IO\IOInterface;
|
||||
use Seld\JsonLint\ParsingException;
|
||||
|
||||
/**
|
||||
* Reads/writes project lockfile (composer.lock).
|
||||
|
@ -35,6 +35,7 @@ class Locker
|
|||
private $repositoryManager;
|
||||
private $installationManager;
|
||||
private $hash;
|
||||
private $contentHash;
|
||||
private $loader;
|
||||
private $dumper;
|
||||
private $process;
|
||||
|
@ -44,17 +45,18 @@ class Locker
|
|||
* Initializes packages locker.
|
||||
*
|
||||
* @param IOInterface $io
|
||||
* @param JsonFile $lockFile lockfile loader
|
||||
* @param RepositoryManager $repositoryManager repository manager instance
|
||||
* @param InstallationManager $installationManager installation manager instance
|
||||
* @param string $hash unique hash of the current composer configuration
|
||||
* @param JsonFile $lockFile lockfile loader
|
||||
* @param RepositoryManager $repositoryManager repository manager instance
|
||||
* @param InstallationManager $installationManager installation manager instance
|
||||
* @param string $composerFileContents The contents of the composer file
|
||||
*/
|
||||
public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $hash)
|
||||
public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $composerFileContents)
|
||||
{
|
||||
$this->lockFile = $lockFile;
|
||||
$this->repositoryManager = $repositoryManager;
|
||||
$this->installationManager = $installationManager;
|
||||
$this->hash = $hash;
|
||||
$this->hash = md5($composerFileContents);
|
||||
$this->contentHash = $this->getContentHash($composerFileContents);
|
||||
$this->loader = new ArrayLoader(null, true);
|
||||
$this->dumper = new ArrayDumper();
|
||||
$this->process = new ProcessExecutor($io);
|
||||
|
@ -85,6 +87,11 @@ class Locker
|
|||
{
|
||||
$lock = $this->lockFile->read();
|
||||
|
||||
if (!empty($lock['content-hash'])) {
|
||||
// There is a content hash key, use that instead of the file hash
|
||||
return $this->contentHash === $lock['content-hash'];
|
||||
}
|
||||
|
||||
return $this->hash === $lock['hash'];
|
||||
}
|
||||
|
||||
|
@ -133,11 +140,10 @@ class Locker
|
|||
public function getPlatformRequirements($withDevReqs = false)
|
||||
{
|
||||
$lockData = $this->getLockData();
|
||||
$versionParser = new VersionParser();
|
||||
$requirements = array();
|
||||
|
||||
if (!empty($lockData['platform'])) {
|
||||
$requirements = $versionParser->parseLinks(
|
||||
$requirements = $this->loader->parseLinks(
|
||||
'__ROOT__',
|
||||
'1.0.0',
|
||||
'requires',
|
||||
|
@ -146,7 +152,7 @@ class Locker
|
|||
}
|
||||
|
||||
if ($withDevReqs && !empty($lockData['platform-dev'])) {
|
||||
$devRequirements = $versionParser->parseLinks(
|
||||
$devRequirements = $this->loader->parseLinks(
|
||||
'__ROOT__',
|
||||
'1.0.0',
|
||||
'requires',
|
||||
|
@ -239,8 +245,9 @@ class Locker
|
|||
$lock = array(
|
||||
'_readme' => array('This file locks the dependencies of your project to a known state',
|
||||
'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file',
|
||||
'This file is @gener'.'ated automatically'),
|
||||
'This file is @gener'.'ated automatically', ),
|
||||
'hash' => $this->hash,
|
||||
'content-hash' => $this->contentHash,
|
||||
'packages' => null,
|
||||
'packages-dev' => null,
|
||||
'aliases' => array(),
|
||||
|
@ -280,7 +287,12 @@ class Locker
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!$this->isLocked() || $lock !== $this->getLockData()) {
|
||||
try {
|
||||
$isLocked = $this->isLocked();
|
||||
} catch (ParsingException $e) {
|
||||
$isLocked = false;
|
||||
}
|
||||
if (!$isLocked || $lock !== $this->getLockData()) {
|
||||
$this->lockFile->write($lock);
|
||||
$this->lockDataCache = null;
|
||||
|
||||
|
@ -378,4 +390,43 @@ class Locker
|
|||
|
||||
return $datetime ? $datetime->format('Y-m-d H:i:s') : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the md5 hash of the sorted content of the composer file.
|
||||
*
|
||||
* @param string $composerFileContents The contents of the composer file.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getContentHash($composerFileContents)
|
||||
{
|
||||
$content = json_decode($composerFileContents, true);
|
||||
|
||||
$relevantKeys = array(
|
||||
'name',
|
||||
'version',
|
||||
'require',
|
||||
'require-dev',
|
||||
'conflict',
|
||||
'replace',
|
||||
'provide',
|
||||
'minimum-stability',
|
||||
'prefer-stable',
|
||||
'repositories',
|
||||
'extra',
|
||||
);
|
||||
|
||||
$relevantContent = array();
|
||||
|
||||
foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
|
||||
$relevantContent[$key] = $content[$key];
|
||||
}
|
||||
if (isset($content['config']['platform'])) {
|
||||
$relevantContent['config']['platform'] = $content['config']['platform'];
|
||||
}
|
||||
|
||||
ksort($relevantContent);
|
||||
|
||||
return md5(json_encode($relevantContent));
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue