Merge branch '2.3' into main
commit
d971f2e37e
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -71,6 +71,15 @@
|
||||||
* Fixed symlink creation in linux VM guest filesystems to be recognized by Windows (#10592)
|
* Fixed symlink creation in linux VM guest filesystems to be recognized by Windows (#10592)
|
||||||
* Performance improvement in pool optimization step (#10585)
|
* Performance improvement in pool optimization step (#10585)
|
||||||
|
|
||||||
|
### [2.2.13] 2022-05-25
|
||||||
|
|
||||||
|
* Fixed invalid credentials loop when setting up GitLab token (#10748)
|
||||||
|
* Fixed PHP 8.2 deprecations (#10766)
|
||||||
|
* Fixed lock file changes being output even when the lock file creation is disabled
|
||||||
|
* Fixed race condition when multiple requests asking for auth on the same hostname fired concurrently (#10763)
|
||||||
|
* Fixed quoting of commas on Windows (#10775)
|
||||||
|
* Fixed issue installing path repos with a disabled symlink function (#10786)
|
||||||
|
|
||||||
### [2.2.12] 2022-04-13
|
### [2.2.12] 2022-04-13
|
||||||
|
|
||||||
* Security: Fixed command injection vulnerability in HgDriver/GitDriver (GHSA-x7cr-6qr6-2hh6 / CVE-2022-24828)
|
* Security: Fixed command injection vulnerability in HgDriver/GitDriver (GHSA-x7cr-6qr6-2hh6 / CVE-2022-24828)
|
||||||
|
@ -1508,6 +1517,7 @@
|
||||||
[2.3.0]: https://github.com/composer/composer/compare/2.3.0-RC2...2.3.0
|
[2.3.0]: https://github.com/composer/composer/compare/2.3.0-RC2...2.3.0
|
||||||
[2.3.0-RC2]: https://github.com/composer/composer/compare/2.3.0-RC1...2.3.0-RC2
|
[2.3.0-RC2]: https://github.com/composer/composer/compare/2.3.0-RC1...2.3.0-RC2
|
||||||
[2.3.0-RC1]: https://github.com/composer/composer/compare/2.2.9...2.3.0-RC1
|
[2.3.0-RC1]: https://github.com/composer/composer/compare/2.2.9...2.3.0-RC1
|
||||||
|
[2.2.13]: https://github.com/composer/composer/compare/2.2.12...2.2.13
|
||||||
[2.2.12]: https://github.com/composer/composer/compare/2.2.11...2.2.12
|
[2.2.12]: https://github.com/composer/composer/compare/2.2.11...2.2.12
|
||||||
[2.2.11]: https://github.com/composer/composer/compare/2.2.10...2.2.11
|
[2.2.11]: https://github.com/composer/composer/compare/2.2.10...2.2.11
|
||||||
[2.2.10]: https://github.com/composer/composer/compare/2.2.9...2.2.10
|
[2.2.10]: https://github.com/composer/composer/compare/2.2.9...2.2.10
|
||||||
|
|
|
@ -8,16 +8,16 @@
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "composer/ca-bundle",
|
"name": "composer/ca-bundle",
|
||||||
"version": "1.3.1",
|
"version": "1.3.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/composer/ca-bundle.git",
|
"url": "https://github.com/composer/ca-bundle.git",
|
||||||
"reference": "4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b"
|
"reference": "fd5dd441932a7e10ca6e5b490e272d34c8430640"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b",
|
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/fd5dd441932a7e10ca6e5b490e272d34c8430640",
|
||||||
"reference": "4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b",
|
"reference": "fd5dd441932a7e10ca6e5b490e272d34c8430640",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -64,7 +64,7 @@
|
||||||
"support": {
|
"support": {
|
||||||
"irc": "irc://irc.freenode.org/composer",
|
"irc": "irc://irc.freenode.org/composer",
|
||||||
"issues": "https://github.com/composer/ca-bundle/issues",
|
"issues": "https://github.com/composer/ca-bundle/issues",
|
||||||
"source": "https://github.com/composer/ca-bundle/tree/1.3.1"
|
"source": "https://github.com/composer/ca-bundle/tree/1.3.2"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -80,7 +80,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2021-10-28T20:44:15+00:00"
|
"time": "2022-05-24T11:56:16+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "composer/metadata-minifier",
|
"name": "composer/metadata-minifier",
|
||||||
|
@ -305,16 +305,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "composer/spdx-licenses",
|
"name": "composer/spdx-licenses",
|
||||||
"version": "1.5.6",
|
"version": "1.5.7",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/composer/spdx-licenses.git",
|
"url": "https://github.com/composer/spdx-licenses.git",
|
||||||
"reference": "a30d487169d799745ca7280bc90fdfa693536901"
|
"reference": "c848241796da2abf65837d51dce1fae55a960149"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/composer/spdx-licenses/zipball/a30d487169d799745ca7280bc90fdfa693536901",
|
"url": "https://api.github.com/repos/composer/spdx-licenses/zipball/c848241796da2abf65837d51dce1fae55a960149",
|
||||||
"reference": "a30d487169d799745ca7280bc90fdfa693536901",
|
"reference": "c848241796da2abf65837d51dce1fae55a960149",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -365,7 +365,7 @@
|
||||||
"support": {
|
"support": {
|
||||||
"irc": "irc://irc.freenode.org/composer",
|
"irc": "irc://irc.freenode.org/composer",
|
||||||
"issues": "https://github.com/composer/spdx-licenses/issues",
|
"issues": "https://github.com/composer/spdx-licenses/issues",
|
||||||
"source": "https://github.com/composer/spdx-licenses/tree/1.5.6"
|
"source": "https://github.com/composer/spdx-licenses/tree/1.5.7"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -381,7 +381,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2021-11-18T10:14:14+00:00"
|
"time": "2022-05-23T07:37:50+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "composer/xdebug-handler",
|
"name": "composer/xdebug-handler",
|
||||||
|
@ -1825,16 +1825,16 @@
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
{
|
{
|
||||||
"name": "phpstan/phpstan",
|
"name": "phpstan/phpstan",
|
||||||
"version": "1.6.8",
|
"version": "1.7.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpstan/phpstan.git",
|
"url": "https://github.com/phpstan/phpstan.git",
|
||||||
"reference": "d76498c5531232cb8386ceb6004f7e013138d3ba"
|
"reference": "e3baed2ee2ef322e0f9b8fe8f87fdbe024c7c719"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/d76498c5531232cb8386ceb6004f7e013138d3ba",
|
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/e3baed2ee2ef322e0f9b8fe8f87fdbe024c7c719",
|
||||||
"reference": "d76498c5531232cb8386ceb6004f7e013138d3ba",
|
"reference": "e3baed2ee2ef322e0f9b8fe8f87fdbe024c7c719",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -1860,7 +1860,7 @@
|
||||||
"description": "PHPStan - PHP Static Analysis Tool",
|
"description": "PHPStan - PHP Static Analysis Tool",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/phpstan/phpstan/issues",
|
"issues": "https://github.com/phpstan/phpstan/issues",
|
||||||
"source": "https://github.com/phpstan/phpstan/tree/1.6.8"
|
"source": "https://github.com/phpstan/phpstan/tree/1.7.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -1880,7 +1880,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-05-10T06:54:21+00:00"
|
"time": "2022-05-24T09:05:09+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpstan/phpstan-deprecation-rules",
|
"name": "phpstan/phpstan-deprecation-rules",
|
||||||
|
|
|
@ -2167,7 +2167,7 @@ parameters:
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Call to function in_array\\(\\) with arguments 20, array\\{0\\: 10\\|20, 1\\?\\: 20\\} and true will always evaluate to true\\.$#"
|
message: "#^Call to function in_array\\(\\) with arguments 20, array\\{0\\: 10\\|20, 1\\?\\: 20\\} and true will always evaluate to true\\.$#"
|
||||||
count: 1
|
count: 2
|
||||||
path: ../src/Composer/Downloader/PathDownloader.php
|
path: ../src/Composer/Downloader/PathDownloader.php
|
||||||
|
|
||||||
-
|
-
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Package name, including 'vendor-name/' prefix.",
|
"description": "Package name, including 'vendor-name/' prefix.",
|
||||||
"pattern": "^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$"
|
"pattern": "^[a-z0-9]([_.-]?[a-z0-9]++)*+/[a-z0-9](([_.]|-{1,2})?[a-z0-9]++)*+$"
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
|
@ -159,7 +159,7 @@ EOT
|
||||||
$localRepo = $composer->getRepositoryManager()->getLocalRepository();
|
$localRepo = $composer->getRepositoryManager()->getLocalRepository();
|
||||||
$repo = new CompositeRepository(array_merge(array($localRepo), $composer->getRepositoryManager()->getRepositories()));
|
$repo = new CompositeRepository(array_merge(array($localRepo), $composer->getRepositoryManager()->getRepositories()));
|
||||||
} else {
|
} else {
|
||||||
$defaultRepos = RepositoryFactory::defaultRepos($this->getIO());
|
$defaultRepos = RepositoryFactory::defaultReposWithDefaultManager($io);
|
||||||
$io->writeError('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos)));
|
$io->writeError('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos)));
|
||||||
$repo = new CompositeRepository($defaultRepos);
|
$repo = new CompositeRepository($defaultRepos);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ use Composer\Package\CompletePackageInterface;
|
||||||
use Composer\Package\RootPackage;
|
use Composer\Package\RootPackage;
|
||||||
use Composer\Repository\InstalledArrayRepository;
|
use Composer\Repository\InstalledArrayRepository;
|
||||||
use Composer\Repository\CompositeRepository;
|
use Composer\Repository\CompositeRepository;
|
||||||
|
use Composer\Repository\RepositoryInterface;
|
||||||
use Composer\Repository\RootPackageRepository;
|
use Composer\Repository\RootPackageRepository;
|
||||||
use Composer\Repository\InstalledRepository;
|
use Composer\Repository\InstalledRepository;
|
||||||
use Composer\Repository\PlatformRepository;
|
use Composer\Repository\PlatformRepository;
|
||||||
|
@ -80,7 +81,7 @@ abstract class BaseDependencyCommand extends BaseCommand
|
||||||
// If the version we ask for is not installed then we need to locate it in remote repos and add it.
|
// If the version we ask for is not installed then we need to locate it in remote repos and add it.
|
||||||
// This is needed for why-not to resolve conflicts from an uninstalled version against installed packages.
|
// This is needed for why-not to resolve conflicts from an uninstalled version against installed packages.
|
||||||
if (!$installedRepo->findPackage($needle, $textConstraint)) {
|
if (!$installedRepo->findPackage($needle, $textConstraint)) {
|
||||||
$defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO()));
|
$defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO(), $composer->getConfig(), $composer->getRepositoryManager()));
|
||||||
if ($match = $defaultRepos->findPackage($needle, $textConstraint)) {
|
if ($match = $defaultRepos->findPackage($needle, $textConstraint)) {
|
||||||
$installedRepo->addRepository(new InstalledArrayRepository(array(clone $match)));
|
$installedRepo->addRepository(new InstalledArrayRepository(array(clone $match)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,6 +170,6 @@ EOT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return RepositoryFactory::defaultRepos($this->getIO());
|
return RepositoryFactory::defaultReposWithDefaultManager($this->getIO());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,6 +225,9 @@ EOT
|
||||||
$repositories = $input->getOption('repository');
|
$repositories = $input->getOption('repository');
|
||||||
if (count($repositories) > 0) {
|
if (count($repositories) > 0) {
|
||||||
$config = Factory::createConfig($io);
|
$config = Factory::createConfig($io);
|
||||||
|
$io->loadConfiguration($config);
|
||||||
|
$repoManager = RepositoryFactory::manager($io, $config);
|
||||||
|
|
||||||
$repos = array(new PlatformRepository);
|
$repos = array(new PlatformRepository);
|
||||||
$createDefaultPackagistRepo = true;
|
$createDefaultPackagistRepo = true;
|
||||||
foreach ($repositories as $repo) {
|
foreach ($repositories as $repo) {
|
||||||
|
@ -236,14 +239,14 @@ EOT
|
||||||
$createDefaultPackagistRepo = false;
|
$createDefaultPackagistRepo = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$repos[] = RepositoryFactory::createRepo($io, $config, $repoConfig);
|
$repos[] = RepositoryFactory::createRepo($io, $config, $repoConfig, $repoManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($createDefaultPackagistRepo) {
|
if ($createDefaultPackagistRepo) {
|
||||||
$repos[] = RepositoryFactory::createRepo($io, $config, array(
|
$repos[] = RepositoryFactory::createRepo($io, $config, array(
|
||||||
'type' => 'composer',
|
'type' => 'composer',
|
||||||
'url' => 'https://repo.packagist.org',
|
'url' => 'https://repo.packagist.org',
|
||||||
));
|
), $repoManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->repos = new CompositeRepository($repos);
|
$this->repos = new CompositeRepository($repos);
|
||||||
|
|
|
@ -47,7 +47,7 @@ trait PackageDiscoveryTrait
|
||||||
if (null === $this->repos) {
|
if (null === $this->repos) {
|
||||||
$this->repos = new CompositeRepository(array_merge(
|
$this->repos = new CompositeRepository(array_merge(
|
||||||
array(new PlatformRepository),
|
array(new PlatformRepository),
|
||||||
RepositoryFactory::defaultRepos($this->getIO())
|
RepositoryFactory::defaultReposWithDefaultManager($this->getIO())
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -194,7 +194,7 @@ EOT
|
||||||
$repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
|
$repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
|
||||||
$installedRepo->addRepository($composer->getRepositoryManager()->getLocalRepository());
|
$installedRepo->addRepository($composer->getRepositoryManager()->getLocalRepository());
|
||||||
} else {
|
} else {
|
||||||
$defaultRepos = RepositoryFactory::defaultRepos($io);
|
$defaultRepos = RepositoryFactory::defaultReposWithDefaultManager($io);
|
||||||
$repos = new CompositeRepository($defaultRepos);
|
$repos = new CompositeRepository($defaultRepos);
|
||||||
$io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
|
$io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,7 @@ EOT
|
||||||
}
|
}
|
||||||
$repos = new CompositeRepository(array_merge(array(new FilterRepository($installedRepo, array('canonical' => false))), $composer->getRepositoryManager()->getRepositories()));
|
$repos = new CompositeRepository(array_merge(array(new FilterRepository($installedRepo, array('canonical' => false))), $composer->getRepositoryManager()->getRepositories()));
|
||||||
} elseif ($input->getOption('all')) {
|
} elseif ($input->getOption('all')) {
|
||||||
$defaultRepos = RepositoryFactory::defaultRepos($io);
|
$defaultRepos = RepositoryFactory::defaultReposWithDefaultManager($io);
|
||||||
$io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
|
$io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
|
||||||
$installedRepo = new InstalledRepository(array($platformRepo));
|
$installedRepo = new InstalledRepository(array($platformRepo));
|
||||||
$repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
|
$repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
|
||||||
|
|
|
@ -135,7 +135,8 @@ class Application extends BaseApplication
|
||||||
$this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
|
$this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
|
||||||
$this->disableScriptsByDefault = $input->hasParameterOption('--no-scripts');
|
$this->disableScriptsByDefault = $input->hasParameterOption('--no-scripts');
|
||||||
|
|
||||||
if (Platform::getEnv('COMPOSER_NO_INTERACTION') || !Platform::isTty(defined('STDIN') ? STDIN : fopen('php://stdin', 'r'))) {
|
$stdin = defined('STDIN') ? STDIN : fopen('php://stdin', 'r');
|
||||||
|
if (Platform::getEnv('COMPOSER_NO_INTERACTION') || $stdin === false || !Platform::isTty($stdin)) {
|
||||||
$input->setInteractive(false);
|
$input->setInteractive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ class RuleSetIterator implements \Iterator
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->currentType = $this->types[$this->currentTypeOffset];
|
$this->currentType = $this->types[$this->currentTypeOffset];
|
||||||
} while (isset($this->types[$this->currentTypeOffset]) && !\count($this->rules[$this->currentType]));
|
} while (0 === \count($this->rules[$this->currentType]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ class RuleSetIterator implements \Iterator
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->currentType = $this->types[$this->currentTypeOffset];
|
$this->currentType = $this->types[$this->currentTypeOffset];
|
||||||
} while (isset($this->types[$this->currentTypeOffset]) && !\count($this->rules[$this->currentType]));
|
} while (0 === \count($this->rules[$this->currentType]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function valid(): bool
|
public function valid(): bool
|
||||||
|
|
|
@ -280,6 +280,15 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter
|
||||||
$allowedStrategies = array(self::STRATEGY_MIRROR);
|
$allowedStrategies = array(self::STRATEGY_MIRROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check we can use symlink() otherwise
|
||||||
|
if (!Platform::isWindows() && self::STRATEGY_SYMLINK === $currentStrategy && !function_exists('symlink')) {
|
||||||
|
if (!in_array(self::STRATEGY_MIRROR, $allowedStrategies, true)) {
|
||||||
|
throw new \RuntimeException('Your PHP has the symlink() function disabled which does not allow Composer to use symlinks and this path repository has symlink:true in its options so copying is not allowed');
|
||||||
|
}
|
||||||
|
$currentStrategy = self::STRATEGY_MIRROR;
|
||||||
|
$allowedStrategies = array(self::STRATEGY_MIRROR);
|
||||||
|
}
|
||||||
|
|
||||||
return array($currentStrategy, $allowedStrategies);
|
return array($currentStrategy, $allowedStrategies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,6 @@ abstract class BasePackage implements PackageInterface
|
||||||
* READ-ONLY: The package id, public for fast access in dependency solver
|
* READ-ONLY: The package id, public for fast access in dependency solver
|
||||||
* @var int
|
* @var int
|
||||||
* @internal
|
* @internal
|
||||||
* @readonly
|
|
||||||
*/
|
*/
|
||||||
public $id;
|
public $id;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
|
|
|
@ -456,7 +456,7 @@ class ValidatingArrayLoader implements LoaderInterface
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Preg::isMatch('{^[a-z0-9](?:[_.-]?[a-z0-9]+)*/[a-z0-9](?:(?:[_.]?|-{0,2})[a-z0-9]+)*$}iD', $name)) {
|
if (!Preg::isMatch('{^[a-z0-9](?:[_.-]?[a-z0-9]++)*+/[a-z0-9](?:(?:[_.]|-{1,2})?[a-z0-9]++)*+$}iD', $name)) {
|
||||||
return $name.' is invalid, it should have a vendor name, a forward slash, and a package name. The vendor and package name can be words separated by -, . or _. The complete name should match "^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$".';
|
return $name.' is invalid, it should have a vendor name, a forward slash, and a package name. The vendor and package name can be words separated by -, . or _. The complete name should match "^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$".';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,8 @@ class RepositoryFactory
|
||||||
public static function createRepo(IOInterface $io, Config $config, array $repoConfig, RepositoryManager $rm = null): RepositoryInterface
|
public static function createRepo(IOInterface $io, Config $config, array $repoConfig, RepositoryManager $rm = null): RepositoryInterface
|
||||||
{
|
{
|
||||||
if (!$rm) {
|
if (!$rm) {
|
||||||
$rm = static::manager($io, $config, Factory::createHttpDownloader($io, $config));
|
@trigger_error('Not passing a repository manager when calling createRepo is deprecated since Composer 2.3.6', E_USER_DEPRECATED);
|
||||||
|
$rm = static::manager($io, $config);
|
||||||
}
|
}
|
||||||
$repos = self::createRepos($rm, array($repoConfig));
|
$repos = self::createRepos($rm, array($repoConfig));
|
||||||
|
|
||||||
|
@ -95,14 +96,18 @@ class RepositoryFactory
|
||||||
*/
|
*/
|
||||||
public static function defaultRepos(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null): array
|
public static function defaultRepos(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null): array
|
||||||
{
|
{
|
||||||
if (!$config) {
|
if (null === $rm) {
|
||||||
|
@trigger_error('Not passing a repository manager when calling defaultRepos is deprecated since Composer 2.3.6, use defaultReposWithDefaultManager() instead if you cannot get a manager.', E_USER_DEPRECATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $config) {
|
||||||
$config = Factory::createConfig($io);
|
$config = Factory::createConfig($io);
|
||||||
}
|
}
|
||||||
if ($io) {
|
if (null !== $io) {
|
||||||
$io->loadConfiguration($config);
|
$io->loadConfiguration($config);
|
||||||
}
|
}
|
||||||
if (!$rm) {
|
if (null === $rm) {
|
||||||
if (!$io) {
|
if (null === $io) {
|
||||||
throw new \InvalidArgumentException('This function requires either an IOInterface or a RepositoryManager');
|
throw new \InvalidArgumentException('This function requires either an IOInterface or a RepositoryManager');
|
||||||
}
|
}
|
||||||
$rm = static::manager($io, $config, Factory::createHttpDownloader($io, $config));
|
$rm = static::manager($io, $config, Factory::createHttpDownloader($io, $config));
|
||||||
|
@ -118,8 +123,16 @@ class RepositoryFactory
|
||||||
* @param HttpDownloader $httpDownloader
|
* @param HttpDownloader $httpDownloader
|
||||||
* @return RepositoryManager
|
* @return RepositoryManager
|
||||||
*/
|
*/
|
||||||
public static function manager(IOInterface $io, Config $config, HttpDownloader $httpDownloader, EventDispatcher $eventDispatcher = null, ProcessExecutor $process = null): RepositoryManager
|
public static function manager(IOInterface $io, Config $config, HttpDownloader $httpDownloader = null, EventDispatcher $eventDispatcher = null, ProcessExecutor $process = null): RepositoryManager
|
||||||
{
|
{
|
||||||
|
if ($httpDownloader === null) {
|
||||||
|
$httpDownloader = Factory::createHttpDownloader($io, $config);
|
||||||
|
}
|
||||||
|
if ($process === null) {
|
||||||
|
$process = new ProcessExecutor($io);
|
||||||
|
$process->enableAsync();
|
||||||
|
}
|
||||||
|
|
||||||
$rm = new RepositoryManager($io, $config, $httpDownloader, $eventDispatcher, $process);
|
$rm = new RepositoryManager($io, $config, $httpDownloader, $eventDispatcher, $process);
|
||||||
$rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository');
|
$rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository');
|
||||||
$rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository');
|
$rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository');
|
||||||
|
@ -140,6 +153,18 @@ class RepositoryFactory
|
||||||
return $rm;
|
return $rm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return RepositoryInterface[]
|
||||||
|
*/
|
||||||
|
public static function defaultReposWithDefaultManager(IOInterface $io): array
|
||||||
|
{
|
||||||
|
$manager = RepositoryFactory::manager($io, $config = Factory::createConfig($io));
|
||||||
|
$io->loadConfiguration($config);
|
||||||
|
|
||||||
|
return RepositoryFactory::defaultRepos($io, $config, $manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<int|string, mixed> $repoConfigs
|
* @param array<int|string, mixed> $repoConfigs
|
||||||
*
|
*
|
||||||
|
|
|
@ -295,6 +295,13 @@ class GitHubDriver extends VcsDriver
|
||||||
|
|
||||||
$resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier);
|
$resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier);
|
||||||
$resource = $this->getContents($resource)->decodeJson();
|
$resource = $this->getContents($resource)->decodeJson();
|
||||||
|
|
||||||
|
// The GitHub contents API only returns files up to 1MB as base64 encoded files
|
||||||
|
// larger files either need be fetched with a raw accept header or by using the git blob endpoint
|
||||||
|
if ((!isset($resource['content']) || $resource['content'] === '') && $resource['encoding'] === 'none' && isset($resource['git_url'])) {
|
||||||
|
$resource = $this->getContents($resource['git_url'])->decodeJson();
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) {
|
if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) {
|
||||||
throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier);
|
throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,8 +38,10 @@ class ErrorHandler
|
||||||
*/
|
*/
|
||||||
public static function handle(int $level, string $message, string $file, int $line): bool
|
public static function handle(int $level, string $message, string $file, int $line): bool
|
||||||
{
|
{
|
||||||
|
$isDeprecationNotice = $level === E_DEPRECATED || $level === E_USER_DEPRECATED;
|
||||||
|
|
||||||
// error code is not included in error_reporting
|
// error code is not included in error_reporting
|
||||||
if (!(error_reporting() & $level)) {
|
if (!$isDeprecationNotice && !(error_reporting() & $level)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +50,7 @@ class ErrorHandler
|
||||||
"\na legitimately suppressed error that you were not supposed to see.";
|
"\na legitimately suppressed error that you were not supposed to see.";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($level !== E_DEPRECATED && $level !== E_USER_DEPRECATED) {
|
if (!$isDeprecationNotice) {
|
||||||
throw new \ErrorException($message, 0, $level, $file, $line);
|
throw new \ErrorException($message, 0, $level, $file, $line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ use Composer\Downloader\MaxFileSizeExceededException;
|
||||||
use Composer\IO\IOInterface;
|
use Composer\IO\IOInterface;
|
||||||
use Composer\Downloader\TransportException;
|
use Composer\Downloader\TransportException;
|
||||||
use Composer\Pcre\Preg;
|
use Composer\Pcre\Preg;
|
||||||
|
use Composer\Util\Platform;
|
||||||
use Composer\Util\StreamContextFactory;
|
use Composer\Util\StreamContextFactory;
|
||||||
use Composer\Util\AuthHelper;
|
use Composer\Util\AuthHelper;
|
||||||
use Composer\Util\Url;
|
use Composer\Util\Url;
|
||||||
|
@ -394,8 +395,19 @@ class CurlDownloader
|
||||||
$response = new CurlResponse(array('url' => $progress['url']), $statusCode, $headers, $contents, $progress);
|
$response = new CurlResponse(array('url' => $progress['url']), $statusCode, $headers, $contents, $progress);
|
||||||
$this->io->writeError('['.$statusCode.'] '.Url::sanitize($progress['url']), true, IOInterface::DEBUG);
|
$this->io->writeError('['.$statusCode.'] '.Url::sanitize($progress['url']), true, IOInterface::DEBUG);
|
||||||
} else {
|
} else {
|
||||||
|
$maxFileSize = $job['options']['max_file_size'] ?? null;
|
||||||
rewind($job['bodyHandle']);
|
rewind($job['bodyHandle']);
|
||||||
$contents = stream_get_contents($job['bodyHandle']);
|
if ($maxFileSize !== null) {
|
||||||
|
$contents = stream_get_contents($job['bodyHandle'], $maxFileSize);
|
||||||
|
// Gzipped responses with missing Content-Length header cannot be detected during the file download
|
||||||
|
// because $progress['size_download'] refers to the gzipped size downloaded, not the actual file size
|
||||||
|
if ($contents !== false && Platform::strlen($contents) >= $maxFileSize) {
|
||||||
|
throw new MaxFileSizeExceededException('Maximum allowed download size reached. Downloaded ' . Platform::strlen($contents) . ' of allowed ' . $maxFileSize . ' bytes');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$contents = stream_get_contents($job['bodyHandle']);
|
||||||
|
}
|
||||||
|
|
||||||
$response = new CurlResponse(array('url' => $progress['url']), $statusCode, $headers, $contents, $progress);
|
$response = new CurlResponse(array('url' => $progress['url']), $statusCode, $headers, $contents, $progress);
|
||||||
$this->io->writeError('['.$statusCode.'] '.Url::sanitize($progress['url']), true, IOInterface::DEBUG);
|
$this->io->writeError('['.$statusCode.'] '.Url::sanitize($progress['url']), true, IOInterface::DEBUG);
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,6 +201,9 @@ class Platform
|
||||||
{
|
{
|
||||||
if ($fd === null) {
|
if ($fd === null) {
|
||||||
$fd = defined('STDOUT') ? STDOUT : fopen('php://stdout', 'w');
|
$fd = defined('STDOUT') ? STDOUT : fopen('php://stdout', 'w');
|
||||||
|
if ($fd === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// detect msysgit/mingw and assume this is a tty because detection
|
// detect msysgit/mingw and assume this is a tty because detection
|
||||||
|
|
|
@ -455,7 +455,8 @@ class ProcessExecutor
|
||||||
// New lines break cmd.exe command parsing
|
// New lines break cmd.exe command parsing
|
||||||
$argument = strtr($argument, "\n", ' ');
|
$argument = strtr($argument, "\n", ' ');
|
||||||
|
|
||||||
$quote = strpbrk($argument, " \t") !== false;
|
// In addition to whitespace, commas need quoting to preserve paths
|
||||||
|
$quote = strpbrk($argument, " \t,") !== false;
|
||||||
$argument = Preg::replace('/(\\\\*)"/', '$1$1\\"', $argument, -1, $dquotes);
|
$argument = Preg::replace('/(\\\\*)"/', '$1$1\\"', $argument, -1, $dquotes);
|
||||||
$meta = $dquotes || Preg::isMatch('/%[^%]+%|![^!]+!/', $argument);
|
$meta = $dquotes || Preg::isMatch('/%[^%]+%|![^!]+!/', $argument);
|
||||||
|
|
||||||
|
|
|
@ -87,9 +87,11 @@ class PoolBuilderTest extends TestCase
|
||||||
chdir(__DIR__.'/Fixtures/poolbuilder/');
|
chdir(__DIR__.'/Fixtures/poolbuilder/');
|
||||||
|
|
||||||
$repositorySet = new RepositorySet($minimumStability, $stabilityFlags, $rootAliases, $rootReferences);
|
$repositorySet = new RepositorySet($minimumStability, $stabilityFlags, $rootAliases, $rootReferences);
|
||||||
|
$config = new Config(false);
|
||||||
|
$rm = RepositoryFactory::manager($io = new NullIO(), $config);
|
||||||
foreach ($packageRepos as $packages) {
|
foreach ($packageRepos as $packages) {
|
||||||
if (isset($packages['type'])) {
|
if (isset($packages['type'])) {
|
||||||
$repo = RepositoryFactory::createRepo(new NullIO, new Config(false), $packages);
|
$repo = RepositoryFactory::createRepo($io, $config, $packages, $rm);
|
||||||
$repositorySet->addRepository($repo);
|
$repositorySet->addRepository($repo);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,9 @@ class ComposerSchemaTest extends TestCase
|
||||||
$expectedError = array(
|
$expectedError = array(
|
||||||
array(
|
array(
|
||||||
'property' => 'name',
|
'property' => 'name',
|
||||||
'message' => 'Does not match the regex pattern ^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$',
|
'message' => 'Does not match the regex pattern ^[a-z0-9]([_.-]?[a-z0-9]++)*+/[a-z0-9](([_.]|-{1,2})?[a-z0-9]++)*+$',
|
||||||
'constraint' => 'pattern',
|
'constraint' => 'pattern',
|
||||||
'pattern' => '^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$',
|
'pattern' => '^[a-z0-9]([_.-]?[a-z0-9]++)*+/[a-z0-9](([_.]|-{1,2})?[a-z0-9]++)*+$',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ class ArchivableFilesFinderTest extends TestCase
|
||||||
);
|
);
|
||||||
|
|
||||||
$fileTree = array(
|
$fileTree = array(
|
||||||
|
'.foo',
|
||||||
'A/prefixA.foo',
|
'A/prefixA.foo',
|
||||||
'A/prefixB.foo',
|
'A/prefixB.foo',
|
||||||
'A/prefixC.foo',
|
'A/prefixC.foo',
|
||||||
|
@ -110,6 +111,7 @@ class ArchivableFilesFinderTest extends TestCase
|
||||||
'/prefixA.foo',
|
'/prefixA.foo',
|
||||||
'prefixC.*',
|
'prefixC.*',
|
||||||
'!*/*/*/prefixC.foo',
|
'!*/*/*/prefixC.foo',
|
||||||
|
'.*',
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->finder = new ArchivableFilesFinder($this->sources, $excludes);
|
$this->finder = new ArchivableFilesFinder($this->sources, $excludes);
|
||||||
|
@ -214,6 +216,7 @@ class ArchivableFilesFinderTest extends TestCase
|
||||||
'/!important!.txt',
|
'/!important!.txt',
|
||||||
'/!important_too!.txt',
|
'/!important_too!.txt',
|
||||||
'/#weirdfile',
|
'/#weirdfile',
|
||||||
|
'/.foo',
|
||||||
'/A/prefixA.foo',
|
'/A/prefixA.foo',
|
||||||
'/A/prefixB.foo',
|
'/A/prefixB.foo',
|
||||||
'/A/prefixC.foo',
|
'/A/prefixC.foo',
|
||||||
|
|
|
@ -179,6 +179,9 @@ class ProcessExecutorTest extends TestCase
|
||||||
// no whitespace must not be quoted
|
// no whitespace must not be quoted
|
||||||
'no-ws' => array('abc', 'abc', "'abc'"),
|
'no-ws' => array('abc', 'abc', "'abc'"),
|
||||||
|
|
||||||
|
// commas must be quoted
|
||||||
|
'comma' => array('a,bc', '"a,bc"', "'a,bc'"),
|
||||||
|
|
||||||
// double-quotes must be backslash-escaped
|
// double-quotes must be backslash-escaped
|
||||||
'dq' => array('a"bc', 'a\^"bc', "'a\"bc'"),
|
'dq' => array('a"bc', 'a\^"bc', "'a\"bc'"),
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue