Browse Source

Make sure circular dependencies do not break the autoload dumper, refs #7316, refs #7348

Jordi Boggiano 6 years ago
parent
commit
eedbd218f5

+ 9 - 6
src/Composer/Autoload/AutoloadGenerator.php

@@ -902,12 +902,13 @@ INITIALIZER;
 
     /**
      * Filters out dev-dependencies when not in dev-mode
-     * 
+     *
      * @param array $packageMap
      * @param PackageInterface $mainPackage
      * @return array
      */
-    protected function filterPackageMap(array $packageMap, PackageInterface $mainPackage) {
+    protected function filterPackageMap(array $packageMap, PackageInterface $mainPackage)
+    {
         if ($this->devMode === true) {
             return $packageMap;
         }
@@ -924,14 +925,16 @@ INITIALIZER;
         $add = function (PackageInterface $package) use (&$add, $mainPackage, $packages, &$include) {
             foreach ($package->getRequires() as $link) {
                 $target = $link->getTarget();
-                $include[$target] = true;
-                if (isset($packages[$target])) {
-                    $add($packages[$target]);
+                if (!isset($include[$target])) {
+                    $include[$target] = true;
+                    if (isset($packages[$target])) {
+                        $add($packages[$target]);
+                    }
                 }
             }
         };
         $add($mainPackage);
-    
+
         return array_filter(
             $packageMap,
             function ($item) use ($include) {

+ 33 - 0
tests/Composer/Test/Autoload/AutoloadGeneratorTest.php

@@ -386,6 +386,39 @@ class AutoloadGeneratorTest extends TestCase
         $this->assertFileExists($this->vendorDir.'/composer/autoload_classmap.php', "ClassMap file needs to be generated, even if empty.");
     }
 
+    public function testNonDevAutoloadExclusionWithRecursion()
+    {
+        $package = new Package('a', '1.0', '1.0');
+        $package->setRequires(array(
+            new Link('a', 'a/a'),
+        ));
+
+        $packages = array();
+        $packages[] = $a = new Package('a/a', '1.0', '1.0');
+        $packages[] = $b = new Package('b/b', '1.0', '1.0');
+        $a->setAutoload(array('psr-0' => array('A' => 'src/', 'A\\B' => 'lib/')));
+        $a->setRequires(array(
+            new Link('a/a', 'b/b'),
+        ));
+        $b->setAutoload(array('psr-0' => array('B\\Sub\\Name' => 'src/')));
+        $b->setRequires(array(
+            new Link('b/b', 'a/a'),
+        ));
+
+        $this->repository->expects($this->once())
+            ->method('getCanonicalPackages')
+            ->will($this->returnValue($packages));
+
+        $this->fs->ensureDirectoryExists($this->vendorDir.'/composer');
+        $this->fs->ensureDirectoryExists($this->vendorDir.'/a/a/src');
+        $this->fs->ensureDirectoryExists($this->vendorDir.'/a/a/lib');
+        $this->fs->ensureDirectoryExists($this->vendorDir.'/b/b/src');
+
+        $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, '_5');
+        $this->assertAutoloadFiles('vendors', $this->vendorDir.'/composer');
+        $this->assertFileExists($this->vendorDir.'/composer/autoload_classmap.php', "ClassMap file needs to be generated, even if empty.");
+    }
+
     public function testPSRToClassMapIgnoresNonExistingDir()
     {
         $package = new Package('a', '1.0', '1.0');