Merge branch '2.5'
commit
5a96e6ae13
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -1,3 +1,15 @@
|
|||
### [2.5.6] 2023-05-24
|
||||
|
||||
* BC Warning: Installers and `InstallationManager::getInstallPath` will now return `null` instead of an empty string for metapackages' paths. This may have adverse effects on plugin code using this expecting always a string but it is unlikely (#11455)
|
||||
* Fixed metapackages showing their install path as the root package's path instead of empty (#11455)
|
||||
* Fixed lock file verification on `install` to deal better with `replace`/`provide` (#11475)
|
||||
* Fixed lock file having a more recent modification time than the vendor dir when `require` guesses the constraint after resolution (#11405)
|
||||
* Fixed numeric default branches with a `v` prefix being treated as non-numeric ones and receiving an alias like e.g. dev-main would (e51d755a08)
|
||||
* Fixed binary proxies not being transparent when included by another PHP process and returning a value (#11454)
|
||||
* Fixed support for plugin classes being marked as `readonly` (#11404)
|
||||
* Fixed `getmypid` being required as it is not always available (#11401)
|
||||
* Fixed authentication issue when downloading several files from private Bitbucket in parallel (#11464)
|
||||
|
||||
### [2.5.5] 2023-03-21
|
||||
|
||||
* Fixed basic auth failures resulting in infinite retry loop (#11320)
|
||||
|
@ -1708,6 +1720,7 @@
|
|||
|
||||
* Initial release
|
||||
|
||||
[2.5.6]: https://github.com/composer/composer/compare/2.5.5...2.5.6
|
||||
[2.5.5]: https://github.com/composer/composer/compare/2.5.4...2.5.5
|
||||
[2.5.4]: https://github.com/composer/composer/compare/2.5.3...2.5.4
|
||||
[2.5.3]: https://github.com/composer/composer/compare/2.5.2...2.5.3
|
||||
|
|
|
@ -18,6 +18,7 @@ use Composer\Pcre\Preg;
|
|||
use Composer\Repository\InstalledRepository;
|
||||
use Composer\Repository\LockArrayRepository;
|
||||
use Composer\Repository\PlatformRepository;
|
||||
use Composer\Repository\RootPackageRepository;
|
||||
use Composer\Util\ProcessExecutor;
|
||||
use Composer\Package\Dumper\ArrayDumper;
|
||||
use Composer\Package\Loader\ArrayLoader;
|
||||
|
@ -514,9 +515,10 @@ class Locker
|
|||
if ($includeDev === true) {
|
||||
$sets[] = ['repo' => $this->getLockedRepository(true), 'method' => 'getDevRequires', 'description' => 'Required (in require-dev)'];
|
||||
}
|
||||
$rootRepo = new RootPackageRepository($package);
|
||||
|
||||
foreach ($sets as $set) {
|
||||
$installedRepo = new InstalledRepository([$set['repo']]);
|
||||
$installedRepo = new InstalledRepository([$set['repo'], $rootRepo]);
|
||||
|
||||
foreach (call_user_func([$package, $set['method']]) as $link) {
|
||||
if (PlatformRepository::isPlatformPackage($link->getTarget())) {
|
||||
|
@ -527,9 +529,21 @@ class Locker
|
|||
}
|
||||
if ($installedRepo->findPackagesWithReplacersAndProviders($link->getTarget(), $link->getConstraint()) === []) {
|
||||
$results = $installedRepo->findPackagesWithReplacersAndProviders($link->getTarget());
|
||||
|
||||
if ($results !== []) {
|
||||
$provider = reset($results);
|
||||
$missingRequirementInfo[] = '- ' . $set['description'].' package "' . $link->getTarget() . '" is in the lock file as "'.$provider->getPrettyVersion().'" but that does not satisfy your constraint "'.$link->getPrettyConstraint().'".';
|
||||
$description = $provider->getPrettyVersion();
|
||||
if ($provider->getName() !== $link->getTarget()) {
|
||||
foreach (['getReplaces' => 'replaced as %s by %s', 'getProvides' => 'provided as %s by %s'] as $method => $text) {
|
||||
foreach (call_user_func([$provider, $method]) as $providerLink) {
|
||||
if ($providerLink->getTarget() === $link->getTarget()) {
|
||||
$description = sprintf($text, $providerLink->getPrettyConstraint(), $provider->getPrettyName().' '.$provider->getPrettyVersion());
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$missingRequirementInfo[] = '- ' . $set['description'].' package "' . $link->getTarget() . '" is in the lock file as "'.$description.'" but that does not satisfy your constraint "'.$link->getPrettyConstraint().'".';
|
||||
} else {
|
||||
$missingRequirementInfo[] = '- ' . $set['description'].' package "' . $link->getTarget() . '" is not present in the lock file.';
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ class AuthHelper
|
|||
protected $config;
|
||||
/** @var array<string, string> Map of origins to message displayed */
|
||||
private $displayedOriginAuthentications = [];
|
||||
/** @var array<string, bool> Map of URLs and whether they already retried with authentication from Bitbucket */
|
||||
private $bitbucketRetry = [];
|
||||
|
||||
public function __construct(IOInterface $io, Config $config)
|
||||
{
|
||||
|
@ -164,6 +166,12 @@ class AuthHelper
|
|||
$this->io->setAuthentication($origin, 'x-token-auth', $accessToken);
|
||||
$askForOAuthToken = false;
|
||||
}
|
||||
} elseif (!isset($this->bitbucketRetry[$url])) {
|
||||
// when multiple requests fire at the same time, they will all fail and the first one resets the token to be correct above but then the others
|
||||
// reach the code path and without this fallback they would end up throwing below
|
||||
// see https://github.com/composer/composer/pull/11464 for more details
|
||||
$askForOAuthToken = false;
|
||||
$this->bitbucketRetry[$url] = true;
|
||||
} else {
|
||||
throw new TransportException('Could not authenticate against ' . $origin, 401);
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ class Platform
|
|||
if (
|
||||
!ini_get('open_basedir')
|
||||
&& is_readable('/proc/version')
|
||||
&& false !== stripos(Silencer::call('file_get_contents', '/proc/version'), 'microsoft')
|
||||
&& false !== stripos((string)Silencer::call('file_get_contents', '/proc/version'), 'microsoft')
|
||||
&& !file_exists('/.dockerenv') // docker running inside WSL should not be seen as WSL
|
||||
) {
|
||||
return self::$isWindowsSubsystemForLinux = true;
|
||||
|
|
|
@ -17,7 +17,15 @@ The locked version will not get overwritten by an install but fails on invalid p
|
|||
"require": {
|
||||
"foo/bar": "2.0.0",
|
||||
"foo/baz": "2.0.0",
|
||||
"foo/self": "self.version"
|
||||
"foo/self": "self.version",
|
||||
"foo/provided": "1.0.0",
|
||||
"foo/provided-wrong-version": "1.0.0",
|
||||
"foo/root-replaced": "1.0.0",
|
||||
"foo/root-replaced-wrong-version": "1.0.0"
|
||||
},
|
||||
"replace": {
|
||||
"foo/root-replaced": "^1",
|
||||
"foo/root-replaced-wrong-version": "^2"
|
||||
}
|
||||
}
|
||||
--LOCK--
|
||||
|
@ -25,7 +33,14 @@ The locked version will not get overwritten by an install but fails on invalid p
|
|||
"packages": [
|
||||
{ "name": "foo/bar", "version": "1.0.0" },
|
||||
{ "name": "foo/baz", "version": "2.0.0" },
|
||||
{ "name": "foo/self", "version": "1.2.2" }
|
||||
{
|
||||
"name": "foo/self",
|
||||
"version": "1.2.2",
|
||||
"provide": {
|
||||
"foo/provided": "^1",
|
||||
"foo/provided-wrong-version": "^3"
|
||||
}
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
|
@ -45,6 +60,8 @@ install
|
|||
Installing dependencies from lock file (including require-dev)
|
||||
Verifying lock file contents can be installed on current platform.
|
||||
- Required package "foo/bar" is in the lock file as "1.0.0" but that does not satisfy your constraint "2.0.0".
|
||||
- Required package "foo/provided-wrong-version" is in the lock file as "provided as ^3 by foo/self 1.2.2" but that does not satisfy your constraint "1.0.0".
|
||||
- Required package "foo/root-replaced-wrong-version" is in the lock file as "replaced as ^2 by __root__ 1.2.3" but that does not satisfy your constraint "1.0.0".
|
||||
This usually happens when composer files are incorrectly merged or the composer.json file is manually edited.
|
||||
Read more about correctly resolving merge conflicts https://getcomposer.org/doc/articles/resolving-merge-conflicts.md
|
||||
and prefer using the "require" command over editing the composer.json file directly https://getcomposer.org/doc/03-cli.md#require-r
|
||||
|
|
|
@ -538,6 +538,71 @@ class AuthHelperTest extends TestCase
|
|||
$this->authHelper->promptAuthIfNeeded('https://gitlab.com/acme/archive.zip', $origin, 404, 'GitLab requires authentication and it was not provided');
|
||||
}
|
||||
|
||||
public function testPromptAuthIfNeededMultipleBitbucketDownloads(): void
|
||||
{
|
||||
$origin = 'bitbucket.org';
|
||||
|
||||
$expectedResult = [
|
||||
'retry' => true,
|
||||
'storeAuth' => false,
|
||||
];
|
||||
|
||||
$authConfig = [
|
||||
'bitbucket.org' => [
|
||||
'access-token' => 'bitbucket_access_token',
|
||||
'access-token-expiration' => time() + 1800,
|
||||
]
|
||||
];
|
||||
|
||||
$this->config
|
||||
->method('get')
|
||||
->willReturnMap([
|
||||
['github-domains', 0, []],
|
||||
['gitlab-domains', 0, []],
|
||||
['bitbucket-oauth', 0, $authConfig],
|
||||
['github-domains', 0, []],
|
||||
['gitlab-domains', 0, []],
|
||||
]);
|
||||
|
||||
$this->io
|
||||
->expects($this->exactly(2))
|
||||
->method('hasAuthentication')
|
||||
->with($origin)
|
||||
->willReturn(true);
|
||||
|
||||
$getAuthenticationReturnValues = [
|
||||
['username' => 'bitbucket_client_id', 'password' => 'bitbucket_client_secret'],
|
||||
['username' => 'x-token-auth', 'password' => 'bitbucket_access_token'],
|
||||
];
|
||||
|
||||
$this->io
|
||||
->expects($this->exactly(2))
|
||||
->method('getAuthentication')
|
||||
->willReturnCallback(
|
||||
function ($repositoryName) use (&$getAuthenticationReturnValues) {
|
||||
return array_shift($getAuthenticationReturnValues);
|
||||
}
|
||||
);
|
||||
|
||||
$this->io
|
||||
->expects($this->once())
|
||||
->method('setAuthentication')
|
||||
->with($origin, 'x-token-auth', 'bitbucket_access_token');
|
||||
|
||||
$result1 = $this->authHelper->promptAuthIfNeeded('https://bitbucket.org/workspace/repo1/get/hash1.zip', $origin, 401, 'HTTP/2 401 ');
|
||||
$result2 = $this->authHelper->promptAuthIfNeeded('https://bitbucket.org/workspace/repo2/get/hash2.zip', $origin, 401, 'HTTP/2 401 ');
|
||||
|
||||
$this->assertSame(
|
||||
$expectedResult,
|
||||
$result1
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
$expectedResult,
|
||||
$result2
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string|null> $auth
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue