Procházet zdrojové kódy

Merge remote-tracking branch 'hason/classloader'

Jordi Boggiano před 13 roky
rodič
revize
5f30206c69

+ 3 - 7
src/Composer/Autoload/AutoloadGenerator.php

@@ -58,7 +58,7 @@ EOF;
 
         $filesystem = new Filesystem();
         $vendorPath = strtr(realpath($installationManager->getVendorPath()), '\\', '/');
-        $relVendorPath = $filesystem->findShortestPath(getcwd(), $vendorPath);
+        $relVendorPath = $filesystem->findShortestPath(getcwd(), $vendorPath, true);
         $vendorDirCode = $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true);
 
         $appBaseDir = $filesystem->findShortestPathCode($vendorPath, getcwd(), true);
@@ -85,11 +85,7 @@ EOF;
                 $path = strtr($path, '\\', '/');
                 $baseDir = '';
                 if (!$filesystem->isAbsolutePath($path)) {
-                    // vendor dir == working dir
-                    if (preg_match('{^(\./?)?$}', $relVendorPath)) {
-                        $path = '/'.$path;
-                        $baseDir = '$vendorDir . ';
-                    } elseif (strpos($path, $relVendorPath) === 0) {
+                    if (strpos($path, $relVendorPath) === 0) {
                         // path starts with vendor dir
                         $path = substr($path, strlen($relVendorPath));
                         $baseDir = '$vendorDir . ';
@@ -129,7 +125,7 @@ EOF;
         $autoloads['classmap'] = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($autoloads['classmap']));
         foreach ($autoloads['classmap'] as $dir) {
             foreach (ClassMapGenerator::createMap($dir) as $class => $path) {
-                $path = '/'.$filesystem->findShortestPath(getcwd(), $path);
+                $path = '/'.$filesystem->findShortestPath(getcwd(), $path, true);
                 $classmapFile .= '    '.var_export($class, true).' => $baseDir . '.var_export($path, true).",\n";
             }
         }

+ 7 - 2
src/Composer/Util/Filesystem.php

@@ -58,9 +58,10 @@ class Filesystem
      *
      * @param string $from
      * @param string $to
+     * @param Boolean $directories if true, the source/target are considered to be directories
      * @return string
      */
-    public function findShortestPath($from, $to)
+    public function findShortestPath($from, $to, $directories = false)
     {
         if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
             throw new \InvalidArgumentException('from and to must be absolute paths');
@@ -69,6 +70,10 @@ class Filesystem
         $from = lcfirst(rtrim(strtr($from, '\\', '/'), '/'));
         $to = lcfirst(rtrim(strtr($to, '\\', '/'), '/'));
 
+        if ($directories) {
+            $from .= '/dummy_file';
+        }
+
         if (dirname($from) === dirname($to)) {
             return './'.basename($to);
         }
@@ -143,4 +148,4 @@ class Filesystem
     {
         return new ProcessExecutor;
     }
-}
+}

+ 40 - 6
tests/Composer/Test/Autoload/AutoloadGeneratorTest.php

@@ -66,21 +66,34 @@ class AutoloadGeneratorTest extends TestCase
         } elseif (is_dir($this->vendorDir)) {
             $this->fs->removeDirectory($this->vendorDir);
         }
+        if (is_dir($this->workingDir.'/.composersrc')) {
+            $this->fs->removeDirectory($this->workingDir.'/.composersrc');
+        }
+
         chdir($this->dir);
     }
 
     public function testMainPackageAutoloading()
     {
         $package = new MemoryPackage('a', '1.0', '1.0');
-        $package->setAutoload(array('psr-0' => array('Main' => 'src/', 'Lala' => 'src/')));
+        $package->setAutoload(array(
+            'psr-0' => array('Main' => 'src/', 'Lala' => 'src/'),
+            'classmap' => array('.composersrc/'),
+        ));
 
         $this->repository->expects($this->once())
             ->method('getPackages')
             ->will($this->returnValue(array()));
 
-        mkdir($this->vendorDir.'/.composer');
+        if (!is_dir($this->vendorDir.'/.composer')) {
+            mkdir($this->vendorDir.'/.composer');
+        }
+
+        $this->createClassFile($this->workingDir);
+
         $this->generator->dump($this->repository, $package, $this->im, $this->vendorDir.'/.composer');
         $this->assertAutoloadFiles('main', $this->vendorDir.'/.composer');
+        $this->assertAutoloadFiles('classmap', $this->vendorDir.'/.composer', 'classmap');
     }
 
     public function testVendorDirSameAsWorkingDir()
@@ -88,7 +101,10 @@ class AutoloadGeneratorTest extends TestCase
         $this->vendorDir = $this->workingDir;
 
         $package = new MemoryPackage('a', '1.0', '1.0');
-        $package->setAutoload(array('psr-0' => array('Main' => 'src/', 'Lala' => 'src/')));
+        $package->setAutoload(array(
+            'psr-0' => array('Main' => 'src/', 'Lala' => 'src/'),
+            'classmap' => array('.composersrc/'),
+        ));
 
         $this->repository->expects($this->once())
             ->method('getPackages')
@@ -98,14 +114,20 @@ class AutoloadGeneratorTest extends TestCase
             mkdir($this->vendorDir.'/.composer', 0777, true);
         }
 
+        $this->createClassFile($this->vendorDir);
+
         $this->generator->dump($this->repository, $package, $this->im, $this->vendorDir.'/.composer');
         $this->assertAutoloadFiles('main3', $this->vendorDir.'/.composer');
+        $this->assertAutoloadFiles('classmap3', $this->vendorDir.'/.composer', 'classmap');
     }
 
     public function testMainPackageAutoloadingAlternativeVendorDir()
     {
         $package = new MemoryPackage('a', '1.0', '1.0');
-        $package->setAutoload(array('psr-0' => array('Main' => 'src/', 'Lala' => 'src/')));
+        $package->setAutoload(array(
+            'psr-0' => array('Main' => 'src/', 'Lala' => 'src/'),
+            'classmap' => array('.composersrc/'),
+        ));
 
         $this->repository->expects($this->once())
             ->method('getPackages')
@@ -113,8 +135,10 @@ class AutoloadGeneratorTest extends TestCase
 
         $this->vendorDir .= '/subdir';
         mkdir($this->vendorDir.'/.composer', 0777, true);
+        $this->createClassFile($this->workingDir);
         $this->generator->dump($this->repository, $package, $this->im, $this->vendorDir.'/.composer');
         $this->assertAutoloadFiles('main2', $this->vendorDir.'/.composer');
+        $this->assertAutoloadFiles('classmap2', $this->vendorDir.'/.composer', 'classmap');
     }
 
     public function testVendorsAutoloading()
@@ -169,6 +193,7 @@ class AutoloadGeneratorTest extends TestCase
             ),
             include ($this->vendorDir.'/.composer/autoload_classmap.php')
         );
+        $this->assertAutoloadFiles('classmap4', $this->vendorDir.'/.composer', 'classmap');
     }
 
     public function testOverrideVendorsAutoloading()
@@ -191,8 +216,17 @@ class AutoloadGeneratorTest extends TestCase
         $this->assertAutoloadFiles('override_vendors', $this->vendorDir.'/.composer');
     }
 
-    private function assertAutoloadFiles($name, $dir)
+    private function createClassFile($basedir)
+    {
+        if (!is_dir($basedir.'/.composersrc')) {
+            mkdir($basedir.'/.composersrc', 0777, true);
+        }
+
+        file_put_contents($basedir.'/.composersrc/foo.php', '<?php class ClassMapFoo {}');
+    }
+
+    private function assertAutoloadFiles($name, $dir, $type = 'namespaces')
     {
-        $this->assertFileEquals(__DIR__.'/Fixtures/autoload_'.$name.'.php', $dir.'/autoload_namespaces.php');
+        $this->assertFileEquals(__DIR__.'/Fixtures/autoload_'.$name.'.php', $dir.'/autoload_'.$type.'.php');
     }
 }

+ 15 - 1
tests/Composer/Test/Autoload/ClassMapGeneratorTest.php

@@ -25,7 +25,7 @@ class ClassMapGeneratorTest extends \PHPUnit_Framework_TestCase
 
     public function getTestCreateMapTests()
     {
-        return array(
+        $data = array(
             array(__DIR__.'/Fixtures/Namespaced', array(
                 'Namespaced\\Bar' => realpath(__DIR__).'/Fixtures/Namespaced/Bar.php',
                 'Namespaced\\Foo' => realpath(__DIR__).'/Fixtures/Namespaced/Foo.php',
@@ -44,6 +44,7 @@ class ClassMapGeneratorTest extends \PHPUnit_Framework_TestCase
             array(__DIR__.'/Fixtures/classmap', array(
                 'Foo\\Bar\\A'             => realpath(__DIR__).'/Fixtures/classmap/sameNsMultipleClasses.php',
                 'Foo\\Bar\\B'             => realpath(__DIR__).'/Fixtures/classmap/sameNsMultipleClasses.php',
+                'A'                       => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
                 'Alpha\\A'                => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
                 'Alpha\\B'                => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
                 'Beta\\A'                 => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
@@ -53,6 +54,19 @@ class ClassMapGeneratorTest extends \PHPUnit_Framework_TestCase
                 'ClassMap\\SomeClass'     => realpath(__DIR__).'/Fixtures/classmap/SomeClass.php',
             )),
         );
+
+        if (version_compare(PHP_VERSION, '5.4', '>=')) {
+            $data[] = array(__DIR__.'/Fixtures/php5.4', array(
+                'TFoo' => __DIR__.'/Fixtures/php5.4/traits.php',
+                'CFoo' => __DIR__.'/Fixtures/php5.4/traits.php',
+                'Foo\\TBar' => __DIR__.'/Fixtures/php5.4/traits.php',
+                'Foo\\IBar' => __DIR__.'/Fixtures/php5.4/traits.php',
+                'Foo\\TFooBar' => __DIR__.'/Fixtures/php5.4/traits.php',
+                'Foo\\CBar' => __DIR__.'/Fixtures/php5.4/traits.php',
+            ));
+        }
+
+        return $data;
     }
 
     public function testCreateMapFinderSupport()

+ 10 - 0
tests/Composer/Test/Autoload/Fixtures/autoload_classmap.php

@@ -0,0 +1,10 @@
+<?php
+
+// autoload_classmap.php generated by Composer
+
+$vendorDir = dirname(__DIR__);
+$baseDir = dirname($vendorDir);
+
+return array(
+    'ClassMapFoo' => $baseDir . '/.composersrc/foo.php',
+);

+ 10 - 0
tests/Composer/Test/Autoload/Fixtures/autoload_classmap2.php

@@ -0,0 +1,10 @@
+<?php
+
+// autoload_classmap.php generated by Composer
+
+$vendorDir = dirname(__DIR__);
+$baseDir = dirname(dirname($vendorDir));
+
+return array(
+    'ClassMapFoo' => $baseDir . '/.composersrc/foo.php',
+);

+ 10 - 0
tests/Composer/Test/Autoload/Fixtures/autoload_classmap3.php

@@ -0,0 +1,10 @@
+<?php
+
+// autoload_classmap.php generated by Composer
+
+$vendorDir = dirname(__DIR__);
+$baseDir = $vendorDir;
+
+return array(
+    'ClassMapFoo' => $baseDir . '/.composersrc/foo.php',
+);

+ 12 - 0
tests/Composer/Test/Autoload/Fixtures/autoload_classmap4.php

@@ -0,0 +1,12 @@
+<?php
+
+// autoload_classmap.php generated by Composer
+
+$vendorDir = dirname(__DIR__);
+$baseDir = dirname($vendorDir);
+
+return array(
+    'ClassMapBaz' => $baseDir . '/composer-test-autoload/b/b/lib/c.php',
+    'ClassMapFoo' => $baseDir . '/composer-test-autoload/a/a/src/a.php',
+    'ClassMapBar' => $baseDir . '/composer-test-autoload/b/b/src/b.php',
+);

+ 3 - 0
tests/Composer/Test/Autoload/Fixtures/classmap/multipleNs.php

@@ -1,4 +1,7 @@
 <?php
+namespace {
+    class A {}
+}
 
 namespace Alpha {
     class A {}

+ 28 - 0
tests/Composer/Test/Autoload/Fixtures/php5.4/traits.php

@@ -0,0 +1,28 @@
+<?php
+namespace {
+    trait TFoo {
+
+    }
+
+    class CFoo {
+        use TFoo;
+    }
+}
+
+namespace Foo {
+    trait TBar {
+
+    }
+
+    interface IBar {
+
+    }
+
+    trait TFooBar {
+
+    }
+
+    class CBar implements IBar {
+        use TBar, TFooBar;
+    }
+}

+ 8 - 2
tests/Composer/Test/Util/FilesystemTest.php

@@ -58,10 +58,10 @@ class FilesystemTest extends TestCase
     /**
      * @dataProvider providePathCouples
      */
-    public function testFindShortestPath($a, $b, $expected)
+    public function testFindShortestPath($a, $b, $expected, $directory = false)
     {
         $fs = new Filesystem;
-        $this->assertEquals($expected, $fs->findShortestPath($a, $b));
+        $this->assertEquals($expected, $fs->findShortestPath($a, $b, $directory));
     }
 
     public function providePathCouples()
@@ -69,8 +69,13 @@ class FilesystemTest extends TestCase
         return array(
             array('/foo/bar', '/foo/bar', "./bar"),
             array('/foo/bar', '/foo/baz', "./baz"),
+            array('/foo/bar/', '/foo/baz', "./baz"),
+            array('/foo/bar', '/foo/bar', "./", true),
+            array('/foo/bar', '/foo/baz', "../baz", true),
+            array('/foo/bar/', '/foo/baz', "../baz", true),
             array('/foo/bin/run', '/foo/vendor/acme/bin/run', "../vendor/acme/bin/run"),
             array('/foo/bin/run', '/bar/bin/run', "/bar/bin/run"),
+            array('/foo/bin/run', '/bar/bin/run', "/bar/bin/run", true),
             array('c:/bin/run', 'c:/vendor/acme/bin/run', "../vendor/acme/bin/run"),
             array('c:\\bin\\run', 'c:/vendor/acme/bin/run', "../vendor/acme/bin/run"),
             array('c:/bin/run', 'd:/vendor/acme/bin/run', "d:/vendor/acme/bin/run"),
@@ -79,6 +84,7 @@ class FilesystemTest extends TestCase
             array('/tmp/test', '/tmp', "./"),
             array('C:/Temp/test/sub', 'C:\Temp', "../"),
             array('/tmp/test/sub', '/tmp', "../"),
+            array('/tmp/test/sub', '/tmp', "../../", true),
             array('/tmp', '/tmp/test', "test"),
             array('C:/Temp', 'C:\Temp\test', "test"),
             array('C:/Temp', 'c:\Temp\test', "test"),