Browse Source

Allow loading of multiple composer autoloaders concurrently, fixes #1248

Jordi Boggiano 12 years ago
parent
commit
487e66d0a9

+ 17 - 5
src/Composer/Autoload/AutoloadGenerator.php

@@ -158,13 +158,17 @@ EOF;
             $filesCode .= '        require '.$this->getPathCode($filesystem, $relVendorPath, $vendorPath, $functionFile).";\n";
         }
 
+        if (!$suffix) {
+            $suffix = md5(uniqid('', true));
+        }
+
         file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile);
         file_put_contents($targetDir.'/autoload_classmap.php', $classmapFile);
         if ($includePathFile = $this->getIncludePathsFile($packageMap, $filesystem, $relVendorPath, $vendorPath, $vendorPathCode, $appBaseDirCode)) {
             file_put_contents($targetDir.'/include_paths.php', $includePathFile);
         }
         file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
-        file_put_contents($targetDir.'/autoload_real'.$suffix.'.php', $this->getAutoloadRealFile(true, true, (bool) $includePathFile, $targetDirLoader, $filesCode, $vendorPathCode, $appBaseDirCode, $suffix));
+        file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, true, (bool) $includePathFile, $targetDirLoader, $filesCode, $vendorPathCode, $appBaseDirCode, $suffix));
         copy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php');
     }
 
@@ -313,7 +317,7 @@ EOF;
 
 // autoload.php generated by Composer
 
-require_once $vendorPathToTargetDirCode . '/autoload_real$suffix.php';
+require_once $vendorPathToTargetDirCode . '/autoload_real.php';
 
 return ComposerAutoloaderInit$suffix::getLoader();
 
@@ -336,21 +340,29 @@ AUTOLOAD;
         $file = <<<HEADER
 <?php
 
-// autoload_real$suffix.php generated by Composer
-
-require __DIR__ . '/ClassLoader.php';
+// autoload_real.php generated by Composer
 
 class ComposerAutoloaderInit$suffix
 {
     private static \$loader;
 
+    public static function loadClassLoader(\$class)
+    {
+        if ('Composer\\Autoload\\ClassLoader' === \$class) {
+            require __DIR__ . '/ClassLoader.php';
+        }
+    }
+
     public static function getLoader()
     {
         if (null !== static::\$loader) {
             return static::\$loader;
         }
 
+        spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'));
         static::\$loader = \$loader = new \\Composer\\Autoload\\ClassLoader();
+        spl_autoload_unregister(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'));
+
         \$vendorDir = $vendorPathCode;
         \$baseDir = $appBaseDirCode;
 

+ 8 - 0
tests/Composer/Test/AllFunctionalTest.php

@@ -12,6 +12,8 @@ use Symfony\Component\Finder\Finder;
 class AllFunctionalTest extends \PHPUnit_Framework_TestCase
 {
     protected $oldcwd;
+    protected $testDir;
+
     public function setUp()
     {
         $this->oldcwd = getcwd();
@@ -21,6 +23,11 @@ class AllFunctionalTest extends \PHPUnit_Framework_TestCase
     public function tearDown()
     {
         chdir($this->oldcwd);
+        if ($this->testDir) {
+            $fs = new Filesystem;
+            $fs->removeDirectory($this->testDir);
+            $this->testDir = null;
+        }
     }
 
     /**
@@ -74,6 +81,7 @@ class AllFunctionalTest extends \PHPUnit_Framework_TestCase
         $section = null;
 
         $testDir = sys_get_temp_dir().'/composer_functional_test'.uniqid(mt_rand(), true);
+        $this->testDir = $testDir;
         $varRegex = '#%([a-zA-Z_-]+)%#';
         $variableReplacer = function($match) use (&$data, $testDir) {
             list(, $var) = $match;

+ 39 - 29
tests/Composer/Test/Autoload/AutoloadGeneratorTest.php

@@ -36,7 +36,7 @@ class AutoloadGeneratorTest extends TestCase
 
         $this->workingDir = realpath(sys_get_temp_dir()).DIRECTORY_SEPARATOR.'cmptest';
         $this->fs->ensureDirectoryExists($this->workingDir);
-        $this->vendorDir = $this->workingDir.DIRECTORY_SEPARATOR.'composer-test-autoload';
+        $this->vendorDir = $this->workingDir.DIRECTORY_SEPARATOR.'composer-test-autoload-'.md5(uniqid('', true));
         $this->ensureDirectoryExistsAndClear($this->vendorDir);
 
         $this->config = $this->getMock('Composer\Config');
@@ -162,7 +162,7 @@ class AutoloadGeneratorTest extends TestCase
 
         $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, 'TargetDir');
         $this->assertFileEquals(__DIR__.'/Fixtures/autoload_target_dir.php', $this->vendorDir.'/autoload.php');
-        $this->assertFileEquals(__DIR__.'/Fixtures/autoload_real_target_dir.php', $this->vendorDir.'/composer/autoload_realTargetDir.php');
+        $this->assertFileEquals(__DIR__.'/Fixtures/autoload_real_target_dir.php', $this->vendorDir.'/composer/autoload_real.php');
     }
 
     public function testMainPackageAutoloadingWithTargetDirAndNoPsr()
@@ -237,12 +237,12 @@ class AutoloadGeneratorTest extends TestCase
         $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, '_6');
         $this->assertTrue(file_exists($this->vendorDir.'/composer/autoload_classmap.php'), "ClassMap file needs to be generated.");
         $this->assertEquals(
-            array(
-                'ClassMapBar' => $this->workingDir.'/composer-test-autoload/b/b/src/b.php',
-                'ClassMapBaz' => $this->workingDir.'/composer-test-autoload/b/b/lib/c.php',
-                'ClassMapFoo' => $this->workingDir.'/composer-test-autoload/a/a/src/a.php',
-            ),
-            include ($this->vendorDir.'/composer/autoload_classmap.php')
+            $this->normalizePaths(array(
+                'ClassMapBar' => $this->vendorDir.'/b/b/src/b.php',
+                'ClassMapBaz' => $this->vendorDir.'/b/b/lib/c.php',
+                'ClassMapFoo' => $this->vendorDir.'/a/a/src/a.php',
+            )),
+            $this->normalizePaths(include $this->vendorDir.'/composer/autoload_classmap.php')
         );
         $this->assertAutoloadFiles('classmap4', $this->vendorDir.'/composer', 'classmap');
     }
@@ -274,12 +274,12 @@ class AutoloadGeneratorTest extends TestCase
         $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, '_7');
         $this->assertTrue(file_exists($this->vendorDir.'/composer/autoload_classmap.php'), "ClassMap file needs to be generated.");
         $this->assertEquals(
-            array(
-                'ClassMapBar' => $this->workingDir.'/composer-test-autoload/b/b/test.php',
-                'ClassMapBaz' => $this->workingDir.'/composer-test-autoload/c/c/foo/test.php',
-                'ClassMapFoo' => $this->workingDir.'/composer-test-autoload/a/a/src/a.php',
-            ),
-            include ($this->vendorDir.'/composer/autoload_classmap.php')
+            $this->normalizePaths(array(
+                'ClassMapBar' => $this->vendorDir.'/b/b/test.php',
+                'ClassMapBaz' => $this->vendorDir.'/c/c/foo/test.php',
+                'ClassMapFoo' => $this->vendorDir.'/a/a/src/a.php',
+            )),
+            $this->normalizePaths(include $this->vendorDir.'/composer/autoload_classmap.php')
         );
         $this->assertAutoloadFiles('classmap5', $this->vendorDir.'/composer', 'classmap');
     }
@@ -307,10 +307,7 @@ class AutoloadGeneratorTest extends TestCase
 
         $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, 'FilesAutoload');
         $this->assertFileEquals(__DIR__.'/Fixtures/autoload_functions.php', $this->vendorDir.'/autoload.php');
-        $this->assertFileEquals(__DIR__.'/Fixtures/autoload_real_functions.php', $this->vendorDir.'/composer/autoload_realFilesAutoload.php');
-
-        // suppress the class loader to avoid fatals if the class is redefined
-        file_put_contents($this->vendorDir.'/composer/ClassLoader.php', '');
+        $this->assertFileEquals(__DIR__.'/Fixtures/autoload_real_functions.php', $this->vendorDir.'/composer/autoload_real.php');
 
         include $this->vendorDir . '/autoload.php';
         $this->assertTrue(function_exists('testFilesAutoloadGeneration1'));
@@ -362,12 +359,9 @@ class AutoloadGeneratorTest extends TestCase
 
         $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, 'FilesAutoloadOrder');
         $this->assertFileEquals(__DIR__ . '/Fixtures/autoload_functions_by_dependency.php', $this->vendorDir . '/autoload.php');
-        $this->assertFileEquals(__DIR__ . '/Fixtures/autoload_real_files_by_dependency.php', $this->vendorDir . '/composer/autoload_realFilesAutoloadOrder.php');
+        $this->assertFileEquals(__DIR__ . '/Fixtures/autoload_real_files_by_dependency.php', $this->vendorDir . '/composer/autoload_real.php');
 
-        // suppress the class loader to avoid fatals if the class is redefined
-        file_put_contents($this->vendorDir . '/composer/ClassLoader.php', '');
-
-        include $this->vendorDir . '/autoload.php';
+        require $this->vendorDir . '/autoload.php';
 
         $this->assertTrue(function_exists('testFilesAutoloadOrderByDependency1'));
         $this->assertTrue(function_exists('testFilesAutoloadOrderByDependency2'));
@@ -475,7 +469,7 @@ EOF;
                 $this->vendorDir."/b/b/library",
                 $this->vendorDir."/c/library",
             ),
-            require($this->vendorDir."/composer/include_paths.php")
+            require $this->vendorDir."/composer/include_paths.php"
         );
     }
 
@@ -499,10 +493,7 @@ EOF;
 
         $oldIncludePath = get_include_path();
 
-        // suppress the class loader to avoid fatals if the class is redefined
-        file_put_contents($this->vendorDir.'/composer/ClassLoader.php', '');
-
-        require($this->vendorDir."/autoload.php");
+        require $this->vendorDir."/autoload.php";
 
         $this->assertEquals(
             $this->vendorDir."/a/a/lib".PATH_SEPARATOR.$oldIncludePath,
@@ -542,6 +533,25 @@ EOF;
 
     private function assertAutoloadFiles($name, $dir, $type = 'namespaces')
     {
-        $this->assertFileEquals(__DIR__.'/Fixtures/autoload_'.$name.'.php', $dir.'/autoload_'.$type.'.php');
+        $a = __DIR__.'/Fixtures/autoload_'.$name.'.php';
+        $b = $dir.'/autoload_'.$type.'.php';
+        $this->assertEquals(
+            str_replace('%vendorDir%', basename($this->vendorDir), file_get_contents($a)),
+            file_get_contents($b),
+            $a .' does not equal '. $b
+        );
+    }
+
+    private function normalizePaths($paths)
+    {
+        if (!is_array($paths)) {
+            return strtr($paths, '\\', '/');
+        }
+
+        foreach ($paths as $key => $path) {
+            $paths[$key] = strtr($path, '\\', '/');
+        }
+
+        return $paths;
     }
 }

+ 3 - 3
tests/Composer/Test/Autoload/Fixtures/autoload_classmap4.php

@@ -6,7 +6,7 @@ $vendorDir = dirname(__DIR__);
 $baseDir = dirname($vendorDir);
 
 return array(
-    'ClassMapBar' => $baseDir . '/composer-test-autoload/b/b/src/b.php',
-    'ClassMapBaz' => $baseDir . '/composer-test-autoload/b/b/lib/c.php',
-    'ClassMapFoo' => $baseDir . '/composer-test-autoload/a/a/src/a.php',
+    'ClassMapBar' => $baseDir . '/%vendorDir%/b/b/src/b.php',
+    'ClassMapBaz' => $baseDir . '/%vendorDir%/b/b/lib/c.php',
+    'ClassMapFoo' => $baseDir . '/%vendorDir%/a/a/src/a.php',
 );

+ 3 - 3
tests/Composer/Test/Autoload/Fixtures/autoload_classmap5.php

@@ -6,7 +6,7 @@ $vendorDir = dirname(__DIR__);
 $baseDir = dirname($vendorDir);
 
 return array(
-    'ClassMapBar' => $baseDir . '/composer-test-autoload/b/b/test.php',
-    'ClassMapBaz' => $baseDir . '/composer-test-autoload/c/c/foo/test.php',
-    'ClassMapFoo' => $baseDir . '/composer-test-autoload/a/a/src/a.php',
+    'ClassMapBar' => $baseDir . '/%vendorDir%/b/b/test.php',
+    'ClassMapBaz' => $baseDir . '/%vendorDir%/c/c/foo/test.php',
+    'ClassMapFoo' => $baseDir . '/%vendorDir%/a/a/src/a.php',
 );

+ 1 - 1
tests/Composer/Test/Autoload/Fixtures/autoload_functions.php

@@ -2,6 +2,6 @@
 
 // autoload.php generated by Composer
 
-require_once __DIR__ . '/composer' . '/autoload_realFilesAutoload.php';
+require_once __DIR__ . '/composer' . '/autoload_real.php';
 
 return ComposerAutoloaderInitFilesAutoload::getLoader();

+ 1 - 1
tests/Composer/Test/Autoload/Fixtures/autoload_functions_by_dependency.php

@@ -2,6 +2,6 @@
 
 // autoload.php generated by Composer
 
-require_once __DIR__ . '/composer' . '/autoload_realFilesAutoloadOrder.php';
+require_once __DIR__ . '/composer' . '/autoload_real.php';
 
 return ComposerAutoloaderInitFilesAutoloadOrder::getLoader();

+ 11 - 3
tests/Composer/Test/Autoload/Fixtures/autoload_real_files_by_dependency.php

@@ -1,20 +1,28 @@
 <?php
 
-// autoload_realFilesAutoloadOrder.php generated by Composer
-
-require __DIR__ . '/ClassLoader.php';
+// autoload_real.php generated by Composer
 
 class ComposerAutoloaderInitFilesAutoloadOrder
 {
     private static $loader;
 
+    public static function loadClassLoader($class)
+    {
+        if ('Composer\Autoload\ClassLoader' === $class) {
+            require __DIR__ . '/ClassLoader.php';
+        }
+    }
+
     public static function getLoader()
     {
         if (null !== static::$loader) {
             return static::$loader;
         }
 
+        spl_autoload_register(array('ComposerAutoloaderInitFilesAutoloadOrder', 'loadClassLoader'));
         static::$loader = $loader = new \Composer\Autoload\ClassLoader();
+        spl_autoload_unregister(array('ComposerAutoloaderInitFilesAutoloadOrder', 'loadClassLoader'));
+
         $vendorDir = dirname(__DIR__);
         $baseDir = dirname($vendorDir);
 

+ 11 - 3
tests/Composer/Test/Autoload/Fixtures/autoload_real_functions.php

@@ -1,20 +1,28 @@
 <?php
 
-// autoload_realFilesAutoload.php generated by Composer
-
-require __DIR__ . '/ClassLoader.php';
+// autoload_real.php generated by Composer
 
 class ComposerAutoloaderInitFilesAutoload
 {
     private static $loader;
 
+    public static function loadClassLoader($class)
+    {
+        if ('Composer\Autoload\ClassLoader' === $class) {
+            require __DIR__ . '/ClassLoader.php';
+        }
+    }
+
     public static function getLoader()
     {
         if (null !== static::$loader) {
             return static::$loader;
         }
 
+        spl_autoload_register(array('ComposerAutoloaderInitFilesAutoload', 'loadClassLoader'));
         static::$loader = $loader = new \Composer\Autoload\ClassLoader();
+        spl_autoload_unregister(array('ComposerAutoloaderInitFilesAutoload', 'loadClassLoader'));
+
         $vendorDir = dirname(__DIR__);
         $baseDir = dirname($vendorDir);
 

+ 11 - 3
tests/Composer/Test/Autoload/Fixtures/autoload_real_target_dir.php

@@ -1,20 +1,28 @@
 <?php
 
-// autoload_realTargetDir.php generated by Composer
-
-require __DIR__ . '/ClassLoader.php';
+// autoload_real.php generated by Composer
 
 class ComposerAutoloaderInitTargetDir
 {
     private static $loader;
 
+    public static function loadClassLoader($class)
+    {
+        if ('Composer\Autoload\ClassLoader' === $class) {
+            require __DIR__ . '/ClassLoader.php';
+        }
+    }
+
     public static function getLoader()
     {
         if (null !== static::$loader) {
             return static::$loader;
         }
 
+        spl_autoload_register(array('ComposerAutoloaderInitTargetDir', 'loadClassLoader'));
         static::$loader = $loader = new \Composer\Autoload\ClassLoader();
+        spl_autoload_unregister(array('ComposerAutoloaderInitTargetDir', 'loadClassLoader'));
+
         $vendorDir = dirname(__DIR__);
         $baseDir = dirname($vendorDir);
 

+ 1 - 1
tests/Composer/Test/Autoload/Fixtures/autoload_target_dir.php

@@ -2,6 +2,6 @@
 
 // autoload.php generated by Composer
 
-require_once __DIR__ . '/composer' . '/autoload_realTargetDir.php';
+require_once __DIR__ . '/composer' . '/autoload_real.php';
 
 return ComposerAutoloaderInitTargetDir::getLoader();

+ 6 - 0
tests/Composer/Test/Repository/Vcs/GitHubDriverTest.php

@@ -31,6 +31,12 @@ class GitHubDriverTest extends \PHPUnit_Framework_TestCase
         ));
     }
 
+    public function tearDown()
+    {
+        $fs = new Filesystem;
+        $fs->removeDirectory(sys_get_temp_dir() . '/composer-test');
+    }
+
     public function testPrivateRepository()
     {
         $repoUrl = 'http://github.com/composer/packagist';