| @@ -32,8 +32,13 @@ | ||
| 32 | 32 | */ |
| 33 | 33 | private static $installed; |
| 34 | 34 | |
| 35 | 35 | /** |
| 36 | + * @var bool | |
| 37 | + */ | |
| 38 | + private static $installedIsLocalDir; | |
| 39 | + | |
| 40 | + /** | |
| 36 | 41 | * @var bool|null |
| 37 | 42 | */ |
| 38 | 43 | private static $canGetVendors; |
| 39 | 44 | |
| @@ -308,8 +313,14 @@ | ||
| 308 | 313 | public static function reload($data) |
| 309 | 314 | { |
| 310 | 315 | self::$installed = $data; |
| 311 | 316 | self::$installedByVendor = array(); |
| 317 | + | |
| 318 | + // when using reload, we disable the duplicate protection to ensure that self::$installed data is | |
| 319 | + // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not, | |
| 320 | + // so we have to assume it does not, and that may result in duplicate data being returned when listing | |
| 321 | + // all installed packages for example | |
| 322 | + self::$installedIsLocalDir = false; | |
| 312 | 323 | } |
| 313 | 324 | |
| 314 | 325 | /** |
| 315 | 326 | * @return array[] |
| @@ -321,21 +332,29 @@ | ||
| 321 | 332 | self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); |
| 322 | 333 | } |
| 323 | 334 | |
| 324 | 335 | $installed = array(); |
| 336 | + $copiedLocalDir = false; | |
| 325 | 337 | |
| 326 | 338 | if (self::$canGetVendors) { |
| 339 | + $selfDir = strtr(__DIR__, '\\', '/'); | |
| 327 | 340 | foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { |
| 341 | + $vendorDir = strtr($vendorDir, '\\', '/'); | |
| 328 | 342 | if (isset(self::$installedByVendor[$vendorDir])) { |
| 329 | 343 | $installed[] = self::$installedByVendor[$vendorDir]; |
| 330 | 344 | } elseif (is_file($vendorDir.'/composer/installed.php')) { |
| 331 | 345 | /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */ |
| 332 | 346 | $required = require $vendorDir.'/composer/installed.php'; |
| 333 | - $installed[] = self::$installedByVendor[$vendorDir] = $required; | |
| 334 | - if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { | |
| 335 | - self::$installed = $installed[count($installed) - 1]; | |
| 347 | + self::$installedByVendor[$vendorDir] = $required; | |
| 348 | + $installed[] = $required; | |
| 349 | + if (self::$installed === null && $vendorDir.'/composer' === $selfDir) { | |
| 350 | + self::$installed = $required; | |
| 351 | + self::$installedIsLocalDir = true; | |
| 336 | 352 | } |
| 337 | 353 | } |
| 354 | + if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) { | |
| 355 | + $copiedLocalDir = true; | |
| 356 | + } | |
| 338 | 357 | } |
| 339 | 358 | } |
| 340 | 359 | |
| 341 | 360 | if (null === self::$installed) { |
| @@ -349,9 +368,9 @@ | ||
| 349 | 368 | self::$installed = array(); |
| 350 | 369 | } |
| 351 | 370 | } |
| 352 | 371 | |
| 353 | - if (self::$installed !== array()) { | |
| 372 | + if (self::$installed !== array() && !$copiedLocalDir) { | |
| 354 | 373 | $installed[] = self::$installed; |
| 355 | 374 | } |
| 356 | 375 | |
| 357 | 376 | return $installed; |