Browse Source

Merge remote-tracking branch 'upstream/master'

Kael Shipman 8 years ago
parent
commit
9a755fa7d4

+ 2 - 0
bin/composer

@@ -48,6 +48,8 @@ if (function_exists('ini_set')) {
     unset($memoryInBytes, $memoryLimit);
     unset($memoryInBytes, $memoryLimit);
 }
 }
 
 
+putenv('COMPOSER_BINARY='.realpath($_SERVER['argv'][0]));
+
 // run the command application
 // run the command application
 $application = new Application();
 $application = new Application();
 $application->run(null, $output);
 $application->run(null, $output);

+ 1 - 1
doc/05-repositories.md

@@ -58,7 +58,7 @@ The main repository type is the `composer` repository. It uses a single
 
 
 This is also the repository type that packagist uses. To reference a
 This is also the repository type that packagist uses. To reference a
 `composer` repository, just supply the path before the `packages.json` file.
 `composer` repository, just supply the path before the `packages.json` file.
-In case of packagist, that file is located at `/packages.json`, so the URL of
+In the case of packagist, that file is located at `/packages.json`, so the URL of
 the repository would be `packagist.org`. For `example.org/packages.json` the
 the repository would be `packagist.org`. For `example.org/packages.json` the
 repository URL would be `example.org`.
 repository URL would be `example.org`.
 
 

+ 5 - 3
src/Composer/Command/ArchiveCommand.php

@@ -45,6 +45,7 @@ class ArchiveCommand extends BaseCommand
                 new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'),
                 new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'),
                 new InputOption('file', null, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.'
                 new InputOption('file', null, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.'
                     .' Note that the format will be appended.'),
                     .' Note that the format will be appended.'),
+                new InputOption('ignore-filters', false, InputOption::VALUE_NONE, 'Ignore filters when saving package')
             ))
             ))
             ->setHelp(<<<EOT
             ->setHelp(<<<EOT
 The <info>archive</info> command creates an archive of the specified format
 The <info>archive</info> command creates an archive of the specified format
@@ -82,7 +83,8 @@ EOT
             $input->getArgument('version'),
             $input->getArgument('version'),
             $input->getOption('format'),
             $input->getOption('format'),
             $input->getOption('dir'),
             $input->getOption('dir'),
-            $input->getOption('file')
+            $input->getOption('file'),
+            $input->getOption('ignore-filters')
         );
         );
 
 
         if (0 === $returnCode && $composer) {
         if (0 === $returnCode && $composer) {
@@ -92,7 +94,7 @@ EOT
         return $returnCode;
         return $returnCode;
     }
     }
 
 
-    protected function archive(IOInterface $io, Config $config, $packageName = null, $version = null, $format = 'tar', $dest = '.', $fileName = null)
+    protected function archive(IOInterface $io, Config $config, $packageName = null, $version = null, $format = 'tar', $dest = '.', $fileName = null, $ignoreFilters)
     {
     {
         $factory = new Factory;
         $factory = new Factory;
         $downloadManager = $factory->createDownloadManager($io, $config);
         $downloadManager = $factory->createDownloadManager($io, $config);
@@ -109,7 +111,7 @@ EOT
         }
         }
 
 
         $io->writeError('<info>Creating the archive into "'.$dest.'".</info>');
         $io->writeError('<info>Creating the archive into "'.$dest.'".</info>');
-        $packagePath = $archiveManager->archive($package, $format, $dest, $fileName);
+        $packagePath = $archiveManager->archive($package, $format, $dest, $fileName, $ignoreFilters);
         $fs = new Filesystem;
         $fs = new Filesystem;
         $shortPath = $fs->findShortestPath(getcwd(), $packagePath, true);
         $shortPath = $fs->findShortestPath(getcwd(), $packagePath, true);
 
 

+ 5 - 0
src/Composer/Command/CreateProjectCommand.php

@@ -23,6 +23,7 @@ use Composer\Package\BasePackage;
 use Composer\DependencyResolver\Pool;
 use Composer\DependencyResolver\Pool;
 use Composer\DependencyResolver\Operation\InstallOperation;
 use Composer\DependencyResolver\Operation\InstallOperation;
 use Composer\Package\Version\VersionSelector;
 use Composer\Package\Version\VersionSelector;
+use Composer\Package\AliasPackage;
 use Composer\Repository\RepositoryFactory;
 use Composer\Repository\RepositoryFactory;
 use Composer\Repository\CompositeRepository;
 use Composer\Repository\CompositeRepository;
 use Composer\Repository\PlatformRepository;
 use Composer\Repository\PlatformRepository;
@@ -330,6 +331,10 @@ EOT
             $io->writeError('<info>Plugins have been disabled.</info>');
             $io->writeError('<info>Plugins have been disabled.</info>');
         }
         }
 
 
+        if ($package instanceof AliasPackage) {
+            $package = $package->getAliasOf();
+        }
+
         if (0 === strpos($package->getPrettyVersion(), 'dev-') && in_array($package->getSourceType(), array('git', 'hg'))) {
         if (0 === strpos($package->getPrettyVersion(), 'dev-') && in_array($package->getSourceType(), array('git', 'hg'))) {
             $package->setSourceReference(substr($package->getPrettyVersion(), 4));
             $package->setSourceReference(substr($package->getPrettyVersion(), 4));
         }
         }

+ 4 - 4
src/Composer/Command/OutdatedCommand.php

@@ -39,13 +39,13 @@ class OutdatedCommand extends ShowCommand
             ->setHelp(<<<EOT
             ->setHelp(<<<EOT
 The outdated command is just a proxy for `composer show -l`
 The outdated command is just a proxy for `composer show -l`
 
 
-The color coding for dependency versions is as such:
+The color coding (or signage if you have ANSI colors disabled) for dependency versions is as such:
 
 
-- <info>green</info>: Dependency is in the latest version and is up to date.
-- <comment>yellow</comment>: Dependency has a new version available that includes backwards
+- <info>green</info> (=): Dependency is in the latest version and is up to date.
+- <comment>yellow</comment> (~): Dependency has a new version available that includes backwards
   compatibility breaks according to semver, so upgrade when you can but it
   compatibility breaks according to semver, so upgrade when you can but it
   may involve work.
   may involve work.
-- <highlight>red</highlight>: Dependency has a new version that is semver-compatible and you should upgrade it.
+- <highlight>red</highlight> (!): Dependency has a new version that is semver-compatible and you should upgrade it.
 
 
 
 
 EOT
 EOT

+ 7 - 1
src/Composer/Command/ShowCommand.php

@@ -173,7 +173,7 @@ EOT
                     }
                     }
 
 
                     $io->writeError('Package ' . $packageFilter . ' not found in ' . $options['working-dir'] . '/composer.json');
                     $io->writeError('Package ' . $packageFilter . ' not found in ' . $options['working-dir'] . '/composer.json');
-                    return;
+                    return 1;
                 }
                 }
             } else {
             } else {
                 $versions = array($package->getPrettyVersion() => $package->getVersion());
                 $versions = array($package->getPrettyVersion() => $package->getVersion());
@@ -317,6 +317,9 @@ EOT
                 $writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion && ($nameLength + $versionLength + 3 <= $width);
                 $writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion && ($nameLength + $versionLength + 3 <= $width);
                 $writeLatest = $writeVersion && $showLatest && ($nameLength + $versionLength + $latestLength + 3 <= $width);
                 $writeLatest = $writeVersion && $showLatest && ($nameLength + $versionLength + $latestLength + 3 <= $width);
                 $writeDescription = !$input->getOption('name-only') && !$input->getOption('path') && ($nameLength + $versionLength + $latestLength + 24 <= $width);
                 $writeDescription = !$input->getOption('name-only') && !$input->getOption('path') && ($nameLength + $versionLength + $latestLength + 24 <= $width);
+                if ($writeLatest && !$io->isDecorated()) {
+                    $latestLength += 2;
+                }
                 $hasOutdatedPackages = false;
                 $hasOutdatedPackages = false;
                 foreach ($packages[$type] as $package) {
                 foreach ($packages[$type] as $package) {
                     if (is_object($package)) {
                     if (is_object($package)) {
@@ -339,6 +342,9 @@ EOT
                         if ($writeLatest && $latestPackackage) {
                         if ($writeLatest && $latestPackackage) {
                             $latestVersion = $latestPackackage->getFullPrettyVersion();
                             $latestVersion = $latestPackackage->getFullPrettyVersion();
                             $style = $this->getVersionStyle($latestPackackage, $package);
                             $style = $this->getVersionStyle($latestPackackage, $package);
+                            if (!$io->isDecorated()) {
+                                $latestVersion = str_replace(array('info', 'highlight', 'comment'), array('=', '!', '~'), $style) . ' ' . $latestVersion;
+                            }
                             $io->write(' <'.$style.'>' . str_pad($latestVersion, $latestLength, ' ') . '</'.$style.'>', false);
                             $io->write(' <'.$style.'>' . str_pad($latestVersion, $latestLength, ' ') . '</'.$style.'>', false);
                         }
                         }
 
 

+ 1 - 1
src/Composer/Console/Application.php

@@ -166,7 +166,7 @@ class Application extends BaseApplication
                 $io->writeError('<warning>Composer only officially supports PHP 5.3.2 and above, you will most likely encounter problems with your PHP '.PHP_VERSION.', upgrading is strongly recommended.</warning>');
                 $io->writeError('<warning>Composer only officially supports PHP 5.3.2 and above, you will most likely encounter problems with your PHP '.PHP_VERSION.', upgrading is strongly recommended.</warning>');
             }
             }
 
 
-            if (extension_loaded('xdebug') && (!getenv('COMPOSER_DISABLE_XDEBUG_WARN') || getenv('COMPOSER_ALLOW_XDEBUG'))) {
+            if (extension_loaded('xdebug') && !getenv('COMPOSER_DISABLE_XDEBUG_WARN')) {
                 $io->writeError('<warning>You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug</warning>');
                 $io->writeError('<warning>You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug</warning>');
             }
             }
 
 

+ 15 - 12
src/Composer/EventDispatcher/EventDispatcher.php

@@ -175,12 +175,7 @@ class EventDispatcher
                 $args = $event->getArguments();
                 $args = $event->getArguments();
                 $flags = $event->getFlags();
                 $flags = $event->getFlags();
                 if (substr($callable, 0, 10) === '@composer ') {
                 if (substr($callable, 0, 10) === '@composer ') {
-                    $finder = new PhpExecutableFinder();
-                    $phpPath = $finder->find();
-                    if (!$phpPath) {
-                        throw new \RuntimeException('Failed to locate PHP binary to execute '.$scriptName);
-                    }
-                    $exec = $phpPath . '  ' . realpath($_SERVER['argv'][0]) . substr($callable, 9);
+                    $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($callable, 9);
                     if (0 !== ($exitCode = $this->process->execute($exec))) {
                     if (0 !== ($exitCode = $this->process->execute($exec))) {
                         $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()));
                         $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()));
 
 
@@ -234,12 +229,7 @@ class EventDispatcher
                 }
                 }
 
 
                 if (substr($exec, 0, 5) === '@php ') {
                 if (substr($exec, 0, 5) === '@php ') {
-                    $finder = new PhpExecutableFinder();
-                    $phpPath = $finder->find();
-                    if (!$phpPath) {
-                        throw new \RuntimeException('Failed to locate PHP binary to execute "'.$exec.'"');
-                    }
-                    $exec = $phpPath . ' ' . substr($exec, 5);
+                    $exec = $this->getPhpExecCommand() . ' ' . substr($exec, 5);
                 }
                 }
 
 
                 if (0 !== ($exitCode = $this->process->execute($exec))) {
                 if (0 !== ($exitCode = $this->process->execute($exec))) {
@@ -259,6 +249,19 @@ class EventDispatcher
         return $return;
         return $return;
     }
     }
 
 
+    protected function getPhpExecCommand()
+    {
+        $finder = new PhpExecutableFinder();
+        $phpPath = $finder->find();
+        if (!$phpPath) {
+            throw new \RuntimeException('Failed to locate PHP binary to execute '.$scriptName);
+        }
+
+        $memoryFlag = ' -d memory_limit='.ini_get('memory_limit');
+
+        return ProcessExecutor::escape($phpPath) . $memoryFlag;
+    }
+
     /**
     /**
      * @param string $className
      * @param string $className
      * @param string $methodName
      * @param string $methodName

+ 1 - 1
src/Composer/Installer.php

@@ -605,7 +605,7 @@ class Installer
                 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
                 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
             }
             }
 
 
-            if ($this->executeOperations) {
+            if ($this->executeOperations || $this->writeLock) {
                 $localRepo->write();
                 $localRepo->write();
             }
             }
         }
         }

+ 11 - 6
src/Composer/Package/Archiver/ArchivableFilesFinder.php

@@ -37,18 +37,23 @@ class ArchivableFilesFinder extends \FilterIterator
      *
      *
      * @param string $sources  Path to source files to be archived
      * @param string $sources  Path to source files to be archived
      * @param array  $excludes Composer's own exclude rules from composer.json
      * @param array  $excludes Composer's own exclude rules from composer.json
+     * @param boolean $ignoreFilters Ignore filters when looking for files
      */
      */
-    public function __construct($sources, array $excludes)
+    public function __construct($sources, array $excludes, $ignoreFilters = false)
     {
     {
         $fs = new Filesystem();
         $fs = new Filesystem();
 
 
         $sources = $fs->normalizePath($sources);
         $sources = $fs->normalizePath($sources);
 
 
-        $filters = array(
-            new HgExcludeFilter($sources),
-            new GitExcludeFilter($sources),
-            new ComposerExcludeFilter($sources, $excludes),
-        );
+        if ($ignoreFilters) {
+            $filters = array();
+        } else {
+            $filters = array(
+                new HgExcludeFilter($sources),
+                new GitExcludeFilter($sources),
+                new ComposerExcludeFilter($sources, $excludes),
+            );
+        }
 
 
         $this->finder = new Finder();
         $this->finder = new Finder();
 
 

+ 3 - 2
src/Composer/Package/Archiver/ArchiveManager.php

@@ -99,11 +99,12 @@ class ArchiveManager
      * @param  string                    $targetDir The directory where to build the archive
      * @param  string                    $targetDir The directory where to build the archive
      * @param  string|null               $fileName  The relative file name to use for the archive, or null to generate
      * @param  string|null               $fileName  The relative file name to use for the archive, or null to generate
      *                                              the package name. Note that the format will be appended to this name
      *                                              the package name. Note that the format will be appended to this name
+     * @param boolean                    $ignoreFilters Ignore filters when looking for files in the package
      * @throws \InvalidArgumentException
      * @throws \InvalidArgumentException
      * @throws \RuntimeException
      * @throws \RuntimeException
      * @return string                    The path of the created archive
      * @return string                    The path of the created archive
      */
      */
-    public function archive(PackageInterface $package, $format, $targetDir, $fileName = null)
+    public function archive(PackageInterface $package, $format, $targetDir, $fileName = null, $ignoreFilters = false)
     {
     {
         if (empty($format)) {
         if (empty($format)) {
             throw new \InvalidArgumentException('Format must be specified');
             throw new \InvalidArgumentException('Format must be specified');
@@ -163,7 +164,7 @@ class ArchiveManager
         $tempTarget = sys_get_temp_dir().'/composer_archive'.uniqid().'.'.$format;
         $tempTarget = sys_get_temp_dir().'/composer_archive'.uniqid().'.'.$format;
         $filesystem->ensureDirectoryExists(dirname($tempTarget));
         $filesystem->ensureDirectoryExists(dirname($tempTarget));
 
 
-        $archivePath = $usableArchiver->archive($sourcePath, $tempTarget, $format, $package->getArchiveExcludes());
+        $archivePath = $usableArchiver->archive($sourcePath, $tempTarget, $format, $package->getArchiveExcludes(), $ignoreFilters);
         $filesystem->rename($archivePath, $target);
         $filesystem->rename($archivePath, $target);
 
 
         // cleanup temporary download
         // cleanup temporary download

+ 1 - 1
src/Composer/Package/Archiver/ArchiverInterface.php

@@ -29,7 +29,7 @@ interface ArchiverInterface
      *
      *
      * @return string The path to the written archive file
      * @return string The path to the written archive file
      */
      */
-    public function archive($sources, $target, $format, array $excludes = array());
+    public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false);
 
 
     /**
     /**
      * Format supported by the archiver.
      * Format supported by the archiver.

+ 2 - 2
src/Composer/Package/Archiver/PharArchiver.php

@@ -34,7 +34,7 @@ class PharArchiver implements ArchiverInterface
     /**
     /**
      * {@inheritdoc}
      * {@inheritdoc}
      */
      */
-    public function archive($sources, $target, $format, array $excludes = array())
+    public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
     {
     {
         $sources = realpath($sources);
         $sources = realpath($sources);
 
 
@@ -53,7 +53,7 @@ class PharArchiver implements ArchiverInterface
             }
             }
 
 
             $phar = new \PharData($target, null, null, static::$formats[$format]);
             $phar = new \PharData($target, null, null, static::$formats[$format]);
-            $files = new ArchivableFilesFinder($sources, $excludes);
+            $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
             $filesOnly = new ArchivableFilesFilter($files);
             $filesOnly = new ArchivableFilesFilter($files);
             $phar->buildFromIterator($filesOnly, $sources);
             $phar->buildFromIterator($filesOnly, $sources);
             $filesOnly->addEmptyDir($phar, $sources);
             $filesOnly->addEmptyDir($phar, $sources);

+ 2 - 2
src/Composer/Package/Archiver/ZipArchiver.php

@@ -27,7 +27,7 @@ class ZipArchiver implements ArchiverInterface
     /**
     /**
      * {@inheritdoc}
      * {@inheritdoc}
      */
      */
-    public function archive($sources, $target, $format, array $excludes = array())
+    public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
     {
     {
         $fs = new Filesystem();
         $fs = new Filesystem();
         $sources = $fs->normalizePath($sources);
         $sources = $fs->normalizePath($sources);
@@ -35,7 +35,7 @@ class ZipArchiver implements ArchiverInterface
         $zip = new ZipArchive();
         $zip = new ZipArchive();
         $res = $zip->open($target, ZipArchive::CREATE);
         $res = $zip->open($target, ZipArchive::CREATE);
         if ($res === true) {
         if ($res === true) {
-            $files = new ArchivableFilesFinder($sources, $excludes);
+            $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
             foreach ($files as $file) {
             foreach ($files as $file) {
                 /** @var $file \SplFileInfo */
                 /** @var $file \SplFileInfo */
                 $filepath = strtr($file->getPath()."/".$file->getFilename(), '\\', '/');
                 $filepath = strtr($file->getPath()."/".$file->getFilename(), '\\', '/');

+ 55 - 0
tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php

@@ -235,6 +235,61 @@ class ArchivableFilesFinderTest extends TestCase
         $this->assertArchivableFiles($expectedFiles);
         $this->assertArchivableFiles($expectedFiles);
     }
     }
 
 
+    public function testSkipExcludes()
+    {
+        $excludes = array(
+            'prefixB.foo',
+        );
+
+        $this->finder = new ArchivableFilesFinder($this->sources, $excludes, true);
+
+        $this->assertArchivableFiles(array(
+            '/!important!.txt',
+            '/!important_too!.txt',
+            '/#weirdfile',
+            '/A/prefixA.foo',
+            '/A/prefixB.foo',
+            '/A/prefixC.foo',
+            '/A/prefixD.foo',
+            '/A/prefixE.foo',
+            '/A/prefixF.foo',
+            '/B/sub/prefixA.foo',
+            '/B/sub/prefixB.foo',
+            '/B/sub/prefixC.foo',
+            '/B/sub/prefixD.foo',
+            '/B/sub/prefixE.foo',
+            '/B/sub/prefixF.foo',
+            '/C/prefixA.foo',
+            '/C/prefixB.foo',
+            '/C/prefixC.foo',
+            '/C/prefixD.foo',
+            '/C/prefixE.foo',
+            '/C/prefixF.foo',
+            '/D/prefixA',
+            '/D/prefixB',
+            '/D/prefixC',
+            '/D/prefixD',
+            '/D/prefixE',
+            '/D/prefixF',
+            '/E/subtestA.foo',
+            '/F/subtestA.foo',
+            '/G/subtestA.foo',
+            '/H/subtestA.foo',
+            '/I/J/subtestA.foo',
+            '/K/dirJ/subtestA.foo',
+            '/parameters.yml',
+            '/parameters.yml.dist',
+            '/prefixA.foo',
+            '/prefixB.foo',
+            '/prefixC.foo',
+            '/prefixD.foo',
+            '/prefixE.foo',
+            '/prefixF.foo',
+            '/toplevelA.foo',
+            '/toplevelB.foo',
+        ));
+    }
+
     protected function getArchivableFiles()
     protected function getArchivableFiles()
     {
     {
         $files = array();
         $files = array();