Browse Source

Merge branch 'master' of github.com:composer/composer into tls-config

Pádraic Brady 11 years ago
parent
commit
6c7dd39837

+ 2 - 2
.travis.yml

@@ -16,8 +16,8 @@ matrix:
 before_script:
     - sudo apt-get install parallel
     - rm -f ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini
-    - composer install --dev --prefer-source
-    - bin/composer install --dev --prefer-source
+    - composer install --prefer-source
+    - bin/composer install --prefer-source
     - git config --global user.name travis-ci
     - git config --global user.email travis@example.com
 

+ 3 - 0
composer.json

@@ -39,6 +39,9 @@
     "autoload": {
         "psr-0": { "Composer": "src/" }
     },
+    "autoload-dev": {
+        "psr-0": { "Composer\\Test": "tests/" }
+    },
     "bin": ["bin/composer"],
     "extra": {
         "branch-alias": {

+ 12 - 12
composer.lock

@@ -3,7 +3,7 @@
         "This file locks the dependencies of your project to a known state",
         "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
     ],
-    "hash": "78b771e9b9f3c0181350f1d6ed8fa3c7",
+    "hash": "e68bf60f228ca192b8b492cb95a80fa7",
     "packages": [
         {
             "name": "justinrainbow/json-schema",
@@ -277,16 +277,16 @@
     "packages-dev": [
         {
             "name": "phpunit/php-code-coverage",
-            "version": "1.2.15",
+            "version": "1.2.16",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
-                "reference": "6ba4ed2895d538a039d5d5866edc4ec0424c7852"
+                "reference": "69e55e68481cf708a6db43aff0b504e31402fe27"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6ba4ed2895d538a039d5d5866edc4ec0424c7852",
-                "reference": "6ba4ed2895d538a039d5d5866edc4ec0424c7852",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/69e55e68481cf708a6db43aff0b504e31402fe27",
+                "reference": "69e55e68481cf708a6db43aff0b504e31402fe27",
                 "shasum": ""
             },
             "require": {
@@ -334,7 +334,7 @@
                 "testing",
                 "xunit"
             ],
-            "time": "2014-02-03 07:44:47"
+            "time": "2014-02-25 03:34:05"
         },
         {
             "name": "phpunit/php-file-iterator",
@@ -521,16 +521,16 @@
         },
         {
             "name": "phpunit/phpunit",
-            "version": "3.7.31",
+            "version": "3.7.32",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "d24e9877331039582497052cc3c4d9f465b88210"
+                "reference": "2752cbb9ea5bd84c2811b34b6953f76965ec7a2f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d24e9877331039582497052cc3c4d9f465b88210",
-                "reference": "d24e9877331039582497052cc3c4d9f465b88210",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2752cbb9ea5bd84c2811b34b6953f76965ec7a2f",
+                "reference": "2752cbb9ea5bd84c2811b34b6953f76965ec7a2f",
                 "shasum": ""
             },
             "require": {
@@ -547,7 +547,7 @@
                 "symfony/yaml": "~2.0"
             },
             "require-dev": {
-                "pear-pear/pear": "1.9.4"
+                "pear-pear.php.net/pear": "1.9.4"
             },
             "suggest": {
                 "ext-json": "*",
@@ -591,7 +591,7 @@
                 "testing",
                 "xunit"
             ],
-            "time": "2014-02-03 07:46:27"
+            "time": "2014-02-25 03:47:29"
         },
         {
             "name": "phpunit/phpunit-mock-objects",

+ 1 - 0
doc/03-cli.md

@@ -401,6 +401,7 @@ performance.
 * **--optimize (-o):** Convert PSR-0/4 autoloading to classmap to get a faster
   autoloader. This is recommended especially for production, but can take
   a bit of time to run so it is currently not done by default.
+* **--no-dev:** Disables autoload-dev rules.
 
 ## licenses
 

+ 22 - 0
doc/04-schema.md

@@ -516,6 +516,28 @@ Example:
         }
     }
 
+### autoload-dev <span>(root-only)</span>
+
+This section allows to define autoload rules for development purposes.
+
+Classes needed to run the test suite should not be included in the main autoload
+rules to avoid polluting the autoloader in production and when other people use
+your package as a dependency.
+
+Therefore, it is a good idea to rely on a dedicated path for your unit tests
+and to add it within the autoload-dev section.
+
+Example:
+
+    {
+        "autoload": {
+            "psr-4": { "MyLibrary\\": "src/" }
+        },
+        "autoload-dev": {
+            "psr-4": { "MyLibrary\\Tests": "tests/" }
+        }
+    }
+
 ### include-path
 
 > **DEPRECATED**: This is only present to support legacy projects, and all new code

+ 24 - 0
res/composer-schema.json

@@ -226,6 +226,30 @@
                 }
             }
         },
+        "autoload-dev": {
+            "type": "object",
+            "description": "Description of additional autoload rules for development purpose (eg. a test suite).",
+            "properties": {
+                "psr-0": {
+                    "type": "object",
+                    "description": "This is a hash of namespaces (keys) and the directories they can be found into (values, can be arrays of paths) by the autoloader.",
+                    "additionalProperties": true
+                },
+                "psr-4": {
+                    "type": "object",
+                    "description": "This is a hash of namespaces (keys) and the PSR-4 directories they can map to (values, can be arrays of paths) by the autoloader.",
+                    "additionalProperties": true
+                },
+                "classmap": {
+                    "type": "array",
+                    "description": "This is an array of directories that contain classes to be included in the class-map generation process."
+                },
+                "files": {
+                    "type": "array",
+                    "description": "This is an array of files that are always required on every request."
+                }
+            }
+        },
         "archive": {
             "type": ["object"],
             "description": "Options for creating package archives for distribution.",

+ 26 - 26
src/Composer/Autoload/AutoloadGenerator.php

@@ -32,14 +32,21 @@ class AutoloadGenerator
      */
     private $eventDispatcher;
 
+    private $devMode = false;
+
     public function __construct(EventDispatcher $eventDispatcher)
     {
         $this->eventDispatcher = $eventDispatcher;
     }
 
+    public function setDevMode($devMode = true)
+    {
+        $this->devMode = (boolean) $devMode;
+    }
+
     public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '')
     {
-        $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP);
+        $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode);
 
         $filesystem = new Filesystem();
         $filesystem->ensureDirectoryExists($config->get('vendor-dir'));
@@ -183,7 +190,6 @@ EOF;
             }
         }
 
-        $autoloads['classmap'] = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($autoloads['classmap']));
         foreach ($autoloads['classmap'] as $dir) {
             foreach (ClassMapGenerator::createMap($dir) as $class => $path) {
                 $path = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
@@ -222,7 +228,7 @@ EOF;
         fclose($targetLoader);
         unset($sourceLoader, $targetLoader);
 
-        $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP);
+        $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode);
     }
 
     public function buildPackageMap(InstallationManager $installationManager, PackageInterface $mainPackage, array $packages)
@@ -360,7 +366,6 @@ EOF;
     protected function getIncludeFilesFile(array $files, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
     {
         $filesCode = '';
-        $files = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($files));
         foreach ($files as $functionFile) {
             $filesCode .= '    '.$this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile).",\n";
         }
@@ -569,6 +574,9 @@ FOOTER;
             list($package, $installPath) = $item;
 
             $autoload = $package->getAutoload();
+            if ($this->devMode && $package === $mainPackage) {
+                $autoload = array_merge_recursive($autoload, $package->getDevAutoload());
+            }
 
             // skip misconfigured packages
             if (!isset($autoload[$type]) || !is_array($autoload[$type])) {
@@ -580,33 +588,25 @@ FOOTER;
 
             foreach ($autoload[$type] as $namespace => $paths) {
                 foreach ((array) $paths as $path) {
-                    // remove target-dir from file paths of the root package
-                    if ($type === 'files' && $package === $mainPackage && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
-                        $targetDir = str_replace('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $package->getTargetDir())));
-                        $path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/');
+                    if (($type === 'files' || $type === 'classmap') && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
+                        // remove target-dir from file paths of the root package
+                        if ($package === $mainPackage) {
+                            $targetDir = str_replace('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $package->getTargetDir())));
+                            $path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/');
+                        } else {
+                            // add target-dir from file paths that don't have it
+                            $path = $package->getTargetDir() . '/' . $path;
+                        }
                     }
 
-                    // add target-dir from file paths that don't have it
-                    if ($type === 'files' && $package !== $mainPackage && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
-                        $path = $package->getTargetDir() . '/' . $path;
-                    }
+                    $relativePath = empty($installPath) ? (empty($path) ? '.' : $path) : $installPath.'/'.$path;
 
-                    // remove target-dir from classmap entries of the root package
-                    if ($type === 'classmap' && $package === $mainPackage && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
-                        $targetDir = str_replace('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $package->getTargetDir())));
-                        $path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/');
+                    if ($type === 'files' || $type === 'classmap') {
+                        $autoloads[] = $relativePath;
+                        continue;
                     }
 
-                    // add target-dir to classmap entries that don't have it
-                    if ($type === 'classmap' && $package !== $mainPackage && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
-                        $path = $package->getTargetDir() . '/' . $path;
-                    }
-
-                    if (empty($installPath)) {
-                        $autoloads[$namespace][] = empty($path) ? '.' : $path;
-                    } else {
-                        $autoloads[$namespace][] = $installPath.'/'.$path;
-                    }
+                    $autoloads[$namespace][] = $relativePath;
                 }
             }
         }

+ 4 - 1
src/Composer/Command/DumpAutoloadCommand.php

@@ -31,6 +31,7 @@ class DumpAutoloadCommand extends Command
             ->setDescription('Dumps the autoloader')
             ->setDefinition(array(
                 new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 packages to be loaded with classmaps too, good for production.'),
+                new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules.'),
             ))
             ->setHelp(<<<EOT
 <info>php composer.phar dump-autoload</info>
@@ -59,6 +60,8 @@ EOT
             $output->writeln('<info>Generating autoload files</info>');
         }
 
-        $composer->getAutoloadGenerator()->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);
+        $generator = $composer->getAutoloadGenerator();
+        $generator->setDevMode(!$input->getOption('no-dev'));
+        $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);
     }
 }

+ 2 - 6
src/Composer/EventDispatcher/EventDispatcher.php

@@ -75,13 +75,9 @@ class EventDispatcher
      * @param string       $eventName The constant in ScriptEvents
      * @param Script\Event $event
      */
-    public function dispatchScript($eventName, Script\Event $event = null)
+    public function dispatchScript($eventName, $devMode = false)
     {
-        if (null == $event) {
-            $event = new Script\Event($eventName, $this->composer, $this->io);
-        }
-
-        $this->doDispatch($event);
+        $this->doDispatch(new Script\Event($eventName, $this->composer, $this->io, $devMode));
     }
 
     /**

+ 1 - 0
src/Composer/Installer.php

@@ -290,6 +290,7 @@ class Installer
                 $this->io->write('<info>Generating autoload files</info>');
             }
 
+            $this->autoloadGenerator->setDevMode($this->devMode);
             $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader);
 
             if ($this->runScripts) {

+ 4 - 0
src/Composer/Package/AliasPackage.php

@@ -245,6 +245,10 @@ class AliasPackage extends BasePackage implements CompletePackageInterface
     {
         return $this->aliasOf->getAutoload();
     }
+    public function getDevAutoload()
+    {
+        return $this->aliasOf->getDevAutoload();
+    }
     public function getIncludePaths()
     {
         return $this->aliasOf->getIncludePaths();

+ 1 - 0
src/Composer/Package/Dumper/ArrayDumper.php

@@ -31,6 +31,7 @@ class ArrayDumper
             'extra',
             'installationSource' => 'installation-source',
             'autoload',
+            'devAutoload' => 'autoload-dev',
             'notificationUrl' => 'notification-url',
             'includePaths' => 'include-path',
         );

+ 4 - 0
src/Composer/Package/Loader/ArrayLoader.php

@@ -130,6 +130,10 @@ class ArrayLoader implements LoaderInterface
             $package->setAutoload($config['autoload']);
         }
 
+        if (isset($config['autoload-dev'])) {
+            $package->setDevAutoload($config['autoload-dev']);
+        }
+
         if (isset($config['include-path'])) {
             $package->setIncludePaths($config['include-path']);
         }

+ 19 - 0
src/Composer/Package/Package.php

@@ -47,6 +47,7 @@ class Package extends BasePackage
     protected $devRequires = array();
     protected $suggests = array();
     protected $autoload = array();
+    protected $devAutoload = array();
     protected $includePaths = array();
     protected $archiveExcludes = array();
 
@@ -440,6 +441,24 @@ class Package extends BasePackage
         return $this->autoload;
     }
 
+    /**
+     * Set the dev autoload mapping
+     *
+     * @param array $autoload Mapping of dev autoloading rules
+     */
+    public function setDevAutoload(array $devAutoload)
+    {
+        $this->devAutoload = $devAutoload;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function getDevAutoload()
+    {
+        return $this->devAutoload;
+    }
+
     /**
      * Sets the list of paths added to PHP's include path.
      *

+ 14 - 2
src/Composer/Package/PackageInterface.php

@@ -231,13 +231,25 @@ interface PackageInterface
      *
      * {"<type>": {"<namespace": "<directory>"}}
      *
-     * Type is either "psr-0" or "pear". Namespaces are mapped to directories
-     * for autoloading using the type specified.
+     * Type is either "psr-4", "psr-0", "classmap" or "files". Namespaces are mapped to
+     * directories for autoloading using the type specified.
      *
      * @return array Mapping of autoloading rules
      */
     public function getAutoload();
 
+    /**
+     * Returns an associative array of dev autoloading rules
+     *
+     * {"<type>": {"<namespace": "<directory>"}}
+     *
+     * Type is either "psr-4", "psr-0", "classmap" or "files". Namespaces are mapped to
+     * directories for autoloading using the type specified.
+     *
+     * @return array Mapping of dev autoloading rules
+     */
+    public function getDevAutoload();
+
     /**
      * Returns a list of directories which should get added to PHP's
      * include path.

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

@@ -171,6 +171,77 @@ class AutoloadGeneratorTest extends TestCase
         $this->assertAutoloadFiles('classmap', $this->vendorDir.'/composer', 'classmap');
     }
 
+    public function testMainPackageDevAutoloading()
+    {
+        $package = new Package('a', '1.0', '1.0');
+        $package->setAutoload(array(
+            'psr-0' => array(
+                'Main' => 'src/',
+            ),
+        ));
+        $package->setDevAutoload(array(
+            'files' => array('devfiles/foo.php'),
+            'psr-0' => array(
+                'Main' => 'tests/'
+            ),
+        ));
+
+        $this->repository->expects($this->once())
+            ->method('getCanonicalPackages')
+            ->will($this->returnValue(array()));
+
+        $this->fs->ensureDirectoryExists($this->workingDir.'/composer');
+        $this->fs->ensureDirectoryExists($this->workingDir.'/src/Main');
+        file_put_contents($this->workingDir.'/src/Main/ClassMain.php', '<?php namespace Main; class ClassMain {}');
+
+        $this->fs->ensureDirectoryExists($this->workingDir.'/devfiles');
+        file_put_contents($this->workingDir.'/devfiles/foo.php', '<?php function foo() { echo "foo"; }');
+
+        // generate autoload files with the dev mode set to true
+        $this->generator->setDevMode(true);
+        $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', true, '_1');
+
+        // check standard autoload
+        $this->assertAutoloadFiles('main5', $this->vendorDir.'/composer');
+        $this->assertAutoloadFiles('classmap7', $this->vendorDir.'/composer', 'classmap');
+
+        // make sure dev autoload is correctly dumped
+        $this->assertAutoloadFiles('files2', $this->vendorDir.'/composer', 'files');
+    }
+
+    public function testMainPackageDevAutoloadingDisabledByDefault()
+    {
+        $package = new Package('a', '1.0', '1.0');
+        $package->setAutoload(array(
+            'psr-0' => array(
+                'Main' => 'src/',
+            ),
+        ));
+        $package->setDevAutoload(array(
+            'files' => array('devfiles/foo.php'),
+        ));
+
+        $this->repository->expects($this->once())
+            ->method('getCanonicalPackages')
+            ->will($this->returnValue(array()));
+
+        $this->fs->ensureDirectoryExists($this->workingDir.'/composer');
+        $this->fs->ensureDirectoryExists($this->workingDir.'/src/Main');
+        file_put_contents($this->workingDir.'/src/Main/ClassMain.php', '<?php namespace Main; class ClassMain {}');
+
+        $this->fs->ensureDirectoryExists($this->workingDir.'/devfiles');
+        file_put_contents($this->workingDir.'/devfiles/foo.php', '<?php function foo() { echo "foo"; }');
+
+        $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', true, '_1');
+
+        // check standard autoload
+        $this->assertAutoloadFiles('main4', $this->vendorDir.'/composer');
+        $this->assertAutoloadFiles('classmap7', $this->vendorDir.'/composer', 'classmap');
+
+        // make sure dev autoload is disabled when dev mode is set to false
+        $this->assertFalse(is_file($this->vendorDir.'/composer/autoload_files.php'));
+    }
+
     public function testVendorDirSameAsWorkingDir()
     {
         $this->vendorDir = $this->workingDir;

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

@@ -0,0 +1,10 @@
+<?php
+
+// autoload_classmap.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+    'Main\\ClassMain' => $baseDir . '/src/Main/ClassMain.php',
+);

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

@@ -0,0 +1,10 @@
+<?php
+
+// autoload_files.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+    $baseDir . '/devfiles/foo.php',
+);

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

@@ -9,6 +9,6 @@ return array(
     $vendorDir . '/a/a/test.php',
     $vendorDir . '/b/b/test2.php',
     $vendorDir . '/c/c/foo/bar/test3.php',
-    $baseDir . '/root.php',
     $vendorDir . '/c/c/foo/bar/test4.php',
+    $baseDir . '/root.php',
 );

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

@@ -0,0 +1,10 @@
+<?php
+
+// autoload_namespaces.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+    'Main' => array($baseDir . '/src'),
+);

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

@@ -0,0 +1,10 @@
+<?php
+
+// autoload_namespaces.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+    'Main' => array($baseDir . '/src', $baseDir . '/tests'),
+);

+ 1 - 3
tests/bootstrap.php

@@ -12,7 +12,5 @@
 
 error_reporting(E_ALL);
 
-$loader = require __DIR__.'/../src/bootstrap.php';
-$loader->add('Composer\Test', __DIR__);
-
+require __DIR__.'/../src/bootstrap.php';
 require __DIR__.'/Composer/TestCase.php';