Fix autoload regression with metapackage dependencies (#11481)
fixes #11480 introduced by #11455pull/11494/head
parent
4893b67efa
commit
33c293aec3
|
@ -473,7 +473,7 @@ EOF;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param PackageInterface[] $packages
|
* @param PackageInterface[] $packages
|
||||||
* @return array<int, array{0: PackageInterface, 1: string}>
|
* @return non-empty-array<int, array{0: PackageInterface, 1: string|null}>
|
||||||
*/
|
*/
|
||||||
public function buildPackageMap(InstallationManager $installationManager, PackageInterface $rootPackage, array $packages)
|
public function buildPackageMap(InstallationManager $installationManager, PackageInterface $rootPackage, array $packages)
|
||||||
{
|
{
|
||||||
|
@ -485,14 +485,9 @@ EOF;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$this->validatePackage($package);
|
$this->validatePackage($package);
|
||||||
$installPath = $installationManager->getInstallPath($package);
|
|
||||||
if ($installPath === null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$packageMap[] = [
|
$packageMap[] = [
|
||||||
$package,
|
$package,
|
||||||
$installPath,
|
$installationManager->getInstallPath($package),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,7 +518,7 @@ EOF;
|
||||||
/**
|
/**
|
||||||
* Compiles an ordered list of namespace => path mappings
|
* Compiles an ordered list of namespace => path mappings
|
||||||
*
|
*
|
||||||
* @param array<int, array{0: PackageInterface, 1: string}> $packageMap array of array(package, installDir-relative-to-composer.json)
|
* @param non-empty-array<int, array{0: PackageInterface, 1: string|null}> $packageMap array of array(package, installDir-relative-to-composer.json or null for metapackages)
|
||||||
* @param RootPackageInterface $rootPackage root package instance
|
* @param RootPackageInterface $rootPackage root package instance
|
||||||
* @param bool|string[] $filteredDevPackages If an array, the list of packages that must be removed. If bool, whether to filter out require-dev packages
|
* @param bool|string[] $filteredDevPackages If an array, the list of packages that must be removed. If bool, whether to filter out require-dev packages
|
||||||
* @return array
|
* @return array
|
||||||
|
@ -613,7 +608,7 @@ EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<int, array{0: PackageInterface, 1: string}> $packageMap
|
* @param array<int, array{0: PackageInterface, 1: string|null}> $packageMap
|
||||||
* @return ?string
|
* @return ?string
|
||||||
*/
|
*/
|
||||||
protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, string $basePath, string $vendorPath, string $vendorPathCode, string $appBaseDirCode)
|
protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, string $basePath, string $vendorPath, string $vendorPathCode, string $appBaseDirCode)
|
||||||
|
@ -623,6 +618,11 @@ EOF;
|
||||||
foreach ($packageMap as $item) {
|
foreach ($packageMap as $item) {
|
||||||
[$package, $installPath] = $item;
|
[$package, $installPath] = $item;
|
||||||
|
|
||||||
|
// packages that are not installed cannot autoload anything
|
||||||
|
if (null === $installPath) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (null !== $package->getTargetDir() && strlen($package->getTargetDir()) > 0) {
|
if (null !== $package->getTargetDir() && strlen($package->getTargetDir()) > 0) {
|
||||||
$installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
|
$installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
|
||||||
}
|
}
|
||||||
|
@ -716,7 +716,7 @@ EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<int, array{0: PackageInterface, 1: string}> $packageMap
|
* @param array<int, array{0: PackageInterface, 1: string|null}> $packageMap
|
||||||
* @param bool|'php-only' $checkPlatform
|
* @param bool|'php-only' $checkPlatform
|
||||||
* @param string[] $devPackageNames
|
* @param string[] $devPackageNames
|
||||||
* @return ?string
|
* @return ?string
|
||||||
|
@ -1149,7 +1149,7 @@ INITIALIZER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<int, array{0: PackageInterface, 1: string}> $packageMap
|
* @param array<int, array{0: PackageInterface, 1: string|null}> $packageMap
|
||||||
* @param string $type one of: 'psr-0'|'psr-4'|'classmap'|'files'
|
* @param string $type one of: 'psr-0'|'psr-4'|'classmap'|'files'
|
||||||
* @return array<int, string>|array<string, array<string>>|array<string, string>
|
* @return array<int, string>|array<string, array<string>>|array<string, string>
|
||||||
*/
|
*/
|
||||||
|
@ -1160,6 +1160,11 @@ INITIALIZER;
|
||||||
foreach ($packageMap as $item) {
|
foreach ($packageMap as $item) {
|
||||||
[$package, $installPath] = $item;
|
[$package, $installPath] = $item;
|
||||||
|
|
||||||
|
// packages that are not installed cannot autoload anything
|
||||||
|
if (null === $installPath) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$autoload = $package->getAutoload();
|
$autoload = $package->getAutoload();
|
||||||
if ($this->devMode && $package === $rootPackage) {
|
if ($this->devMode && $package === $rootPackage) {
|
||||||
$autoload = array_merge_recursive($autoload, $package->getDevAutoload());
|
$autoload = array_merge_recursive($autoload, $package->getDevAutoload());
|
||||||
|
@ -1249,10 +1254,8 @@ INITIALIZER;
|
||||||
/**
|
/**
|
||||||
* Filters out dev-dependencies
|
* Filters out dev-dependencies
|
||||||
*
|
*
|
||||||
* @param array<int, array{0: PackageInterface, 1: string}> $packageMap
|
* @param array<int, array{0: PackageInterface, 1: string|null}> $packageMap
|
||||||
* @return array<int, array{0: PackageInterface, 1: string}>
|
* @return array<int, array{0: PackageInterface, 1: string|null}>
|
||||||
*
|
|
||||||
* @phpstan-param array<int, array{0: PackageInterface, 1: string}> $packageMap
|
|
||||||
*/
|
*/
|
||||||
protected function filterPackageMap(array $packageMap, RootPackageInterface $rootPackage)
|
protected function filterPackageMap(array $packageMap, RootPackageInterface $rootPackage)
|
||||||
{
|
{
|
||||||
|
@ -1305,8 +1308,8 @@ INITIALIZER;
|
||||||
*
|
*
|
||||||
* Packages of equal weight are sorted alphabetically
|
* Packages of equal weight are sorted alphabetically
|
||||||
*
|
*
|
||||||
* @param array<int, array{0: PackageInterface, 1: string}> $packageMap
|
* @param array<int, array{0: PackageInterface, 1: string|null}> $packageMap
|
||||||
* @return array<int, array{0: PackageInterface, 1: string}>
|
* @return array<int, array{0: PackageInterface, 1: string|null}>
|
||||||
*/
|
*/
|
||||||
protected function sortPackageMap(array $packageMap)
|
protected function sortPackageMap(array $packageMap)
|
||||||
{
|
{
|
||||||
|
|
|
@ -131,7 +131,11 @@ class AutoloadGeneratorTest extends TestCase
|
||||||
->getMock();
|
->getMock();
|
||||||
$this->im->expects($this->any())
|
$this->im->expects($this->any())
|
||||||
->method('getInstallPath')
|
->method('getInstallPath')
|
||||||
->will($this->returnCallback(function ($package): string {
|
->will($this->returnCallback(function ($package): ?string {
|
||||||
|
if ($package->getType() === 'metapackage') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
$targetDir = $package->getTargetDir();
|
$targetDir = $package->getTargetDir();
|
||||||
|
|
||||||
return $this->vendorDir.'/'.$package->getName() . ($targetDir ? '/'.$targetDir : '');
|
return $this->vendorDir.'/'.$package->getName() . ($targetDir ? '/'.$targetDir : '');
|
||||||
|
@ -398,6 +402,40 @@ class AutoloadGeneratorTest extends TestCase
|
||||||
$this->assertFileExists($this->vendorDir.'/composer/autoload_classmap.php', "ClassMap file needs to be generated, even if empty.");
|
$this->assertFileExists($this->vendorDir.'/composer/autoload_classmap.php', "ClassMap file needs to be generated, even if empty.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testVendorsAutoloadingWithMetapackages(): void
|
||||||
|
{
|
||||||
|
$package = new RootPackage('root/a', '1.0', '1.0');
|
||||||
|
$package->setRequires([
|
||||||
|
'a/a' => new Link('a', 'a/a', new MatchAllConstraint()),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$packages = [];
|
||||||
|
$packages[] = $a = new Package('a/a', '1.0', '1.0');
|
||||||
|
$packages[] = $b = new Package('b/b', '1.0', '1.0');
|
||||||
|
$packages[] = $c = new AliasPackage($b, '1.2', '1.2');
|
||||||
|
$a->setAutoload(['psr-0' => ['A' => 'src/', 'A\\B' => 'lib/']]);
|
||||||
|
$b->setAutoload(['psr-0' => ['B\\Sub\\Name' => 'src/']]);
|
||||||
|
$a->setType('metapackage');
|
||||||
|
$a->setRequires([
|
||||||
|
'b/b' => new Link('a/a', 'b/b', new MatchAllConstraint()),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->repository->expects($this->once())
|
||||||
|
->method('getCanonicalPackages')
|
||||||
|
->will($this->returnValue($packages));
|
||||||
|
|
||||||
|
$this->fs->ensureDirectoryExists($this->vendorDir.'/composer');
|
||||||
|
$this->fs->ensureDirectoryExists($this->vendorDir.'/b/b/src');
|
||||||
|
// creating a/a files to make sure they would be found by autoloader even tho they are technically not
|
||||||
|
// needed as the package is a metapackage, but if it fails to be excluded it would find these
|
||||||
|
$this->fs->ensureDirectoryExists($this->vendorDir.'/a/a/src');
|
||||||
|
$this->fs->ensureDirectoryExists($this->vendorDir.'/a/a/lib');
|
||||||
|
|
||||||
|
$this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, '_5');
|
||||||
|
$this->assertAutoloadFiles('vendors_meta', $this->vendorDir.'/composer');
|
||||||
|
$this->assertFileExists($this->vendorDir.'/composer/autoload_classmap.php', "ClassMap file needs to be generated, even if empty.");
|
||||||
|
}
|
||||||
|
|
||||||
public function testNonDevAutoloadExclusionWithRecursion(): void
|
public function testNonDevAutoloadExclusionWithRecursion(): void
|
||||||
{
|
{
|
||||||
$package = new RootPackage('root/a', '1.0', '1.0');
|
$package = new RootPackage('root/a', '1.0', '1.0');
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_namespaces.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'B\\Sub\\Name' => array($vendorDir . '/b/b/src'),
|
||||||
|
);
|
Loading…
Reference in New Issue