From e2f5afd4cdde2ba180dca8b9c986f2e411b7be77 Mon Sep 17 00:00:00 2001 From: wgevaert <56224691+wgevaert@users.noreply.github.com> Date: Wed, 13 Sep 2023 14:11:00 +0200 Subject: [PATCH] Add warning when duplicate "files" autoload rules are detected (#11109) Co-authored-by: Wout Gevaert Co-authored-by: Jordi Boggiano --- src/Composer/Autoload/AutoloadGenerator.php | 20 +++++++++-- .../Test/Autoload/AutoloadGeneratorTest.php | 36 ++++++++++++++++++- .../Fixtures/autoload_files_duplicates.php | 13 +++++++ 3 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 tests/Composer/Test/Autoload/Fixtures/autoload_files_duplicates.php diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index be776f1d0..3e2faa3eb 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -679,10 +679,26 @@ EOF; */ protected function getIncludeFilesFile(array $files, Filesystem $filesystem, string $basePath, string $vendorPath, string $vendorPathCode, string $appBaseDirCode) { + // Get the path to each file, and make sure these paths are unique. + $files = array_map( + function (string $functionFile) use ($filesystem, $basePath, $vendorPath): string { + return $this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile); + }, + $files + ); + $uniqueFiles = array_unique($files); + if (count($uniqueFiles) < count($files)) { + $this->io->writeError('The following "files" autoload rules are included multiple times, this may cause issues and should be resolved:'); + foreach (array_unique(array_diff_assoc($files, $uniqueFiles)) as $duplicateFile) { + $this->io->writeError(' - '.$duplicateFile.''); + } + } + unset($uniqueFiles); + $filesCode = ''; + foreach ($files as $fileIdentifier => $functionFile) { - $filesCode .= ' ' . var_export($fileIdentifier, true) . ' => ' - . $this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile) . ",\n"; + $filesCode .= ' ' . var_export($fileIdentifier, true) . ' => ' . $functionFile . ",\n"; } if (!$filesCode) { diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index fda3b06ed..cc8c2f0ac 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -14,6 +14,8 @@ namespace Composer\Test\Autoload; use Composer\Autoload\AutoloadGenerator; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory; +use Composer\IO\BufferIO; +use Composer\IO\IOInterface; use Composer\Package\CompletePackage; use Composer\Package\Link; use Composer\Package\Version\VersionParser; @@ -74,6 +76,11 @@ class AutoloadGeneratorTest extends TestCase */ private $fs; + /** + * @var BufferIO + */ + private $io; + /** * @var EventDispatcher&MockObject */ @@ -109,6 +116,8 @@ class AutoloadGeneratorTest extends TestCase }, ]; + $this->io = new BufferIO(); + $this->config->expects($this->atLeastOnce()) ->method('get') ->will($this->returnCallback(function ($arg) { @@ -149,7 +158,7 @@ class AutoloadGeneratorTest extends TestCase ->disableOriginalConstructor() ->getMock(); - $this->generator = new AutoloadGenerator($this->eventDispatcher); + $this->generator = new AutoloadGenerator($this->eventDispatcher, $this->io); } protected function tearDown(): void @@ -373,6 +382,31 @@ class AutoloadGeneratorTest extends TestCase $this->assertAutoloadFiles('classmap6', $this->vendorDir.'/composer', 'classmap'); } + public function testDuplicateFilesWarning(): void + { + $package = new RootPackage('root/a', '1.0', '1.0'); + $package->setAutoload([ + 'files' => ['foo.php', 'bar.php', './foo.php', '././foo.php'], + ]); + + $this->repository->expects($this->once()) + ->method('getCanonicalPackages') + ->will($this->returnValue([])); + + $this->fs->ensureDirectoryExists($this->vendorDir.'/a'); + $this->fs->ensureDirectoryExists($this->workingDir.'/src'); + $this->fs->ensureDirectoryExists($this->workingDir.'/lib'); + + file_put_contents($this->workingDir.'/foo.php', 'workingDir.'/bar.php', 'generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, 'FilesWarning'); + self::assertFileContentEquals(__DIR__.'/Fixtures/autoload_files_duplicates.php', $this->vendorDir.'/composer/autoload_files.php'); + $expected = 'The following "files" autoload rules are included multiple times, this may cause issues and should be resolved:'.PHP_EOL. + ' - $baseDir . \'/foo.php\''.PHP_EOL; + self::assertEquals($expected, $this->io->getOutput());; + } + public function testVendorsAutoloading(): void { $package = new RootPackage('root/a', '1.0', '1.0'); diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_files_duplicates.php b/tests/Composer/Test/Autoload/Fixtures/autoload_files_duplicates.php new file mode 100644 index 000000000..d1c5e0841 --- /dev/null +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_files_duplicates.php @@ -0,0 +1,13 @@ + $baseDir . '/foo.php', + '99b24fc198db06c1d2d8118a8a5475eb' => $baseDir . '/bar.php', + '6bad5af0771cca3d076e69b25d0791bb' => $baseDir . '/foo.php', + '51841489e2c601aedd3623cb72708483' => $baseDir . '/foo.php', +);