Feature: Add support for autocompleting setting-keys in config-command (#11130)
* Add support for autocompleting setting-keys in config-command This PR implements the support for autocompletion of setting-keys in the config-command and its related funtional tests. The implementation takes existing command-line options like `--unset` or `--global` into account, as well as existing exposable package-properties. The result is a context- sensitive auto-completion of individual lists of setting-keys. Additionally showing the value `suggest.` sub-keys has been allowed in the config-command, as setting and unsetting them has alwas been possible, and I did not want to distinguish between showing, setting and unsetting those keys. In the setting-key flattening-method I used the `array_is_list()` function, which was added in PHP 8.1 recently. For backwards PHP-compatiblity the package `symfony/polyfill-php81` has been added. Signed-off-by: Stephan Jorek <stephan.jorek@brandung.de>pull/11150/head
parent
8ffd8bef08
commit
d54f2f21c5
|
@ -41,6 +41,7 @@
|
||||||
"composer/pcre": "^2 || ^3",
|
"composer/pcre": "^2 || ^3",
|
||||||
"symfony/polyfill-php73": "^1.24",
|
"symfony/polyfill-php73": "^1.24",
|
||||||
"symfony/polyfill-php80": "^1.24",
|
"symfony/polyfill-php80": "^1.24",
|
||||||
|
"symfony/polyfill-php81": "^1.24",
|
||||||
"seld/signal-handler": "^2.0"
|
"seld/signal-handler": "^2.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "a676a5855e58daf2c80e70dbb6fce5da",
|
"content-hash": "2dc8cd355eee4bb6c9fb0d2e10ffb7c6",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "composer/ca-bundle",
|
"name": "composer/ca-bundle",
|
||||||
|
@ -1724,6 +1724,85 @@
|
||||||
],
|
],
|
||||||
"time": "2022-05-10T07:21:04+00:00"
|
"time": "2022-05-10T07:21:04+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/polyfill-php81",
|
||||||
|
"version": "v1.26.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/polyfill-php81.git",
|
||||||
|
"reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/13f6d1271c663dc5ae9fb843a8f16521db7687a1",
|
||||||
|
"reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "1.26-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "symfony/polyfill",
|
||||||
|
"url": "https://github.com/symfony/polyfill"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Php81\\": ""
|
||||||
|
},
|
||||||
|
"classmap": [
|
||||||
|
"Resources/stubs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"compatibility",
|
||||||
|
"polyfill",
|
||||||
|
"portable",
|
||||||
|
"shim"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-php81/tree/v1.26.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-05-24T11:49:31+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/process",
|
"name": "symfony/process",
|
||||||
"version": "v5.4.11",
|
"version": "v5.4.11",
|
||||||
|
|
|
@ -17,7 +17,8 @@ use Composer\Util\Filesystem;
|
||||||
use Composer\Util\Platform;
|
use Composer\Util\Platform;
|
||||||
use Composer\Util\Silencer;
|
use Composer\Util\Silencer;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Composer\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Completion\CompletionInput;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Composer\Config;
|
use Composer\Config;
|
||||||
|
@ -34,6 +35,26 @@ use Composer\Package\BasePackage;
|
||||||
*/
|
*/
|
||||||
class ConfigCommand extends BaseCommand
|
class ConfigCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* List of additional configurable package-properties
|
||||||
|
*
|
||||||
|
* @var string[]
|
||||||
|
*/
|
||||||
|
protected const CONFIGURABLE_PACKAGE_PROPERTIES = [
|
||||||
|
'name',
|
||||||
|
'type',
|
||||||
|
'description',
|
||||||
|
'homepage',
|
||||||
|
'version',
|
||||||
|
'minimum-stability',
|
||||||
|
'prefer-stable',
|
||||||
|
'keywords',
|
||||||
|
'license',
|
||||||
|
'repositories',
|
||||||
|
'suggest',
|
||||||
|
'extra',
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Config
|
* @var Config
|
||||||
*/
|
*/
|
||||||
|
@ -76,7 +97,7 @@ class ConfigCommand extends BaseCommand
|
||||||
new InputOption('merge', 'm', InputOption::VALUE_NONE, 'Merge the setting value with the current value, to be used with extra.* keys in combination with --json'),
|
new InputOption('merge', 'm', InputOption::VALUE_NONE, 'Merge the setting value with the current value, to be used with extra.* keys in combination with --json'),
|
||||||
new InputOption('append', null, InputOption::VALUE_NONE, 'When adding a repository, append it (lowest priority) to the existing ones instead of prepending it (highest priority)'),
|
new InputOption('append', null, InputOption::VALUE_NONE, 'When adding a repository, append it (lowest priority) to the existing ones instead of prepending it (highest priority)'),
|
||||||
new InputOption('source', null, InputOption::VALUE_NONE, 'Display where the config value is loaded from'),
|
new InputOption('source', null, InputOption::VALUE_NONE, 'Display where the config value is loaded from'),
|
||||||
new InputArgument('setting-key', null, 'Setting key'),
|
new InputArgument('setting-key', null, 'Setting key', null, $this->suggestSettingKeys()),
|
||||||
new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value'),
|
new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value'),
|
||||||
])
|
])
|
||||||
->setHelp(
|
->setHelp(
|
||||||
|
@ -161,11 +182,7 @@ EOT
|
||||||
$io = $this->getIO();
|
$io = $this->getIO();
|
||||||
$this->config = Factory::createConfig($io);
|
$this->config = Factory::createConfig($io);
|
||||||
|
|
||||||
// Get the local composer.json, global config.json, or if the user
|
$configFile = $this->getComposerConfigFile($input, $this->config);
|
||||||
// passed in a file to use
|
|
||||||
$configFile = $input->getOption('global')
|
|
||||||
? ($this->config->get('home') . '/config.json')
|
|
||||||
: ($input->getOption('file') ?: Factory::getComposerFile());
|
|
||||||
|
|
||||||
// Create global composer.json if this was invoked using `composer global config`
|
// Create global composer.json if this was invoked using `composer global config`
|
||||||
if (
|
if (
|
||||||
|
@ -179,9 +196,7 @@ EOT
|
||||||
$this->configFile = new JsonFile($configFile, null, $io);
|
$this->configFile = new JsonFile($configFile, null, $io);
|
||||||
$this->configSource = new JsonConfigSource($this->configFile);
|
$this->configSource = new JsonConfigSource($this->configFile);
|
||||||
|
|
||||||
$authConfigFile = $input->getOption('global')
|
$authConfigFile = $this->getAuthConfigFile($input, $this->config);
|
||||||
? ($this->config->get('home') . '/auth.json')
|
|
||||||
: dirname($configFile) . '/auth.json';
|
|
||||||
|
|
||||||
$this->authConfigFile = new JsonFile($authConfigFile, null, $io);
|
$this->authConfigFile = new JsonFile($authConfigFile, null, $io);
|
||||||
$this->authConfigSource = new JsonConfigSource($this->authConfigFile, true);
|
$this->authConfigSource = new JsonConfigSource($this->authConfigFile, true);
|
||||||
|
@ -258,7 +273,7 @@ EOT
|
||||||
|
|
||||||
// show the value if no value is provided
|
// show the value if no value is provided
|
||||||
if ([] === $input->getArgument('setting-value') && !$input->getOption('unset')) {
|
if ([] === $input->getArgument('setting-value') && !$input->getOption('unset')) {
|
||||||
$properties = ['name', 'type', 'description', 'homepage', 'version', 'minimum-stability', 'prefer-stable', 'keywords', 'license', 'extra'];
|
$properties = self::CONFIGURABLE_PACKAGE_PROPERTIES;
|
||||||
$rawData = $this->configFile->read();
|
$rawData = $this->configFile->read();
|
||||||
$data = $this->config->all();
|
$data = $this->config->all();
|
||||||
if (Preg::isMatch('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) {
|
if (Preg::isMatch('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) {
|
||||||
|
@ -273,7 +288,7 @@ EOT
|
||||||
}
|
}
|
||||||
} elseif (strpos($settingKey, '.')) {
|
} elseif (strpos($settingKey, '.')) {
|
||||||
$bits = explode('.', $settingKey);
|
$bits = explode('.', $settingKey);
|
||||||
if ($bits[0] === 'extra') {
|
if ($bits[0] === 'extra' || $bits[0] === 'suggest') {
|
||||||
$data = $rawData;
|
$data = $rawData;
|
||||||
} else {
|
} else {
|
||||||
$data = $data['config'];
|
$data = $data['config'];
|
||||||
|
@ -914,4 +929,136 @@ EOT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the local composer.json, global config.json, or the file passed by the user
|
||||||
|
*/
|
||||||
|
private function getComposerConfigFile(InputInterface $input, Config $config): string
|
||||||
|
{
|
||||||
|
return $input->getOption('global')
|
||||||
|
? ($config->get('home') . '/config.json')
|
||||||
|
: ($input->getOption('file') ?: Factory::getComposerFile())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the local auth.json or global auth.json, or if the user passed in a file to use,
|
||||||
|
* the corresponding auth.json
|
||||||
|
*/
|
||||||
|
private function getAuthConfigFile(InputInterface $input, Config $config): string
|
||||||
|
{
|
||||||
|
return $input->getOption('global')
|
||||||
|
? ($config->get('home') . '/auth.json')
|
||||||
|
: dirname($this->getComposerConfigFile($input, $config)) . '/auth.json'
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suggest setting-keys, while taking given options in acount.
|
||||||
|
*/
|
||||||
|
private function suggestSettingKeys(): \Closure
|
||||||
|
{
|
||||||
|
return function (CompletionInput $input): array {
|
||||||
|
if ($input->getOption('list') || $input->getOption('editor') || $input->getOption('auth')) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize configuration
|
||||||
|
$config = Factory::createConfig();
|
||||||
|
|
||||||
|
// load configuration
|
||||||
|
$configFile = new JsonFile($this->getComposerConfigFile($input, $config));
|
||||||
|
if ($configFile->exists()) {
|
||||||
|
$config->merge($configFile->read(), $configFile->getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
// load auth-configuration
|
||||||
|
$authConfigFile = new JsonFile($this->getAuthConfigFile($input, $config));
|
||||||
|
if ($authConfigFile->exists()) {
|
||||||
|
$config->merge(['config' => $authConfigFile->read()], $authConfigFile->getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
// collect all configuration setting-keys
|
||||||
|
$rawConfig = $config->raw();
|
||||||
|
$keys = array_merge(
|
||||||
|
$this->flattenSettingKeys($rawConfig['config']),
|
||||||
|
$this->flattenSettingKeys($rawConfig['repositories'], 'repositories.')
|
||||||
|
);
|
||||||
|
|
||||||
|
// if unsetting …
|
||||||
|
if ($input->getOption('unset')) {
|
||||||
|
// … keep only the currently customized setting-keys …
|
||||||
|
$sources = [$configFile->getPath(), $authConfigFile->getPath()];
|
||||||
|
$keys = array_filter(
|
||||||
|
$keys,
|
||||||
|
static function (string $key) use ($config, $sources): bool {
|
||||||
|
return in_array($config->getSourceOfValue($key), $sources, true);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// … else if showing or setting a value …
|
||||||
|
} else {
|
||||||
|
// … add all configurable package-properties, no matter if it exist
|
||||||
|
$keys = array_merge($keys, self::CONFIGURABLE_PACKAGE_PROPERTIES);
|
||||||
|
|
||||||
|
// it would be nice to distinguish between showing and setting
|
||||||
|
// a value, but that makes the implementation much more complex
|
||||||
|
// and partially impossible because symfony's implementation
|
||||||
|
// does not complete arguments followed by other arguments
|
||||||
|
}
|
||||||
|
|
||||||
|
// add all existing configurable package-properties
|
||||||
|
if ($configFile->exists()) {
|
||||||
|
$properties = array_filter(
|
||||||
|
$configFile->read(),
|
||||||
|
static function (string $key): bool {
|
||||||
|
return in_array($key, self::CONFIGURABLE_PACKAGE_PROPERTIES, true);
|
||||||
|
},
|
||||||
|
ARRAY_FILTER_USE_KEY
|
||||||
|
);
|
||||||
|
|
||||||
|
$keys = array_merge(
|
||||||
|
$keys,
|
||||||
|
$this->flattenSettingKeys($properties)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter settings-keys by completion value
|
||||||
|
$completionValue = $input->getCompletionValue();
|
||||||
|
|
||||||
|
if ($completionValue !== '') {
|
||||||
|
$keys = array_filter(
|
||||||
|
$keys,
|
||||||
|
static function (string $key) use ($completionValue): bool {
|
||||||
|
return str_starts_with($key, $completionValue);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
sort($keys);
|
||||||
|
|
||||||
|
return array_unique($keys);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* build a flat list of dot-separated setting-keys from given config
|
||||||
|
*
|
||||||
|
* @param array<mixed[]|string> $config
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
private function flattenSettingKeys(array $config, string $prefix = ''): array
|
||||||
|
{
|
||||||
|
$keys = [];
|
||||||
|
foreach ($config as $key => $value) {
|
||||||
|
$keys[] = [$prefix . $key];
|
||||||
|
// array-lists must not be added to completion
|
||||||
|
// sub-keys of repository-keys must not be added to completion
|
||||||
|
if (is_array($value) && !array_is_list($value) && $prefix !== 'repositories.') {
|
||||||
|
$keys[] = $this->flattenSettingKeys($value, $prefix . $key . '.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_merge(...$keys);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,46 @@ class CompletionFunctionalTest extends TestCase
|
||||||
|
|
||||||
yield ['update --prefer-install ', $preferInstall];
|
yield ['update --prefer-install ', $preferInstall];
|
||||||
yield ['update ', $installedPackages];
|
yield ['update ', $installedPackages];
|
||||||
|
|
||||||
|
yield ['config --list ', null];
|
||||||
|
yield ['config --editor ', null];
|
||||||
|
yield ['config --auth ', null];
|
||||||
|
|
||||||
|
yield ['config ', ['bin-compat', 'extra', 'extra.branch-alias', 'home', 'name', 'repositories', 'repositories.packagist.org', 'suggest', 'suggest.ext-zip', 'type', 'version']];
|
||||||
|
yield ['config bin', ['bin-dir']]; // global setting
|
||||||
|
yield ['config nam', ['name']]; // existing package-property
|
||||||
|
yield ['config ver', ['version']]; // non-existing package-property
|
||||||
|
yield ['config repo', ['repositories', 'repositories.packagist.org']];
|
||||||
|
yield ['config repositories.', ['repositories.packagist.org']];
|
||||||
|
yield ['config sug', ['suggest', 'suggest.ext-zip']];
|
||||||
|
yield ['config suggest.ext-', ['suggest.ext-zip']];
|
||||||
|
yield ['config ext', ['extra', 'extra.branch-alias', 'extra.branch-alias.dev-main']];
|
||||||
|
|
||||||
|
// as this test does not use a fixture (yet?), the completion
|
||||||
|
// of setting authentication settings can have varying results
|
||||||
|
// yield ['config http-basic.', […]];
|
||||||
|
|
||||||
|
yield ['config --unset ', ['extra', 'extra.branch-alias', 'extra.branch-alias.dev-main', 'name', 'suggest', 'suggest.ext-zip', 'type']];
|
||||||
|
yield ['config --unset bin-dir', null]; // global setting
|
||||||
|
yield ['config --unset nam', ['name']]; // existing package-property
|
||||||
|
yield ['config --unset version', null]; // non-existing package-property
|
||||||
|
yield ['config --unset extra.', ['extra.branch-alias', 'extra.branch-alias.dev-main']];
|
||||||
|
|
||||||
|
// as this test does not use a fixture (yet?), the completion
|
||||||
|
// of unsetting authentication settings can have varying results
|
||||||
|
// yield ['config --unset http-basic.', […]];
|
||||||
|
|
||||||
|
yield ['config --global ', ['bin-compat', 'home', 'repositories', 'repositories.packagist.org']];
|
||||||
|
yield ['config --global repo', ['repositories', 'repositories.packagist.org']];
|
||||||
|
yield ['config --global repositories.', ['repositories.packagist.org']];
|
||||||
|
|
||||||
|
// as this test does not use a fixture (yet?), the completion
|
||||||
|
// of unsetting global settings can have varying results
|
||||||
|
// yield ['config --global --unset ', null];
|
||||||
|
|
||||||
|
// as this test does not use a fixture (yet?), the completion of
|
||||||
|
// unsetting global authentication settings can have varying results
|
||||||
|
// yield ['config --global --unset http-basic.', […]];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -8,7 +8,7 @@ Checks that package versions in InstalledVersions are correct on initial install
|
||||||
update
|
update
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
> Hooks::preUpdate
|
> Hooks::preUpdate
|
||||||
!!PreUpdate:["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/process","symfony/service-contracts","symfony/string"]
|
!!PreUpdate:["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/polyfill-php81","symfony/process","symfony/service-contracts","symfony/string"]
|
||||||
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
||||||
Loading composer repositories with package information
|
Loading composer repositories with package information
|
||||||
%((Info|Warning) from .*\n)?%Updating dependencies
|
%((Info|Warning) from .*\n)?%Updating dependencies
|
||||||
|
@ -26,12 +26,12 @@ Package operations: 6 installs, 0 updates, 0 removals%(\nAs there is no 'unzip'
|
||||||
- Downloading symfony/filesystem (%v?[2-8]\.\d+\.\d+%)
|
- Downloading symfony/filesystem (%v?[2-8]\.\d+\.\d+%)
|
||||||
- Installing symfony/console (99999.1.2): Symlinking from symfony-console
|
- Installing symfony/console (99999.1.2): Symlinking from symfony-console
|
||||||
- Installing plugin/a (1.1.1): Symlinking from plugin-a
|
- Installing plugin/a (1.1.1): Symlinking from plugin-a
|
||||||
!!PluginAInit["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/process","symfony/service-contracts","symfony/string","root/pkg"]
|
!!PluginAInit["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/polyfill-php81","symfony/process","symfony/service-contracts","symfony/string","root/pkg"]
|
||||||
!!PluginA:null
|
!!PluginA:null
|
||||||
!!PluginB:null
|
!!PluginB:null
|
||||||
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
||||||
- Installing plugin/b (2.2.2): Symlinking from plugin-b
|
- Installing plugin/b (2.2.2): Symlinking from plugin-b
|
||||||
!!PluginBInit["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/process","symfony/service-contracts","symfony/string","plugin/a","root/pkg"]
|
!!PluginBInit["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/polyfill-php81","symfony/process","symfony/service-contracts","symfony/string","plugin/a","root/pkg"]
|
||||||
!!PluginA:1.1.1.0
|
!!PluginA:1.1.1.0
|
||||||
!!PluginB:null
|
!!PluginB:null
|
||||||
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
||||||
|
@ -42,7 +42,7 @@ Generating autoload files
|
||||||
2 packages you are using are looking for funding.
|
2 packages you are using are looking for funding.
|
||||||
Use the `composer fund` command to find out more!
|
Use the `composer fund` command to find out more!
|
||||||
> Hooks::postUpdate
|
> Hooks::postUpdate
|
||||||
!!PostUpdate:["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/process","symfony/service-contracts","symfony/string","plugin/a","plugin/b","root/pkg"]
|
!!PostUpdate:["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/polyfill-php81","symfony/process","symfony/service-contracts","symfony/string","plugin/a","plugin/b","root/pkg"]
|
||||||
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
||||||
|
|
||||||
--EXPECT-EXIT-CODE--
|
--EXPECT-EXIT-CODE--
|
||||||
|
|
|
@ -7,14 +7,14 @@ Checks that package versions in InstalledVersions are correct during an upgrade.
|
||||||
--RUN--
|
--RUN--
|
||||||
update plugin/* symfony/console symfony/filesystem symfony/process
|
update plugin/* symfony/console symfony/filesystem symfony/process
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
!!PluginA:1.1.1.0["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/process","symfony/service-contracts","symfony/string","plugin/a","plugin/b","root/pkg"]
|
!!PluginA:1.1.1.0["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/polyfill-php81","symfony/process","symfony/service-contracts","symfony/string","plugin/a","plugin/b","root/pkg"]
|
||||||
!!PluginB:2.2.2.0
|
!!PluginB:2.2.2.0
|
||||||
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
||||||
!!PluginB:2.2.2.0["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/process","symfony/service-contracts","symfony/string","plugin/a","plugin/b","root/pkg"]
|
!!PluginB:2.2.2.0["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/polyfill-php81","symfony/process","symfony/service-contracts","symfony/string","plugin/a","plugin/b","root/pkg"]
|
||||||
!!PluginA:1.1.1.0
|
!!PluginA:1.1.1.0
|
||||||
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
||||||
> Hooks::preUpdate
|
> Hooks::preUpdate
|
||||||
!!PreUpdate:["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/process","symfony/service-contracts","symfony/string","plugin/a","plugin/b","root/pkg"]
|
!!PreUpdate:["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/polyfill-php81","symfony/process","symfony/service-contracts","symfony/string","plugin/a","plugin/b","root/pkg"]
|
||||||
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
||||||
Loading composer repositories with package information
|
Loading composer repositories with package information
|
||||||
%((Info|Warning) from .*\n)?%Updating dependencies
|
%((Info|Warning) from .*\n)?%Updating dependencies
|
||||||
|
@ -30,12 +30,12 @@ Package operations: 0 installs, 5 updates, 0 removals%(\nAs there is no 'unzip'
|
||||||
- Downloading symfony/filesystem (%v?[2-8]\.\d+\.\d+%)
|
- Downloading symfony/filesystem (%v?[2-8]\.\d+\.\d+%)
|
||||||
- Upgrading symfony/console (99999.1.2 => 99999.1.3): Mirroring from symfony-console
|
- Upgrading symfony/console (99999.1.2 => 99999.1.3): Mirroring from symfony-console
|
||||||
- Upgrading plugin/a (1.1.1 => 1.1.2): Mirroring from plugin-a
|
- Upgrading plugin/a (1.1.1 => 1.1.2): Mirroring from plugin-a
|
||||||
!!PluginAInit["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/process","symfony/service-contracts","symfony/string","plugin/a","plugin/b","root/pkg"]
|
!!PluginAInit["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/polyfill-php81","symfony/process","symfony/service-contracts","symfony/string","plugin/a","plugin/b","root/pkg"]
|
||||||
!!PluginA:1.1.1.0
|
!!PluginA:1.1.1.0
|
||||||
!!PluginB:2.2.2.0
|
!!PluginB:2.2.2.0
|
||||||
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
||||||
- Upgrading plugin/b (2.2.2 => 2.2.3): Mirroring from plugin-b
|
- Upgrading plugin/b (2.2.2 => 2.2.3): Mirroring from plugin-b
|
||||||
!!PluginBInit["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/process","symfony/service-contracts","symfony/string","plugin/a","plugin/b","root/pkg"]
|
!!PluginBInit["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/polyfill-php81","symfony/process","symfony/service-contracts","symfony/string","plugin/a","plugin/b","root/pkg"]
|
||||||
!!PluginA:1.1.2.0
|
!!PluginA:1.1.2.0
|
||||||
!!PluginB:2.2.2.0
|
!!PluginB:2.2.2.0
|
||||||
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
||||||
|
@ -45,7 +45,7 @@ Generating autoload files
|
||||||
2 packages you are using are looking for funding.
|
2 packages you are using are looking for funding.
|
||||||
Use the `composer fund` command to find out more!
|
Use the `composer fund` command to find out more!
|
||||||
> Hooks::postUpdate
|
> Hooks::postUpdate
|
||||||
!!PostUpdate:["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/process","symfony/service-contracts","symfony/string","plugin/a","plugin/b","root/pkg"]
|
!!PostUpdate:["composer/ca-bundle","composer/class-map-generator","composer/composer","composer/metadata-minifier","composer/pcre","composer/semver","composer/spdx-licenses","composer/xdebug-handler","justinrainbow/json-schema","psr/container","psr/log","psr/log-implementation","react/promise","seld/jsonlint","seld/phar-utils","seld/signal-handler","symfony/console","symfony/deprecation-contracts","symfony/filesystem","symfony/finder","symfony/polyfill-ctype","symfony/polyfill-intl-grapheme","symfony/polyfill-intl-normalizer","symfony/polyfill-mbstring","symfony/polyfill-php73","symfony/polyfill-php80","symfony/polyfill-php81","symfony/process","symfony/service-contracts","symfony/string","plugin/a","plugin/b","root/pkg"]
|
||||||
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
!!Versions:console:%[2-8]\.\d+\.\d+.0%;process:%[2-8]\.\d+\.\d+.0%;filesystem:%[2-8]\.\d+\.\d+.0%
|
||||||
!!PluginA:1.1.2.0
|
!!PluginA:1.1.2.0
|
||||||
!!PluginB:2.2.3.0
|
!!PluginB:2.2.3.0
|
||||||
|
|
Loading…
Reference in New Issue