Merge branch 'master' into 2.0
* master: (48 commits) SVN: hide passwords for debug output Free $solver asap fixes #8179 [minor] Fixed a typo in the CHANGELOG.md. Update deps Update changelog Revert "Allow overriding self-update target file with envvar COMPOSER_SELF_UPDATE_TARGET" Revert "Add docs for COMPOSER_SELF_UPDATE_TARGET, refs #8151" Add docs for COMPOSER_SELF_UPDATE_TARGET, refs #8151 Fix display of HHVM warning appearing when HHVM is not in use, fixes #8138 Read classmap-authoritative and apcu-autoloader from project config when installing via create-project, fixes #8155 Use possessive quantifiers Update xdebug-handler to 1.3.3 fixes #8159 Allow overriding self-update target file with envvar COMPOSER_SELF_UPDATE_TARGET flag should come before script name use full command name, not abbreviated/alias modify text Document the alternatives to disable the default script timeout Anchor pattern Fix URL resolution for Composer repositories ...pull/8223/head
commit
d2fa1e1319
|
@ -10,3 +10,8 @@
|
|||
|
||||
# Exclude non-essential files from dist
|
||||
/tests export-ignore
|
||||
.github export-ignore
|
||||
.php_cs export-ignore
|
||||
.travis.yml export-ignore
|
||||
appveyor.yml export-ignore
|
||||
phpunit.xml.dist export-ignore
|
||||
|
|
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -1,3 +1,17 @@
|
|||
### [1.8.6] 2019-06-11
|
||||
|
||||
* Fixed handling of backslash-escapes handling in composer.json when using the require command
|
||||
* Fixed create-project not following classmap-authoritative and apcu-autoloader config values
|
||||
* Fixed HHVM version warning showing up in some cases when it was not in use
|
||||
|
||||
### [1.8.5] 2019-04-09
|
||||
|
||||
* HHVM 4.0 is no longer compatible with Composer. Please use PHP instead going forward.
|
||||
* Added forward compatibility with upcoming 2.0 changes
|
||||
* Fixed support for PHP 7.3-style heredoc/nowdoc syntax changes in autoload generation
|
||||
* Fixed require command usage when combined with --ignore-platform-reqs
|
||||
* Fixed and cleaned up various Windows junctions handling issues
|
||||
|
||||
### [1.8.4] 2019-02-11
|
||||
|
||||
* Fixed long standing solver bug leading to odd solving issues in edge cases, see #7946
|
||||
|
@ -737,6 +751,8 @@
|
|||
|
||||
* Initial release
|
||||
|
||||
[1.8.6]: https://github.com/composer/composer/compare/1.8.5...1.8.6
|
||||
[1.8.5]: https://github.com/composer/composer/compare/1.8.4...1.8.5
|
||||
[1.8.4]: https://github.com/composer/composer/compare/1.8.3...1.8.4
|
||||
[1.8.3]: https://github.com/composer/composer/compare/1.8.2...1.8.3
|
||||
[1.8.2]: https://github.com/composer/composer/compare/1.8.1...1.8.2
|
||||
|
|
|
@ -126,24 +126,23 @@
|
|||
},
|
||||
{
|
||||
"name": "composer/spdx-licenses",
|
||||
"version": "1.5.0",
|
||||
"version": "1.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/spdx-licenses.git",
|
||||
"reference": "7a9556b22bd9d4df7cad89876b00af58ef20d3a2"
|
||||
"reference": "a1aa51cf3ab838b83b0867b14e56fc20fbd55b3d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/spdx-licenses/zipball/7a9556b22bd9d4df7cad89876b00af58ef20d3a2",
|
||||
"reference": "7a9556b22bd9d4df7cad89876b00af58ef20d3a2",
|
||||
"url": "https://api.github.com/repos/composer/spdx-licenses/zipball/a1aa51cf3ab838b83b0867b14e56fc20fbd55b3d",
|
||||
"reference": "a1aa51cf3ab838b83b0867b14e56fc20fbd55b3d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"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-mock-objects": "2.3.0 || ^3.0"
|
||||
"phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 7"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
|
@ -183,20 +182,20 @@
|
|||
"spdx",
|
||||
"validator"
|
||||
],
|
||||
"time": "2018-11-01T09:45:54+00:00"
|
||||
"time": "2019-03-26T10:23:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/xdebug-handler",
|
||||
"version": "1.3.2",
|
||||
"version": "1.3.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/xdebug-handler.git",
|
||||
"reference": "d17708133b6c276d6e42ef887a877866b909d892"
|
||||
"reference": "46867cbf8ca9fb8d60c506895449eb799db1184f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/d17708133b6c276d6e42ef887a877866b909d892",
|
||||
"reference": "d17708133b6c276d6e42ef887a877866b909d892",
|
||||
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/46867cbf8ca9fb8d60c506895449eb799db1184f",
|
||||
"reference": "46867cbf8ca9fb8d60c506895449eb799db1184f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -227,7 +226,7 @@
|
|||
"Xdebug",
|
||||
"performance"
|
||||
],
|
||||
"time": "2019-01-28T20:25:53+00:00"
|
||||
"time": "2019-05-27T17:52:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "justinrainbow/json-schema",
|
||||
|
@ -481,7 +480,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v2.8.49",
|
||||
"version": "v2.8.50",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
|
@ -542,7 +541,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/debug",
|
||||
"version": "v2.8.49",
|
||||
"version": "v2.8.50",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/debug.git",
|
||||
|
@ -599,7 +598,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v2.8.49",
|
||||
"version": "v2.8.50",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
|
@ -649,7 +648,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v2.8.49",
|
||||
"version": "v2.8.50",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
|
@ -698,16 +697,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.10.0",
|
||||
"version": "v1.11.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "e3d826245268269cd66f8326bd8bc066687b4a19"
|
||||
"reference": "82ebae02209c21113908c229e9883c419720738a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19",
|
||||
"reference": "e3d826245268269cd66f8326bd8bc066687b4a19",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a",
|
||||
"reference": "82ebae02209c21113908c229e9883c419720738a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -719,7 +718,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.9-dev"
|
||||
"dev-master": "1.11-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -752,20 +751,20 @@
|
|||
"polyfill",
|
||||
"portable"
|
||||
],
|
||||
"time": "2018-08-06T14:22:27+00:00"
|
||||
"time": "2019-02-06T07:57:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.10.0",
|
||||
"version": "v1.11.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "c79c051f5b3a46be09205c73b80b346e4153e494"
|
||||
"reference": "fe5e94c604826c35a32fa832f35bd036b6799609"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
|
||||
"reference": "c79c051f5b3a46be09205c73b80b346e4153e494",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609",
|
||||
"reference": "fe5e94c604826c35a32fa832f35bd036b6799609",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -777,7 +776,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.9-dev"
|
||||
"dev-master": "1.11-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -811,11 +810,11 @@
|
|||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2018-09-21T13:07:52+00:00"
|
||||
"time": "2019-02-06T07:57:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v2.8.49",
|
||||
"version": "v2.8.50",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
|
@ -1780,7 +1779,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v2.8.49",
|
||||
"version": "v2.8.50",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
|
|
|
@ -920,6 +920,10 @@ If you use a proxy but it does not support the request_fulluri flag for HTTPS
|
|||
requests, then you should set this env var to `false` or `0` to prevent Composer
|
||||
from setting the request_fulluri option.
|
||||
|
||||
### COMPOSER_SELF_UPDATE_TARGET
|
||||
|
||||
If set, makes the self-update command write the new Composer phar file into that path instead of overwriting itself. Useful for updating Composer on read-only filesystem.
|
||||
|
||||
### no_proxy or NO_PROXY
|
||||
|
||||
If you are behind a proxy and would like to disable it for certain domains, you
|
||||
|
|
|
@ -9,6 +9,20 @@ Defaults to `300`. The duration processes like git clones can run before
|
|||
Composer assumes they died out. You may need to make this higher if you have a
|
||||
slow connection or huge vendors.
|
||||
|
||||
To disable the process timeout on a custom command under `scripts`, a static
|
||||
helper is available:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"test": [
|
||||
"Composer\\Config::disableProcessTimeout",
|
||||
"phpunit"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## use-include-path
|
||||
|
||||
Defaults to `false`. If `true`, the Composer autoloader will also look for classes
|
||||
|
|
|
@ -261,6 +261,11 @@ Now the `custom-plugin-command` is available alongside Composer commands.
|
|||
|
||||
> _Composer commands are based on the [Symfony Console Component][10]._
|
||||
|
||||
## Running plugins manually
|
||||
|
||||
Plugins for an event can be run manually by the `run-script` command. This works the same way as
|
||||
[running scripts manually](scripts.md#running-scripts-manually).
|
||||
|
||||
## Using Plugins
|
||||
|
||||
Plugin packages are automatically loaded as soon as they are installed and will
|
||||
|
|
|
@ -189,7 +189,7 @@ composer run-script [--dev] [--no-dev] script
|
|||
```
|
||||
|
||||
For example `composer run-script post-install-cmd` will run any
|
||||
**post-install-cmd** scripts that have been defined.
|
||||
**post-install-cmd** scripts and [plugins](plugins.md) that have been defined.
|
||||
|
||||
You can also give additional arguments to the script handler by appending `--`
|
||||
followed by the handler arguments. e.g.
|
||||
|
@ -221,6 +221,56 @@ to the `phpunit` script.
|
|||
> are easily accessible. In this example no matter if the `phpunit` binary is
|
||||
> actually in `vendor/bin/phpunit` or `bin/phpunit` it will be found and executed.
|
||||
|
||||
Although Composer is not intended to manage long-running processes and other
|
||||
such aspects of PHP projects, it can sometimes be handy to disable the process
|
||||
timeout on custom commands. This timeout defaults to 300 seconds and can be
|
||||
overridden in a variety of ways depending on the desired effect:
|
||||
|
||||
- disable it for all commands using the config key `process-timeout`,
|
||||
- disable it for the current or future invocations of composer using the
|
||||
environment variable `COMPOSER_PROCESS_TIMEOUT`,
|
||||
- for a specific invocation using the `--timeout` flag of the `run-script` command,
|
||||
- using a static helper for specific scripts.
|
||||
|
||||
To disable the timeout for specific scripts with the static helper directly in
|
||||
composer.json:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"test": [
|
||||
"Composer\\Config::disableProcessTimeout",
|
||||
"phpunit"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To disable the timeout for every script on a given project, you can use the
|
||||
composer.json configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"config": {
|
||||
"process-timeout": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It's also possible to set the global environment variable to disable the timeout
|
||||
of all following scripts in the current terminal environment:
|
||||
|
||||
```
|
||||
export COMPOSER_PROCESS_TIMEOUT=0
|
||||
```
|
||||
|
||||
To disable the timeout of a single script call, you must use the `run-script` composer
|
||||
command and specify the `--timeout` parameter:
|
||||
|
||||
```
|
||||
composer run-script --timeout=0 test
|
||||
```
|
||||
|
||||
## Referencing scripts
|
||||
|
||||
To enable script re-use and avoid duplicates, you can call a script from another
|
||||
|
|
|
@ -32,7 +32,7 @@ repository:*
|
|||
v1
|
||||
v2
|
||||
my-feature
|
||||
nother-feature
|
||||
another-feature
|
||||
|
||||
~/my-library$ git tag
|
||||
v1.0
|
||||
|
|
|
@ -21,6 +21,7 @@ use Composer\Package\PackageInterface;
|
|||
use Composer\Repository\InstalledRepositoryInterface;
|
||||
use Composer\Util\Filesystem;
|
||||
use Composer\Script\ScriptEvents;
|
||||
use Composer\Util\PackageSorter;
|
||||
|
||||
/**
|
||||
* @author Igor Wiedler <igor@wiedler.ch>
|
||||
|
@ -545,7 +546,7 @@ EOF;
|
|||
}
|
||||
}
|
||||
|
||||
if (preg_match('/\.phar.+$/', $path)) {
|
||||
if (strpos($path, '.phar') !== false) {
|
||||
$baseDir = "'phar://' . " . $baseDir;
|
||||
}
|
||||
|
||||
|
@ -769,10 +770,14 @@ HEADER;
|
|||
$filesystem = new Filesystem();
|
||||
|
||||
$vendorPathCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
|
||||
$vendorPharPathCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
|
||||
$appBaseDirCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
|
||||
$appBaseDirPharCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
|
||||
|
||||
$absoluteVendorPathCode = ' => ' . substr(var_export(rtrim($vendorDir, '\\/') . '/', true), 0, -1);
|
||||
$absoluteVendorPharPathCode = ' => ' . substr(var_export(rtrim('phar://' . $vendorDir, '\\/') . '/', true), 0, -1);
|
||||
$absoluteAppBaseDirCode = ' => ' . substr(var_export(rtrim($baseDir, '\\/') . '/', true), 0, -1);
|
||||
$absoluteAppBaseDirPharCode = ' => ' . substr(var_export(rtrim('phar://' . $baseDir, '\\/') . '/', true), 0, -1);
|
||||
|
||||
$initializer = '';
|
||||
$prefix = "\0Composer\Autoload\ClassLoader\0";
|
||||
|
@ -795,9 +800,15 @@ HEADER;
|
|||
// See https://bugs.php.net/68057
|
||||
$staticPhpVersion = 70000;
|
||||
}
|
||||
$value = var_export($value, true);
|
||||
$value = str_replace($absoluteVendorPathCode, $vendorPathCode, $value);
|
||||
$value = str_replace($absoluteAppBaseDirCode, $appBaseDirCode, $value);
|
||||
$value = strtr(
|
||||
var_export($value, true),
|
||||
array(
|
||||
$absoluteVendorPathCode => $vendorPathCode,
|
||||
$absoluteVendorPharPathCode => $vendorPharPathCode,
|
||||
$absoluteAppBaseDirCode => $appBaseDirCode,
|
||||
$absoluteAppBaseDirPharCode => $appBaseDirPharCode,
|
||||
)
|
||||
);
|
||||
$value = ltrim(preg_replace('/^ */m', ' $0$0', $value));
|
||||
|
||||
$file .= sprintf(" public static $%s = %s;\n\n", $prop, $value);
|
||||
|
@ -963,80 +974,21 @@ INITIALIZER;
|
|||
{
|
||||
$packages = array();
|
||||
$paths = array();
|
||||
$usageList = array();
|
||||
|
||||
foreach ($packageMap as $item) {
|
||||
list($package, $path) = $item;
|
||||
$name = $package->getName();
|
||||
$packages[$name] = $package;
|
||||
$paths[$name] = $path;
|
||||
|
||||
foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) {
|
||||
$target = $link->getTarget();
|
||||
$usageList[$target][] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
$computing = array();
|
||||
$computed = array();
|
||||
$computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) {
|
||||
// reusing computed importance
|
||||
if (isset($computed[$name])) {
|
||||
return $computed[$name];
|
||||
}
|
||||
$sortedPackages = PackageSorter::sortPackages($packages);
|
||||
|
||||
// canceling circular dependency
|
||||
if (isset($computing[$name])) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$computing[$name] = true;
|
||||
$weight = 0;
|
||||
|
||||
if (isset($usageList[$name])) {
|
||||
foreach ($usageList[$name] as $user) {
|
||||
$weight -= 1 - $computeImportance($user);
|
||||
}
|
||||
}
|
||||
|
||||
unset($computing[$name]);
|
||||
$computed[$name] = $weight;
|
||||
|
||||
return $weight;
|
||||
};
|
||||
|
||||
$weightList = array();
|
||||
|
||||
foreach ($packages as $name => $package) {
|
||||
$weight = $computeImportance($name);
|
||||
$weightList[$name] = $weight;
|
||||
}
|
||||
|
||||
$stable_sort = function (&$array) {
|
||||
static $transform, $restore;
|
||||
|
||||
$i = 0;
|
||||
|
||||
if (!$transform) {
|
||||
$transform = function (&$v, $k) use (&$i) {
|
||||
$v = array($v, ++$i, $k, $v);
|
||||
};
|
||||
|
||||
$restore = function (&$v, $k) {
|
||||
$v = $v[3];
|
||||
};
|
||||
}
|
||||
|
||||
array_walk($array, $transform);
|
||||
asort($array);
|
||||
array_walk($array, $restore);
|
||||
};
|
||||
|
||||
$stable_sort($weightList);
|
||||
|
||||
$sortedPackageMap = array();
|
||||
|
||||
foreach (array_keys($weightList) as $name) {
|
||||
foreach ($sortedPackages as $package) {
|
||||
$name = $package->getName();
|
||||
$sortedPackageMap[] = array($packages[$name], $paths[$name]);
|
||||
}
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ class ClassMapGenerator
|
|||
}
|
||||
|
||||
// strip heredocs/nowdocs
|
||||
$contents = preg_replace('{<<<\s*(\'?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\2(?=\r\n|\n|\r|;)}s', 'null', $contents);
|
||||
$contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)(?:\s*)\\2(?=\s+|[;,.)])}s', 'null', $contents);
|
||||
// strip strings
|
||||
$contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
|
||||
// strip leading non-php code if needed
|
||||
|
|
|
@ -184,7 +184,9 @@ EOT
|
|||
->setRunScripts(!$noScripts)
|
||||
->setIgnorePlatformRequirements($ignorePlatformReqs)
|
||||
->setSuggestedPackagesReporter($this->suggestedPackagesReporter)
|
||||
->setOptimizeAutoloader($config->get('optimize-autoloader'));
|
||||
->setOptimizeAutoloader($config->get('optimize-autoloader'))
|
||||
->setClassMapAuthoritative($config->get('classmap-authoritative'))
|
||||
->setApcuAutoloader($config->get('apcu-autoloader'));
|
||||
|
||||
if ($disablePlugins) {
|
||||
$installer->disablePlugins();
|
||||
|
|
|
@ -25,6 +25,7 @@ use Composer\Plugin\CommandEvent;
|
|||
use Composer\Plugin\PluginEvents;
|
||||
use Composer\Repository\CompositeRepository;
|
||||
use Composer\Repository\PlatformRepository;
|
||||
use Composer\IO\IOInterface;
|
||||
|
||||
/**
|
||||
* @author Jérémy Romey <jeremy@free-agent.fr>
|
||||
|
@ -160,15 +161,26 @@ EOT
|
|||
if ($input->getOption('no-update')) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
try {
|
||||
return $this->doUpdate($input, $output, $io, $requirements);
|
||||
} catch (\Exception $e) {
|
||||
$this->revertComposerFile(false);
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
private function doUpdate(InputInterface $input, OutputInterface $output, IOInterface $io, array $requirements)
|
||||
{
|
||||
// Update packages
|
||||
$this->resetComposer();
|
||||
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
|
||||
|
||||
$updateDevMode = !$input->getOption('update-no-dev');
|
||||
$optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
|
||||
$authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
|
||||
$apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
|
||||
|
||||
// Update packages
|
||||
$this->resetComposer();
|
||||
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
|
||||
|
||||
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
|
||||
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ use Composer\Config\ConfigSourceInterface;
|
|||
use Composer\Downloader\TransportException;
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\Util\Platform;
|
||||
use Composer\Util\ProcessExecutor;
|
||||
|
||||
/**
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
|
@ -459,4 +460,20 @@ class Config
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by long-running custom scripts in composer.json
|
||||
*
|
||||
* "scripts": {
|
||||
* "watch": [
|
||||
* "Composer\\Config::disableProcessTimeout",
|
||||
* "vendor/bin/long-running-script --watch"
|
||||
* ]
|
||||
* }
|
||||
*/
|
||||
public static function disableProcessTimeout()
|
||||
{
|
||||
// Override global timeout set earlier by environment or config
|
||||
ProcessExecutor::setTimeout(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,8 +81,11 @@ class Problem
|
|||
|
||||
$job = $reason['job'];
|
||||
|
||||
if (isset($job['constraint'])) {
|
||||
$packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
|
||||
$packageName = $job['packageName'];
|
||||
$constraint = $job['constraint'];
|
||||
|
||||
if (isset($constraint)) {
|
||||
$packages = $this->pool->whatProvides($packageName, $constraint);
|
||||
} else {
|
||||
$packages = array();
|
||||
}
|
||||
|
@ -90,9 +93,9 @@ class Problem
|
|||
if ($job && $job['cmd'] === 'install' && empty($packages)) {
|
||||
|
||||
// handle php/hhvm
|
||||
if ($job['packageName'] === 'php' || $job['packageName'] === 'php-64bit' || $job['packageName'] === 'hhvm') {
|
||||
if ($packageName === 'php' || $packageName === 'php-64bit' || $packageName === 'hhvm') {
|
||||
$version = phpversion();
|
||||
$available = $this->pool->whatProvides($job['packageName']);
|
||||
$available = $this->pool->whatProvides($packageName);
|
||||
|
||||
if (count($available)) {
|
||||
$firstAvailable = reset($available);
|
||||
|
@ -103,13 +106,13 @@ class Problem
|
|||
}
|
||||
}
|
||||
|
||||
$msg = "\n - This package requires ".$job['packageName'].$this->constraintToText($job['constraint']).' but ';
|
||||
$msg = "\n - This package requires ".$packageName.$this->constraintToText($constraint).' but ';
|
||||
|
||||
if (defined('HHVM_VERSION') || count($available)) {
|
||||
if (defined('HHVM_VERSION') || (count($available) && $packageName === 'hhvm')) {
|
||||
return $msg . 'your HHVM version does not satisfy that requirement.';
|
||||
}
|
||||
|
||||
if ($job['packageName'] === 'hhvm') {
|
||||
if ($packageName === 'hhvm') {
|
||||
return $msg . 'you are running this with PHP and not HHVM.';
|
||||
}
|
||||
|
||||
|
@ -117,43 +120,43 @@ class Problem
|
|||
}
|
||||
|
||||
// handle php extensions
|
||||
if (0 === stripos($job['packageName'], 'ext-')) {
|
||||
if (false !== strpos($job['packageName'], ' ')) {
|
||||
return "\n - The requested PHP extension ".$job['packageName'].' should be required as '.str_replace(' ', '-', $job['packageName']).'.';
|
||||
if (0 === stripos($packageName, 'ext-')) {
|
||||
if (false !== strpos($packageName, ' ')) {
|
||||
return "\n - The requested PHP extension ".$packageName.' should be required as '.str_replace(' ', '-', $packageName).'.';
|
||||
}
|
||||
|
||||
$ext = substr($job['packageName'], 4);
|
||||
$ext = substr($packageName, 4);
|
||||
$error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
|
||||
|
||||
return "\n - The requested PHP extension ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.';
|
||||
return "\n - The requested PHP extension ".$packageName.$this->constraintToText($constraint).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.';
|
||||
}
|
||||
|
||||
// handle linked libs
|
||||
if (0 === stripos($job['packageName'], 'lib-')) {
|
||||
if (strtolower($job['packageName']) === 'lib-icu') {
|
||||
if (0 === stripos($packageName, 'lib-')) {
|
||||
if (strtolower($packageName) === 'lib-icu') {
|
||||
$error = extension_loaded('intl') ? 'has the wrong version installed, try upgrading the intl extension.' : 'is missing from your system, make sure the intl extension is loaded.';
|
||||
|
||||
return "\n - The requested linked library ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error;
|
||||
return "\n - The requested linked library ".$packageName.$this->constraintToText($constraint).' '.$error;
|
||||
}
|
||||
|
||||
return "\n - The requested linked library ".$job['packageName'].$this->constraintToText($job['constraint']).' has the wrong version installed or is missing from your system, make sure to load the extension providing it.';
|
||||
return "\n - The requested linked library ".$packageName.$this->constraintToText($constraint).' has the wrong version installed or is missing from your system, make sure to load the extension providing it.';
|
||||
}
|
||||
|
||||
if (!preg_match('{^[A-Za-z0-9_./-]+$}', $job['packageName'])) {
|
||||
$illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $job['packageName']);
|
||||
if (!preg_match('{^[A-Za-z0-9_./-]+$}', $packageName)) {
|
||||
$illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $packageName);
|
||||
|
||||
return "\n - The requested package ".$job['packageName'].' could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.';
|
||||
return "\n - The requested package ".$packageName.' could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.';
|
||||
}
|
||||
|
||||
if ($providers = $this->pool->whatProvides($job['packageName'], $job['constraint'], true, true)) {
|
||||
return "\n - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' is satisfiable by '.$this->getPackageList($providers).' but these conflict with your requirements or minimum-stability.';
|
||||
if ($providers = $this->pool->whatProvides($packageName, $constraint, true, true)) {
|
||||
return "\n - The requested package ".$packageName.$this->constraintToText($constraint).' is satisfiable by '.$this->getPackageList($providers).' but these conflict with your requirements or minimum-stability.';
|
||||
}
|
||||
|
||||
if ($providers = $this->pool->whatProvides($job['packageName'], null, true, true)) {
|
||||
return "\n - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.';
|
||||
if ($providers = $this->pool->whatProvides($packageName, null, true, true)) {
|
||||
return "\n - The requested package ".$packageName.$this->constraintToText($constraint).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.';
|
||||
}
|
||||
|
||||
return "\n - The requested package ".$job['packageName'].' could not be found in any version, there may be a typo in the package name.';
|
||||
return "\n - The requested package ".$packageName.' could not be found in any version, there may be a typo in the package name.';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,27 +205,29 @@ class Problem
|
|||
*/
|
||||
protected function jobToText($job)
|
||||
{
|
||||
$packageName = $job['packageName'];
|
||||
$constraint = $job['constraint'];
|
||||
switch ($job['cmd']) {
|
||||
case 'install':
|
||||
$packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
|
||||
$packages = $this->pool->whatProvides($packageName, $constraint);
|
||||
if (!$packages) {
|
||||
return 'No package found to satisfy install request for '.$job['packageName'].$this->constraintToText($job['constraint']);
|
||||
return 'No package found to satisfy install request for '.$packageName.$this->constraintToText($constraint);
|
||||
}
|
||||
|
||||
return 'Installation request for '.$job['packageName'].$this->constraintToText($job['constraint']).' -> satisfiable by '.$this->getPackageList($packages).'.';
|
||||
return 'Installation request for '.$packageName.$this->constraintToText($constraint).' -> satisfiable by '.$this->getPackageList($packages).'.';
|
||||
case 'update':
|
||||
return 'Update request for '.$job['packageName'].$this->constraintToText($job['constraint']).'.';
|
||||
return 'Update request for '.$packageName.$this->constraintToText($constraint).'.';
|
||||
case 'remove':
|
||||
return 'Removal request for '.$job['packageName'].$this->constraintToText($job['constraint']).'';
|
||||
return 'Removal request for '.$packageName.$this->constraintToText($constraint).'';
|
||||
}
|
||||
|
||||
if (isset($job['constraint'])) {
|
||||
$packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
|
||||
if (isset($constraint)) {
|
||||
$packages = $this->pool->whatProvides($packageName, $constraint);
|
||||
} else {
|
||||
$packages = array();
|
||||
}
|
||||
|
||||
return 'Job(cmd='.$job['cmd'].', target='.$job['packageName'].', packages=['.$this->getPackageList($packages).'])';
|
||||
return 'Job(cmd='.$job['cmd'].', target='.$packageName.', packages=['.$this->getPackageList($packages).'])';
|
||||
}
|
||||
|
||||
protected function getPackageList($packages)
|
||||
|
|
|
@ -477,6 +477,8 @@ class Installer
|
|||
$solver = new Solver($policy, $pool, $installedRepo, $this->io);
|
||||
try {
|
||||
$operations = $solver->solve($request, $this->ignorePlatformReqs);
|
||||
$ruleSetSize = $solver->getRuleSetSize();
|
||||
$solver = null;
|
||||
} catch (SolverProblemsException $e) {
|
||||
$this->io->writeError('<error>Your requirements could not be resolved to an installable set of packages.</error>', true, IOInterface::QUIET);
|
||||
$this->io->writeError($e->getMessage());
|
||||
|
@ -493,7 +495,7 @@ class Installer
|
|||
$this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $this->devMode, $policy, $repositorySet, $installedRepo, $request, $operations);
|
||||
|
||||
$this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies", true, IOInterface::VERBOSE);
|
||||
$this->io->writeError("Analyzed ".$solver->getRuleSetSize()." rules to resolve dependencies", true, IOInterface::VERBOSE);
|
||||
$this->io->writeError("Analyzed ".$ruleSetSize." rules to resolve dependencies", true, IOInterface::VERBOSE);
|
||||
|
||||
// execute operations
|
||||
if (!$operations) {
|
||||
|
|
|
@ -22,7 +22,7 @@ class JsonManipulator
|
|||
private static $DEFINES = '(?(DEFINE)
|
||||
(?<number> -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
|
||||
(?<boolean> true | false | null )
|
||||
(?<string> " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " )
|
||||
(?<string> " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9A-Fa-f]{4} )* " )
|
||||
(?<array> \[ (?: (?&json) \s* (?: , (?&json) \s* )* )? \s* \] )
|
||||
(?<pair> \s* (?&string) \s* : (?&json) \s* )
|
||||
(?<object> \{ (?: (?&pair) (?: , (?&pair) )* )? \s* \} )
|
||||
|
|
|
@ -401,4 +401,14 @@ class AliasPackage extends BasePackage implements CompletePackageInterface
|
|||
{
|
||||
return parent::__toString().' (alias of '.$this->aliasOf->getVersion().')';
|
||||
}
|
||||
|
||||
public function setDistUrl($url)
|
||||
{
|
||||
return $this->aliasOf->setDistUrl($url);
|
||||
}
|
||||
|
||||
public function setDistType($type)
|
||||
{
|
||||
return $this->aliasOf->setDistType($type);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,10 @@ class ValidatingArrayLoader implements LoaderInterface
|
|||
$this->warnings = array();
|
||||
$this->config = $config;
|
||||
|
||||
if ($err = self::hasPackageNamingError($config['name'])) {
|
||||
$this->warnings[] = 'Deprecation warning: Your package name '.$err.' Make sure you fix this as Composer 2.0 will error.';
|
||||
}
|
||||
|
||||
if ($this->strictName) {
|
||||
$this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true);
|
||||
} else {
|
||||
|
@ -195,7 +199,9 @@ class ValidatingArrayLoader implements LoaderInterface
|
|||
foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
|
||||
if ($this->validateArray($linkType) && isset($this->config[$linkType])) {
|
||||
foreach ($this->config[$linkType] as $package => $constraint) {
|
||||
if (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) {
|
||||
if ($err = self::hasPackageNamingError($package, true)) {
|
||||
$this->warnings[] = 'Deprecation warning: '.$linkType.'.'.$err.' Make sure you fix this as Composer 2.0 will error.';
|
||||
} elseif (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) {
|
||||
$this->warnings[] = $linkType.'.'.$package.' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]';
|
||||
}
|
||||
if (!is_string($constraint)) {
|
||||
|
|
|
@ -358,4 +358,32 @@ interface PackageInterface
|
|||
* @return array
|
||||
*/
|
||||
public function getTransportOptions();
|
||||
|
||||
/**
|
||||
* @param string $reference
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setSourceReference($reference);
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setDistUrl($url);
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setDistType($type);
|
||||
|
||||
/**
|
||||
* @param string $reference
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setDistReference($reference);
|
||||
}
|
||||
|
|
|
@ -15,15 +15,16 @@ namespace Composer\Plugin;
|
|||
use Composer\Composer;
|
||||
use Composer\EventDispatcher\EventSubscriberInterface;
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\Package\CompletePackage;
|
||||
use Composer\Package\Package;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Repository\RepositoryInterface;
|
||||
use Composer\Package\AliasPackage;
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\Package\Link;
|
||||
use Composer\Repository\RepositorySet;
|
||||
use Composer\Semver\Constraint\Constraint;
|
||||
use Composer\Plugin\Capability\Capability;
|
||||
use Composer\Util\PackageSorter;
|
||||
|
||||
/**
|
||||
* Plugin manager
|
||||
|
@ -253,8 +254,10 @@ class PluginManager
|
|||
*/
|
||||
private function loadRepository(RepositoryInterface $repo)
|
||||
{
|
||||
foreach ($repo->getPackages() as $package) { /** @var PackageInterface $package */
|
||||
if ($package instanceof AliasPackage) {
|
||||
$packages = $repo->getPackages();
|
||||
$sortedPackages = array_reverse(PackageSorter::sortPackages($packages));
|
||||
foreach ($sortedPackages as $package) {
|
||||
if (!($package instanceof CompletePackage)) {
|
||||
continue;
|
||||
}
|
||||
if ('composer-plugin' === $package->getType()) {
|
||||
|
|
|
@ -803,7 +803,11 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
|||
private function canonicalizeUrl($url)
|
||||
{
|
||||
if ('/' === $url[0]) {
|
||||
return preg_replace('{(https?://[^/]+).*}i', '$1' . $url, $this->url);
|
||||
if (preg_match('{^[^:]++://[^/]*+}', $this->url, $matches)) {
|
||||
return $matches[0] . $url;
|
||||
}
|
||||
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
return $url;
|
||||
|
|
|
@ -166,8 +166,14 @@ class PlatformRepository extends ArrayRepository
|
|||
case 'imagick':
|
||||
$imagick = new \Imagick();
|
||||
$imageMagickVersion = $imagick->getVersion();
|
||||
preg_match('/^ImageMagick ([\d.]+)-(\d+)/', $imageMagickVersion['versionString'], $matches);
|
||||
// 6.x: ImageMagick 6.2.9 08/24/06 Q16 http://www.imagemagick.org
|
||||
// 7.x: ImageMagick 7.0.8-34 Q16 x86_64 2019-03-23 https://imagemagick.org
|
||||
preg_match('/^ImageMagick ([\d.]+)(?:-(\d+))?/', $imageMagickVersion['versionString'], $matches);
|
||||
if (isset($matches[2])) {
|
||||
$prettyVersion = "{$matches[1]}.{$matches[2]}";
|
||||
} else {
|
||||
$prettyVersion = $matches[1];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'libxml':
|
||||
|
|
|
@ -219,6 +219,13 @@ abstract class BitbucketDriver extends VcsDriver
|
|||
return $this->fallbackDriver->getChangeDate($identifier);
|
||||
}
|
||||
|
||||
if (strpos($identifier, '/') !== false) {
|
||||
$branches = $this->getBranches();
|
||||
if (isset($branches[$identifier])) {
|
||||
$identifier = $branches[$identifier];
|
||||
}
|
||||
}
|
||||
|
||||
$resource = sprintf(
|
||||
'https://api.bitbucket.org/2.0/repositories/%s/%s/commit/%s?fields=date',
|
||||
$this->owner,
|
||||
|
|
|
@ -66,8 +66,9 @@ class HgDriver extends VcsDriver
|
|||
// clean up directory and do a fresh clone into it
|
||||
$fs->removeDirectory($this->repoDir);
|
||||
|
||||
$command = function ($url) {
|
||||
return sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($this->repoDir));
|
||||
$repoDir = $this->repoDir;
|
||||
$command = function ($url) use ($repoDir) {
|
||||
return sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($repoDir));
|
||||
};
|
||||
|
||||
$hgUtils->runCommand($command, $this->url, $this->repoDir);
|
||||
|
|
|
@ -32,7 +32,8 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
{
|
||||
protected $url;
|
||||
protected $packageName;
|
||||
protected $verbose;
|
||||
protected $isVerbose;
|
||||
protected $isVeryVerbose;
|
||||
protected $io;
|
||||
protected $config;
|
||||
protected $versionParser;
|
||||
|
@ -68,7 +69,8 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
$this->url = $repoConfig['url'];
|
||||
$this->io = $io;
|
||||
$this->type = isset($repoConfig['type']) ? $repoConfig['type'] : 'vcs';
|
||||
$this->verbose = $io->isVeryVerbose();
|
||||
$this->isVerbose = $io->isVerbose();
|
||||
$this->isVeryVerbose = $io->isVeryVerbose();
|
||||
$this->config = $config;
|
||||
$this->repoConfig = $repoConfig;
|
||||
$this->versionCache = $versionCache;
|
||||
|
@ -133,7 +135,8 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
{
|
||||
parent::initialize();
|
||||
|
||||
$verbose = $this->verbose;
|
||||
$isVerbose = $this->isVerbose;
|
||||
$isVeryVerbose = $this->isVeryVerbose;
|
||||
|
||||
$driver = $this->getDriver();
|
||||
if (!$driver) {
|
||||
|
@ -151,23 +154,23 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
$this->packageName = !empty($data['name']) ? $data['name'] : null;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError('<error>Skipped parsing '.$driver->getRootIdentifier().', '.$e->getMessage().'</error>');
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($driver->getTags() as $tag => $identifier) {
|
||||
$msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $tag . '</comment>)';
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError($msg);
|
||||
} else {
|
||||
} elseif ($isVerbose) {
|
||||
$this->io->overwriteError($msg, false);
|
||||
}
|
||||
|
||||
// strip the release- prefix from tags if present
|
||||
$tag = str_replace('release-', '', $tag);
|
||||
|
||||
$cachedPackage = $this->getCachedPackageVersion($tag, $identifier, $verbose);
|
||||
$cachedPackage = $this->getCachedPackageVersion($tag, $identifier, $isVerbose, $isVeryVerbose);
|
||||
if ($cachedPackage) {
|
||||
$this->addPackage($cachedPackage);
|
||||
|
||||
|
@ -179,7 +182,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
}
|
||||
|
||||
if (!$parsedTag = $this->validateTag($tag)) {
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError('<warning>Skipped tag '.$tag.', invalid tag name</warning>');
|
||||
}
|
||||
continue;
|
||||
|
@ -187,7 +190,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
|
||||
try {
|
||||
if (!$data = $driver->getComposerInformation($identifier)) {
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError('<warning>Skipped tag '.$tag.', no composer file</warning>');
|
||||
}
|
||||
$this->emptyReferences[] = $identifier;
|
||||
|
@ -209,7 +212,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
|
||||
// broken package, version doesn't match tag
|
||||
if ($data['version_normalized'] !== $parsedTag) {
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError('<warning>Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json</warning>');
|
||||
}
|
||||
continue;
|
||||
|
@ -217,13 +220,13 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
|
||||
$tagPackageName = isset($data['name']) ? $data['name'] : $this->packageName;
|
||||
if ($existingPackage = $this->findPackage($tagPackageName, $data['version_normalized'])) {
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError('<warning>Skipped tag '.$tag.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$data['version_normalized'].' internally</warning>');
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError('Importing tag '.$tag.' ('.$data['version_normalized'].')');
|
||||
}
|
||||
|
||||
|
@ -232,35 +235,35 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
if ($e instanceof TransportException && $e->getCode() === 404) {
|
||||
$this->emptyReferences[] = $identifier;
|
||||
}
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError('<warning>Skipped tag '.$tag.', '.($e instanceof TransportException ? 'no composer file was found' : $e->getMessage()).'</warning>');
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$verbose) {
|
||||
if (!$isVeryVerbose) {
|
||||
$this->io->overwriteError('', false);
|
||||
}
|
||||
|
||||
$branches = $driver->getBranches();
|
||||
foreach ($branches as $branch => $identifier) {
|
||||
$msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $branch . '</comment>)';
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError($msg);
|
||||
} else {
|
||||
} elseif ($isVerbose) {
|
||||
$this->io->overwriteError($msg, false);
|
||||
}
|
||||
|
||||
if ($branch === 'trunk' && isset($branches['master'])) {
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError('<warning>Skipped branch '.$branch.', can not parse both master and trunk branches as they both resolve to 9999999-dev internally</warning>');
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$parsedBranch = $this->validateBranch($branch)) {
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError('<warning>Skipped branch '.$branch.', invalid name</warning>');
|
||||
}
|
||||
continue;
|
||||
|
@ -274,7 +277,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
$version = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch);
|
||||
}
|
||||
|
||||
$cachedPackage = $this->getCachedPackageVersion($version, $identifier, $verbose);
|
||||
$cachedPackage = $this->getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose);
|
||||
if ($cachedPackage) {
|
||||
$this->addPackage($cachedPackage);
|
||||
|
||||
|
@ -287,7 +290,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
|
||||
try {
|
||||
if (!$data = $driver->getComposerInformation($identifier)) {
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError('<warning>Skipped branch '.$branch.', no composer file</warning>');
|
||||
}
|
||||
$this->emptyReferences[] = $identifier;
|
||||
|
@ -298,7 +301,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
$data['version'] = $version;
|
||||
$data['version_normalized'] = $parsedBranch;
|
||||
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError('Importing branch '.$branch.' ('.$data['version'].')');
|
||||
}
|
||||
|
||||
|
@ -312,12 +315,12 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
if ($e->getCode() === 404) {
|
||||
$this->emptyReferences[] = $identifier;
|
||||
}
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError('<warning>Skipped branch '.$branch.', no composer file was found</warning>');
|
||||
}
|
||||
continue;
|
||||
} catch (\Exception $e) {
|
||||
if (!$verbose) {
|
||||
if (!$isVeryVerbose) {
|
||||
$this->io->writeError('');
|
||||
}
|
||||
$this->branchErrorOccurred = true;
|
||||
|
@ -328,7 +331,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
}
|
||||
$driver->cleanup();
|
||||
|
||||
if (!$verbose) {
|
||||
if (!$isVeryVerbose) {
|
||||
$this->io->overwriteError('', false);
|
||||
}
|
||||
|
||||
|
@ -373,7 +376,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
return false;
|
||||
}
|
||||
|
||||
private function getCachedPackageVersion($version, $identifier, $verbose)
|
||||
private function getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose)
|
||||
{
|
||||
if (!$this->versionCache) {
|
||||
return;
|
||||
|
@ -381,7 +384,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
|
||||
$cachedPackage = $this->versionCache->getVersionPackage($version, $identifier);
|
||||
if ($cachedPackage === false) {
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError('<warning>Skipped '.$version.', no composer file (cached from ref '.$identifier.')</warning>');
|
||||
}
|
||||
|
||||
|
@ -390,14 +393,14 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
|
|||
|
||||
if ($cachedPackage) {
|
||||
$msg = 'Found cached composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $version . '</comment>)';
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError($msg);
|
||||
} else {
|
||||
} elseif ($isVerbose) {
|
||||
$this->io->overwriteError($msg, false);
|
||||
}
|
||||
|
||||
if ($existingPackage = $this->findPackage($cachedPackage['name'], $cachedPackage['version_normalized'])) {
|
||||
if ($verbose) {
|
||||
if ($isVeryVerbose) {
|
||||
$this->io->writeError('<warning>Skipped cached version '.$version.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$cachedPackage['version_normalized'].' internally</warning>');
|
||||
}
|
||||
$cachedPackage = null;
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace Composer\Util;
|
||||
|
||||
use Composer\Package\Link;
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
class PackageSorter
|
||||
{
|
||||
/**
|
||||
* Sorts packages by dependency weight
|
||||
*
|
||||
* Packages of equal weight retain the original order
|
||||
*
|
||||
* @param array $packages
|
||||
* @return array
|
||||
*/
|
||||
public static function sortPackages(array $packages) {
|
||||
$usageList = array();
|
||||
|
||||
foreach ($packages as $package) { /** @var PackageInterface $package */
|
||||
foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) { /** @var Link $link */
|
||||
$target = $link->getTarget();
|
||||
$usageList[$target][] = $package->getName();
|
||||
}
|
||||
}
|
||||
$computing = array();
|
||||
$computed = array();
|
||||
$computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) {
|
||||
// reusing computed importance
|
||||
if (isset($computed[$name])) {
|
||||
return $computed[$name];
|
||||
}
|
||||
|
||||
// canceling circular dependency
|
||||
if (isset($computing[$name])) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$computing[$name] = true;
|
||||
$weight = 0;
|
||||
|
||||
if (isset($usageList[$name])) {
|
||||
foreach ($usageList[$name] as $user) {
|
||||
$weight -= 1 - $computeImportance($user);
|
||||
}
|
||||
}
|
||||
|
||||
unset($computing[$name]);
|
||||
$computed[$name] = $weight;
|
||||
|
||||
return $weight;
|
||||
};
|
||||
|
||||
$weightList = array();
|
||||
|
||||
foreach ($packages as $name => $package) {
|
||||
$weight = $computeImportance($name);
|
||||
$weightList[$name] = $weight;
|
||||
}
|
||||
|
||||
$stable_sort = function (&$array) {
|
||||
static $transform, $restore;
|
||||
|
||||
$i = 0;
|
||||
|
||||
if (!$transform) {
|
||||
$transform = function (&$v, $k) use (&$i) {
|
||||
$v = array($v, ++$i, $k, $v);
|
||||
};
|
||||
|
||||
$restore = function (&$v) {
|
||||
$v = $v[3];
|
||||
};
|
||||
}
|
||||
|
||||
array_walk($array, $transform);
|
||||
asort($array);
|
||||
array_walk($array, $restore);
|
||||
};
|
||||
|
||||
$stable_sort($weightList);
|
||||
|
||||
$sortedPackages = array();
|
||||
|
||||
foreach (array_keys($weightList) as $name) {
|
||||
$sortedPackages[] = $packages[$name];
|
||||
}
|
||||
return $sortedPackages;
|
||||
}
|
||||
}
|
|
@ -51,6 +51,7 @@ class ProcessExecutor
|
|||
|
||||
return '://'.$m['user'].':***@';
|
||||
}, $command);
|
||||
$safeCommand = preg_replace("{--password (.*[^\\\\]\') }", '--password \'***\' ', $safeCommand);
|
||||
$this->io->writeError('Executing command ('.($cwd ?: 'CWD').'): '.$safeCommand);
|
||||
}
|
||||
|
||||
|
|
|
@ -486,6 +486,47 @@ class AutoloadGeneratorTest extends TestCase
|
|||
$this->assertFileExists($this->vendorDir.'/composer/autoload_classmap.php', "ClassMap file needs to be generated, even if empty.");
|
||||
}
|
||||
|
||||
public function testPharAutoload()
|
||||
{
|
||||
$package = new Package('a', '1.0', '1.0');
|
||||
$package->setRequires(array(
|
||||
new Link('a', 'a/a'),
|
||||
));
|
||||
|
||||
$package->setAutoload(array(
|
||||
'psr-0' => array(
|
||||
'Foo' => 'foo.phar',
|
||||
'Bar' => 'dir/bar.phar/src',
|
||||
),
|
||||
'psr-4' => array(
|
||||
'Baz\\' => 'baz.phar',
|
||||
'Qux\\' => 'dir/qux.phar/src',
|
||||
),
|
||||
));
|
||||
|
||||
$vendorPackage = new Package('a/a', '1.0', '1.0');
|
||||
$vendorPackage->setAutoload(array(
|
||||
'psr-0' => array(
|
||||
'Lorem' => 'lorem.phar',
|
||||
'Ipsum' => 'dir/ipsum.phar/src',
|
||||
),
|
||||
'psr-4' => array(
|
||||
'Dolor\\' => 'dolor.phar',
|
||||
'Sit\\' => 'dir/sit.phar/src',
|
||||
),
|
||||
));
|
||||
|
||||
$this->repository->expects($this->once())
|
||||
->method('getCanonicalPackages')
|
||||
->will($this->returnValue(array($vendorPackage)));
|
||||
|
||||
$this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', true, 'Phar');
|
||||
|
||||
$this->assertAutoloadFiles('phar', $this->vendorDir . '/composer');
|
||||
$this->assertAutoloadFiles('phar_psr4', $this->vendorDir . '/composer', 'psr4');
|
||||
$this->assertAutoloadFiles('phar_static', $this->vendorDir . '/composer', 'static');
|
||||
}
|
||||
|
||||
public function testPSRToClassMapIgnoresNonExistingDir()
|
||||
{
|
||||
$package = new Package('a', '1.0', '1.0');
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Lorem' => array('phar://' . $vendorDir . '/a/a/lorem.phar'),
|
||||
'Ipsum' => array('phar://' . $vendorDir . '/a/a/dir/ipsum.phar/src'),
|
||||
'Foo' => array('phar://' . $baseDir . '/foo.phar'),
|
||||
'Bar' => array('phar://' . $baseDir . '/dir/bar.phar/src'),
|
||||
);
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Sit\\' => array('phar://' . $vendorDir . '/a/a/dir/sit.phar/src'),
|
||||
'Qux\\' => array('phar://' . $baseDir . '/dir/qux.phar/src'),
|
||||
'Dolor\\' => array('phar://' . $vendorDir . '/a/a/dolor.phar'),
|
||||
'Baz\\' => array('phar://' . $baseDir . '/baz.phar'),
|
||||
);
|
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInitPhar
|
||||
{
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'S' =>
|
||||
array (
|
||||
'Sit\\' => 4,
|
||||
),
|
||||
'Q' =>
|
||||
array (
|
||||
'Qux\\' => 4,
|
||||
),
|
||||
'D' =>
|
||||
array (
|
||||
'Dolor\\' => 6,
|
||||
),
|
||||
'B' =>
|
||||
array (
|
||||
'Baz\\' => 4,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'Sit\\' =>
|
||||
array (
|
||||
0 => 'phar://' . __DIR__ . '/..' . '/a/a/dir/sit.phar/src',
|
||||
),
|
||||
'Qux\\' =>
|
||||
array (
|
||||
0 => 'phar://' . __DIR__ . '/../..' . '/dir/qux.phar/src',
|
||||
),
|
||||
'Dolor\\' =>
|
||||
array (
|
||||
0 => 'phar://' . __DIR__ . '/..' . '/a/a/dolor.phar',
|
||||
),
|
||||
'Baz\\' =>
|
||||
array (
|
||||
0 => 'phar://' . __DIR__ . '/../..' . '/baz.phar',
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixesPsr0 = array (
|
||||
'L' =>
|
||||
array (
|
||||
'Lorem' =>
|
||||
array (
|
||||
0 => 'phar://' . __DIR__ . '/..' . '/a/a/lorem.phar',
|
||||
),
|
||||
),
|
||||
'I' =>
|
||||
array (
|
||||
'Ipsum' =>
|
||||
array (
|
||||
0 => 'phar://' . __DIR__ . '/..' . '/a/a/dir/ipsum.phar/src',
|
||||
),
|
||||
),
|
||||
'F' =>
|
||||
array (
|
||||
'Foo' =>
|
||||
array (
|
||||
0 => 'phar://' . __DIR__ . '/../..' . '/foo.phar',
|
||||
),
|
||||
),
|
||||
'B' =>
|
||||
array (
|
||||
'Bar' =>
|
||||
array (
|
||||
0 => 'phar://' . __DIR__ . '/../..' . '/dir/bar.phar/src',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInitPhar::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInitPhar::$prefixDirsPsr4;
|
||||
$loader->prefixesPsr0 = ComposerStaticInitPhar::$prefixesPsr0;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
|
@ -7,42 +7,81 @@ namespace Foo;
|
|||
*/
|
||||
class StripNoise
|
||||
{
|
||||
public function test()
|
||||
public function test_heredoc()
|
||||
{
|
||||
return <<<A
|
||||
class Fail2
|
||||
return <<<HEREDOC
|
||||
class FailHeredocBasic
|
||||
{
|
||||
|
||||
}
|
||||
A
|
||||
. <<< AB
|
||||
class Fail3
|
||||
HEREDOC . <<< WHITESPACE
|
||||
class FailHeredocWhitespace
|
||||
{
|
||||
|
||||
}
|
||||
AB
|
||||
. <<<'TEST'
|
||||
class Fail4
|
||||
WHITESPACE . <<<"DOUBLEQUOTES"
|
||||
class FailHeredocDoubleQuotes
|
||||
{
|
||||
|
||||
}
|
||||
TEST
|
||||
. <<< 'ANOTHER'
|
||||
class Fail5
|
||||
DOUBLEQUOTES . <<< "DOUBLEQUOTESTABBED"
|
||||
class FailHeredocDoubleQuotesTabbed
|
||||
{
|
||||
|
||||
}
|
||||
ANOTHER
|
||||
. <<< 'ONEMORE'
|
||||
class Fail6
|
||||
DOUBLEQUOTESTABBED . <<<HEREDOCPHP73
|
||||
class FailHeredocPHP73
|
||||
{
|
||||
|
||||
}
|
||||
ONEMORE;
|
||||
HEREDOCPHP73;
|
||||
}
|
||||
|
||||
public function test2()
|
||||
public function test_nowdoc()
|
||||
{
|
||||
$class = 'class Fail4 {}';
|
||||
return <<<'NOWDOC'
|
||||
class FailNowdocBasic
|
||||
{
|
||||
}
|
||||
NOWDOC . <<< 'WHITESPACE'
|
||||
class FailNowdocWhitespace
|
||||
{
|
||||
}
|
||||
WHITESPACE . <<< 'NOWDOCTABBED'
|
||||
class FailNowdocTabbed
|
||||
{
|
||||
}
|
||||
NOWDOCTABBED . <<<'NOWDOCPHP73'
|
||||
class FailNowdocPHP73
|
||||
{
|
||||
}
|
||||
NOWDOCPHP73;
|
||||
}
|
||||
|
||||
public function test_followed_by_parentheses()
|
||||
{
|
||||
return array(<<<PARENTHESES
|
||||
class FailParentheses
|
||||
{
|
||||
}
|
||||
PARENTHESES);
|
||||
}
|
||||
|
||||
public function test_followed_by_comma()
|
||||
{
|
||||
return array(1, 2, <<<COMMA
|
||||
class FailComma
|
||||
{
|
||||
}
|
||||
COMMA, 3, 4);
|
||||
}
|
||||
|
||||
public function test_followed_by_period()
|
||||
{
|
||||
return <<<PERIOD
|
||||
class FailPeriod
|
||||
{
|
||||
}
|
||||
PERIOD.'?>';
|
||||
}
|
||||
|
||||
public function test_simple_string()
|
||||
{
|
||||
return 'class FailSimpleString {}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2374,6 +2374,26 @@ class JsonManipulatorTest extends TestCase
|
|||
"package/a": "*"
|
||||
}
|
||||
}
|
||||
', $manipulator->getContents());
|
||||
}
|
||||
|
||||
public function testEscapedUnicodeDoesNotCauseBacktrackLimitErrorGithubIssue8131()
|
||||
{
|
||||
$manipulator = new JsonManipulator('{
|
||||
"description": "Some U\u00F1icode",
|
||||
"require": {
|
||||
"foo/bar": "^1.0"
|
||||
}
|
||||
}');
|
||||
|
||||
$this->assertTrue($manipulator->addLink('require', 'foo/baz', '^1.0'));
|
||||
$this->assertEquals('{
|
||||
"description": "Some U\u00F1icode",
|
||||
"require": {
|
||||
"foo/bar": "^1.0",
|
||||
"foo/baz": "^1.0"
|
||||
}
|
||||
}
|
||||
', $manipulator->getContents());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -298,6 +298,30 @@ class ValidatingArrayLoaderTest extends TestCase
|
|||
'homepage : invalid value (foo:bar), must be an http/https URL',
|
||||
),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'name' => 'foo/bar.json',
|
||||
),
|
||||
array(
|
||||
'Deprecation warning: Your package name foo/bar.json is invalid, package names can not end in .json, consider renaming it or perhaps using a -json suffix instead. Make sure you fix this as Composer 2.0 will error.',
|
||||
),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'name' => 'com1/foo',
|
||||
),
|
||||
array(
|
||||
'Deprecation warning: Your package name com1/foo is reserved, package and vendor names can not match any of: nul, con, prn, aux, com1, com2, com3, com4, com5, com6, com7, com8, com9, lpt1, lpt2, lpt3, lpt4, lpt5, lpt6, lpt7, lpt8, lpt9. Make sure you fix this as Composer 2.0 will error.',
|
||||
),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'name' => 'Foo/Bar',
|
||||
),
|
||||
array(
|
||||
'Deprecation warning: Your package name Foo/Bar is invalid, it should not contain uppercase characters. We suggest using foo/bar instead. Make sure you fix this as Composer 2.0 will error.',
|
||||
),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'name' => 'foo/bar',
|
||||
|
@ -337,6 +361,18 @@ class ValidatingArrayLoaderTest extends TestCase
|
|||
),
|
||||
false,
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'name' => 'foo/bar',
|
||||
'require' => array(
|
||||
'Foo/Baz' => '^1.0',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'Deprecation warning: require.Foo/Baz is invalid, it should not contain uppercase characters. Please use foo/baz instead. Make sure you fix this as Composer 2.0 will error.',
|
||||
),
|
||||
false,
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'name' => 'foo/bar',
|
||||
|
|
|
@ -214,4 +214,71 @@ class ComposerRepositoryTest extends TestCase
|
|||
$repository->search('foo', RepositoryInterface::SEARCH_FULLTEXT, 'library')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider canonicalizeUrlProvider
|
||||
*
|
||||
* @param string $expected
|
||||
* @param string $url
|
||||
* @param string $repositoryUrl
|
||||
*/
|
||||
public function testCanonicalizeUrl($expected, $url, $repositoryUrl)
|
||||
{
|
||||
$repository = new ComposerRepository(
|
||||
array('url' => $repositoryUrl),
|
||||
new NullIO(),
|
||||
FactoryMock::createConfig()
|
||||
);
|
||||
|
||||
$object = new \ReflectionObject($repository);
|
||||
|
||||
$method = $object->getMethod('canonicalizeUrl');
|
||||
$method->setAccessible(true);
|
||||
|
||||
// ComposerRepository::__construct ensures that the repository URL has a
|
||||
// protocol, so reset it here in order to test all cases.
|
||||
$property = $object->getProperty('url');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($repository, $repositoryUrl);
|
||||
|
||||
$this->assertSame($expected, $method->invoke($repository, $url));
|
||||
}
|
||||
|
||||
public function canonicalizeUrlProvider()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
'https://example.org/path/to/file',
|
||||
'/path/to/file',
|
||||
'https://example.org',
|
||||
),
|
||||
array(
|
||||
'https://example.org/canonic_url',
|
||||
'https://example.org/canonic_url',
|
||||
'https://should-not-see-me.test',
|
||||
),
|
||||
array(
|
||||
'file:///path/to/repository/file',
|
||||
'/path/to/repository/file',
|
||||
'file:///path/to/repository',
|
||||
),
|
||||
array(
|
||||
// Assert that the repository URL is returned unchanged if it is
|
||||
// not a URL.
|
||||
// (Backward compatibility test)
|
||||
'invalid_repo_url',
|
||||
'/path/to/file',
|
||||
'invalid_repo_url',
|
||||
),
|
||||
array(
|
||||
// Assert that URLs can contain sequences resembling pattern
|
||||
// references as understood by preg_replace() without messing up
|
||||
// the result.
|
||||
// (Regression test)
|
||||
'https://example.org/path/to/unusual_$0_filename',
|
||||
'/path/to/unusual_$0_filename',
|
||||
'https://example.org',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,11 +61,25 @@ class ProcessExecutorTest extends TestCase
|
|||
ProcessExecutor::setTimeout(60);
|
||||
}
|
||||
|
||||
public function testHidePasswords()
|
||||
/**
|
||||
* @dataProvider hidePasswordProvider
|
||||
*/
|
||||
public function testHidePasswords($command, $expectedCommandOutput)
|
||||
{
|
||||
$process = new ProcessExecutor($buffer = new BufferIO('', StreamOutput::VERBOSITY_DEBUG));
|
||||
$process->execute('echo https://foo:bar@example.org/ && echo http://foo@example.org && echo http://abcdef1234567890234578:x-oauth-token@github.com/', $output);
|
||||
$this->assertEquals('Executing command (CWD): echo https://foo:***@example.org/ && echo http://foo@example.org && echo http://***:***@github.com/', trim($buffer->getOutput()));
|
||||
$process->execute($command, $output);
|
||||
$this->assertEquals('Executing command (CWD): ' . $expectedCommandOutput, trim($buffer->getOutput()));
|
||||
}
|
||||
|
||||
public function hidePasswordProvider()
|
||||
{
|
||||
return array(
|
||||
array('echo https://foo:bar@example.org/', 'echo https://foo:***@example.org/'),
|
||||
array('echo http://foo@example.org', 'echo http://foo@example.org'),
|
||||
array('echo http://abcdef1234567890234578:x-oauth-token@github.com/', 'echo http://***:***@github.com/'),
|
||||
array("svn ls --verbose --non-interactive --username 'foo' --password 'bar' 'https://foo.example.org/svn/'", "svn ls --verbose --non-interactive --username 'foo' --password '***' 'https://foo.example.org/svn/'"),
|
||||
array("svn ls --verbose --non-interactive --username 'foo' --password 'bar \'bar' 'https://foo.example.org/svn/'", "svn ls --verbose --non-interactive --username 'foo' --password '***' 'https://foo.example.org/svn/'"),
|
||||
);
|
||||
}
|
||||
|
||||
public function testDoesntHidePorts()
|
||||
|
|
Loading…
Reference in New Issue