Merge branch 'master' into 2.0
commit
bc2a1d762a
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -1,3 +1,16 @@
|
|||
### [1.9.0] 2019-08-02
|
||||
|
||||
* Breaking: artifact repositories with URLs containing port numbers and requiring authentication now require you to configure http-basic auth for the `host:port` pair explicitly
|
||||
* Added a `--no-cache` flag available on all commands to run with the cache disabled
|
||||
* Added PHP_BINARY as env var pointing to the PHP process when executing Composer scripts as shell scripts
|
||||
* Added a `use-github-api` config option which can set the `no-api` flag on all GitHub VCS repositories declared
|
||||
* Added a static helper you can preprend to a script to avoid process timeouts, `"Composer\\Config::disableProcessTimeout"`
|
||||
* Added Event::getOriginatingEvent to retrieve an event's original event when a script handler forwards to another one
|
||||
* Added support for autoloading directly from a phar file
|
||||
* Fixed loading order of plugins to always initialize them in order of dependencies
|
||||
* Fixed various network-mount related issues
|
||||
* Fixed --ignore-platform-reqs not ignoring conflict rules against platform packages
|
||||
|
||||
### [1.8.6] 2019-06-11
|
||||
|
||||
* Fixed handling of backslash-escapes handling in composer.json when using the require command
|
||||
|
@ -751,6 +764,7 @@
|
|||
|
||||
* Initial release
|
||||
|
||||
[1.9.0]: https://github.com/composer/composer/compare/1.8.6...1.9.0
|
||||
[1.8.6]: https://github.com/composer/composer/compare/1.8.5...1.8.6
|
||||
[1.8.5]: https://github.com/composer/composer/compare/1.8.4...1.8.5
|
||||
[1.8.4]: https://github.com/composer/composer/compare/1.8.3...1.8.4
|
||||
|
|
|
@ -8,25 +8,25 @@
|
|||
"packages": [
|
||||
{
|
||||
"name": "composer/ca-bundle",
|
||||
"version": "1.1.4",
|
||||
"version": "1.2.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/ca-bundle.git",
|
||||
"reference": "558f321c52faeb4828c03e7dc0cfe39a09e09a2d"
|
||||
"reference": "10bb96592168a0f8e8f6dcde3532d9fa50b0b527"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/558f321c52faeb4828c03e7dc0cfe39a09e09a2d",
|
||||
"reference": "558f321c52faeb4828c03e7dc0cfe39a09e09a2d",
|
||||
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/10bb96592168a0f8e8f6dcde3532d9fa50b0b527",
|
||||
"reference": "10bb96592168a0f8e8f6dcde3532d9fa50b0b527",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-openssl": "*",
|
||||
"ext-pcre": "*",
|
||||
"php": "^5.3.2 || ^7.0"
|
||||
"php": "^5.3.2 || ^7.0 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5",
|
||||
"phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8",
|
||||
"psr/log": "^1.0",
|
||||
"symfony/process": "^2.5 || ^3.0 || ^4.0"
|
||||
},
|
||||
|
@ -60,7 +60,7 @@
|
|||
"ssl",
|
||||
"tls"
|
||||
],
|
||||
"time": "2019-01-28T09:30:10+00:00"
|
||||
"time": "2019-08-30T08:44:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/semver",
|
||||
|
@ -126,16 +126,16 @@
|
|||
},
|
||||
{
|
||||
"name": "composer/spdx-licenses",
|
||||
"version": "1.5.1",
|
||||
"version": "1.5.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/spdx-licenses.git",
|
||||
"reference": "a1aa51cf3ab838b83b0867b14e56fc20fbd55b3d"
|
||||
"reference": "7ac1e6aec371357df067f8a688c3d6974df68fa5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/spdx-licenses/zipball/a1aa51cf3ab838b83b0867b14e56fc20fbd55b3d",
|
||||
"reference": "a1aa51cf3ab838b83b0867b14e56fc20fbd55b3d",
|
||||
"url": "https://api.github.com/repos/composer/spdx-licenses/zipball/7ac1e6aec371357df067f8a688c3d6974df68fa5",
|
||||
"reference": "7ac1e6aec371357df067f8a688c3d6974df68fa5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -182,7 +182,7 @@
|
|||
"spdx",
|
||||
"validator"
|
||||
],
|
||||
"time": "2019-03-26T10:23:26+00:00"
|
||||
"time": "2019-07-29T10:31:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/xdebug-handler",
|
||||
|
@ -697,16 +697,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.11.0",
|
||||
"version": "v1.12.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "82ebae02209c21113908c229e9883c419720738a"
|
||||
"reference": "550ebaac289296ce228a706d0867afc34687e3f4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a",
|
||||
"reference": "82ebae02209c21113908c229e9883c419720738a",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4",
|
||||
"reference": "550ebaac289296ce228a706d0867afc34687e3f4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -718,7 +718,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.11-dev"
|
||||
"dev-master": "1.12-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -734,13 +734,13 @@
|
|||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
},
|
||||
{
|
||||
"name": "Gert de Pagter",
|
||||
"email": "BackEndTea@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for ctype functions",
|
||||
|
@ -751,20 +751,20 @@
|
|||
"polyfill",
|
||||
"portable"
|
||||
],
|
||||
"time": "2019-02-06T07:57:58+00:00"
|
||||
"time": "2019-08-06T08:03:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.11.0",
|
||||
"version": "v1.12.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "fe5e94c604826c35a32fa832f35bd036b6799609"
|
||||
"reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609",
|
||||
"reference": "fe5e94c604826c35a32fa832f35bd036b6799609",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17",
|
||||
"reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -776,7 +776,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.11-dev"
|
||||
"dev-master": "1.12-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -810,7 +810,7 @@
|
|||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2019-02-06T07:57:58+00:00"
|
||||
"time": "2019-08-06T08:03:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
|
@ -968,22 +968,22 @@
|
|||
},
|
||||
{
|
||||
"name": "phpspec/prophecy",
|
||||
"version": "1.8.0",
|
||||
"version": "1.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpspec/prophecy.git",
|
||||
"reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06"
|
||||
"reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06",
|
||||
"reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06",
|
||||
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/f6811d96d97bdf400077a0cc100ae56aa32b9203",
|
||||
"reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/instantiator": "^1.0.2",
|
||||
"php": "^5.3|^7.0",
|
||||
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0",
|
||||
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0",
|
||||
"sebastian/comparator": "^1.1|^2.0|^3.0",
|
||||
"sebastian/recursion-context": "^1.0|^2.0|^3.0"
|
||||
},
|
||||
|
@ -998,8 +998,8 @@
|
|||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Prophecy\\": "src/"
|
||||
"psr-4": {
|
||||
"Prophecy\\": "src/Prophecy"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
|
@ -1027,7 +1027,7 @@
|
|||
"spy",
|
||||
"stub"
|
||||
],
|
||||
"time": "2018-08-05T17:53:17+00:00"
|
||||
"time": "2019-10-03T11:07:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
|
|
|
@ -106,7 +106,8 @@ Linux distributions.
|
|||
> `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.
|
||||
> [Wikipedia article](https://en.wikipedia.org/wiki/PATH_(variable)) and/or use
|
||||
> your search engine of choice.
|
||||
|
||||
Now run `composer` in order to run Composer instead of `php composer.phar`.
|
||||
|
||||
|
@ -139,7 +140,7 @@ C:\bin>echo @php "%~dp0composer.phar" %*>composer.bat
|
|||
Add the directory to your PATH environment variable if it isn't already.
|
||||
For information on changing your PATH variable, please see
|
||||
[this article](https://www.computerhope.com/issues/ch000549.htm) and/or
|
||||
use Google.
|
||||
use your search engine of choice.
|
||||
|
||||
Close your current terminal. Test usage with a new terminal:
|
||||
|
||||
|
|
|
@ -296,4 +296,9 @@ Example:
|
|||
Defaults to `true`. If set to `false`, Composer will not create `.htaccess` files
|
||||
in the composer home, cache, and data directories.
|
||||
|
||||
## lock
|
||||
|
||||
Defaults to `true`. If set to `false`, Composer will not create a `composer.lock`
|
||||
file.
|
||||
|
||||
← [Repositories](05-repositories.md) | [Community](07-community.md) →
|
||||
|
|
|
@ -339,6 +339,9 @@ One limitation of this is that you can not call multiple commands in
|
|||
a row like `@php install && @php foo`. You must split them up in a
|
||||
JSON array of commands.
|
||||
|
||||
You can also call a shell/bash script, which will have the path to
|
||||
the PHP executable available in it as a `PHP_BINARY` env var.
|
||||
|
||||
## Custom descriptions.
|
||||
|
||||
You can set custom script descriptions with the following in your `composer.json`:
|
||||
|
|
|
@ -211,6 +211,19 @@ To enable the swap you can use for example:
|
|||
```
|
||||
You can make a permanent swap file following this [tutorial](https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04).
|
||||
|
||||
## proc_open(): failed to open stream errors (Windows)
|
||||
|
||||
If composer shows proc_open(NUL) errors on Windows:
|
||||
|
||||
`proc_open(NUL): failed to open stream: No such file or directory`
|
||||
|
||||
This could be happening because you are working in a _OneDrive_ directory and
|
||||
using a version of PHP that does not support the file system semantics of this
|
||||
service. The issue was fixed in PHP 7.2.23 and 7.3.10.
|
||||
|
||||
Alternatively it could be because the Windows Null Service is not enabled. For
|
||||
more information, see this [issue](https://github.com/composer/composer/issues/7186#issuecomment-373134916).
|
||||
|
||||
## Degraded Mode
|
||||
|
||||
Due to some intermittent issues on Travis and other systems, we introduced a
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
},
|
||||
"type": {
|
||||
"description": "Package type, either 'library' for common packages, 'composer-plugin' for plugins, 'metapackage' for empty packages, or a custom type ([a-z0-9-]+) defined by whatever project this package applies to.",
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"pattern": "^[a-z0-9-]+$"
|
||||
},
|
||||
"target-dir": {
|
||||
"description": "DEPRECATED: Forces the package to be installed into the given subdirectory path. This is used for autoloading PSR-0 packages that do not contain their full path. Use forward slashes for cross-platform compatibility.",
|
||||
|
@ -39,7 +40,8 @@
|
|||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes."
|
||||
"description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes.",
|
||||
"pattern": "^v?\\d+(((\\.\\d+)?\\.\\d+)?\\.\\d+)?"
|
||||
},
|
||||
"time": {
|
||||
"type": "string",
|
||||
|
@ -290,6 +292,10 @@
|
|||
"sort-packages": {
|
||||
"type": "boolean",
|
||||
"description": "Defaults to false. If set to true, Composer will sort packages when adding/updating a new dependency."
|
||||
},
|
||||
"lock": {
|
||||
"type": "boolean",
|
||||
"description": "Defaults to true. If set to false, Composer will not create a composer.lock file."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -592,6 +592,9 @@ class ComposerAutoloaderInit$suffix
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::\$loader) {
|
||||
|
|
|
@ -173,7 +173,7 @@ class ClassMapGenerator
|
|||
}
|
||||
}
|
||||
// strip non-php blocks in the file
|
||||
$contents = preg_replace('{\?>.+<\?}s', '?><?', $contents);
|
||||
$contents = preg_replace('{\?>(?:[^<]++|<(?!\?))*+<\?}s', '?><?', $contents);
|
||||
// strip trailing non-php code if needed
|
||||
$pos = strrpos($contents, '?>');
|
||||
if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
|
||||
|
|
|
@ -42,5 +42,7 @@ EOT
|
|||
See https://getcomposer.org/ for more information.</comment>
|
||||
EOT
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ class BaseDependencyCommand extends BaseCommand
|
|||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @param bool $inverted Whether to invert matching process (why-not vs why behaviour)
|
||||
* @return int|null Exit code of the operation.
|
||||
* @return int Exit code of the operation.
|
||||
*/
|
||||
protected function doExecute(InputInterface $input, OutputInterface $output, $inverted = false)
|
||||
{
|
||||
|
|
|
@ -70,5 +70,7 @@ EOT
|
|||
}
|
||||
|
||||
$io->writeError('<info>All caches cleared.</info>');
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -412,6 +412,7 @@ EOT
|
|||
),
|
||||
'github-expose-hostname' => array($booleanValidator, $booleanNormalizer),
|
||||
'htaccess-protect' => array($booleanValidator, $booleanNormalizer),
|
||||
'lock' => array($booleanValidator, $booleanNormalizer),
|
||||
);
|
||||
$multiConfigValues = array(
|
||||
'github-protocols' => array(
|
||||
|
@ -463,13 +464,19 @@ EOT
|
|||
$this->getIO()->writeError('<info>You are now running Composer with SSL/TLS protection enabled.</info>');
|
||||
}
|
||||
|
||||
return $this->configSource->removeConfigSetting($settingKey);
|
||||
$this->configSource->removeConfigSetting($settingKey);
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (isset($uniqueConfigValues[$settingKey])) {
|
||||
return $this->handleSingleValue($settingKey, $uniqueConfigValues[$settingKey], $values, 'addConfigSetting');
|
||||
$this->handleSingleValue($settingKey, $uniqueConfigValues[$settingKey], $values, 'addConfigSetting');
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (isset($multiConfigValues[$settingKey])) {
|
||||
return $this->handleMultiValue($settingKey, $multiConfigValues[$settingKey], $values, 'addConfigSetting');
|
||||
$this->handleMultiValue($settingKey, $multiConfigValues[$settingKey], $values, 'addConfigSetting');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// handle properties
|
||||
|
@ -530,38 +537,51 @@ EOT
|
|||
throw new \InvalidArgumentException('The '.$settingKey.' property can not be set in the global config.json file. Use `composer global config` to apply changes to the global composer.json');
|
||||
}
|
||||
if ($input->getOption('unset') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]))) {
|
||||
return $this->configSource->removeProperty($settingKey);
|
||||
$this->configSource->removeProperty($settingKey);
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (isset($uniqueProps[$settingKey])) {
|
||||
return $this->handleSingleValue($settingKey, $uniqueProps[$settingKey], $values, 'addProperty');
|
||||
$this->handleSingleValue($settingKey, $uniqueProps[$settingKey], $values, 'addProperty');
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (isset($multiProps[$settingKey])) {
|
||||
return $this->handleMultiValue($settingKey, $multiProps[$settingKey], $values, 'addProperty');
|
||||
$this->handleMultiValue($settingKey, $multiProps[$settingKey], $values, 'addProperty');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// handle repositories
|
||||
if (preg_match('/^repos?(?:itories)?\.(.+)/', $settingKey, $matches)) {
|
||||
if ($input->getOption('unset')) {
|
||||
return $this->configSource->removeRepository($matches[1]);
|
||||
$this->configSource->removeRepository($matches[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (2 === count($values)) {
|
||||
return $this->configSource->addRepository($matches[1], array(
|
||||
$this->configSource->addRepository($matches[1], array(
|
||||
'type' => $values[0],
|
||||
'url' => $values[1],
|
||||
));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (1 === count($values)) {
|
||||
$value = strtolower($values[0]);
|
||||
if (true === $booleanValidator($value)) {
|
||||
if (false === $booleanNormalizer($value)) {
|
||||
return $this->configSource->addRepository($matches[1], false);
|
||||
$this->configSource->addRepository($matches[1], false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
$value = JsonFile::parseJson($values[0]);
|
||||
$this->configSource->addRepository($matches[1], $value);
|
||||
|
||||
return $this->configSource->addRepository($matches[1], $value);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -571,22 +591,32 @@ EOT
|
|||
// handle extra
|
||||
if (preg_match('/^extra\.(.+)/', $settingKey, $matches)) {
|
||||
if ($input->getOption('unset')) {
|
||||
return $this->configSource->removeProperty($settingKey);
|
||||
$this->configSource->removeProperty($settingKey);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $this->configSource->addProperty($settingKey, $values[0]);
|
||||
$this->configSource->addProperty($settingKey, $values[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// handle platform
|
||||
if (preg_match('/^platform\.(.+)/', $settingKey, $matches)) {
|
||||
if ($input->getOption('unset')) {
|
||||
return $this->configSource->removeConfigSetting($settingKey);
|
||||
$this->configSource->removeConfigSetting($settingKey);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $this->configSource->addConfigSetting($settingKey, $values[0]);
|
||||
$this->configSource->addConfigSetting($settingKey, $values[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
if ($settingKey === 'platform' && $input->getOption('unset')) {
|
||||
return $this->configSource->removeConfigSetting($settingKey);
|
||||
$this->configSource->removeConfigSetting($settingKey);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// handle auth
|
||||
|
@ -595,7 +625,7 @@ EOT
|
|||
$this->authConfigSource->removeConfigSetting($matches[1].'.'.$matches[2]);
|
||||
$this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
|
||||
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($matches[1] === 'bitbucket-oauth') {
|
||||
|
@ -618,16 +648,20 @@ EOT
|
|||
$this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('username' => $values[0], 'password' => $values[1]));
|
||||
}
|
||||
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// handle script
|
||||
if (preg_match('/^scripts\.(.+)/', $settingKey, $matches)) {
|
||||
if ($input->getOption('unset')) {
|
||||
return $this->configSource->removeProperty($settingKey);
|
||||
$this->configSource->removeProperty($settingKey);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $this->configSource->addProperty($settingKey, count($values) > 1 ? $values : $values[0]);
|
||||
$this->configSource->addProperty($settingKey, count($values) > 1 ? $values : $values[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('Setting '.$settingKey.' does not exist or is not supported by this command');
|
||||
|
|
|
@ -48,7 +48,7 @@ EOT
|
|||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return int|null
|
||||
* @return int
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
|
|
|
@ -84,5 +84,7 @@ EOT
|
|||
} else {
|
||||
$this->getIO()->overwriteError('<info>Generated autoload files containing '. $numberOfClasses .' classes</info>');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,6 +152,8 @@ EOT
|
|||
if ($input->isInteractive() && $this->hasDependencies($options) && $io->askConfirmation($question, true)) {
|
||||
$this->installDependencies($output);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -400,7 +402,7 @@ EOT
|
|||
return $this->repos;
|
||||
}
|
||||
|
||||
protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array(), $phpVersion = null, $preferredStability = 'stable', $checkProvidedVersions = true)
|
||||
final protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array(), $phpVersion = null, $preferredStability = 'stable', $checkProvidedVersions = true, $fixed = false)
|
||||
{
|
||||
if ($requires) {
|
||||
$requires = $this->normalizeRequirements($requires);
|
||||
|
@ -410,7 +412,7 @@ EOT
|
|||
foreach ($requires as $requirement) {
|
||||
if (!isset($requirement['version'])) {
|
||||
// determine the best version automatically
|
||||
list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability);
|
||||
list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, null, null, $fixed);
|
||||
$requirement['version'] = $version;
|
||||
|
||||
// replace package name from packagist.org
|
||||
|
@ -423,7 +425,7 @@ EOT
|
|||
));
|
||||
} else {
|
||||
// check that the specified version/constraint exists before we proceed
|
||||
list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, $checkProvidedVersions ? $requirement['version'] : null, 'dev');
|
||||
list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, $checkProvidedVersions ? $requirement['version'] : null, 'dev', $fixed);
|
||||
|
||||
// replace package name from packagist.org
|
||||
$requirement['name'] = $name;
|
||||
|
@ -700,10 +702,11 @@ EOT
|
|||
* @param string $preferredStability
|
||||
* @param string|null $requiredVersion
|
||||
* @param string $minimumStability
|
||||
* @param bool $fixed
|
||||
* @throws \InvalidArgumentException
|
||||
* @return array name version
|
||||
*/
|
||||
private function findBestVersionAndNameForPackage(InputInterface $input, $name, $phpVersion, $preferredStability = 'stable', $requiredVersion = null, $minimumStability = null)
|
||||
private function findBestVersionAndNameForPackage(InputInterface $input, $name, $phpVersion, $preferredStability = 'stable', $requiredVersion = null, $minimumStability = null, $fixed = null)
|
||||
{
|
||||
// find the latest version allowed in this repo set
|
||||
$versionSelector = new VersionSelector($this->getRepositorySet($input, $minimumStability));
|
||||
|
@ -777,7 +780,7 @@ EOT
|
|||
|
||||
return array(
|
||||
$package->getPrettyName(),
|
||||
$versionSelector->findRecommendedRequireVersion($package),
|
||||
$fixed ? $package->getPrettyVersion() : $versionSelector->findRecommendedRequireVersion($package),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,8 @@ EOT
|
|||
default:
|
||||
throw new \RuntimeException(sprintf('Unsupported format "%s". See help for supported formats.', $format));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -59,7 +59,7 @@ EOT
|
|||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$args = array(
|
||||
'show',
|
||||
'command' => 'show',
|
||||
'--latest' => true,
|
||||
);
|
||||
if (!$input->getOption('all')) {
|
||||
|
|
|
@ -48,7 +48,7 @@ EOT
|
|||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return int|null
|
||||
* @return int
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
|
|
|
@ -49,6 +49,7 @@ class RequireCommand extends InitCommand
|
|||
new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'),
|
||||
new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
|
||||
new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
|
||||
new InputOption('fixed', null, InputOption::VALUE_NONE, 'Write fixed version to the composer.json.'),
|
||||
new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
|
||||
new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
|
||||
new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
|
||||
|
@ -99,7 +100,9 @@ EOT
|
|||
|
||||
return 1;
|
||||
}
|
||||
if (!is_readable($this->file)) {
|
||||
// check for readability by reading the file as is_readable can not be trusted on network-mounts
|
||||
// see https://github.com/composer/composer/issues/8231 and https://bugs.php.net/bug.php?id=68926
|
||||
if (!is_readable($this->file) && false === Silencer::call('file_get_contents', $this->file)) {
|
||||
$io->writeError('<error>'.$this->file.' is not readable.</error>');
|
||||
|
||||
return 1;
|
||||
|
@ -120,6 +123,25 @@ EOT
|
|||
return 1;
|
||||
}
|
||||
|
||||
if ($input->getOption('fixed') === true) {
|
||||
$config = $this->json->read();
|
||||
|
||||
$packageType = empty($config['type']) ? 'library' : $config['type'];
|
||||
|
||||
/**
|
||||
* @see https://github.com/composer/composer/pull/8313#issuecomment-532637955
|
||||
*/
|
||||
if ($packageType !== 'project') {
|
||||
$io->writeError('<error>"--fixed" option is allowed for "project" package types only to prevent possible misuses.</error>');
|
||||
|
||||
if (empty($config['type'])) {
|
||||
$io->writeError('<error>If your package is not library, you should explicitly specify "type" parameter in composer.json.</error>');
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
|
||||
$repos = $composer->getRepositoryManager()->getRepositories();
|
||||
|
||||
|
@ -137,7 +159,7 @@ EOT
|
|||
}
|
||||
|
||||
$phpVersion = $this->repos->findPackage('php', '*')->getPrettyVersion();
|
||||
$requirements = $this->determineRequirements($input, $output, $input->getArgument('packages'), $phpVersion, $preferredStability, !$input->getOption('no-update'));
|
||||
$requirements = $this->determineRequirements($input, $output, $input->getArgument('packages'), $phpVersion, $preferredStability, !$input->getOption('no-update'), $input->getOption('fixed'));
|
||||
|
||||
$requireKey = $input->getOption('dev') ? 'require-dev' : 'require';
|
||||
$removeKey = $input->getOption('dev') ? 'require' : 'require-dev';
|
||||
|
|
|
@ -79,5 +79,7 @@ EOT
|
|||
foreach ($results as $result) {
|
||||
$io->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -254,6 +254,8 @@ TAGSPUBKEY
|
|||
} else {
|
||||
$io->writeError('<warning>A backup of the current version could not be written to '.$backupFile.', no rollback possible</warning>');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function fetchKeys(IOInterface $io, Config $config)
|
||||
|
|
|
@ -129,6 +129,12 @@ EOT
|
|||
return 1;
|
||||
}
|
||||
|
||||
if ($input->getOption('tree') && $input->getOption('path')) {
|
||||
$io->writeError('The --tree (-t) option is not usable in combination with --path (-P)');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$format = $input->getOption('format');
|
||||
if (!in_array($format, array('text', 'json'))) {
|
||||
$io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format));
|
||||
|
@ -586,6 +592,7 @@ EOT
|
|||
}
|
||||
$io->write('<info>type</info> : ' . $package->getType());
|
||||
$this->printLicenses($package);
|
||||
$io->write('<info>homepage</info> : ' . $package->getHomepage());
|
||||
$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()));
|
||||
if ($installedRepo->hasPackage($package)) {
|
||||
|
|
|
@ -61,7 +61,7 @@ EOT
|
|||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return int|null
|
||||
* @return int
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
|
|
|
@ -93,7 +93,7 @@ EOT
|
|||
continue;
|
||||
}
|
||||
foreach ($package['suggest'] as $suggestion => $reason) {
|
||||
if (false === strpos('/', $suggestion) && null !== $platform->findPackage($suggestion, '*')) {
|
||||
if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $suggestion) && null !== $platform->findPackage($suggestion, '*')) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($installed[$suggestion])) {
|
||||
|
@ -121,7 +121,7 @@ EOT
|
|||
$io->write(sprintf('<info>%s</info>', $suggestion));
|
||||
}
|
||||
|
||||
return null;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Grouped by package
|
||||
|
@ -151,5 +151,7 @@ EOT
|
|||
$io->write('');
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ class Config
|
|||
'archive-dir' => '.',
|
||||
'htaccess-protect' => true,
|
||||
'use-github-api' => true,
|
||||
'lock' => true,
|
||||
// valid keys without defaults (auth config stuff):
|
||||
// bitbucket-oauth
|
||||
// github-oauth
|
||||
|
@ -329,6 +330,8 @@ class Config
|
|||
return $this->config[$key] !== 'false' && (bool) $this->config[$key];
|
||||
case 'use-github-api':
|
||||
return $this->config[$key] !== 'false' && (bool) $this->config[$key];
|
||||
case 'lock':
|
||||
return $this->config[$key] !== 'false' && (bool) $this->config[$key];
|
||||
default:
|
||||
if (!isset($this->config[$key])) {
|
||||
return null;
|
||||
|
|
|
@ -113,6 +113,10 @@ class Application extends BaseApplication
|
|||
{
|
||||
$this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
|
||||
|
||||
if (getenv('COMPOSER_NO_INTERACTION')) {
|
||||
$input->setInteractive(false);
|
||||
}
|
||||
|
||||
$io = $this->io = new ConsoleIO($input, $output, new HelperSet(array(
|
||||
new QuestionHelper(),
|
||||
)));
|
||||
|
@ -208,11 +212,7 @@ class Application extends BaseApplication
|
|||
$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']));
|
||||
}
|
||||
|
||||
if (getenv('COMPOSER_NO_INTERACTION')) {
|
||||
$input->setInteractive(false);
|
||||
}
|
||||
|
||||
if (!Platform::isWindows() && function_exists('exec') && !getenv('COMPOSER_ALLOW_SUPERUSER')) {
|
||||
if (!Platform::isWindows() && function_exists('exec') && !getenv('COMPOSER_ALLOW_SUPERUSER') && !file_exists('/.dockerenv')) {
|
||||
if (function_exists('posix_getuid') && posix_getuid() === 0) {
|
||||
if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
|
||||
$io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');
|
||||
|
|
|
@ -183,7 +183,7 @@ class Decisions implements \Iterator, \Countable
|
|||
|
||||
$previousDecision = isset($this->decisionMap[$packageId]) ? $this->decisionMap[$packageId] : null;
|
||||
if ($previousDecision != 0) {
|
||||
$literalString = $this->pool->literalToString($literal);
|
||||
$literalString = $this->pool->literalToPrettyString($literal, array());
|
||||
$package = $this->pool->literalToPackage($literal);
|
||||
throw new SolverBugException(
|
||||
"Trying to decide $literalString on level $level, even though $package was previously decided as ".(int) $previousDecision."."
|
||||
|
|
|
@ -119,7 +119,7 @@ class Installer
|
|||
protected $preferStable = false;
|
||||
protected $preferLowest = false;
|
||||
protected $skipSuggest = false;
|
||||
protected $writeLock = true;
|
||||
protected $writeLock;
|
||||
protected $executeOperations = true;
|
||||
|
||||
/**
|
||||
|
@ -165,6 +165,8 @@ class Installer
|
|||
$this->installationManager = $installationManager;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->autoloadGenerator = $autoloadGenerator;
|
||||
|
||||
$this->writeLock = $config->get('lock');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -98,6 +98,27 @@ abstract class BaseRepository implements RepositoryInterface
|
|||
// Replacements are considered valid reasons for a package to be installed during forward resolution
|
||||
if (!$invert) {
|
||||
$links += $package->getReplaces();
|
||||
|
||||
// On forward search, check if any replaced package was required and add the replaced
|
||||
// packages to the list of needles. Contrary to the cross-reference link check below,
|
||||
// replaced packages are the target of links.
|
||||
foreach ($package->getReplaces() as $link) {
|
||||
foreach ($needles as $needle) {
|
||||
if ($link->getSource() === $needle) {
|
||||
if ($constraint === null || ($link->getConstraint()->matches($constraint) === !$invert)) {
|
||||
// already displayed this node's dependencies, cutting short
|
||||
if (in_array($link->getTarget(), $packagesInTree)) {
|
||||
$results[] = array($package, $link, false);
|
||||
continue;
|
||||
}
|
||||
$packagesInTree[] = $link->getTarget();
|
||||
$dependents = $recurse ? $this->getDependents($link->getTarget(), null, false, true, $packagesInTree) : array();
|
||||
$results[] = array($package, $link, $dependents);
|
||||
$needles[] = $link->getTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Require-dev is only relevant for the root package
|
||||
|
@ -112,12 +133,12 @@ abstract class BaseRepository implements RepositoryInterface
|
|||
if ($constraint === null || ($link->getConstraint()->matches($constraint) === !$invert)) {
|
||||
// already displayed this node's dependencies, cutting short
|
||||
if (in_array($link->getSource(), $packagesInTree)) {
|
||||
$results[$link->getSource()] = array($package, $link, false);
|
||||
$results[] = array($package, $link, false);
|
||||
continue;
|
||||
}
|
||||
$packagesInTree[] = $link->getSource();
|
||||
$dependents = $recurse ? $this->getDependents($link->getSource(), null, false, true, $packagesInTree) : array();
|
||||
$results[$link->getSource()] = array($package, $link, $dependents);
|
||||
$results[] = array($package, $link, $dependents);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,7 +125,13 @@ class PathRepository extends ArrayRepository implements ConfigurableRepositoryIn
|
|||
{
|
||||
parent::initialize();
|
||||
|
||||
foreach ($this->getUrlMatches() as $url) {
|
||||
$urlMatches = $this->getUrlMatches();
|
||||
|
||||
if (empty($urlMatches)) {
|
||||
throw new \RuntimeException('The `url` supplied for the path (' . $this->url . ') repository does not exist');
|
||||
}
|
||||
|
||||
foreach ($urlMatches as $url) {
|
||||
$path = realpath($url) . DIRECTORY_SEPARATOR;
|
||||
$composerFilePath = $path.'composer.json';
|
||||
|
||||
|
@ -155,7 +161,11 @@ class PathRepository extends ArrayRepository implements ConfigurableRepositoryIn
|
|||
|
||||
if (!isset($package['version'])) {
|
||||
$versionData = $this->versionGuesser->guessVersion($package, $path);
|
||||
$package['version'] = $versionData['pretty_version'] ?: 'dev-master';
|
||||
if (is_array($versionData) && $versionData['pretty_version']) {
|
||||
$package['version'] = $versionData['pretty_version'];
|
||||
} else {
|
||||
$package['version'] = 'dev-master';
|
||||
}
|
||||
}
|
||||
|
||||
$output = '';
|
||||
|
|
|
@ -47,7 +47,7 @@ abstract class BitbucketDriver extends VcsDriver
|
|||
*/
|
||||
public function initialize()
|
||||
{
|
||||
preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)$#', $this->url, $match);
|
||||
preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)$#i', $this->url, $match);
|
||||
$this->owner = $match[1];
|
||||
$this->repository = $match[2];
|
||||
$this->originUrl = 'bitbucket.org';
|
||||
|
|
|
@ -53,7 +53,7 @@ class GitBitbucketDriver extends BitbucketDriver
|
|||
*/
|
||||
public static function supports(IOInterface $io, Config $config, $url, $deep = false)
|
||||
{
|
||||
if (!preg_match('#^https?://bitbucket\.org/([^/]+)/(.+?)\.git$#', $url)) {
|
||||
if (!preg_match('#^https?://bitbucket\.org/([^/]+)/(.+?)\.git$#i', $url)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,10 +48,10 @@ class GitHubDriver extends VcsDriver
|
|||
*/
|
||||
public function initialize()
|
||||
{
|
||||
preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $this->url, $match);
|
||||
preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/(.+?)(?:\.git|/)?$#', $this->url, $match);
|
||||
$this->owner = $match[3];
|
||||
$this->repository = $match[4];
|
||||
$this->originUrl = !empty($match[1]) ? $match[1] : $match[2];
|
||||
$this->originUrl = strtolower(!empty($match[1]) ? $match[1] : $match[2]);
|
||||
if ($this->originUrl === 'www.github.com') {
|
||||
$this->originUrl = 'github.com';
|
||||
}
|
||||
|
@ -270,12 +270,12 @@ class GitHubDriver extends VcsDriver
|
|||
*/
|
||||
public static function supports(IOInterface $io, Config $config, $url, $deep = false)
|
||||
{
|
||||
if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $url, $matches)) {
|
||||
if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/(.+?)(?:\.git|/)?$#', $url, $matches)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$originUrl = !empty($matches[2]) ? $matches[2] : $matches[3];
|
||||
if (!in_array(preg_replace('{^www\.}i', '', $originUrl), $config->get('github-domains'))) {
|
||||
if (!in_array(strtolower(preg_replace('{^www\.}i', '', $originUrl)), $config->get('github-domains'))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -497,6 +497,8 @@ class GitLabDriver extends VcsDriver
|
|||
*/
|
||||
private static function determineOrigin(array $configuredDomains, $guessedDomain, array &$urlParts, $portNumber)
|
||||
{
|
||||
$guessedDomain = strtolower($guessedDomain);
|
||||
|
||||
if (in_array($guessedDomain, $configuredDomains) || ($portNumber && in_array($guessedDomain.':'.$portNumber, $configuredDomains))) {
|
||||
if ($portNumber) {
|
||||
return $guessedDomain.':'.$portNumber;
|
||||
|
|
|
@ -53,7 +53,7 @@ class HgBitbucketDriver extends BitbucketDriver
|
|||
*/
|
||||
public static function supports(IOInterface $io, Config $config, $url, $deep = false)
|
||||
{
|
||||
if (!preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+)/?$#', $url)) {
|
||||
if (!preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+)/?$#i', $url)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ class HgDriver extends VcsDriver
|
|||
return sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($repoDir));
|
||||
};
|
||||
|
||||
$hgUtils->runCommand($command, $this->url, $this->repoDir);
|
||||
$hgUtils->runCommand($command, $this->url, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ class AuthHelper
|
|||
{
|
||||
protected $io;
|
||||
protected $config;
|
||||
private $displayedOriginAuthentications = array();
|
||||
|
||||
public function __construct(IOInterface $io, Config $config)
|
||||
{
|
||||
|
@ -172,7 +173,7 @@ class AuthHelper
|
|||
throw new TransportException("Invalid credentials for '" . $url . "', aborting.", $statusCode);
|
||||
}
|
||||
|
||||
$this->io->writeError(' Authentication required (<info>'.parse_url($url, PHP_URL_HOST).'</info>):');
|
||||
$this->io->writeError(' Authentication required (<info>'.$origin.'</info>):');
|
||||
$username = $this->io->ask(' Username: ');
|
||||
$password = $this->io->askAndHideAnswer(' Password: ');
|
||||
$this->io->setAuthentication($origin, $username, $password);
|
||||
|
@ -193,14 +194,18 @@ class AuthHelper
|
|||
public function addAuthenticationHeader(array $headers, $origin, $url)
|
||||
{
|
||||
if ($this->io->hasAuthentication($origin)) {
|
||||
$authenticationDisplayMessage = null;
|
||||
$auth = $this->io->getAuthentication($origin);
|
||||
if ('github.com' === $origin && 'x-oauth-basic' === $auth['password']) {
|
||||
$headers[] = 'Authorization: token '.$auth['username'];
|
||||
$authenticationDisplayMessage = 'Using GitHub token authentication';
|
||||
} elseif (in_array($origin, $this->config->get('gitlab-domains'), true)) {
|
||||
if ($auth['password'] === 'oauth2') {
|
||||
$headers[] = 'Authorization: Bearer '.$auth['username'];
|
||||
$authenticationDisplayMessage = 'Using GitLab OAuth token authentication';
|
||||
} elseif ($auth['password'] === 'private-token') {
|
||||
$headers[] = 'PRIVATE-TOKEN: '.$auth['username'];
|
||||
$authenticationDisplayMessage = 'Using GitLab private token authentication';
|
||||
}
|
||||
} elseif (
|
||||
'bitbucket.org' === $origin
|
||||
|
@ -209,10 +214,17 @@ class AuthHelper
|
|||
) {
|
||||
if (!$this->isPublicBitBucketDownload($url)) {
|
||||
$headers[] = 'Authorization: Bearer ' . $auth['password'];
|
||||
$authenticationDisplayMessage = 'Using Bitbucket OAuth token authentication';
|
||||
}
|
||||
} else {
|
||||
$authStr = base64_encode($auth['username'] . ':' . $auth['password']);
|
||||
$headers[] = 'Authorization: Basic '.$authStr;
|
||||
$authenticationDisplayMessage = 'Using HTTP basic authentication with username "' . $auth['username'] . '"';
|
||||
}
|
||||
|
||||
if ($authenticationDisplayMessage && !in_array($origin, $this->displayedOriginAuthentications, true)) {
|
||||
$this->io->writeError($authenticationDisplayMessage, true, IOInterface::DEBUG);
|
||||
$this->displayedOriginAuthentications[] = $origin;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,4 +255,15 @@ class AuthHelper
|
|||
|
||||
return count($pathParts) >= 4 && $pathParts[3] == 'downloads';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @return string
|
||||
*/
|
||||
public function stripCredentialsFromUrl($url)
|
||||
{
|
||||
// GitHub repository rename result in redirect locations containing the access_token as GET parameter
|
||||
// e.g. https://api.github.com/repositories/9999999999?access_token=github_token
|
||||
return preg_replace('{([&?]access_token=)[^&]+}', '$1***', $url);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -687,12 +687,14 @@ class Filesystem
|
|||
if (!Platform::isWindows()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Important to clear all caches first
|
||||
clearstatcache(true, $junction);
|
||||
|
||||
if (!is_dir($junction) || is_link($junction)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Important to clear all caches first
|
||||
clearstatcache(true, $junction);
|
||||
$stat = lstat($junction);
|
||||
|
||||
// S_ISDIR test (S_IFDIR is 0x4000, S_IFMT is 0xF000 bitmask)
|
||||
|
|
|
@ -193,7 +193,7 @@ class Git
|
|||
}
|
||||
}
|
||||
|
||||
$this->io->writeError(' Authentication required (<info>' . parse_url($url, PHP_URL_HOST) . '</info>):');
|
||||
$this->io->writeError(' Authentication required (<info>' . $match[2] . '</info>):');
|
||||
$auth = array(
|
||||
'username' => $this->io->ask(' Username: ', $defaultUsername),
|
||||
'password' => $this->io->askAndHideAnswer(' Password: '),
|
||||
|
|
|
@ -195,7 +195,7 @@ class CurlDownloader
|
|||
$usingProxy = !empty($options['http']['proxy']) ? ' using proxy ' . $options['http']['proxy'] : '';
|
||||
$ifModified = false !== strpos(strtolower(implode(',', $options['http']['header'])), 'if-modified-since:') ? ' if modified' : '';
|
||||
if ($attributes['redirects'] === 0) {
|
||||
$this->io->writeError('Downloading ' . $url . $usingProxy . $ifModified, true, IOInterface::DEBUG);
|
||||
$this->io->writeError('Downloading ' . $this->authHelper->stripCredentialsFromUrl($url) . $usingProxy . $ifModified, true, IOInterface::DEBUG);
|
||||
}
|
||||
|
||||
$this->checkCurlResult(curl_multi_add_handle($this->multiHandle, $curlHandle));
|
||||
|
@ -254,12 +254,12 @@ class CurlDownloader
|
|||
$contents = stream_get_contents($job['bodyHandle']);
|
||||
}
|
||||
$response = new Response(array('url' => $progress['url']), $statusCode, $headers, $contents);
|
||||
$this->io->writeError('['.$statusCode.'] '.$progress['url'], true, IOInterface::DEBUG);
|
||||
$this->io->writeError('['.$statusCode.'] '.$this->authHelper->stripCredentialsFromUrl($progress['url']), true, IOInterface::DEBUG);
|
||||
} else {
|
||||
rewind($job['bodyHandle']);
|
||||
$contents = stream_get_contents($job['bodyHandle']);
|
||||
$response = new Response(array('url' => $progress['url']), $statusCode, $headers, $contents);
|
||||
$this->io->writeError('['.$statusCode.'] '.$progress['url'], true, IOInterface::DEBUG);
|
||||
$this->io->writeError('['.$statusCode.'] '.$this->authHelper->stripCredentialsFromUrl($progress['url']), true, IOInterface::DEBUG);
|
||||
}
|
||||
fclose($job['bodyHandle']);
|
||||
|
||||
|
@ -362,7 +362,7 @@ class CurlDownloader
|
|||
}
|
||||
|
||||
if (!empty($targetUrl)) {
|
||||
$this->io->writeError(sprintf('Following redirect (%u) %s', $job['attributes']['redirects'] + 1, $targetUrl), true, IOInterface::DEBUG);
|
||||
$this->io->writeError(sprintf('Following redirect (%u) %s', $job['attributes']['redirects'] + 1, $this->authHelper->stripCredentialsFromUrl($targetUrl)), true, IOInterface::DEBUG);
|
||||
|
||||
return $targetUrl;
|
||||
}
|
||||
|
|
|
@ -246,7 +246,7 @@ class RemoteFilesystem
|
|||
|
||||
$actualContextOptions = stream_context_get_options($ctx);
|
||||
$usingProxy = !empty($actualContextOptions['http']['proxy']) ? ' using proxy ' . $actualContextOptions['http']['proxy'] : '';
|
||||
$this->io->writeError((substr($origFileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $origFileUrl . $usingProxy, true, IOInterface::DEBUG);
|
||||
$this->io->writeError((substr($origFileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $this->authHelper->stripCredentialsFromUrl($origFileUrl) . $usingProxy, true, IOInterface::DEBUG);
|
||||
unset($origFileUrl, $actualContextOptions);
|
||||
|
||||
// Check for secure HTTP, but allow insecure Packagist calls to $hashed providers as file integrity is verified with sha256
|
||||
|
@ -704,7 +704,7 @@ class RemoteFilesystem
|
|||
$this->redirects++;
|
||||
|
||||
$this->io->writeError('', true, IOInterface::DEBUG);
|
||||
$this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, $targetUrl), true, IOInterface::DEBUG);
|
||||
$this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, $this->authHelper->stripCredentialsFromUrl($targetUrl)), true, IOInterface::DEBUG);
|
||||
|
||||
$additionalOptions['redirects'] = $this->redirects;
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ class Zip
|
|||
* Gets content of the root composer.json inside a ZIP archive.
|
||||
*
|
||||
* @param string $pathToZip
|
||||
* @param string $filename
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
|
|
|
@ -25,12 +25,18 @@ class ApplicationTest extends TestCase
|
|||
$inputMock = $this->getMockBuilder('Symfony\Component\Console\Input\InputInterface')->getMock();
|
||||
$outputMock = $this->getMockBuilder('Symfony\Component\Console\Output\OutputInterface')->getMock();
|
||||
|
||||
putenv('COMPOSER_NO_INTERACTION=1');
|
||||
|
||||
$index = 0;
|
||||
$inputMock->expects($this->at($index++))
|
||||
->method('hasParameterOption')
|
||||
->with($this->equalTo('--no-plugins'))
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$inputMock->expects($this->at($index++))
|
||||
->method('setInteractive')
|
||||
->with($this->equalTo(false));
|
||||
|
||||
$inputMock->expects($this->at($index++))
|
||||
->method('hasParameterOption')
|
||||
->with($this->equalTo('--no-cache'))
|
||||
|
@ -83,12 +89,18 @@ class ApplicationTest extends TestCase
|
|||
$inputMock = $this->getMockBuilder('Symfony\Component\Console\Input\InputInterface')->getMock();
|
||||
$outputMock = $this->getMockBuilder('Symfony\Component\Console\Output\OutputInterface')->getMock();
|
||||
|
||||
putenv('COMPOSER_NO_INTERACTION=1');
|
||||
|
||||
$index = 0;
|
||||
$inputMock->expects($this->at($index++))
|
||||
->method('hasParameterOption')
|
||||
->with($this->equalTo('--no-plugins'))
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$inputMock->expects($this->at($index++))
|
||||
->method('setInteractive')
|
||||
->with($this->equalTo(false));
|
||||
|
||||
$inputMock->expects($this->at($index++))
|
||||
->method('hasParameterOption')
|
||||
->with($this->equalTo('--no-cache'))
|
||||
|
|
|
@ -13,6 +13,9 @@ class ComposerAutoloaderInitFilesAutoloadOrder
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
|
|
|
@ -13,6 +13,9 @@ class ComposerAutoloaderInitFilesAutoload
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
|
|
|
@ -13,6 +13,9 @@ class ComposerAutoloaderInitFilesAutoload
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
|
|
|
@ -13,6 +13,9 @@ class ComposerAutoloaderInitFilesAutoload
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
|
|
|
@ -13,6 +13,9 @@ class ComposerAutoloaderInitIncludePath
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
|
|
|
@ -13,6 +13,9 @@ class ComposerAutoloaderInitTargetDir
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
|
|
|
@ -1385,6 +1385,10 @@ namespace Foo;
|
|||
<?php
|
||||
class LargeGap
|
||||
{
|
||||
public function a1380() { var_dump(var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null)); }
|
||||
public function test_double_gap() { var_dump(var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null));
|
||||
?>
|
||||
public function a1381() { var_dump(var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null), var_dump(null)); }
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
--TEST--
|
||||
Installs from composer.json without writing a lock file
|
||||
--COMPOSER--
|
||||
{
|
||||
"repositories": [
|
||||
{
|
||||
"type": "package",
|
||||
"package": [
|
||||
{ "name": "a/a", "version": "1.0.0" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"a/a": "1.0.0"
|
||||
},
|
||||
"config": {
|
||||
"lock": "false"
|
||||
}
|
||||
}
|
||||
--RUN--
|
||||
install
|
||||
--EXPECT--
|
||||
Installing a/a (1.0.0)
|
||||
--EXPECT-LOCK--
|
||||
false
|
|
@ -0,0 +1,25 @@
|
|||
--TEST--
|
||||
Updates when no lock file is present without writing a lock file
|
||||
--COMPOSER--
|
||||
{
|
||||
"repositories": [
|
||||
{
|
||||
"type": "package",
|
||||
"package": [
|
||||
{ "name": "a/a", "version": "1.0.0" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"a/a": "1.0.0"
|
||||
},
|
||||
"config": {
|
||||
"lock": false
|
||||
}
|
||||
}
|
||||
--RUN--
|
||||
update
|
||||
--EXPECT--
|
||||
Installing a/a (1.0.0)
|
||||
--EXPECT-LOCK--
|
||||
false
|
|
@ -199,6 +199,9 @@ class InstallerTest extends TestCase
|
|||
// so store value temporarily in reference for later assetion
|
||||
$actualLock = $hash;
|
||||
}));
|
||||
} elseif ($expectLock === false) {
|
||||
$lockJsonMock->expects($this->never())
|
||||
->method('write');
|
||||
}
|
||||
|
||||
$contents = json_encode($composerConfig);
|
||||
|
@ -282,15 +285,15 @@ class InstallerTest extends TestCase
|
|||
continue;
|
||||
}
|
||||
|
||||
$testData = $this->readTestFile($file, $fixturesDir);
|
||||
|
||||
$installed = array();
|
||||
$installedDev = array();
|
||||
$lock = array();
|
||||
$expectLock = array();
|
||||
$expectResult = 0;
|
||||
|
||||
try {
|
||||
$testData = $this->readTestFile($file, $fixturesDir);
|
||||
|
||||
$installed = array();
|
||||
$installedDev = array();
|
||||
$lock = array();
|
||||
$expectLock = array();
|
||||
$expectResult = 0;
|
||||
|
||||
$message = $testData['TEST'];
|
||||
$condition = !empty($testData['CONDITION']) ? $testData['CONDITION'] : null;
|
||||
$composer = JsonFile::parseJson($testData['COMPOSER']);
|
||||
|
@ -321,7 +324,11 @@ class InstallerTest extends TestCase
|
|||
}
|
||||
$run = $testData['RUN'];
|
||||
if (!empty($testData['EXPECT-LOCK'])) {
|
||||
$expectLock = JsonFile::parseJson($testData['EXPECT-LOCK']);
|
||||
if ($testData['EXPECT-LOCK'] === 'false') {
|
||||
$expectLock = false;
|
||||
} else {
|
||||
$expectLock = JsonFile::parseJson($testData['EXPECT-LOCK']);
|
||||
}
|
||||
}
|
||||
$expectOutput = isset($testData['EXPECT-OUTPUT']) ? $testData['EXPECT-OUTPUT'] : null;
|
||||
$expect = $testData['EXPECT'];
|
||||
|
|
|
@ -19,6 +19,22 @@ use Composer\Package\Version\VersionParser;
|
|||
|
||||
class PathRepositoryTest extends TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @expectedException RuntimeException
|
||||
*/
|
||||
public function testLoadPackageFromFileSystemWithIncorrectPath()
|
||||
{
|
||||
$ioInterface = $this->getMockBuilder('Composer\IO\IOInterface')
|
||||
->getMock();
|
||||
|
||||
$config = new \Composer\Config();
|
||||
|
||||
$repositoryUrl = implode(DIRECTORY_SEPARATOR, array(__DIR__, 'Fixtures', 'path', 'missing'));
|
||||
$repository = new PathRepository(array('url' => $repositoryUrl), $ioInterface, $config);
|
||||
$repository->getPackages();
|
||||
}
|
||||
|
||||
public function testLoadPackageFromFileSystemWithVersion()
|
||||
{
|
||||
$ioInterface = $this->getMockBuilder('Composer\IO\IOInterface')
|
||||
|
|
|
@ -300,16 +300,16 @@ class FilesystemTest extends TestCase
|
|||
|
||||
// Create and detect junction
|
||||
$fs->junction($target, $junction);
|
||||
$this->assertTrue($fs->isJunction($junction));
|
||||
$this->assertFalse($fs->isJunction($target));
|
||||
$this->assertTrue($fs->isJunction($target . '/../../junction'));
|
||||
$this->assertFalse($fs->isJunction($junction . '/../real'));
|
||||
$this->assertTrue($fs->isJunction($junction . '/../junction'));
|
||||
$this->assertTrue($fs->isJunction($junction), $junction . ': is a junction');
|
||||
$this->assertFalse($fs->isJunction($target), $target . ': is not a junction');
|
||||
$this->assertTrue($fs->isJunction($target . '/../../junction'), $target . '/../../junction: is a junction');
|
||||
$this->assertFalse($fs->isJunction($junction . '/../real'), $junction . '/../real: is not a junction');
|
||||
$this->assertTrue($fs->isJunction($junction . '/../junction'), $junction . '/../junction: is a junction');
|
||||
|
||||
// Remove junction
|
||||
$this->assertTrue(is_dir($junction));
|
||||
$this->assertTrue($fs->removeJunction($junction));
|
||||
$this->assertFalse(is_dir($junction));
|
||||
$this->assertTrue(is_dir($junction), $junction . ' is a directory');
|
||||
$this->assertTrue($fs->removeJunction($junction), $junction . ' has been removed');
|
||||
$this->assertFalse(is_dir($junction), $junction . ' is not a directory');
|
||||
}
|
||||
|
||||
public function testCopy()
|
||||
|
|
Loading…
Reference in New Issue