1
0
Fork 0

Merge pull request #12269 from Seldaek/fix_installed_regr

Fix regression from #12233 in InstalledVersions when reload is used
main
Jordi Boggiano 2025-01-21 13:51:20 +01:00 committed by GitHub
commit 0626efaa13
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 49 additions and 7 deletions

View File

@ -32,6 +32,11 @@ class InstalledVersions
*/
private static $installed;
/**
* @var bool
*/
private static $installedIsLocalDir;
/**
* @var bool|null
*/
@ -309,6 +314,12 @@ class InstalledVersions
{
self::$installed = $data;
self::$installedByVendor = array();
// when using reload, we disable the duplicate protection to ensure that self::$installed data is
// always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
// so we have to assume it does not, and that may result in duplicate data being returned when listing
// all installed packages for example
self::$installedIsLocalDir = false;
}
/**
@ -325,7 +336,9 @@ class InstalledVersions
$copiedLocalDir = false;
if (self::$canGetVendors) {
$selfDir = strtr(__DIR__, '\\', '/');
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
$vendorDir = strtr($vendorDir, '\\', '/');
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
@ -333,11 +346,14 @@ class InstalledVersions
$required = require $vendorDir.'/composer/installed.php';
self::$installedByVendor[$vendorDir] = $required;
$installed[] = $required;
if (strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
self::$installed = $required;
$copiedLocalDir = true;
self::$installedIsLocalDir = true;
}
}
if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
$copiedLocalDir = true;
}
}
}

View File

@ -266,4 +266,31 @@ class InstalledVersionsTest extends TestCase
self::assertSame('/foo/bar/vendor/c/c', \Composer\InstalledVersions::getInstallPath('c/c'));
self::assertNull(\Composer\InstalledVersions::getInstallPath('foo/impl'));
}
public function testWithClassLoaderLoaded(): void
{
// disable multiple-ClassLoader-based checks of InstalledVersions by making it seem like no
// class loaders are registered
$prop = new \ReflectionProperty(ClassLoader::class, 'registeredLoaders');
$prop->setAccessible(true);
$prop->setValue(null, array_slice(self::$previousRegisteredLoaders, 0, 1, true));
$prop2 = new \ReflectionProperty(InstalledVersions::class, 'installedIsLocalDir');
$prop2->setAccessible(true);
$prop2->setValue(null, true);
self::assertFalse(InstalledVersions::isInstalled('foo/bar'));
InstalledVersions::reload([
'root' => InstalledVersions::getRootPackage(),
'versions' => [
'foo/bar' => [
'version' => '1.0.0',
'dev_requirement' => false,
],
],
]);
self::assertTrue(InstalledVersions::isInstalled('foo/bar'));
$prop->setValue(null, []);
}
}

View File

@ -10,7 +10,6 @@
* file that was distributed with this source code.
*/
use Composer\InstalledVersions;
use Composer\Util\Platform;
error_reporting(E_ALL);
@ -20,10 +19,10 @@ if (function_exists('date_default_timezone_set') && function_exists('date_defaul
}
require __DIR__.'/../src/bootstrap.php';
if (!class_exists(InstalledVersions::class, false)) {
require __DIR__.'/../src/Composer/InstalledVersions.php';
}
// ensure we always use the latest InstalledVersions.php even if an older composer ran the install, but we need
// to have it included from vendor dir and not from src/ otherwise some gated check in the code will not work
copy(__DIR__.'/../src/Composer/InstalledVersions.php', __DIR__.'/../vendor/composer/InstalledVersions.php');
require __DIR__.'/../vendor/composer/InstalledVersions.php';
Platform::putEnv('COMPOSER_TESTS_ARE_RUNNING', '1');