1
0
Fork 0

Merge branch '2.5'

pull/11478/head
Jordi Boggiano 2023-05-23 23:49:53 +02:00
commit 5a96e6ae13
No known key found for this signature in database
GPG Key ID: 7BBD42C429EC80BC
6 changed files with 122 additions and 5 deletions

View File

@ -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

View File

@ -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.';
}

View 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);
}

View File

@ -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;

View File

@ -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

View File

@ -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
*