From 91d9e91c0af9ff95ee9affd51b47c8d547be95ea Mon Sep 17 00:00:00 2001 From: Ben Davies Date: Tue, 20 Aug 2013 15:24:21 +0100 Subject: [PATCH 001/238] load IO configuration --- src/Composer/Factory.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index b63ad13f1..82c5084c2 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -342,7 +342,9 @@ class Factory public function createArchiveManager(Config $config, Downloader\DownloadManager $dm = null) { if (null === $dm) { - $dm = $this->createDownloadManager(new IO\NullIO(), $config); + $io = new IO\NullIO(); + $io->loadConfiguration($config); + $dm = $this->createDownloadManager($io, $config); } $am = new Archiver\ArchiveManager($dm); From abb1db54bbcd13b40d261386aafb2355ea3bbd2c Mon Sep 17 00:00:00 2001 From: DerManoMann Date: Fri, 23 Aug 2013 09:29:19 +1200 Subject: [PATCH 002/238] Add another svn auth failed string to check (older svn server version) --- src/Composer/Util/Svn.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Composer/Util/Svn.php b/src/Composer/Util/Svn.php index fcfac6d7e..c61c55584 100644 --- a/src/Composer/Util/Svn.php +++ b/src/Composer/Util/Svn.php @@ -108,6 +108,7 @@ class Svn // the error is not auth-related if (false === stripos($output, 'Could not authenticate to server:') + && false === stripos($output, 'authorization failed') && false === stripos($output, 'svn: E170001:')) { throw new \RuntimeException($output); } From 6aefe6d8ada4488aa2519f84049f745f893bf760 Mon Sep 17 00:00:00 2001 From: jonathan bensaid Date: Fri, 23 Aug 2013 12:09:46 +0300 Subject: [PATCH 003/238] Describe stability flags more consistently --- doc/04-schema.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/doc/04-schema.md b/doc/04-schema.md index dc8360cd7..7b8ef5558 100644 --- a/doc/04-schema.md +++ b/doc/04-schema.md @@ -263,7 +263,7 @@ All links are optional fields. These allow you to further restrict or expand the stability of a package beyond the scope of the [minimum-stability](#minimum-stability) setting. You can apply them to a constraint, or just apply them to an empty constraint if you want to -allow unstable packages of a dependency's dependency for example. +allow unstable packages of a dependency for example. Example: @@ -274,6 +274,18 @@ Example: } } +If one of your dependencies has a dependency on an unstable package you need to +explicitly require it as well, along with its sufficient stability flag. + +Example: + + { + "require": { + "doctrine/doctrine-fixtures-bundle": "dev-master", + "doctrine/data-fixtures": "@dev" + } + } + `require` and `require-dev` additionally support explicit references (i.e. commit) for dev versions to make sure they are locked to a given state, even when you run update. These only work if you explicitly require a dev version From 61c0127f05a3795861afa10102a9b7dc46725cea Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 23 Aug 2013 11:59:26 +0200 Subject: [PATCH 004/238] Fix build --- .../Test/Fixtures/functional/create-project-command.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Composer/Test/Fixtures/functional/create-project-command.test b/tests/Composer/Test/Fixtures/functional/create-project-command.test index f5d330912..2e4b2762a 100644 --- a/tests/Composer/Test/Fixtures/functional/create-project-command.test +++ b/tests/Composer/Test/Fixtures/functional/create-project-command.test @@ -3,7 +3,7 @@ create-project seld/jsonlint %testDir% 1.0.0 --prefer-source -n --EXPECT-- Installing seld/jsonlint (1.0.0) - Installing seld/jsonlint (1.0.0) - Cloning 1.0.0 + Cloning 3b4bc2a96ff5d3fe6866bfe9dd0c845246705791 Created project in %testDir% Loading composer repositories with package information From 6eee550c2f51b26eb31b5a843dbf0b42254b674b Mon Sep 17 00:00:00 2001 From: David Stoline Date: Fri, 23 Aug 2013 10:59:43 -0400 Subject: [PATCH 005/238] Update help docs for the global command I noticed that COMPOSER_HOME/vendor/bin was wrong. Correcting. --- src/Composer/Command/GlobalCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Command/GlobalCommand.php b/src/Composer/Command/GlobalCommand.php index d37958939..46019f1c3 100644 --- a/src/Composer/Command/GlobalCommand.php +++ b/src/Composer/Command/GlobalCommand.php @@ -38,7 +38,7 @@ Use this command as a wrapper to run other Composer commands within the global context of COMPOSER_HOME. You can use this to install CLI utilities globally, all you need -is to add the COMPOSER_HOME/vendor/bin dir to your PATH env var. +is to add the COMPOSER_HOME/bin dir to your PATH env var. COMPOSER_HOME is c:\Users\\AppData\Roaming\Composer on Windows and /home//.composer on unix systems. From 54a74e81d5a99bc6597339f60e6e3af6a6eb9fe4 Mon Sep 17 00:00:00 2001 From: David Stoline Date: Fri, 23 Aug 2013 12:02:35 -0400 Subject: [PATCH 006/238] Add a note about customizations --- src/Composer/Command/GlobalCommand.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Composer/Command/GlobalCommand.php b/src/Composer/Command/GlobalCommand.php index 46019f1c3..2b3b87db5 100644 --- a/src/Composer/Command/GlobalCommand.php +++ b/src/Composer/Command/GlobalCommand.php @@ -38,11 +38,14 @@ Use this command as a wrapper to run other Composer commands within the global context of COMPOSER_HOME. You can use this to install CLI utilities globally, all you need -is to add the COMPOSER_HOME/bin dir to your PATH env var. +is to add the COMPOSER_HOME/vendor/bin dir to your PATH env var. COMPOSER_HOME is c:\Users\\AppData\Roaming\Composer on Windows and /home//.composer on unix systems. +Note: This path may vary depending on customizations to bin-dir in +composer.json or the environmental variable COMPOSER_BIN_DIR. + EOT ) ; From c2dc433fa4ec38a036bd6ffc88839b29a98335ab Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 26 Aug 2013 12:03:32 +0200 Subject: [PATCH 007/238] Improve global command to support short command resolution --- src/Composer/Command/GlobalCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Command/GlobalCommand.php b/src/Composer/Command/GlobalCommand.php index d37958939..89a7c701f 100644 --- a/src/Composer/Command/GlobalCommand.php +++ b/src/Composer/Command/GlobalCommand.php @@ -74,6 +74,6 @@ EOT // create new input without "global" command prefix $input = new StringInput(preg_replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', $input->__toString(), 1)); - return $this->getApplication()->get($args[1])->run($input, $output); + return $this->getApplication()->run($input, $output); } } From 51ea1f03f9088095fd1192278fd67a5fdf8eb5ab Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 26 Aug 2013 13:29:47 +0200 Subject: [PATCH 008/238] Validate constraints in require command, fixes #2197 --- src/Composer/Command/RequireCommand.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Composer/Command/RequireCommand.php b/src/Composer/Command/RequireCommand.php index f47445a4e..fb4f9a9b1 100644 --- a/src/Composer/Command/RequireCommand.php +++ b/src/Composer/Command/RequireCommand.php @@ -20,6 +20,7 @@ use Composer\Factory; use Composer\Installer; use Composer\Json\JsonFile; use Composer\Json\JsonManipulator; +use Composer\Package\Version\VersionParser; /** * @author Jérémy Romey @@ -80,6 +81,12 @@ EOT $baseRequirements = array_key_exists($requireKey, $composer) ? $composer[$requireKey] : array(); $requirements = $this->formatRequirements($requirements); + // validate requirements format + $versionParser = new VersionParser(); + foreach ($requirements as $constraint) { + $versionParser->parseConstraints($constraint); + } + if (!$this->updateFileCleanly($json, $baseRequirements, $requirements, $requireKey)) { foreach ($requirements as $package => $version) { $baseRequirements[$package] = $version; From 0299041ee25fc969fbd7f3de4ef8411a53b82761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Grabovsk=C3=BD?= Date: Tue, 27 Aug 2013 15:21:57 +0200 Subject: [PATCH 009/238] Better wording in a note --- doc/02-libraries.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/02-libraries.md b/doc/02-libraries.md index a2cee3a97..3c6323e9c 100644 --- a/doc/02-libraries.md +++ b/doc/02-libraries.md @@ -98,7 +98,9 @@ Here are some examples of version branch names: 1.0 (equals 1.0.x) 1.1.x -> **Note:** When you install a dev version, it will install it from source. +> **Note:** When you install a development version, it will be automatically +> pulled from its `source`. See the [`install`](03-cli.md#install) command +> for more details. ### Aliases From 046d55e8868af2c93ae7c0700edfc1e26820602b Mon Sep 17 00:00:00 2001 From: Firehed Date: Tue, 27 Aug 2013 16:08:38 -0700 Subject: [PATCH 010/238] Change 'generated' notice to @phpdoc-style annotation While it isn't an official part of the syntax, it integrates better with other tools that ignore diffs on generated code. --- src/Composer/Autoload/AutoloadGenerator.php | 12 ++++++------ .../Test/Autoload/AutoloadGeneratorTest.php | 16 ++++++++-------- .../Test/Autoload/Fixtures/autoload_classmap.php | 2 +- .../Autoload/Fixtures/autoload_classmap2.php | 2 +- .../Autoload/Fixtures/autoload_classmap3.php | 2 +- .../Autoload/Fixtures/autoload_classmap4.php | 2 +- .../Autoload/Fixtures/autoload_classmap5.php | 2 +- .../Autoload/Fixtures/autoload_classmap6.php | 2 +- .../Test/Autoload/Fixtures/autoload_files.php | 2 +- .../autoload_files_files_by_dependency.php | 2 +- .../Fixtures/autoload_files_functions.php | 2 +- .../Fixtures/autoload_files_target_dir.php | 2 +- .../Autoload/Fixtures/autoload_functions.php | 2 +- .../autoload_functions_by_dependency.php | 2 +- .../Test/Autoload/Fixtures/autoload_main.php | 2 +- .../Test/Autoload/Fixtures/autoload_main2.php | 2 +- .../Test/Autoload/Fixtures/autoload_main3.php | 2 +- .../autoload_real_files_by_dependency.php | 2 +- .../Fixtures/autoload_real_functions.php | 2 +- .../Fixtures/autoload_real_include_path.php | 2 +- .../Fixtures/autoload_real_target_dir.php | 2 +- .../Autoload/Fixtures/autoload_target_dir.php | 2 +- .../Test/Autoload/Fixtures/autoload_vendors.php | 2 +- .../Test/Autoload/Fixtures/include_paths.php | 2 +- 24 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index b0fe9b232..8d6dcb793 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -59,7 +59,7 @@ class AutoloadGenerator $namespacesFile = << Date: Fri, 30 Aug 2013 11:46:39 +0100 Subject: [PATCH 011/238] Fix parse error thrown in PHP5.5+ When running composer update the file generated by AutoloadGenerator was not able to be parsed by php due to a require statement inside the foreach loop. The fix is to make the statement work the same as the autoload_namespaces.php require is done. Issue occured using the following php versions PHP 5.5.1-2+debphp.org~precise+2 PHP 5.5.3-1+debphp.org~precise+2 --- src/Composer/Autoload/AutoloadGenerator.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index b0fe9b232..512b25f84 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -460,9 +460,10 @@ REGISTER_AUTOLOAD; REGISTER_LOADER; if ($useIncludeFiles) { - $file .= << Date: Tue, 13 Aug 2013 13:25:21 +0200 Subject: [PATCH 012/238] As preparation for composer plugins, rename custom installers to plugins --- doc/04-schema.md | 2 +- res/composer-schema.json | 4 ++-- src/Composer/Command/CreateProjectCommand.php | 18 +++++++++--------- src/Composer/Command/InstallCommand.php | 6 +++--- src/Composer/Command/UpdateCommand.php | 6 +++--- src/Composer/Factory.php | 2 +- src/Composer/Installer.php | 14 +++++++------- src/Composer/Installer/InstallationManager.php | 8 ++++---- ...tallerInstaller.php => PluginInstaller.php} | 11 +++++++---- ...t.test => plugins-are-installed-first.test} | 4 ++-- .../Fixtures/installer-v1/composer.json | 2 +- .../Fixtures/installer-v2/composer.json | 2 +- .../Fixtures/installer-v3/composer.json | 2 +- .../Fixtures/installer-v4/composer.json | 2 +- ...stallerTest.php => PluginInstallerTest.php} | 14 +++++++------- 15 files changed, 50 insertions(+), 47 deletions(-) rename src/Composer/Installer/{InstallerInstaller.php => PluginInstaller.php} (86%) rename tests/Composer/Test/Fixtures/installer/{custom-installers-are-installed-first.test => plugins-are-installed-first.test} (90%) rename tests/Composer/Test/Installer/{InstallerInstallerTest.php => PluginInstallerTest.php} (92%) diff --git a/doc/04-schema.md b/doc/04-schema.md index 7b8ef5558..7d2775af1 100644 --- a/doc/04-schema.md +++ b/doc/04-schema.md @@ -99,7 +99,7 @@ Out of the box, composer supports three types: their installation, but contains no files and will not write anything to the filesystem. As such, it does not require a dist or source key to be installable. -- **composer-installer:** A package of type `composer-installer` provides an +- **composer-plugin:** A package of type `composer-plugin` may provide an installer for other packages that have a custom type. Read more in the [dedicated article](articles/custom-installers.md). diff --git a/res/composer-schema.json b/res/composer-schema.json index 328794ef8..eef9aa3d6 100644 --- a/res/composer-schema.json +++ b/res/composer-schema.json @@ -9,7 +9,7 @@ "required": true }, "type": { - "description": "Package type, either 'library' for common packages, 'composer-installer' for custom installers, 'metapackage' for empty packages, or a custom type ([a-z0-9-]+) defined by whatever project this package applies to.", + "description": "Package type, either 'library' for common packages, 'composer-plugin' for plugins, 'metapackage' for empty packages, or a custom type ([a-z0-9-]+) defined by whatever project this package applies to.", "type": "string" }, "target-dir": { @@ -180,7 +180,7 @@ }, "extra": { "type": ["object", "array"], - "description": "Arbitrary extra data that can be used by custom installers, for example, package of type composer-installer must have a 'class' key defining the installer class name.", + "description": "Arbitrary extra data that can be used by plugins, for example, package of type composer-plugin may have a 'class' key defining an installer class name.", "additionalProperties": true }, "autoload": { diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index 222add8e5..c38f0bec4 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -62,7 +62,7 @@ class CreateProjectCommand extends Command new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'Pick a different repository url to look for the package.'), new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'), - new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'Whether to disable custom installers.'), + new InputOption('no-plugins', null, InputOption::VALUE_NONE, 'Whether to disable plugins.'), new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deletion vcs folder.'), @@ -127,19 +127,19 @@ EOT $preferDist, !$input->getOption('no-dev'), $input->getOption('repository-url'), - $input->getOption('no-custom-installers'), + $input->getOption('no-plugins'), $input->getOption('no-scripts'), $input->getOption('keep-vcs'), $input->getOption('no-progress') ); } - public function installProject(IOInterface $io, $config, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repositoryUrl = null, $disableCustomInstallers = false, $noScripts = false, $keepVcs = false, $noProgress = false) + public function installProject(IOInterface $io, $config, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repositoryUrl = null, $disablePlugins = false, $noScripts = false, $keepVcs = false, $noProgress = false) { $oldCwd = getcwd(); if ($packageName !== null) { - $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repositoryUrl, $disableCustomInstallers, $noScripts, $keepVcs, $noProgress); + $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repositoryUrl, $disablePlugins, $noScripts, $keepVcs, $noProgress); } else { $installedFromVcs = false; } @@ -158,8 +158,8 @@ EOT ->setDevMode($installDevPackages) ->setRunScripts( ! $noScripts); - if ($disableCustomInstallers) { - $installer->disableCustomInstallers(); + if ($disablePlugins) { + $installer->disablePlugins(); } if (!$installer->run()) { @@ -226,7 +226,7 @@ EOT return 0; } - protected function installRootPackage(IOInterface $io, $config, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repositoryUrl = null, $disableCustomInstallers = false, $noScripts = false, $keepVcs = false, $noProgress = false) + protected function installRootPackage(IOInterface $io, $config, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repositoryUrl = null, $disablePlugins = false, $noScripts = false, $keepVcs = false, $noProgress = false) { $stability = strtolower($stability); if ($stability === 'rc') { @@ -285,8 +285,8 @@ EOT $io->write('Installing ' . $package->getName() . ' (' . VersionParser::formatVersion($package, false) . ')'); - if ($disableCustomInstallers) { - $io->write('Custom installers have been disabled.'); + if ($disablePlugins) { + $io->write('Plugins have been disabled.'); } if (0 === strpos($package->getPrettyVersion(), 'dev-') && in_array($package->getSourceType(), array('git', 'hg'))) { diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index 05d3f37d9..90ad2810f 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -35,7 +35,7 @@ class InstallCommand extends Command new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'), new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'), - new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'Disables all custom installers.'), + new InputOption('no-plugins', null, InputOption::VALUE_NONE, 'Disables all plugins.'), new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), @@ -90,8 +90,8 @@ EOT ->setOptimizeAutoloader($input->getOption('optimize-autoloader')) ; - if ($input->getOption('no-custom-installers')) { - $install->disableCustomInstallers(); + if ($input->getOption('no-plugins')) { + $install->disablePlugins(); } return $install->run() ? 0 : 1; diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index dc103cf99..8d3133b83 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -36,7 +36,7 @@ class UpdateCommand extends Command new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'), new InputOption('lock', null, InputOption::VALUE_NONE, 'Only updates the lock file hash to suppress warning about the lock file being out of date.'), - new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'Disables all custom installers.'), + new InputOption('no-plugins', null, InputOption::VALUE_NONE, 'Disables all plugins.'), new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), @@ -96,8 +96,8 @@ EOT ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $input->getArgument('packages')) ; - if ($input->getOption('no-custom-installers')) { - $install->disableCustomInstallers(); + if ($input->getOption('no-plugins')) { + $install->disablePlugins(); } return $install->run() ? 0 : 1; diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 82c5084c2..749e1ad88 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -370,7 +370,7 @@ class Factory { $im->addInstaller(new Installer\LibraryInstaller($io, $composer, null)); $im->addInstaller(new Installer\PearInstaller($io, $composer, 'pear-library')); - $im->addInstaller(new Installer\InstallerInstaller($io, $composer)); + $im->addInstaller(new Installer\PluginInstaller($io, $composer)); $im->addInstaller(new Installer\MetapackageInstaller($io)); } diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 8f424cc39..1d3ec9255 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -461,7 +461,7 @@ class Installer $this->io->write('Nothing to install or update'); } - $operations = $this->moveCustomInstallersToFront($operations); + $operations = $this->movePluginsToFront($operations); foreach ($operations as $operation) { // collect suggestions @@ -540,7 +540,7 @@ class Installer /** - * Workaround: if your packages depend on custom installers, we must be sure + * Workaround: if your packages depend on plugins, we must be sure * that those are installed / updated first; else it would lead to packages * being installed multiple times in different folders, when running Composer * twice. @@ -552,7 +552,7 @@ class Installer * @param OperationInterface[] $operations * @return OperationInterface[] reordered operation list */ - private function moveCustomInstallersToFront(array $operations) + private function movePluginsToFront(array $operations) { $installerOps = array(); foreach ($operations as $idx => $op) { @@ -564,7 +564,7 @@ class Installer continue; } - if ($package->getRequires() === array() && $package->getType() === 'composer-installer') { + if ($package->getRequires() === array() && ($package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer')) { $installerOps[] = $op; unset($operations[$idx]); } @@ -1055,7 +1055,7 @@ class Installer } /** - * Disables custom installers. + * Disables plugins. * * Call this if you want to ensure that third-party code never gets * executed. The default is to automatically install, and execute @@ -1063,9 +1063,9 @@ class Installer * * @return Installer */ - public function disableCustomInstallers() + public function disablePlugins() { - $this->installationManager->disableCustomInstallers(); + $this->installationManager->disablePlugins(); return $this; } diff --git a/src/Composer/Installer/InstallationManager.php b/src/Composer/Installer/InstallationManager.php index 406ee1166..b26273847 100644 --- a/src/Composer/Installer/InstallationManager.php +++ b/src/Composer/Installer/InstallationManager.php @@ -66,16 +66,16 @@ class InstallationManager } /** - * Disables custom installers. + * Disables plugins. * - * We prevent any custom installers from being instantiated by simply + * We prevent any plugins from being instantiated by simply * deactivating the installer for them. This ensure that no third-party * code is ever executed. */ - public function disableCustomInstallers() + public function disablePlugins() { foreach ($this->installers as $i => $installer) { - if (!$installer instanceof InstallerInstaller) { + if (!$installer instanceof PluginInstaller) { continue; } diff --git a/src/Composer/Installer/InstallerInstaller.php b/src/Composer/Installer/PluginInstaller.php similarity index 86% rename from src/Composer/Installer/InstallerInstaller.php rename to src/Composer/Installer/PluginInstaller.php index a833b68d2..9be0a9155 100644 --- a/src/Composer/Installer/InstallerInstaller.php +++ b/src/Composer/Installer/PluginInstaller.php @@ -23,7 +23,7 @@ use Composer\Package\PackageInterface; * * @author Jordi Boggiano */ -class InstallerInstaller extends LibraryInstaller +class PluginInstaller extends LibraryInstaller { private $installationManager; private static $classCounter = 0; @@ -37,7 +37,7 @@ class InstallerInstaller extends LibraryInstaller */ public function __construct(IOInterface $io, Composer $composer, $type = 'library') { - parent::__construct($io, $composer, 'composer-installer'); + parent::__construct($io, $composer, $type); $this->installationManager = $composer->getInstallationManager(); $repo = $composer->getRepositoryManager()->getLocalRepository(); @@ -45,6 +45,9 @@ class InstallerInstaller extends LibraryInstaller if ('composer-installer' === $package->getType()) { $this->registerInstaller($package); } + if ('composer-plugin' === $package->getType()) { + $this->registerInstaller($package); + } } } @@ -55,7 +58,7 @@ class InstallerInstaller extends LibraryInstaller { $extra = $package->getExtra(); if (empty($extra['class'])) { - throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-installer packages should have a class defined in their extra key to be usable.'); + throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.'); } parent::install($repo, $package); @@ -69,7 +72,7 @@ class InstallerInstaller extends LibraryInstaller { $extra = $target->getExtra(); if (empty($extra['class'])) { - throw new \UnexpectedValueException('Error while installing '.$target->getPrettyName().', composer-installer packages should have a class defined in their extra key to be usable.'); + throw new \UnexpectedValueException('Error while installing '.$target->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.'); } parent::update($repo, $initial, $target); diff --git a/tests/Composer/Test/Fixtures/installer/custom-installers-are-installed-first.test b/tests/Composer/Test/Fixtures/installer/plugins-are-installed-first.test similarity index 90% rename from tests/Composer/Test/Fixtures/installer/custom-installers-are-installed-first.test rename to tests/Composer/Test/Fixtures/installer/plugins-are-installed-first.test index dd9d26d98..c57a36d35 100644 --- a/tests/Composer/Test/Fixtures/installer/custom-installers-are-installed-first.test +++ b/tests/Composer/Test/Fixtures/installer/plugins-are-installed-first.test @@ -8,8 +8,8 @@ Composer installers are installed first if they have no requirements "package": [ { "name": "pkg", "version": "1.0.0" }, { "name": "pkg2", "version": "1.0.0" }, - { "name": "inst", "version": "1.0.0", "type": "composer-installer" }, - { "name": "inst2", "version": "1.0.0", "type": "composer-installer", "require": { "pkg2": "*" } } + { "name": "inst", "version": "1.0.0", "type": "composer-plugin" }, + { "name": "inst2", "version": "1.0.0", "type": "composer-plugin", "require": { "pkg2": "*" } } ] } ], diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v1/composer.json b/tests/Composer/Test/Installer/Fixtures/installer-v1/composer.json index 2230f4c4c..3ec38c60e 100644 --- a/tests/Composer/Test/Installer/Fixtures/installer-v1/composer.json +++ b/tests/Composer/Test/Installer/Fixtures/installer-v1/composer.json @@ -1,7 +1,7 @@ { "name": "", "version": "1.0.0", - "type": "composer-installer", + "type": "composer-plugin", "autoload": { "psr-0": { "Installer": "" } }, "extra": { "class": "Installer\\Custom" diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v2/composer.json b/tests/Composer/Test/Installer/Fixtures/installer-v2/composer.json index 82daa3d43..974c82b54 100644 --- a/tests/Composer/Test/Installer/Fixtures/installer-v2/composer.json +++ b/tests/Composer/Test/Installer/Fixtures/installer-v2/composer.json @@ -1,7 +1,7 @@ { "name": "", "version": "2.0.0", - "type": "composer-installer", + "type": "composer-plugin", "autoload": { "psr-0": { "Installer": "" } }, "extra": { "class": "Installer\\Custom2" diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v3/composer.json b/tests/Composer/Test/Installer/Fixtures/installer-v3/composer.json index 84c1d8c00..ef2cc278b 100644 --- a/tests/Composer/Test/Installer/Fixtures/installer-v3/composer.json +++ b/tests/Composer/Test/Installer/Fixtures/installer-v3/composer.json @@ -1,7 +1,7 @@ { "name": "", "version": "3.0.0", - "type": "composer-installer", + "type": "composer-plugin", "autoload": { "psr-0": { "Installer": "" } }, "extra": { "class": "Installer\\Custom2" diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v4/composer.json b/tests/Composer/Test/Installer/Fixtures/installer-v4/composer.json index f29258bc6..5ff8d7cb6 100644 --- a/tests/Composer/Test/Installer/Fixtures/installer-v4/composer.json +++ b/tests/Composer/Test/Installer/Fixtures/installer-v4/composer.json @@ -1,7 +1,7 @@ { "name": "", "version": "4.0.0", - "type": "composer-installer", + "type": "composer-plugin", "autoload": { "psr-0": { "Installer": "" } }, "extra": { "class": [ diff --git a/tests/Composer/Test/Installer/InstallerInstallerTest.php b/tests/Composer/Test/Installer/PluginInstallerTest.php similarity index 92% rename from tests/Composer/Test/Installer/InstallerInstallerTest.php rename to tests/Composer/Test/Installer/PluginInstallerTest.php index c61182389..217edb999 100644 --- a/tests/Composer/Test/Installer/InstallerInstallerTest.php +++ b/tests/Composer/Test/Installer/PluginInstallerTest.php @@ -14,13 +14,13 @@ namespace Composer\Test\Installer; use Composer\Composer; use Composer\Config; -use Composer\Installer\InstallerInstaller; +use Composer\Installer\PluginInstaller; use Composer\Package\Loader\JsonLoader; use Composer\Package\Loader\ArrayLoader; use Composer\Package\PackageInterface; use Composer\Autoload\AutoloadGenerator; -class InstallerInstallerTest extends \PHPUnit_Framework_TestCase +class PluginInstallerTest extends \PHPUnit_Framework_TestCase { protected $composer; protected $packages; @@ -81,7 +81,7 @@ class InstallerInstallerTest extends \PHPUnit_Framework_TestCase ->expects($this->once()) ->method('getPackages') ->will($this->returnValue(array())); - $installer = new InstallerInstallerMock($this->io, $this->composer); + $installer = new PluginInstallerMock($this->io, $this->composer); $test = $this; $this->im @@ -101,7 +101,7 @@ class InstallerInstallerTest extends \PHPUnit_Framework_TestCase ->method('getPackages') ->will($this->returnValue(array())); - $installer = new InstallerInstallerMock($this->io, $this->composer); + $installer = new PluginInstallerMock($this->io, $this->composer); $test = $this; @@ -134,7 +134,7 @@ class InstallerInstallerTest extends \PHPUnit_Framework_TestCase ->expects($this->exactly(2)) ->method('hasPackage') ->will($this->onConsecutiveCalls(true, false)); - $installer = new InstallerInstallerMock($this->io, $this->composer); + $installer = new PluginInstallerMock($this->io, $this->composer); $test = $this; $this->im @@ -157,7 +157,7 @@ class InstallerInstallerTest extends \PHPUnit_Framework_TestCase ->expects($this->exactly(2)) ->method('hasPackage') ->will($this->onConsecutiveCalls(true, false)); - $installer = new InstallerInstallerMock($this->io, $this->composer); + $installer = new PluginInstallerMock($this->io, $this->composer); $test = $this; $this->im @@ -171,7 +171,7 @@ class InstallerInstallerTest extends \PHPUnit_Framework_TestCase } } -class InstallerInstallerMock extends InstallerInstaller +class PluginInstallerMock extends PluginInstaller { public function getInstallPath(PackageInterface $package) { From eb966d347fae748a2571927d40a3273af7a6ac5b Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Tue, 13 Aug 2013 15:55:52 +0200 Subject: [PATCH 013/238] Implement a plugin manager and interface, update installer plugin tests --- src/Composer/Composer.php | 22 ++++++++ src/Composer/Factory.php | 12 +++++ src/Composer/Installer/PluginInstaller.php | 26 ++++++---- src/Composer/Plugin/PluginInterface.php | 30 +++++++++++ src/Composer/Plugin/PluginManager.php | 49 ++++++++++++++++++ .../installer-v1/Installer/Custom.php | 19 ------- .../installer-v1/Installer/Exception.php | 7 --- .../installer-v1/Installer/Plugin.php | 15 ++++++ .../Fixtures/installer-v1/composer.json | 2 +- .../installer-v2/Installer/Custom2.php | 19 ------- .../installer-v2/Installer/Exception.php | 7 --- .../installer-v2/Installer/Plugin2.php | 15 ++++++ .../Fixtures/installer-v2/composer.json | 2 +- .../installer-v3/Installer/Custom2.php | 19 ------- .../installer-v3/Installer/Exception.php | 7 --- .../installer-v3/Installer/Plugin2.php | 15 ++++++ .../Fixtures/installer-v3/composer.json | 2 +- .../installer-v4/Installer/Custom1.php | 20 -------- .../installer-v4/Installer/Custom2.php | 20 -------- .../installer-v4/Installer/Plugin1.php | 16 ++++++ .../installer-v4/Installer/Plugin2.php | 16 ++++++ .../Fixtures/installer-v4/composer.json | 4 +- .../Test/Installer/PluginInstallerTest.php | 50 +++++++++++-------- 23 files changed, 238 insertions(+), 156 deletions(-) create mode 100644 src/Composer/Plugin/PluginInterface.php create mode 100644 src/Composer/Plugin/PluginManager.php delete mode 100644 tests/Composer/Test/Installer/Fixtures/installer-v1/Installer/Custom.php delete mode 100644 tests/Composer/Test/Installer/Fixtures/installer-v1/Installer/Exception.php create mode 100644 tests/Composer/Test/Installer/Fixtures/installer-v1/Installer/Plugin.php delete mode 100644 tests/Composer/Test/Installer/Fixtures/installer-v2/Installer/Custom2.php delete mode 100644 tests/Composer/Test/Installer/Fixtures/installer-v2/Installer/Exception.php create mode 100644 tests/Composer/Test/Installer/Fixtures/installer-v2/Installer/Plugin2.php delete mode 100644 tests/Composer/Test/Installer/Fixtures/installer-v3/Installer/Custom2.php delete mode 100644 tests/Composer/Test/Installer/Fixtures/installer-v3/Installer/Exception.php create mode 100644 tests/Composer/Test/Installer/Fixtures/installer-v3/Installer/Plugin2.php delete mode 100644 tests/Composer/Test/Installer/Fixtures/installer-v4/Installer/Custom1.php delete mode 100644 tests/Composer/Test/Installer/Fixtures/installer-v4/Installer/Custom2.php create mode 100644 tests/Composer/Test/Installer/Fixtures/installer-v4/Installer/Plugin1.php create mode 100644 tests/Composer/Test/Installer/Fixtures/installer-v4/Installer/Plugin2.php diff --git a/src/Composer/Composer.php b/src/Composer/Composer.php index 8c5d0785f..32d48b771 100644 --- a/src/Composer/Composer.php +++ b/src/Composer/Composer.php @@ -16,6 +16,7 @@ use Composer\Package\RootPackageInterface; use Composer\Package\Locker; use Composer\Repository\RepositoryManager; use Composer\Installer\InstallationManager; +use Composer\Plugin\PluginManager; use Composer\Downloader\DownloadManager; use Composer\Script\EventDispatcher; use Composer\Autoload\AutoloadGenerator; @@ -53,6 +54,11 @@ class Composer */ private $installationManager; + /** + * + */ + private $pluginManager; + /** * @var Config */ @@ -165,6 +171,22 @@ class Composer return $this->installationManager; } + /** + * @param Plugin\PluginManager $manager + */ + public function setPluginManager(PluginManager $manager) + { + $this->pluginManager = $manager; + } + + /** + * @return Plugin\PluginManager + */ + public function getPluginManager() + { + return $this->pluginManager; + } + /** * @param Script\EventDispatcher $eventDispatcher */ diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 749e1ad88..1dd612b13 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -264,6 +264,10 @@ class Factory $composer->setLocker($locker); } + $pm = $this->createPluginManager($composer); + + $composer->setPluginManager($pm); + return $composer; } @@ -353,6 +357,14 @@ class Factory return $am; } + /** + * @return Plugin\PluginManager + */ + protected function createPluginManager(Composer $composer) + { + return new Plugin\PluginManager($composer); + } + /** * @return Installer\InstallationManager */ diff --git a/src/Composer/Installer/PluginInstaller.php b/src/Composer/Installer/PluginInstaller.php index 9be0a9155..dfcc97669 100644 --- a/src/Composer/Installer/PluginInstaller.php +++ b/src/Composer/Installer/PluginInstaller.php @@ -29,7 +29,7 @@ class PluginInstaller extends LibraryInstaller private static $classCounter = 0; /** - * Initializes Installer installer. + * Initializes Plugin installer. * * @param IOInterface $io * @param Composer $composer @@ -42,11 +42,8 @@ class PluginInstaller extends LibraryInstaller $repo = $composer->getRepositoryManager()->getLocalRepository(); foreach ($repo->getPackages() as $package) { - if ('composer-installer' === $package->getType()) { - $this->registerInstaller($package); - } - if ('composer-plugin' === $package->getType()) { - $this->registerInstaller($package); + if ('composer-plugin' === $package->getType() || 'composer-installer' === $package->getType()) { + $this->registerPlugin($package); } } } @@ -62,7 +59,7 @@ class PluginInstaller extends LibraryInstaller } parent::install($repo, $package); - $this->registerInstaller($package); + $this->registerPlugin($package); } /** @@ -76,11 +73,13 @@ class PluginInstaller extends LibraryInstaller } parent::update($repo, $initial, $target); - $this->registerInstaller($target); + $this->registerPlugin($target); } - private function registerInstaller(PackageInterface $package) + private function registerPlugin(PackageInterface $package) { + $oldInstallerPlugin = ($package->getType() === 'composer-installer'); + $downloadPath = $this->getInstallPath($package); $extra = $package->getExtra(); @@ -100,8 +99,13 @@ class PluginInstaller extends LibraryInstaller self::$classCounter++; } - $installer = new $class($this->io, $this->composer); - $this->installationManager->addInstaller($installer); + $plugin = new $class($this->io, $this->composer); + + if ($oldInstallerPlugin) { + $this->installationManager->addInstaller($installer); + } else { + $this->composer->getPluginManager()->addPlugin($plugin); + } } } } diff --git a/src/Composer/Plugin/PluginInterface.php b/src/Composer/Plugin/PluginInterface.php new file mode 100644 index 000000000..ebbbe0026 --- /dev/null +++ b/src/Composer/Plugin/PluginInterface.php @@ -0,0 +1,30 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Plugin; + +use Composer\Composer; + +/** + * Plugin interface + * + * @author Nils Adermann + */ +interface PluginInterface +{ + /** + * Apply plugin modifications to the passed in composer object + * + * @param Composer $composer + */ + public function activate(Composer $composer); +} diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php new file mode 100644 index 000000000..aa08de2ef --- /dev/null +++ b/src/Composer/Plugin/PluginManager.php @@ -0,0 +1,49 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Plugin; + +use Composer\Composer; +use Composer\Package\PackageInterface; + +/** + * Plugin manager + * + * @author Nils Adermann + */ +class PluginManager +{ + protected $composer; + + protected $plugins = array(); + + /** + * Initializes plugin manager + * + * @param Composer $composer + */ + public function __construct(Composer $composer) + { + $this->composer = $composer; + } + + /** + * Adds plugin + * + * @param PluginInterface $plugin plugin instance + */ + public function addPlugin(PluginInterface $plugin) + { + $this->plugins[] = $plugin; + $plugin->activate($this->composer); + } +} diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v1/Installer/Custom.php b/tests/Composer/Test/Installer/Fixtures/installer-v1/Installer/Custom.php deleted file mode 100644 index bfad4a88a..000000000 --- a/tests/Composer/Test/Installer/Fixtures/installer-v1/Installer/Custom.php +++ /dev/null @@ -1,19 +0,0 @@ -disableOriginalConstructor() ->getMock(); + $this->pm = $this->getMockBuilder('Composer\Plugin\PluginManager') + ->disableOriginalConstructor() + ->getMock(); + $this->repository = $this->getMock('Composer\Repository\InstalledRepositoryInterface'); $rm = $this->getMockBuilder('Composer\Repository\RepositoryManager') @@ -64,6 +69,7 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase $this->composer->setConfig($config); $this->composer->setDownloadManager($dm); $this->composer->setInstallationManager($this->im); + $this->composer->setPluginManager($this->pm); $this->composer->setRepositoryManager($rm); $this->composer->setAutoloadGenerator($this->autoloadGenerator); @@ -75,7 +81,7 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase )); } - public function testInstallNewInstaller() + public function testInstallNewPlugin() { $this->repository ->expects($this->once()) @@ -84,9 +90,9 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase $installer = new PluginInstallerMock($this->io, $this->composer); $test = $this; - $this->im + $this->pm ->expects($this->once()) - ->method('addInstaller') + ->method('addPlugin') ->will($this->returnCallback(function ($installer) use ($test) { $test->assertEquals('installer-v1', $installer->version); })); @@ -94,7 +100,7 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase $installer->install($this->repository, $this->packages[0]); } - public function testInstallMultipleInstallers() + public function testInstallMultiplePlugins() { $this->repository ->expects($this->once()) @@ -105,20 +111,20 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase $test = $this; - $this->im + $this->pm ->expects($this->at(0)) - ->method('addInstaller') - ->will($this->returnCallback(function ($installer) use ($test) { - $test->assertEquals('custom1', $installer->name); - $test->assertEquals('installer-v4', $installer->version); + ->method('addPlugin') + ->will($this->returnCallback(function ($plugin) use ($test) { + $test->assertEquals('plugin1', $plugin->name); + $test->assertEquals('installer-v4', $plugin->version); })); - $this->im + $this->pm ->expects($this->at(1)) - ->method('addInstaller') - ->will($this->returnCallback(function ($installer) use ($test) { - $test->assertEquals('custom2', $installer->name); - $test->assertEquals('installer-v4', $installer->version); + ->method('addPlugin') + ->will($this->returnCallback(function ($plugin) use ($test) { + $test->assertEquals('plugin2', $plugin->name); + $test->assertEquals('installer-v4', $plugin->version); })); $installer->install($this->repository, $this->packages[3]); @@ -137,11 +143,11 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase $installer = new PluginInstallerMock($this->io, $this->composer); $test = $this; - $this->im + $this->pm ->expects($this->once()) - ->method('addInstaller') - ->will($this->returnCallback(function ($installer) use ($test) { - $test->assertEquals('installer-v2', $installer->version); + ->method('addPlugin') + ->will($this->returnCallback(function ($plugin) use ($test) { + $test->assertEquals('installer-v2', $plugin->version); })); $installer->update($this->repository, $this->packages[0], $this->packages[1]); @@ -160,11 +166,11 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase $installer = new PluginInstallerMock($this->io, $this->composer); $test = $this; - $this->im + $this->pm ->expects($this->once()) - ->method('addInstaller') - ->will($this->returnCallback(function ($installer) use ($test) { - $test->assertEquals('installer-v3', $installer->version); + ->method('addPlugin') + ->will($this->returnCallback(function ($plugin) use ($test) { + $test->assertEquals('installer-v3', $plugin->version); })); $installer->update($this->repository, $this->packages[1], $this->packages[2]); From 3e41977be7f1a6775b5f49f73c4c319c1c813057 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Tue, 13 Aug 2013 15:59:26 +0200 Subject: [PATCH 014/238] Plugin tests are no longer strictly installer tests --- .../Fixtures/plugin-v1}/Installer/Plugin.php | 0 .../installer-v1 => Plugin/Fixtures/plugin-v1}/composer.json | 0 .../Fixtures/plugin-v2}/Installer/Plugin2.php | 0 .../installer-v2 => Plugin/Fixtures/plugin-v2}/composer.json | 0 .../Fixtures/plugin-v3}/Installer/Plugin2.php | 0 .../installer-v3 => Plugin/Fixtures/plugin-v3}/composer.json | 0 .../Fixtures/plugin-v4}/Installer/Plugin1.php | 0 .../Fixtures/plugin-v4}/Installer/Plugin2.php | 0 .../installer-v4 => Plugin/Fixtures/plugin-v4}/composer.json | 0 .../Test/{Installer => Plugin}/PluginInstallerTest.php | 4 ++-- 10 files changed, 2 insertions(+), 2 deletions(-) rename tests/Composer/Test/{Installer/Fixtures/installer-v1 => Plugin/Fixtures/plugin-v1}/Installer/Plugin.php (100%) rename tests/Composer/Test/{Installer/Fixtures/installer-v1 => Plugin/Fixtures/plugin-v1}/composer.json (100%) rename tests/Composer/Test/{Installer/Fixtures/installer-v2 => Plugin/Fixtures/plugin-v2}/Installer/Plugin2.php (100%) rename tests/Composer/Test/{Installer/Fixtures/installer-v2 => Plugin/Fixtures/plugin-v2}/composer.json (100%) rename tests/Composer/Test/{Installer/Fixtures/installer-v3 => Plugin/Fixtures/plugin-v3}/Installer/Plugin2.php (100%) rename tests/Composer/Test/{Installer/Fixtures/installer-v3 => Plugin/Fixtures/plugin-v3}/composer.json (100%) rename tests/Composer/Test/{Installer/Fixtures/installer-v4 => Plugin/Fixtures/plugin-v4}/Installer/Plugin1.php (100%) rename tests/Composer/Test/{Installer/Fixtures/installer-v4 => Plugin/Fixtures/plugin-v4}/Installer/Plugin2.php (100%) rename tests/Composer/Test/{Installer/Fixtures/installer-v4 => Plugin/Fixtures/plugin-v4}/composer.json (100%) rename tests/Composer/Test/{Installer => Plugin}/PluginInstallerTest.php (98%) diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v1/Installer/Plugin.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v1/Installer/Plugin.php similarity index 100% rename from tests/Composer/Test/Installer/Fixtures/installer-v1/Installer/Plugin.php rename to tests/Composer/Test/Plugin/Fixtures/plugin-v1/Installer/Plugin.php diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v1/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v1/composer.json similarity index 100% rename from tests/Composer/Test/Installer/Fixtures/installer-v1/composer.json rename to tests/Composer/Test/Plugin/Fixtures/plugin-v1/composer.json diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v2/Installer/Plugin2.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v2/Installer/Plugin2.php similarity index 100% rename from tests/Composer/Test/Installer/Fixtures/installer-v2/Installer/Plugin2.php rename to tests/Composer/Test/Plugin/Fixtures/plugin-v2/Installer/Plugin2.php diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v2/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v2/composer.json similarity index 100% rename from tests/Composer/Test/Installer/Fixtures/installer-v2/composer.json rename to tests/Composer/Test/Plugin/Fixtures/plugin-v2/composer.json diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v3/Installer/Plugin2.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v3/Installer/Plugin2.php similarity index 100% rename from tests/Composer/Test/Installer/Fixtures/installer-v3/Installer/Plugin2.php rename to tests/Composer/Test/Plugin/Fixtures/plugin-v3/Installer/Plugin2.php diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v3/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v3/composer.json similarity index 100% rename from tests/Composer/Test/Installer/Fixtures/installer-v3/composer.json rename to tests/Composer/Test/Plugin/Fixtures/plugin-v3/composer.json diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v4/Installer/Plugin1.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin1.php similarity index 100% rename from tests/Composer/Test/Installer/Fixtures/installer-v4/Installer/Plugin1.php rename to tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin1.php diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v4/Installer/Plugin2.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin2.php similarity index 100% rename from tests/Composer/Test/Installer/Fixtures/installer-v4/Installer/Plugin2.php rename to tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin2.php diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v4/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v4/composer.json similarity index 100% rename from tests/Composer/Test/Installer/Fixtures/installer-v4/composer.json rename to tests/Composer/Test/Plugin/Fixtures/plugin-v4/composer.json diff --git a/tests/Composer/Test/Installer/PluginInstallerTest.php b/tests/Composer/Test/Plugin/PluginInstallerTest.php similarity index 98% rename from tests/Composer/Test/Installer/PluginInstallerTest.php rename to tests/Composer/Test/Plugin/PluginInstallerTest.php index d9e1133d6..28a9a768a 100644 --- a/tests/Composer/Test/Installer/PluginInstallerTest.php +++ b/tests/Composer/Test/Plugin/PluginInstallerTest.php @@ -35,7 +35,7 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase $loader = new JsonLoader(new ArrayLoader()); $this->packages = array(); for ($i = 1; $i <= 4; $i++) { - $this->packages[] = $loader->load(__DIR__.'/Fixtures/installer-v'.$i.'/composer.json'); + $this->packages[] = $loader->load(__DIR__.'/Fixtures/plugin-v'.$i.'/composer.json'); } $dm = $this->getMockBuilder('Composer\Downloader\DownloadManager') @@ -183,6 +183,6 @@ class PluginInstallerMock extends PluginInstaller { $version = $package->getVersion(); - return __DIR__.'/Fixtures/installer-v'.$version[0].'/'; + return __DIR__.'/Fixtures/plugin-v'.$version[0].'/'; } } From 2f43e9aefb6912610d6279c4c7f623c8f043164e Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Tue, 13 Aug 2013 19:13:17 +0200 Subject: [PATCH 015/238] Load installed plugins at appropriate time and adapt tests accordingly --- src/Composer/Composer.php | 2 +- src/Composer/Factory.php | 11 ++- src/Composer/Installer/PluginInstaller.php | 53 +++-------- src/Composer/Plugin/PluginManager.php | 75 ++++++++++++++- .../Plugin/Fixtures/plugin-v1/composer.json | 2 +- .../Plugin/Fixtures/plugin-v2/composer.json | 2 +- .../Plugin/Fixtures/plugin-v3/composer.json | 2 +- .../Plugin/Fixtures/plugin-v4/composer.json | 2 +- .../Test/Plugin/PluginInstallerTest.php | 92 ++++++------------- 9 files changed, 122 insertions(+), 119 deletions(-) diff --git a/src/Composer/Composer.php b/src/Composer/Composer.php index 32d48b771..02da7a3f5 100644 --- a/src/Composer/Composer.php +++ b/src/Composer/Composer.php @@ -55,7 +55,7 @@ class Composer private $installationManager; /** - * + * @var Plugin\PluginManager */ private $pluginManager; diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 1dd612b13..029833bf1 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -249,6 +249,9 @@ class Factory $generator = new AutoloadGenerator($dispatcher); $composer->setAutoloadGenerator($generator); + $pm = $this->createPluginManager($composer, $io); + $composer->setPluginManager($pm); + // add installers to the manager $this->createDefaultInstallers($im, $composer, $io); @@ -264,9 +267,7 @@ class Factory $composer->setLocker($locker); } - $pm = $this->createPluginManager($composer); - - $composer->setPluginManager($pm); + $pm->loadInstalledPlugins(); return $composer; } @@ -360,9 +361,9 @@ class Factory /** * @return Plugin\PluginManager */ - protected function createPluginManager(Composer $composer) + protected function createPluginManager(Composer $composer, IOInterface $io) { - return new Plugin\PluginManager($composer); + return new Plugin\PluginManager($composer, $io); } /** diff --git a/src/Composer/Installer/PluginInstaller.php b/src/Composer/Installer/PluginInstaller.php index dfcc97669..046aced45 100644 --- a/src/Composer/Installer/PluginInstaller.php +++ b/src/Composer/Installer/PluginInstaller.php @@ -37,15 +37,17 @@ class PluginInstaller extends LibraryInstaller */ public function __construct(IOInterface $io, Composer $composer, $type = 'library') { - parent::__construct($io, $composer, $type); + parent::__construct($io, $composer, 'composer-plugin'); $this->installationManager = $composer->getInstallationManager(); - $repo = $composer->getRepositoryManager()->getLocalRepository(); - foreach ($repo->getPackages() as $package) { - if ('composer-plugin' === $package->getType() || 'composer-installer' === $package->getType()) { - $this->registerPlugin($package); - } - } + } + + /** + * {@inheritDoc} + */ + public function supports($packageType) + { + return $packageType === 'composer-plugin' || $packageType === 'composer-installer'; } /** @@ -59,7 +61,7 @@ class PluginInstaller extends LibraryInstaller } parent::install($repo, $package); - $this->registerPlugin($package); + $this->composer->getPluginManager()->registerPackage($package); } /** @@ -73,39 +75,6 @@ class PluginInstaller extends LibraryInstaller } parent::update($repo, $initial, $target); - $this->registerPlugin($target); - } - - private function registerPlugin(PackageInterface $package) - { - $oldInstallerPlugin = ($package->getType() === 'composer-installer'); - - $downloadPath = $this->getInstallPath($package); - - $extra = $package->getExtra(); - $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']); - - $generator = $this->composer->getAutoloadGenerator(); - $map = $generator->parseAutoloads(array(array($package, $downloadPath)), new Package('dummy', '1.0.0.0', '1.0.0')); - $classLoader = $generator->createLoader($map); - $classLoader->register(); - - foreach ($classes as $class) { - if (class_exists($class, false)) { - $code = file_get_contents($classLoader->findFile($class)); - $code = preg_replace('{^(\s*)class\s+(\S+)}mi', '$1class $2_composer_tmp'.self::$classCounter, $code); - eval('?>'.$code); - $class .= '_composer_tmp'.self::$classCounter; - self::$classCounter++; - } - - $plugin = new $class($this->io, $this->composer); - - if ($oldInstallerPlugin) { - $this->installationManager->addInstaller($installer); - } else { - $this->composer->getPluginManager()->addPlugin($plugin); - } - } + $this->composer->getPluginManager()->registerPackage($target); } } diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index aa08de2ef..24e4890ac 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -13,6 +13,8 @@ namespace Composer\Plugin; use Composer\Composer; +use Composer\Package\Package; +use Composer\IO\IOInterface; use Composer\Package\PackageInterface; /** @@ -23,17 +25,34 @@ use Composer\Package\PackageInterface; class PluginManager { protected $composer; + protected $io; protected $plugins = array(); + private static $classCounter = 0; + /** * Initializes plugin manager * * @param Composer $composer */ - public function __construct(Composer $composer) + public function __construct(Composer $composer, IOInterface $io) { $this->composer = $composer; + $this->io = $io; + } + + public function loadInstalledPlugins() + { + $repo = $this->composer->getRepositoryManager()->getLocalRepository(); + + if ($repo) { + foreach ($repo->getPackages() as $package) { + if ('composer-plugin' === $package->getType() || 'composer-installer' === $package->getType()) { + $this->registerPackage($package); + } + } + } } /** @@ -46,4 +65,58 @@ class PluginManager $this->plugins[] = $plugin; $plugin->activate($this->composer); } + + public function getPlugins() + { + return $this->plugins; + } + + public function registerPackage(PackageInterface $package) + { + $oldInstallerPlugin = ($package->getType() === 'composer-installer'); + + $downloadPath = $this->getInstallPath($package); + + $extra = $package->getExtra(); + if (empty($extra['class'])) { + throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.'); + } + $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']); + + $generator = $this->composer->getAutoloadGenerator(); + $map = $generator->parseAutoloads(array(array($package, $downloadPath)), new Package('dummy', '1.0.0.0', '1.0.0')); + $classLoader = $generator->createLoader($map); + $classLoader->register(); + + foreach ($classes as $class) { + if (class_exists($class, false)) { + $code = file_get_contents($classLoader->findFile($class)); + $code = preg_replace('{^(\s*)class\s+(\S+)}mi', '$1class $2_composer_tmp'.self::$classCounter, $code); + eval('?>'.$code); + $class .= '_composer_tmp'.self::$classCounter; + self::$classCounter++; + } + + $plugin = new $class($this->io, $this->composer); + + if ($oldInstallerPlugin) { + $this->composer->getInstallationManager()->addInstaller($installer); + } else { + $this->addPlugin($plugin); + } + } + } + + public function getInstallPath(PackageInterface $package) + { + $targetDir = $package->getTargetDir(); + + return $this->getPackageBasePath($package) . ($targetDir ? '/'.$targetDir : ''); + } + + protected function getPackageBasePath(PackageInterface $package) + { + $vendorDir = rtrim($this->composer->getConfig()->get('vendor-dir'), '/'); + return ($vendorDir ? $vendorDir.'/' : '') . $package->getPrettyName(); + } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v1/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v1/composer.json index 969218ebc..996e5ee3e 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v1/composer.json +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v1/composer.json @@ -1,5 +1,5 @@ { - "name": "", + "name": "plugin-v1", "version": "1.0.0", "type": "composer-plugin", "autoload": { "psr-0": { "Installer": "" } }, diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v2/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v2/composer.json index 8ec717c46..c099da413 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v2/composer.json +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v2/composer.json @@ -1,5 +1,5 @@ { - "name": "", + "name": "plugin-v2", "version": "2.0.0", "type": "composer-plugin", "autoload": { "psr-0": { "Installer": "" } }, diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v3/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v3/composer.json index fe7aba7a4..3ba04e6f6 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v3/composer.json +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v3/composer.json @@ -1,5 +1,5 @@ { - "name": "", + "name": "plugin-v3", "version": "3.0.0", "type": "composer-plugin", "autoload": { "psr-0": { "Installer": "" } }, diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v4/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v4/composer.json index e2c2a4e47..10387a021 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v4/composer.json +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v4/composer.json @@ -1,5 +1,5 @@ { - "name": "", + "name": "plugin-v4", "version": "4.0.0", "type": "composer-plugin", "autoload": { "psr-0": { "Installer": "" } }, diff --git a/tests/Composer/Test/Plugin/PluginInstallerTest.php b/tests/Composer/Test/Plugin/PluginInstallerTest.php index 28a9a768a..ab5696af8 100644 --- a/tests/Composer/Test/Plugin/PluginInstallerTest.php +++ b/tests/Composer/Test/Plugin/PluginInstallerTest.php @@ -42,14 +42,6 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMock(); - $this->im = $this->getMockBuilder('Composer\Installer\InstallationManager') - ->disableOriginalConstructor() - ->getMock(); - - $this->pm = $this->getMockBuilder('Composer\Plugin\PluginManager') - ->disableOriginalConstructor() - ->getMock(); - $this->repository = $this->getMock('Composer\Repository\InstalledRepositoryInterface'); $rm = $this->getMockBuilder('Composer\Repository\RepositoryManager') @@ -68,11 +60,12 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase $config = new Config(); $this->composer->setConfig($config); $this->composer->setDownloadManager($dm); - $this->composer->setInstallationManager($this->im); - $this->composer->setPluginManager($this->pm); $this->composer->setRepositoryManager($rm); $this->composer->setAutoloadGenerator($this->autoloadGenerator); + $this->pm = new \Composer\Plugin\PluginManager($this->composer, $this->io); + $this->composer->setPluginManager($this->pm); + $config->merge(array( 'config' => array( 'vendor-dir' => __DIR__.'/Fixtures/', @@ -87,17 +80,13 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase ->expects($this->once()) ->method('getPackages') ->will($this->returnValue(array())); - $installer = new PluginInstallerMock($this->io, $this->composer); - - $test = $this; - $this->pm - ->expects($this->once()) - ->method('addPlugin') - ->will($this->returnCallback(function ($installer) use ($test) { - $test->assertEquals('installer-v1', $installer->version); - })); + $installer = new PluginInstaller($this->io, $this->composer); + $this->pm->loadInstalledPlugins(); $installer->install($this->repository, $this->packages[0]); + + $plugins = $this->pm->getPlugins(); + $this->assertEquals('installer-v1', $plugins[0]->version); } public function testInstallMultiplePlugins() @@ -106,28 +95,16 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase ->expects($this->once()) ->method('getPackages') ->will($this->returnValue(array())); - - $installer = new PluginInstallerMock($this->io, $this->composer); - - $test = $this; - - $this->pm - ->expects($this->at(0)) - ->method('addPlugin') - ->will($this->returnCallback(function ($plugin) use ($test) { - $test->assertEquals('plugin1', $plugin->name); - $test->assertEquals('installer-v4', $plugin->version); - })); - - $this->pm - ->expects($this->at(1)) - ->method('addPlugin') - ->will($this->returnCallback(function ($plugin) use ($test) { - $test->assertEquals('plugin2', $plugin->name); - $test->assertEquals('installer-v4', $plugin->version); - })); + $installer = new PluginInstaller($this->io, $this->composer); + $this->pm->loadInstalledPlugins(); $installer->install($this->repository, $this->packages[3]); + + $plugins = $this->pm->getPlugins(); + $this->assertEquals('plugin1', $plugins[0]->name); + $this->assertEquals('installer-v4', $plugins[0]->version); + $this->assertEquals('plugin2', $plugins[1]->name); + $this->assertEquals('installer-v4', $plugins[1]->version); } public function testUpgradeWithNewClassName() @@ -140,17 +117,13 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase ->expects($this->exactly(2)) ->method('hasPackage') ->will($this->onConsecutiveCalls(true, false)); - $installer = new PluginInstallerMock($this->io, $this->composer); - - $test = $this; - $this->pm - ->expects($this->once()) - ->method('addPlugin') - ->will($this->returnCallback(function ($plugin) use ($test) { - $test->assertEquals('installer-v2', $plugin->version); - })); + $installer = new PluginInstaller($this->io, $this->composer); + $this->pm->loadInstalledPlugins(); $installer->update($this->repository, $this->packages[0], $this->packages[1]); + + $plugins = $this->pm->getPlugins(); + $this->assertEquals('installer-v2', $plugins[1]->version); } public function testUpgradeWithSameClassName() @@ -163,26 +136,13 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase ->expects($this->exactly(2)) ->method('hasPackage') ->will($this->onConsecutiveCalls(true, false)); - $installer = new PluginInstallerMock($this->io, $this->composer); - - $test = $this; - $this->pm - ->expects($this->once()) - ->method('addPlugin') - ->will($this->returnCallback(function ($plugin) use ($test) { - $test->assertEquals('installer-v3', $plugin->version); - })); + $installer = new PluginInstaller($this->io, $this->composer); + $this->pm->loadInstalledPlugins(); $installer->update($this->repository, $this->packages[1], $this->packages[2]); + + $plugins = $this->pm->getPlugins(); + $this->assertEquals('installer-v3', $plugins[1]->version); } } -class PluginInstallerMock extends PluginInstaller -{ - public function getInstallPath(PackageInterface $package) - { - $version = $package->getVersion(); - - return __DIR__.'/Fixtures/plugin-v'.$version[0].'/'; - } -} From 3960edd64e27e5ba9dfee7bb8b81b37153c4f074 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Wed, 14 Aug 2013 17:42:11 +0200 Subject: [PATCH 016/238] Turn EventDispatcher into generic solution handling plugins as well --- src/Composer/Autoload/AutoloadGenerator.php | 6 +- src/Composer/Composer.php | 8 +- src/Composer/Downloader/FileDownloader.php | 25 ++++-- src/Composer/Downloader/ZipDownloader.php | 5 +- src/Composer/EventDispatcher/Event.php | 72 +++++++++++++++++ .../EventDispatcher.php | 72 +++++++++++++++-- src/Composer/Factory.php | 22 ++--- src/Composer/Installer.php | 2 +- src/Composer/Plugin/PluginEvents.php | 31 +++++++ src/Composer/Plugin/PluginManager.php | 4 + .../Plugin/PrepareRemoteFilesystemEvent.php | 80 +++++++++++++++++++ src/Composer/Script/Event.php | 22 +---- .../Test/Autoload/AutoloadGeneratorTest.php | 6 +- .../Test/Downloader/FileDownloaderTest.php | 2 +- .../EventDispatcherTest.php | 25 +++--- tests/Composer/Test/InstallerTest.php | 4 +- .../Test/Plugin/PluginInstallerTest.php | 2 +- 17 files changed, 320 insertions(+), 68 deletions(-) create mode 100644 src/Composer/EventDispatcher/Event.php rename src/Composer/{Script => EventDispatcher}/EventDispatcher.php (72%) create mode 100644 src/Composer/Plugin/PluginEvents.php create mode 100644 src/Composer/Plugin/PrepareRemoteFilesystemEvent.php rename tests/Composer/Test/{Script => EventDispatcher}/EventDispatcherTest.php (83%) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index b0fe9b232..88f0f4e68 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -13,12 +13,12 @@ namespace Composer\Autoload; use Composer\Config; +use Composer\EventDispatcher\EventDispatcher; use Composer\Installer\InstallationManager; use Composer\Package\AliasPackage; use Composer\Package\PackageInterface; use Composer\Repository\InstalledRepositoryInterface; use Composer\Util\Filesystem; -use Composer\Script\EventDispatcher; use Composer\Script\ScriptEvents; /** @@ -39,7 +39,7 @@ class AutoloadGenerator public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '') { - $this->eventDispatcher->dispatch(ScriptEvents::PRE_AUTOLOAD_DUMP); + $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP); $filesystem = new Filesystem(); $filesystem->ensureDirectoryExists($config->get('vendor-dir')); @@ -191,7 +191,7 @@ EOF; fclose($targetLoader); unset($sourceLoader, $targetLoader); - $this->eventDispatcher->dispatch(ScriptEvents::POST_AUTOLOAD_DUMP); + $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP); } public function buildPackageMap(InstallationManager $installationManager, PackageInterface $mainPackage, array $packages) diff --git a/src/Composer/Composer.php b/src/Composer/Composer.php index 02da7a3f5..e77316e4c 100644 --- a/src/Composer/Composer.php +++ b/src/Composer/Composer.php @@ -18,7 +18,7 @@ use Composer\Repository\RepositoryManager; use Composer\Installer\InstallationManager; use Composer\Plugin\PluginManager; use Composer\Downloader\DownloadManager; -use Composer\Script\EventDispatcher; +use Composer\EventDispatcher\EventDispatcher; use Composer\Autoload\AutoloadGenerator; /** @@ -65,7 +65,7 @@ class Composer private $config; /** - * @var Script\EventDispatcher + * @var EventDispatcher\EventDispatcher */ private $eventDispatcher; @@ -188,7 +188,7 @@ class Composer } /** - * @param Script\EventDispatcher $eventDispatcher + * @param EventDispatcher\EventDispatcher $eventDispatcher */ public function setEventDispatcher(EventDispatcher $eventDispatcher) { @@ -196,7 +196,7 @@ class Composer } /** - * @return Script\EventDispatcher + * @return EventDispatcher\EventDispatcher */ public function getEventDispatcher() { diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index 8ed0712bf..b9852d730 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -17,6 +17,9 @@ use Composer\Cache; use Composer\IO\IOInterface; use Composer\Package\PackageInterface; use Composer\Package\Version\VersionParser; +use Composer\Plugin\PluginEvents; +use Composer\Plugin\PrepareRemoteFilesystemEvent; +use Composer\EventDispatcher\EventDispatcher; use Composer\Util\Filesystem; use Composer\Util\GitHub; use Composer\Util\RemoteFilesystem; @@ -27,6 +30,7 @@ use Composer\Util\RemoteFilesystem; * @author Kirill chEbba Chebunin * @author Jordi Boggiano * @author François Pluchino + * @author Nils Adermann */ class FileDownloader implements DownloaderInterface { @@ -43,14 +47,16 @@ class FileDownloader implements DownloaderInterface * * @param IOInterface $io The IO instance * @param Config $config The config + * @param EventDispatcher $eventDispatcher The event dispatcher * @param Cache $cache Optional cache instance * @param RemoteFilesystem $rfs The remote filesystem * @param Filesystem $filesystem The filesystem */ - public function __construct(IOInterface $io, Config $config, Cache $cache = null, RemoteFilesystem $rfs = null, Filesystem $filesystem = null) + public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, RemoteFilesystem $rfs = null, Filesystem $filesystem = null) { $this->io = $io; $this->config = $config; + $this->eventDispatcher = $eventDispatcher; $this->rfs = $rfs ?: new RemoteFilesystem($io); $this->filesystem = $filesystem ?: new Filesystem(); $this->cache = $cache; @@ -88,6 +94,12 @@ class FileDownloader implements DownloaderInterface $processedUrl = $this->processUrl($package, $url); $hostname = parse_url($processedUrl, PHP_URL_HOST); + $prepRfsEvent = new PrepareRemoteFilesystemEvent(PluginEvents::PREPARE_REMOTE_FILESYSTEM, $this->rfs, $processedUrl); + if ($this->eventDispatcher) { + $this->eventDispatcher->dispatch($prepRfsEvent->getName(), $prepRfsEvent); + } + $rfs = $prepRfsEvent->getRemoteFilesystem(); + if (strpos($hostname, '.github.com') === (strlen($hostname) - 11)) { $hostname = 'github.com'; } @@ -103,7 +115,7 @@ class FileDownloader implements DownloaderInterface $retries = 3; while ($retries--) { try { - $this->rfs->copy($hostname, $processedUrl, $fileName, $this->outputProgress); + $rfs->copy($hostname, $processedUrl, $fileName, $this->outputProgress); break; } catch (TransportException $e) { // if we got an http response with a proper code, then requesting again will probably not help, abort @@ -124,15 +136,18 @@ class FileDownloader implements DownloaderInterface $this->io->write(' Loading from cache'); } } catch (TransportException $e) { - if (in_array($e->getCode(), array(404, 403)) && 'github.com' === $hostname && !$this->io->hasAuthentication($hostname)) { + if (!in_array($e->getCode(), array(404, 403, 412))) { + throw $e; + } + if ('github.com' === $hostname && !$this->io->hasAuthentication($hostname)) { $message = "\n".'Could not fetch '.$processedUrl.', enter your GitHub credentials '.($e->getCode() === 404 ? 'to access private repos' : 'to go over the API rate limit'); - $gitHubUtil = new GitHub($this->io, $this->config, null, $this->rfs); + $gitHubUtil = new GitHub($this->io, $this->config, null, $rfs); if (!$gitHubUtil->authorizeOAuth($hostname) && (!$this->io->isInteractive() || !$gitHubUtil->authorizeOAuthInteractively($hostname, $message)) ) { throw $e; } - $this->rfs->copy($hostname, $processedUrl, $fileName, $this->outputProgress); + $rfs->copy($hostname, $processedUrl, $fileName, $this->outputProgress); } else { throw $e; } diff --git a/src/Composer/Downloader/ZipDownloader.php b/src/Composer/Downloader/ZipDownloader.php index 80bc60272..c2394543d 100644 --- a/src/Composer/Downloader/ZipDownloader.php +++ b/src/Composer/Downloader/ZipDownloader.php @@ -14,6 +14,7 @@ namespace Composer\Downloader; use Composer\Config; use Composer\Cache; +use Composer\EventDispatcher\EventDispatcher; use Composer\Util\ProcessExecutor; use Composer\IO\IOInterface; use ZipArchive; @@ -25,10 +26,10 @@ class ZipDownloader extends ArchiveDownloader { protected $process; - public function __construct(IOInterface $io, Config $config, Cache $cache = null, ProcessExecutor $process = null) + public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null) { $this->process = $process ?: new ProcessExecutor($io); - parent::__construct($io, $config, $cache); + parent::__construct($io, $config, $eventDispatcher, $cache); } protected function extract($file, $path) diff --git a/src/Composer/EventDispatcher/Event.php b/src/Composer/EventDispatcher/Event.php new file mode 100644 index 000000000..c0a887372 --- /dev/null +++ b/src/Composer/EventDispatcher/Event.php @@ -0,0 +1,72 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\EventDispatcher; + +use Composer\Composer; +use Composer\IO\IOInterface; + +/** + * The base event class + * + * @author Nils Adermann + */ +class Event +{ + /** + * @var string This event's name + */ + protected $name; + + /** + * @var boolean Whether the event should not be passed to more listeners + */ + private $propagationStopped = false; + + /** + * Constructor. + * + * @param string $name The event name + */ + public function __construct($name) + { + $this->name = $name; + } + + /** + * Returns the event's name. + * + * @return string The event name + */ + public function getName() + { + return $this->name; + } + + /** + * Checks if stopPropagation has been called + * + * @return boolean Whether propagation has been stopped + */ + public function isPropagationStopped() + { + return $this->propagationStopped; + } + + /** + * Prevents the event from being passed to further listeners + */ + public function stopPropagation() + { + $this->propagationStopped = true; + } +} diff --git a/src/Composer/Script/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php similarity index 72% rename from src/Composer/Script/EventDispatcher.php rename to src/Composer/EventDispatcher/EventDispatcher.php index 46d3d94d7..d15ceb212 100644 --- a/src/Composer/Script/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -10,11 +10,14 @@ * file that was distributed with this source code. */ -namespace Composer\Script; +namespace Composer\EventDispatcher; use Composer\IO\IOInterface; use Composer\Composer; use Composer\DependencyResolver\Operation\OperationInterface; +use Composer\Script; +use Composer\Script\CommandEvent; +use Composer\Script\PackageEvent; use Composer\Util\ProcessExecutor; /** @@ -28,6 +31,7 @@ use Composer\Util\ProcessExecutor; * * @author François Pluchino * @author Jordi Boggiano + * @author Nils Adermann */ class EventDispatcher { @@ -51,15 +55,30 @@ class EventDispatcher } /** - * Dispatch a script event. + * Dispatch an event * - * @param string $eventName The constant in ScriptEvents + * @param string $eventName An event name * @param Event $event */ public function dispatch($eventName, Event $event = null) { if (null == $event) { - $event = new Event($eventName, $this->composer, $this->io); + $event = new Event($eventName); + } + + $this->doDispatch($event); + } + + /** + * Dispatch a script event. + * + * @param string $eventName The constant in ScriptEvents + * @param Event $event + */ + public function dispatchScript($eventName, Script\Event $event = null) + { + if (null == $event) { + $event = new Script\Event($eventName, $this->composer, $this->io); } $this->doDispatch($event); @@ -100,7 +119,9 @@ class EventDispatcher $listeners = $this->getListeners($event); foreach ($listeners as $callable) { - if ($this->isPhpScript($callable)) { + if ((is_array($callable) && $is_callable($callable)) || $callable instanceof Closure) { + $callable($event); + } elseif ($this->isPhpScript($callable)) { $className = substr($callable, 0, strpos($callable, '::')); $methodName = substr($callable, strpos($callable, '::') + 2); @@ -127,6 +148,10 @@ class EventDispatcher throw new \RuntimeException('Error Output: '.$this->process->getErrorOutput(), $exitCode); } } + + if ($event->isPropagationStopped()) { + break; + } } } @@ -140,11 +165,46 @@ class EventDispatcher $className::$methodName($event); } + protected function addListener($eventName, $listener, $priority = 0) + { + $this->listeners[$eventName][$priority][] = $listener; + } + + protected function addSubscriber($subscriber) + { + foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { + if (is_string($params)) { + $this->addListener($eventName, array($subscriber, $params)); + } elseif (is_string($params[0])) { + $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0); + } else { + foreach ($params as $listener) { + $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0); + } + } + } + } + + protected function getListeners(Event $event) + { + $scriptListeners = $this->getScriptListeners($event); + + if (!isset($this->listeners[$event->getName()][0])) { + $this->listeners[$event->getName()][0] = array(); + } + krsort($this->listeners[$event->getName()]); + + $listeners = $this->listeners; + $listeners[$event->getName()][0] = array_merge($listeners[$event->getName()][0], $scriptListeners); + + return call_user_func_array('array_merge', $listeners[$event->getName()]); + } + /** * @param Event $event Event object * @return array Listeners */ - protected function getListeners(Event $event) + protected function getScriptListeners(Event $event) { $package = $this->composer->getPackage(); $scripts = $package->getScripts(); diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 029833bf1..a7609469a 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -21,7 +21,7 @@ use Composer\Repository\RepositoryManager; use Composer\Util\ProcessExecutor; use Composer\Util\RemoteFilesystem; use Symfony\Component\Console\Formatter\OutputFormatterStyle; -use Composer\Script\EventDispatcher; +use Composer\EventDispatcher\EventDispatcher; use Composer\Autoload\AutoloadGenerator; use Composer\Package\Version\VersionParser; @@ -227,9 +227,6 @@ class Factory $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, new ProcessExecutor($io)); $package = $loader->load($localConfig); - // initialize download manager - $dm = $this->createDownloadManager($io, $config); - // initialize installation manager $im = $this->createInstallationManager(); @@ -238,11 +235,15 @@ class Factory $composer->setConfig($config); $composer->setPackage($package); $composer->setRepositoryManager($rm); - $composer->setDownloadManager($dm); $composer->setInstallationManager($im); // initialize event dispatcher $dispatcher = new EventDispatcher($composer, $io); + + // initialize download manager + $dm = $this->createDownloadManager($io, $config, $dispatcher); + + $composer->setDownloadManager($dm); $composer->setEventDispatcher($dispatcher); // initialize autoload generator @@ -304,9 +305,10 @@ class Factory /** * @param IO\IOInterface $io * @param Config $config + * @param EventDispatcher $eventDispatcher * @return Downloader\DownloadManager */ - public function createDownloadManager(IOInterface $io, Config $config) + public function createDownloadManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null) { $cache = null; if ($config->get('cache-files-ttl') > 0) { @@ -330,10 +332,10 @@ class Factory $dm->setDownloader('git', new Downloader\GitDownloader($io, $config)); $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config)); $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config)); - $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $cache)); - $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $cache)); - $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $cache)); - $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $cache)); + $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $eventDispatcher, $cache)); + $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $eventDispatcher, $cache)); + $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache)); + $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache)); return $dm; } diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 1d3ec9255..aec6e55a7 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -24,6 +24,7 @@ use Composer\DependencyResolver\Rule; use Composer\DependencyResolver\Solver; use Composer\DependencyResolver\SolverProblemsException; use Composer\Downloader\DownloadManager; +use Composer\EventDispatcher\EventDispatcher; use Composer\Installer\InstallationManager; use Composer\Config; use Composer\Installer\NoopInstaller; @@ -41,7 +42,6 @@ use Composer\Repository\InstalledFilesystemRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryInterface; use Composer\Repository\RepositoryManager; -use Composer\Script\EventDispatcher; use Composer\Script\ScriptEvents; /** diff --git a/src/Composer/Plugin/PluginEvents.php b/src/Composer/Plugin/PluginEvents.php new file mode 100644 index 000000000..bfdfba3dd --- /dev/null +++ b/src/Composer/Plugin/PluginEvents.php @@ -0,0 +1,31 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Plugin; + +/** + * The Plugin Events. + * + * @author Nils Adermann + */ +class PluginEvents +{ + /** + * The PREPARE_REMOTE_FILESYSTEM event occurs before downloading a file + * + * The event listener method receives a + * Composer\Plugin\PrepareRemoteFilesystemEvent instance. + * + * @var string + */ + const PREPARE_REMOTE_FILESYSTEM = 'prepare-remote-filesystem'; +} diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index 24e4890ac..1d424627a 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -64,6 +64,10 @@ class PluginManager { $this->plugins[] = $plugin; $plugin->activate($this->composer); + + if ($plugin instanceof \Symfony\Component\EventDispatcher\EventSubscriberInterface) { + $this->composer->getPluginEventDispatcher()->addSubscriber($plugin); + } } public function getPlugins() diff --git a/src/Composer/Plugin/PrepareRemoteFilesystemEvent.php b/src/Composer/Plugin/PrepareRemoteFilesystemEvent.php new file mode 100644 index 000000000..91b0543f3 --- /dev/null +++ b/src/Composer/Plugin/PrepareRemoteFilesystemEvent.php @@ -0,0 +1,80 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Plugin; + +use Composer\Composer; +use Composer\IO\IOInterface; +use Composer\EventDispatcher\Event; +use Composer\Util\RemoteFilesystem; + +/** + * The Prepare Remote Filesystem Event. + * + * @author Nils Adermann + */ +class PrepareRemoteFilesystemEvent extends Event +{ + /** + * @var RemoteFilesystem + */ + private $rfs; + + /** + * @var string + */ + private $processedUrl; + + /** + * Constructor. + * + * @param string $name The event name + * @param Composer $composer The composer object + * @param IOInterface $io The IOInterface object + * @param boolean $devMode Whether or not we are in dev mode + * @param OperationInterface $operation The operation object + */ + public function __construct($name, RemoteFilesystem $rfs, $processedUrl) + { + parent::__construct($name); + $this->rfs = $rfs; + $this->processedUrl = $processedUrl; + } + + /** + * Returns the remote filesystem + * + * @return OperationInterface + */ + public function getRemoteFilesystem() + { + return $this->rfs; + } + + /** + * Sets the remote filesystem + */ + public function setRemoteFilesystem(RemoteFilesystem $rfs) + { + $this->rfs = $rfs; + } + + /** + * Retrieves the processed URL this remote filesystem will be used for + * + * @return string + */ + public function getProcessedUrl() + { + return $this->processedUrl; + } +} diff --git a/src/Composer/Script/Event.php b/src/Composer/Script/Event.php index cafea2948..40b109b2d 100644 --- a/src/Composer/Script/Event.php +++ b/src/Composer/Script/Event.php @@ -16,17 +16,13 @@ use Composer\Composer; use Composer\IO\IOInterface; /** - * The base event class + * The script event class * * @author François Pluchino + * @author Nils Adermann */ -class Event +class Event extends \Composer\EventDispatcher\Event { - /** - * @var string This event's name - */ - private $name; - /** * @var Composer The composer instance */ @@ -52,22 +48,12 @@ class Event */ public function __construct($name, Composer $composer, IOInterface $io, $devMode = false) { - $this->name = $name; + parent::__construct($name); $this->composer = $composer; $this->io = $io; $this->devMode = $devMode; } - /** - * Returns the event's name. - * - * @return string The event name - */ - public function getName() - { - return $this->name; - } - /** * Returns the composer instance. * diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index dc1fa529e..9955f314f 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -72,7 +72,7 @@ class AutoloadGeneratorTest extends TestCase })); $this->repository = $this->getMock('Composer\Repository\InstalledRepositoryInterface'); - $this->eventDispatcher = $this->getMockBuilder('Composer\Script\EventDispatcher') + $this->eventDispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') ->disableOriginalConstructor() ->getMock(); @@ -626,12 +626,12 @@ EOF; { $this->eventDispatcher ->expects($this->at(0)) - ->method('dispatch') + ->method('dispatchScript') ->with(ScriptEvents::PRE_AUTOLOAD_DUMP, false); $this->eventDispatcher ->expects($this->at(1)) - ->method('dispatch') + ->method('dispatchScript') ->with(ScriptEvents::POST_AUTOLOAD_DUMP, false); $package = new Package('a', '1.0', '1.0'); diff --git a/tests/Composer/Test/Downloader/FileDownloaderTest.php b/tests/Composer/Test/Downloader/FileDownloaderTest.php index 99dcaab18..c91798120 100644 --- a/tests/Composer/Test/Downloader/FileDownloaderTest.php +++ b/tests/Composer/Test/Downloader/FileDownloaderTest.php @@ -23,7 +23,7 @@ class FileDownloaderTest extends \PHPUnit_Framework_TestCase $config = $config ?: $this->getMock('Composer\Config'); $rfs = $rfs ?: $this->getMockBuilder('Composer\Util\RemoteFilesystem')->disableOriginalConstructor()->getMock(); - return new FileDownloader($io, $config, null, $rfs); + return new FileDownloader($io, $config, null, null, $rfs); } /** diff --git a/tests/Composer/Test/Script/EventDispatcherTest.php b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php similarity index 83% rename from tests/Composer/Test/Script/EventDispatcherTest.php rename to tests/Composer/Test/EventDispatcher/EventDispatcherTest.php index cd8f8e76f..7a15679d1 100644 --- a/tests/Composer/Test/Script/EventDispatcherTest.php +++ b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php @@ -10,11 +10,12 @@ * file that was distributed with this source code. */ -namespace Composer\Test\Script; +namespace Composer\Test\EventDispatcher; +use Composer\EventDispatcher\Event; +use Composer\EventDispatcher\EventDispatcher; use Composer\Test\TestCase; -use Composer\Script\Event; -use Composer\Script\EventDispatcher; +use Composer\Script; use Composer\Util\ProcessExecutor; class EventDispatcherTest extends TestCase @@ -26,12 +27,12 @@ class EventDispatcherTest extends TestCase { $io = $this->getMock('Composer\IO\IOInterface'); $dispatcher = $this->getDispatcherStubForListenersTest(array( - "Composer\Test\Script\EventDispatcherTest::call" + "Composer\Test\EventDispatcher\EventDispatcherTest::call" ), $io); $io->expects($this->once()) ->method('write') - ->with('Script Composer\Test\Script\EventDispatcherTest::call handling the post-install-cmd event terminated with an exception'); + ->with('Script Composer\Test\EventDispatcher\EventDispatcherTest::call handling the post-install-cmd event terminated with an exception'); $dispatcher->dispatchCommandEvent("post-install-cmd", false); } @@ -43,7 +44,7 @@ class EventDispatcherTest extends TestCase public function testDispatcherCanExecuteSingleCommandLineScript($command) { $process = $this->getMock('Composer\Util\ProcessExecutor'); - $dispatcher = $this->getMockBuilder('Composer\Script\EventDispatcher') + $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') ->setConstructorArgs(array( $this->getMock('Composer\Composer'), $this->getMock('Composer\IO\IOInterface'), @@ -68,7 +69,7 @@ class EventDispatcherTest extends TestCase public function testDispatcherCanExecuteCliAndPhpInSameEventScriptStack() { $process = $this->getMock('Composer\Util\ProcessExecutor'); - $dispatcher = $this->getMockBuilder('Composer\Script\EventDispatcher') + $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') ->setConstructorArgs(array( $this->getMock('Composer\Composer'), $this->getMock('Composer\IO\IOInterface'), @@ -86,7 +87,7 @@ class EventDispatcherTest extends TestCase $listeners = array( 'echo -n foo', - 'Composer\\Test\\Script\\EventDispatcherTest::someMethod', + 'Composer\\Test\\EventDispatcher\\EventDispatcherTest::someMethod', 'echo -n bar', ); $dispatcher->expects($this->atLeastOnce()) @@ -95,7 +96,7 @@ class EventDispatcherTest extends TestCase $dispatcher->expects($this->once()) ->method('executeEventPhpScript') - ->with('Composer\Test\Script\EventDispatcherTest', 'someMethod') + ->with('Composer\Test\EventDispatcher\EventDispatcherTest', 'someMethod') ->will($this->returnValue(true)); $dispatcher->dispatchCommandEvent("post-install-cmd", false); @@ -103,7 +104,7 @@ class EventDispatcherTest extends TestCase private function getDispatcherStubForListenersTest($listeners, $io) { - $dispatcher = $this->getMockBuilder('Composer\Script\EventDispatcher') + $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') ->setConstructorArgs(array( $this->getMock('Composer\Composer'), $io, @@ -129,7 +130,7 @@ class EventDispatcherTest extends TestCase public function testDispatcherOutputsCommands() { - $dispatcher = $this->getMockBuilder('Composer\Script\EventDispatcher') + $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') ->setConstructorArgs(array( $this->getMock('Composer\Composer'), $this->getMock('Composer\IO\IOInterface'), @@ -150,7 +151,7 @@ class EventDispatcherTest extends TestCase public function testDispatcherOutputsErrorOnFailedCommand() { - $dispatcher = $this->getMockBuilder('Composer\Script\EventDispatcher') + $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') ->setConstructorArgs(array( $this->getMock('Composer\Composer'), $io = $this->getMock('Composer\IO\IOInterface'), diff --git a/tests/Composer/Test/InstallerTest.php b/tests/Composer/Test/InstallerTest.php index 7c3791791..e3ec2b927 100644 --- a/tests/Composer/Test/InstallerTest.php +++ b/tests/Composer/Test/InstallerTest.php @@ -66,7 +66,7 @@ class InstallerTest extends TestCase $locker = $this->getMockBuilder('Composer\Package\Locker')->disableOriginalConstructor()->getMock(); $installationManager = new InstallationManagerMock(); - $eventDispatcher = $this->getMockBuilder('Composer\Script\EventDispatcher')->disableOriginalConstructor()->getMock(); + $eventDispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')->disableOriginalConstructor()->getMock(); $autoloadGenerator = $this->getMockBuilder('Composer\Autoload\AutoloadGenerator')->disableOriginalConstructor()->getMock(); $installer = new Installer($io, $config, clone $rootPackage, $downloadManager, $repositoryManager, $locker, $installationManager, $eventDispatcher, $autoloadGenerator); @@ -189,7 +189,7 @@ class InstallerTest extends TestCase $locker = new Locker($io, $lockJsonMock, $repositoryManager, $composer->getInstallationManager(), md5(json_encode($composerConfig))); $composer->setLocker($locker); - $eventDispatcher = $this->getMockBuilder('Composer\Script\EventDispatcher')->disableOriginalConstructor()->getMock(); + $eventDispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')->disableOriginalConstructor()->getMock(); $autoloadGenerator = $this->getMock('Composer\Autoload\AutoloadGenerator', array(), array($eventDispatcher)); $composer->setAutoloadGenerator($autoloadGenerator); $composer->setEventDispatcher($eventDispatcher); diff --git a/tests/Composer/Test/Plugin/PluginInstallerTest.php b/tests/Composer/Test/Plugin/PluginInstallerTest.php index ab5696af8..8734993ea 100644 --- a/tests/Composer/Test/Plugin/PluginInstallerTest.php +++ b/tests/Composer/Test/Plugin/PluginInstallerTest.php @@ -53,7 +53,7 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase $this->io = $this->getMock('Composer\IO\IOInterface'); - $dispatcher = $this->getMockBuilder('Composer\Script\EventDispatcher')->disableOriginalConstructor()->getMock(); + $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')->disableOriginalConstructor()->getMock(); $this->autoloadGenerator = new AutoloadGenerator($dispatcher); $this->composer = new Composer(); From 919a19015336f37b283bc72233d172709d14dd97 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Wed, 14 Aug 2013 18:27:54 +0200 Subject: [PATCH 017/238] Add an EventSubscriberInterface which may also be implemented by plugins --- src/Composer/EventDispatcher/Event.php | 3 -- .../EventDispatcher/EventDispatcher.php | 2 +- .../EventSubscriberInterface.php | 48 +++++++++++++++++++ src/Composer/Plugin/PluginManager.php | 5 +- 4 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 src/Composer/EventDispatcher/EventSubscriberInterface.php diff --git a/src/Composer/EventDispatcher/Event.php b/src/Composer/EventDispatcher/Event.php index c0a887372..8a9352653 100644 --- a/src/Composer/EventDispatcher/Event.php +++ b/src/Composer/EventDispatcher/Event.php @@ -12,9 +12,6 @@ namespace Composer\EventDispatcher; -use Composer\Composer; -use Composer\IO\IOInterface; - /** * The base event class * diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index d15ceb212..f47e77044 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -170,7 +170,7 @@ class EventDispatcher $this->listeners[$eventName][$priority][] = $listener; } - protected function addSubscriber($subscriber) + public function addSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { if (is_string($params)) { diff --git a/src/Composer/EventDispatcher/EventSubscriberInterface.php b/src/Composer/EventDispatcher/EventSubscriberInterface.php new file mode 100644 index 000000000..6b0c4ca06 --- /dev/null +++ b/src/Composer/EventDispatcher/EventSubscriberInterface.php @@ -0,0 +1,48 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\EventDispatcher; + +/** + * An EventSubscriber knows which events it is interested in. + * + * If an EventSubscriber is added to an EventDispatcher, the manager invokes + * {@link getSubscribedEvents} and registers the subscriber as a listener for all + * returned events. + * + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Bernhard Schussek + */ +interface EventSubscriberInterface +{ + /** + * Returns an array of event names this subscriber wants to listen to. + * + * The array keys are event names and the value can be: + * + * * The method name to call (priority defaults to 0) + * * An array composed of the method name to call and the priority + * * An array of arrays composed of the method names to call and respective + * priorities, or 0 if unset + * + * For instance: + * + * * array('eventName' => 'methodName') + * * array('eventName' => array('methodName', $priority)) + * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) + * + * @return array The event names to listen to + */ + public static function getSubscribedEvents(); +} diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index 1d424627a..74c0081c3 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -13,6 +13,7 @@ namespace Composer\Plugin; use Composer\Composer; +use Composer\EventDispatcher\EventSubscriberInterface; use Composer\Package\Package; use Composer\IO\IOInterface; use Composer\Package\PackageInterface; @@ -65,8 +66,8 @@ class PluginManager $this->plugins[] = $plugin; $plugin->activate($this->composer); - if ($plugin instanceof \Symfony\Component\EventDispatcher\EventSubscriberInterface) { - $this->composer->getPluginEventDispatcher()->addSubscriber($plugin); + if ($plugin instanceof EventSubscriberInterface) { + $this->composer->getEventDispatcher()->addSubscriber($plugin); } } From f00f5113bfc4c1c7035921a2c9dace34f6071e8d Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Wed, 14 Aug 2013 18:30:09 +0200 Subject: [PATCH 018/238] Fix typo --- src/Composer/EventDispatcher/EventDispatcher.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index f47e77044..3762529e7 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -119,7 +119,7 @@ class EventDispatcher $listeners = $this->getListeners($event); foreach ($listeners as $callable) { - if ((is_array($callable) && $is_callable($callable)) || $callable instanceof Closure) { + if ((is_array($callable) && is_callable($callable)) || $callable instanceof Closure) { $callable($event); } elseif ($this->isPhpScript($callable)) { $className = substr($callable, 0, strpos($callable, '::')); From 9402a9fb3c69b75b044377b2e0331c1f3118554e Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Wed, 14 Aug 2013 18:47:25 +0200 Subject: [PATCH 019/238] Plugins receive composer and io objects on construction already --- src/Composer/Plugin/PluginInterface.php | 6 ++---- src/Composer/Plugin/PluginManager.php | 4 ++-- src/Composer/Util/RemoteFilesystem.php | 10 ++++++++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Composer/Plugin/PluginInterface.php b/src/Composer/Plugin/PluginInterface.php index ebbbe0026..2c38d0f8d 100644 --- a/src/Composer/Plugin/PluginInterface.php +++ b/src/Composer/Plugin/PluginInterface.php @@ -22,9 +22,7 @@ use Composer\Composer; interface PluginInterface { /** - * Apply plugin modifications to the passed in composer object - * - * @param Composer $composer + * Apply plugin modifications to composer */ - public function activate(Composer $composer); + public function activate(); } diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index 74c0081c3..f97900679 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -64,7 +64,7 @@ class PluginManager public function addPlugin(PluginInterface $plugin) { $this->plugins[] = $plugin; - $plugin->activate($this->composer); + $plugin->activate(); if ($plugin instanceof EventSubscriberInterface) { $this->composer->getEventDispatcher()->addSubscriber($plugin); @@ -102,7 +102,7 @@ class PluginManager self::$classCounter++; } - $plugin = new $class($this->io, $this->composer); + $plugin = new $class($this->composer, $this->io); if ($oldInstallerPlugin) { $this->composer->getInstallationManager()->addInstaller($installer); diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php index 3db55ab6d..29ed98321 100644 --- a/src/Composer/Util/RemoteFilesystem.php +++ b/src/Composer/Util/RemoteFilesystem.php @@ -76,6 +76,16 @@ class RemoteFilesystem return $this->get($originUrl, $fileUrl, $options, null, $progress); } + /** + * Retrieve the options set in the constructor + * + * @return array Options + */ + public function getOptions() + { + return $this->options; + } + /** * Get file content or copy action. * From 69a028f368ca96d52c6814933ce53d52b55e64fe Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Wed, 14 Aug 2013 19:13:27 +0200 Subject: [PATCH 020/238] Fix plugin interface usage in tests --- .../Test/Plugin/Fixtures/plugin-v1/Installer/Plugin.php | 2 +- .../Test/Plugin/Fixtures/plugin-v2/Installer/Plugin2.php | 2 +- .../Test/Plugin/Fixtures/plugin-v3/Installer/Plugin2.php | 2 +- .../Test/Plugin/Fixtures/plugin-v4/Installer/Plugin1.php | 2 +- .../Test/Plugin/Fixtures/plugin-v4/Installer/Plugin2.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v1/Installer/Plugin.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v1/Installer/Plugin.php index 9196523e7..76c6cef09 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v1/Installer/Plugin.php +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v1/Installer/Plugin.php @@ -9,7 +9,7 @@ class Plugin implements PluginInterface { public $version = 'installer-v1'; - public function activate(Composer $composer) + public function activate() { } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v2/Installer/Plugin2.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v2/Installer/Plugin2.php index 5cea4f0d0..72e44a1b5 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v2/Installer/Plugin2.php +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v2/Installer/Plugin2.php @@ -9,7 +9,7 @@ class Plugin2 implements PluginInterface { public $version = 'installer-v2'; - public function activate(Composer $composer) + public function activate() { } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v3/Installer/Plugin2.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v3/Installer/Plugin2.php index 336618e57..e7130a1a6 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v3/Installer/Plugin2.php +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v3/Installer/Plugin2.php @@ -9,7 +9,7 @@ class Plugin2 implements PluginInterface { public $version = 'installer-v3'; - public function activate(Composer $composer) + public function activate() { } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin1.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin1.php index 9359d0f0e..826e5d52f 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin1.php +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin1.php @@ -10,7 +10,7 @@ class Plugin1 implements PluginInterface public $name = 'plugin1'; public $version = 'installer-v4'; - public function activate(Composer $composer) + public function activate() { } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin2.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin2.php index b98b4f393..5716e3fae 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin2.php +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin2.php @@ -10,7 +10,7 @@ class Plugin2 implements PluginInterface public $name = 'plugin2'; public $version = 'installer-v4'; - public function activate(Composer $composer) + public function activate() { } } From cd66328d68160911692ede4c6805844a8e1ec46d Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 15 Aug 2013 15:11:17 +0200 Subject: [PATCH 021/238] Autoload dependencies of plugins using a pool of only the local repo --- src/Composer/Plugin/PluginManager.php | 43 +++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index f97900679..f13c9787d 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -17,6 +17,8 @@ use Composer\EventDispatcher\EventSubscriberInterface; use Composer\Package\Package; use Composer\IO\IOInterface; use Composer\Package\PackageInterface; +use Composer\Package\Link; +use Composer\DependencyResolver\Pool; /** * Plugin manager @@ -76,20 +78,55 @@ class PluginManager return $this->plugins; } + protected function collectDependencies(Pool $pool, array $collected, PackageInterface $package) + { + $requires = array_merge( + $package->getRequires(), + $package->getDevRequires() + ); + + foreach ($requires as $requireLink) { + $requiredPackage = $this->lookupInstalledPackage($pool, $requireLink); + if ($requiredPackage && !isset($collected[$requiredPackage->getName()])) { + $collected[$requiredPackage->getName()] = $requiredPackage; + $collected = $this->collectDependencies($pool, $collected, $requiredPackage); + } + } + + return $collected; + } + + protected function lookupInstalledPackage(Pool $pool, Link $link) + { + $packages = $pool->whatProvides($link->getTarget(), $link->getConstraint()); + + return (!empty($packages)) ? $packages[0] : null; + } + public function registerPackage(PackageInterface $package) { $oldInstallerPlugin = ($package->getType() === 'composer-installer'); - $downloadPath = $this->getInstallPath($package); - $extra = $package->getExtra(); if (empty($extra['class'])) { throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.'); } $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']); + $pool = new Pool('dev'); + $pool->addRepository($this->composer->getRepositoryManager()->getLocalRepository()); + + $autoloadPackages = array($package->getName() => $package); + $autoloadPackages = $this->collectDependencies($pool, $autoloadPackages, $package); + $generator = $this->composer->getAutoloadGenerator(); - $map = $generator->parseAutoloads(array(array($package, $downloadPath)), new Package('dummy', '1.0.0.0', '1.0.0')); + $autoloads = array(); + foreach ($autoloadPackages as $autoloadPackage) { + $downloadPath = $this->getInstallPath($autoloadPackage); + $autoloads[] = array($autoloadPackage, $downloadPath); + } + + $map = $generator->parseAutoloads($autoloads, new Package('dummy', '1.0.0.0', '1.0.0')); $classLoader = $generator->createLoader($map); $classLoader->register(); From b83535d2d91890e7f89570f701553d3f2722864a Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 15 Aug 2013 16:35:42 +0200 Subject: [PATCH 022/238] Add back --no-custom-installers option with a deprecated warning --- src/Composer/Command/CreateProjectCommand.php | 6 ++++++ src/Composer/Command/InstallCommand.php | 5 +++++ src/Composer/Command/UpdateCommand.php | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index c38f0bec4..5cc19927a 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -63,6 +63,7 @@ class CreateProjectCommand extends Command new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'), new InputOption('no-plugins', null, InputOption::VALUE_NONE, 'Whether to disable plugins.'), + new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'), new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deletion vcs folder.'), @@ -116,6 +117,11 @@ EOT $preferDist = $input->getOption('prefer-dist'); } + if ($input->getOption('no-custom-installers')) { + $output->writeln('You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.'); + $input->setOption('no-plugins', true); + } + return $this->installProject( $this->getIO(), $config, diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index 90ad2810f..2a9c6466a 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -36,6 +36,7 @@ class InstallCommand extends Command new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'), new InputOption('no-plugins', null, InputOption::VALUE_NONE, 'Disables all plugins.'), + new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'), new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), @@ -90,6 +91,10 @@ EOT ->setOptimizeAutoloader($input->getOption('optimize-autoloader')) ; + if ($input->getOption('no-custom-installers')) { + $output->writeln('You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.'); + $input->setOption('no-plugins', true); + } if ($input->getOption('no-plugins')) { $install->disablePlugins(); } diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index 8d3133b83..09fa61a9b 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -37,6 +37,7 @@ class UpdateCommand extends Command new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'), new InputOption('lock', null, InputOption::VALUE_NONE, 'Only updates the lock file hash to suppress warning about the lock file being out of date.'), new InputOption('no-plugins', null, InputOption::VALUE_NONE, 'Disables all plugins.'), + new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'), new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), @@ -96,6 +97,10 @@ EOT ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $input->getArgument('packages')) ; + if ($input->getOption('no-custom-installers')) { + $output->writeln('You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.'); + $input->setOption('no-plugins', true); + } if ($input->getOption('no-plugins')) { $install->disablePlugins(); } From b9c575867061d5afdbd62cb16478673f617eeadd Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 15 Aug 2013 16:58:48 +0200 Subject: [PATCH 023/238] Make composer/io part of the activate plugin API rather than constructor args --- src/Composer/Plugin/PluginInterface.php | 6 +++++- src/Composer/Plugin/PluginManager.php | 6 +++--- .../Test/Plugin/Fixtures/plugin-v1/Installer/Plugin.php | 3 ++- .../Test/Plugin/Fixtures/plugin-v2/Installer/Plugin2.php | 3 ++- .../Test/Plugin/Fixtures/plugin-v3/Installer/Plugin2.php | 3 ++- .../Test/Plugin/Fixtures/plugin-v4/Installer/Plugin1.php | 3 ++- .../Test/Plugin/Fixtures/plugin-v4/Installer/Plugin2.php | 3 ++- tests/Composer/Test/Plugin/PluginInstallerTest.php | 8 ++++---- 8 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/Composer/Plugin/PluginInterface.php b/src/Composer/Plugin/PluginInterface.php index 2c38d0f8d..302175a25 100644 --- a/src/Composer/Plugin/PluginInterface.php +++ b/src/Composer/Plugin/PluginInterface.php @@ -13,6 +13,7 @@ namespace Composer\Plugin; use Composer\Composer; +use Composer\IO\IOInterface; /** * Plugin interface @@ -23,6 +24,9 @@ interface PluginInterface { /** * Apply plugin modifications to composer + * + * @param Composer $composer + * @param IOInterface $io */ - public function activate(); + public function activate(Composer $composer, IOInterface $io); } diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index f13c9787d..a6956c24e 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -66,7 +66,7 @@ class PluginManager public function addPlugin(PluginInterface $plugin) { $this->plugins[] = $plugin; - $plugin->activate(); + $plugin->activate($this->composer, $this->io); if ($plugin instanceof EventSubscriberInterface) { $this->composer->getEventDispatcher()->addSubscriber($plugin); @@ -139,11 +139,11 @@ class PluginManager self::$classCounter++; } - $plugin = new $class($this->composer, $this->io); - if ($oldInstallerPlugin) { + $installer = new $class($this->composer, $this->io); $this->composer->getInstallationManager()->addInstaller($installer); } else { + $plugin = new $class(); $this->addPlugin($plugin); } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v1/Installer/Plugin.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v1/Installer/Plugin.php index 76c6cef09..f80acd325 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v1/Installer/Plugin.php +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v1/Installer/Plugin.php @@ -3,13 +3,14 @@ namespace Installer; use Composer\Composer; +use Composer\IO\IOInterface; use Composer\Plugin\PluginInterface; class Plugin implements PluginInterface { public $version = 'installer-v1'; - public function activate() + public function activate(Composer $composer, IOInterface $io) { } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v2/Installer/Plugin2.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v2/Installer/Plugin2.php index 72e44a1b5..db5a4462e 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v2/Installer/Plugin2.php +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v2/Installer/Plugin2.php @@ -3,13 +3,14 @@ namespace Installer; use Composer\Composer; +use Composer\IO\IOInterface; use Composer\Plugin\PluginInterface; class Plugin2 implements PluginInterface { public $version = 'installer-v2'; - public function activate() + public function activate(Composer $composer, IOInterface $io) { } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v3/Installer/Plugin2.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v3/Installer/Plugin2.php index e7130a1a6..861c1679b 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v3/Installer/Plugin2.php +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v3/Installer/Plugin2.php @@ -3,13 +3,14 @@ namespace Installer; use Composer\Composer; +use Composer\IO\IOInterface; use Composer\Plugin\PluginInterface; class Plugin2 implements PluginInterface { public $version = 'installer-v3'; - public function activate() + public function activate(Composer $composer, IOInterface $io) { } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin1.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin1.php index 826e5d52f..93bcabc98 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin1.php +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin1.php @@ -3,6 +3,7 @@ namespace Installer; use Composer\Composer; +use Composer\IO\IOInterface; use Composer\Plugin\PluginInterface; class Plugin1 implements PluginInterface @@ -10,7 +11,7 @@ class Plugin1 implements PluginInterface public $name = 'plugin1'; public $version = 'installer-v4'; - public function activate() + public function activate(Composer $composer, IOInterface $io) { } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin2.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin2.php index 5716e3fae..d946deb89 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin2.php +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v4/Installer/Plugin2.php @@ -3,6 +3,7 @@ namespace Installer; use Composer\Composer; +use Composer\IO\IOInterface; use Composer\Plugin\PluginInterface; class Plugin2 implements PluginInterface @@ -10,7 +11,7 @@ class Plugin2 implements PluginInterface public $name = 'plugin2'; public $version = 'installer-v4'; - public function activate() + public function activate(Composer $composer, IOInterface $io) { } } diff --git a/tests/Composer/Test/Plugin/PluginInstallerTest.php b/tests/Composer/Test/Plugin/PluginInstallerTest.php index 8734993ea..5d21f59db 100644 --- a/tests/Composer/Test/Plugin/PluginInstallerTest.php +++ b/tests/Composer/Test/Plugin/PluginInstallerTest.php @@ -77,7 +77,7 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase public function testInstallNewPlugin() { $this->repository - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getPackages') ->will($this->returnValue(array())); $installer = new PluginInstaller($this->io, $this->composer); @@ -92,7 +92,7 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase public function testInstallMultiplePlugins() { $this->repository - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getPackages') ->will($this->returnValue(array())); $installer = new PluginInstaller($this->io, $this->composer); @@ -110,7 +110,7 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase public function testUpgradeWithNewClassName() { $this->repository - ->expects($this->once()) + ->expects($this->exactly(3)) ->method('getPackages') ->will($this->returnValue(array($this->packages[0]))); $this->repository @@ -129,7 +129,7 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase public function testUpgradeWithSameClassName() { $this->repository - ->expects($this->once()) + ->expects($this->exactly(3)) ->method('getPackages') ->will($this->returnValue(array($this->packages[1]))); $this->repository From f0b45099c1354e6822d9bf6a7664dde5eb3a6a65 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 15 Aug 2013 17:14:48 +0200 Subject: [PATCH 024/238] Correct authorship info for files I edited --- src/Composer/Command/CreateProjectCommand.php | 1 + src/Composer/Command/InstallCommand.php | 1 + src/Composer/Command/UpdateCommand.php | 1 + src/Composer/Composer.php | 1 + src/Composer/Factory.php | 1 + src/Composer/Installer.php | 1 + src/Composer/Installer/InstallationManager.php | 1 + src/Composer/Installer/PluginInstaller.php | 3 ++- src/Composer/Util/RemoteFilesystem.php | 1 + 9 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index 5cc19927a..308f1d204 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -44,6 +44,7 @@ use Composer\Package\Version\VersionParser; * @author Benjamin Eberlei * @author Jordi Boggiano * @author Tobias Munk + * @author Nils Adermann */ class CreateProjectCommand extends Command { diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index 2a9c6466a..edf8ae593 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -21,6 +21,7 @@ use Symfony\Component\Console\Output\OutputInterface; * @author Jordi Boggiano * @author Ryan Weaver * @author Konstantin Kudryashov + * @author Nils Adermann */ class InstallCommand extends Command { diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index 09fa61a9b..3ac0e1401 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -20,6 +20,7 @@ use Symfony\Component\Console\Output\OutputInterface; /** * @author Jordi Boggiano + * @author Nils Adermann */ class UpdateCommand extends Command { diff --git a/src/Composer/Composer.php b/src/Composer/Composer.php index e77316e4c..20279b5ac 100644 --- a/src/Composer/Composer.php +++ b/src/Composer/Composer.php @@ -24,6 +24,7 @@ use Composer\Autoload\AutoloadGenerator; /** * @author Jordi Boggiano * @author Konstantin Kudryashiv + * @author Nils Adermann */ class Composer { diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index a7609469a..ae18bee50 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -31,6 +31,7 @@ use Composer\Package\Version\VersionParser; * @author Ryan Weaver * @author Jordi Boggiano * @author Igor Wiedler + * @author Nils Adermann */ class Factory { diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index aec6e55a7..3e9a9bf6b 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -48,6 +48,7 @@ use Composer\Script\ScriptEvents; * @author Jordi Boggiano * @author Beau Simensen * @author Konstantin Kudryashov + * @author Nils Adermann */ class Installer { diff --git a/src/Composer/Installer/InstallationManager.php b/src/Composer/Installer/InstallationManager.php index b26273847..a43acbbda 100644 --- a/src/Composer/Installer/InstallationManager.php +++ b/src/Composer/Installer/InstallationManager.php @@ -29,6 +29,7 @@ use Composer\Util\StreamContextFactory; * * @author Konstantin Kudryashov * @author Jordi Boggiano + * @author Nils Adermann */ class InstallationManager { diff --git a/src/Composer/Installer/PluginInstaller.php b/src/Composer/Installer/PluginInstaller.php index 046aced45..61c5a2823 100644 --- a/src/Composer/Installer/PluginInstaller.php +++ b/src/Composer/Installer/PluginInstaller.php @@ -19,9 +19,10 @@ use Composer\Repository\InstalledRepositoryInterface; use Composer\Package\PackageInterface; /** - * Installer installation manager. + * Installer for plugin packages * * @author Jordi Boggiano + * @author Nils Adermann */ class PluginInstaller extends LibraryInstaller { diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php index 29ed98321..7c26bd290 100644 --- a/src/Composer/Util/RemoteFilesystem.php +++ b/src/Composer/Util/RemoteFilesystem.php @@ -19,6 +19,7 @@ use Composer\Downloader\TransportException; /** * @author François Pluchino * @author Jordi Boggiano + * @author Nils Adermann */ class RemoteFilesystem { From 3b519e44c44fef5d034ab8c727d15c87bdfa814c Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 15 Aug 2013 17:18:10 +0200 Subject: [PATCH 025/238] Rename PrepareRemoteFilesystem event to PreFileDownload --- src/Composer/Downloader/FileDownloader.php | 8 ++++---- src/Composer/Plugin/PluginEvents.php | 6 +++--- ...RemoteFilesystemEvent.php => PreFileDownloadEvent.php} | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) rename src/Composer/Plugin/{PrepareRemoteFilesystemEvent.php => PreFileDownloadEvent.php} (95%) diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index b9852d730..40cbe0a12 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -18,7 +18,7 @@ use Composer\IO\IOInterface; use Composer\Package\PackageInterface; use Composer\Package\Version\VersionParser; use Composer\Plugin\PluginEvents; -use Composer\Plugin\PrepareRemoteFilesystemEvent; +use Composer\Plugin\PreFileDownloadEvent; use Composer\EventDispatcher\EventDispatcher; use Composer\Util\Filesystem; use Composer\Util\GitHub; @@ -94,11 +94,11 @@ class FileDownloader implements DownloaderInterface $processedUrl = $this->processUrl($package, $url); $hostname = parse_url($processedUrl, PHP_URL_HOST); - $prepRfsEvent = new PrepareRemoteFilesystemEvent(PluginEvents::PREPARE_REMOTE_FILESYSTEM, $this->rfs, $processedUrl); + $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $processedUrl); if ($this->eventDispatcher) { - $this->eventDispatcher->dispatch($prepRfsEvent->getName(), $prepRfsEvent); + $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent); } - $rfs = $prepRfsEvent->getRemoteFilesystem(); + $rfs = $preFileDownloadEvent->getRemoteFilesystem(); if (strpos($hostname, '.github.com') === (strlen($hostname) - 11)) { $hostname = 'github.com'; diff --git a/src/Composer/Plugin/PluginEvents.php b/src/Composer/Plugin/PluginEvents.php index bfdfba3dd..cbf9b1148 100644 --- a/src/Composer/Plugin/PluginEvents.php +++ b/src/Composer/Plugin/PluginEvents.php @@ -20,12 +20,12 @@ namespace Composer\Plugin; class PluginEvents { /** - * The PREPARE_REMOTE_FILESYSTEM event occurs before downloading a file + * The PRE_FILE_DOWNLOAD event occurs before downloading a file * * The event listener method receives a - * Composer\Plugin\PrepareRemoteFilesystemEvent instance. + * Composer\Plugin\PreFileDownloadEvent instance. * * @var string */ - const PREPARE_REMOTE_FILESYSTEM = 'prepare-remote-filesystem'; + const PRE_FILE_DOWNLOAD = 'pre-file-download'; } diff --git a/src/Composer/Plugin/PrepareRemoteFilesystemEvent.php b/src/Composer/Plugin/PreFileDownloadEvent.php similarity index 95% rename from src/Composer/Plugin/PrepareRemoteFilesystemEvent.php rename to src/Composer/Plugin/PreFileDownloadEvent.php index 91b0543f3..94621a5c2 100644 --- a/src/Composer/Plugin/PrepareRemoteFilesystemEvent.php +++ b/src/Composer/Plugin/PreFileDownloadEvent.php @@ -18,11 +18,11 @@ use Composer\EventDispatcher\Event; use Composer\Util\RemoteFilesystem; /** - * The Prepare Remote Filesystem Event. + * The pre file download event. * * @author Nils Adermann */ -class PrepareRemoteFilesystemEvent extends Event +class PreFileDownloadEvent extends Event { /** * @var RemoteFilesystem From 3e1519cde09cbbf2e33fa4acce983453f30f1f75 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 15 Aug 2013 18:04:13 +0200 Subject: [PATCH 026/238] Complete missing docblocks and fix incorrect ones --- .../EventDispatcher/EventDispatcher.php | 22 ++++++++ src/Composer/Plugin/PluginManager.php | 51 ++++++++++++++++++- src/Composer/Plugin/PreFileDownloadEvent.php | 12 ++--- 3 files changed, 78 insertions(+), 7 deletions(-) diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index 3762529e7..acf8d2f2c 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -165,11 +165,25 @@ class EventDispatcher $className::$methodName($event); } + /** + * Add a listener for a particular event + * + * @param string $eventName The event name - typically a constant + * @param Callable $listener A callable expecting an event argument + * @param integer $priority A higher value represents a higher priority + */ protected function addListener($eventName, $listener, $priority = 0) { $this->listeners[$eventName][$priority][] = $listener; } + /** + * Adds object methods as listeners for the events in getSubscribedEvents + * + * @see EventSubscriberInterface + * + * @param EventSubscriberInterface $subscriber + */ public function addSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { @@ -185,6 +199,12 @@ class EventDispatcher } } + /** + * Retrieves all listeners for a given event + * + * @param Event $event + * @return array All listeners: callables and scripts + */ protected function getListeners(Event $event) { $scriptListeners = $this->getScriptListeners($event); @@ -201,6 +221,8 @@ class EventDispatcher } /** + * Finds all listeners defined as scripts in the package + * * @param Event $event Event object * @return array Listeners */ diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index a6956c24e..386de461b 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -45,6 +45,9 @@ class PluginManager $this->io = $io; } + /** + * Loads all plugins from currently installed plugin packages + */ public function loadInstalledPlugins() { $repo = $this->composer->getRepositoryManager()->getLocalRepository(); @@ -59,7 +62,7 @@ class PluginManager } /** - * Adds plugin + * Adds a plugin, activates it and registers it with the event dispatcher * * @param PluginInterface $plugin plugin instance */ @@ -73,11 +76,25 @@ class PluginManager } } + /** + * Gets all currently active plugin instances + * + * @return array plugins + */ public function getPlugins() { return $this->plugins; } + /** + * Recursively generates a map of package names to packages for all deps + * + * @param Pool $pool Package pool of installed packages + * @param array $collected Current state of the map for recursion + * @param PackageInterface $package The package to analyze + * + * @return array Map of package names to packages + */ protected function collectDependencies(Pool $pool, array $collected, PackageInterface $package) { $requires = array_merge( @@ -96,6 +113,16 @@ class PluginManager return $collected; } + /** + * Resolves a package link to a package in the installed pool + * + * Since dependencies are already installed this should always find one. + * + * @param Pool $pool Pool of installed packages only + * @param Link $link Package link to look up + * + * @return PackageInterface|null The found package + */ protected function lookupInstalledPackage(Pool $pool, Link $link) { $packages = $pool->whatProvides($link->getTarget(), $link->getConstraint()); @@ -103,6 +130,14 @@ class PluginManager return (!empty($packages)) ? $packages[0] : null; } + /** + * Register a plugin package, activate it etc. + * + * If it's of type composer-installer it is registered as an installer + * instead for BC + * + * @param PackageInterface $package + */ public function registerPackage(PackageInterface $package) { $oldInstallerPlugin = ($package->getType() === 'composer-installer'); @@ -149,6 +184,12 @@ class PluginManager } } + /** + * Retrieves the path a package is installed to. + * + * @param PackageInterface $package + * @return string Install path + */ public function getInstallPath(PackageInterface $package) { $targetDir = $package->getTargetDir(); @@ -156,6 +197,14 @@ class PluginManager return $this->getPackageBasePath($package) . ($targetDir ? '/'.$targetDir : ''); } + /** + * Retrieves the base path a package gets installed into. + * + * Does not take targetDir into account. + * + * @param PackageInterface $package + * @return string Base path + */ protected function getPackageBasePath(PackageInterface $package) { $vendorDir = rtrim($this->composer->getConfig()->get('vendor-dir'), '/'); diff --git a/src/Composer/Plugin/PreFileDownloadEvent.php b/src/Composer/Plugin/PreFileDownloadEvent.php index 94621a5c2..847477e10 100644 --- a/src/Composer/Plugin/PreFileDownloadEvent.php +++ b/src/Composer/Plugin/PreFileDownloadEvent.php @@ -37,11 +37,9 @@ class PreFileDownloadEvent extends Event /** * Constructor. * - * @param string $name The event name - * @param Composer $composer The composer object - * @param IOInterface $io The IOInterface object - * @param boolean $devMode Whether or not we are in dev mode - * @param OperationInterface $operation The operation object + * @param string $name The event name + * @param RemoteFilesystem $rfs + * @param string $processedUrl */ public function __construct($name, RemoteFilesystem $rfs, $processedUrl) { @@ -53,7 +51,7 @@ class PreFileDownloadEvent extends Event /** * Returns the remote filesystem * - * @return OperationInterface + * @return RemoteFilesystem */ public function getRemoteFilesystem() { @@ -62,6 +60,8 @@ class PreFileDownloadEvent extends Event /** * Sets the remote filesystem + * + * @param RemoteFilesystem $rfs */ public function setRemoteFilesystem(RemoteFilesystem $rfs) { From 15ac7be6f1115c176dd9849ee3530b8aa8a94d48 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 15 Aug 2013 18:46:17 +0200 Subject: [PATCH 027/238] Fix disabling plugins which has to happen in the factory now --- src/Composer/Command/Command.php | 5 +++-- src/Composer/Command/CreateProjectCommand.php | 2 +- src/Composer/Command/InstallCommand.php | 11 ++++++----- src/Composer/Command/UpdateCommand.php | 11 ++++++----- src/Composer/Console/Application.php | 5 +++-- src/Composer/Factory.php | 12 ++++++++---- src/Composer/Installer/InstallationManager.php | 1 + 7 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/Composer/Command/Command.php b/src/Composer/Command/Command.php index 6e91ff869..862b54e58 100644 --- a/src/Composer/Command/Command.php +++ b/src/Composer/Command/Command.php @@ -38,16 +38,17 @@ abstract class Command extends BaseCommand /** * @param bool $required + * @param bool $disablePlugins * @throws \RuntimeException * @return Composer */ - public function getComposer($required = true) + public function getComposer($required = true, $disablePlugins = false) { if (null === $this->composer) { $application = $this->getApplication(); if ($application instanceof Application) { /* @var $application Application */ - $this->composer = $application->getComposer($required); + $this->composer = $application->getComposer($required, $disablePlugins); } elseif ($required) { throw new \RuntimeException( 'Could not create a Composer\Composer instance, you must inject '. diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index 308f1d204..c764c9340 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -151,7 +151,7 @@ EOT $installedFromVcs = false; } - $composer = Factory::create($io); + $composer = Factory::create($io, null, $disablePlugins); if ($noScripts === false) { // dispatch event diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index edf8ae593..adc2ca595 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -58,7 +58,12 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { - $composer = $this->getComposer(); + if ($input->getOption('no-custom-installers')) { + $output->writeln('You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.'); + $input->setOption('no-plugins', true); + } + + $composer = $this->getComposer(true, $input->getOption('no-plugins')); $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress')); $io = $this->getIO(); $install = Installer::create($io, $composer); @@ -92,10 +97,6 @@ EOT ->setOptimizeAutoloader($input->getOption('optimize-autoloader')) ; - if ($input->getOption('no-custom-installers')) { - $output->writeln('You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.'); - $input->setOption('no-plugins', true); - } if ($input->getOption('no-plugins')) { $install->disablePlugins(); } diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index 3ac0e1401..728fadd24 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -62,7 +62,12 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { - $composer = $this->getComposer(); + if ($input->getOption('no-custom-installers')) { + $output->writeln('You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.'); + $input->setOption('no-plugins', true); + } + + $composer = $this->getComposer(true, $input->getOption('no-plugins')); $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress')); $io = $this->getIO(); $install = Installer::create($io, $composer); @@ -98,10 +103,6 @@ EOT ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $input->getArgument('packages')) ; - if ($input->getOption('no-custom-installers')) { - $output->writeln('You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.'); - $input->setOption('no-plugins', true); - } if ($input->getOption('no-plugins')) { $install->disablePlugins(); } diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index 0d1e45500..63bb59124 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -165,14 +165,15 @@ class Application extends BaseApplication /** * @param bool $required + * @param bool $disablePlugins * @throws JsonValidationException * @return \Composer\Composer */ - public function getComposer($required = true) + public function getComposer($required = true, $disablePlugins = false) { if (null === $this->composer) { try { - $this->composer = Factory::create($this->io); + $this->composer = Factory::create($this->io, null, $disablePlugins); } catch (\InvalidArgumentException $e) { if ($required) { $this->io->write($e->getMessage()); diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index ae18bee50..28b00fd49 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -177,11 +177,12 @@ class Factory * @param IOInterface $io IO instance * @param array|string|null $localConfig either a configuration array or a filename to read from, if null it will * read from the default filename + * @param bool $disablePlugins Whether plugins should not be loaded * @throws \InvalidArgumentException * @throws \UnexpectedValueException * @return Composer */ - public function createComposer(IOInterface $io, $localConfig = null) + public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = false) { // load Composer configuration if (null === $localConfig) { @@ -269,7 +270,9 @@ class Factory $composer->setLocker($locker); } - $pm->loadInstalledPlugins(); + if (!$disablePlugins) { + $pm->loadInstalledPlugins(); + } return $composer; } @@ -408,12 +411,13 @@ class Factory * @param IOInterface $io IO instance * @param mixed $config either a configuration array or a filename to read from, if null it will read from * the default filename + * @param bool $disablePlugins Whether plugins should not be loaded * @return Composer */ - public static function create(IOInterface $io, $config = null) + public static function create(IOInterface $io, $config = null, $disablePlugins = false) { $factory = new static(); - return $factory->createComposer($io, $config); + return $factory->createComposer($io, $config, $disablePlugins); } } diff --git a/src/Composer/Installer/InstallationManager.php b/src/Composer/Installer/InstallationManager.php index a43acbbda..21b16e2fd 100644 --- a/src/Composer/Installer/InstallationManager.php +++ b/src/Composer/Installer/InstallationManager.php @@ -14,6 +14,7 @@ namespace Composer\Installer; use Composer\Package\PackageInterface; use Composer\Package\AliasPackage; +use Composer\Plugin\PluginInstaller; use Composer\Repository\RepositoryInterface; use Composer\Repository\InstalledRepositoryInterface; use Composer\DependencyResolver\Operation\OperationInterface; From a8c0170a91e927359dd7eb4934e98c502555d1b6 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 16 Aug 2013 15:14:38 +0200 Subject: [PATCH 028/238] Revert constructor arguments to old order for custom installers --- src/Composer/Plugin/PluginManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index 386de461b..cfbc804d6 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -175,7 +175,7 @@ class PluginManager } if ($oldInstallerPlugin) { - $installer = new $class($this->composer, $this->io); + $installer = new $class($this->io, $this->composer); $this->composer->getInstallationManager()->addInstaller($installer); } else { $plugin = new $class(); From 5867d477bee5d964e6e104a352b208a1e76090ac Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 30 Aug 2013 12:51:06 +0200 Subject: [PATCH 029/238] Use call_user_func for PHP < 5.4 compatability and accept __invoke --- src/Composer/EventDispatcher/EventDispatcher.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index acf8d2f2c..912d4eaea 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -119,8 +119,8 @@ class EventDispatcher $listeners = $this->getListeners($event); foreach ($listeners as $callable) { - if ((is_array($callable) && is_callable($callable)) || $callable instanceof Closure) { - $callable($event); + if (!is_string($callable) && is_callable($callable)) { + call_user_func($callable, $event); } elseif ($this->isPhpScript($callable)) { $className = substr($callable, 0, strpos($callable, '::')); $methodName = substr($callable, strpos($callable, '::') + 2); From c5c180fdd236adb67d8c905991026f393ece32c0 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 30 Aug 2013 14:02:34 +0200 Subject: [PATCH 030/238] Load plugins from global vendor dir too --- src/Composer/Factory.php | 24 +++++++++++++++++++++-- src/Composer/Plugin/PluginManager.php | 28 ++++++++++++++++++++------- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 28b00fd49..18b4a57f4 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -18,6 +18,7 @@ use Composer\IO\IOInterface; use Composer\Package\Archiver; use Composer\Repository\ComposerRepository; use Composer\Repository\RepositoryManager; +use Composer\Repository\RepositoryInterface; use Composer\Util\ProcessExecutor; use Composer\Util\RemoteFilesystem; use Symfony\Component\Console\Formatter\OutputFormatterStyle; @@ -252,6 +253,7 @@ class Factory $generator = new AutoloadGenerator($dispatcher); $composer->setAutoloadGenerator($generator); + $globalRepository = $this->createGlobalRepository($config, $vendorDir); $pm = $this->createPluginManager($composer, $io); $composer->setPluginManager($pm); @@ -306,6 +308,24 @@ class Factory $rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json'))); } + /** + * @param Config $config + * @param string $vendorDir + */ + protected function createGlobalRepository(Config $config, $vendorDir) + { + if ($config->get('home') == $vendorDir) { + return null; + } + + $path = $config->get('home').'/vendor/composer/installed.json'; + if (!file_exists($path)) { + return null; + } + + return new Repository\InstalledFilesystemRepository(new JsonFile($path)); + } + /** * @param IO\IOInterface $io * @param Config $config @@ -367,9 +387,9 @@ class Factory /** * @return Plugin\PluginManager */ - protected function createPluginManager(Composer $composer, IOInterface $io) + protected function createPluginManager(Composer $composer, IOInterface $io, RepositoryInterface $globalRepository = null) { - return new Plugin\PluginManager($composer, $io); + return new Plugin\PluginManager($composer, $io, $globalRepository); } /** diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index cfbc804d6..0a4cd5583 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -14,8 +14,9 @@ namespace Composer\Plugin; use Composer\Composer; use Composer\EventDispatcher\EventSubscriberInterface; -use Composer\Package\Package; use Composer\IO\IOInterface; +use Composer\Package\Package; +use Composer\Repository\RepositoryInterface; use Composer\Package\PackageInterface; use Composer\Package\Link; use Composer\DependencyResolver\Pool; @@ -29,6 +30,7 @@ class PluginManager { protected $composer; protected $io; + protected $globalRepository; protected $plugins = array(); @@ -39,10 +41,11 @@ class PluginManager * * @param Composer $composer */ - public function __construct(Composer $composer, IOInterface $io) + public function __construct(Composer $composer, IOInterface $io, RepositoryInterface $globalRepository = null) { $this->composer = $composer; $this->io = $io; + $this->globalRepository = $globalRepository; } /** @@ -53,11 +56,10 @@ class PluginManager $repo = $this->composer->getRepositoryManager()->getLocalRepository(); if ($repo) { - foreach ($repo->getPackages() as $package) { - if ('composer-plugin' === $package->getType() || 'composer-installer' === $package->getType()) { - $this->registerPackage($package); - } - } + $this->loadRepository($repo); + } + if ($this->globalRepository) { + $this->loadRepository($this->globalRepository); } } @@ -86,6 +88,15 @@ class PluginManager return $this->plugins; } + protected function loadRepository(RepositoryInterface $repo) + { + foreach ($repo->getPackages() as $package) { + if ('composer-plugin' === $package->getType() || 'composer-installer' === $package->getType()) { + $this->registerPackage($package); + } + } + } + /** * Recursively generates a map of package names to packages for all deps * @@ -150,6 +161,9 @@ class PluginManager $pool = new Pool('dev'); $pool->addRepository($this->composer->getRepositoryManager()->getLocalRepository()); + if ($this->globalRepository) { + $pool->addRepository($this->globalRepository); + } $autoloadPackages = array($package->getName() => $package); $autoloadPackages = $this->collectDependencies($pool, $autoloadPackages, $package); From 1892f57e474d0ee748c1a57b87a37c2ea29ef07b Mon Sep 17 00:00:00 2001 From: Alan Hollis Date: Fri, 30 Aug 2013 12:09:17 +0000 Subject: [PATCH 031/238] Fix file layout in unit tests Changes made in previious commit made the output of the file change, which in turn broke the unit tests. This commit updates the fixtures to match the new output. --- .../Autoload/Fixtures/autoload_real_files_by_dependency.php | 3 ++- .../Test/Autoload/Fixtures/autoload_real_functions.php | 3 ++- .../Test/Autoload/Fixtures/autoload_real_target_dir.php | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_real_files_by_dependency.php b/tests/Composer/Test/Autoload/Fixtures/autoload_real_files_by_dependency.php index 376f8512c..9321b86c8 100644 --- a/tests/Composer/Test/Autoload/Fixtures/autoload_real_files_by_dependency.php +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_real_files_by_dependency.php @@ -38,7 +38,8 @@ class ComposerAutoloaderInitFilesAutoloadOrder $loader->register(true); - foreach (require __DIR__ . '/autoload_files.php' as $file) { + $includeFiles = require __DIR__ . '/autoload_files.php'; + foreach ($includeFiles as $file) { require $file; } diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_real_functions.php b/tests/Composer/Test/Autoload/Fixtures/autoload_real_functions.php index 3ddbc9ca9..6407c93b7 100644 --- a/tests/Composer/Test/Autoload/Fixtures/autoload_real_functions.php +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_real_functions.php @@ -38,7 +38,8 @@ class ComposerAutoloaderInitFilesAutoload $loader->register(true); - foreach (require __DIR__ . '/autoload_files.php' as $file) { + $includeFiles = require __DIR__ . '/autoload_files.php'; + foreach ($includeFiles as $file) { require $file; } diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_real_target_dir.php b/tests/Composer/Test/Autoload/Fixtures/autoload_real_target_dir.php index 347454fc5..32e155422 100644 --- a/tests/Composer/Test/Autoload/Fixtures/autoload_real_target_dir.php +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_real_target_dir.php @@ -40,7 +40,8 @@ class ComposerAutoloaderInitTargetDir $loader->register(true); - foreach (require __DIR__ . '/autoload_files.php' as $file) { + $includeFiles = require __DIR__ . '/autoload_files.php'; + foreach ($includeFiles as $file) { require $file; } From 5993450d5a2cdef4a11c039f339a6fd652df7ca7 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 30 Aug 2013 14:11:20 +0200 Subject: [PATCH 032/238] Load plugin code from global vendor dir correctly --- src/Composer/Factory.php | 2 +- src/Composer/Plugin/PluginManager.php | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 18b4a57f4..a3736300c 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -254,7 +254,7 @@ class Factory $composer->setAutoloadGenerator($generator); $globalRepository = $this->createGlobalRepository($config, $vendorDir); - $pm = $this->createPluginManager($composer, $io); + $pm = $this->createPluginManager($composer, $io, $globalRepository); $composer->setPluginManager($pm); // add installers to the manager diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index 0a4cd5583..f331337c0 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -160,7 +160,8 @@ class PluginManager $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']); $pool = new Pool('dev'); - $pool->addRepository($this->composer->getRepositoryManager()->getLocalRepository()); + $localRepo = $this->composer->getRepositoryManager()->getLocalRepository(); + $pool->addRepository($localRepo); if ($this->globalRepository) { $pool->addRepository($this->globalRepository); } @@ -171,7 +172,7 @@ class PluginManager $generator = $this->composer->getAutoloadGenerator(); $autoloads = array(); foreach ($autoloadPackages as $autoloadPackage) { - $downloadPath = $this->getInstallPath($autoloadPackage); + $downloadPath = $this->getInstallPath($autoloadPackage, !$localRepo->hasPackage($autoloadPackage)); $autoloads[] = array($autoloadPackage, $downloadPath); } @@ -202,13 +203,15 @@ class PluginManager * Retrieves the path a package is installed to. * * @param PackageInterface $package + * @param bool $global Whether this is a global package + * * @return string Install path */ - public function getInstallPath(PackageInterface $package) + public function getInstallPath(PackageInterface $package, $global = false) { $targetDir = $package->getTargetDir(); - return $this->getPackageBasePath($package) . ($targetDir ? '/'.$targetDir : ''); + return $this->getPackageBasePath($package, $global) . ($targetDir ? '/'.$targetDir : ''); } /** @@ -217,11 +220,17 @@ class PluginManager * Does not take targetDir into account. * * @param PackageInterface $package + * @param bool $global Whether this is a global package + * * @return string Base path */ - protected function getPackageBasePath(PackageInterface $package) + protected function getPackageBasePath(PackageInterface $package, $global = false) { - $vendorDir = rtrim($this->composer->getConfig()->get('vendor-dir'), '/'); + if ($global) { + $vendorDir = $this->composer->getConfig()->get('home').'/vendor'; + } else { + $vendorDir = rtrim($this->composer->getConfig()->get('vendor-dir'), '/'); + } return ($vendorDir ? $vendorDir.'/' : '') . $package->getPrettyName(); } } From 2bf90b544a3ec04b83a1d565759735edd1d187f1 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 31 Aug 2013 15:22:08 +0200 Subject: [PATCH 033/238] Fix parsing of trunk in SvnDriver, fixes composer/satis#88 --- src/Composer/Repository/Vcs/SvnDriver.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Composer/Repository/Vcs/SvnDriver.php b/src/Composer/Repository/Vcs/SvnDriver.php index b979c2e4b..c5a67b455 100644 --- a/src/Composer/Repository/Vcs/SvnDriver.php +++ b/src/Composer/Repository/Vcs/SvnDriver.php @@ -193,7 +193,13 @@ class SvnDriver extends VcsDriver if (null === $this->branches) { $this->branches = array(); - $output = $this->execute('svn ls --verbose', $this->baseUrl . '/'); + if (false === strpos($this->trunkPath, '/')) { + $trunkParent = $this->baseUrl . '/'; + } else { + $trunkParent = $this->baseUrl . '/' . dirname($this->trunkPath) . '/'; + } + + $output = $this->execute('svn ls --verbose', $trunkParent); if ($output) { foreach ($this->process->splitLines($output) as $line) { $line = trim($line); From a080ae3a51a16e1cbfe0c881797dba869cef95af Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sat, 31 Aug 2013 15:42:26 +0200 Subject: [PATCH 034/238] Make sure directories we are downloading to are empty We already clear them on error anyway and usually they should be empty, but just to be safe. --- src/Composer/Downloader/FileDownloader.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index 8ed0712bf..e67693563 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -79,6 +79,7 @@ class FileDownloader implements DownloaderInterface throw new \InvalidArgumentException('The given package is missing url information'); } + $this->filesystem->removeDirectory($path); $this->filesystem->ensureDirectoryExists($path); $fileName = $this->getFileName($package, $path); From 72919e04b0dfdedf160ca49c0da88bd782d7ac99 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sat, 31 Aug 2013 15:55:12 +0200 Subject: [PATCH 035/238] Correct FileDownloaderTest for invalid checksum --- tests/Composer/Test/Downloader/FileDownloaderTest.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/Composer/Test/Downloader/FileDownloaderTest.php b/tests/Composer/Test/Downloader/FileDownloaderTest.php index 99dcaab18..cc7d25df3 100644 --- a/tests/Composer/Test/Downloader/FileDownloaderTest.php +++ b/tests/Composer/Test/Downloader/FileDownloaderTest.php @@ -17,13 +17,13 @@ use Composer\Util\Filesystem; class FileDownloaderTest extends \PHPUnit_Framework_TestCase { - protected function getDownloader($io = null, $config = null, $rfs = null) + protected function getDownloader($io = null, $config = null, $rfs = null, $filesystem = null) { $io = $io ?: $this->getMock('Composer\IO\IOInterface'); $config = $config ?: $this->getMock('Composer\Config'); $rfs = $rfs ?: $this->getMockBuilder('Composer\Util\RemoteFilesystem')->disableOriginalConstructor()->getMock(); - return new FileDownloader($io, $config, null, $rfs); + return new FileDownloader($io, $config, null, $rfs, $filesystem); } /** @@ -134,12 +134,13 @@ class FileDownloaderTest extends \PHPUnit_Framework_TestCase ->method('getDistSha1Checksum') ->will($this->returnValue('invalid')) ; + $filesystem = $this->getMock('Composer\Util\Filesystem'); do { $path = sys_get_temp_dir().'/'.md5(time().mt_rand()); } while (file_exists($path)); - $downloader = $this->getDownloader(); + $downloader = $this->getDownloader(null, null, null, $filesystem); // make sure the file expected to be downloaded is on disk already mkdir($path, 0777, true); From bf080192929320ab5cb043dd3ee933a0b8c9d17c Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sat, 31 Aug 2013 16:20:38 +0200 Subject: [PATCH 036/238] Load plugins and installers prior to checking installed packages --- src/Composer/Factory.php | 8 ++++---- src/Composer/Plugin/PluginManager.php | 2 +- tests/Composer/Test/Plugin/PluginInstallerTest.php | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index a3736300c..a1d17232d 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -260,6 +260,10 @@ class Factory // add installers to the manager $this->createDefaultInstallers($im, $composer, $io); + if (!$disablePlugins) { + $pm->loadInstalledPlugins(); + } + // purge packages if they have been deleted on the filesystem $this->purgePackages($rm, $im); @@ -272,10 +276,6 @@ class Factory $composer->setLocker($locker); } - if (!$disablePlugins) { - $pm->loadInstalledPlugins(); - } - return $composer; } diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index f331337c0..c67ea9622 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -172,7 +172,7 @@ class PluginManager $generator = $this->composer->getAutoloadGenerator(); $autoloads = array(); foreach ($autoloadPackages as $autoloadPackage) { - $downloadPath = $this->getInstallPath($autoloadPackage, !$localRepo->hasPackage($autoloadPackage)); + $downloadPath = $this->getInstallPath($autoloadPackage, ($this->globalRepository && $this->globalRepository->hasPackage($autoloadPackage))); $autoloads[] = array($autoloadPackage, $downloadPath); } diff --git a/tests/Composer/Test/Plugin/PluginInstallerTest.php b/tests/Composer/Test/Plugin/PluginInstallerTest.php index 5d21f59db..1e67eafe1 100644 --- a/tests/Composer/Test/Plugin/PluginInstallerTest.php +++ b/tests/Composer/Test/Plugin/PluginInstallerTest.php @@ -69,6 +69,7 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase $config->merge(array( 'config' => array( 'vendor-dir' => __DIR__.'/Fixtures/', + 'home' => __DIR__.'/Fixtures', 'bin-dir' => __DIR__.'/Fixtures/bin', ), )); From 80184b87d192c3903d62e44c239eb318f6ddcc5c Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 2 Sep 2013 11:21:37 +0200 Subject: [PATCH 037/238] Fix undefined index error, fixes #2224 --- src/Composer/Command/CreateProjectCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index 222add8e5..b62033d17 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -275,7 +275,7 @@ EOT } // select highest version if we have many - $package = $candidates[0]; + $package = reset($candidates); foreach ($candidates as $candidate) { if (version_compare($package->getVersion(), $candidate->getVersion(), '<')) { $package = $candidate; From a980228b7689e712f2dc66d95e1117e6706cd712 Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Wed, 24 Jul 2013 09:56:08 -0500 Subject: [PATCH 038/238] Added Perforce VCS to Composer. Added Perforce utility class, PerforceDriver and PeforceDownloader Added PerforceDriverTest Updated Factory, VcsRepository to incorporate Perforce classes. Modified ArchivableFilesFinderTest to skip Mercurial test that does not work for me. --- src/Composer/Factory.php | 1 + src/Composer/Repository/VcsRepository.php | 1 + .../Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php | 1 + 3 files changed, 3 insertions(+) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 82c5084c2..b7a83446d 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -325,6 +325,7 @@ class Factory $dm->setDownloader('git', new Downloader\GitDownloader($io, $config)); $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config)); $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config)); + $dm->setDownloader('perforce', new Downloader\PerforceDownloader($io, $config)); $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $cache)); $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $cache)); $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $cache)); diff --git a/src/Composer/Repository/VcsRepository.php b/src/Composer/Repository/VcsRepository.php index f8fb84005..bb3bacc68 100644 --- a/src/Composer/Repository/VcsRepository.php +++ b/src/Composer/Repository/VcsRepository.php @@ -46,6 +46,7 @@ class VcsRepository extends ArrayRepository 'git' => 'Composer\Repository\Vcs\GitDriver', 'hg-bitbucket' => 'Composer\Repository\Vcs\HgBitbucketDriver', 'hg' => 'Composer\Repository\Vcs\HgDriver', + 'perforce' => 'Composer\Repository\Vcs\PerforceDriver', // svn must be last because identifying a subversion server for sure is practically impossible 'svn' => 'Composer\Repository\Vcs\SvnDriver', ); diff --git a/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php b/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php index 536f2128c..2623007d8 100644 --- a/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php +++ b/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php @@ -146,6 +146,7 @@ class ArchivableFilesFinderTest extends \PHPUnit_Framework_TestCase public function testHgExcludes() { + $this->markTestSkipped('Mercurial test does not work.'); // Ensure that Mercurial is available for testing. if (!$this->isProcessAvailable('hg')) { return $this->markTestSkipped('Mercurial is not available.'); From 0d061f25300062067488b64c35ff28d3cc0bedf8 Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Wed, 24 Jul 2013 10:06:35 -0500 Subject: [PATCH 039/238] Added Perforce to Composer --- .../Downloader/PerforceDownloader.php | 109 +++++++++ .../Repository/Vcs/PerforceDriver.php | 218 ++++++++++++++++++ src/Composer/Util/Perforce.php | 70 ++++++ .../Repository/Vcs/PerforceDriverTest.php | 152 ++++++++++++ 4 files changed, 549 insertions(+) create mode 100644 src/Composer/Downloader/PerforceDownloader.php create mode 100644 src/Composer/Repository/Vcs/PerforceDriver.php create mode 100644 src/Composer/Util/Perforce.php create mode 100644 tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php new file mode 100644 index 000000000..b82abdc61 --- /dev/null +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -0,0 +1,109 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Downloader; + +use Composer\Package\PackageInterface; +use Composer\Util\Perforce; +#use Composer\Util\GitHub; +#use Composer\Util\Git as GitUtil; + +/** + * @author Jordi Boggiano + */ +class PerforceDownloader extends VcsDownloader +{ + private $hasStashedChanges = false; + + /** + * {@inheritDoc} + */ + public function doDownload(PackageInterface $package, $path) + { + print ("Perforce Downloader:doDownload - path:" . var_export($path, true) . "\n"); + + $ref = $package->getSourceReference(); + $p4client = "composer_perforce_dl_" . str_replace("/", "_", str_replace("//", "", $ref)); + + $clientSpec = "$path/$p4client.p4.spec"; + print ("PerforceDownloader:doDownload - clientSpec: $clientSpec, targetDir: $path, p4Client: $p4client\n\n"); + $perforce = new Perforce(); + $perforce->writeP4ClientSpec($clientSpec, $path, $p4client, $ref); + $perforce->syncCodeBase($clientSpec, $path, $p4client); + } + + /** + * {@inheritDoc} + */ + public function doUpdate(PackageInterface $initial, PackageInterface $target, $path) + { + print("PerforceDownloader:doUpdate\n"); + +// $this->cleanEnv(); +// $path = $this->normalizePath($path); +// +// $ref = $target->getSourceReference(); +// $this->io->write(" Checking out ".$ref); +// $command = 'git remote set-url composer %s && git fetch composer && git fetch --tags composer'; +// +// // capture username/password from URL if there is one +// $this->process->execute('git remote -v', $output, $path); +// if (preg_match('{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im', $output, $match)) { +// $this->io->setAuthentication($match[3], urldecode($match[1]), urldecode($match[2])); +// } +// +// $commandCallable = function($url) use ($command) { +// return sprintf($command, escapeshellarg($url)); +// }; +// +// $this->runCommand($commandCallable, $target->getSourceUrl(), $path); +// $this->updateToCommit($path, $ref, $target->getPrettyVersion(), $target->getReleaseDate()); + } + + /** + * {@inheritDoc} + */ + public function getLocalChanges($path) + { + print("PerforceDownloader:getLocalChanges\n"); +// $this->cleanEnv(); +// $path = $this->normalizePath($path); +// if (!is_dir($path.'/.git')) { +// return; +// } +// +// $command = 'git status --porcelain --untracked-files=no'; +// if (0 !== $this->process->execute($command, $output, $path)) { +// throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()); +// } +// +// return trim($output) ?: null; + } + + + /** + * {@inheritDoc} + */ + protected function getCommitLogs($fromReference, $toReference, $path) + { + print("PerforceDownloader:getCommitLogs\n"); +// $path = $this->normalizePath($path); +// $command = sprintf('git log %s..%s --pretty=format:"%%h - %%an: %%s"', $fromReference, $toReference); +// +// if (0 !== $this->process->execute($command, $output, $path)) { +// throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()); +// } +// +// return $output; + } + +} diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php new file mode 100644 index 000000000..6ecb47050 --- /dev/null +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -0,0 +1,218 @@ + + * Jordi Boggiano + * + * Contributor: matt-whittom + * Date: 7/17/13 + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Repository\Vcs; + +#use Composer\Downloader\TransportException; +#use Composer\Json\JsonFile; +#use Composer\Cache; +use Composer\IO\IOInterface; +use Composer\Util\Filesystem; +use Composer\Util\Perforce; +#use Composer\Util\RemoteFilesystem; +#use Composer\Util\GitHub; + +/** + * @author matt-whittom <> + */ +class PerforceDriver extends VcsDriver +{ +// protected $cache; +// protected $owner; +// protected $repository; +// protected $tags; +// protected $branches; + protected $rootIdentifier = 'mainline'; + protected $repoDir; +// protected $hasIssues; +// protected $infoCache = array(); +// protected $isPrivate = false; + protected $depot; + protected $p4client; + + /** + * {@inheritDoc} + */ + public function initialize() + { + print ("PerforceDriver:initialize\n"); + $this->depot = $this->repoConfig['depot']; + $this->p4client = "composer_perforce_$this->depot"; + $this->repoDir = $this->config->get('cache-vcs-dir') . "/$this->depot"; + $clientSpec = $this->config->get('cache-dir') . "/perforce/$this->p4client.p4.spec"; + + $this->p4Login(); + + $fs = new Filesystem(); + $fs->ensureDirectoryExists($this->repoDir); + + $stream = "//$this->depot/$this->rootIdentifier"; + $perforce = new Perforce(); + $perforce->writeP4ClientSpec($clientSpec, $this->repoDir, $this->p4client, $stream); + $perforce->syncCodeBase($clientSpec, $this->repoDir, $this->p4client); + + return true; + } + + protected function p4Login(){ + $password = trim(shell_exec('echo $P4PASSWD')); + $command = "echo $password | p4 login -a "; + shell_exec($command); + } + + + + /** + * {@inheritDoc} + */ + public function getComposerInformation($identifier) + { + print ("PerforceDriver:getComposerInformation: $identifier\n"); + $command = "p4 print $identifier/composer.json"; + $result = shell_exec($command); + $index = strpos($result, "{"); + if ($index === false){ + return; + } + if ($index >=0){ + $rawData = substr($result, $index); + $composer_info = json_decode($rawData, true); + print ("ComposerInfo is:".var_export($composer_info, true) . "\n"); + return $composer_info; + } + + +// Basically, read the composer.json file from the project. +// +// Git stuff: +// ..getComposerInfo is: array ( +// 'support' => +// array ( +// 'source' => 'http://github.com/composer/packagist', +// ), +// 'time' => '2012-09-10', +// ) + } + + /** + * {@inheritDoc} + */ + public function getRootIdentifier() + { + print ("PerforceDriver:getRootIdentifier\n"); + return $this->rootIdentifier; + } + + /** + * {@inheritDoc} + */ + public function getBranches() + { + //return $branch->$identifier + //getComposer($identifier) + //validate($branch) + print ("PerforceDriver:getBranches\n"); + $command = "p4 streams //$this->depot/..."; + $result = shell_exec($command); + + $resArray = explode("\n", $result); + $branches = array(); + foreach ($resArray as $line){ + $resBits = explode(" ", $line); + if (count($resBits) > 4){ + $branch = substr($resBits[4], 1, strlen($resBits[4])-2); + $branches[$branch] = $resBits[1]; + } + } + $branches['master'] = $branches['mainline']; + print ("PerforceDriver:getBranches - returning branches:".var_export($branches, true)."\n"); + return $branches; + } + + /** + * {@inheritDoc} + */ + public function getTags() + { + print ("PerforceDriver:getTags\n"); + return array(); + } + + /** + * {@inheritDoc} + */ + public function getDist($identifier) + { + print ("PerforceDriver:getDist: $identifier\n"); + return null; + } + + /** + * {@inheritDoc} + */ + public function getSource($identifier) + { + print ("PerforceDriver:getSource: $identifier\n"); + + $source = array ( + 'type' => 'perforce', + 'url' => $this->repoConfig['url'], + 'reference' => $identifier + ); + return $source; + } + + /** + * {@inheritDoc} + */ + public function getUrl() + { + print ("PerforceDriver:getUrl\n"); + + } + + /** + * {@inheritDoc} + */ + public function hasComposerFile($identifier) + { + print ("PerforceDriver:hasComposerFile: $identifier\n"); + + //Does the project have a composer file? + return true; + } + + /** + * {@inheritDoc} + */ + public function getContents($url) + { + print("PerforceDriver:getContents - url: $url"); + } + + /** + * {@inheritDoc} + */ + public static function supports(IOInterface $io, $url, $deep = false) + { + print ("PerforceDriver:supports\n"); + + print ("\nChecking url for support: $url\n\n"); + if (preg_match('#(^perforce)#', $url)) { + return true; + } + return false; + } +} diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php new file mode 100644 index 000000000..15f4b6ac5 --- /dev/null +++ b/src/Composer/Util/Perforce.php @@ -0,0 +1,70 @@ +ensureDirectoryExists(dirname($clientSpec)); + + $p4user = trim(shell_exec('echo $P4USER')); + print ("PerforceDriver: writing to client spec: $clientSpec\n\n"); + $spec = fopen($clientSpec, 'w'); + try { + fwrite($spec, "Client: $p4client\n\n"); + fwrite($spec, "Update: " . date("Y/m/d H:i:s") . "\n\n"); + fwrite($spec, "Access: " . date("Y/m/d H:i:s") . "\n" ); + fwrite($spec, "Owner: $p4user\n\n" ); + fwrite($spec, "Description:\n" ); + fwrite($spec, " Created by $p4user from composer.\n\n" ); + fwrite($spec, "Root: $targetDir\n\n" ); + fwrite($spec, "Options: noallwrite noclobber nocompress unlocked modtime rmdir\n\n" ); + fwrite($spec, "SubmitOptions: revertunchanged\n\n" ); + fwrite($spec, "LineEnd: local\n\n" ); + fwrite($spec, "Stream:\n" ); + fwrite($spec, " $stream\n" ); + } catch(Exception $e){ + fclose($spec); + throw $e; + } + fclose($spec); + } + + +} \ No newline at end of file diff --git a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php new file mode 100644 index 000000000..2745887ed --- /dev/null +++ b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php @@ -0,0 +1,152 @@ + + * Jordi Boggiano + * + * Contributor: matt-whittom + * Date: 7/17/13 + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Test\Repository\Vcs; + +#use Composer\Downloader\TransportException; +use Composer\Repository\Vcs\PerforceDriver; +use Composer\Util\Filesystem; +use Composer\Config; +use Composer\IO\ConsoleIO; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Output\ConsoleOutput; +use Symfony\Component\Console\Helper\HelperSet; + + +class PerforceDriverTest extends \PHPUnit_Framework_TestCase +{ + private $config; + private $io; + + public function setUp() + { + $this->config = new Config(); + $this->config->merge(array( + 'config' => array( + 'home' => sys_get_temp_dir() . '/composer-test', + ), + )); + $inputParameters = array(); + $input = new ArrayInput($inputParameters); + $output = new ConsoleOutput(); + $helperSet = new HelperSet(); + $this->io = new ConsoleIO($input, $output, $helperSet); + } + + public function tearDown() + { + $fs = new Filesystem; + $fs->removeDirectory(sys_get_temp_dir() . '/composer-test'); + } + + public function testPrivateRepository() + { + $repo_config = array( + 'url' => "perforce.vuhl.root.mrc.local:3710", + 'depot' => "lighthouse" + ); + + $vcs = new PerforceDriver($repo_config, $this->io, $this->config); + $result = $vcs->initialize(); + $this->assertTrue($result); + } + + public function testGetBranches() + { + $repo_config = array( + 'url' => "perforce.vuhl.root.mrc.local:3710", + 'depot' => "lighthouse" + ); + + $vcs = new PerforceDriver($repo_config, $this->io, $this->config); + $result = $vcs->initialize(); + $this->assertTrue($result); + $branches = $vcs->getBranches(); + //print ("\nBranches are: " . var_export($branches, true)); + $this->assertTrue(strcmp($branches['mainline'], "//lighthouse/mainline") == 0); + } + + public function testGetTags() + { + $repo_config = array( + 'url' => "perforce.vuhl.root.mrc.local:3710", + 'depot' => "lighthouse" + ); + + $vcs = new PerforceDriver($repo_config, $this->io, $this->config); + $result = $vcs->initialize(); + $this->assertTrue($result); + $tags = $vcs->getTags(); + $this->assertTrue(empty($tags)); + } + + public function testGetSource() + { + $repo_config = array( + 'url' => "perforce.vuhl.root.mrc.local:3710", + 'depot' => "lighthouse" + ); + + $vcs = new PerforceDriver($repo_config, $this->io, $this->config); + $result = $vcs->initialize(); + $this->assertTrue($result); + $identifier = $vcs->getRootIdentifier(); + $source = $vcs->getSource($identifier); + $this->assertEquals($source['type'], "perforce"); + $this->assertEquals($source['reference'], $identifier); + } + + public function testGetDist() + { + $repo_config = array( + 'url' => "perforce.vuhl.root.mrc.local:3710", + 'depot' => "lighthouse" + ); + + $vcs = new PerforceDriver($repo_config, $this->io, $this->config); + $result = $vcs->initialize(); + $this->assertTrue($result); + $identifier = $vcs->getRootIdentifier(); + $dist = $vcs->getDist($identifier); + $this->assertNull($dist); + } + + public function testGetRootIdentifier(){ + $repo_config = array( + 'url' => "perforce.vuhl.root.mrc.local:3710", + 'depot' => "lighthouse" + ); + + $vcs = new PerforceDriver($repo_config, $this->io, $this->config); + $result = $vcs->initialize(); + $this->assertTrue($result); + $rootId = $vcs->getRootIdentifier(); + $this->assertEquals("mainline", $rootId); + } + + public function testHasComposerFile(){ + $repo_config = array( + 'url' => "perforce.vuhl.root.mrc.local:3710", + 'depot' => "lighthouse" + ); + + $vcs = new PerforceDriver($repo_config, $this->io, $this->config); + $result = $vcs->initialize(); + $this->assertTrue($result); + $identifier = $vcs->getRootIdentifier(); + $value = $vcs->hasComposerFile($identifier); + $this->assertTrue($value); + } +} + From 36dd7dfea5b7c42adab172aa9985c0cd479aab42 Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Thu, 25 Jul 2013 15:25:09 -0500 Subject: [PATCH 040/238] Cleaned up perforce code Checks to see if already logged in to Perforce, and prompts for password if not and P4PASSWD is not set Checks server url with perforce call Checks for composer.json file, and returns the contents of the file already retrieved. --- .../Downloader/PerforceDownloader.php | 53 +------ .../Repository/Vcs/PerforceDriver.php | 101 +++---------- src/Composer/Util/Perforce.php | 140 ++++++++++++++---- 3 files changed, 138 insertions(+), 156 deletions(-) diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index b82abdc61..c8fcf442f 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -14,8 +14,6 @@ namespace Composer\Downloader; use Composer\Package\PackageInterface; use Composer\Util\Perforce; -#use Composer\Util\GitHub; -#use Composer\Util\Git as GitUtil; /** * @author Jordi Boggiano @@ -29,16 +27,11 @@ class PerforceDownloader extends VcsDownloader */ public function doDownload(PackageInterface $package, $path) { - print ("Perforce Downloader:doDownload - path:" . var_export($path, true) . "\n"); - $ref = $package->getSourceReference(); - $p4client = "composer_perforce_dl_" . str_replace("/", "_", str_replace("//", "", $ref)); - $clientSpec = "$path/$p4client.p4.spec"; - print ("PerforceDownloader:doDownload - clientSpec: $clientSpec, targetDir: $path, p4Client: $p4client\n\n"); - $perforce = new Perforce(); - $perforce->writeP4ClientSpec($clientSpec, $path, $p4client, $ref); - $perforce->syncCodeBase($clientSpec, $path, $p4client); + $perforce = new Perforce($ref, $package->getSourceUrl(), $path); + $perforce->writeP4ClientSpec(); + $perforce->syncCodeBase(); } /** @@ -47,26 +40,6 @@ class PerforceDownloader extends VcsDownloader public function doUpdate(PackageInterface $initial, PackageInterface $target, $path) { print("PerforceDownloader:doUpdate\n"); - -// $this->cleanEnv(); -// $path = $this->normalizePath($path); -// -// $ref = $target->getSourceReference(); -// $this->io->write(" Checking out ".$ref); -// $command = 'git remote set-url composer %s && git fetch composer && git fetch --tags composer'; -// -// // capture username/password from URL if there is one -// $this->process->execute('git remote -v', $output, $path); -// if (preg_match('{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im', $output, $match)) { -// $this->io->setAuthentication($match[3], urldecode($match[1]), urldecode($match[2])); -// } -// -// $commandCallable = function($url) use ($command) { -// return sprintf($command, escapeshellarg($url)); -// }; -// -// $this->runCommand($commandCallable, $target->getSourceUrl(), $path); -// $this->updateToCommit($path, $ref, $target->getPrettyVersion(), $target->getReleaseDate()); } /** @@ -75,18 +48,6 @@ class PerforceDownloader extends VcsDownloader public function getLocalChanges($path) { print("PerforceDownloader:getLocalChanges\n"); -// $this->cleanEnv(); -// $path = $this->normalizePath($path); -// if (!is_dir($path.'/.git')) { -// return; -// } -// -// $command = 'git status --porcelain --untracked-files=no'; -// if (0 !== $this->process->execute($command, $output, $path)) { -// throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()); -// } -// -// return trim($output) ?: null; } @@ -96,14 +57,6 @@ class PerforceDownloader extends VcsDownloader protected function getCommitLogs($fromReference, $toReference, $path) { print("PerforceDownloader:getCommitLogs\n"); -// $path = $this->normalizePath($path); -// $command = sprintf('git log %s..%s --pretty=format:"%%h - %%an: %%s"', $fromReference, $toReference); -// -// if (0 !== $this->process->execute($command, $output, $path)) { -// throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()); -// } -// -// return $output; } } diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 6ecb47050..7d110c888 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -15,62 +15,39 @@ namespace Composer\Repository\Vcs; -#use Composer\Downloader\TransportException; -#use Composer\Json\JsonFile; -#use Composer\Cache; use Composer\IO\IOInterface; use Composer\Util\Filesystem; use Composer\Util\Perforce; -#use Composer\Util\RemoteFilesystem; -#use Composer\Util\GitHub; /** * @author matt-whittom <> */ class PerforceDriver extends VcsDriver { -// protected $cache; -// protected $owner; -// protected $repository; -// protected $tags; -// protected $branches; - protected $rootIdentifier = 'mainline'; - protected $repoDir; -// protected $hasIssues; -// protected $infoCache = array(); -// protected $isPrivate = false; + protected $rootIdentifier; protected $depot; - protected $p4client; + protected $perforce; /** * {@inheritDoc} */ public function initialize() { - print ("PerforceDriver:initialize\n"); + print ("\nPerforceDriver:initialize\n"); + $this->rootIdentifier = "mainline"; $this->depot = $this->repoConfig['depot']; - $this->p4client = "composer_perforce_$this->depot"; - $this->repoDir = $this->config->get('cache-vcs-dir') . "/$this->depot"; - $clientSpec = $this->config->get('cache-dir') . "/perforce/$this->p4client.p4.spec"; - - $this->p4Login(); - - $fs = new Filesystem(); - $fs->ensureDirectoryExists($this->repoDir); $stream = "//$this->depot/$this->rootIdentifier"; - $perforce = new Perforce(); - $perforce->writeP4ClientSpec($clientSpec, $this->repoDir, $this->p4client, $stream); - $perforce->syncCodeBase($clientSpec, $this->repoDir, $this->p4client); + $repoDir = $this->config->get('cache-vcs-dir') . "/$this->depot"; + $this->perforce = new Perforce($stream, $this->getUrl(), $repoDir); + + $this->perforce->p4Login($this->io); + $this->perforce->writeP4ClientSpec(); + $this->perforce->syncCodeBase(); return true; } - protected function p4Login(){ - $password = trim(shell_exec('echo $P4PASSWD')); - $command = "echo $password | p4 login -a "; - shell_exec($command); - } @@ -79,31 +56,9 @@ class PerforceDriver extends VcsDriver */ public function getComposerInformation($identifier) { - print ("PerforceDriver:getComposerInformation: $identifier\n"); - $command = "p4 print $identifier/composer.json"; - $result = shell_exec($command); - $index = strpos($result, "{"); - if ($index === false){ - return; - } - if ($index >=0){ - $rawData = substr($result, $index); - $composer_info = json_decode($rawData, true); - print ("ComposerInfo is:".var_export($composer_info, true) . "\n"); - return $composer_info; - } - - -// Basically, read the composer.json file from the project. -// -// Git stuff: -// ..getComposerInfo is: array ( -// 'support' => -// array ( -// 'source' => 'http://github.com/composer/packagist', -// ), -// 'time' => '2012-09-10', -// ) + print ("PerforceDriver:getComposerInformation - identifier: $identifier\n"); + $composer_info =$this->perforce->getComposerInformation($identifier); + return $composer_info; } /** @@ -120,9 +75,6 @@ class PerforceDriver extends VcsDriver */ public function getBranches() { - //return $branch->$identifier - //getComposer($identifier) - //validate($branch) print ("PerforceDriver:getBranches\n"); $command = "p4 streams //$this->depot/..."; $result = shell_exec($command); @@ -137,7 +89,6 @@ class PerforceDriver extends VcsDriver } } $branches['master'] = $branches['mainline']; - print ("PerforceDriver:getBranches - returning branches:".var_export($branches, true)."\n"); return $branches; } @@ -155,7 +106,7 @@ class PerforceDriver extends VcsDriver */ public function getDist($identifier) { - print ("PerforceDriver:getDist: $identifier\n"); + print("\nPerforceDriver:getDist: identifier: $identifier\n"); return null; } @@ -164,7 +115,7 @@ class PerforceDriver extends VcsDriver */ public function getSource($identifier) { - print ("PerforceDriver:getSource: $identifier\n"); + print ("\nPerforceDriver:getSource - identifier: $identifier\n"); $source = array ( 'type' => 'perforce', @@ -180,7 +131,7 @@ class PerforceDriver extends VcsDriver public function getUrl() { print ("PerforceDriver:getUrl\n"); - + return $this->url; } /** @@ -188,10 +139,10 @@ class PerforceDriver extends VcsDriver */ public function hasComposerFile($identifier) { - print ("PerforceDriver:hasComposerFile: $identifier\n"); - - //Does the project have a composer file? - return true; + print ("\nPerforceDriver:hasComposerFile - identifier: $identifier\n"); + $composerFile = $this->perforce->getComposerFilePath($identifier); + print ("returning: " . var_export(file_exists($composerFile),true) . "\n"); + return file_exists($composerFile); } /** @@ -199,7 +150,8 @@ class PerforceDriver extends VcsDriver */ public function getContents($url) { - print("PerforceDriver:getContents - url: $url"); + print ("\nPerforceDriver:getContents - url: $url\n"); + return false; } /** @@ -207,12 +159,7 @@ class PerforceDriver extends VcsDriver */ public static function supports(IOInterface $io, $url, $deep = false) { - print ("PerforceDriver:supports\n"); - - print ("\nChecking url for support: $url\n\n"); - if (preg_match('#(^perforce)#', $url)) { - return true; - } - return false; + print ("PerforceDriver:supports - url: $url\n"); + return Perforce::checkServerExists($url); } } diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 15f4b6ac5..dfd87b724 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -9,56 +9,93 @@ namespace Composer\Util; +use Composer\IO\IOInterface; + class Perforce { - public function syncCodeBase($clientSpec, $targetDir, $p4client){ - $p4CreateClientCommand = "p4 client -i < $clientSpec"; - print ("\nPerforceDriver create client: $p4CreateClientCommand\n"); + + protected $path; + protected $p4client; + protected $p4user; + protected $p4port; + protected $p4stream; + protected $p4clientSpec; + + final public function __construct($stream, $port, $path){ + $this->p4stream = $stream; + $this->p4port = $port; + $this->path = $path; + $fs = new Filesystem(); + $fs->ensureDirectoryExists($path); + } + + protected function getClient() + { + if (!isset($this->p4client)){ + $random_value = mt_rand(1000,9999); + $this->p4client = "composer_perforce_" . $random_value . "_".str_replace("/", "_", str_replace("//", "", $this->p4stream)); + } + return $this->p4client; + } + + protected function getUser() + { + if (!isset($this->p4user)){ + $this->p4user = trim(shell_exec('echo $P4USER')); + } + return $this->p4user; + } + + protected function getPath() + { + return $this->path; + } + protected function getPort() + { + return $this->p4port; + } + + protected function getStream() + { + return $this->p4stream; + } + protected function getP4ClientSpec() + { + $p4clientSpec = $this->path . "/" . $this->getClient() . ".p4.spec"; + return $p4clientSpec; + } + + public function syncCodeBase(){ + $p4CreateClientCommand = $this->generateP4Command( "client -i < " . $this->getP4ClientSpec()); $result = shell_exec($p4CreateClientCommand); - print ("result: $result\n\n"); $prevDir = getcwd(); - chdir($targetDir); + chdir($this->path); - //write p4 config file - $p4ConfigFileSpec = "$targetDir/p4config.config"; - $p4ConfigFile = fopen($p4ConfigFileSpec, 'w'); - fwrite($p4ConfigFile, "P4CLIENT=$p4client"); - fclose($p4ConfigFile); + $result = shell_exec("pwd"); - $testCommand = "pwd"; - print ("PerforceDriver test dir command: $testCommand\n"); - $result = shell_exec($testCommand); - print ("result: $result\n\n"); - - $p4SyncCommand = "p4 sync -f //$p4client/..."; - print ("PerforceDriver sync client: $p4SyncCommand\n"); + $p4SyncCommand = $this->generateP4Command( "sync -f //".$this->getClient()."/..."); $result = shell_exec($p4SyncCommand); - print ("result: $result\n\n"); chdir($prevDir); } - public function writeP4ClientSpec($clientSpec, $targetDir, $p4client, $stream){ - $fs = new Filesystem(); - $fs->ensureDirectoryExists(dirname($clientSpec)); + public function writeP4ClientSpec(){ - $p4user = trim(shell_exec('echo $P4USER')); - print ("PerforceDriver: writing to client spec: $clientSpec\n\n"); - $spec = fopen($clientSpec, 'w'); + $spec = fopen($this->getP4ClientSpec(), 'w'); try { - fwrite($spec, "Client: $p4client\n\n"); + fwrite($spec, "Client: " . $this->getClient() . "\n\n"); fwrite($spec, "Update: " . date("Y/m/d H:i:s") . "\n\n"); fwrite($spec, "Access: " . date("Y/m/d H:i:s") . "\n" ); - fwrite($spec, "Owner: $p4user\n\n" ); + fwrite($spec, "Owner: " . $this->getUser() . "\n\n" ); fwrite($spec, "Description:\n" ); - fwrite($spec, " Created by $p4user from composer.\n\n" ); - fwrite($spec, "Root: $targetDir\n\n" ); + fwrite($spec, " Created by " . $this->getUser() . " from composer.\n\n" ); + fwrite($spec, "Root: " .$this->getPath(). "\n\n" ); fwrite($spec, "Options: noallwrite noclobber nocompress unlocked modtime rmdir\n\n" ); fwrite($spec, "SubmitOptions: revertunchanged\n\n" ); fwrite($spec, "LineEnd: local\n\n" ); fwrite($spec, "Stream:\n" ); - fwrite($spec, " $stream\n" ); + fwrite($spec, " " . $this->getStream()."\n" ); } catch(Exception $e){ fclose($spec); throw $e; @@ -66,5 +103,50 @@ class Perforce { fclose($spec); } + public function getComposerFilePath($identifier) + { + $composerFilePath = $this->path . "/composer.json" ; + print ("\nPerforceUtility - getComposerPath: $composerFilePath\n\n"); + return $composerFilePath; + } + protected function generateP4Command($command) { + $p4Command = "p4 "; + $p4Command = $p4Command . "-u " . $this->getUser() . " "; + $p4Command = $p4Command . "-c " . $this->getClient() . " "; + $p4Command = $p4Command . "-p " . $this->getPort() . " "; + $p4Command = $p4Command . $command; + return $p4Command; + } + public function p4Login(IOInterface $io){ + $user = $this->getUser(); + $result = trim(shell_exec("p4 login -s")); + $index = strpos($result, $user); + if ($index === false){ + $password = trim(shell_exec('echo $P4PASSWD')); + if (strlen($password) <= 0){ + $password = $io->ask("Enter password for Perforce user " . $this->getUser() . ": " ); + } + $command = "echo $password | p4 login -a "; + shell_exec($command); + } + } + + public static function checkServerExists($url) + { + $result = shell_exec("p4 -p $url info -s"); + $index = strpos($result, "error"); + if ($index === false){ + return true; + } + return false; + } + + public function getComposerInformation($identifier) + { + $composerFilePath =$this->getComposerFilePath($identifier); + $contents = file_get_contents($composerFilePath); + $composer_info = json_decode($contents, true); + return $composer_info; + } } \ No newline at end of file From 64bda65e116d19cd97e8ddf2449d14b01ed727b8 Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Wed, 31 Jul 2013 11:01:18 -0500 Subject: [PATCH 041/238] Updated Perforce driver to use labels dev checkin, lots of cleanup to do --- .../Downloader/PerforceDownloader.php | 9 +- .../Repository/Vcs/PerforceDriver.php | 40 +-- src/Composer/Util/Perforce.php | 264 ++++++++++++++++-- 3 files changed, 254 insertions(+), 59 deletions(-) diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index c8fcf442f..ccc53b9ef 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -20,18 +20,19 @@ use Composer\Util\Perforce; */ class PerforceDownloader extends VcsDownloader { - private $hasStashedChanges = false; - /** * {@inheritDoc} */ public function doDownload(PackageInterface $package, $path) { $ref = $package->getSourceReference(); + $label = $package->getPrettyVersion(); + print ("PerforceDownloader: doDownload: ref:$ref, label:$label\n"); - $perforce = new Perforce($ref, $package->getSourceUrl(), $path); + $perforce = new Perforce("", "", $package->getSourceUrl(), $path); + $perforce->setStream($ref); $perforce->writeP4ClientSpec(); - $perforce->syncCodeBase(); + $perforce->syncCodeBase($label); } /** diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 7d110c888..3710c55ff 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -24,8 +24,8 @@ use Composer\Util\Perforce; */ class PerforceDriver extends VcsDriver { - protected $rootIdentifier; protected $depot; + protected $branch; protected $perforce; /** @@ -34,16 +34,20 @@ class PerforceDriver extends VcsDriver public function initialize() { print ("\nPerforceDriver:initialize\n"); - $this->rootIdentifier = "mainline"; $this->depot = $this->repoConfig['depot']; + $this->branch = ""; + if (isset($this->repoConfig['branch'])){ + $this->branch = $this->repoConfig['branch']; + } - $stream = "//$this->depot/$this->rootIdentifier"; $repoDir = $this->config->get('cache-vcs-dir') . "/$this->depot"; - $this->perforce = new Perforce($stream, $this->getUrl(), $repoDir); + $this->perforce = new Perforce($this->depot, $this->branch, $this->getUrl(), $repoDir); $this->perforce->p4Login($this->io); - $this->perforce->writeP4ClientSpec(); - $this->perforce->syncCodeBase(); + $this->perforce->checkStream($this->depot); + +// $this->perforce->writeP4ClientSpec(); +// $this->perforce->syncCodeBase(); return true; } @@ -56,7 +60,7 @@ class PerforceDriver extends VcsDriver */ public function getComposerInformation($identifier) { - print ("PerforceDriver:getComposerInformation - identifier: $identifier\n"); + print("PerforceDriver:getComposerInformation - identifier: $identifier\n"); $composer_info =$this->perforce->getComposerInformation($identifier); return $composer_info; } @@ -67,7 +71,7 @@ class PerforceDriver extends VcsDriver public function getRootIdentifier() { print ("PerforceDriver:getRootIdentifier\n"); - return $this->rootIdentifier; + return $this->branch; } /** @@ -76,19 +80,7 @@ class PerforceDriver extends VcsDriver public function getBranches() { print ("PerforceDriver:getBranches\n"); - $command = "p4 streams //$this->depot/..."; - $result = shell_exec($command); - - $resArray = explode("\n", $result); - $branches = array(); - foreach ($resArray as $line){ - $resBits = explode(" ", $line); - if (count($resBits) > 4){ - $branch = substr($resBits[4], 1, strlen($resBits[4])-2); - $branches[$branch] = $resBits[1]; - } - } - $branches['master'] = $branches['mainline']; + $branches = $this->perforce->getBranches(); return $branches; } @@ -98,7 +90,8 @@ class PerforceDriver extends VcsDriver public function getTags() { print ("PerforceDriver:getTags\n"); - return array(); + $tags = $this->perforce->getTags(); + return $tags; } /** @@ -106,7 +99,6 @@ class PerforceDriver extends VcsDriver */ public function getDist($identifier) { - print("\nPerforceDriver:getDist: identifier: $identifier\n"); return null; } @@ -115,8 +107,6 @@ class PerforceDriver extends VcsDriver */ public function getSource($identifier) { - print ("\nPerforceDriver:getSource - identifier: $identifier\n"); - $source = array ( 'type' => 'perforce', 'url' => $this->repoConfig['url'], diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index dfd87b724..7b55cf0d5 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -20,9 +20,12 @@ class Perforce { protected $p4port; protected $p4stream; protected $p4clientSpec; + protected $p4depotType; + protected $p4branch; - final public function __construct($stream, $port, $path){ - $this->p4stream = $stream; + final public function __construct($depot, $branch, $port, $path){ + $this->p4depot = $depot; + $this->p4branch = $branch; $this->p4port = $port; $this->path = $path; $fs = new Filesystem(); @@ -33,7 +36,8 @@ class Perforce { { if (!isset($this->p4client)){ $random_value = mt_rand(1000,9999); - $this->p4client = "composer_perforce_" . $random_value . "_".str_replace("/", "_", str_replace("//", "", $this->p4stream)); + $clean_stream_name = str_replace("@", "", str_replace("/", "_", str_replace("//", "", $this->p4stream))); + $this->p4client = "composer_perforce_" . $random_value . "_".$clean_stream_name; } return $this->p4client; } @@ -50,6 +54,7 @@ class Perforce { { return $this->path; } + protected function getPort() { return $this->p4port; @@ -57,16 +62,80 @@ class Perforce { protected function getStream() { + if (!isset($this->p4stream)){ + if ($this->isStream()){ + $this->p4stream = "//$this->p4depot/$this->p4branch"; + } else { + $this->p4stream = "//$this->p4depot"; + } + } return $this->p4stream; } + + protected function getStreamWithoutLabel() + { + $stream = $this->getStream(); + $index = strpos($stream, "@"); + if ($index === false){ + return $stream; + } + return substr($stream, 0, $index); + } + protected function getP4ClientSpec() { $p4clientSpec = $this->path . "/" . $this->getClient() . ".p4.spec"; return $p4clientSpec; } - public function syncCodeBase(){ + protected function queryP4User(IOInterface $io){ + $this->getUser(); + if (strlen($this->p4user) <= 0){ + $this->p4user = $io->ask("Enter P4 User:"); + } + } + + protected function queryP4Password(IOInterface $io){ + $password = trim(shell_exec('echo $P4PASSWD')); + if (strlen($password) <= 0){ + $password = $io->ask("Enter password for Perforce user " . $this->getUser() . ": " ); + } + return $password; + } + + protected function isStream(){ + return (strcmp($this->p4depotType, "stream") === 0); + } + + protected function generateP4Command($command, $useClient = true) { + $p4Command = "p4 "; + $p4Command = $p4Command . "-u " . $this->getUser() . " "; + if ($useClient){ + $p4Command = $p4Command . "-c " . $this->getClient() . " "; + } + $p4Command = $p4Command . "-p " . $this->getPort() . " "; + $p4Command = $p4Command . $command; + return $p4Command; + } + + protected function isLoggedIn(){ + $command = $this->generateP4Command("login -s "); + $result = trim(shell_exec($command)); + $index = strpos($result, $this->getUser()); + if ($index === false){ + return false; + } + return true; + } + + public function setStream($stream){ + $this->p4stream = $stream; + $this->p4depotType = "stream"; + } + + public function syncCodeBase($label){ $p4CreateClientCommand = $this->generateP4Command( "client -i < " . $this->getP4ClientSpec()); + print ("Perforce: syncCodeBase - client command:$p4CreateClientCommand \n"); $result = shell_exec($p4CreateClientCommand); $prevDir = getcwd(); @@ -75,13 +144,19 @@ class Perforce { $result = shell_exec("pwd"); $p4SyncCommand = $this->generateP4Command( "sync -f //".$this->getClient()."/..."); + if (isset($label)){ + if (strcmp($label, "dev-master") != 0){ + $p4SyncCommand = $p4SyncCommand . "@" . $label; + } + } + print ("Perforce: syncCodeBase - sync command:$p4SyncCommand \n"); $result = shell_exec($p4SyncCommand); chdir($prevDir); } public function writeP4ClientSpec(){ - + print ("Perforce: writeP4ClientSpec\n"); $spec = fopen($this->getP4ClientSpec(), 'w'); try { fwrite($spec, "Client: " . $this->getClient() . "\n\n"); @@ -94,8 +169,12 @@ class Perforce { fwrite($spec, "Options: noallwrite noclobber nocompress unlocked modtime rmdir\n\n" ); fwrite($spec, "SubmitOptions: revertunchanged\n\n" ); fwrite($spec, "LineEnd: local\n\n" ); - fwrite($spec, "Stream:\n" ); - fwrite($spec, " " . $this->getStream()."\n" ); + if ($this->isStream()){ + fwrite($spec, "Stream:\n" ); + fwrite($spec, " " . $this->getStreamWithoutLabel()."\n" ); + } else { + fwrite($spec, "View: " . $this->getStream() . "/... //" . $this->getClient() . "/" . str_replace("//", "", $this->getStream()) . "/... \n"); + } } catch(Exception $e){ fclose($spec); throw $e; @@ -105,35 +184,27 @@ class Perforce { public function getComposerFilePath($identifier) { - $composerFilePath = $this->path . "/composer.json" ; - print ("\nPerforceUtility - getComposerPath: $composerFilePath\n\n"); + if ($this->isStream()){ + $composerFilePath = $this->path . "/composer.json" ; + } else { + $composerFilePath = $this->path . "/" . $this->p4depot . "/composer.json" ; + } return $composerFilePath; } - protected function generateP4Command($command) { - $p4Command = "p4 "; - $p4Command = $p4Command . "-u " . $this->getUser() . " "; - $p4Command = $p4Command . "-c " . $this->getClient() . " "; - $p4Command = $p4Command . "-p " . $this->getPort() . " "; - $p4Command = $p4Command . $command; - return $p4Command; - } public function p4Login(IOInterface $io){ - $user = $this->getUser(); - $result = trim(shell_exec("p4 login -s")); - $index = strpos($result, $user); - if ($index === false){ - $password = trim(shell_exec('echo $P4PASSWD')); - if (strlen($password) <= 0){ - $password = $io->ask("Enter password for Perforce user " . $this->getUser() . ": " ); - } - $command = "echo $password | p4 login -a "; + print ("Perforce: P4Login\n"); + $this->queryP4User($io); + if (!$this->isLoggedIn()){ + $password = $this->queryP4Password($io); + $command = "echo $password | " . $this->generateP4Command("login -a "); shell_exec($command); } } public static function checkServerExists($url) { + print ("Perforce: checkServerExists\n"); $result = shell_exec("p4 -p $url info -s"); $index = strpos($result, "error"); if ($index === false){ @@ -144,9 +215,142 @@ class Perforce { public function getComposerInformation($identifier) { - $composerFilePath =$this->getComposerFilePath($identifier); - $contents = file_get_contents($composerFilePath); - $composer_info = json_decode($contents, true); - return $composer_info; + $index = strpos($identifier, "@"); + if ($index === false){ + return $this->getComposerInformationFromId($identifier); + } else { + return $this->getComposerInformationFromTag($identifier, $index); + } + } + public function getComposerInformationFromId($identifier) + { + $composer_json = "$identifier/composer.json"; + $command = $this->generateP4Command(" print $composer_json", false); + print ("Perforce: getComposerInformation: command: $command\n\n"); + $result = shell_exec($command); + $index = strpos($result, "{"); + if ($index === false){ + return ""; + } + if ($index >=0){ + $rawData = substr($result, $index); + $composer_info = json_decode($rawData, true); + print ("ComposerInfo is:".var_export($composer_info, true) . "\n"); + return $composer_info; + } + return ""; + } + + public function getComposerInformationFromTag($identifier, $index) + { + $composer_json = substr($identifier, 0, $index) . "/composer.json" . substr($identifier, $index); + $command = $this->generateP4Command(" files $composer_json", false); + print("\n\nPerforce: getComposerInformationFromTag: $identifier, command:\n $command\n\n"); + $result = shell_exec($command); + print("\n\nPerforce: getComposerInformationFromTag: result: \n $result\n\n"); + $index2 = strpos($result, "no such file(s)."); + if ($index2 === false){ + $index3 = strpos($result, "change"); + if (!($index3 ===false )){ + $phrase = trim(substr($result, $index3)); + $fields = explode(" ", $phrase); + $id = $fields[1]; + $composer_json = substr($identifier, 0, $index) . "/composer.json@" . $id; + $command = $this->generateP4Command(" print $composer_json", false); + $result = shell_exec($command); + $index = strpos($result, "{"); + if ($index === false){ + return ""; + } + if ($index >=0){ + $rawData = substr($result, $index); + $composer_info = json_decode($rawData, true); + print ("ComposerInfo is:".var_export($composer_info, true) . "\n"); + return $composer_info; + } + } + } + + return ""; + } + +// public function getComposerInformation($identifier) +// { +// $composerFilePath =$this->getComposerFilePath($identifier); +// $contents = file_get_contents($composerFilePath); +// $composer_info = json_decode($contents, true); +// return $composer_info; +// } + + public function getBranches() + { + $branches = array(); + if (!$this->isStream()){ + $branches[$this->p4branch] = $this->p4stream; + } else { + $command = $this->generateP4Command("streams //$this->p4depot/..."); + $result = shell_exec($command); + print ("Perforce: getBranches: result: $result\n"); + $resArray = explode("\n", $result); + foreach ($resArray as $line){ + $resBits = explode(" ", $line); + if (count($resBits) > 4){ + $branch = substr($resBits[4], 1, strlen($resBits[4])-2); + $branches[$branch] = $resBits[1]; + } + } + } + $branches['master'] = $branches[$this->p4branch]; + return $branches; + } + + public function getTags() + { + + $command = $this->generateP4Command("changes " . $this->getStream() . "/..."); + print("\nPerforce:getTags - command:($command)\n"); + $result = shell_exec($command); + $resArray = explode("\n", $result); + $tags = array(); + foreach ($resArray as $line){ + $index = strpos($line, "Change"); + if (!($index===false)){ +// $fields = explode(" ", $line); +// $tags["0.0.".$fields[1]] = $this->getStream() . "@" . $fields[1]; + } + } + + $command = $this->generateP4Command("labels"); + print("\nPerforce:getTags - command:($command)\n"); + $result = shell_exec($command); + $resArray = explode("\n", $result); + print("\nPerforce:getTags - result:$result\n"); + foreach ($resArray as $line){ + $index = strpos($line, "Label"); + if (!($index===false)){ + $fields = explode(" ", $line); + $tags[$fields[1]] = $this->getStream()."@" . $fields[1]; + } + } + print ("Perforce:getTags - tags:" . var_export($tags, true)."\n"); + return $tags; + } + + public function checkStream () + { + $command = $this->generateP4Command("depots"); + $result = shell_exec($command); + $resArray = explode("\n", $result); + foreach ($resArray as $line){ + $index = strpos($line, "Depot"); + if (!($index===false)){ + $fields = explode(" ", $line); + if (strcmp($this->p4depot, $fields[1]) === 0){ + $this->p4depotType = $fields[3]; + return $this->isStream(); + } + } + } + return false; } } \ No newline at end of file From 43108b4692c7eb1e4e6892fce0ea8ccca6d30977 Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Wed, 31 Jul 2013 13:26:44 -0500 Subject: [PATCH 042/238] Cleanup phase 1 Removed branches - only returning the "master" --- .../Repository/Vcs/PerforceDriver.php | 17 +++-- src/Composer/Util/Perforce.php | 71 +++++-------------- 2 files changed, 29 insertions(+), 59 deletions(-) diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 3710c55ff..4fdaa38f2 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -33,7 +33,7 @@ class PerforceDriver extends VcsDriver */ public function initialize() { - print ("\nPerforceDriver:initialize\n"); + print ("PerforceDriver:initialize\n"); $this->depot = $this->repoConfig['depot']; $this->branch = ""; if (isset($this->repoConfig['branch'])){ @@ -46,7 +46,7 @@ class PerforceDriver extends VcsDriver $this->perforce->p4Login($this->io); $this->perforce->checkStream($this->depot); -// $this->perforce->writeP4ClientSpec(); + $this->perforce->writeP4ClientSpec(); // $this->perforce->syncCodeBase(); return true; @@ -60,7 +60,7 @@ class PerforceDriver extends VcsDriver */ public function getComposerInformation($identifier) { - print("PerforceDriver:getComposerInformation - identifier: $identifier\n"); + print("\nPerforceDriver:getComposerInformation - identifier: $identifier\n"); $composer_info =$this->perforce->getComposerInformation($identifier); return $composer_info; } @@ -129,10 +129,15 @@ class PerforceDriver extends VcsDriver */ public function hasComposerFile($identifier) { - print ("\nPerforceDriver:hasComposerFile - identifier: $identifier\n"); + print ("PerforceDriver:hasComposerFile - identifier: $identifier\n"); $composerFile = $this->perforce->getComposerFilePath($identifier); - print ("returning: " . var_export(file_exists($composerFile),true) . "\n"); - return file_exists($composerFile); + print ("composerFile: $composerFile\n"); + if (!file_exists(filename)){ + $composer_info = $this->perforce->getComposerInformation(); + $result = strlen(trim($composer_info))>0; + return $result; + } + return true; } /** diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 7b55cf0d5..f80a4bb72 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -217,16 +217,16 @@ class Perforce { { $index = strpos($identifier, "@"); if ($index === false){ - return $this->getComposerInformationFromId($identifier); + $composer_json = "$identifier/composer.json"; + return $this->getComposerInformationFromPath($composer_json); } else { - return $this->getComposerInformationFromTag($identifier, $index); + return $this->getComposerInformationFromLabel($identifier, $index); } } - public function getComposerInformationFromId($identifier) + public function getComposerInformationFromPath($composer_json) { - $composer_json = "$identifier/composer.json"; $command = $this->generateP4Command(" print $composer_json", false); - print ("Perforce: getComposerInformation: command: $command\n\n"); + print ("Perforce: getComposerInformation: command: $command\n"); $result = shell_exec($command); $index = strpos($result, "{"); if ($index === false){ @@ -235,19 +235,18 @@ class Perforce { if ($index >=0){ $rawData = substr($result, $index); $composer_info = json_decode($rawData, true); - print ("ComposerInfo is:".var_export($composer_info, true) . "\n"); return $composer_info; } return ""; } - public function getComposerInformationFromTag($identifier, $index) + public function getComposerInformationFromLabel($identifier, $index) { - $composer_json = substr($identifier, 0, $index) . "/composer.json" . substr($identifier, $index); - $command = $this->generateP4Command(" files $composer_json", false); - print("\n\nPerforce: getComposerInformationFromTag: $identifier, command:\n $command\n\n"); + $composer_json_path = substr($identifier, 0, $index) . "/composer.json" . substr($identifier, $index); + $command = $this->generateP4Command(" files $composer_json_path", false); + print("Perforce: getComposerInformationFromTag: $identifier, command:\n $command\n"); $result = shell_exec($command); - print("\n\nPerforce: getComposerInformationFromTag: result: \n $result\n\n"); + print("Perforce: getComposerInformationFromTag: result: \n $result\n"); $index2 = strpos($result, "no such file(s)."); if ($index2 === false){ $index3 = strpos($result, "change"); @@ -256,75 +255,42 @@ class Perforce { $fields = explode(" ", $phrase); $id = $fields[1]; $composer_json = substr($identifier, 0, $index) . "/composer.json@" . $id; - $command = $this->generateP4Command(" print $composer_json", false); - $result = shell_exec($command); - $index = strpos($result, "{"); - if ($index === false){ - return ""; - } - if ($index >=0){ - $rawData = substr($result, $index); - $composer_info = json_decode($rawData, true); - print ("ComposerInfo is:".var_export($composer_info, true) . "\n"); - return $composer_info; - } + return $this->getComposerInformationFromPath($composer_json); } } - return ""; } -// public function getComposerInformation($identifier) -// { -// $composerFilePath =$this->getComposerFilePath($identifier); -// $contents = file_get_contents($composerFilePath); -// $composer_info = json_decode($contents, true); -// return $composer_info; -// } - public function getBranches() { - $branches = array(); + $possible_branches = array(); if (!$this->isStream()){ $branches[$this->p4branch] = $this->p4stream; } else { $command = $this->generateP4Command("streams //$this->p4depot/..."); $result = shell_exec($command); - print ("Perforce: getBranches: result: $result\n"); $resArray = explode("\n", $result); foreach ($resArray as $line){ $resBits = explode(" ", $line); if (count($resBits) > 4){ $branch = substr($resBits[4], 1, strlen($resBits[4])-2); - $branches[$branch] = $resBits[1]; + $possible_branches[$branch] = $resBits[1]; } } } - $branches['master'] = $branches[$this->p4branch]; + $branches = array(); + $branches['master'] = $possible_branches[$this->p4branch]; + print ("Perforce: getBranches: returning: \n" . var_export($branches, true) . "\n"); return $branches; } public function getTags() { - - $command = $this->generateP4Command("changes " . $this->getStream() . "/..."); - print("\nPerforce:getTags - command:($command)\n"); - $result = shell_exec($command); - $resArray = explode("\n", $result); - $tags = array(); - foreach ($resArray as $line){ - $index = strpos($line, "Change"); - if (!($index===false)){ -// $fields = explode(" ", $line); -// $tags["0.0.".$fields[1]] = $this->getStream() . "@" . $fields[1]; - } - } - $command = $this->generateP4Command("labels"); - print("\nPerforce:getTags - command:($command)\n"); $result = shell_exec($command); $resArray = explode("\n", $result); - print("\nPerforce:getTags - result:$result\n"); + print("Perforce:getTags - result:\n$result\n"); + $tags = array(); foreach ($resArray as $line){ $index = strpos($line, "Label"); if (!($index===false)){ @@ -332,7 +298,6 @@ class Perforce { $tags[$fields[1]] = $this->getStream()."@" . $fields[1]; } } - print ("Perforce:getTags - tags:" . var_export($tags, true)."\n"); return $tags; } From a5df2851efac41cdb8e6776a2201b0d2114e7c32 Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Wed, 31 Jul 2013 13:30:55 -0500 Subject: [PATCH 043/238] Finished cleanup of debug messages. --- src/Composer/Downloader/PerforceDownloader.php | 1 - src/Composer/Repository/Vcs/PerforceDriver.php | 9 --------- src/Composer/Util/Perforce.php | 10 ---------- 3 files changed, 20 deletions(-) diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index ccc53b9ef..59adadfaf 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -27,7 +27,6 @@ class PerforceDownloader extends VcsDownloader { $ref = $package->getSourceReference(); $label = $package->getPrettyVersion(); - print ("PerforceDownloader: doDownload: ref:$ref, label:$label\n"); $perforce = new Perforce("", "", $package->getSourceUrl(), $path); $perforce->setStream($ref); diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 4fdaa38f2..e75e5d181 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -33,7 +33,6 @@ class PerforceDriver extends VcsDriver */ public function initialize() { - print ("PerforceDriver:initialize\n"); $this->depot = $this->repoConfig['depot']; $this->branch = ""; if (isset($this->repoConfig['branch'])){ @@ -60,7 +59,6 @@ class PerforceDriver extends VcsDriver */ public function getComposerInformation($identifier) { - print("\nPerforceDriver:getComposerInformation - identifier: $identifier\n"); $composer_info =$this->perforce->getComposerInformation($identifier); return $composer_info; } @@ -70,7 +68,6 @@ class PerforceDriver extends VcsDriver */ public function getRootIdentifier() { - print ("PerforceDriver:getRootIdentifier\n"); return $this->branch; } @@ -79,7 +76,6 @@ class PerforceDriver extends VcsDriver */ public function getBranches() { - print ("PerforceDriver:getBranches\n"); $branches = $this->perforce->getBranches(); return $branches; } @@ -89,7 +85,6 @@ class PerforceDriver extends VcsDriver */ public function getTags() { - print ("PerforceDriver:getTags\n"); $tags = $this->perforce->getTags(); return $tags; } @@ -120,7 +115,6 @@ class PerforceDriver extends VcsDriver */ public function getUrl() { - print ("PerforceDriver:getUrl\n"); return $this->url; } @@ -129,9 +123,7 @@ class PerforceDriver extends VcsDriver */ public function hasComposerFile($identifier) { - print ("PerforceDriver:hasComposerFile - identifier: $identifier\n"); $composerFile = $this->perforce->getComposerFilePath($identifier); - print ("composerFile: $composerFile\n"); if (!file_exists(filename)){ $composer_info = $this->perforce->getComposerInformation(); $result = strlen(trim($composer_info))>0; @@ -154,7 +146,6 @@ class PerforceDriver extends VcsDriver */ public static function supports(IOInterface $io, $url, $deep = false) { - print ("PerforceDriver:supports - url: $url\n"); return Perforce::checkServerExists($url); } } diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index f80a4bb72..245dd182e 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -135,7 +135,6 @@ class Perforce { public function syncCodeBase($label){ $p4CreateClientCommand = $this->generateP4Command( "client -i < " . $this->getP4ClientSpec()); - print ("Perforce: syncCodeBase - client command:$p4CreateClientCommand \n"); $result = shell_exec($p4CreateClientCommand); $prevDir = getcwd(); @@ -149,14 +148,12 @@ class Perforce { $p4SyncCommand = $p4SyncCommand . "@" . $label; } } - print ("Perforce: syncCodeBase - sync command:$p4SyncCommand \n"); $result = shell_exec($p4SyncCommand); chdir($prevDir); } public function writeP4ClientSpec(){ - print ("Perforce: writeP4ClientSpec\n"); $spec = fopen($this->getP4ClientSpec(), 'w'); try { fwrite($spec, "Client: " . $this->getClient() . "\n\n"); @@ -193,7 +190,6 @@ class Perforce { } public function p4Login(IOInterface $io){ - print ("Perforce: P4Login\n"); $this->queryP4User($io); if (!$this->isLoggedIn()){ $password = $this->queryP4Password($io); @@ -204,7 +200,6 @@ class Perforce { public static function checkServerExists($url) { - print ("Perforce: checkServerExists\n"); $result = shell_exec("p4 -p $url info -s"); $index = strpos($result, "error"); if ($index === false){ @@ -226,7 +221,6 @@ class Perforce { public function getComposerInformationFromPath($composer_json) { $command = $this->generateP4Command(" print $composer_json", false); - print ("Perforce: getComposerInformation: command: $command\n"); $result = shell_exec($command); $index = strpos($result, "{"); if ($index === false){ @@ -244,9 +238,7 @@ class Perforce { { $composer_json_path = substr($identifier, 0, $index) . "/composer.json" . substr($identifier, $index); $command = $this->generateP4Command(" files $composer_json_path", false); - print("Perforce: getComposerInformationFromTag: $identifier, command:\n $command\n"); $result = shell_exec($command); - print("Perforce: getComposerInformationFromTag: result: \n $result\n"); $index2 = strpos($result, "no such file(s)."); if ($index2 === false){ $index3 = strpos($result, "change"); @@ -280,7 +272,6 @@ class Perforce { } $branches = array(); $branches['master'] = $possible_branches[$this->p4branch]; - print ("Perforce: getBranches: returning: \n" . var_export($branches, true) . "\n"); return $branches; } @@ -289,7 +280,6 @@ class Perforce { $command = $this->generateP4Command("labels"); $result = shell_exec($command); $resArray = explode("\n", $result); - print("Perforce:getTags - result:\n$result\n"); $tags = array(); foreach ($resArray as $line){ $index = strpos($line, "Label"); From 53d6fcd6d3e56b7c80b156667d3e4f44f1ec1303 Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Tue, 13 Aug 2013 10:50:47 -0500 Subject: [PATCH 044/238] using theirs --- .../Downloader/PerforceDownloader.php | 5 + .../Repository/Vcs/PerforceDriver.php | 82 ++--- src/Composer/Util/Perforce.php | 345 +++++++++++------- .../Repository/Vcs/PerforceDriverTest.php | 41 --- .../Test/Util/RemoteFilesystemTest.php | 15 +- 5 files changed, 267 insertions(+), 221 deletions(-) diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index 59adadfaf..8e5f3d01e 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -30,7 +30,9 @@ class PerforceDownloader extends VcsDownloader $perforce = new Perforce("", "", $package->getSourceUrl(), $path); $perforce->setStream($ref); + $perforce->queryP4User($this->io); $perforce->writeP4ClientSpec(); + $perforce->connectClient(); $perforce->syncCodeBase($label); } @@ -40,6 +42,7 @@ class PerforceDownloader extends VcsDownloader public function doUpdate(PackageInterface $initial, PackageInterface $target, $path) { print("PerforceDownloader:doUpdate\n"); + throw new Exception("Unsupported Operation: PerforceDownloader:doUpdate"); } /** @@ -48,6 +51,7 @@ class PerforceDownloader extends VcsDownloader public function getLocalChanges($path) { print("PerforceDownloader:getLocalChanges\n"); + throw new Exception("Unsupported Operation: PerforceDownloader:getLocalChanges"); } @@ -57,6 +61,7 @@ class PerforceDownloader extends VcsDownloader protected function getCommitLogs($fromReference, $toReference, $path) { print("PerforceDownloader:getCommitLogs\n"); + throw new Exception("Unsupported Operation: PerforceDownloader:getCommitLogs"); } } diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index e75e5d181..a1080e5c4 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -16,14 +16,14 @@ namespace Composer\Repository\Vcs; use Composer\IO\IOInterface; +use Composer\Util\ProcessExecutor; use Composer\Util\Filesystem; use Composer\Util\Perforce; /** * @author matt-whittom <> */ -class PerforceDriver extends VcsDriver -{ +class PerforceDriver extends VcsDriver { protected $depot; protected $branch; protected $perforce; @@ -31,60 +31,61 @@ class PerforceDriver extends VcsDriver /** * {@inheritDoc} */ - public function initialize() - { - $this->depot = $this->repoConfig['depot']; + public function initialize() { + $this->depot = $this->repoConfig['depot']; $this->branch = ""; - if (isset($this->repoConfig['branch'])){ + if (isset($this->repoConfig['branch'])) { $this->branch = $this->repoConfig['branch']; } $repoDir = $this->config->get('cache-vcs-dir') . "/$this->depot"; - $this->perforce = new Perforce($this->depot, $this->branch, $this->getUrl(), $repoDir); + if (!isset($this->perforce)) { + $this->perforce = new Perforce($this->depot, $this->branch, $this->getUrl(), $repoDir, $this->process); + } $this->perforce->p4Login($this->io); $this->perforce->checkStream($this->depot); $this->perforce->writeP4ClientSpec(); -// $this->perforce->syncCodeBase(); + $this->perforce->connectClient(); - return true; + return TRUE; } - + public function injectPerforce(Perforce $perforce) { + $this->perforce = $perforce; + } /** * {@inheritDoc} */ - public function getComposerInformation($identifier) - { - $composer_info =$this->perforce->getComposerInformation($identifier); + public function getComposerInformation($identifier) { + $composer_info = $this->perforce->getComposerInformation($identifier); + return $composer_info; } /** * {@inheritDoc} */ - public function getRootIdentifier() - { + public function getRootIdentifier() { return $this->branch; } /** * {@inheritDoc} */ - public function getBranches() - { + public function getBranches() { $branches = $this->perforce->getBranches(); + return $branches; } /** * {@inheritDoc} */ - public function getTags() - { + public function getTags() { $tags = $this->perforce->getTags(); return $tags; } @@ -92,60 +93,51 @@ class PerforceDriver extends VcsDriver /** * {@inheritDoc} */ - public function getDist($identifier) - { - return null; + public function getDist($identifier) { + return NULL; } /** * {@inheritDoc} */ - public function getSource($identifier) - { - $source = array ( - 'type' => 'perforce', - 'url' => $this->repoConfig['url'], + public function getSource($identifier) { + $source = array( + 'type' => 'perforce', + 'url' => $this->repoConfig['url'], 'reference' => $identifier ); + return $source; } /** * {@inheritDoc} */ - public function getUrl() - { + public function getUrl() { return $this->url; } /** * {@inheritDoc} */ - public function hasComposerFile($identifier) - { - $composerFile = $this->perforce->getComposerFilePath($identifier); - if (!file_exists(filename)){ - $composer_info = $this->perforce->getComposerInformation(); - $result = strlen(trim($composer_info))>0; - return $result; - } - return true; + public function hasComposerFile($identifier) { + $composer_info = $this->perforce->getComposerInformation("//$this->depot/$identifier"); + $result = strlen(trim($composer_info)) > 0; + + return $result; } /** * {@inheritDoc} */ - public function getContents($url) - { - print ("\nPerforceDriver:getContents - url: $url\n"); - return false; + public function getContents($url) { + return FALSE; } /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, $deep = false) - { - return Perforce::checkServerExists($url); + public static function supports(IOInterface $io, $url, $deep = FALSE) { + return Perforce::checkServerExists($url, new ProcessExecutor); } } diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 245dd182e..6174c5c49 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -22,290 +22,385 @@ class Perforce { protected $p4clientSpec; protected $p4depotType; protected $p4branch; + protected $process; - final public function __construct($depot, $branch, $port, $path){ + public function __construct($depot, $branch, $port, $path, ProcessExecutor $process = null) { $this->p4depot = $depot; $this->p4branch = $branch; $this->p4port = $port; $this->path = $path; + $this->process = $process ? : new ProcessExecutor; $fs = new Filesystem(); $fs->ensureDirectoryExists($path); } - protected function getClient() - { - if (!isset($this->p4client)){ - $random_value = mt_rand(1000,9999); - $clean_stream_name = str_replace("@", "", str_replace("/", "_", str_replace("//", "", $this->p4stream))); - $this->p4client = "composer_perforce_" . $random_value . "_".$clean_stream_name; + protected function getRandomValue() { + return mt_rand(1000, 9999); + } + + protected function executeCommand($command) { + $result = ""; + $this->process->execute($command, $result); + + return $result; + } + + protected function getClient() { + if (!isset($this->p4client)) { + $random_value = $this->getRandomValue(); + $clean_stream_name = str_replace("@", "", str_replace("/", "_", str_replace("//", "", $this->getStream()))); + $this->p4client = "composer_perforce_" . $random_value . "_" . $clean_stream_name; } + return $this->p4client; } - protected function getUser() - { - if (!isset($this->p4user)){ - $this->p4user = trim(shell_exec('echo $P4USER')); + public function getUser() { + if (!isset($this->p4user)) { + $this->p4user = $this->getP4variable("P4USER"); } + return $this->p4user; } - protected function getPath() - { + protected function getPath() { return $this->path; } - protected function getPort() - { + protected function getPort() { return $this->p4port; } - protected function getStream() - { - if (!isset($this->p4stream)){ - if ($this->isStream()){ + protected function getStream() { + if (!isset($this->p4stream)) { + if ($this->isStream()) { $this->p4stream = "//$this->p4depot/$this->p4branch"; - } else { + } + else { $this->p4stream = "//$this->p4depot"; } } + return $this->p4stream; } - protected function getStreamWithoutLabel() - { + protected function getStreamWithoutLabel() { $stream = $this->getStream(); $index = strpos($stream, "@"); - if ($index === false){ + if ($index === FALSE) { return $stream; } + return substr($stream, 0, $index); } - protected function getP4ClientSpec() - { + protected function getP4ClientSpec() { $p4clientSpec = $this->path . "/" . $this->getClient() . ".p4.spec"; + return $p4clientSpec; } - protected function queryP4User(IOInterface $io){ + public function queryP4User(IOInterface $io) { $this->getUser(); - if (strlen($this->p4user) <= 0){ + if (strlen($this->p4user) <= 0) { $this->p4user = $io->ask("Enter P4 User:"); + if (defined('PHP_WINDOWS_VERSION_BUILD')) { + $command = "p4 set P4USER=$this->p4user"; + } else { + $command = "export P4USER=$this->p4user"; + } + $result = $this->executeCommand($command); } } - protected function queryP4Password(IOInterface $io){ - $password = trim(shell_exec('echo $P4PASSWD')); - if (strlen($password) <= 0){ - $password = $io->ask("Enter password for Perforce user " . $this->getUser() . ": " ); + protected function queryP4Password(IOInterface $io) { + $password = $this->getP4variable("P4PASSWD"); + if (strlen($password) <= 0) { + $password = $io->askAndHideAnswer("Enter password for Perforce user " . $this->getUser() . ": "); } return $password; } - protected function isStream(){ + protected function isStream() { return (strcmp($this->p4depotType, "stream") === 0); } - protected function generateP4Command($command, $useClient = true) { + protected function generateP4Command($command, $useClient = TRUE) { $p4Command = "p4 "; $p4Command = $p4Command . "-u " . $this->getUser() . " "; - if ($useClient){ - $p4Command = $p4Command . "-c " . $this->getClient() . " "; + if ($useClient) { + $p4Command = $p4Command . "-c " . $this->getClient() . " "; } $p4Command = $p4Command . "-p " . $this->getPort() . " "; $p4Command = $p4Command . $command; + return $p4Command; } - protected function isLoggedIn(){ - $command = $this->generateP4Command("login -s "); - $result = trim(shell_exec($command)); + protected function isLoggedIn() { + $command = $this->generateP4Command("login -s", FALSE); + $result = trim($this->executeCommand($command)); $index = strpos($result, $this->getUser()); - if ($index === false){ - return false; + if ($index === FALSE) { + return FALSE; } - return true; + return TRUE; } - public function setStream($stream){ + public function setStream($stream) { $this->p4stream = $stream; $this->p4depotType = "stream"; } - public function syncCodeBase($label){ - $p4CreateClientCommand = $this->generateP4Command( "client -i < " . $this->getP4ClientSpec()); - $result = shell_exec($p4CreateClientCommand); + public function connectClient() { + $p4CreateClientCommand = $this->generateP4Command("client -i < " . $this->getP4ClientSpec()); + $this->executeCommand($p4CreateClientCommand); + } + public function syncCodeBase($label) { $prevDir = getcwd(); chdir($this->path); - $result = shell_exec("pwd"); + $this->executeCommand("pwd"); - $p4SyncCommand = $this->generateP4Command( "sync -f //".$this->getClient()."/..."); - if (isset($label)){ - if (strcmp($label, "dev-master") != 0){ + $p4SyncCommand = $this->generateP4Command("sync -f "); + if (isset($label)) { + if (strcmp($label, "dev-master") != 0) { $p4SyncCommand = $p4SyncCommand . "@" . $label; } } - $result = shell_exec($p4SyncCommand); + $this->executeCommand($p4SyncCommand); chdir($prevDir); } - public function writeP4ClientSpec(){ + protected function writeClientSpecToFile($spec) { + fwrite($spec, "Client: " . $this->getClient() . "\n\n"); + fwrite($spec, "Update: " . date("Y/m/d H:i:s") . "\n\n"); + fwrite($spec, "Access: " . date("Y/m/d H:i:s") . "\n"); + fwrite($spec, "Owner: " . $this->getUser() . "\n\n"); + fwrite($spec, "Description:\n"); + fwrite($spec, " Created by " . $this->getUser() . " from composer.\n\n"); + fwrite($spec, "Root: " . $this->getPath() . "\n\n"); + fwrite($spec, "Options: noallwrite noclobber nocompress unlocked modtime rmdir\n\n"); + fwrite($spec, "SubmitOptions: revertunchanged\n\n"); + fwrite($spec, "LineEnd: local\n\n"); + if ($this->isStream()) { + fwrite($spec, "Stream:\n"); + fwrite($spec, " " . $this->getStreamWithoutLabel() . "\n"); + } + else { + fwrite( + $spec, "View: " . $this->getStream() . "/... //" . $this->getClient() . "/" . str_replace( + "//", "", $this->getStream() + ) . "/... \n" + ); + } + } + + public function writeP4ClientSpec() { $spec = fopen($this->getP4ClientSpec(), 'w'); try { - fwrite($spec, "Client: " . $this->getClient() . "\n\n"); - fwrite($spec, "Update: " . date("Y/m/d H:i:s") . "\n\n"); - fwrite($spec, "Access: " . date("Y/m/d H:i:s") . "\n" ); - fwrite($spec, "Owner: " . $this->getUser() . "\n\n" ); - fwrite($spec, "Description:\n" ); - fwrite($spec, " Created by " . $this->getUser() . " from composer.\n\n" ); - fwrite($spec, "Root: " .$this->getPath(). "\n\n" ); - fwrite($spec, "Options: noallwrite noclobber nocompress unlocked modtime rmdir\n\n" ); - fwrite($spec, "SubmitOptions: revertunchanged\n\n" ); - fwrite($spec, "LineEnd: local\n\n" ); - if ($this->isStream()){ - fwrite($spec, "Stream:\n" ); - fwrite($spec, " " . $this->getStreamWithoutLabel()."\n" ); - } else { - fwrite($spec, "View: " . $this->getStream() . "/... //" . $this->getClient() . "/" . str_replace("//", "", $this->getStream()) . "/... \n"); - } - } catch(Exception $e){ + $this->writeClientSpecToFile($spec); + } catch (Exception $e) { fclose($spec); throw $e; } fclose($spec); } - public function getComposerFilePath($identifier) - { - if ($this->isStream()){ - $composerFilePath = $this->path . "/composer.json" ; + protected function getP4variable($name){ + if (defined('PHP_WINDOWS_VERSION_BUILD')) { + $command = "p4 set"; + $result = $this->executeCommand($command); + $resArray = explode("\n", $result); + foreach ($resArray as $line) { + $fields = explode("=", $line); + if (strcmp($name, $fields[0]) == 0){ + $index = strpos($fields[1], " "); + if ($index === false){ + $value = $fields[1]; + } else { + $value = substr($fields[1], 0, $index); + } + $value = trim($value); + return $value; + } + } } else { - $composerFilePath = $this->path . "/" . $this->p4depot . "/composer.json" ; + $command = 'echo $' . $name; + $result = trim($this->executeCommand($command)); + return $result; } - return $composerFilePath; + } - public function p4Login(IOInterface $io){ + protected function read($pipe, $name){ + if (feof($pipe)) { + return; + } + $line = fgets($pipe); + while ($line != false){ + $line = fgets($pipe); + } + return; + } + + public function windowsLogin($password){ + $descriptorspec = array( + 0 => array("pipe", "r"), + 1 => array("pipe", "w"), + 2 => array("pipe", "a") + ); + $command = $this->generateP4Command(" login -a"); + $process = proc_open($command, $descriptorspec, $pipes); + if (!is_resource($process)){ + return false; + } + fwrite($pipes[0], $password); + fclose($pipes[0]); + + $this->read($pipes[1], "Output"); + $this->read($pipes[2], "Error"); + + fclose($pipes[1]); + fclose($pipes[2]); + + $return_code = proc_close($process); + + return $return_code; + } + + + public function p4Login(IOInterface $io) { $this->queryP4User($io); - if (!$this->isLoggedIn()){ + if (!$this->isLoggedIn()) { $password = $this->queryP4Password($io); - $command = "echo $password | " . $this->generateP4Command("login -a "); - shell_exec($command); + if (defined('PHP_WINDOWS_VERSION_BUILD')) { + $this->windowsLogin($password); + } else { + $command = "echo $password | ".$this->generateP4Command(" login -a", false); + $this->executeCommand($command); + } } } - public static function checkServerExists($url) - { - $result = shell_exec("p4 -p $url info -s"); + public static function checkServerExists($url, ProcessExecutor $process_executor) { + $process = $process_executor ? : new ProcessExecutor; + $result = ""; + $process->execute("p4 -p $url info -s", $result); $index = strpos($result, "error"); - if ($index === false){ - return true; + if ($index === FALSE) { + return TRUE; } - return false; + + return FALSE; } - public function getComposerInformation($identifier) - { + public function getComposerInformation($identifier) { $index = strpos($identifier, "@"); - if ($index === false){ - $composer_json = "$identifier/composer.json"; + if ($index === FALSE) { + $composer_json = "$identifier/composer.json"; + return $this->getComposerInformationFromPath($composer_json); - } else { + } + else { return $this->getComposerInformationFromLabel($identifier, $index); } } - public function getComposerInformationFromPath($composer_json) - { - $command = $this->generateP4Command(" print $composer_json", false); - $result = shell_exec($command); + + public function getComposerInformationFromPath($composer_json) { + $command = $this->generateP4Command(" print $composer_json"); + $result = $this->executeCommand($command); $index = strpos($result, "{"); - if ($index === false){ + if ($index === FALSE) { return ""; } - if ($index >=0){ + if ($index >= 0) { $rawData = substr($result, $index); - $composer_info = json_decode($rawData, true); + $composer_info = json_decode($rawData, TRUE); + return $composer_info; } + return ""; } - public function getComposerInformationFromLabel($identifier, $index) - { + public function getComposerInformationFromLabel($identifier, $index) { $composer_json_path = substr($identifier, 0, $index) . "/composer.json" . substr($identifier, $index); - $command = $this->generateP4Command(" files $composer_json_path", false); - $result = shell_exec($command); + $command = $this->generateP4Command(" files $composer_json_path", FALSE); + $result = $this->executeCommand($command); $index2 = strpos($result, "no such file(s)."); - if ($index2 === false){ + if ($index2 === FALSE) { $index3 = strpos($result, "change"); - if (!($index3 ===false )){ + if (!($index3 === FALSE)) { $phrase = trim(substr($result, $index3)); $fields = explode(" ", $phrase); $id = $fields[1]; $composer_json = substr($identifier, 0, $index) . "/composer.json@" . $id; + return $this->getComposerInformationFromPath($composer_json); } } + return ""; } - public function getBranches() - { + public function getBranches() { $possible_branches = array(); - if (!$this->isStream()){ - $branches[$this->p4branch] = $this->p4stream; - } else { + if (!$this->isStream()) { + $possible_branches[$this->p4branch] = $this->getStream(); + } + else { $command = $this->generateP4Command("streams //$this->p4depot/..."); - $result = shell_exec($command); + $result = ""; + $this->process->execute($command, $result); $resArray = explode("\n", $result); - foreach ($resArray as $line){ + foreach ($resArray as $line) { $resBits = explode(" ", $line); - if (count($resBits) > 4){ - $branch = substr($resBits[4], 1, strlen($resBits[4])-2); + if (count($resBits) > 4) { + $branch = preg_replace("/[^A-Za-z0-9 ]/", '', $resBits[4]); $possible_branches[$branch] = $resBits[1]; } } } $branches = array(); $branches['master'] = $possible_branches[$this->p4branch]; + return $branches; } - public function getTags() - { + public function getTags() { $command = $this->generateP4Command("labels"); - $result = shell_exec($command); + $result = $this->executeCommand($command); $resArray = explode("\n", $result); $tags = array(); - foreach ($resArray as $line){ + foreach ($resArray as $line) { $index = strpos($line, "Label"); - if (!($index===false)){ + if (!($index === FALSE)) { $fields = explode(" ", $line); - $tags[$fields[1]] = $this->getStream()."@" . $fields[1]; + $tags[$fields[1]] = $this->getStream() . "@" . $fields[1]; } } return $tags; } - public function checkStream () - { - $command = $this->generateP4Command("depots"); - $result = shell_exec($command); + public function checkStream() { + $command = $this->generateP4Command("depots", FALSE); + $result = $this->executeCommand($command); $resArray = explode("\n", $result); - foreach ($resArray as $line){ + foreach ($resArray as $line) { $index = strpos($line, "Depot"); - if (!($index===false)){ + if (!($index === FALSE)) { $fields = explode(" ", $line); - if (strcmp($this->p4depot, $fields[1]) === 0){ + if (strcmp($this->p4depot, $fields[1]) === 0) { $this->p4depotType = $fields[3]; + return $this->isStream(); } } } - return false; + + return FALSE; } } \ No newline at end of file diff --git a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php index 2745887ed..19a374737 100644 --- a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php @@ -62,21 +62,6 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase $this->assertTrue($result); } - public function testGetBranches() - { - $repo_config = array( - 'url' => "perforce.vuhl.root.mrc.local:3710", - 'depot' => "lighthouse" - ); - - $vcs = new PerforceDriver($repo_config, $this->io, $this->config); - $result = $vcs->initialize(); - $this->assertTrue($result); - $branches = $vcs->getBranches(); - //print ("\nBranches are: " . var_export($branches, true)); - $this->assertTrue(strcmp($branches['mainline'], "//lighthouse/mainline") == 0); - } - public function testGetTags() { $repo_config = array( @@ -122,31 +107,5 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase $this->assertNull($dist); } - public function testGetRootIdentifier(){ - $repo_config = array( - 'url' => "perforce.vuhl.root.mrc.local:3710", - 'depot' => "lighthouse" - ); - - $vcs = new PerforceDriver($repo_config, $this->io, $this->config); - $result = $vcs->initialize(); - $this->assertTrue($result); - $rootId = $vcs->getRootIdentifier(); - $this->assertEquals("mainline", $rootId); - } - - public function testHasComposerFile(){ - $repo_config = array( - 'url' => "perforce.vuhl.root.mrc.local:3710", - 'depot' => "lighthouse" - ); - - $vcs = new PerforceDriver($repo_config, $this->io, $this->config); - $result = $vcs->initialize(); - $this->assertTrue($result); - $identifier = $vcs->getRootIdentifier(); - $value = $vcs->hasComposerFile($identifier); - $this->assertTrue($value); - } } diff --git a/tests/Composer/Test/Util/RemoteFilesystemTest.php b/tests/Composer/Test/Util/RemoteFilesystemTest.php index eb8ebc07e..f2950a2da 100644 --- a/tests/Composer/Test/Util/RemoteFilesystemTest.php +++ b/tests/Composer/Test/Util/RemoteFilesystemTest.php @@ -148,18 +148,13 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase public function testCaptureAuthenticationParamsFromUrl() { $io = $this->getMock('Composer\IO\IOInterface'); - $io->expects($this->once()) - ->method('setAuthentication') - ->with($this->equalTo('example.com'), $this->equalTo('user'), $this->equalTo('pass')); + $io + ->expects($this->once()) + ->method('setAuthentication') + ; $fs = new RemoteFilesystem($io); - try { - $fs->getContents('example.com', 'http://user:pass@www.example.com/something'); - } catch (\Exception $e) { - $this->assertInstanceOf('Composer\Downloader\TransportException', $e); - $this->assertEquals(404, $e->getCode()); - $this->assertContains('404 Not Found', $e->getMessage()); - } + $fs->getContents('example.com', 'http://user:pass@www.example.com'); } public function testGetContents() From bab10dd9f8058646f66860f5808552f4d3bfba99 Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Thu, 8 Aug 2013 15:35:21 -0500 Subject: [PATCH 045/238] Added ability to pass p4user and p4password in composer.json --- .../Downloader/PerforceDownloader.php | 20 ++++- .../Repository/Vcs/PerforceDriver.php | 10 ++- src/Composer/Util/Perforce.php | 78 +++++++++++-------- 3 files changed, 72 insertions(+), 36 deletions(-) diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index 8e5f3d01e..325892c32 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -28,7 +28,25 @@ class PerforceDownloader extends VcsDownloader $ref = $package->getSourceReference(); $label = $package->getPrettyVersion(); - $perforce = new Perforce("", "", $package->getSourceUrl(), $path); + $repository = $package->getRepository(); + //assume repository is a Perforce Repository + + $reflector = new \ReflectionClass($repository); + $repoConfigProperty = $reflector->getProperty("repoConfig"); + $repoConfigProperty->setAccessible(true); + $repoConfig = $repoConfigProperty->getValue($repository); + + $p4user = ""; + if (isset($repoConfig['p4user'])) { + $p4user = $repoConfig['p4user']; + } + $p4password = ""; + if (isset($repoConfig['p4password'])) { + $p4password = $repoConfig['p4password']; + } + +// print("Perforce Downloader:doDownload - repoConfig:" . var_dump($repoConfig, true) . "\n\n"); + $perforce = new Perforce("", "", $package->getSourceUrl(), $path, null, $p4user, $p4password); $perforce->setStream($ref); $perforce->queryP4User($this->io); $perforce->writeP4ClientSpec(); diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index a1080e5c4..489a0812c 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -37,10 +37,18 @@ class PerforceDriver extends VcsDriver { if (isset($this->repoConfig['branch'])) { $this->branch = $this->repoConfig['branch']; } + $p4user = ""; + if (isset($this->repoConfig['p4user'])) { + $p4user = $this->repoConfig['p4user']; + } + $p4password = ""; + if (isset($this->repoConfig['p4password'])) { + $p4password = $this->repoConfig['p4password']; + } $repoDir = $this->config->get('cache-vcs-dir') . "/$this->depot"; if (!isset($this->perforce)) { - $this->perforce = new Perforce($this->depot, $this->branch, $this->getUrl(), $repoDir, $this->process); + $this->perforce = new Perforce($this->depot, $this->branch, $this->getUrl(), $repoDir, $this->process, $p4user, $p4password); } $this->perforce->p4Login($this->io); diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 6174c5c49..cb46bac81 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -17,6 +17,7 @@ class Perforce { protected $path; protected $p4client; protected $p4user; + protected $p4password; protected $p4port; protected $p4stream; protected $p4clientSpec; @@ -24,7 +25,7 @@ class Perforce { protected $p4branch; protected $process; - public function __construct($depot, $branch, $port, $path, ProcessExecutor $process = null) { + public function __construct($depot, $branch, $port, $path, ProcessExecutor $process = null, $p4user = null, $p4password = null) { $this->p4depot = $depot; $this->p4branch = $branch; $this->p4port = $port; @@ -32,6 +33,14 @@ class Perforce { $this->process = $process ? : new ProcessExecutor; $fs = new Filesystem(); $fs->ensureDirectoryExists($path); + if (isset($p4user)){ + $this->p4user = $p4user; + } else { + $this->p4user = $this->getP4variable("P4USER"); + } + if (isset($p4password)){ + $this->p4password = $p4password; + } } protected function getRandomValue() { @@ -55,14 +64,6 @@ class Perforce { return $this->p4client; } - public function getUser() { - if (!isset($this->p4user)) { - $this->p4user = $this->getP4variable("P4USER"); - } - - return $this->p4user; - } - protected function getPath() { return $this->path; } @@ -100,6 +101,10 @@ class Perforce { return $p4clientSpec; } + public function getUser() { + return $this->p4user; + } + public function queryP4User(IOInterface $io) { $this->getUser(); if (strlen($this->p4user) <= 0) { @@ -113,11 +118,41 @@ class Perforce { } } + protected function getP4variable($name){ + if (defined('PHP_WINDOWS_VERSION_BUILD')) { + $command = "p4 set"; + $result = $this->executeCommand($command); + $resArray = explode("\n", $result); + foreach ($resArray as $line) { + $fields = explode("=", $line); + if (strcmp($name, $fields[0]) == 0){ + $index = strpos($fields[1], " "); + if ($index === false){ + $value = $fields[1]; + } else { + $value = substr($fields[1], 0, $index); + } + $value = trim($value); + return $value; + } + } + } else { + $command = 'echo $' . $name; + $result = trim($this->executeCommand($command)); + return $result; + } + + } + protected function queryP4Password(IOInterface $io) { + if (isset($this->p4password)){ + return $this->p4password; + } $password = $this->getP4variable("P4PASSWD"); if (strlen($password) <= 0) { $password = $io->askAndHideAnswer("Enter password for Perforce user " . $this->getUser() . ": "); } + $this->p4password = $password; return $password; } @@ -209,31 +244,6 @@ class Perforce { fclose($spec); } - protected function getP4variable($name){ - if (defined('PHP_WINDOWS_VERSION_BUILD')) { - $command = "p4 set"; - $result = $this->executeCommand($command); - $resArray = explode("\n", $result); - foreach ($resArray as $line) { - $fields = explode("=", $line); - if (strcmp($name, $fields[0]) == 0){ - $index = strpos($fields[1], " "); - if ($index === false){ - $value = $fields[1]; - } else { - $value = substr($fields[1], 0, $index); - } - $value = trim($value); - return $value; - } - } - } else { - $command = 'echo $' . $name; - $result = trim($this->executeCommand($command)); - return $result; - } - - } protected function read($pipe, $name){ if (feof($pipe)) { From 1019c014e58b82d5e211216031a00b1c6aec0425 Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Tue, 13 Aug 2013 10:54:35 -0500 Subject: [PATCH 046/238] using theirs --- composer.json | 3 +- composer.lock | 63 ++++++-- .../Downloader/PerforceDownloader.php | 44 +++--- .../Repository/Vcs/PerforceDriver.php | 26 ++-- src/Composer/Repository/VcsRepository.php | 5 + src/Composer/Util/Perforce.php | 96 +++++++----- .../Repository/Vcs/PerforceDriverTest.php | 138 +++++++++--------- 7 files changed, 221 insertions(+), 154 deletions(-) diff --git a/composer.json b/composer.json index f0d4ee56e..77cc9590f 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,8 @@ "symfony/process": "~2.1" }, "require-dev": { - "phpunit/phpunit": "~3.7.10" + "phpunit/phpunit": "~3.7.10", + "mikey179/vfsStream" : "1.2.*" }, "suggest": { "ext-zip": "Enabling the zip extension allows you to unzip archives, and allows gzip compression of all internet traffic", diff --git a/composer.lock b/composer.lock index cae3bad07..5a23476b4 100644 --- a/composer.lock +++ b/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": "370b764a9317165e8ea7a2e1623e031b", + "hash": "6203fdb419c10ffd84f85611fc9eec61", "packages": [ { "name": "justinrainbow/json-schema", @@ -79,17 +79,17 @@ }, { "name": "symfony/console", - "version": "v2.3.3", + "version": "dev-master", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "v2.3.3" + "reference": "872a494b88fba2f62be85e0bc8441e7946bb6ba6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/v2.3.3", - "reference": "v2.3.3", + "url": "https://api.github.com/repos/symfony/Console/zipball/872a494b88fba2f62be85e0bc8441e7946bb6ba6", + "reference": "872a494b88fba2f62be85e0bc8441e7946bb6ba6", "shasum": "" }, "require": { @@ -104,7 +104,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.4-dev" } }, "autoload": { @@ -128,7 +128,7 @@ ], "description": "Symfony Console Component", "homepage": "http://symfony.com", - "time": "2013-07-21 12:12:18" + "time": "2013-08-09 06:00:31" }, { "name": "symfony/finder", @@ -179,17 +179,17 @@ }, { "name": "symfony/process", - "version": "v2.3.3", + "version": "dev-master", "target-dir": "Symfony/Component/Process", "source": { "type": "git", "url": "https://github.com/symfony/Process.git", - "reference": "v2.3.3" + "reference": "723fe405fcc878ae75469babcb9507d292797ece" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/v2.3.3", - "reference": "v2.3.3", + "url": "https://api.github.com/repos/symfony/Process/zipball/723fe405fcc878ae75469babcb9507d292797ece", + "reference": "723fe405fcc878ae75469babcb9507d292797ece", "shasum": "" }, "require": { @@ -198,7 +198,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.4-dev" } }, "autoload": { @@ -222,10 +222,40 @@ ], "description": "Symfony Process Component", "homepage": "http://symfony.com", - "time": "2013-08-02 21:51:01" + "time": "2013-08-09 07:03:52" } ], "packages-dev": [ + { + "name": "mikey179/vfsStream", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/mikey179/vfsStream.git", + "reference": "v1.2.0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mikey179/vfsStream/zipball/v1.2.0", + "reference": "v1.2.0", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "org\\bovigo\\vfs\\": "src/main/php" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD" + ], + "homepage": "http://vfs.bovigo.org/", + "time": "2013-04-01 10:41:02" + }, { "name": "phpunit/php-code-coverage", "version": "1.2.12", @@ -645,9 +675,10 @@ ], "minimum-stability": "stable", - "stability-flags": [ - - ], + "stability-flags": { + "symfony/console": 20, + "symfony/process": 20 + }, "platform": { "php": ">=5.3.2" }, diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index 325892c32..5ed241d79 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -13,6 +13,7 @@ namespace Composer\Downloader; use Composer\Package\PackageInterface; +use Composer\Repository\VcsRepository; use Composer\Util\Perforce; /** @@ -20,6 +21,8 @@ use Composer\Util\Perforce; */ class PerforceDownloader extends VcsDownloader { + protected $perforce; + /** * {@inheritDoc} */ @@ -28,30 +31,29 @@ class PerforceDownloader extends VcsDownloader $ref = $package->getSourceReference(); $label = $package->getPrettyVersion(); + $this->initPerforce($package, $path); + $this->perforce->setStream($ref); + $this->perforce->queryP4User($this->io); + $this->perforce->writeP4ClientSpec(); + $this->perforce->connectClient(); + $this->perforce->syncCodeBase($label); + } + + private function initPerforce($package, $path){ + if (isset($this->perforce)){ + return; + } $repository = $package->getRepository(); - //assume repository is a Perforce Repository + $repoConfig = $this->getRepoConfig($repository); + $this->perforce = new Perforce($repoConfig, $package->getSourceUrl(), $path); + } - $reflector = new \ReflectionClass($repository); - $repoConfigProperty = $reflector->getProperty("repoConfig"); - $repoConfigProperty->setAccessible(true); - $repoConfig = $repoConfigProperty->getValue($repository); + public function injectPerforce($perforce){ + $this->perforce = $perforce; + } - $p4user = ""; - if (isset($repoConfig['p4user'])) { - $p4user = $repoConfig['p4user']; - } - $p4password = ""; - if (isset($repoConfig['p4password'])) { - $p4password = $repoConfig['p4password']; - } - -// print("Perforce Downloader:doDownload - repoConfig:" . var_dump($repoConfig, true) . "\n\n"); - $perforce = new Perforce("", "", $package->getSourceUrl(), $path, null, $p4user, $p4password); - $perforce->setStream($ref); - $perforce->queryP4User($this->io); - $perforce->writeP4ClientSpec(); - $perforce->connectClient(); - $perforce->syncCodeBase($label); + private function getRepoConfig(VcsRepository $repository){ + return $repository->getRepoConfig(); } /** diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 489a0812c..0f930a52b 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -32,25 +32,13 @@ class PerforceDriver extends VcsDriver { * {@inheritDoc} */ public function initialize() { - $this->depot = $this->repoConfig['depot']; + $this->depot = $this->repoConfig['depot']; $this->branch = ""; if (isset($this->repoConfig['branch'])) { $this->branch = $this->repoConfig['branch']; } - $p4user = ""; - if (isset($this->repoConfig['p4user'])) { - $p4user = $this->repoConfig['p4user']; - } - $p4password = ""; - if (isset($this->repoConfig['p4password'])) { - $p4password = $this->repoConfig['p4password']; - } - - $repoDir = $this->config->get('cache-vcs-dir') . "/$this->depot"; - if (!isset($this->perforce)) { - $this->perforce = new Perforce($this->depot, $this->branch, $this->getUrl(), $repoDir, $this->process, $p4user, $p4password); - } + $this->initPerforce(); $this->perforce->p4Login($this->io); $this->perforce->checkStream($this->depot); @@ -60,6 +48,15 @@ class PerforceDriver extends VcsDriver { return TRUE; } + private function initPerforce() { + if (isset($this->perforce)) { + return; + } + + $repoDir = $this->config->get('cache-vcs-dir') . "/$this->depot"; + $this->perforce = new Perforce($this->repoConfig, $this->getUrl(), $repoDir, $this->process); + } + public function injectPerforce(Perforce $perforce) { $this->perforce = $perforce; } @@ -95,6 +92,7 @@ class PerforceDriver extends VcsDriver { */ public function getTags() { $tags = $this->perforce->getTags(); + return $tags; } diff --git a/src/Composer/Repository/VcsRepository.php b/src/Composer/Repository/VcsRepository.php index bb3bacc68..2b876bc22 100644 --- a/src/Composer/Repository/VcsRepository.php +++ b/src/Composer/Repository/VcsRepository.php @@ -59,6 +59,11 @@ class VcsRepository extends ArrayRepository $this->repoConfig = $repoConfig; } + public function getRepoConfig() + { + return $this->repoConfig; + } + public function setLoader(LoaderInterface $loader) { $this->loader = $loader; diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index cb46bac81..5b032b71b 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -25,21 +25,27 @@ class Perforce { protected $p4branch; protected $process; - public function __construct($depot, $branch, $port, $path, ProcessExecutor $process = null, $p4user = null, $p4password = null) { - $this->p4depot = $depot; - $this->p4branch = $branch; + public function __construct($repoConfig, $port, $path, ProcessExecutor $process = NULL) { $this->p4port = $port; $this->path = $path; $this->process = $process ? : new ProcessExecutor; $fs = new Filesystem(); $fs->ensureDirectoryExists($path); - if (isset($p4user)){ - $this->p4user = $p4user; - } else { + + if (isset($repoConfig['depot'])) { + $this->p4depot = $repoConfig['depot']; + } + if (isset($repoConfig['branch'])) { + $this->p4branch = $repoConfig['branch']; + } + if (isset($repoConfig['p4user'])) { + $this->p4user = $repoConfig['p4user']; + } + else { $this->p4user = $this->getP4variable("P4USER"); } - if (isset($p4password)){ - $this->p4password = $p4password; + if (isset($repoConfig['p4password'])) { + $this->p4password = $repoConfig['p4password']; } } @@ -47,6 +53,10 @@ class Perforce { return mt_rand(1000, 9999); } + protected function isWindows(){ + return defined('PHP_WINDOWS_VERSION_BUILD'); + } + protected function executeCommand($command) { $result = ""; $this->process->execute($command, $result); @@ -72,6 +82,10 @@ class Perforce { return $this->p4port; } + protected function isStream() { + return (strcmp($this->p4depotType, "stream") === 0); + } + protected function getStream() { if (!isset($this->p4stream)) { if ($this->isStream()) { @@ -107,45 +121,54 @@ class Perforce { public function queryP4User(IOInterface $io) { $this->getUser(); - if (strlen($this->p4user) <= 0) { - $this->p4user = $io->ask("Enter P4 User:"); - if (defined('PHP_WINDOWS_VERSION_BUILD')) { - $command = "p4 set P4USER=$this->p4user"; - } else { - $command = "export P4USER=$this->p4user"; - } - $result = $this->executeCommand($command); + if (strlen($this->p4user) > 0) { + return; } + $this->p4user = $this->getP4variable("P4USER"); + if (strlen($this->p4user) > 0) { + return; + } + $this->p4user = $io->ask("Enter P4 User:"); + if ($this->isWindows()) { + $command = "p4 set P4USER=$this->p4user"; + } + else { + $command = "export P4USER=$this->p4user"; + } + $result = $this->executeCommand($command); } - protected function getP4variable($name){ - if (defined('PHP_WINDOWS_VERSION_BUILD')) { + protected function getP4variable($name) { + if ($this->isWindows()) { $command = "p4 set"; $result = $this->executeCommand($command); $resArray = explode("\n", $result); foreach ($resArray as $line) { $fields = explode("=", $line); - if (strcmp($name, $fields[0]) == 0){ + if (strcmp($name, $fields[0]) == 0) { $index = strpos($fields[1], " "); - if ($index === false){ + if ($index === FALSE) { $value = $fields[1]; - } else { + } + else { $value = substr($fields[1], 0, $index); } $value = trim($value); + return $value; } } - } else { + } + else { $command = 'echo $' . $name; $result = trim($this->executeCommand($command)); + return $result; } - } protected function queryP4Password(IOInterface $io) { - if (isset($this->p4password)){ + if (isset($this->p4password)) { return $this->p4password; } $password = $this->getP4variable("P4PASSWD"); @@ -153,11 +176,8 @@ class Perforce { $password = $io->askAndHideAnswer("Enter password for Perforce user " . $this->getUser() . ": "); } $this->p4password = $password; - return $password; - } - protected function isStream() { - return (strcmp($this->p4depotType, "stream") === 0); + return $password; } protected function generateP4Command($command, $useClient = TRUE) { @@ -179,6 +199,7 @@ class Perforce { if ($index === FALSE) { return FALSE; } + return TRUE; } @@ -245,18 +266,19 @@ class Perforce { } - protected function read($pipe, $name){ + protected function read($pipe, $name) { if (feof($pipe)) { return; } $line = fgets($pipe); - while ($line != false){ + while ($line != FALSE) { $line = fgets($pipe); } + return; } - public function windowsLogin($password){ + public function windowsLogin($password) { $descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), @@ -264,8 +286,8 @@ class Perforce { ); $command = $this->generateP4Command(" login -a"); $process = proc_open($command, $descriptorspec, $pipes); - if (!is_resource($process)){ - return false; + if (!is_resource($process)) { + return FALSE; } fwrite($pipes[0], $password); fclose($pipes[0]); @@ -286,10 +308,11 @@ class Perforce { $this->queryP4User($io); if (!$this->isLoggedIn()) { $password = $this->queryP4Password($io); - if (defined('PHP_WINDOWS_VERSION_BUILD')) { + if ($this->isWindows()) { $this->windowsLogin($password); - } else { - $command = "echo $password | ".$this->generateP4Command(" login -a", false); + } + else { + $command = "echo $password | " . $this->generateP4Command(" login -a", FALSE); $this->executeCommand($command); } } @@ -392,6 +415,7 @@ class Perforce { $tags[$fields[1]] = $this->getStream() . "@" . $fields[1]; } } + return $tags; } diff --git a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php index 19a374737..db1485836 100644 --- a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php @@ -14,97 +14,103 @@ namespace Composer\Test\Repository\Vcs; -#use Composer\Downloader\TransportException; + use Composer\Repository\Vcs\PerforceDriver; use Composer\Util\Filesystem; use Composer\Config; -use Composer\IO\ConsoleIO; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\Console\Helper\HelperSet; -class PerforceDriverTest extends \PHPUnit_Framework_TestCase -{ +class PerforceDriverTest extends \PHPUnit_Framework_TestCase { private $config; private $io; + private $process; + private $remoteFileSystem; + private $testPath; - public function setUp() - { + public function setUp() { + $this->testPath = sys_get_temp_dir() . '/composer-test'; $this->config = new Config(); - $this->config->merge(array( - 'config' => array( - 'home' => sys_get_temp_dir() . '/composer-test', - ), - )); - $inputParameters = array(); - $input = new ArrayInput($inputParameters); - $output = new ConsoleOutput(); - $helperSet = new HelperSet(); - $this->io = new ConsoleIO($input, $output, $helperSet); + $this->config->merge( + array( + 'config' => array( + 'home' => $this->testPath, + ), + ) + ); + + $this->io = $this->getMock('Composer\IO\IOInterface'); + $this->process = $this->getMock('Composer\Util\ProcessExecutor'); + $this->remoteFileSystem = $this->getMockBuilder('Composer\Util\RemoteFilesystem')->disableOriginalConstructor()->getMock(); } - public function tearDown() - { + public function tearDown() { $fs = new Filesystem; - $fs->removeDirectory(sys_get_temp_dir() . '/composer-test'); + $fs->removeDirectory($this->testPath); } - public function testPrivateRepository() - { - $repo_config = array( - 'url' => "perforce.vuhl.root.mrc.local:3710", - 'depot' => "lighthouse" - ); + //Test: + //hasComposerFile - $vcs = new PerforceDriver($repo_config, $this->io, $this->config); - $result = $vcs->initialize(); - $this->assertTrue($result); + public function testInitializeCapturesVariablesFromRepoConfig() { + $this->setUp(); + $repo_config = array( + 'url' => 'TEST_PERFORCE_URL', + 'depot' => 'TEST_DEPOT_CONFIG', + 'branch' => 'TEST_BRANCH_CONFIG' + ); + $driver = new TestingPerforceDriver($repo_config, $this->io, $this->config, $this->process, $this->remoteFileSystem); + $arguments = array(array('depot'=>'TEST_DEPOT', 'branch'=>'TEST_BRANCH'), 'port'=>'TEST_PORT', 'path'=>$this->testPath); + $perforce = $this->getMock('Composer\Util\Perforce', null, $arguments); + $driver->injectPerforce($perforce); + $driver->initialize(); + $this->assertEquals("TEST_PERFORCE_URL", $driver->getUrl()); + $this->assertEquals("TEST_DEPOT_CONFIG", $driver->getDepot()); + $this->assertEquals("TEST_BRANCH_CONFIG", $driver->getBranch()); } - public function testGetTags() - { + public function testInitializeLogsInAndConnectsClient() { + $this->setUp(); $repo_config = array( - 'url' => "perforce.vuhl.root.mrc.local:3710", - 'depot' => "lighthouse" + 'url' => 'TEST_PERFORCE_URL', + 'depot' => 'TEST_DEPOT_CONFIG', + 'branch' => 'TEST_BRANCH_CONFIG' ); + $driver = new TestingPerforceDriver($repo_config, $this->io, $this->config, $this->process, $this->remoteFileSystem); + $perforce = $this->getMockBuilder('Composer\Util\Perforce')->disableOriginalConstructor()->getMock(); + $perforce->expects($this->at(0)) + ->method('p4Login') + ->with($this->io); + $perforce->expects($this->at(1)) + ->method('checkStream') + ->with($this->equalTo("TEST_DEPOT_CONFIG")); + $perforce->expects($this->at(2)) + ->method('writeP4ClientSpec'); + $perforce->expects($this->at(3)) + ->method('connectClient'); - $vcs = new PerforceDriver($repo_config, $this->io, $this->config); - $result = $vcs->initialize(); - $this->assertTrue($result); - $tags = $vcs->getTags(); - $this->assertTrue(empty($tags)); + $driver->injectPerforce($perforce); + $driver->initialize(); } - public function testGetSource() - { + public function testHasComposerFile() { + $this->setUp(); $repo_config = array( - 'url' => "perforce.vuhl.root.mrc.local:3710", - 'depot' => "lighthouse" + 'url' => 'TEST_PERFORCE_URL', + 'depot' => 'TEST_DEPOT_CONFIG', + 'branch' => 'TEST_BRANCH_CONFIG' ); - - $vcs = new PerforceDriver($repo_config, $this->io, $this->config); - $result = $vcs->initialize(); + $driver = new TestingPerforceDriver($repo_config, $this->io, $this->config, $this->process, $this->remoteFileSystem); + $arguments = array(array('depot'=>'TEST_DEPOT', 'branch'=>'TEST_BRANCH'), 'port'=>'TEST_PORT', 'path'=>$this->testPath); + $perforce = $this->getMock('Composer\Util\Perforce', array('getComposerInformation'), $arguments); + $perforce->expects($this->at(0)) + ->method('getComposerInformation') + ->with($this->equalTo("//TEST_DEPOT_CONFIG/TEST_IDENTIFIER")) + ->will($this->returnValue("Some json stuff")); + $driver->injectPerforce($perforce); + $driver->initialize(); + $identifier = "TEST_IDENTIFIER"; + $result = $driver->hasComposerFile($identifier); $this->assertTrue($result); - $identifier = $vcs->getRootIdentifier(); - $source = $vcs->getSource($identifier); - $this->assertEquals($source['type'], "perforce"); - $this->assertEquals($source['reference'], $identifier); - } - - public function testGetDist() - { - $repo_config = array( - 'url' => "perforce.vuhl.root.mrc.local:3710", - 'depot' => "lighthouse" - ); - - $vcs = new PerforceDriver($repo_config, $this->io, $this->config); - $result = $vcs->initialize(); - $this->assertTrue($result); - $identifier = $vcs->getRootIdentifier(); - $dist = $vcs->getDist($identifier); - $this->assertNull($dist); } } From 10159576591ddada028915bd8ad17142137f6483 Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Fri, 9 Aug 2013 14:24:58 -0500 Subject: [PATCH 047/238] Added tests and code for tests --- .../Downloader/PerforceDownloaderTest.php | 91 +++ .../Repository/Vcs/TestingPerforceDriver.php | 26 + tests/Composer/Test/Util/PerforceTest.php | 537 ++++++++++++++++++ tests/Composer/Test/Util/TestingPerforce.php | 106 ++++ 4 files changed, 760 insertions(+) create mode 100644 tests/Composer/Test/Downloader/PerforceDownloaderTest.php create mode 100644 tests/Composer/Test/Repository/Vcs/TestingPerforceDriver.php create mode 100644 tests/Composer/Test/Util/PerforceTest.php create mode 100644 tests/Composer/Test/Util/TestingPerforce.php diff --git a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php new file mode 100644 index 000000000..66ed81776 --- /dev/null +++ b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php @@ -0,0 +1,91 @@ +testPath = sys_get_temp_dir() . '/composer-test'; + $this->config = new Config(); + $this->config->merge( + array( + 'config' => array( + 'home' => $this->testPath, + ), + ) + ); + $this->io = $this->getMock('Composer\IO\IOInterface'); + } + + + public function testDoDownloadGetRepoConfig() { + $downloader = new PerforceDownloader($this->io, $this->config); + $package = $this->getMock('Composer\Package\PackageInterface' ); + $repoConfig = array('url'=>'TEST_URL','p4user'=>'TEST_USER'); + $repository = $this->getMock('Composer\Repository\VcsRepository', array('getRepoConfig'), array($repoConfig, $this->io, $this->config)); + $package->expects($this->at(0)) + ->method('getSourceReference') + ->will($this->returnValue("SOURCE_REF")); + $package->expects($this->at(1)) + ->method('getPrettyVersion') + ->will($this->returnValue("100")); + $package->expects($this->at(2)) + ->method('getRepository') + ->will($this->returnValue($repository)); + $repository->expects($this->at(0)) + ->method('getRepoConfig'); + $path = $this->testPath; + $downloader->doDownload($package, $path); + } + + public function testDoDownload() { + $downloader = new PerforceDownloader($this->io, $this->config); + $repoConfig = array("depot"=>"TEST_DEPOT", "branch"=>"TEST_BRANCH", "p4user"=>"TEST_USER"); + $port = "TEST_PORT"; + $path = "TEST_PATH"; + $perforce = $this->getMock('Composer\Util\Perforce', array('setStream', 'queryP4User', 'writeP4ClientSpec', 'connectClient', 'syncCodeBase'), array($repoConfig, $port, $path)); + $ref = "SOURCE_REF"; + $label = "LABEL"; + $perforce->expects($this->at(0)) + ->method('setStream') + ->with($this->equalTo($ref)); + $perforce->expects($this->at(1)) + ->method('queryP4User') + ->with($this->io); + $perforce->expects($this->at(2)) + ->method('writeP4ClientSpec'); + $perforce->expects($this->at(3)) + ->method('connectClient'); + $perforce->expects($this->at(4)) + ->method('syncCodeBase') + ->with($this->equalTo($label)); + $downloader->injectPerforce($perforce); + $package = $this->getMock('Composer\Package\PackageInterface' ); + $package->expects($this->at(0)) + ->method('getSourceReference') + ->will($this->returnValue($ref)); + $package->expects($this->at(1)) + ->method('getPrettyVersion') + ->will($this->returnValue($label)); + $path = $this->testPath; + $downloader->doDownload($package, $path); + + } +} diff --git a/tests/Composer/Test/Repository/Vcs/TestingPerforceDriver.php b/tests/Composer/Test/Repository/Vcs/TestingPerforceDriver.php new file mode 100644 index 000000000..574c69377 --- /dev/null +++ b/tests/Composer/Test/Repository/Vcs/TestingPerforceDriver.php @@ -0,0 +1,26 @@ +depot; + } + public function getBranch(){ + return $this->branch; + } + +} \ No newline at end of file diff --git a/tests/Composer/Test/Util/PerforceTest.php b/tests/Composer/Test/Util/PerforceTest.php new file mode 100644 index 000000000..8a653394f --- /dev/null +++ b/tests/Composer/Test/Util/PerforceTest.php @@ -0,0 +1,537 @@ +processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); + $repoConfig = array("depot"=>"depot", "branch"=>"branch", "p4user"=>"user"); + $this->perforce = new TestingPerforce($repoConfig, "port", "path", $this->processExecutor); + } + + public function testGetClientWithoutStream() { + $client = $this->perforce->testGetClient(); + $expected = "composer_perforce_TEST_depot"; + $this->assertEquals($expected, $client); + } + + public function testGetClientFromStream() { + $this->perforce->setDepotType("stream"); + $client = $this->perforce->testGetClient(); + + $expected = "composer_perforce_TEST_depot_branch"; + $this->assertEquals($expected, $client); + } + + public function testGetStreamWithoutStream() { + $stream = $this->perforce->testGetStream(); + $this->assertEquals("//depot", $stream); + } + + public function testGetStreamWithStream() { + $this->perforce->setDepotType("stream"); + $stream = $this->perforce->testGetStream(); + $this->assertEquals("//depot/branch", $stream); + } + + public function testGetStreamWithoutLabel() { + $stream = $this->perforce->testGetStreamWithoutLabel(); + $this->assertEquals("//depot", $stream); + $this->perforce->setDepotType("stream"); + $stream = $this->perforce->testGetStreamWithoutLabel(); + $this->assertEquals("//depot/branch", $stream); + $this->perforce->setStream("//depot/branching@label"); + $stream = $this->perforce->testGetStreamWithoutLabel(); + $this->assertEquals("//depot/branching", $stream); + } + + public function testGetClientSpec() { + $clientSpec = $this->perforce->testGetClientSpec(); + $expected = "path/composer_perforce_TEST_depot.p4.spec"; + $this->assertEquals($expected, $clientSpec); + } + + public function testGenerateP4Command() { + $command = "do something"; + $p4Command = $this->perforce->testGenerateP4Command($command); + $expected = "p4 -u user -c composer_perforce_TEST_depot -p port do something"; + $this->assertEquals($expected, $p4Command); + } + + public function testQueryP4UserWithUserAlreadySet(){ + $io = $this->getMock('Composer\IO\IOInterface'); + + $this->perforce->setP4User("TEST_USER"); + $this->perforce->queryP4user($io); + $this->assertEquals("TEST_USER", $this->perforce->getUser()); + } + + public function testQueryP4UserWithUserSetInP4VariablesWithWindowsOS(){ + $this->perforce->windows_flag = true; + + $io = $this->getMock('Composer\IO\IOInterface'); + $expectedCommand = "p4 set"; + $this->processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnCallback(function($command, &$output) {$output = "P4USER=TEST_P4VARIABLE_USER\n"; return true;})); + + $this->perforce->setP4User(null); + $this->perforce->queryP4user($io); + $this->assertEquals("TEST_P4VARIABLE_USER", $this->perforce->getUser()); + } + + public function testQueryP4UserWithUserSetInP4VariablesNotWindowsOS(){ + $this->perforce->windows_flag = false; + + $io = $this->getMock('Composer\IO\IOInterface'); + $expectedCommand = 'echo $P4USER'; + $this->processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnCallback(function($command, &$output) {$output = "TEST_P4VARIABLE_USER\n"; return true;})); + + $this->perforce->setP4User(null); + $this->perforce->queryP4user($io); + $this->assertEquals("TEST_P4VARIABLE_USER", $this->perforce->getUser()); + } + + public function testQueryP4UserQueriesForUser(){ + $io = $this->getMock('Composer\IO\IOInterface'); + $expectedQuestion = "Enter P4 User:"; + $io->expects($this->at(0)) + ->method('ask') + ->with($this->equalTo($expectedQuestion)) + ->will($this->returnValue("TEST_QUERY_USER")); + + $this->perforce->setP4User(null); + $this->perforce->queryP4user($io); + $this->assertEquals("TEST_QUERY_USER", $this->perforce->getUser()); + } + + public function testQueryP4UserStoresResponseToQueryForUserWithWindows(){ + $this->perforce->windows_flag = true; + + $io = $this->getMock('Composer\IO\IOInterface'); + $expectedQuestion = "Enter P4 User:"; + $io->expects($this->at(0)) + ->method('ask') + ->with($this->equalTo($expectedQuestion)) + ->will($this->returnValue("TEST_QUERY_USER")); + $expectedCommand = "p4 set P4USER=TEST_QUERY_USER"; + $this->processExecutor->expects($this->at(1)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnValue(0)); + + $this->perforce->setP4User(null); + $this->perforce->queryP4user($io); + } + + public function testQueryP4UserStoresResponseToQueryForUserWithoutWindows(){ + $this->perforce->windows_flag = false; + + $io = $this->getMock('Composer\IO\IOInterface'); + $expectedQuestion = "Enter P4 User:"; + $io->expects($this->at(0)) + ->method('ask') + ->with($this->equalTo($expectedQuestion)) + ->will($this->returnValue("TEST_QUERY_USER")); + $expectedCommand = "export P4USER=TEST_QUERY_USER"; + $this->processExecutor->expects($this->at(1)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnValue(0)); + + $this->perforce->setP4User(null); + $this->perforce->queryP4user($io); + } + + public function testQueryP4PasswordWithPasswordAlreadySet(){ + $io = $this->getMock('Composer\IO\IOInterface'); + + $this->perforce->setP4Password("TEST_PASSWORD"); + $password = $this->perforce->testQueryP4Password($io); + $this->assertEquals("TEST_PASSWORD", $password); + } + + public function testQueryP4PasswordWithPasswordSetInP4VariablesWithWindowsOS(){ + $this->perforce->windows_flag = true; + + $io = $this->getMock('Composer\IO\IOInterface'); + $expectedCommand = "p4 set"; + $this->processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnCallback(function($command, &$output) {$output = "P4PASSWD=TEST_P4VARIABLE_PASSWORD\n"; return true;})); + + $this->perforce->setP4Password(null); + $password = $this->perforce->testQueryP4Password($io); + $this->assertEquals("TEST_P4VARIABLE_PASSWORD", $password); + } + + public function testQueryP4PasswordWithPasswordSetInP4VariablesNotWindowsOS(){ + $this->perforce->windows_flag = false; + + $io = $this->getMock('Composer\IO\IOInterface'); + $expectedCommand = 'echo $P4PASSWD'; + $this->processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnCallback(function($command, &$output) {$output = "TEST_P4VARIABLE_PASSWORD\n"; return true;})); + + $this->perforce->setP4Password(null); + $password = $this->perforce->testQueryP4Password($io); + $this->assertEquals("TEST_P4VARIABLE_PASSWORD", $password); + } + + public function testQueryP4PasswordQueriesForPassword(){ + $io = $this->getMock('Composer\IO\IOInterface'); + $expectedQuestion = "Enter password for Perforce user user: "; + $io->expects($this->at(0)) + ->method('askAndHideAnswer') + ->with($this->equalTo($expectedQuestion)) + ->will($this->returnValue("TEST_QUERY_PASSWORD")); + + $this->perforce->setP4Password(null); + $password = $this->perforce->testQueryP4Password($io); + $this->assertEquals("TEST_QUERY_PASSWORD", $password); + } + + public function testWriteP4ClientSpecWithoutStream() { + vfsStreamWrapper::register(); + VfsStreamWrapper::setRoot(new vfsStreamDirectory("path")); + $clientSpec = $this->perforce->testGetClientSpec(); + $this->perforce->writeP4ClientSpec(); + $spec = fopen(vfsStream::url($clientSpec), 'r'); + $expectedArray = $this->getExpectedClientSpec(FALSE); + try { + foreach ($expectedArray as $expected) { + $this->assertStringStartsWith($expected, fgets($spec)); + } + $this->assertFalse(fgets($spec)); + } catch (Exception $e) { + fclose($spec); + throw $e; + } + fclose($spec); + } + + public function testWriteP4ClientSpecWithStream() { + vfsStreamWrapper::register(); + VfsStreamWrapper::setRoot(new vfsStreamDirectory("path")); + $this->perforce->setStream("//depot/branching@label"); + $clientSpec = $this->perforce->testGetClientSpec(); + $this->perforce->writeP4ClientSpec(); + $spec = fopen(vfsStream::url($clientSpec), 'r'); + $expectedArray = $this->getExpectedClientSpec(TRUE); + try { + foreach ($expectedArray as $expected) { + $this->assertStringStartsWith($expected, fgets($spec)); + } + $this->assertFalse(fgets($spec)); + } catch (Exception $e) { + fclose($spec); + throw $e; + } + fclose($spec); + } + + public function testIsLoggedIn() { + $expectedCommand = $this->winCompat("p4 -u user -p port login -s"); + $this->processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedCommand), $this->equalTo(null)) + ->will($this->returnValue(0)); + + $this->perforce->testIsLoggedIn(); + } + + public function testConnectClient() { + $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot -p port client -i < path/composer_perforce_TEST_depot.p4.spec"); + $this->processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedCommand), $this->equalTo(null)) + ->will($this->returnValue(0)); + + $this->perforce->connectClient(); + } + + public function testGetBranchesWithStream() { + $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot_branchlabel -p port streams //depot/..."); + $this->processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnCallback(function($command, &$output) {$output = "Stream //depot/branch mainline none 'branch'\n"; return true;})); + + $this->perforce->setStream("//depot/branch@label"); + $branches = $this->perforce->getBranches(); + $this->assertEquals("//depot/branch", $branches['master']); + } + + public function testGetBranchesWithoutStream() { + $expectedCommand = $this->winCompat("p4 -u user -p port depots"); + $this->processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnCallback(function($command, &$output) {$output = "Depot depot 2013/01/28 local /path/to/depots/depot/... 'depot project'\n"; return true;})); + + $result = $this->perforce->checkStream("depot"); + $this->assertFalse($result); + + $branches = $this->perforce->getBranches(); + $this->assertEquals("//depot", $branches['master']); + } + + public function testGetTagsWithoutStream() { + $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot -p port labels"); + $this->processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnCallback(function($command, &$output) {$output = "Label 0.0.1 2013/07/31 'First Label!'\nLabel 0.0.2 2013/08/01 'Second Label!'\n"; return true;})); + + $tags = $this->perforce->getTags(); + $this->assertEquals("//depot@0.0.1", $tags['0.0.1']); + $this->assertEquals("//depot@0.0.2", $tags['0.0.2']); + } + + public function testGetTagsWithStream() { + $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot_branch -p port labels"); + $this->processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnCallback(function($command, &$output) {$output = "Label 0.0.1 2013/07/31 'First Label!'\nLabel 0.0.2 2013/08/01 'Second Label!'\n"; return true;})); + + $this->perforce->setStream("//depot/branch"); + $tags = $this->perforce->getTags(); + $this->assertEquals("//depot/branch@0.0.1", $tags['0.0.1']); + $this->assertEquals("//depot/branch@0.0.2", $tags['0.0.2']); + } + + public function testCheckStreamWithoutStream() { + $this->perforce->commandReturnValue = "Depot depot 2013/01/28 local /path/to/depots/depot/... 'depot project'"; + $result = $this->perforce->checkStream("depot"); + $this->assertFalse($result); + $this->assertFalse($this->perforce->testIsStream()); + } + + public function testCheckStreamWithStream() { + $line1 = "Depot depot 2013/01/28 branch /path/to/depots/depot/... 'depot project'\n"; + $line2 = "Depot depot 2013/01/28 development /path/to/depots/depot/... 'depot project'\n"; + $this->perforce->commandReturnValue = $line1 . $line2; + $result = $this->perforce->checkStream("depot"); + $this->assertFalse($result); + $this->assertFalse($this->perforce->testIsStream()); + } + + public function testGetComposerInformationWithoutLabelWithoutStream() { + $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot -p port print //depot/composer.json"); + $this->processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnCallback(function($command, &$output) {$output = PerforceTest::getComposerJson(); return true;})); + + $result = $this->perforce->getComposerInformation("//depot"); + $expected = array( + "name" => "test/perforce", + "description" => "Basic project for testing", + "minimum-stability" => "dev", + "autoload" => array("psr-0" => array()) + ); + $this->assertEquals($expected, $result); + } + + public function testGetComposerInformationWithLabelWithoutStream() { + $expectedCommand = $this->winCompat("p4 -u user -p port files //depot/composer.json@0.0.1"); + $this->processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnCallback(function($command, &$output) {$output = "//depot/composer.json#1 - branch change 10001 (text)"; return true;})); + + $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot -p port print //depot/composer.json@10001"); + $this->processExecutor->expects($this->at(1)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnCallback(function($command, &$output) {$output = PerforceTest::getComposerJson(); return true;})); + + $result = $this->perforce->getComposerInformation("//depot@0.0.1"); + + $expected = array( + "name" => "test/perforce", + "description" => "Basic project for testing", + "minimum-stability" => "dev", + "autoload" => array("psr-0" => array()) + ); + $this->assertEquals($expected, $result); + } + + public function testGetComposerInformationWithoutLabelWithStream() { + $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot_branch -p port print //depot/branch/composer.json"); + $this->processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnCallback(function($command, &$output) {$output = PerforceTest::getComposerJson(); return true;})); + + $this->perforce->setStream("//depot/branch"); + $result = $this->perforce->getComposerInformation("//depot/branch"); + + $expected = array( + "name" => "test/perforce", + "description" => "Basic project for testing", + "minimum-stability" => "dev", + "autoload" => array("psr-0" => array()) + ); + $this->assertEquals($expected, $result); + } + + public function testGetComposerInformationWithLabelWithStream() { + $expectedCommand = $this->winCompat("p4 -u user -p port files //depot/branch/composer.json@0.0.1"); + $this->processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnCallback(function($command, &$output) {$output = "//depot/composer.json#1 - branch change 10001 (text)"; return true;})); + + $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot_branch -p port print //depot/branch/composer.json@10001"); + $this->processExecutor->expects($this->at(1)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnCallback(function($command, &$output) {$output = PerforceTest::getComposerJson(); return true;})); + + $this->perforce->setStream("//depot/branch"); + $result = $this->perforce->getComposerInformation("//depot/branch@0.0.1"); + + $expected = array( + "name" => "test/perforce", + "description" => "Basic project for testing", + "minimum-stability" => "dev", + "autoload" => array("psr-0" => array()) + ); + $this->assertEquals($expected, $result); + } + + public function testSyncCodeBaseWithoutStream() { + $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot -p port sync -f @label"); + $this->processExecutor->expects($this->at(1)) + ->method('execute') + ->with($this->equalTo($expectedCommand), $this->equalTo(null)) + ->will($this->returnValue(0)); + + $this->perforce->syncCodeBase("label"); + } + + public function testSyncCodeBaseWithStream() { + $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot_branch -p port sync -f @label"); + $this->processExecutor->expects($this->at(1)) + ->method('execute') + ->with($this->equalTo($expectedCommand), $this->equalTo(null)) + ->will($this->returnValue(0)); + + $this->perforce->setStream("//depot/branch"); + $this->perforce->syncCodeBase("label"); + } + + public function testCheckServerExists() { + $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); + + $expectedCommand = $this->winCompat("p4 -p perforce.does.exist:port info -s"); + $processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedCommand), $this->equalTo(null)) + ->will($this->returnValue(0)); + + $result = $this->perforce->checkServerExists("perforce.does.exist:port", $processExecutor); + $this->assertTrue($result); + } + + public function testCheckServerExistsWithFailure() { + $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); + + $expectedCommand = $this->winCompat("p4 -p perforce.does.not.exist:port info -s"); + $processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($expectedCommand), $this->equalTo(null)) + ->will($this->returnValue("Perforce client error:")); + + $result = $this->perforce->checkServerExists("perforce.does.not.exist:port", $processExecutor); + $this->assertTrue($result); + } + + public static function getComposerJson() { + $composer_json = array( + '{', + '"name": "test/perforce",', + '"description": "Basic project for testing",', + '"minimum-stability": "dev",', + '"autoload": {', + '"psr-0" : {', + '}', + '}', + '}' + ); + + return implode($composer_json); + } + + private function getExpectedClientSpec($withStream) { + $expectedArray = array( + "Client: composer_perforce_TEST_depot", + "\n", + "Update:", + "\n", + "Access:", + "Owner: user", + "\n", + "Description:", + " Created by user from composer.", + "\n", + "Root: path", + "\n", + "Options: noallwrite noclobber nocompress unlocked modtime rmdir", + "\n", + "SubmitOptions: revertunchanged", + "\n", + "LineEnd: local", + "\n" + ); + if ($withStream) { + $expectedArray[] = "Stream:"; + $expectedArray[] = " //depot/branching"; + } + else { + $expectedArray[] = "View: //depot/... //composer_perforce_TEST_depot/depot/..."; + } + + return $expectedArray; + } + + private function winCompat($cmd) { + if (defined('PHP_WINDOWS_VERSION_BUILD')) { + $cmd = str_replace('cd ', 'cd /D ', $cmd); + $cmd = str_replace('composerPath', getcwd() . '/composerPath', $cmd); + + return strtr($cmd, "'", '"'); + } + + return $cmd; + } + +} + diff --git a/tests/Composer/Test/Util/TestingPerforce.php b/tests/Composer/Test/Util/TestingPerforce.php new file mode 100644 index 000000000..dc21e8c33 --- /dev/null +++ b/tests/Composer/Test/Util/TestingPerforce.php @@ -0,0 +1,106 @@ +windows_flag = false; + } + /* + * Override functions + */ + protected function getRandomValue() { + return "TEST"; + } + protected function isWindows(){ + return $this->windows_flag; + } + +// protected function executeCommand($command) { +// $this->previousCommand = $this->lastCommand; +// $this->lastCommand = $command; +// $result = $this->commandReturnValue; +// $this->commandReturnValue = $this->nextCommandReturnValue; +// $this->nextCommandReturnValue = null; +// return $result; +// } + + public function writeP4ClientSpec() { + $spec = fopen(vfsStream::url($this->getP4ClientSpec()), 'w'); + $this->writeClientSpecToFile($spec); + fclose($spec); + } + + /* + * Test Helper functions + */ + public function setDepotType($depotType) { + $this->p4depotType = $depotType; + $this->p4stream = NULL; + } + + /* + * Functions to expose protected methods for testing: + */ + public function setP4User($p4user){ + $this->p4user = $p4user; + } + public function setP4Password($password){ + $this->p4password = $password; + } + + public function testGetClient() { + return $this->getClient(); + } + + public function testGetStream() { + return $this->getStream(); + } + + public function testGetStreamWithoutLabel() { + return $this->getStreamWithoutLabel(); + } + + public function testGetClientSpec() { + return $this->getP4ClientSpec(); + } + + public function testGenerateP4Command($command, $useClient = TRUE) { + return $this->generateP4Command($command, $useClient); + } + + public function testIsLoggedIn() + { + return $this->isLoggedIn(); + } + + public function testIsStream() + { + return $this->isStream(); + } + + public function testGetP4Variable($name) + { + return $this->testGetP4Variable($name); + } + + public function testQueryP4Password($io) + { + return $this->queryP4Password($io); + } +} \ No newline at end of file From 7fdcdb4c54bb22ac76794ba9e4e59831e4cd80cf Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Mon, 12 Aug 2013 13:28:09 -0500 Subject: [PATCH 048/238] Updated to complete functionality in Downloader to handle updates, returning change logs. --- .../Downloader/PerforceDownloader.php | 15 +++++---- src/Composer/Util/Perforce.php | 31 +++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index 5ed241d79..c7ca64ec1 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -22,6 +22,7 @@ use Composer\Util\Perforce; class PerforceDownloader extends VcsDownloader { protected $perforce; + protected $perforceInjected = false; /** * {@inheritDoc} @@ -31,6 +32,7 @@ class PerforceDownloader extends VcsDownloader $ref = $package->getSourceReference(); $label = $package->getPrettyVersion(); + $this->io->write(" Cloning ".$ref); $this->initPerforce($package, $path); $this->perforce->setStream($ref); $this->perforce->queryP4User($this->io); @@ -40,7 +42,7 @@ class PerforceDownloader extends VcsDownloader } private function initPerforce($package, $path){ - if (isset($this->perforce)){ + if ($this->perforceInjected){ return; } $repository = $package->getRepository(); @@ -50,6 +52,7 @@ class PerforceDownloader extends VcsDownloader public function injectPerforce($perforce){ $this->perforce = $perforce; + $this->perforceInjected = true; } private function getRepoConfig(VcsRepository $repository){ @@ -62,7 +65,7 @@ class PerforceDownloader extends VcsDownloader public function doUpdate(PackageInterface $initial, PackageInterface $target, $path) { print("PerforceDownloader:doUpdate\n"); - throw new Exception("Unsupported Operation: PerforceDownloader:doUpdate"); + $this->doDownload($target, $path); } /** @@ -70,8 +73,8 @@ class PerforceDownloader extends VcsDownloader */ public function getLocalChanges($path) { - print("PerforceDownloader:getLocalChanges\n"); - throw new Exception("Unsupported Operation: PerforceDownloader:getLocalChanges"); + print ("Perforce driver does not check for local changes before overriding\n"); + return; } @@ -80,8 +83,8 @@ class PerforceDownloader extends VcsDownloader */ protected function getCommitLogs($fromReference, $toReference, $path) { - print("PerforceDownloader:getCommitLogs\n"); - throw new Exception("Unsupported Operation: PerforceDownloader:getCommitLogs"); + $commitLogs = $this->perforce->getCommitLogs($fromReference, $toReference); + return $commitLogs; } } diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 5b032b71b..7a9e26643 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -437,4 +437,35 @@ class Perforce { return FALSE; } + + protected function getChangeList($reference){ + $index = strpos($reference, "@"); + if ($index === false){ + return; + } + $label = substr($reference, $index); + $command = $this->generateP4Command(" changes -m1 $label"); + $changes = $this->executeCommand($command); + if (strpos($changes, "Change") !== 0){ + return; + } + $fields = explode(" ", $changes); + $changeList = $fields[1]; + return $changeList; + } + public function getCommitLogs($fromReference, $toReference){ + $fromChangeList = $this->getChangeList($fromReference); + if ($fromChangeList == null){ + return; + } + $toChangeList = $this->getChangeList($toReference); + if ($toChangeList == null){ + return; + } + $index = strpos($fromReference, "@"); + $main = substr($fromReference, 0, $index) . "/..."; + $command = $this->generateP4Command("filelog $main@$fromChangeList,$toChangeList"); + $result = $this->executeCommand($command); + return $result; + } } \ No newline at end of file From 997b1b5d46aa69f64b9c9ff2a92ab8bf84d03890 Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Tue, 13 Aug 2013 10:04:47 -0500 Subject: [PATCH 049/238] Replaced changes in RemoteFilesystemTest with changes from main branch. --- .../Test/Util/RemoteFilesystemTest.php | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/tests/Composer/Test/Util/RemoteFilesystemTest.php b/tests/Composer/Test/Util/RemoteFilesystemTest.php index f2950a2da..39a3bb63d 100644 --- a/tests/Composer/Test/Util/RemoteFilesystemTest.php +++ b/tests/Composer/Test/Util/RemoteFilesystemTest.php @@ -21,9 +21,9 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase { $io = $this->getMock('Composer\IO\IOInterface'); $io - ->expects($this->once()) - ->method('hasAuthentication') - ->will($this->returnValue(false)) + ->expects($this->once()) + ->method('hasAuthentication') + ->will($this->returnValue(false)) ; $res = $this->callGetOptionsForUrl($io, array('http://example.org', array())); @@ -42,14 +42,14 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase { $io = $this->getMock('Composer\IO\IOInterface'); $io - ->expects($this->once()) - ->method('hasAuthentication') - ->will($this->returnValue(true)) + ->expects($this->once()) + ->method('hasAuthentication') + ->will($this->returnValue(true)) ; $io - ->expects($this->once()) - ->method('getAuthentication') - ->will($this->returnValue(array('username' => 'login', 'password' => 'password'))) + ->expects($this->once()) + ->method('getAuthentication') + ->will($this->returnValue(array('username' => 'login', 'password' => 'password'))) ; $options = $this->callGetOptionsForUrl($io, array('http://example.org', array())); @@ -67,9 +67,9 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase { $io = $this->getMock('Composer\IO\IOInterface'); $io - ->expects($this->once()) - ->method('hasAuthentication') - ->will($this->returnValue(true)) + ->expects($this->once()) + ->method('hasAuthentication') + ->will($this->returnValue(true)) ; $streamOptions = array('ssl' => array( @@ -84,9 +84,9 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase { $io = $this->getMock('Composer\IO\IOInterface'); $io - ->expects($this->once()) - ->method('hasAuthentication') - ->will($this->returnValue(true)) + ->expects($this->once()) + ->method('hasAuthentication') + ->will($this->returnValue(true)) ; $streamOptions = array('http' => array( @@ -118,8 +118,8 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase { $io = $this->getMock('Composer\IO\IOInterface'); $io - ->expects($this->once()) - ->method('overwrite') + ->expects($this->once()) + ->method('overwrite') ; $fs = new RemoteFilesystem($io); @@ -148,13 +148,18 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase public function testCaptureAuthenticationParamsFromUrl() { $io = $this->getMock('Composer\IO\IOInterface'); - $io - ->expects($this->once()) + $io->expects($this->once()) ->method('setAuthentication') - ; + ->with($this->equalTo('example.com'), $this->equalTo('user'), $this->equalTo('pass')); $fs = new RemoteFilesystem($io); - $fs->getContents('example.com', 'http://user:pass@www.example.com'); + try { + $fs->getContents('example.com', 'http://user:pass@www.example.com/something'); + } catch (\Exception $e) { + $this->assertInstanceOf('Composer\Downloader\TransportException', $e); + $this->assertEquals(404, $e->getCode()); + $this->assertContains('404 Not Found', $e->getMessage()); + } } public function testGetContents() @@ -197,4 +202,4 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase $attr->setAccessible(true); $attr->setValue($object, $value); } -} +} \ No newline at end of file From dd81449998f86bc0028bfd7424fa08ee92c62cbd Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Thu, 15 Aug 2013 12:16:15 -0500 Subject: [PATCH 050/238] Updated to remove vfsStreams (no longer needed by tests) Updated Perforce to cleanup, modified VcsRepository to call cleanup on Driver class Updated tests, perforce constructor to make tests cleaner/easier --- composer.json | 3 +- composer.lock | 97 ++++---- .../Downloader/PerforceDownloader.php | 12 +- .../Repository/Vcs/PerforceDriver.php | 40 ++- src/Composer/Repository/Vcs/VcsDriver.php | 8 + .../Repository/Vcs/VcsDriverInterface.php | 6 + src/Composer/Repository/VcsRepository.php | 1 + src/Composer/Util/Perforce.php | 183 ++++++++------ .../Downloader/PerforceDownloaderTest.php | 3 +- .../Repository/Vcs/PerforceDriverTest.php | 15 +- .../Repository/Vcs/TestingPerforceDriver.php | 26 -- tests/Composer/Test/Util/PerforceTest.php | 232 +++++++++--------- tests/Composer/Test/Util/TestingPerforce.php | 106 -------- 13 files changed, 333 insertions(+), 399 deletions(-) delete mode 100644 tests/Composer/Test/Repository/Vcs/TestingPerforceDriver.php delete mode 100644 tests/Composer/Test/Util/TestingPerforce.php diff --git a/composer.json b/composer.json index 77cc9590f..f0d4ee56e 100644 --- a/composer.json +++ b/composer.json @@ -30,8 +30,7 @@ "symfony/process": "~2.1" }, "require-dev": { - "phpunit/phpunit": "~3.7.10", - "mikey179/vfsStream" : "1.2.*" + "phpunit/phpunit": "~3.7.10" }, "suggest": { "ext-zip": "Enabling the zip extension allows you to unzip archives, and allows gzip compression of all internet traffic", diff --git a/composer.lock b/composer.lock index 5a23476b4..b6ff8ec60 100644 --- a/composer.lock +++ b/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": "6203fdb419c10ffd84f85611fc9eec61", + "hash": "370b764a9317165e8ea7a2e1623e031b", "packages": [ { "name": "justinrainbow/json-schema", @@ -15,7 +15,7 @@ }, "dist": { "type": "zip", - "url": "https://github.com/justinrainbow/json-schema/zipball/v1.1.0", + "url": "https://github.com/justinrainbow/json-schema/archive/v1.1.0.zip", "reference": "v1.1.0", "shasum": "" }, @@ -28,7 +28,37 @@ "JsonSchema": "src/" } }, - "time": "2012-01-02 21:33:17" + "notification-url": "https://packagist.org/downloads/", + "license": [ + "NewBSD" + ], + "authors": [ + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch", + "homepage": "http://wiedler.ch/igor/" + }, + { + "name": "Bruno Prieto Reis", + "email": "bruno.p.reis@gmail.com" + }, + { + "name": "Justin Rainbow", + "email": "justin.rainbow@gmail.com" + }, + { + "name": "Robert Schönthal", + "email": "seroscho@googlemail.com", + "homepage": "http://digitalkaoz.net" + } + ], + "description": "A library to validate a json schema.", + "homepage": "https://github.com/justinrainbow/json-schema", + "keywords": [ + "json", + "schema" + ], + "time": "2012-01-03 00:33:17" }, { "name": "seld/jsonlint", @@ -79,17 +109,17 @@ }, { "name": "symfony/console", - "version": "dev-master", + "version": "v2.3.3", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "872a494b88fba2f62be85e0bc8441e7946bb6ba6" + "reference": "v2.3.3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/872a494b88fba2f62be85e0bc8441e7946bb6ba6", - "reference": "872a494b88fba2f62be85e0bc8441e7946bb6ba6", + "url": "https://api.github.com/repos/symfony/Console/zipball/v2.3.3", + "reference": "v2.3.3", "shasum": "" }, "require": { @@ -104,7 +134,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.3-dev" } }, "autoload": { @@ -128,7 +158,7 @@ ], "description": "Symfony Console Component", "homepage": "http://symfony.com", - "time": "2013-08-09 06:00:31" + "time": "2013-07-21 12:12:18" }, { "name": "symfony/finder", @@ -179,17 +209,17 @@ }, { "name": "symfony/process", - "version": "dev-master", + "version": "v2.3.3", "target-dir": "Symfony/Component/Process", "source": { "type": "git", "url": "https://github.com/symfony/Process.git", - "reference": "723fe405fcc878ae75469babcb9507d292797ece" + "reference": "v2.3.3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/723fe405fcc878ae75469babcb9507d292797ece", - "reference": "723fe405fcc878ae75469babcb9507d292797ece", + "url": "https://api.github.com/repos/symfony/Process/zipball/v2.3.3", + "reference": "v2.3.3", "shasum": "" }, "require": { @@ -198,7 +228,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.3-dev" } }, "autoload": { @@ -222,40 +252,10 @@ ], "description": "Symfony Process Component", "homepage": "http://symfony.com", - "time": "2013-08-09 07:03:52" + "time": "2013-08-02 21:51:01" } ], "packages-dev": [ - { - "name": "mikey179/vfsStream", - "version": "v1.2.0", - "source": { - "type": "git", - "url": "https://github.com/mikey179/vfsStream.git", - "reference": "v1.2.0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mikey179/vfsStream/zipball/v1.2.0", - "reference": "v1.2.0", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "autoload": { - "psr-0": { - "org\\bovigo\\vfs\\": "src/main/php" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD" - ], - "homepage": "http://vfs.bovigo.org/", - "time": "2013-04-01 10:41:02" - }, { "name": "phpunit/php-code-coverage", "version": "1.2.12", @@ -675,10 +675,9 @@ ], "minimum-stability": "stable", - "stability-flags": { - "symfony/console": 20, - "symfony/process": 20 - }, + "stability-flags": [ + + ], "platform": { "php": ">=5.3.2" }, diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index c7ca64ec1..5cede4ff6 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -6,10 +6,14 @@ * (c) Nils Adermann * Jordi Boggiano * + * Contributor: Matt Whittom + * Date: 7/17/13 + * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ + namespace Composer\Downloader; use Composer\Package\PackageInterface; @@ -17,7 +21,7 @@ use Composer\Repository\VcsRepository; use Composer\Util\Perforce; /** - * @author Jordi Boggiano + * @author Matt Whittom */ class PerforceDownloader extends VcsDownloader { @@ -39,6 +43,7 @@ class PerforceDownloader extends VcsDownloader $this->perforce->writeP4ClientSpec(); $this->perforce->connectClient(); $this->perforce->syncCodeBase($label); + $this->perforce->cleanupClientSpec(); } private function initPerforce($package, $path){ @@ -47,7 +52,7 @@ class PerforceDownloader extends VcsDownloader } $repository = $package->getRepository(); $repoConfig = $this->getRepoConfig($repository); - $this->perforce = new Perforce($repoConfig, $package->getSourceUrl(), $path); + $this->perforce = Perforce::createPerforce($repoConfig, $package->getSourceUrl(), $path); } public function injectPerforce($perforce){ @@ -64,14 +69,13 @@ class PerforceDownloader extends VcsDownloader */ public function doUpdate(PackageInterface $initial, PackageInterface $target, $path) { - print("PerforceDownloader:doUpdate\n"); $this->doDownload($target, $path); } /** * {@inheritDoc} */ - public function getLocalChanges($path) + public function getLocalChanges(PackageInterface $package, $path) { print ("Perforce driver does not check for local changes before overriding\n"); return; diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 0f930a52b..7068ebb3e 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -6,13 +6,14 @@ * (c) Nils Adermann * Jordi Boggiano * - * Contributor: matt-whittom + * Contributor: Matt Whittom * Date: 7/17/13 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ + namespace Composer\Repository\Vcs; use Composer\IO\IOInterface; @@ -21,12 +22,14 @@ use Composer\Util\Filesystem; use Composer\Util\Perforce; /** - * @author matt-whittom <> + * @author Matt Whittom */ class PerforceDriver extends VcsDriver { protected $depot; protected $branch; protected $perforce; + protected $composer_info; + protected $composer_info_identifier; /** * {@inheritDoc} @@ -54,7 +57,7 @@ class PerforceDriver extends VcsDriver { } $repoDir = $this->config->get('cache-vcs-dir') . "/$this->depot"; - $this->perforce = new Perforce($this->repoConfig, $this->getUrl(), $repoDir, $this->process); + $this->perforce = Perforce::createPerforce($this->repoConfig, $this->getUrl(), $repoDir, $this->process); } public function injectPerforce(Perforce $perforce) { @@ -66,6 +69,12 @@ class PerforceDriver extends VcsDriver { * {@inheritDoc} */ public function getComposerInformation($identifier) { + if (isset($this->composer_info_identifier)){ + if (strcmp($identifier, $this->composer_info_identifier) === 0 ) + { + return $this->composer_info; + } + } $composer_info = $this->perforce->getComposerInformation($identifier); return $composer_info; @@ -127,9 +136,12 @@ class PerforceDriver extends VcsDriver { * {@inheritDoc} */ public function hasComposerFile($identifier) { - $composer_info = $this->perforce->getComposerInformation("//$this->depot/$identifier"); - $result = strlen(trim($composer_info)) > 0; - + $this->composer_info = $this->perforce->getComposerInformation("//$this->depot/$identifier"); + $this->composer_info_identifier = $identifier; + $result = false; + if (isset($this->composer_info)){ + $result = count($this->composer_info) > 0; + } return $result; } @@ -146,4 +158,20 @@ class PerforceDriver extends VcsDriver { public static function supports(IOInterface $io, $url, $deep = FALSE) { return Perforce::checkServerExists($url, new ProcessExecutor); } + + /** + * {@inheritDoc} + */ + public function cleanup(){ + $this->perforce->cleanupClientSpec(); + $this->perforce = null; + } + + public function getDepot(){ + return $this->depot; + } + + public function getBranch(){ + return $this->branch; + } } diff --git a/src/Composer/Repository/Vcs/VcsDriver.php b/src/Composer/Repository/Vcs/VcsDriver.php index f6d428802..1a42e0927 100644 --- a/src/Composer/Repository/Vcs/VcsDriver.php +++ b/src/Composer/Repository/Vcs/VcsDriver.php @@ -105,4 +105,12 @@ abstract class VcsDriver implements VcsDriverInterface { return (bool) preg_match('{^(file://|/|[a-z]:[\\\\/])}i', $url); } + + /** + * {@inheritDoc} + */ + public function cleanup() + { + return; + } } diff --git a/src/Composer/Repository/Vcs/VcsDriverInterface.php b/src/Composer/Repository/Vcs/VcsDriverInterface.php index 44486f007..b29841b68 100644 --- a/src/Composer/Repository/Vcs/VcsDriverInterface.php +++ b/src/Composer/Repository/Vcs/VcsDriverInterface.php @@ -81,6 +81,12 @@ interface VcsDriverInterface */ public function hasComposerFile($identifier); + /** + * Performs any cleanup necessary as the driver is not longer needed + * + */ + public function cleanup(); + /** * Checks if this driver can handle a given url * diff --git a/src/Composer/Repository/VcsRepository.php b/src/Composer/Repository/VcsRepository.php index 2b876bc22..701db33bb 100644 --- a/src/Composer/Repository/VcsRepository.php +++ b/src/Composer/Repository/VcsRepository.php @@ -253,6 +253,7 @@ class VcsRepository extends ArrayRepository continue; } } + $driver->cleanup(); if (!$verbose) { $this->io->overwrite('', false); diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 7a9e26643..6acee208f 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -1,60 +1,91 @@ + * Jordi Boggiano + * + * Contributor: Matt Whittom + * Date: 7/17/13 + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ + namespace Composer\Util; use Composer\IO\IOInterface; - +/** + * @author Matt Whittom + */ class Perforce { protected $path; - protected $p4client; - protected $p4user; - protected $p4password; - protected $p4port; - protected $p4stream; - protected $p4clientSpec; - protected $p4depotType; - protected $p4branch; + protected $p4Depot; + protected $p4Client; + protected $p4User; + protected $p4Password; + protected $p4Port; + protected $p4Stream; + protected $p4ClientSpec; + protected $p4DepotType; + protected $p4Branch; protected $process; + protected $unique_perforce_client_name; + protected $windowsFlag; - public function __construct($repoConfig, $port, $path, ProcessExecutor $process = NULL) { - $this->p4port = $port; + + public static function createPerforce($repoConfig, $port, $path, ProcessExecutor $process = NULL) { + if (!isset($process)){ + $process = new ProcessExecutor; + } + $isWindows = defined('PHP_WINDOWS_VERSION_BUILD'); + if (isset($repoConfig['unique_perforce_client_name'])){ + $unique_perforce_client_name = $repoConfig['unique_perforce_client_name']; + } else { + $unique_perforce_client_name = gethostname() . "_" . time(); + $repoConfig['unique_perforce_client_name'] = $unique_perforce_client_name; + } + + $perforce = new Perforce($repoConfig, $port, $path, $process, $isWindows, $unique_perforce_client_name); + return $perforce; + } + + public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows, $unique_perforce_client_name) { + $this->windowsFlag = $isWindows; + $this->unique_perforce_client_name = $unique_perforce_client_name; + $this->p4Port = $port; $this->path = $path; - $this->process = $process ? : new ProcessExecutor; $fs = new Filesystem(); $fs->ensureDirectoryExists($path); + $this->process = $process; if (isset($repoConfig['depot'])) { - $this->p4depot = $repoConfig['depot']; + $this->p4Depot = $repoConfig['depot']; } if (isset($repoConfig['branch'])) { - $this->p4branch = $repoConfig['branch']; + $this->p4Branch = $repoConfig['branch']; } if (isset($repoConfig['p4user'])) { - $this->p4user = $repoConfig['p4user']; + $this->p4User = $repoConfig['p4user']; } else { - $this->p4user = $this->getP4variable("P4USER"); + $this->p4User = $this->getP4variable("P4USER"); } if (isset($repoConfig['p4password'])) { - $this->p4password = $repoConfig['p4password']; + $this->p4Password = $repoConfig['p4password']; } } - protected function getRandomValue() { - return mt_rand(1000, 9999); - } - - protected function isWindows(){ - return defined('PHP_WINDOWS_VERSION_BUILD'); + public function cleanupClientSpec(){ + $client = $this->getClient(); + $command = "p4 client -d $client"; + $this->executeCommand($command); + $clientSpec = $this->getP4ClientSpec(); + $fileSystem = new FileSystem($this->process); + $fileSystem->remove($clientSpec); } protected function executeCommand($command) { @@ -64,14 +95,13 @@ class Perforce { return $result; } - protected function getClient() { - if (!isset($this->p4client)) { - $random_value = $this->getRandomValue(); + public function getClient() { + if (!isset($this->p4Client)) { $clean_stream_name = str_replace("@", "", str_replace("/", "_", str_replace("//", "", $this->getStream()))); - $this->p4client = "composer_perforce_" . $random_value . "_" . $clean_stream_name; + $this->p4Client = "composer_perforce_" . $this->unique_perforce_client_name . "_" . $clean_stream_name; } - return $this->p4client; + return $this->p4Client; } protected function getPath() { @@ -79,28 +109,31 @@ class Perforce { } protected function getPort() { - return $this->p4port; + return $this->p4Port; } - protected function isStream() { - return (strcmp($this->p4depotType, "stream") === 0); + public function setStream($stream) { + $this->p4Stream = $stream; + $this->p4DepotType = "stream"; } - protected function getStream() { - if (!isset($this->p4stream)) { + public function isStream() { + return (strcmp($this->p4DepotType, "stream") === 0); + } + + public function getStream() { + if (!isset($this->p4Stream)) { if ($this->isStream()) { - $this->p4stream = "//$this->p4depot/$this->p4branch"; + $this->p4Stream = "//$this->p4Depot/$this->p4Branch"; } else { - $this->p4stream = "//$this->p4depot"; + $this->p4Stream = "//$this->p4Depot"; } } - - return $this->p4stream; + return $this->p4Stream; } - protected function getStreamWithoutLabel() { - $stream = $this->getStream(); + public function getStreamWithoutLabel($stream) { $index = strpos($stream, "@"); if ($index === FALSE) { return $stream; @@ -109,37 +142,37 @@ class Perforce { return substr($stream, 0, $index); } - protected function getP4ClientSpec() { + public function getP4ClientSpec() { $p4clientSpec = $this->path . "/" . $this->getClient() . ".p4.spec"; return $p4clientSpec; } public function getUser() { - return $this->p4user; + return $this->p4User; } public function queryP4User(IOInterface $io) { $this->getUser(); - if (strlen($this->p4user) > 0) { + if (strlen($this->p4User) > 0) { return; } - $this->p4user = $this->getP4variable("P4USER"); - if (strlen($this->p4user) > 0) { + $this->p4User = $this->getP4variable("P4USER"); + if (strlen($this->p4User) > 0) { return; } - $this->p4user = $io->ask("Enter P4 User:"); - if ($this->isWindows()) { - $command = "p4 set P4USER=$this->p4user"; + $this->p4User = $io->ask("Enter P4 User:"); + if ($this->windowsFlag) { + $command = "p4 set P4USER=$this->p4User"; } else { - $command = "export P4USER=$this->p4user"; + $command = "export P4USER=$this->p4User"; } $result = $this->executeCommand($command); } protected function getP4variable($name) { - if ($this->isWindows()) { + if ($this->windowsFlag) { $command = "p4 set"; $result = $this->executeCommand($command); $resArray = explode("\n", $result); @@ -167,20 +200,20 @@ class Perforce { } } - protected function queryP4Password(IOInterface $io) { - if (isset($this->p4password)) { - return $this->p4password; + public function queryP4Password(IOInterface $io) { + if (isset($this->p4Password)) { + return $this->p4Password; } $password = $this->getP4variable("P4PASSWD"); if (strlen($password) <= 0) { $password = $io->askAndHideAnswer("Enter password for Perforce user " . $this->getUser() . ": "); } - $this->p4password = $password; + $this->p4Password = $password; return $password; } - protected function generateP4Command($command, $useClient = TRUE) { + public function generateP4Command($command, $useClient = TRUE) { $p4Command = "p4 "; $p4Command = $p4Command . "-u " . $this->getUser() . " "; if ($useClient) { @@ -192,22 +225,16 @@ class Perforce { return $p4Command; } - protected function isLoggedIn() { + public function isLoggedIn() { $command = $this->generateP4Command("login -s", FALSE); $result = trim($this->executeCommand($command)); $index = strpos($result, $this->getUser()); if ($index === FALSE) { return FALSE; } - return TRUE; } - public function setStream($stream) { - $this->p4stream = $stream; - $this->p4depotType = "stream"; - } - public function connectClient() { $p4CreateClientCommand = $this->generateP4Command("client -i < " . $this->getP4ClientSpec()); $this->executeCommand($p4CreateClientCommand); @@ -230,7 +257,7 @@ class Perforce { chdir($prevDir); } - protected function writeClientSpecToFile($spec) { + public function writeClientSpecToFile($spec) { fwrite($spec, "Client: " . $this->getClient() . "\n\n"); fwrite($spec, "Update: " . date("Y/m/d H:i:s") . "\n\n"); fwrite($spec, "Access: " . date("Y/m/d H:i:s") . "\n"); @@ -243,7 +270,7 @@ class Perforce { fwrite($spec, "LineEnd: local\n\n"); if ($this->isStream()) { fwrite($spec, "Stream:\n"); - fwrite($spec, " " . $this->getStreamWithoutLabel() . "\n"); + fwrite($spec, " " . $this->getStreamWithoutLabel($this->p4Stream) . "\n"); } else { fwrite( @@ -255,7 +282,8 @@ class Perforce { } public function writeP4ClientSpec() { - $spec = fopen($this->getP4ClientSpec(), 'w'); + $clientSpec = $this->getP4ClientSpec(); + $spec = fopen($clientSpec, 'w'); try { $this->writeClientSpecToFile($spec); } catch (Exception $e) { @@ -308,7 +336,7 @@ class Perforce { $this->queryP4User($io); if (!$this->isLoggedIn()) { $password = $this->queryP4Password($io); - if ($this->isWindows()) { + if ($this->windowsFlag) { $this->windowsLogin($password); } else { @@ -382,12 +410,11 @@ class Perforce { public function getBranches() { $possible_branches = array(); if (!$this->isStream()) { - $possible_branches[$this->p4branch] = $this->getStream(); + $possible_branches[$this->p4Branch] = $this->getStream(); } else { - $command = $this->generateP4Command("streams //$this->p4depot/..."); - $result = ""; - $this->process->execute($command, $result); + $command = $this->generateP4Command("streams //$this->p4Depot/..."); + $result = $this->executeCommand($command); $resArray = explode("\n", $result); foreach ($resArray as $line) { $resBits = explode(" ", $line); @@ -398,7 +425,7 @@ class Perforce { } } $branches = array(); - $branches['master'] = $possible_branches[$this->p4branch]; + $branches['master'] = $possible_branches[$this->p4Branch]; return $branches; } @@ -427,8 +454,8 @@ class Perforce { $index = strpos($line, "Depot"); if (!($index === FALSE)) { $fields = explode(" ", $line); - if (strcmp($this->p4depot, $fields[1]) === 0) { - $this->p4depotType = $fields[3]; + if (strcmp($this->p4Depot, $fields[1]) === 0) { + $this->p4DepotType = $fields[3]; return $this->isStream(); } diff --git a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php index 66ed81776..634cc5f18 100644 --- a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php +++ b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php @@ -60,7 +60,8 @@ class PerforceDownloaderTest extends \PHPUnit_Framework_TestCase { $repoConfig = array("depot"=>"TEST_DEPOT", "branch"=>"TEST_BRANCH", "p4user"=>"TEST_USER"); $port = "TEST_PORT"; $path = "TEST_PATH"; - $perforce = $this->getMock('Composer\Util\Perforce', array('setStream', 'queryP4User', 'writeP4ClientSpec', 'connectClient', 'syncCodeBase'), array($repoConfig, $port, $path)); + $process = $this->getmock('Composer\Util\ProcessExecutor'); + $perforce = $this->getMock('Composer\Util\Perforce', array('setStream', 'queryP4User', 'writeP4ClientSpec', 'connectClient', 'syncCodeBase'), array($repoConfig, $port, $path, $process, true, "TEST")); $ref = "SOURCE_REF"; $label = "LABEL"; $perforce->expects($this->at(0)) diff --git a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php index db1485836..ed14b077e 100644 --- a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php @@ -48,9 +48,6 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase { $fs->removeDirectory($this->testPath); } - //Test: - //hasComposerFile - public function testInitializeCapturesVariablesFromRepoConfig() { $this->setUp(); $repo_config = array( @@ -58,8 +55,9 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase { 'depot' => 'TEST_DEPOT_CONFIG', 'branch' => 'TEST_BRANCH_CONFIG' ); - $driver = new TestingPerforceDriver($repo_config, $this->io, $this->config, $this->process, $this->remoteFileSystem); - $arguments = array(array('depot'=>'TEST_DEPOT', 'branch'=>'TEST_BRANCH'), 'port'=>'TEST_PORT', 'path'=>$this->testPath); + $driver = new PerforceDriver($repo_config, $this->io, $this->config, $this->process, $this->remoteFileSystem); + $process = $this->getMock('Composer\Util\ProcessExecutor'); + $arguments = array(array('depot'=>'TEST_DEPOT', 'branch'=>'TEST_BRANCH'), 'port'=>'TEST_PORT', 'path'=>$this->testPath, $process, true, "TEST"); $perforce = $this->getMock('Composer\Util\Perforce', null, $arguments); $driver->injectPerforce($perforce); $driver->initialize(); @@ -75,7 +73,7 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase { 'depot' => 'TEST_DEPOT_CONFIG', 'branch' => 'TEST_BRANCH_CONFIG' ); - $driver = new TestingPerforceDriver($repo_config, $this->io, $this->config, $this->process, $this->remoteFileSystem); + $driver = new PerforceDriver($repo_config, $this->io, $this->config, $this->process, $this->remoteFileSystem); $perforce = $this->getMockBuilder('Composer\Util\Perforce')->disableOriginalConstructor()->getMock(); $perforce->expects($this->at(0)) ->method('p4Login') @@ -99,8 +97,9 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase { 'depot' => 'TEST_DEPOT_CONFIG', 'branch' => 'TEST_BRANCH_CONFIG' ); - $driver = new TestingPerforceDriver($repo_config, $this->io, $this->config, $this->process, $this->remoteFileSystem); - $arguments = array(array('depot'=>'TEST_DEPOT', 'branch'=>'TEST_BRANCH'), 'port'=>'TEST_PORT', 'path'=>$this->testPath); + $driver = new PerforceDriver($repo_config, $this->io, $this->config, $this->process, $this->remoteFileSystem); + $process = $this->getMock('Composer\Util\ProcessExecutor'); + $arguments = array(array('depot'=>'TEST_DEPOT', 'branch'=>'TEST_BRANCH'), 'port'=>'TEST_PORT', 'path'=>$this->testPath, $process, true, "TEST"); $perforce = $this->getMock('Composer\Util\Perforce', array('getComposerInformation'), $arguments); $perforce->expects($this->at(0)) ->method('getComposerInformation') diff --git a/tests/Composer/Test/Repository/Vcs/TestingPerforceDriver.php b/tests/Composer/Test/Repository/Vcs/TestingPerforceDriver.php deleted file mode 100644 index 574c69377..000000000 --- a/tests/Composer/Test/Repository/Vcs/TestingPerforceDriver.php +++ /dev/null @@ -1,26 +0,0 @@ -depot; - } - public function getBranch(){ - return $this->branch; - } - -} \ No newline at end of file diff --git a/tests/Composer/Test/Util/PerforceTest.php b/tests/Composer/Test/Util/PerforceTest.php index 8a653394f..62df75f69 100644 --- a/tests/Composer/Test/Util/PerforceTest.php +++ b/tests/Composer/Test/Util/PerforceTest.php @@ -1,21 +1,26 @@ + * Jordi Boggiano + * + * Contributor: Matt Whittom + * Date: 7/17/13 + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ + namespace Composer\Test\Util; -use Composer\Test\Util\TestingPerforce; +use Composer\Util\Perforce; use Composer\Util\ProcessExecutor; -use org\bovigo\vfs\vfsStreamWrapper; -use org\bovigo\vfs\vfsStreamDirectory; -use org\bovigo\vfs\vfsStream; - +/** + * @author Matt Whittom + */ class PerforceTest extends \PHPUnit_Framework_TestCase { protected $perforce; @@ -24,54 +29,59 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { public function setUp() { $this->processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); $repoConfig = array("depot"=>"depot", "branch"=>"branch", "p4user"=>"user"); - $this->perforce = new TestingPerforce($repoConfig, "port", "path", $this->processExecutor); + $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, true, "TEST"); } public function testGetClientWithoutStream() { - $client = $this->perforce->testGetClient(); + $client = $this->perforce->getClient(); + $hostname = gethostname(); + $timestamp = time(); + $expected = "composer_perforce_TEST_depot"; $this->assertEquals($expected, $client); } public function testGetClientFromStream() { - $this->perforce->setDepotType("stream"); - $client = $this->perforce->testGetClient(); + $this->setPerforceToStream(); + + $client = $this->perforce->getClient(); $expected = "composer_perforce_TEST_depot_branch"; $this->assertEquals($expected, $client); } public function testGetStreamWithoutStream() { - $stream = $this->perforce->testGetStream(); + $stream = $this->perforce->getStream(); $this->assertEquals("//depot", $stream); } public function testGetStreamWithStream() { - $this->perforce->setDepotType("stream"); - $stream = $this->perforce->testGetStream(); + $this->setPerforceToStream(); + + $stream = $this->perforce->getStream(); $this->assertEquals("//depot/branch", $stream); } - public function testGetStreamWithoutLabel() { - $stream = $this->perforce->testGetStreamWithoutLabel(); - $this->assertEquals("//depot", $stream); - $this->perforce->setDepotType("stream"); - $stream = $this->perforce->testGetStreamWithoutLabel(); + + public function testGetStreamWithoutLabelWithStreamWithoutLabel(){ + $stream = $this->perforce->getStreamWithoutLabel("//depot/branch"); $this->assertEquals("//depot/branch", $stream); - $this->perforce->setStream("//depot/branching@label"); - $stream = $this->perforce->testGetStreamWithoutLabel(); + } + + public function testGetStreamWithoutLabelWithStreamWithLabel(){ + $stream = $this->perforce->getStreamWithoutLabel("//depot/branching@label"); $this->assertEquals("//depot/branching", $stream); } public function testGetClientSpec() { - $clientSpec = $this->perforce->testGetClientSpec(); + $clientSpec = $this->perforce->getP4ClientSpec(); $expected = "path/composer_perforce_TEST_depot.p4.spec"; $this->assertEquals($expected, $clientSpec); } public function testGenerateP4Command() { $command = "do something"; - $p4Command = $this->perforce->testGenerateP4Command($command); + $p4Command = $this->perforce->generateP4Command($command); $expected = "p4 -u user -c composer_perforce_TEST_depot -p port do something"; $this->assertEquals($expected, $p4Command); } @@ -79,13 +89,16 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { public function testQueryP4UserWithUserAlreadySet(){ $io = $this->getMock('Composer\IO\IOInterface'); - $this->perforce->setP4User("TEST_USER"); + $repoConfig = array("depot"=>"depot", "branch"=>"branch", "p4user"=>"TEST_USER"); + $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, true, "TEST"); + $this->perforce->queryP4user($io); $this->assertEquals("TEST_USER", $this->perforce->getUser()); } public function testQueryP4UserWithUserSetInP4VariablesWithWindowsOS(){ - $this->perforce->windows_flag = true; + $repoConfig = array("depot"=>"depot", "branch"=>"branch"); + $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, true, "TEST"); $io = $this->getMock('Composer\IO\IOInterface'); $expectedCommand = "p4 set"; @@ -94,13 +107,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { ->with($this->equalTo($expectedCommand)) ->will($this->returnCallback(function($command, &$output) {$output = "P4USER=TEST_P4VARIABLE_USER\n"; return true;})); - $this->perforce->setP4User(null); $this->perforce->queryP4user($io); $this->assertEquals("TEST_P4VARIABLE_USER", $this->perforce->getUser()); } public function testQueryP4UserWithUserSetInP4VariablesNotWindowsOS(){ - $this->perforce->windows_flag = false; + $repoConfig = array("depot"=>"depot", "branch"=>"branch"); + $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, false, "TEST"); $io = $this->getMock('Composer\IO\IOInterface'); $expectedCommand = 'echo $P4USER'; @@ -109,12 +122,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { ->with($this->equalTo($expectedCommand)) ->will($this->returnCallback(function($command, &$output) {$output = "TEST_P4VARIABLE_USER\n"; return true;})); - $this->perforce->setP4User(null); $this->perforce->queryP4user($io); $this->assertEquals("TEST_P4VARIABLE_USER", $this->perforce->getUser()); } public function testQueryP4UserQueriesForUser(){ + $repoConfig = array("depot"=>"depot", "branch"=>"branch"); + $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, false, "TEST"); $io = $this->getMock('Composer\IO\IOInterface'); $expectedQuestion = "Enter P4 User:"; $io->expects($this->at(0)) @@ -122,13 +136,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { ->with($this->equalTo($expectedQuestion)) ->will($this->returnValue("TEST_QUERY_USER")); - $this->perforce->setP4User(null); $this->perforce->queryP4user($io); $this->assertEquals("TEST_QUERY_USER", $this->perforce->getUser()); } public function testQueryP4UserStoresResponseToQueryForUserWithWindows(){ - $this->perforce->windows_flag = true; + $repoConfig = array("depot"=>"depot", "branch"=>"branch"); + $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, true, "TEST"); $io = $this->getMock('Composer\IO\IOInterface'); $expectedQuestion = "Enter P4 User:"; @@ -142,12 +156,12 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { ->with($this->equalTo($expectedCommand)) ->will($this->returnValue(0)); - $this->perforce->setP4User(null); $this->perforce->queryP4user($io); } public function testQueryP4UserStoresResponseToQueryForUserWithoutWindows(){ - $this->perforce->windows_flag = false; + $repoConfig = array("depot"=>"depot", "branch"=>"branch"); + $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, false, "TEST"); $io = $this->getMock('Composer\IO\IOInterface'); $expectedQuestion = "Enter P4 User:"; @@ -161,35 +175,34 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { ->with($this->equalTo($expectedCommand)) ->will($this->returnValue(0)); - $this->perforce->setP4User(null); $this->perforce->queryP4user($io); } public function testQueryP4PasswordWithPasswordAlreadySet(){ + $repoConfig = array("depot"=>"depot", "branch"=>"branch", "p4user"=>"user", "p4password"=>"TEST_PASSWORD"); + $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, false, "TEST"); $io = $this->getMock('Composer\IO\IOInterface'); - $this->perforce->setP4Password("TEST_PASSWORD"); - $password = $this->perforce->testQueryP4Password($io); + $password = $this->perforce->queryP4Password($io); $this->assertEquals("TEST_PASSWORD", $password); } public function testQueryP4PasswordWithPasswordSetInP4VariablesWithWindowsOS(){ - $this->perforce->windows_flag = true; - $io = $this->getMock('Composer\IO\IOInterface'); + $expectedCommand = "p4 set"; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnCallback(function($command, &$output) {$output = "P4PASSWD=TEST_P4VARIABLE_PASSWORD\n"; return true;})); - $this->perforce->setP4Password(null); - $password = $this->perforce->testQueryP4Password($io); + $password = $this->perforce->queryP4Password($io); $this->assertEquals("TEST_P4VARIABLE_PASSWORD", $password); } public function testQueryP4PasswordWithPasswordSetInP4VariablesNotWindowsOS(){ - $this->perforce->windows_flag = false; + $repoConfig = array("depot"=>"depot", "branch"=>"branch", "p4user"=>"user"); + $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, false, "TEST"); $io = $this->getMock('Composer\IO\IOInterface'); $expectedCommand = 'echo $P4PASSWD'; @@ -198,8 +211,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { ->with($this->equalTo($expectedCommand)) ->will($this->returnCallback(function($command, &$output) {$output = "TEST_P4VARIABLE_PASSWORD\n"; return true;})); - $this->perforce->setP4Password(null); - $password = $this->perforce->testQueryP4Password($io); + $password = $this->perforce->queryP4Password($io); $this->assertEquals("TEST_P4VARIABLE_PASSWORD", $password); } @@ -211,62 +223,60 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { ->with($this->equalTo($expectedQuestion)) ->will($this->returnValue("TEST_QUERY_PASSWORD")); - $this->perforce->setP4Password(null); - $password = $this->perforce->testQueryP4Password($io); + $password = $this->perforce->queryP4Password($io); $this->assertEquals("TEST_QUERY_PASSWORD", $password); } public function testWriteP4ClientSpecWithoutStream() { - vfsStreamWrapper::register(); - VfsStreamWrapper::setRoot(new vfsStreamDirectory("path")); - $clientSpec = $this->perforce->testGetClientSpec(); - $this->perforce->writeP4ClientSpec(); - $spec = fopen(vfsStream::url($clientSpec), 'r'); + $stream = fopen("php://memory", 'w+'); + $this->perforce->writeClientSpecToFile($stream); + + rewind($stream); $expectedArray = $this->getExpectedClientSpec(FALSE); try { foreach ($expectedArray as $expected) { - $this->assertStringStartsWith($expected, fgets($spec)); + $this->assertStringStartsWith($expected, fgets($stream)); } - $this->assertFalse(fgets($spec)); + $this->assertFalse(fgets($stream)); } catch (Exception $e) { - fclose($spec); + fclose($stream); throw $e; } - fclose($spec); + fclose($stream); } public function testWriteP4ClientSpecWithStream() { - vfsStreamWrapper::register(); - VfsStreamWrapper::setRoot(new vfsStreamDirectory("path")); - $this->perforce->setStream("//depot/branching@label"); - $clientSpec = $this->perforce->testGetClientSpec(); - $this->perforce->writeP4ClientSpec(); - $spec = fopen(vfsStream::url($clientSpec), 'r'); + $this->setPerforceToStream(); + $stream = fopen("php://memory", 'w+'); + + $this->perforce->writeClientSpecToFile($stream); + rewind($stream); + $expectedArray = $this->getExpectedClientSpec(TRUE); try { foreach ($expectedArray as $expected) { - $this->assertStringStartsWith($expected, fgets($spec)); + $this->assertStringStartsWith($expected, fgets($stream)); } - $this->assertFalse(fgets($spec)); + $this->assertFalse(fgets($stream)); } catch (Exception $e) { - fclose($spec); + fclose($stream); throw $e; } - fclose($spec); + fclose($stream); } public function testIsLoggedIn() { - $expectedCommand = $this->winCompat("p4 -u user -p port login -s"); + $expectedCommand = "p4 -u user -p port login -s"; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand), $this->equalTo(null)) ->will($this->returnValue(0)); - $this->perforce->testIsLoggedIn(); + $this->perforce->isLoggedIn(); } public function testConnectClient() { - $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot -p port client -i < path/composer_perforce_TEST_depot.p4.spec"); + $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot -p port client -i < path/composer_perforce_TEST_depot.p4.spec"; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand), $this->equalTo(null)) @@ -276,33 +286,25 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { } public function testGetBranchesWithStream() { - $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot_branchlabel -p port streams //depot/..."); + $this->setPerforceToStream(); + + $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot_branch -p port streams //depot/..."; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnCallback(function($command, &$output) {$output = "Stream //depot/branch mainline none 'branch'\n"; return true;})); - $this->perforce->setStream("//depot/branch@label"); $branches = $this->perforce->getBranches(); $this->assertEquals("//depot/branch", $branches['master']); } public function testGetBranchesWithoutStream() { - $expectedCommand = $this->winCompat("p4 -u user -p port depots"); - $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will($this->returnCallback(function($command, &$output) {$output = "Depot depot 2013/01/28 local /path/to/depots/depot/... 'depot project'\n"; return true;})); - - $result = $this->perforce->checkStream("depot"); - $this->assertFalse($result); - $branches = $this->perforce->getBranches(); $this->assertEquals("//depot", $branches['master']); } public function testGetTagsWithoutStream() { - $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot -p port labels"); + $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot -p port labels"; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) @@ -314,36 +316,35 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { } public function testGetTagsWithStream() { - $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot_branch -p port labels"); + $this->setPerforceToStream(); + + $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot_branch -p port labels"; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnCallback(function($command, &$output) {$output = "Label 0.0.1 2013/07/31 'First Label!'\nLabel 0.0.2 2013/08/01 'Second Label!'\n"; return true;})); - $this->perforce->setStream("//depot/branch"); $tags = $this->perforce->getTags(); $this->assertEquals("//depot/branch@0.0.1", $tags['0.0.1']); $this->assertEquals("//depot/branch@0.0.2", $tags['0.0.2']); } public function testCheckStreamWithoutStream() { - $this->perforce->commandReturnValue = "Depot depot 2013/01/28 local /path/to/depots/depot/... 'depot project'"; $result = $this->perforce->checkStream("depot"); $this->assertFalse($result); - $this->assertFalse($this->perforce->testIsStream()); + $this->assertFalse($this->perforce->isStream()); } public function testCheckStreamWithStream() { - $line1 = "Depot depot 2013/01/28 branch /path/to/depots/depot/... 'depot project'\n"; - $line2 = "Depot depot 2013/01/28 development /path/to/depots/depot/... 'depot project'\n"; - $this->perforce->commandReturnValue = $line1 . $line2; + $this->processExecutor->expects($this->any())->method('execute') + ->will($this->returnCallback(function($command, &$output) {$output = "Depot depot 2013/06/25 stream /p4/1/depots/depot/... 'Created by Me'"; return true;})); $result = $this->perforce->checkStream("depot"); - $this->assertFalse($result); - $this->assertFalse($this->perforce->testIsStream()); + $this->assertTrue($result); + $this->assertTrue($this->perforce->isStream()); } public function testGetComposerInformationWithoutLabelWithoutStream() { - $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot -p port print //depot/composer.json"); + $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot -p port print //depot/composer.json"; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) @@ -360,13 +361,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { } public function testGetComposerInformationWithLabelWithoutStream() { - $expectedCommand = $this->winCompat("p4 -u user -p port files //depot/composer.json@0.0.1"); + $expectedCommand = "p4 -u user -p port files //depot/composer.json@0.0.1"; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnCallback(function($command, &$output) {$output = "//depot/composer.json#1 - branch change 10001 (text)"; return true;})); - $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot -p port print //depot/composer.json@10001"); + $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot -p port print //depot/composer.json@10001"; $this->processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) @@ -384,13 +385,14 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { } public function testGetComposerInformationWithoutLabelWithStream() { - $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot_branch -p port print //depot/branch/composer.json"); + $this->setPerforceToStream(); + + $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot_branch -p port print //depot/branch/composer.json"; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnCallback(function($command, &$output) {$output = PerforceTest::getComposerJson(); return true;})); - $this->perforce->setStream("//depot/branch"); $result = $this->perforce->getComposerInformation("//depot/branch"); $expected = array( @@ -403,19 +405,19 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { } public function testGetComposerInformationWithLabelWithStream() { - $expectedCommand = $this->winCompat("p4 -u user -p port files //depot/branch/composer.json@0.0.1"); + $this->setPerforceToStream(); + $expectedCommand = "p4 -u user -p port files //depot/branch/composer.json@0.0.1"; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnCallback(function($command, &$output) {$output = "//depot/composer.json#1 - branch change 10001 (text)"; return true;})); - $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot_branch -p port print //depot/branch/composer.json@10001"); + $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot_branch -p port print //depot/branch/composer.json@10001"; $this->processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnCallback(function($command, &$output) {$output = PerforceTest::getComposerJson(); return true;})); - $this->perforce->setStream("//depot/branch"); $result = $this->perforce->getComposerInformation("//depot/branch@0.0.1"); $expected = array( @@ -428,7 +430,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { } public function testSyncCodeBaseWithoutStream() { - $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot -p port sync -f @label"); + $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot -p port sync -f @label"; $this->processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand), $this->equalTo(null)) @@ -438,20 +440,20 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { } public function testSyncCodeBaseWithStream() { - $expectedCommand = $this->winCompat("p4 -u user -c composer_perforce_TEST_depot_branch -p port sync -f @label"); - $this->processExecutor->expects($this->at(1)) - ->method('execute') - ->with($this->equalTo($expectedCommand), $this->equalTo(null)) - ->will($this->returnValue(0)); + $this->setPerforceToStream(); + $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot_branch -p port sync -f @label"; + $this->processExecutor->expects($this->at(1)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnValue(0)); - $this->perforce->setStream("//depot/branch"); $this->perforce->syncCodeBase("label"); } public function testCheckServerExists() { $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); - $expectedCommand = $this->winCompat("p4 -p perforce.does.exist:port info -s"); + $expectedCommand = "p4 -p perforce.does.exist:port info -s"; $processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand), $this->equalTo(null)) @@ -464,7 +466,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { public function testCheckServerExistsWithFailure() { $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); - $expectedCommand = $this->winCompat("p4 -p perforce.does.not.exist:port info -s"); + $expectedCommand = "p4 -p perforce.does.not.exist:port info -s"; $processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand), $this->equalTo(null)) @@ -513,7 +515,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { ); if ($withStream) { $expectedArray[] = "Stream:"; - $expectedArray[] = " //depot/branching"; + $expectedArray[] = " //depot/branch"; } else { $expectedArray[] = "View: //depot/... //composer_perforce_TEST_depot/depot/..."; @@ -522,16 +524,8 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { return $expectedArray; } - private function winCompat($cmd) { - if (defined('PHP_WINDOWS_VERSION_BUILD')) { - $cmd = str_replace('cd ', 'cd /D ', $cmd); - $cmd = str_replace('composerPath', getcwd() . '/composerPath', $cmd); - - return strtr($cmd, "'", '"'); - } - - return $cmd; + private function setPerforceToStream(){ + $this->perforce->setStream("//depot/branch"); } - } diff --git a/tests/Composer/Test/Util/TestingPerforce.php b/tests/Composer/Test/Util/TestingPerforce.php deleted file mode 100644 index dc21e8c33..000000000 --- a/tests/Composer/Test/Util/TestingPerforce.php +++ /dev/null @@ -1,106 +0,0 @@ -windows_flag = false; - } - /* - * Override functions - */ - protected function getRandomValue() { - return "TEST"; - } - protected function isWindows(){ - return $this->windows_flag; - } - -// protected function executeCommand($command) { -// $this->previousCommand = $this->lastCommand; -// $this->lastCommand = $command; -// $result = $this->commandReturnValue; -// $this->commandReturnValue = $this->nextCommandReturnValue; -// $this->nextCommandReturnValue = null; -// return $result; -// } - - public function writeP4ClientSpec() { - $spec = fopen(vfsStream::url($this->getP4ClientSpec()), 'w'); - $this->writeClientSpecToFile($spec); - fclose($spec); - } - - /* - * Test Helper functions - */ - public function setDepotType($depotType) { - $this->p4depotType = $depotType; - $this->p4stream = NULL; - } - - /* - * Functions to expose protected methods for testing: - */ - public function setP4User($p4user){ - $this->p4user = $p4user; - } - public function setP4Password($password){ - $this->p4password = $password; - } - - public function testGetClient() { - return $this->getClient(); - } - - public function testGetStream() { - return $this->getStream(); - } - - public function testGetStreamWithoutLabel() { - return $this->getStreamWithoutLabel(); - } - - public function testGetClientSpec() { - return $this->getP4ClientSpec(); - } - - public function testGenerateP4Command($command, $useClient = TRUE) { - return $this->generateP4Command($command, $useClient); - } - - public function testIsLoggedIn() - { - return $this->isLoggedIn(); - } - - public function testIsStream() - { - return $this->isStream(); - } - - public function testGetP4Variable($name) - { - return $this->testGetP4Variable($name); - } - - public function testQueryP4Password($io) - { - return $this->queryP4Password($io); - } -} \ No newline at end of file From 8379985166be59f0b23a7c7d8a7ba2ee079bf3dd Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Thu, 15 Aug 2013 14:45:42 -0500 Subject: [PATCH 051/238] Updated/Standardized header comments --- .../Downloader/PerforceDownloaderTest.php | 22 +++++++++++++------ .../Repository/Vcs/PerforceDriverTest.php | 4 +++- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php index 634cc5f18..527ef9f6d 100644 --- a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php +++ b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php @@ -1,19 +1,27 @@ + * Jordi Boggiano + * + * Contributor: Matt Whittom + * Date: 7/17/13 + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ + namespace Composer\Test\Downloader; use Composer\Downloader\PerforceDownloader; use Composer\Config; use Composer\Repository\VcsRepository; - +/** + * @author Matt Whittom + */ class PerforceDownloaderTest extends \PHPUnit_Framework_TestCase { private $io; diff --git a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php index ed14b077e..ef0fc694a 100644 --- a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php @@ -19,7 +19,9 @@ use Composer\Repository\Vcs\PerforceDriver; use Composer\Util\Filesystem; use Composer\Config; - +/** + * @author Matt Whittom + */ class PerforceDriverTest extends \PHPUnit_Framework_TestCase { private $config; private $io; From f3722a46ed8af5858d6bc6fa11caba8f62a050e4 Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Fri, 16 Aug 2013 09:37:11 -0500 Subject: [PATCH 052/238] Updated comments --- .../Downloader/PerforceDownloader.php | 17 +++--- .../Repository/Vcs/PerforceDriver.php | 55 ++++++++++++------- 2 files changed, 42 insertions(+), 30 deletions(-) diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index 5cede4ff6..e68315668 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -51,19 +51,10 @@ class PerforceDownloader extends VcsDownloader return; } $repository = $package->getRepository(); - $repoConfig = $this->getRepoConfig($repository); + $repoConfig = $repository->getRepoConfig(); $this->perforce = Perforce::createPerforce($repoConfig, $package->getSourceUrl(), $path); } - public function injectPerforce($perforce){ - $this->perforce = $perforce; - $this->perforceInjected = true; - } - - private function getRepoConfig(VcsRepository $repository){ - return $repository->getRepoConfig(); - } - /** * {@inheritDoc} */ @@ -91,4 +82,10 @@ class PerforceDownloader extends VcsDownloader return $commitLogs; } + public function injectPerforce($perforce){ + $this->perforce = $perforce; + $this->perforceInjected = true; + } + + } diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 7068ebb3e..4918cca5c 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -34,7 +34,8 @@ class PerforceDriver extends VcsDriver { /** * {@inheritDoc} */ - public function initialize() { + public function initialize() + { $this->depot = $this->repoConfig['depot']; $this->branch = ""; if (isset($this->repoConfig['branch'])) { @@ -51,7 +52,8 @@ class PerforceDriver extends VcsDriver { return TRUE; } - private function initPerforce() { + private function initPerforce() + { if (isset($this->perforce)) { return; } @@ -60,15 +62,11 @@ class PerforceDriver extends VcsDriver { $this->perforce = Perforce::createPerforce($this->repoConfig, $this->getUrl(), $repoDir, $this->process); } - public function injectPerforce(Perforce $perforce) { - $this->perforce = $perforce; - } - - /** * {@inheritDoc} */ - public function getComposerInformation($identifier) { + public function getComposerInformation($identifier) + { if (isset($this->composer_info_identifier)){ if (strcmp($identifier, $this->composer_info_identifier) === 0 ) { @@ -83,14 +81,16 @@ class PerforceDriver extends VcsDriver { /** * {@inheritDoc} */ - public function getRootIdentifier() { + public function getRootIdentifier() + { return $this->branch; } /** * {@inheritDoc} */ - public function getBranches() { + public function getBranches() + { $branches = $this->perforce->getBranches(); return $branches; @@ -99,7 +99,8 @@ class PerforceDriver extends VcsDriver { /** * {@inheritDoc} */ - public function getTags() { + public function getTags() + { $tags = $this->perforce->getTags(); return $tags; @@ -108,14 +109,16 @@ class PerforceDriver extends VcsDriver { /** * {@inheritDoc} */ - public function getDist($identifier) { + public function getDist($identifier) + { return NULL; } /** * {@inheritDoc} */ - public function getSource($identifier) { + public function getSource($identifier) + { $source = array( 'type' => 'perforce', 'url' => $this->repoConfig['url'], @@ -128,14 +131,16 @@ class PerforceDriver extends VcsDriver { /** * {@inheritDoc} */ - public function getUrl() { + public function getUrl() + { return $this->url; } /** * {@inheritDoc} */ - public function hasComposerFile($identifier) { + public function hasComposerFile($identifier) + { $this->composer_info = $this->perforce->getComposerInformation("//$this->depot/$identifier"); $this->composer_info_identifier = $identifier; $result = false; @@ -148,30 +153,40 @@ class PerforceDriver extends VcsDriver { /** * {@inheritDoc} */ - public function getContents($url) { + public function getContents($url) + { return FALSE; } /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, $deep = FALSE) { + public static function supports(IOInterface $io, $url, $deep = FALSE) + { return Perforce::checkServerExists($url, new ProcessExecutor); } /** * {@inheritDoc} */ - public function cleanup(){ + public function cleanup() + { $this->perforce->cleanupClientSpec(); $this->perforce = null; } - public function getDepot(){ + public function getDepot() + { return $this->depot; } - public function getBranch(){ + public function getBranch() + { return $this->branch; } + + public function injectPerforce(Perforce $perforce) + { + $this->perforce = $perforce; + } } From a543e8bc8f69b80f224518b13b525b470ab6eff8 Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Fri, 16 Aug 2013 10:43:52 -0500 Subject: [PATCH 053/238] Replaced composer.lock with version from Master --- composer.lock | 36 +++--------------------------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/composer.lock b/composer.lock index b6ff8ec60..0086e1a4c 100644 --- a/composer.lock +++ b/composer.lock @@ -15,7 +15,7 @@ }, "dist": { "type": "zip", - "url": "https://github.com/justinrainbow/json-schema/archive/v1.1.0.zip", + "url": "https://github.com/justinrainbow/json-schema/zipball/v1.1.0", "reference": "v1.1.0", "shasum": "" }, @@ -28,37 +28,7 @@ "JsonSchema": "src/" } }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "NewBSD" - ], - "authors": [ - { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch", - "homepage": "http://wiedler.ch/igor/" - }, - { - "name": "Bruno Prieto Reis", - "email": "bruno.p.reis@gmail.com" - }, - { - "name": "Justin Rainbow", - "email": "justin.rainbow@gmail.com" - }, - { - "name": "Robert Schönthal", - "email": "seroscho@googlemail.com", - "homepage": "http://digitalkaoz.net" - } - ], - "description": "A library to validate a json schema.", - "homepage": "https://github.com/justinrainbow/json-schema", - "keywords": [ - "json", - "schema" - ], - "time": "2012-01-03 00:33:17" + "time": "2012-01-02 21:33:17" }, { "name": "seld/jsonlint", @@ -684,4 +654,4 @@ "platform-dev": [ ] -} +} \ No newline at end of file From f737e49aae56666d86803058dd07069a836f3e41 Mon Sep 17 00:00:00 2001 From: matt-whittom Date: Thu, 22 Aug 2013 09:49:22 -0500 Subject: [PATCH 054/238] Fixed issue with downloader assuming repository would be VcsRepository --- .../Downloader/PerforceDownloader.php | 13 ++++-- .../Repository/Vcs/PerforceDriver.php | 9 ++-- src/Composer/Util/Perforce.php | 45 ++++++++++++++----- tests/Composer/Test/Util/PerforceTest.php | 4 +- 4 files changed, 50 insertions(+), 21 deletions(-) diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index e68315668..1a7cee65c 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -37,7 +37,7 @@ class PerforceDownloader extends VcsDownloader $label = $package->getPrettyVersion(); $this->io->write(" Cloning ".$ref); - $this->initPerforce($package, $path); + $this->initPerforce($package, $path, $ref); $this->perforce->setStream($ref); $this->perforce->queryP4User($this->io); $this->perforce->writeP4ClientSpec(); @@ -46,15 +46,22 @@ class PerforceDownloader extends VcsDownloader $this->perforce->cleanupClientSpec(); } - private function initPerforce($package, $path){ + private function initPerforce($package, $path, $ref){ if ($this->perforceInjected){ return; } $repository = $package->getRepository(); - $repoConfig = $repository->getRepoConfig(); + $repoConfig = null; + if ($repository instanceof VcsRepository){ + $repoConfig = $this->getRepoConfig($repository); + } $this->perforce = Perforce::createPerforce($repoConfig, $package->getSourceUrl(), $path); } + private function getRepoConfig(VcsRepository $repository){ + return $repository->getRepoConfig(); + } + /** * {@inheritDoc} */ diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 4918cca5c..35f1389f7 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -42,7 +42,7 @@ class PerforceDriver extends VcsDriver { $this->branch = $this->repoConfig['branch']; } - $this->initPerforce(); + $this->initPerforce($this->repoConfig); $this->perforce->p4Login($this->io); $this->perforce->checkStream($this->depot); @@ -52,14 +52,14 @@ class PerforceDriver extends VcsDriver { return TRUE; } - private function initPerforce() + private function initPerforce($repoConfig) { if (isset($this->perforce)) { return; } $repoDir = $this->config->get('cache-vcs-dir') . "/$this->depot"; - $this->perforce = Perforce::createPerforce($this->repoConfig, $this->getUrl(), $repoDir, $this->process); + $this->perforce = Perforce::createPerforce($repoConfig, $this->getUrl(), $repoDir, $this->process); } /** @@ -122,7 +122,8 @@ class PerforceDriver extends VcsDriver { $source = array( 'type' => 'perforce', 'url' => $this->repoConfig['url'], - 'reference' => $identifier + 'reference' => $identifier, + 'p4user' => $this->perforce->getUser() ); return $source; diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 6acee208f..99c640cf1 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -42,30 +42,34 @@ class Perforce { $process = new ProcessExecutor; } $isWindows = defined('PHP_WINDOWS_VERSION_BUILD'); - if (isset($repoConfig['unique_perforce_client_name'])){ - $unique_perforce_client_name = $repoConfig['unique_perforce_client_name']; - } else { - $unique_perforce_client_name = gethostname() . "_" . time(); - $repoConfig['unique_perforce_client_name'] = $unique_perforce_client_name; - } - $perforce = new Perforce($repoConfig, $port, $path, $process, $isWindows, $unique_perforce_client_name); + $perforce = new Perforce($repoConfig, $port, $path, $process, $isWindows); return $perforce; } - public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows, $unique_perforce_client_name) { + public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows) { $this->windowsFlag = $isWindows; - $this->unique_perforce_client_name = $unique_perforce_client_name; $this->p4Port = $port; $this->path = $path; $fs = new Filesystem(); $fs->ensureDirectoryExists($path); $this->process = $process; + $this->initialize($repoConfig); + } - if (isset($repoConfig['depot'])) { + public function initialize($repoConfig){ + $this->unique_perforce_client_name = $this->generateUniquePerforceClientName(); + if (!isset ($repoConfig)){ + return; + } + if (isset($repoConfig['unique_perforce_client_name'])){ + $this->unique_perforce_client_name = $repoConfig['unique_perforce_client_name']; + } + + if (isset($repoConfig['depot'])){ $this->p4Depot = $repoConfig['depot']; } - if (isset($repoConfig['branch'])) { + if (isset($repoConfig['branch'])){ $this->p4Branch = $repoConfig['branch']; } if (isset($repoConfig['p4user'])) { @@ -79,6 +83,19 @@ class Perforce { } } + public function initializeDepotAndBranch($depot, $branch){ + if (isset($depot)) { + $this->p4Depot = $depot; + } + if (isset($branch)) { + $this->p4Branch = $branch; + } + } + + public function generateUniquePerforceClientName(){ + return gethostname() . "_" . time(); + } + public function cleanupClientSpec(){ $client = $this->getClient(); $command = "p4 client -d $client"; @@ -114,7 +131,11 @@ class Perforce { public function setStream($stream) { $this->p4Stream = $stream; - $this->p4DepotType = "stream"; + $index = strrpos($stream, "/"); + //Stream format is //depot/stream, while non-streaming depot is //depot + if ($index > 2){ + $this->p4DepotType = "stream"; + } } public function isStream() { diff --git a/tests/Composer/Test/Util/PerforceTest.php b/tests/Composer/Test/Util/PerforceTest.php index 62df75f69..e4e0e36b3 100644 --- a/tests/Composer/Test/Util/PerforceTest.php +++ b/tests/Composer/Test/Util/PerforceTest.php @@ -28,8 +28,8 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { public function setUp() { $this->processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); - $repoConfig = array("depot"=>"depot", "branch"=>"branch", "p4user"=>"user"); - $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, true, "TEST"); + $repoConfig = array("depot"=>"depot", "branch"=>"branch", "p4user"=>"user", "unique_perforce_client_name" => "TEST"); + $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, true); } public function testGetClientWithoutStream() { From 774a55befd402c061c8e77f38b6bb6c35d36e6f9 Mon Sep 17 00:00:00 2001 From: mwhittom Date: Wed, 4 Sep 2013 09:24:49 -0500 Subject: [PATCH 055/238] Updated to match psr-2 spec, fixed header comments --- .../Downloader/PerforceDownloader.php | 22 +- .../Repository/Vcs/PerforceDriver.php | 23 +- src/Composer/Util/Perforce.php | 220 ++++++----- .../Downloader/PerforceDownloaderTest.php | 74 ++-- .../Repository/Vcs/PerforceDriverTest.php | 73 ++-- tests/Composer/Test/Util/PerforceTest.php | 345 +++++++++++++----- 6 files changed, 476 insertions(+), 281 deletions(-) diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index 1a7cee65c..9d3e31e06 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -6,9 +6,6 @@ * (c) Nils Adermann * Jordi Boggiano * - * Contributor: Matt Whittom - * Date: 7/17/13 - * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -36,7 +33,7 @@ class PerforceDownloader extends VcsDownloader $ref = $package->getSourceReference(); $label = $package->getPrettyVersion(); - $this->io->write(" Cloning ".$ref); + $this->io->write(" Cloning " . $ref); $this->initPerforce($package, $path, $ref); $this->perforce->setStream($ref); $this->perforce->queryP4User($this->io); @@ -46,19 +43,21 @@ class PerforceDownloader extends VcsDownloader $this->perforce->cleanupClientSpec(); } - private function initPerforce($package, $path, $ref){ - if ($this->perforceInjected){ + private function initPerforce($package, $path, $ref) + { + if ($this->perforceInjected) { return; } $repository = $package->getRepository(); $repoConfig = null; - if ($repository instanceof VcsRepository){ + if ($repository instanceof VcsRepository) { $repoConfig = $this->getRepoConfig($repository); } $this->perforce = Perforce::createPerforce($repoConfig, $package->getSourceUrl(), $path); } - private function getRepoConfig(VcsRepository $repository){ + private function getRepoConfig(VcsRepository $repository) + { return $repository->getRepoConfig(); } @@ -75,7 +74,7 @@ class PerforceDownloader extends VcsDownloader */ public function getLocalChanges(PackageInterface $package, $path) { - print ("Perforce driver does not check for local changes before overriding\n"); + $this->io->write("Perforce driver does not check for local changes before overriding", true); return; } @@ -89,10 +88,9 @@ class PerforceDownloader extends VcsDownloader return $commitLogs; } - public function injectPerforce($perforce){ + public function injectPerforce($perforce) + { $this->perforce = $perforce; $this->perforceInjected = true; } - - } diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 35f1389f7..cc04fea2f 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -6,9 +6,6 @@ * (c) Nils Adermann * Jordi Boggiano * - * Contributor: Matt Whittom - * Date: 7/17/13 - * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -24,7 +21,8 @@ use Composer\Util\Perforce; /** * @author Matt Whittom */ -class PerforceDriver extends VcsDriver { +class PerforceDriver extends VcsDriver +{ protected $depot; protected $branch; protected $perforce; @@ -49,7 +47,7 @@ class PerforceDriver extends VcsDriver { $this->perforce->writeP4ClientSpec(); $this->perforce->connectClient(); - return TRUE; + return true; } private function initPerforce($repoConfig) @@ -67,9 +65,8 @@ class PerforceDriver extends VcsDriver { */ public function getComposerInformation($identifier) { - if (isset($this->composer_info_identifier)){ - if (strcmp($identifier, $this->composer_info_identifier) === 0 ) - { + if (isset($this->composer_info_identifier)) { + if (strcmp($identifier, $this->composer_info_identifier) === 0) { return $this->composer_info; } } @@ -111,7 +108,7 @@ class PerforceDriver extends VcsDriver { */ public function getDist($identifier) { - return NULL; + return null; } /** @@ -123,7 +120,7 @@ class PerforceDriver extends VcsDriver { 'type' => 'perforce', 'url' => $this->repoConfig['url'], 'reference' => $identifier, - 'p4user' => $this->perforce->getUser() + 'p4user' => $this->perforce->getUser() ); return $source; @@ -145,7 +142,7 @@ class PerforceDriver extends VcsDriver { $this->composer_info = $this->perforce->getComposerInformation("//$this->depot/$identifier"); $this->composer_info_identifier = $identifier; $result = false; - if (isset($this->composer_info)){ + if (isset($this->composer_info)) { $result = count($this->composer_info) > 0; } return $result; @@ -156,13 +153,13 @@ class PerforceDriver extends VcsDriver { */ public function getContents($url) { - return FALSE; + return false; } /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, $deep = FALSE) + public static function supports(IOInterface $io, $url, $deep = false) { return Perforce::checkServerExists($url, new ProcessExecutor); } diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 99c640cf1..d22d3a13c 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -5,9 +5,6 @@ * (c) Nils Adermann * Jordi Boggiano * - * Contributor: Matt Whittom - * Date: 7/17/13 - * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -20,7 +17,8 @@ use Composer\IO\IOInterface; /** * @author Matt Whittom */ -class Perforce { +class Perforce +{ protected $path; protected $p4Depot; @@ -37,8 +35,9 @@ class Perforce { protected $windowsFlag; - public static function createPerforce($repoConfig, $port, $path, ProcessExecutor $process = NULL) { - if (!isset($process)){ + public static function createPerforce($repoConfig, $port, $path, ProcessExecutor $process = null) + { + if (!isset($process)) { $process = new ProcessExecutor; } $isWindows = defined('PHP_WINDOWS_VERSION_BUILD'); @@ -47,7 +46,8 @@ class Perforce { return $perforce; } - public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows) { + public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows) + { $this->windowsFlag = $isWindows; $this->p4Port = $port; $this->path = $path; @@ -57,25 +57,25 @@ class Perforce { $this->initialize($repoConfig); } - public function initialize($repoConfig){ + public function initialize($repoConfig) + { $this->unique_perforce_client_name = $this->generateUniquePerforceClientName(); - if (!isset ($repoConfig)){ + if (!isset ($repoConfig)) { return; } - if (isset($repoConfig['unique_perforce_client_name'])){ + if (isset($repoConfig['unique_perforce_client_name'])) { $this->unique_perforce_client_name = $repoConfig['unique_perforce_client_name']; } - if (isset($repoConfig['depot'])){ + if (isset($repoConfig['depot'])) { $this->p4Depot = $repoConfig['depot']; } - if (isset($repoConfig['branch'])){ + if (isset($repoConfig['branch'])) { $this->p4Branch = $repoConfig['branch']; } if (isset($repoConfig['p4user'])) { $this->p4User = $repoConfig['p4user']; - } - else { + } else { $this->p4User = $this->getP4variable("P4USER"); } if (isset($repoConfig['p4password'])) { @@ -83,7 +83,8 @@ class Perforce { } } - public function initializeDepotAndBranch($depot, $branch){ + public function initializeDepotAndBranch($depot, $branch) + { if (isset($depot)) { $this->p4Depot = $depot; } @@ -92,11 +93,13 @@ class Perforce { } } - public function generateUniquePerforceClientName(){ - return gethostname() . "_" . time(); + public function generateUniquePerforceClientName() + { + return gethostname() . "_" . time(); } - public function cleanupClientSpec(){ + public function cleanupClientSpec() + { $client = $this->getClient(); $command = "p4 client -d $client"; $this->executeCommand($command); @@ -105,14 +108,16 @@ class Perforce { $fileSystem->remove($clientSpec); } - protected function executeCommand($command) { + protected function executeCommand($command) + { $result = ""; $this->process->execute($command, $result); return $result; } - public function getClient() { + public function getClient() + { if (!isset($this->p4Client)) { $clean_stream_name = str_replace("@", "", str_replace("/", "_", str_replace("//", "", $this->getStream()))); $this->p4Client = "composer_perforce_" . $this->unique_perforce_client_name . "_" . $clean_stream_name; @@ -121,59 +126,67 @@ class Perforce { return $this->p4Client; } - protected function getPath() { + protected function getPath() + { return $this->path; } - protected function getPort() { + protected function getPort() + { return $this->p4Port; } - public function setStream($stream) { + public function setStream($stream) + { $this->p4Stream = $stream; $index = strrpos($stream, "/"); //Stream format is //depot/stream, while non-streaming depot is //depot - if ($index > 2){ + if ($index > 2) { $this->p4DepotType = "stream"; } } - public function isStream() { + public function isStream() + { return (strcmp($this->p4DepotType, "stream") === 0); } - public function getStream() { + public function getStream() + { if (!isset($this->p4Stream)) { if ($this->isStream()) { $this->p4Stream = "//$this->p4Depot/$this->p4Branch"; - } - else { + } else { $this->p4Stream = "//$this->p4Depot"; } } return $this->p4Stream; } - public function getStreamWithoutLabel($stream) { + public function getStreamWithoutLabel($stream) + { $index = strpos($stream, "@"); - if ($index === FALSE) { + if ($index === false) { return $stream; } return substr($stream, 0, $index); } - public function getP4ClientSpec() { + public function getP4ClientSpec() + { $p4clientSpec = $this->path . "/" . $this->getClient() . ".p4.spec"; return $p4clientSpec; } - public function getUser() { + public function getUser() + { return $this->p4User; } - public function queryP4User(IOInterface $io) { + public function queryP4User(IOInterface $io) + { $this->getUser(); if (strlen($this->p4User) > 0) { return; @@ -185,14 +198,14 @@ class Perforce { $this->p4User = $io->ask("Enter P4 User:"); if ($this->windowsFlag) { $command = "p4 set P4USER=$this->p4User"; - } - else { + } else { $command = "export P4USER=$this->p4User"; } $result = $this->executeCommand($command); } - protected function getP4variable($name) { + protected function getP4variable($name) + { if ($this->windowsFlag) { $command = "p4 set"; $result = $this->executeCommand($command); @@ -201,10 +214,9 @@ class Perforce { $fields = explode("=", $line); if (strcmp($name, $fields[0]) == 0) { $index = strpos($fields[1], " "); - if ($index === FALSE) { + if ($index === false) { $value = $fields[1]; - } - else { + } else { $value = substr($fields[1], 0, $index); } $value = trim($value); @@ -212,8 +224,7 @@ class Perforce { return $value; } } - } - else { + } else { $command = 'echo $' . $name; $result = trim($this->executeCommand($command)); @@ -221,7 +232,8 @@ class Perforce { } } - public function queryP4Password(IOInterface $io) { + public function queryP4Password(IOInterface $io) + { if (isset($this->p4Password)) { return $this->p4Password; } @@ -234,7 +246,8 @@ class Perforce { return $password; } - public function generateP4Command($command, $useClient = TRUE) { + public function generateP4Command($command, $useClient = true) + { $p4Command = "p4 "; $p4Command = $p4Command . "-u " . $this->getUser() . " "; if ($useClient) { @@ -246,22 +259,25 @@ class Perforce { return $p4Command; } - public function isLoggedIn() { - $command = $this->generateP4Command("login -s", FALSE); + public function isLoggedIn() + { + $command = $this->generateP4Command("login -s", false); $result = trim($this->executeCommand($command)); $index = strpos($result, $this->getUser()); - if ($index === FALSE) { - return FALSE; + if ($index === false) { + return false; } - return TRUE; + return true; } - public function connectClient() { + public function connectClient() + { $p4CreateClientCommand = $this->generateP4Command("client -i < " . $this->getP4ClientSpec()); $this->executeCommand($p4CreateClientCommand); } - public function syncCodeBase($label) { + public function syncCodeBase($label) + { $prevDir = getcwd(); chdir($this->path); @@ -278,7 +294,8 @@ class Perforce { chdir($prevDir); } - public function writeClientSpecToFile($spec) { + public function writeClientSpecToFile($spec) + { fwrite($spec, "Client: " . $this->getClient() . "\n\n"); fwrite($spec, "Update: " . date("Y/m/d H:i:s") . "\n\n"); fwrite($spec, "Access: " . date("Y/m/d H:i:s") . "\n"); @@ -292,17 +309,20 @@ class Perforce { if ($this->isStream()) { fwrite($spec, "Stream:\n"); fwrite($spec, " " . $this->getStreamWithoutLabel($this->p4Stream) . "\n"); - } - else { + } else { fwrite( - $spec, "View: " . $this->getStream() . "/... //" . $this->getClient() . "/" . str_replace( - "//", "", $this->getStream() - ) . "/... \n" + $spec, + "View: " . $this->getStream() . "/... //" . $this->getClient() . "/" . str_replace( + "//", + "", + $this->getStream() + ) . "/... \n" ); } } - public function writeP4ClientSpec() { + public function writeP4ClientSpec() + { $clientSpec = $this->getP4ClientSpec(); $spec = fopen($clientSpec, 'w'); try { @@ -315,19 +335,21 @@ class Perforce { } - protected function read($pipe, $name) { + protected function read($pipe, $name) + { if (feof($pipe)) { return; } $line = fgets($pipe); - while ($line != FALSE) { + while ($line != false) { $line = fgets($pipe); } return; } - public function windowsLogin($password) { + public function windowsLogin($password) + { $descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), @@ -336,7 +358,7 @@ class Perforce { $command = $this->generateP4Command(" login -a"); $process = proc_open($command, $descriptorspec, $pipes); if (!is_resource($process)) { - return FALSE; + return false; } fwrite($pipes[0], $password); fclose($pipes[0]); @@ -353,54 +375,56 @@ class Perforce { } - public function p4Login(IOInterface $io) { + public function p4Login(IOInterface $io) + { $this->queryP4User($io); if (!$this->isLoggedIn()) { $password = $this->queryP4Password($io); if ($this->windowsFlag) { $this->windowsLogin($password); - } - else { - $command = "echo $password | " . $this->generateP4Command(" login -a", FALSE); + } else { + $command = "echo $password | " . $this->generateP4Command(" login -a", false); $this->executeCommand($command); } } } - public static function checkServerExists($url, ProcessExecutor $process_executor) { + public static function checkServerExists($url, ProcessExecutor $process_executor) + { $process = $process_executor ? : new ProcessExecutor; $result = ""; $process->execute("p4 -p $url info -s", $result); $index = strpos($result, "error"); - if ($index === FALSE) { - return TRUE; + if ($index === false) { + return true; } - return FALSE; + return false; } - public function getComposerInformation($identifier) { + public function getComposerInformation($identifier) + { $index = strpos($identifier, "@"); - if ($index === FALSE) { + if ($index === false) { $composer_json = "$identifier/composer.json"; return $this->getComposerInformationFromPath($composer_json); - } - else { + } else { return $this->getComposerInformationFromLabel($identifier, $index); } } - public function getComposerInformationFromPath($composer_json) { + public function getComposerInformationFromPath($composer_json) + { $command = $this->generateP4Command(" print $composer_json"); $result = $this->executeCommand($command); $index = strpos($result, "{"); - if ($index === FALSE) { + if ($index === false) { return ""; } if ($index >= 0) { $rawData = substr($result, $index); - $composer_info = json_decode($rawData, TRUE); + $composer_info = json_decode($rawData, true); return $composer_info; } @@ -408,14 +432,15 @@ class Perforce { return ""; } - public function getComposerInformationFromLabel($identifier, $index) { + public function getComposerInformationFromLabel($identifier, $index) + { $composer_json_path = substr($identifier, 0, $index) . "/composer.json" . substr($identifier, $index); - $command = $this->generateP4Command(" files $composer_json_path", FALSE); + $command = $this->generateP4Command(" files $composer_json_path", false); $result = $this->executeCommand($command); $index2 = strpos($result, "no such file(s)."); - if ($index2 === FALSE) { + if ($index2 === false) { $index3 = strpos($result, "change"); - if (!($index3 === FALSE)) { + if (!($index3 === false)) { $phrase = trim(substr($result, $index3)); $fields = explode(" ", $phrase); $id = $fields[1]; @@ -428,12 +453,12 @@ class Perforce { return ""; } - public function getBranches() { + public function getBranches() + { $possible_branches = array(); if (!$this->isStream()) { $possible_branches[$this->p4Branch] = $this->getStream(); - } - else { + } else { $command = $this->generateP4Command("streams //$this->p4Depot/..."); $result = $this->executeCommand($command); $resArray = explode("\n", $result); @@ -451,14 +476,15 @@ class Perforce { return $branches; } - public function getTags() { + public function getTags() + { $command = $this->generateP4Command("labels"); $result = $this->executeCommand($command); $resArray = explode("\n", $result); $tags = array(); foreach ($resArray as $line) { $index = strpos($line, "Label"); - if (!($index === FALSE)) { + if (!($index === false)) { $fields = explode(" ", $line); $tags[$fields[1]] = $this->getStream() . "@" . $fields[1]; } @@ -467,13 +493,14 @@ class Perforce { return $tags; } - public function checkStream() { - $command = $this->generateP4Command("depots", FALSE); + public function checkStream() + { + $command = $this->generateP4Command("depots", false); $result = $this->executeCommand($command); $resArray = explode("\n", $result); foreach ($resArray as $line) { $index = strpos($line, "Depot"); - if (!($index === FALSE)) { + if (!($index === false)) { $fields = explode(" ", $line); if (strcmp($this->p4Depot, $fields[1]) === 0) { $this->p4DepotType = $fields[3]; @@ -483,31 +510,34 @@ class Perforce { } } - return FALSE; + return false; } - protected function getChangeList($reference){ + protected function getChangeList($reference) + { $index = strpos($reference, "@"); - if ($index === false){ + if ($index === false) { return; } $label = substr($reference, $index); $command = $this->generateP4Command(" changes -m1 $label"); $changes = $this->executeCommand($command); - if (strpos($changes, "Change") !== 0){ + if (strpos($changes, "Change") !== 0) { return; } $fields = explode(" ", $changes); $changeList = $fields[1]; return $changeList; } - public function getCommitLogs($fromReference, $toReference){ + + public function getCommitLogs($fromReference, $toReference) + { $fromChangeList = $this->getChangeList($fromReference); - if ($fromChangeList == null){ + if ($fromChangeList == null) { return; } $toChangeList = $this->getChangeList($toReference); - if ($toChangeList == null){ + if ($toChangeList == null) { return; } $index = strpos($fromReference, "@"); diff --git a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php index 527ef9f6d..557507090 100644 --- a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php +++ b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php @@ -5,9 +5,6 @@ * (c) Nils Adermann * Jordi Boggiano * - * Contributor: Matt Whittom - * Date: 7/17/13 - * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -22,14 +19,16 @@ use Composer\Repository\VcsRepository; /** * @author Matt Whittom */ -class PerforceDownloaderTest extends \PHPUnit_Framework_TestCase { +class PerforceDownloaderTest extends \PHPUnit_Framework_TestCase +{ private $io; private $config; private $testPath; public static $repository; - function setUp() { + function setUp() + { $this->testPath = sys_get_temp_dir() . '/composer-test'; $this->config = new Config(); $this->config->merge( @@ -43,58 +42,67 @@ class PerforceDownloaderTest extends \PHPUnit_Framework_TestCase { } - public function testDoDownloadGetRepoConfig() { + public function testDoDownloadGetRepoConfig() + { $downloader = new PerforceDownloader($this->io, $this->config); - $package = $this->getMock('Composer\Package\PackageInterface' ); - $repoConfig = array('url'=>'TEST_URL','p4user'=>'TEST_USER'); - $repository = $this->getMock('Composer\Repository\VcsRepository', array('getRepoConfig'), array($repoConfig, $this->io, $this->config)); + $package = $this->getMock('Composer\Package\PackageInterface'); + $repoConfig = array('url' => 'TEST_URL', 'p4user' => 'TEST_USER'); + $repository = $this->getMock( + 'Composer\Repository\VcsRepository', + array('getRepoConfig'), + array($repoConfig, $this->io, $this->config) + ); $package->expects($this->at(0)) - ->method('getSourceReference') - ->will($this->returnValue("SOURCE_REF")); + ->method('getSourceReference') + ->will($this->returnValue("SOURCE_REF")); $package->expects($this->at(1)) - ->method('getPrettyVersion') - ->will($this->returnValue("100")); + ->method('getPrettyVersion') + ->will($this->returnValue("100")); $package->expects($this->at(2)) - ->method('getRepository') - ->will($this->returnValue($repository)); + ->method('getRepository') + ->will($this->returnValue($repository)); $repository->expects($this->at(0)) - ->method('getRepoConfig'); + ->method('getRepoConfig'); $path = $this->testPath; $downloader->doDownload($package, $path); } - public function testDoDownload() { + public function testDoDownload() + { $downloader = new PerforceDownloader($this->io, $this->config); - $repoConfig = array("depot"=>"TEST_DEPOT", "branch"=>"TEST_BRANCH", "p4user"=>"TEST_USER"); + $repoConfig = array("depot" => "TEST_DEPOT", "branch" => "TEST_BRANCH", "p4user" => "TEST_USER"); $port = "TEST_PORT"; $path = "TEST_PATH"; $process = $this->getmock('Composer\Util\ProcessExecutor'); - $perforce = $this->getMock('Composer\Util\Perforce', array('setStream', 'queryP4User', 'writeP4ClientSpec', 'connectClient', 'syncCodeBase'), array($repoConfig, $port, $path, $process, true, "TEST")); + $perforce = $this->getMock( + 'Composer\Util\Perforce', + array('setStream', 'queryP4User', 'writeP4ClientSpec', 'connectClient', 'syncCodeBase'), + array($repoConfig, $port, $path, $process, true, "TEST") + ); $ref = "SOURCE_REF"; $label = "LABEL"; $perforce->expects($this->at(0)) - ->method('setStream') - ->with($this->equalTo($ref)); + ->method('setStream') + ->with($this->equalTo($ref)); $perforce->expects($this->at(1)) - ->method('queryP4User') - ->with($this->io); + ->method('queryP4User') + ->with($this->io); $perforce->expects($this->at(2)) - ->method('writeP4ClientSpec'); + ->method('writeP4ClientSpec'); $perforce->expects($this->at(3)) - ->method('connectClient'); + ->method('connectClient'); $perforce->expects($this->at(4)) - ->method('syncCodeBase') - ->with($this->equalTo($label)); + ->method('syncCodeBase') + ->with($this->equalTo($label)); $downloader->injectPerforce($perforce); - $package = $this->getMock('Composer\Package\PackageInterface' ); + $package = $this->getMock('Composer\Package\PackageInterface'); $package->expects($this->at(0)) - ->method('getSourceReference') - ->will($this->returnValue($ref)); + ->method('getSourceReference') + ->will($this->returnValue($ref)); $package->expects($this->at(1)) - ->method('getPrettyVersion') - ->will($this->returnValue($label)); + ->method('getPrettyVersion') + ->will($this->returnValue($label)); $path = $this->testPath; $downloader->doDownload($package, $path); - } } diff --git a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php index ef0fc694a..77c41a0e1 100644 --- a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php @@ -5,9 +5,6 @@ * (c) Nils Adermann * Jordi Boggiano * - * Contributor: matt-whittom - * Date: 7/17/13 - * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -22,14 +19,16 @@ use Composer\Config; /** * @author Matt Whittom */ -class PerforceDriverTest extends \PHPUnit_Framework_TestCase { +class PerforceDriverTest extends \PHPUnit_Framework_TestCase +{ private $config; private $io; private $process; private $remoteFileSystem; private $testPath; - public function setUp() { + public function setUp() + { $this->testPath = sys_get_temp_dir() . '/composer-test'; $this->config = new Config(); $this->config->merge( @@ -42,24 +41,34 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase { $this->io = $this->getMock('Composer\IO\IOInterface'); $this->process = $this->getMock('Composer\Util\ProcessExecutor'); - $this->remoteFileSystem = $this->getMockBuilder('Composer\Util\RemoteFilesystem')->disableOriginalConstructor()->getMock(); + $this->remoteFileSystem = $this->getMockBuilder('Composer\Util\RemoteFilesystem')->disableOriginalConstructor() + ->getMock(); } - public function tearDown() { + public function tearDown() + { $fs = new Filesystem; $fs->removeDirectory($this->testPath); } - public function testInitializeCapturesVariablesFromRepoConfig() { + public function testInitializeCapturesVariablesFromRepoConfig() + { $this->setUp(); $repo_config = array( - 'url' => 'TEST_PERFORCE_URL', - 'depot' => 'TEST_DEPOT_CONFIG', + 'url' => 'TEST_PERFORCE_URL', + 'depot' => 'TEST_DEPOT_CONFIG', 'branch' => 'TEST_BRANCH_CONFIG' ); $driver = new PerforceDriver($repo_config, $this->io, $this->config, $this->process, $this->remoteFileSystem); $process = $this->getMock('Composer\Util\ProcessExecutor'); - $arguments = array(array('depot'=>'TEST_DEPOT', 'branch'=>'TEST_BRANCH'), 'port'=>'TEST_PORT', 'path'=>$this->testPath, $process, true, "TEST"); + $arguments = array( + array('depot' => 'TEST_DEPOT', 'branch' => 'TEST_BRANCH'), + 'port' => 'TEST_PORT', + 'path' => $this->testPath, + $process, + true, + "TEST" + ); $perforce = $this->getMock('Composer\Util\Perforce', null, $arguments); $driver->injectPerforce($perforce); $driver->initialize(); @@ -68,51 +77,59 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase { $this->assertEquals("TEST_BRANCH_CONFIG", $driver->getBranch()); } - public function testInitializeLogsInAndConnectsClient() { + public function testInitializeLogsInAndConnectsClient() + { $this->setUp(); $repo_config = array( - 'url' => 'TEST_PERFORCE_URL', - 'depot' => 'TEST_DEPOT_CONFIG', + 'url' => 'TEST_PERFORCE_URL', + 'depot' => 'TEST_DEPOT_CONFIG', 'branch' => 'TEST_BRANCH_CONFIG' ); $driver = new PerforceDriver($repo_config, $this->io, $this->config, $this->process, $this->remoteFileSystem); $perforce = $this->getMockBuilder('Composer\Util\Perforce')->disableOriginalConstructor()->getMock(); $perforce->expects($this->at(0)) - ->method('p4Login') - ->with($this->io); + ->method('p4Login') + ->with($this->io); $perforce->expects($this->at(1)) - ->method('checkStream') - ->with($this->equalTo("TEST_DEPOT_CONFIG")); + ->method('checkStream') + ->with($this->equalTo("TEST_DEPOT_CONFIG")); $perforce->expects($this->at(2)) - ->method('writeP4ClientSpec'); + ->method('writeP4ClientSpec'); $perforce->expects($this->at(3)) - ->method('connectClient'); + ->method('connectClient'); $driver->injectPerforce($perforce); $driver->initialize(); } - public function testHasComposerFile() { + public function testHasComposerFile() + { $this->setUp(); $repo_config = array( - 'url' => 'TEST_PERFORCE_URL', - 'depot' => 'TEST_DEPOT_CONFIG', + 'url' => 'TEST_PERFORCE_URL', + 'depot' => 'TEST_DEPOT_CONFIG', 'branch' => 'TEST_BRANCH_CONFIG' ); $driver = new PerforceDriver($repo_config, $this->io, $this->config, $this->process, $this->remoteFileSystem); $process = $this->getMock('Composer\Util\ProcessExecutor'); - $arguments = array(array('depot'=>'TEST_DEPOT', 'branch'=>'TEST_BRANCH'), 'port'=>'TEST_PORT', 'path'=>$this->testPath, $process, true, "TEST"); + $arguments = array( + array('depot' => 'TEST_DEPOT', 'branch' => 'TEST_BRANCH'), + 'port' => 'TEST_PORT', + 'path' => $this->testPath, + $process, + true, + "TEST" + ); $perforce = $this->getMock('Composer\Util\Perforce', array('getComposerInformation'), $arguments); $perforce->expects($this->at(0)) - ->method('getComposerInformation') - ->with($this->equalTo("//TEST_DEPOT_CONFIG/TEST_IDENTIFIER")) - ->will($this->returnValue("Some json stuff")); + ->method('getComposerInformation') + ->with($this->equalTo("//TEST_DEPOT_CONFIG/TEST_IDENTIFIER")) + ->will($this->returnValue("Some json stuff")); $driver->injectPerforce($perforce); $driver->initialize(); $identifier = "TEST_IDENTIFIER"; $result = $driver->hasComposerFile($identifier); $this->assertTrue($result); } - } diff --git a/tests/Composer/Test/Util/PerforceTest.php b/tests/Composer/Test/Util/PerforceTest.php index e4e0e36b3..0cca37c2e 100644 --- a/tests/Composer/Test/Util/PerforceTest.php +++ b/tests/Composer/Test/Util/PerforceTest.php @@ -5,9 +5,6 @@ * (c) Nils Adermann * Jordi Boggiano * - * Contributor: Matt Whittom - * Date: 7/17/13 - * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -21,18 +18,26 @@ use Composer\Util\ProcessExecutor; /** * @author Matt Whittom */ -class PerforceTest extends \PHPUnit_Framework_TestCase { +class PerforceTest extends \PHPUnit_Framework_TestCase +{ protected $perforce; protected $processExecutor; - public function setUp() { + public function setUp() + { $this->processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); - $repoConfig = array("depot"=>"depot", "branch"=>"branch", "p4user"=>"user", "unique_perforce_client_name" => "TEST"); + $repoConfig = array( + "depot" => "depot", + "branch" => "branch", + "p4user" => "user", + "unique_perforce_client_name" => "TEST" + ); $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, true); } - public function testGetClientWithoutStream() { + public function testGetClientWithoutStream() + { $client = $this->perforce->getClient(); $hostname = gethostname(); $timestamp = time(); @@ -41,7 +46,8 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->assertEquals($expected, $client); } - public function testGetClientFromStream() { + public function testGetClientFromStream() + { $this->setPerforceToStream(); $client = $this->perforce->getClient(); @@ -50,12 +56,14 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->assertEquals($expected, $client); } - public function testGetStreamWithoutStream() { + public function testGetStreamWithoutStream() + { $stream = $this->perforce->getStream(); $this->assertEquals("//depot", $stream); } - public function testGetStreamWithStream() { + public function testGetStreamWithStream() + { $this->setPerforceToStream(); $stream = $this->perforce->getStream(); @@ -63,56 +71,70 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { } - public function testGetStreamWithoutLabelWithStreamWithoutLabel(){ + public function testGetStreamWithoutLabelWithStreamWithoutLabel() + { $stream = $this->perforce->getStreamWithoutLabel("//depot/branch"); $this->assertEquals("//depot/branch", $stream); } - public function testGetStreamWithoutLabelWithStreamWithLabel(){ + public function testGetStreamWithoutLabelWithStreamWithLabel() + { $stream = $this->perforce->getStreamWithoutLabel("//depot/branching@label"); $this->assertEquals("//depot/branching", $stream); } - public function testGetClientSpec() { + public function testGetClientSpec() + { $clientSpec = $this->perforce->getP4ClientSpec(); $expected = "path/composer_perforce_TEST_depot.p4.spec"; $this->assertEquals($expected, $clientSpec); } - public function testGenerateP4Command() { + public function testGenerateP4Command() + { $command = "do something"; $p4Command = $this->perforce->generateP4Command($command); $expected = "p4 -u user -c composer_perforce_TEST_depot -p port do something"; $this->assertEquals($expected, $p4Command); } - public function testQueryP4UserWithUserAlreadySet(){ + public function testQueryP4UserWithUserAlreadySet() + { $io = $this->getMock('Composer\IO\IOInterface'); - $repoConfig = array("depot"=>"depot", "branch"=>"branch", "p4user"=>"TEST_USER"); + $repoConfig = array("depot" => "depot", "branch" => "branch", "p4user" => "TEST_USER"); $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, true, "TEST"); $this->perforce->queryP4user($io); $this->assertEquals("TEST_USER", $this->perforce->getUser()); } - public function testQueryP4UserWithUserSetInP4VariablesWithWindowsOS(){ - $repoConfig = array("depot"=>"depot", "branch"=>"branch"); + public function testQueryP4UserWithUserSetInP4VariablesWithWindowsOS() + { + $repoConfig = array("depot" => "depot", "branch" => "branch"); $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, true, "TEST"); $io = $this->getMock('Composer\IO\IOInterface'); $expectedCommand = "p4 set"; $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will($this->returnCallback(function($command, &$output) {$output = "P4USER=TEST_P4VARIABLE_USER\n"; return true;})); + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = "P4USER=TEST_P4VARIABLE_USER\n"; + return true; + } + ) + ); $this->perforce->queryP4user($io); $this->assertEquals("TEST_P4VARIABLE_USER", $this->perforce->getUser()); } - public function testQueryP4UserWithUserSetInP4VariablesNotWindowsOS(){ - $repoConfig = array("depot"=>"depot", "branch"=>"branch"); + public function testQueryP4UserWithUserSetInP4VariablesNotWindowsOS() + { + $repoConfig = array("depot" => "depot", "branch" => "branch"); $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, false, "TEST"); $io = $this->getMock('Composer\IO\IOInterface'); @@ -120,47 +142,57 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) - ->will($this->returnCallback(function($command, &$output) {$output = "TEST_P4VARIABLE_USER\n"; return true;})); + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = "TEST_P4VARIABLE_USER\n"; + return true; + } + ) + ); $this->perforce->queryP4user($io); $this->assertEquals("TEST_P4VARIABLE_USER", $this->perforce->getUser()); } - public function testQueryP4UserQueriesForUser(){ - $repoConfig = array("depot"=>"depot", "branch"=>"branch"); + public function testQueryP4UserQueriesForUser() + { + $repoConfig = array("depot" => "depot", "branch" => "branch"); $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, false, "TEST"); $io = $this->getMock('Composer\IO\IOInterface'); $expectedQuestion = "Enter P4 User:"; $io->expects($this->at(0)) - ->method('ask') - ->with($this->equalTo($expectedQuestion)) - ->will($this->returnValue("TEST_QUERY_USER")); + ->method('ask') + ->with($this->equalTo($expectedQuestion)) + ->will($this->returnValue("TEST_QUERY_USER")); $this->perforce->queryP4user($io); $this->assertEquals("TEST_QUERY_USER", $this->perforce->getUser()); } - public function testQueryP4UserStoresResponseToQueryForUserWithWindows(){ - $repoConfig = array("depot"=>"depot", "branch"=>"branch"); + public function testQueryP4UserStoresResponseToQueryForUserWithWindows() + { + $repoConfig = array("depot" => "depot", "branch" => "branch"); $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, true, "TEST"); $io = $this->getMock('Composer\IO\IOInterface'); $expectedQuestion = "Enter P4 User:"; $io->expects($this->at(0)) - ->method('ask') - ->with($this->equalTo($expectedQuestion)) - ->will($this->returnValue("TEST_QUERY_USER")); + ->method('ask') + ->with($this->equalTo($expectedQuestion)) + ->will($this->returnValue("TEST_QUERY_USER")); $expectedCommand = "p4 set P4USER=TEST_QUERY_USER"; $this->processExecutor->expects($this->at(1)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will($this->returnValue(0)); + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnValue(0)); $this->perforce->queryP4user($io); } - public function testQueryP4UserStoresResponseToQueryForUserWithoutWindows(){ - $repoConfig = array("depot"=>"depot", "branch"=>"branch"); + public function testQueryP4UserStoresResponseToQueryForUserWithoutWindows() + { + $repoConfig = array("depot" => "depot", "branch" => "branch"); $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, false, "TEST"); $io = $this->getMock('Composer\IO\IOInterface'); @@ -178,8 +210,14 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->perforce->queryP4user($io); } - public function testQueryP4PasswordWithPasswordAlreadySet(){ - $repoConfig = array("depot"=>"depot", "branch"=>"branch", "p4user"=>"user", "p4password"=>"TEST_PASSWORD"); + public function testQueryP4PasswordWithPasswordAlreadySet() + { + $repoConfig = array( + "depot" => "depot", + "branch" => "branch", + "p4user" => "user", + "p4password" => "TEST_PASSWORD" + ); $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, false, "TEST"); $io = $this->getMock('Composer\IO\IOInterface'); @@ -187,21 +225,30 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->assertEquals("TEST_PASSWORD", $password); } - public function testQueryP4PasswordWithPasswordSetInP4VariablesWithWindowsOS(){ + public function testQueryP4PasswordWithPasswordSetInP4VariablesWithWindowsOS() + { $io = $this->getMock('Composer\IO\IOInterface'); $expectedCommand = "p4 set"; $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will($this->returnCallback(function($command, &$output) {$output = "P4PASSWD=TEST_P4VARIABLE_PASSWORD\n"; return true;})); + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = "P4PASSWD=TEST_P4VARIABLE_PASSWORD\n"; + return true; + } + ) + ); $password = $this->perforce->queryP4Password($io); $this->assertEquals("TEST_P4VARIABLE_PASSWORD", $password); } - public function testQueryP4PasswordWithPasswordSetInP4VariablesNotWindowsOS(){ - $repoConfig = array("depot"=>"depot", "branch"=>"branch", "p4user"=>"user"); + public function testQueryP4PasswordWithPasswordSetInP4VariablesNotWindowsOS() + { + $repoConfig = array("depot" => "depot", "branch" => "branch", "p4user" => "user"); $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, false, "TEST"); $io = $this->getMock('Composer\IO\IOInterface'); @@ -209,30 +256,39 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) - ->will($this->returnCallback(function($command, &$output) {$output = "TEST_P4VARIABLE_PASSWORD\n"; return true;})); + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = "TEST_P4VARIABLE_PASSWORD\n"; + return true; + } + ) + ); $password = $this->perforce->queryP4Password($io); $this->assertEquals("TEST_P4VARIABLE_PASSWORD", $password); } - public function testQueryP4PasswordQueriesForPassword(){ + public function testQueryP4PasswordQueriesForPassword() + { $io = $this->getMock('Composer\IO\IOInterface'); $expectedQuestion = "Enter password for Perforce user user: "; $io->expects($this->at(0)) - ->method('askAndHideAnswer') - ->with($this->equalTo($expectedQuestion)) - ->will($this->returnValue("TEST_QUERY_PASSWORD")); + ->method('askAndHideAnswer') + ->with($this->equalTo($expectedQuestion)) + ->will($this->returnValue("TEST_QUERY_PASSWORD")); $password = $this->perforce->queryP4Password($io); $this->assertEquals("TEST_QUERY_PASSWORD", $password); } - public function testWriteP4ClientSpecWithoutStream() { + public function testWriteP4ClientSpecWithoutStream() + { $stream = fopen("php://memory", 'w+'); $this->perforce->writeClientSpecToFile($stream); rewind($stream); - $expectedArray = $this->getExpectedClientSpec(FALSE); + $expectedArray = $this->getExpectedClientSpec(false); try { foreach ($expectedArray as $expected) { $this->assertStringStartsWith($expected, fgets($stream)); @@ -245,14 +301,15 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { fclose($stream); } - public function testWriteP4ClientSpecWithStream() { + public function testWriteP4ClientSpecWithStream() + { $this->setPerforceToStream(); $stream = fopen("php://memory", 'w+'); $this->perforce->writeClientSpecToFile($stream); rewind($stream); - $expectedArray = $this->getExpectedClientSpec(TRUE); + $expectedArray = $this->getExpectedClientSpec(true); try { foreach ($expectedArray as $expected) { $this->assertStringStartsWith($expected, fgets($stream)); @@ -265,17 +322,19 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { fclose($stream); } - public function testIsLoggedIn() { + public function testIsLoggedIn() + { $expectedCommand = "p4 -u user -p port login -s"; $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand), $this->equalTo(null)) - ->will($this->returnValue(0)); + ->method('execute') + ->with($this->equalTo($expectedCommand), $this->equalTo(null)) + ->will($this->returnValue(0)); $this->perforce->isLoggedIn(); } - public function testConnectClient() { + public function testConnectClient() + { $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot -p port client -i < path/composer_perforce_TEST_depot.p4.spec"; $this->processExecutor->expects($this->at(0)) ->method('execute') @@ -285,70 +344,112 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->perforce->connectClient(); } - public function testGetBranchesWithStream() { + public function testGetBranchesWithStream() + { $this->setPerforceToStream(); $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot_branch -p port streams //depot/..."; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) - ->will($this->returnCallback(function($command, &$output) {$output = "Stream //depot/branch mainline none 'branch'\n"; return true;})); + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = "Stream //depot/branch mainline none 'branch'\n"; + return true; + } + ) + ); $branches = $this->perforce->getBranches(); $this->assertEquals("//depot/branch", $branches['master']); } - public function testGetBranchesWithoutStream() { + public function testGetBranchesWithoutStream() + { $branches = $this->perforce->getBranches(); $this->assertEquals("//depot", $branches['master']); } - public function testGetTagsWithoutStream() { + public function testGetTagsWithoutStream() + { $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot -p port labels"; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) - ->will($this->returnCallback(function($command, &$output) {$output = "Label 0.0.1 2013/07/31 'First Label!'\nLabel 0.0.2 2013/08/01 'Second Label!'\n"; return true;})); + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = "Label 0.0.1 2013/07/31 'First Label!'\nLabel 0.0.2 2013/08/01 'Second Label!'\n"; + return true; + } + ) + ); $tags = $this->perforce->getTags(); $this->assertEquals("//depot@0.0.1", $tags['0.0.1']); $this->assertEquals("//depot@0.0.2", $tags['0.0.2']); } - public function testGetTagsWithStream() { + public function testGetTagsWithStream() + { $this->setPerforceToStream(); $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot_branch -p port labels"; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) - ->will($this->returnCallback(function($command, &$output) {$output = "Label 0.0.1 2013/07/31 'First Label!'\nLabel 0.0.2 2013/08/01 'Second Label!'\n"; return true;})); + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = "Label 0.0.1 2013/07/31 'First Label!'\nLabel 0.0.2 2013/08/01 'Second Label!'\n"; + return true; + } + ) + ); $tags = $this->perforce->getTags(); $this->assertEquals("//depot/branch@0.0.1", $tags['0.0.1']); $this->assertEquals("//depot/branch@0.0.2", $tags['0.0.2']); } - public function testCheckStreamWithoutStream() { + public function testCheckStreamWithoutStream() + { $result = $this->perforce->checkStream("depot"); $this->assertFalse($result); $this->assertFalse($this->perforce->isStream()); } - public function testCheckStreamWithStream() { + public function testCheckStreamWithStream() + { $this->processExecutor->expects($this->any())->method('execute') - ->will($this->returnCallback(function($command, &$output) {$output = "Depot depot 2013/06/25 stream /p4/1/depots/depot/... 'Created by Me'"; return true;})); + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = "Depot depot 2013/06/25 stream /p4/1/depots/depot/... 'Created by Me'"; + return true; + } + ) + ); $result = $this->perforce->checkStream("depot"); $this->assertTrue($result); $this->assertTrue($this->perforce->isStream()); } - public function testGetComposerInformationWithoutLabelWithoutStream() { + public function testGetComposerInformationWithoutLabelWithoutStream() + { $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot -p port print //depot/composer.json"; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) - ->will($this->returnCallback(function($command, &$output) {$output = PerforceTest::getComposerJson(); return true;})); + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = PerforceTest::getComposerJson(); + return true; + } + ) + ); $result = $this->perforce->getComposerInformation("//depot"); $expected = array( @@ -360,18 +461,33 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->assertEquals($expected, $result); } - public function testGetComposerInformationWithLabelWithoutStream() { + public function testGetComposerInformationWithLabelWithoutStream() + { $expectedCommand = "p4 -u user -p port files //depot/composer.json@0.0.1"; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) - ->will($this->returnCallback(function($command, &$output) {$output = "//depot/composer.json#1 - branch change 10001 (text)"; return true;})); + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = "//depot/composer.json#1 - branch change 10001 (text)"; + return true; + } + ) + ); $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot -p port print //depot/composer.json@10001"; $this->processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) - ->will($this->returnCallback(function($command, &$output) {$output = PerforceTest::getComposerJson(); return true;})); + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = PerforceTest::getComposerJson(); + return true; + } + ) + ); $result = $this->perforce->getComposerInformation("//depot@0.0.1"); @@ -384,14 +500,22 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->assertEquals($expected, $result); } - public function testGetComposerInformationWithoutLabelWithStream() { + public function testGetComposerInformationWithoutLabelWithStream() + { $this->setPerforceToStream(); $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot_branch -p port print //depot/branch/composer.json"; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) - ->will($this->returnCallback(function($command, &$output) {$output = PerforceTest::getComposerJson(); return true;})); + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = PerforceTest::getComposerJson(); + return true; + } + ) + ); $result = $this->perforce->getComposerInformation("//depot/branch"); @@ -404,19 +528,34 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->assertEquals($expected, $result); } - public function testGetComposerInformationWithLabelWithStream() { + public function testGetComposerInformationWithLabelWithStream() + { $this->setPerforceToStream(); $expectedCommand = "p4 -u user -p port files //depot/branch/composer.json@0.0.1"; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) - ->will($this->returnCallback(function($command, &$output) {$output = "//depot/composer.json#1 - branch change 10001 (text)"; return true;})); + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = "//depot/composer.json#1 - branch change 10001 (text)"; + return true; + } + ) + ); $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot_branch -p port print //depot/branch/composer.json@10001"; $this->processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) - ->will($this->returnCallback(function($command, &$output) {$output = PerforceTest::getComposerJson(); return true;})); + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = PerforceTest::getComposerJson(); + return true; + } + ) + ); $result = $this->perforce->getComposerInformation("//depot/branch@0.0.1"); @@ -429,7 +568,8 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->assertEquals($expected, $result); } - public function testSyncCodeBaseWithoutStream() { + public function testSyncCodeBaseWithoutStream() + { $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot -p port sync -f @label"; $this->processExecutor->expects($this->at(1)) ->method('execute') @@ -439,44 +579,48 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->perforce->syncCodeBase("label"); } - public function testSyncCodeBaseWithStream() { + public function testSyncCodeBaseWithStream() + { $this->setPerforceToStream(); $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot_branch -p port sync -f @label"; - $this->processExecutor->expects($this->at(1)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will($this->returnValue(0)); + $this->processExecutor->expects($this->at(1)) + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnValue(0)); $this->perforce->syncCodeBase("label"); } - public function testCheckServerExists() { + public function testCheckServerExists() + { $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); $expectedCommand = "p4 -p perforce.does.exist:port info -s"; $processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand), $this->equalTo(null)) - ->will($this->returnValue(0)); + ->method('execute') + ->with($this->equalTo($expectedCommand), $this->equalTo(null)) + ->will($this->returnValue(0)); $result = $this->perforce->checkServerExists("perforce.does.exist:port", $processExecutor); $this->assertTrue($result); } - public function testCheckServerExistsWithFailure() { + public function testCheckServerExistsWithFailure() + { $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); $expectedCommand = "p4 -p perforce.does.not.exist:port info -s"; $processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand), $this->equalTo(null)) - ->will($this->returnValue("Perforce client error:")); + ->method('execute') + ->with($this->equalTo($expectedCommand), $this->equalTo(null)) + ->will($this->returnValue("Perforce client error:")); $result = $this->perforce->checkServerExists("perforce.does.not.exist:port", $processExecutor); $this->assertTrue($result); } - public static function getComposerJson() { + public static function getComposerJson() + { $composer_json = array( '{', '"name": "test/perforce",', @@ -492,7 +636,8 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { return implode($composer_json); } - private function getExpectedClientSpec($withStream) { + private function getExpectedClientSpec($withStream) + { $expectedArray = array( "Client: composer_perforce_TEST_depot", "\n", @@ -516,15 +661,15 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { if ($withStream) { $expectedArray[] = "Stream:"; $expectedArray[] = " //depot/branch"; - } - else { + } else { $expectedArray[] = "View: //depot/... //composer_perforce_TEST_depot/depot/..."; } return $expectedArray; } - private function setPerforceToStream(){ + private function setPerforceToStream() + { $this->perforce->setStream("//depot/branch"); } } From d77bd493011665dbbd85dc8ab544462ff67118ad Mon Sep 17 00:00:00 2001 From: mwhittom Date: Wed, 4 Sep 2013 09:30:23 -0500 Subject: [PATCH 056/238] Replaced RemoteFileSystemTest with version from main branch --- .../Test/Util/RemoteFilesystemTest.php | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/Composer/Test/Util/RemoteFilesystemTest.php b/tests/Composer/Test/Util/RemoteFilesystemTest.php index 39a3bb63d..eb8ebc07e 100644 --- a/tests/Composer/Test/Util/RemoteFilesystemTest.php +++ b/tests/Composer/Test/Util/RemoteFilesystemTest.php @@ -21,9 +21,9 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase { $io = $this->getMock('Composer\IO\IOInterface'); $io - ->expects($this->once()) - ->method('hasAuthentication') - ->will($this->returnValue(false)) + ->expects($this->once()) + ->method('hasAuthentication') + ->will($this->returnValue(false)) ; $res = $this->callGetOptionsForUrl($io, array('http://example.org', array())); @@ -42,14 +42,14 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase { $io = $this->getMock('Composer\IO\IOInterface'); $io - ->expects($this->once()) - ->method('hasAuthentication') - ->will($this->returnValue(true)) + ->expects($this->once()) + ->method('hasAuthentication') + ->will($this->returnValue(true)) ; $io - ->expects($this->once()) - ->method('getAuthentication') - ->will($this->returnValue(array('username' => 'login', 'password' => 'password'))) + ->expects($this->once()) + ->method('getAuthentication') + ->will($this->returnValue(array('username' => 'login', 'password' => 'password'))) ; $options = $this->callGetOptionsForUrl($io, array('http://example.org', array())); @@ -67,9 +67,9 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase { $io = $this->getMock('Composer\IO\IOInterface'); $io - ->expects($this->once()) - ->method('hasAuthentication') - ->will($this->returnValue(true)) + ->expects($this->once()) + ->method('hasAuthentication') + ->will($this->returnValue(true)) ; $streamOptions = array('ssl' => array( @@ -84,9 +84,9 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase { $io = $this->getMock('Composer\IO\IOInterface'); $io - ->expects($this->once()) - ->method('hasAuthentication') - ->will($this->returnValue(true)) + ->expects($this->once()) + ->method('hasAuthentication') + ->will($this->returnValue(true)) ; $streamOptions = array('http' => array( @@ -118,8 +118,8 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase { $io = $this->getMock('Composer\IO\IOInterface'); $io - ->expects($this->once()) - ->method('overwrite') + ->expects($this->once()) + ->method('overwrite') ; $fs = new RemoteFilesystem($io); @@ -149,8 +149,8 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase { $io = $this->getMock('Composer\IO\IOInterface'); $io->expects($this->once()) - ->method('setAuthentication') - ->with($this->equalTo('example.com'), $this->equalTo('user'), $this->equalTo('pass')); + ->method('setAuthentication') + ->with($this->equalTo('example.com'), $this->equalTo('user'), $this->equalTo('pass')); $fs = new RemoteFilesystem($io); try { @@ -202,4 +202,4 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase $attr->setAccessible(true); $attr->setValue($object, $value); } -} \ No newline at end of file +} From d00ca4bcdb35ad5b0ee243244c7f17fd3b0981ca Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 5 Sep 2013 14:30:03 +0200 Subject: [PATCH 057/238] Add a Command event triggered by all comands which load plugins --- src/Composer/Command/DependsCommand.php | 9 +- src/Composer/Command/DiagnoseCommand.php | 5 ++ src/Composer/Command/DumpAutoloadCommand.php | 6 ++ src/Composer/Command/InstallCommand.php | 6 ++ src/Composer/Command/LicensesCommand.php | 6 ++ src/Composer/Command/RequireCommand.php | 6 ++ src/Composer/Command/SearchCommand.php | 7 ++ src/Composer/Command/ShowCommand.php | 7 ++ src/Composer/Command/StatusCommand.php | 6 ++ src/Composer/Command/UpdateCommand.php | 6 ++ src/Composer/Plugin/CommandEvent.php | 87 ++++++++++++++++++++ src/Composer/Plugin/PluginEvents.php | 10 +++ 12 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 src/Composer/Plugin/CommandEvent.php diff --git a/src/Composer/Command/DependsCommand.php b/src/Composer/Command/DependsCommand.php index 5603a17c0..755b40b90 100644 --- a/src/Composer/Command/DependsCommand.php +++ b/src/Composer/Command/DependsCommand.php @@ -13,6 +13,8 @@ namespace Composer\Command; use Composer\DependencyResolver\Pool; +use Composer\Plugin\CommandEvent; +use Composer\Plugin\PluginEvents; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; @@ -50,7 +52,12 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { - $repo = $this->getComposer()->getRepositoryManager()->getLocalRepository(); + $composer = $this->getComposer(); + + $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'depends', $input, $output); + $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); + + $repo = $composer->getRepositoryManager()->getLocalRepository(); $needle = $input->getArgument('package'); $pool = new Pool(); diff --git a/src/Composer/Command/DiagnoseCommand.php b/src/Composer/Command/DiagnoseCommand.php index 57ed3a003..63ce4ee19 100644 --- a/src/Composer/Command/DiagnoseCommand.php +++ b/src/Composer/Command/DiagnoseCommand.php @@ -15,6 +15,8 @@ namespace Composer\Command; use Composer\Composer; use Composer\Factory; use Composer\Downloader\TransportException; +use Composer\Plugin\CommandEvent; +use Composer\Plugin\PluginEvents; use Composer\Util\ConfigValidator; use Composer\Util\RemoteFilesystem; use Composer\Util\StreamContextFactory; @@ -64,6 +66,9 @@ EOT $composer = $this->getComposer(false); if ($composer) { + $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output); + $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); + $output->write('Checking composer.json: '); $this->outputResult($output, $this->checkComposerSchema()); } diff --git a/src/Composer/Command/DumpAutoloadCommand.php b/src/Composer/Command/DumpAutoloadCommand.php index 4855a409d..3e1541590 100644 --- a/src/Composer/Command/DumpAutoloadCommand.php +++ b/src/Composer/Command/DumpAutoloadCommand.php @@ -12,6 +12,8 @@ namespace Composer\Command; +use Composer\Plugin\CommandEvent; +use Composer\Plugin\PluginEvents; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -42,6 +44,10 @@ EOT $output->writeln('Generating autoload files'); $composer = $this->getComposer(); + + $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'dump-autoload', $input, $output); + $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); + $installationManager = $composer->getInstallationManager(); $localRepo = $composer->getRepositoryManager()->getLocalRepository(); $package = $composer->getPackage(); diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index adc2ca595..6138009a3 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -13,6 +13,8 @@ namespace Composer\Command; use Composer\Installer; +use Composer\Plugin\CommandEvent; +use Composer\Plugin\PluginEvents; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -66,6 +68,10 @@ EOT $composer = $this->getComposer(true, $input->getOption('no-plugins')); $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress')); $io = $this->getIO(); + + $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output); + $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); + $install = Installer::create($io, $composer); $preferSource = false; diff --git a/src/Composer/Command/LicensesCommand.php b/src/Composer/Command/LicensesCommand.php index e30e371c2..a927156c4 100644 --- a/src/Composer/Command/LicensesCommand.php +++ b/src/Composer/Command/LicensesCommand.php @@ -15,6 +15,8 @@ namespace Composer\Command; use Composer\Package\PackageInterface; use Composer\Json\JsonFile; use Composer\Package\Version\VersionParser; +use Composer\Plugin\CommandEvent; +use Composer\Plugin\PluginEvents; use Symfony\Component\Console\Helper\TableHelper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; @@ -46,6 +48,10 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { $composer = $this->getComposer(); + + $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'licenses', $input, $output); + $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); + $root = $composer->getPackage(); $repo = $composer->getRepositoryManager()->getLocalRepository(); diff --git a/src/Composer/Command/RequireCommand.php b/src/Composer/Command/RequireCommand.php index fb4f9a9b1..11951dd08 100644 --- a/src/Composer/Command/RequireCommand.php +++ b/src/Composer/Command/RequireCommand.php @@ -21,6 +21,8 @@ use Composer\Installer; use Composer\Json\JsonFile; use Composer\Json\JsonManipulator; use Composer\Package\Version\VersionParser; +use Composer\Plugin\CommandEvent; +use Composer\Plugin\PluginEvents; /** * @author Jérémy Romey @@ -106,6 +108,10 @@ EOT $composer = $this->getComposer(); $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress')); $io = $this->getIO(); + + $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output); + $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); + $install = Installer::create($io, $composer); $install diff --git a/src/Composer/Command/SearchCommand.php b/src/Composer/Command/SearchCommand.php index a212eb329..b9aaa8d74 100644 --- a/src/Composer/Command/SearchCommand.php +++ b/src/Composer/Command/SearchCommand.php @@ -20,6 +20,8 @@ use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryInterface; use Composer\Factory; +use Composer\Plugin\CommandEvent; +use Composer\Plugin\PluginEvents; /** * @author Robert Schönthal @@ -65,6 +67,11 @@ EOT $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos)); } + if ($composer) { + $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'search', $input, $output); + $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); + } + $onlyName = $input->getOption('only-name'); $flags = $onlyName ? RepositoryInterface::SEARCH_NAME : RepositoryInterface::SEARCH_FULLTEXT; diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index a54de99c7..50dabd74a 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -18,6 +18,8 @@ use Composer\DependencyResolver\DefaultPolicy; use Composer\Factory; use Composer\Package\CompletePackageInterface; use Composer\Package\Version\VersionParser; +use Composer\Plugin\CommandEvent; +use Composer\Plugin\PluginEvents; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; @@ -94,6 +96,11 @@ EOT $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos)); } + if ($composer) { + $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'show', $input, $output); + $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); + } + // show single package or single version if ($input->getArgument('package') || !empty($package)) { $versions = array(); diff --git a/src/Composer/Command/StatusCommand.php b/src/Composer/Command/StatusCommand.php index 5151d734b..5edf3b61e 100644 --- a/src/Composer/Command/StatusCommand.php +++ b/src/Composer/Command/StatusCommand.php @@ -17,6 +17,8 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Composer\Downloader\ChangeReportInterface; use Composer\Downloader\VcsDownloader; +use Composer\Plugin\CommandEvent; +use Composer\Plugin\PluginEvents; use Composer\Script\ScriptEvents; /** @@ -46,6 +48,10 @@ EOT { // init repos $composer = $this->getComposer(); + + $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'status', $input, $output); + $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); + $installedRepo = $composer->getRepositoryManager()->getLocalRepository(); $dm = $composer->getDownloadManager(); diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index 728fadd24..ceabf7ff4 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -13,6 +13,8 @@ namespace Composer\Command; use Composer\Installer; +use Composer\Plugin\CommandEvent; +use Composer\Plugin\PluginEvents; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; @@ -70,6 +72,10 @@ EOT $composer = $this->getComposer(true, $input->getOption('no-plugins')); $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress')); $io = $this->getIO(); + + $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output); + $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); + $install = Installer::create($io, $composer); $preferSource = false; diff --git a/src/Composer/Plugin/CommandEvent.php b/src/Composer/Plugin/CommandEvent.php new file mode 100644 index 000000000..ac2ad2551 --- /dev/null +++ b/src/Composer/Plugin/CommandEvent.php @@ -0,0 +1,87 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Plugin; + +use Composer\IO\IOInterface; +use Composer\EventDispatcher\Event; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * An event for all commands. + * + * @author Nils Adermann + */ +class CommandEvent extends Event +{ + /** + * @var string + */ + private $commandName; + + /** + * @var InputInterface + */ + private $input; + + /** + * @var OutputInterface + */ + private $output; + + /** + * Constructor. + * + * @param string $name The event name + * @param string $commandName The command name + * @param InputInterface $input + * @param OutputInterface $output + */ + public function __construct($name, $commandName, $input, $output) + { + parent::__construct($name); + $this->commandName = $commandName; + $this->input = $input; + $this->output = $output; + } + + /** + * Returns the command input interface + * + * @return InputInterface + */ + public function getInput() + { + return $this->input; + } + + /** + * Retrieves the command output interface + * + * @return OutputInterface + */ + public function getOutput() + { + return $this->output; + } + + /** + * Retrieves the name of the command being run + * + * @return string + */ + public function getCommandName() + { + return $this->commandName; + } +} diff --git a/src/Composer/Plugin/PluginEvents.php b/src/Composer/Plugin/PluginEvents.php index cbf9b1148..ce9efdef2 100644 --- a/src/Composer/Plugin/PluginEvents.php +++ b/src/Composer/Plugin/PluginEvents.php @@ -19,6 +19,16 @@ namespace Composer\Plugin; */ class PluginEvents { + /** + * The COMMAND event occurs as a command begins + * + * The event listener method receives a + * Composer\Plugin\CommandEvent instance. + * + * @var string + */ + const COMMAND = 'command'; + /** * The PRE_FILE_DOWNLOAD event occurs before downloading a file * From 6c2e998e4029cb4a9d6ec433a5b9975cc5e6e8b6 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 5 Sep 2013 14:32:09 +0200 Subject: [PATCH 058/238] Add missing use statement --- tests/Composer/Test/Plugin/PluginInstallerTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Composer/Test/Plugin/PluginInstallerTest.php b/tests/Composer/Test/Plugin/PluginInstallerTest.php index 1e67eafe1..1c2a4cf31 100644 --- a/tests/Composer/Test/Plugin/PluginInstallerTest.php +++ b/tests/Composer/Test/Plugin/PluginInstallerTest.php @@ -18,6 +18,7 @@ use Composer\Installer\PluginInstaller; use Composer\Package\Loader\JsonLoader; use Composer\Package\Loader\ArrayLoader; use Composer\Package\PackageInterface; +use Composer\Plugin\PluginManager; use Composer\Autoload\AutoloadGenerator; class PluginInstallerTest extends \PHPUnit_Framework_TestCase @@ -63,7 +64,7 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase $this->composer->setRepositoryManager($rm); $this->composer->setAutoloadGenerator($this->autoloadGenerator); - $this->pm = new \Composer\Plugin\PluginManager($this->composer, $this->io); + $this->pm = new PluginManager($this->composer, $this->io); $this->composer->setPluginManager($this->pm); $config->merge(array( From 92b1ee2f7ad1c4c823acd96b37dd1986f00bdf02 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 5 Sep 2013 15:47:05 +0200 Subject: [PATCH 059/238] Add a composer-plugin-api platform package and plugins must require it --- src/Composer/Plugin/PluginInterface.php | 7 ++++++ src/Composer/Plugin/PluginManager.php | 23 +++++++++++++++++++ .../Repository/PlatformRepository.php | 8 +++++++ 3 files changed, 38 insertions(+) diff --git a/src/Composer/Plugin/PluginInterface.php b/src/Composer/Plugin/PluginInterface.php index 302175a25..3a33672a6 100644 --- a/src/Composer/Plugin/PluginInterface.php +++ b/src/Composer/Plugin/PluginInterface.php @@ -22,6 +22,13 @@ use Composer\IO\IOInterface; */ interface PluginInterface { + /** + * Version number of the fake composer-plugin-api package + * + * @var string + */ + const PLUGIN_API_VERSION = '1.0.0'; + /** * Apply plugin modifications to composer * diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index c67ea9622..dacf9bd57 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -16,9 +16,11 @@ use Composer\Composer; use Composer\EventDispatcher\EventSubscriberInterface; use Composer\IO\IOInterface; use Composer\Package\Package; +use Composer\Package\Version\VersionParser; use Composer\Repository\RepositoryInterface; use Composer\Package\PackageInterface; use Composer\Package\Link; +use Composer\Package\LinkConstraint\VersionConstraint; use Composer\DependencyResolver\Pool; /** @@ -31,6 +33,7 @@ class PluginManager protected $composer; protected $io; protected $globalRepository; + protected $versionParser; protected $plugins = array(); @@ -46,6 +49,7 @@ class PluginManager $this->composer = $composer; $this->io = $io; $this->globalRepository = $globalRepository; + $this->versionParser = new VersionParser(); } /** @@ -92,6 +96,25 @@ class PluginManager { foreach ($repo->getPackages() as $package) { if ('composer-plugin' === $package->getType() || 'composer-installer' === $package->getType()) { + $requiresComposer = null; + foreach ($package->getRequires() as $link) { + if ($link->getTarget() == 'composer-plugin-api') { + $requiresComposer = $link->getConstraint(); + } + } + + if (!$requiresComposer) { + throw new \RuntimeException("Plugin ".$package->getName()." is missing a require statement for a version of the composer-plugin-api package."); + } + + if (!$requiresComposer->matches(new VersionConstraint('==', $this->versionParser->normalize(PluginInterface::PLUGIN_API_VERSION)))) { + $this->io->write("The plugin ".$package->getName()." requires a version of composer-plugin-api that does not match your composer installation. You may need to run composer update with the '--no-plugins' option."); + } + + $this->registerPackage($package); + } + // Backward compatability + if ('composer-installer' === $package->getType()) { $this->registerPackage($package); } } diff --git a/src/Composer/Repository/PlatformRepository.php b/src/Composer/Repository/PlatformRepository.php index 3f208aae0..7c4b72673 100644 --- a/src/Composer/Repository/PlatformRepository.php +++ b/src/Composer/Repository/PlatformRepository.php @@ -14,6 +14,7 @@ namespace Composer\Repository; use Composer\Package\CompletePackage; use Composer\Package\Version\VersionParser; +use Composer\Plugin\PluginInterface; /** * @author Jordi Boggiano @@ -28,6 +29,12 @@ class PlatformRepository extends ArrayRepository $versionParser = new VersionParser(); + $prettyVersion = PluginInterface::PLUGIN_API_VERSION; + $version = $versionParser->normalize($prettyVersion); + $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion); + $composerPluginApi->setDescription('The Composer Plugin API'); + parent::addPackage($composerPluginApi); + try { $prettyVersion = PHP_VERSION; $version = $versionParser->normalize($prettyVersion); @@ -36,6 +43,7 @@ class PlatformRepository extends ArrayRepository $version = $versionParser->normalize($prettyVersion); } + $php = new CompletePackage('php', $version, $prettyVersion); $php->setDescription('The PHP interpreter'); parent::addPackage($php); From 98e5eabf759baf103e657e6e098ff48a0f3b55a7 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 5 Sep 2013 20:08:17 +0200 Subject: [PATCH 060/238] Document how to write and use plugins --- doc/articles/custom-installers.md | 70 +++++++++----- doc/articles/plugins.md | 147 ++++++++++++++++++++++++++++++ 2 files changed, 194 insertions(+), 23 deletions(-) create mode 100644 doc/articles/plugins.md diff --git a/doc/articles/custom-installers.md b/doc/articles/custom-installers.md index 1eb55436e..7c7117248 100644 --- a/doc/articles/custom-installers.md +++ b/doc/articles/custom-installers.md @@ -29,8 +29,8 @@ An example use-case would be: > phpDocumentor features Templates that need to be installed outside of the > default /vendor folder structure. As such they have chosen to adopt the -> `phpdocumentor-template` [type][1] and create a Custom Installer to send -> these templates to the correct folder. +> `phpdocumentor-template` [type][1] and create a plugin providing the Custom +> Installer to send these templates to the correct folder. An example composer.json of such a template package would be: @@ -38,23 +38,24 @@ An example composer.json of such a template package would be: "name": "phpdocumentor/template-responsive", "type": "phpdocumentor-template", "require": { - "phpdocumentor/template-installer": "*" + "phpdocumentor/template-installer-plugin": "*" } } > **IMPORTANT**: to make sure that the template installer is present at the > time the template package is installed, template packages should require -> the installer package. +> the plugin package. ## Creating an Installer A Custom Installer is defined as a class that implements the -[`Composer\Installer\InstallerInterface`][3] and is contained in a Composer -package that has the [type][1] `composer-installer`. +[`Composer\Installer\InstallerInterface`][3] and is usually distributed in a +Composer Plugin. -A basic Installer would thus compose of two files: +A basic Installer Plugin would thus compose of three files: 1. the package file: composer.json +2. The Plugin class, e.g.: `My\Project\Composer\Plugin.php`, containing a class that implements `Composer\Plugin\PluginInterface`. 2. The Installer class, e.g.: `My\Project\Composer\Installer.php`, containing a class that implements `Composer\Installer\InstallerInterface`. ### composer.json @@ -62,35 +63,57 @@ A basic Installer would thus compose of two files: The package file is the same as any other package file but with the following requirements: -1. the [type][1] attribute must be `composer-installer`. +1. the [type][1] attribute must be `composer-plugin`. 2. the [extra][2] attribute must contain an element `class` defining the - class name of the installer (including namespace). If a package contains - multiple installers this can be array of class names. + class name of the plugin (including namespace). If a package contains + multiple plugins this can be array of class names. Example: { - "name": "phpdocumentor/template-installer", - "type": "composer-installer", + "name": "phpdocumentor/template-installer-plugin", + "type": "composer-installer-plugin", "license": "MIT", "autoload": { "psr-0": {"phpDocumentor\\Composer": "src/"} }, "extra": { - "class": "phpDocumentor\\Composer\\TemplateInstaller" + "class": "phpDocumentor\\Composer\\TemplateInstallerPlugin" + } + } + +### The Plugin class + +The class defining the Composer plugin must implement the +[`Composer\Plugin\PluginInterface`][3]. It can then register the Custom +Installer in its `activate()` method. + +The class may be placed in any location and have any name, as long as it is +autoloadable and matches the `extra.class` element in the package definition. + +Example: + + namespace phpDocumentor\Composer; + + use Composer\Composer; + use Composer\IO\IOInterface; + use Composer\Plugin\PluginInterface + + class TemplateInstallerPlugin implements PluginInterface + { + public function activate(Composer $composer, IOInterface $io) + { + $installer = new TemplateInstaller($io, $composer); + $composer->getInstallationManager()->addInstaller($installer); } } ### The Custom Installer class The class that executes the custom installation should implement the -[`Composer\Installer\InstallerInterface`][3] (or extend another installer that -implements that interface). - -The class may be placed in any location and have any name, as long as it is -autoloadable and matches the `extra.class` element in the package definition. -It will also define the [type][1] string as it will be recognized by packages -that will use this installer in the `supports()` method. +[`Composer\Installer\InstallerInterface`][4] (or extend another installer that +implements that interface). It defines the [type][1] string as it will be +recognized by packages that will use this installer in the `supports()` method. > **NOTE**: _choose your [type][1] name carefully, it is recommended to follow > the format: `vendor-type`_. For example: `phpdocumentor-template`. @@ -146,7 +169,7 @@ Example: } The example demonstrates that it is quite simple to extend the -[`Composer\Installer\LibraryInstaller`][4] class to strip a prefix +[`Composer\Installer\LibraryInstaller`][5] class to strip a prefix (`phpdocumentor/template-`) and use the remaining part to assemble a completely different installation path. @@ -155,5 +178,6 @@ different installation path. [1]: ../04-schema.md#type [2]: ../04-schema.md#extra -[3]: https://github.com/composer/composer/blob/master/src/Composer/Installer/InstallerInterface.php -[4]: https://github.com/composer/composer/blob/master/src/Composer/Installer/LibraryInstaller.php +[3]: https://github.com/composer/composer/blob/master/src/Composer/Plugin/PluginInterface.php +[4]: https://github.com/composer/composer/blob/master/src/Composer/Installer/InstallerInterface.php +[5]: https://github.com/composer/composer/blob/master/src/Composer/Installer/LibraryInstaller.php diff --git a/doc/articles/plugins.md b/doc/articles/plugins.md new file mode 100644 index 000000000..57296f8fe --- /dev/null +++ b/doc/articles/plugins.md @@ -0,0 +1,147 @@ + + +# Setting up and using plugins + +## Synopsis + +You may wish to alter or expand Composer's functionality with your own. For +example if your environment poses special requirements on the behaviour of +Composer which do not apply to the majority of its users or if you wish to +accomplish something with composer in a way that is not desired by most users. + +In these cases you could consider creating a plugin to handle your +specific logic. + +## Creating a Plugin + +A plugin is a regular composer package which ships its code as part of the +package and may also depend on further packages. + +### Plugin Package + +The package file is the same as any other package file but with the following +requirements: + +1. the [type][1] attribute must be `composer-plugin`. +2. the [extra][2] attribute must contain an element `class` defining the + class name of the plugin (including namespace). If a package contains + multiple plugins this can be array of class names. + +Additionally you must require the special package called `composer-plugin-api` +to define which composer API versions your plugin is compatible with. The +current composer plugin API version is 1.0.0. + +For example + + { + "name": "my/plugin-package", + "type": "composer-plugin", + "require": { + "composer-plugin-api": "1.0.0" + } + } + +### Plugin Class + +Every plugin has to supply a class which implements the +[`Composer\Plugin\PluginInterface`][3]. The `activate()` method of the plugin +is called after the plugin is loaded and receives an instance of +[`Composer\Composer`][4] as well as an instance of +[`Composer\IO\IOInterface`][5]. Using these two objects all configuration can +be read and all internal objects and state can be manipulated as desired. + +Example: + + namespace phpDocumentor\Composer; + + use Composer\Composer; + use Composer\IO\IOInterface; + use Composer\Plugin\PluginInterface + + class TemplateInstallerPlugin implements PluginInterface + { + public function activate(Composer $composer, IOInterface $io) + { + $installer = new TemplateInstaller($io, $composer); + $composer->getInstallationManager()->addInstaller($installer); + } + } + +## Event Handler + +Furthermore plugins may implement the +[`Composer\EventDispatcher\EventSubscriberInterface`][6] in order to have its +event handlers automatically registered with the `EventDispatcher` when the +plugin is loaded. + +The events available for plugins are: + +* **COMMAND**, is called at the beginning of all commands that load plugins. + It provides you with access to the input and output objects of the program. +* **PRE_FILE_DOWNLOAD**, is triggered before files are downloaded and allows + you to manipulate the `RemoteFilesystem` object prior to downloading files + based on the URL to be downloaded. + +Example: + + namespace Naderman\Composer\AWS; + + use Composer\Composer; + use Composer\EventDispatcher\EventSubscriberInterface; + use Composer\IO\IOInterface; + use Composer\Plugin\PluginInterface; + use Composer\Plugin\PluginEvents; + use Composer\Plugin\PreFileDownloadEvent; + + class AwsPlugin implements PluginInterface, EventSubscriberInterface + { + protected $composer; + protected $io; + + public function activate(Composer $composer, IOInterface $io) + { + $this->composer = $composer; + $this->io = $io; + } + + public static function getSubscribedEvents() + { + return array( + PluginEvents::PRE_FILE_DOWNLOAD => array( + array('onPreFileDownload', 0) + ), + ); + } + + public function onPreFileDownload(PreFileDownloadEvent $event) + { + $protocol = parse_url($event->getProcessedUrl(), PHP_URL_SCHEME); + + if ($protocol === 's3') { + $awsClient = new AwsClient($this->io, $this->composer->getConfig()); + $s3RemoteFilesystem = new S3RemoteFilesystem($this->io, $event->getRemoteFilesystem()->getOptions(), $awsClient); + $event->setRemoteFilesystem($s3RemoteFilesystem); + } + } + } + +## Using Plugins + +Plugin packages are automatically loaded as soon as they are installed and will +be loaded when composer starts up if they are found in the current project's +list of installed packages. Additionally all plugin packages installed in the +`COMPOSER_HOME` directory using the composer global command are loaded before +local project plugins are loaded. + +> You may pass the `--no-plugins` option to composer commands to disable all +> installed commands. This may be particularly helpful if any of the plugins +> causes errors and you wish to update or uninstall it. + +[1]: ../04-schema.md#type +[2]: ../04-schema.md#extra +[3]: https://github.com/composer/composer/blob/master/src/Composer/Plugin/PluginInterface.php +[4]: https://github.com/composer/composer/blob/master/src/Composer/Composer.php +[5]: https://github.com/composer/composer/blob/master/src/Composer/IO/IOInterface.php +[6]: https://github.com/composer/composer/blob/master/src/Composer/EventDispatcher/EventSubscriberInterface.php From f249fd804fee4958d25d2f6428419dfc90be6a6d Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 6 Sep 2013 13:36:02 +0200 Subject: [PATCH 061/238] Correctly require composer plugin api version in test plugins --- tests/Composer/Test/Plugin/Fixtures/plugin-v1/composer.json | 3 +++ tests/Composer/Test/Plugin/Fixtures/plugin-v2/composer.json | 3 +++ tests/Composer/Test/Plugin/Fixtures/plugin-v3/composer.json | 3 +++ tests/Composer/Test/Plugin/Fixtures/plugin-v4/composer.json | 3 +++ 4 files changed, 12 insertions(+) diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v1/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v1/composer.json index 996e5ee3e..efc552956 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v1/composer.json +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v1/composer.json @@ -5,5 +5,8 @@ "autoload": { "psr-0": { "Installer": "" } }, "extra": { "class": "Installer\\Plugin" + }, + "require": { + "composer-plugin-api": "1.0.0" } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v2/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v2/composer.json index c099da413..6947ddd5c 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v2/composer.json +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v2/composer.json @@ -5,5 +5,8 @@ "autoload": { "psr-0": { "Installer": "" } }, "extra": { "class": "Installer\\Plugin2" + }, + "require": { + "composer-plugin-api": "1.0.0" } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v3/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v3/composer.json index 3ba04e6f6..5cb01d019 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v3/composer.json +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v3/composer.json @@ -5,5 +5,8 @@ "autoload": { "psr-0": { "Installer": "" } }, "extra": { "class": "Installer\\Plugin2" + }, + "require": { + "composer-plugin-api": "1.0.0" } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v4/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v4/composer.json index 10387a021..982d34c7b 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v4/composer.json +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v4/composer.json @@ -8,5 +8,8 @@ "Installer\\Plugin1", "Installer\\Plugin2" ] + }, + "require": { + "composer-plugin-api": "1.0.0" } } From 0f9988b0650027827ce87ed0020a43f6740071a0 Mon Sep 17 00:00:00 2001 From: Fabian Vogler Date: Fri, 6 Sep 2013 16:49:01 +0200 Subject: [PATCH 062/238] Documentation fixes for composer-plugin type --- doc/articles/custom-installers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/articles/custom-installers.md b/doc/articles/custom-installers.md index 7c7117248..daaa2c0e8 100644 --- a/doc/articles/custom-installers.md +++ b/doc/articles/custom-installers.md @@ -72,7 +72,7 @@ Example: { "name": "phpdocumentor/template-installer-plugin", - "type": "composer-installer-plugin", + "type": "composer-plugin", "license": "MIT", "autoload": { "psr-0": {"phpDocumentor\\Composer": "src/"} @@ -97,7 +97,7 @@ Example: use Composer\Composer; use Composer\IO\IOInterface; - use Composer\Plugin\PluginInterface + use Composer\Plugin\PluginInterface; class TemplateInstallerPlugin implements PluginInterface { From 7b43d4909cc1fa8029d21651045857a9df8a2e6a Mon Sep 17 00:00:00 2001 From: Fabian Vogler Date: Fri, 6 Sep 2013 17:44:16 +0200 Subject: [PATCH 063/238] Use getPackageBasePath instead of getInstallPath As LibraryInstaller uses getPackageBasePath for uninstall: https://github.com/composer/composer/blob/master/src/Composer/Installer/LibraryInstaller.php#L126 --- doc/articles/custom-installers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/articles/custom-installers.md b/doc/articles/custom-installers.md index daaa2c0e8..a130e4c7c 100644 --- a/doc/articles/custom-installers.md +++ b/doc/articles/custom-installers.md @@ -145,7 +145,7 @@ Example: /** * {@inheritDoc} */ - public function getInstallPath(PackageInterface $package) + public function getPackageBasePath(PackageInterface $package) { $prefix = substr($package->getPrettyName(), 0, 23); if ('phpdocumentor/template-' !== $prefix) { From 07d46aa3c3fb0d91aedd709a0dd739aa7c43f9be Mon Sep 17 00:00:00 2001 From: mwhittom Date: Fri, 6 Sep 2013 12:14:22 -0500 Subject: [PATCH 064/238] Fixed spacing issues for PSR-2 --- src/Composer/Util/Perforce.php | 2 +- .../Downloader/PerforceDownloaderTest.php | 2 +- .../Repository/Vcs/PerforceDriverTest.php | 1 - tests/Composer/Test/Util/PerforceTest.php | 197 +++++++++--------- 4 files changed, 100 insertions(+), 102 deletions(-) diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index d22d3a13c..c61a1472e 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -546,4 +546,4 @@ class Perforce $result = $this->executeCommand($command); return $result; } -} \ No newline at end of file +} diff --git a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php index 557507090..ad9ba2c9b 100644 --- a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php +++ b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php @@ -27,7 +27,7 @@ class PerforceDownloaderTest extends \PHPUnit_Framework_TestCase private $testPath; public static $repository; - function setUp() + private function setUp() { $this->testPath = sys_get_temp_dir() . '/composer-test'; $this->config = new Config(); diff --git a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php index 77c41a0e1..83647aac6 100644 --- a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php @@ -132,4 +132,3 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase $this->assertTrue($result); } } - diff --git a/tests/Composer/Test/Util/PerforceTest.php b/tests/Composer/Test/Util/PerforceTest.php index 0cca37c2e..912523a31 100644 --- a/tests/Composer/Test/Util/PerforceTest.php +++ b/tests/Composer/Test/Util/PerforceTest.php @@ -120,13 +120,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( - $this->returnCallback( - function ($command, &$output) { - $output = "P4USER=TEST_P4VARIABLE_USER\n"; - return true; - } - ) - ); + $this->returnCallback( + function ($command, &$output) { + $output = "P4USER=TEST_P4VARIABLE_USER\n"; + return true; + } + ) + ); $this->perforce->queryP4user($io); $this->assertEquals("TEST_P4VARIABLE_USER", $this->perforce->getUser()); @@ -143,13 +143,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( - $this->returnCallback( - function ($command, &$output) { - $output = "TEST_P4VARIABLE_USER\n"; - return true; - } - ) - ); + $this->returnCallback( + function ($command, &$output) { + $output = "TEST_P4VARIABLE_USER\n"; + return true; + } + ) + ); $this->perforce->queryP4user($io); $this->assertEquals("TEST_P4VARIABLE_USER", $this->perforce->getUser()); @@ -234,13 +234,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( - $this->returnCallback( - function ($command, &$output) { - $output = "P4PASSWD=TEST_P4VARIABLE_PASSWORD\n"; - return true; - } - ) - ); + $this->returnCallback( + function ($command, &$output) { + $output = "P4PASSWD=TEST_P4VARIABLE_PASSWORD\n"; + return true; + } + ) + ); $password = $this->perforce->queryP4Password($io); $this->assertEquals("TEST_P4VARIABLE_PASSWORD", $password); @@ -257,13 +257,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( - $this->returnCallback( - function ($command, &$output) { - $output = "TEST_P4VARIABLE_PASSWORD\n"; - return true; - } - ) - ); + $this->returnCallback( + function ($command, &$output) { + $output = "TEST_P4VARIABLE_PASSWORD\n"; + return true; + } + ) + ); $password = $this->perforce->queryP4Password($io); $this->assertEquals("TEST_P4VARIABLE_PASSWORD", $password); @@ -353,13 +353,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( - $this->returnCallback( - function ($command, &$output) { - $output = "Stream //depot/branch mainline none 'branch'\n"; - return true; - } - ) - ); + $this->returnCallback( + function ($command, &$output) { + $output = "Stream //depot/branch mainline none 'branch'\n"; + return true; + } + ) + ); $branches = $this->perforce->getBranches(); $this->assertEquals("//depot/branch", $branches['master']); @@ -378,13 +378,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( - $this->returnCallback( - function ($command, &$output) { - $output = "Label 0.0.1 2013/07/31 'First Label!'\nLabel 0.0.2 2013/08/01 'Second Label!'\n"; - return true; - } - ) - ); + $this->returnCallback( + function ($command, &$output) { + $output = "Label 0.0.1 2013/07/31 'First Label!'\nLabel 0.0.2 2013/08/01 'Second Label!'\n"; + return true; + } + ) + ); $tags = $this->perforce->getTags(); $this->assertEquals("//depot@0.0.1", $tags['0.0.1']); @@ -400,13 +400,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( - $this->returnCallback( - function ($command, &$output) { - $output = "Label 0.0.1 2013/07/31 'First Label!'\nLabel 0.0.2 2013/08/01 'Second Label!'\n"; - return true; - } - ) - ); + $this->returnCallback( + function ($command, &$output) { + $output = "Label 0.0.1 2013/07/31 'First Label!'\nLabel 0.0.2 2013/08/01 'Second Label!'\n"; + return true; + } + ) + ); $tags = $this->perforce->getTags(); $this->assertEquals("//depot/branch@0.0.1", $tags['0.0.1']); @@ -424,13 +424,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->processExecutor->expects($this->any())->method('execute') ->will( - $this->returnCallback( - function ($command, &$output) { - $output = "Depot depot 2013/06/25 stream /p4/1/depots/depot/... 'Created by Me'"; - return true; - } - ) - ); + $this->returnCallback( + function ($command, &$output) { + $output = "Depot depot 2013/06/25 stream /p4/1/depots/depot/... 'Created by Me'"; + return true; + } + ) + ); $result = $this->perforce->checkStream("depot"); $this->assertTrue($result); $this->assertTrue($this->perforce->isStream()); @@ -443,13 +443,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( - $this->returnCallback( - function ($command, &$output) { - $output = PerforceTest::getComposerJson(); - return true; - } - ) - ); + $this->returnCallback( + function ($command, &$output) { + $output = PerforceTest::getComposerJson(); + return true; + } + ) + ); $result = $this->perforce->getComposerInformation("//depot"); $expected = array( @@ -468,26 +468,26 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( - $this->returnCallback( - function ($command, &$output) { - $output = "//depot/composer.json#1 - branch change 10001 (text)"; - return true; - } - ) - ); + $this->returnCallback( + function ($command, &$output) { + $output = "//depot/composer.json#1 - branch change 10001 (text)"; + return true; + } + ) + ); $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot -p port print //depot/composer.json@10001"; $this->processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( - $this->returnCallback( - function ($command, &$output) { - $output = PerforceTest::getComposerJson(); - return true; - } - ) - ); + $this->returnCallback( + function ($command, &$output) { + $output = PerforceTest::getComposerJson(); + return true; + } + ) + ); $result = $this->perforce->getComposerInformation("//depot@0.0.1"); @@ -509,13 +509,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( - $this->returnCallback( - function ($command, &$output) { - $output = PerforceTest::getComposerJson(); - return true; - } - ) - ); + $this->returnCallback( + function ($command, &$output) { + $output = PerforceTest::getComposerJson(); + return true; + } + ) + ); $result = $this->perforce->getComposerInformation("//depot/branch"); @@ -536,26 +536,26 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( - $this->returnCallback( - function ($command, &$output) { - $output = "//depot/composer.json#1 - branch change 10001 (text)"; - return true; - } - ) - ); + $this->returnCallback( + function ($command, &$output) { + $output = "//depot/composer.json#1 - branch change 10001 (text)"; + return true; + } + ) + ); $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot_branch -p port print //depot/branch/composer.json@10001"; $this->processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( - $this->returnCallback( - function ($command, &$output) { - $output = PerforceTest::getComposerJson(); - return true; - } - ) - ); + $this->returnCallback( + function ($command, &$output) { + $output = PerforceTest::getComposerJson(); + return true; + } + ) + ); $result = $this->perforce->getComposerInformation("//depot/branch@0.0.1"); @@ -673,4 +673,3 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->perforce->setStream("//depot/branch"); } } - From f7d9f3d8b4ace923685e445eccd20a0fbb82b67e Mon Sep 17 00:00:00 2001 From: mwhittom Date: Fri, 6 Sep 2013 12:31:04 -0500 Subject: [PATCH 065/238] Fixed Test method setUp to be protected instead of private. --- tests/Composer/Test/Downloader/PerforceDownloaderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php index ad9ba2c9b..46eec7284 100644 --- a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php +++ b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php @@ -27,7 +27,7 @@ class PerforceDownloaderTest extends \PHPUnit_Framework_TestCase private $testPath; public static $repository; - private function setUp() + protected function setUp() { $this->testPath = sys_get_temp_dir() . '/composer-test'; $this->config = new Config(); From 5be0ba14fe9fa2cf129ab1fc2c189254b0748886 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 6 Sep 2013 14:11:57 +0200 Subject: [PATCH 066/238] Warn about composer-installer type in composer validate --- src/Composer/Util/ConfigValidator.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Composer/Util/ConfigValidator.php b/src/Composer/Util/ConfigValidator.php index 0c234a245..7c6b321e6 100644 --- a/src/Composer/Util/ConfigValidator.php +++ b/src/Composer/Util/ConfigValidator.php @@ -104,6 +104,10 @@ class ConfigValidator ); } + if (!empty($manifest['type']) && $manifest['type'] == 'composer-installer') { + $warnings[] = "The package type 'composer-installer' is deprecated. Please distribute your custom installers as plugins from now on. See http://getcomposer.org/doc/articles/plugins.md for plugin documentation."; + } + try { $loader = new ValidatingArrayLoader(new ArrayLoader()); if (!isset($manifest['version'])) { From f69a47066d7ebbdba397f3fa2e81a103aa7996c7 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 6 Sep 2013 14:15:11 +0200 Subject: [PATCH 067/238] Fix numbering in custom installers article --- doc/articles/custom-installers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/articles/custom-installers.md b/doc/articles/custom-installers.md index a130e4c7c..5e1df0eab 100644 --- a/doc/articles/custom-installers.md +++ b/doc/articles/custom-installers.md @@ -56,7 +56,7 @@ A basic Installer Plugin would thus compose of three files: 1. the package file: composer.json 2. The Plugin class, e.g.: `My\Project\Composer\Plugin.php`, containing a class that implements `Composer\Plugin\PluginInterface`. -2. The Installer class, e.g.: `My\Project\Composer\Installer.php`, containing a class that implements `Composer\Installer\InstallerInterface`. +3. The Installer class, e.g.: `My\Project\Composer\Installer.php`, containing a class that implements `Composer\Installer\InstallerInterface`. ### composer.json From 689e3056faf4a724006a97b51f0cd4777be19282 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 6 Sep 2013 17:45:22 +0200 Subject: [PATCH 068/238] Plugin API requirements should be for plugins only, not installers --- src/Composer/Plugin/PluginManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index dacf9bd57..990096201 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -95,7 +95,7 @@ class PluginManager protected function loadRepository(RepositoryInterface $repo) { foreach ($repo->getPackages() as $package) { - if ('composer-plugin' === $package->getType() || 'composer-installer' === $package->getType()) { + if ('composer-plugin' === $package->getType()) { $requiresComposer = null; foreach ($package->getRequires() as $link) { if ($link->getTarget() == 'composer-plugin-api') { From b6a620865420fcd4460d4fd7f2de80412ea129d2 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 9 Sep 2013 14:56:25 +0200 Subject: [PATCH 069/238] Update deps --- composer.lock | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/composer.lock b/composer.lock index cae3bad07..1cb435053 100644 --- a/composer.lock +++ b/composer.lock @@ -79,17 +79,17 @@ }, { "name": "symfony/console", - "version": "v2.3.3", + "version": "v2.3.4", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "v2.3.3" + "reference": "db78f8ff7fc9e28d25ff9a0bf6ddf9f0e35fbbe3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/v2.3.3", - "reference": "v2.3.3", + "url": "https://api.github.com/repos/symfony/Console/zipball/db78f8ff7fc9e28d25ff9a0bf6ddf9f0e35fbbe3", + "reference": "db78f8ff7fc9e28d25ff9a0bf6ddf9f0e35fbbe3", "shasum": "" }, "require": { @@ -128,21 +128,21 @@ ], "description": "Symfony Console Component", "homepage": "http://symfony.com", - "time": "2013-07-21 12:12:18" + "time": "2013-08-17 16:34:49" }, { "name": "symfony/finder", - "version": "v2.3.3", + "version": "v2.3.4", "target-dir": "Symfony/Component/Finder", "source": { "type": "git", "url": "https://github.com/symfony/Finder.git", - "reference": "v2.3.3" + "reference": "4a0fee5b86f5bbd9dfdc11ec124eba2915737ce1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/v2.3.3", - "reference": "v2.3.3", + "url": "https://api.github.com/repos/symfony/Finder/zipball/4a0fee5b86f5bbd9dfdc11ec124eba2915737ce1", + "reference": "4a0fee5b86f5bbd9dfdc11ec124eba2915737ce1", "shasum": "" }, "require": { @@ -175,21 +175,21 @@ ], "description": "Symfony Finder Component", "homepage": "http://symfony.com", - "time": "2013-07-21 12:12:18" + "time": "2013-08-13 20:18:00" }, { "name": "symfony/process", - "version": "v2.3.3", + "version": "v2.3.4", "target-dir": "Symfony/Component/Process", "source": { "type": "git", "url": "https://github.com/symfony/Process.git", - "reference": "v2.3.3" + "reference": "1e91553e1cedd0b8fb1da6ea4f89b02e21713d5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/v2.3.3", - "reference": "v2.3.3", + "url": "https://api.github.com/repos/symfony/Process/zipball/1e91553e1cedd0b8fb1da6ea4f89b02e21713d5b", + "reference": "1e91553e1cedd0b8fb1da6ea4f89b02e21713d5b", "shasum": "" }, "require": { @@ -222,7 +222,7 @@ ], "description": "Symfony Process Component", "homepage": "http://symfony.com", - "time": "2013-08-02 21:51:01" + "time": "2013-08-22 06:42:25" } ], "packages-dev": [ @@ -595,17 +595,17 @@ }, { "name": "symfony/yaml", - "version": "v2.3.3", + "version": "v2.3.4", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "v2.3.3" + "reference": "5a279f1b5f5e1045a6c432354d9ea727ff3a9847" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/v2.3.3", - "reference": "v2.3.3", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/5a279f1b5f5e1045a6c432354d9ea727ff3a9847", + "reference": "5a279f1b5f5e1045a6c432354d9ea727ff3a9847", "shasum": "" }, "require": { @@ -638,7 +638,7 @@ ], "description": "Symfony Yaml Component", "homepage": "http://symfony.com", - "time": "2013-07-21 12:12:18" + "time": "2013-08-24 15:26:22" } ], "aliases": [ From 0eb28217334e43c98e98f4712a006206c3cd6a60 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 9 Sep 2013 15:10:09 +0200 Subject: [PATCH 070/238] Fix undefined var error, fixes #2241 --- src/Composer/Command/ShowCommand.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index 50dabd74a..ed1b629f0 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -68,8 +68,9 @@ EOT // init repos $platformRepo = new PlatformRepository; + $composer = $this->getComposer(false); if ($input->getOption('self')) { - $package = $this->getComposer(false)->getPackage(); + $package = $this->getComposer()->getPackage(); $repos = $installedRepo = new ArrayRepository(array($package)); } elseif ($input->getOption('platform')) { $repos = $installedRepo = $platformRepo; @@ -77,15 +78,14 @@ EOT $repos = $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository(); } elseif ($input->getOption('available')) { $installedRepo = $platformRepo; - if ($composer = $this->getComposer(false)) { + if ($composer) { $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories()); } else { $defaultRepos = Factory::createDefaultRepositories($this->getIO()); $repos = new CompositeRepository($defaultRepos); $output->writeln('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos))); } - } elseif ($composer = $this->getComposer(false)) { - $composer = $this->getComposer(); + } elseif ($composer) { $localRepo = $composer->getRepositoryManager()->getLocalRepository(); $installedRepo = new CompositeRepository(array($localRepo, $platformRepo)); $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories())); From e330763c5fde6fb49d5d6bb8a2df698fb36895cc Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 9 Sep 2013 16:52:59 +0200 Subject: [PATCH 071/238] Fix issue when multiple paths are mapped to one dir in the show command --- src/Composer/Command/ShowCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index ed1b629f0..166129989 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -297,7 +297,7 @@ EOT if ($type === 'psr-0') { foreach ($autoloads as $name => $path) { - $output->writeln(($name ?: '*') . ' => ' . ($path ?: '.')); + $output->writeln(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.'))); } } elseif ($type === 'classmap') { $output->writeln(implode(', ', $autoloads)); From 5f538e453448e3082c739f5e4fc64bc6d78a958c Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 9 Sep 2013 18:34:57 +0200 Subject: [PATCH 072/238] Upgrade to latest process component --- composer.json | 2 +- composer.lock | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index f0d4ee56e..33246e7fc 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "seld/jsonlint": "1.*", "symfony/console": "~2.3", "symfony/finder": "~2.2", - "symfony/process": "~2.1" + "symfony/process": "~2.1@dev" }, "require-dev": { "phpunit/phpunit": "~3.7.10" diff --git a/composer.lock b/composer.lock index 1cb435053..118a55cb2 100644 --- a/composer.lock +++ b/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": "370b764a9317165e8ea7a2e1623e031b", + "hash": "4494d3567c8c22b1adaded932825b969", "packages": [ { "name": "justinrainbow/json-schema", @@ -179,17 +179,17 @@ }, { "name": "symfony/process", - "version": "v2.3.4", + "version": "dev-master", "target-dir": "Symfony/Component/Process", "source": { "type": "git", "url": "https://github.com/symfony/Process.git", - "reference": "1e91553e1cedd0b8fb1da6ea4f89b02e21713d5b" + "reference": "f1386b09571aa886e3d51691442bee5554dc11da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/1e91553e1cedd0b8fb1da6ea4f89b02e21713d5b", - "reference": "1e91553e1cedd0b8fb1da6ea4f89b02e21713d5b", + "url": "https://api.github.com/repos/symfony/Process/zipball/f1386b09571aa886e3d51691442bee5554dc11da", + "reference": "f1386b09571aa886e3d51691442bee5554dc11da", "shasum": "" }, "require": { @@ -198,7 +198,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.4-dev" } }, "autoload": { @@ -222,7 +222,7 @@ ], "description": "Symfony Process Component", "homepage": "http://symfony.com", - "time": "2013-08-22 06:42:25" + "time": "2013-09-07 16:33:27" } ], "packages-dev": [ @@ -645,9 +645,9 @@ ], "minimum-stability": "stable", - "stability-flags": [ - - ], + "stability-flags": { + "symfony/process": 20 + }, "platform": { "php": ">=5.3.2" }, From 8207518e04676766a3155757054ea3dca1ca27b7 Mon Sep 17 00:00:00 2001 From: mwhittom Date: Mon, 9 Sep 2013 12:45:50 -0500 Subject: [PATCH 073/238] Updated to clean up code and rename variables to camelcase --- .../Repository/Vcs/PerforceDriver.php | 18 +++--- src/Composer/Util/Perforce.php | 57 ++++++++----------- .../Archiver/ArchivableFilesFinderTest.php | 1 - .../Repository/Vcs/PerforceDriverTest.php | 12 ++-- 4 files changed, 40 insertions(+), 48 deletions(-) diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index cc04fea2f..b6e94c597 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -26,8 +26,8 @@ class PerforceDriver extends VcsDriver protected $depot; protected $branch; protected $perforce; - protected $composer_info; - protected $composer_info_identifier; + protected $composerInfo; + protected $composerInfoIdentifier; /** * {@inheritDoc} @@ -65,9 +65,9 @@ class PerforceDriver extends VcsDriver */ public function getComposerInformation($identifier) { - if (isset($this->composer_info_identifier)) { - if (strcmp($identifier, $this->composer_info_identifier) === 0) { - return $this->composer_info; + if (isset($this->composerInfoIdentifier)) { + if (strcmp($identifier, $this->composerInfoIdentifier) === 0) { + return $this->composerInfo; } } $composer_info = $this->perforce->getComposerInformation($identifier); @@ -139,11 +139,11 @@ class PerforceDriver extends VcsDriver */ public function hasComposerFile($identifier) { - $this->composer_info = $this->perforce->getComposerInformation("//$this->depot/$identifier"); - $this->composer_info_identifier = $identifier; + $this->composerInfo = $this->perforce->getComposerInformation("//$this->depot/$identifier"); + $this->composerInfoIdentifier = $identifier; $result = false; - if (isset($this->composer_info)) { - $result = count($this->composer_info) > 0; + if (isset($this->composerInfo)) { + $result = count($this->composerInfo) > 0; } return $result; } diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index c61a1472e..d5d940e8f 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -31,7 +31,7 @@ class Perforce protected $p4DepotType; protected $p4Branch; protected $process; - protected $unique_perforce_client_name; + protected $uniquePerforceClientName; protected $windowsFlag; @@ -59,12 +59,12 @@ class Perforce public function initialize($repoConfig) { - $this->unique_perforce_client_name = $this->generateUniquePerforceClientName(); - if (!isset ($repoConfig)) { + $this->uniquePerforceClientName = $this->generateUniquePerforceClientName(); + if (null == $repoConfig) { return; } if (isset($repoConfig['unique_perforce_client_name'])) { - $this->unique_perforce_client_name = $repoConfig['unique_perforce_client_name']; + $this->uniquePerforceClientName = $repoConfig['unique_perforce_client_name']; } if (isset($repoConfig['depot'])) { @@ -119,8 +119,8 @@ class Perforce public function getClient() { if (!isset($this->p4Client)) { - $clean_stream_name = str_replace("@", "", str_replace("/", "_", str_replace("//", "", $this->getStream()))); - $this->p4Client = "composer_perforce_" . $this->unique_perforce_client_name . "_" . $clean_stream_name; + $cleanStreamName = str_replace("@", "", str_replace("/", "_", str_replace("//", "", $this->getStream()))); + $this->p4Client = "composer_perforce_" . $this->uniquePerforceClientName . "_" . $cleanStreamName; } return $this->p4Client; @@ -327,7 +327,7 @@ class Perforce $spec = fopen($clientSpec, 'w'); try { $this->writeClientSpecToFile($spec); - } catch (Exception $e) { + } catch (\Exception $e) { fclose($spec); throw $e; } @@ -369,9 +369,9 @@ class Perforce fclose($pipes[1]); fclose($pipes[2]); - $return_code = proc_close($process); + $returnCode = proc_close($process); - return $return_code; + return $returnCode; } @@ -389,34 +389,27 @@ class Perforce } } - public static function checkServerExists($url, ProcessExecutor $process_executor) + public static function checkServerExists($url, ProcessExecutor $processExecutor) { - $process = $process_executor ? : new ProcessExecutor; $result = ""; - $process->execute("p4 -p $url info -s", $result); - $index = strpos($result, "error"); - if ($index === false) { - return true; - } - - return false; + $processExecutor->execute("p4 -p $url info -s", $result); + return false === strpos($result, "error"); } public function getComposerInformation($identifier) { $index = strpos($identifier, "@"); if ($index === false) { - $composer_json = "$identifier/composer.json"; + $composerJson = "$identifier/composer.json"; - return $this->getComposerInformationFromPath($composer_json); - } else { - return $this->getComposerInformationFromLabel($identifier, $index); + return $this->getComposerInformationFromPath($composerJson); } + return $this->getComposerInformationFromLabel($identifier, $index); } - public function getComposerInformationFromPath($composer_json) + public function getComposerInformationFromPath($composerJson) { - $command = $this->generateP4Command(" print $composer_json"); + $command = $this->generateP4Command(" print $composerJson"); $result = $this->executeCommand($command); $index = strpos($result, "{"); if ($index === false) { @@ -434,8 +427,8 @@ class Perforce public function getComposerInformationFromLabel($identifier, $index) { - $composer_json_path = substr($identifier, 0, $index) . "/composer.json" . substr($identifier, $index); - $command = $this->generateP4Command(" files $composer_json_path", false); + $composerJsonPath = substr($identifier, 0, $index) . "/composer.json" . substr($identifier, $index); + $command = $this->generateP4Command(" files $composerJsonPath", false); $result = $this->executeCommand($command); $index2 = strpos($result, "no such file(s)."); if ($index2 === false) { @@ -444,9 +437,9 @@ class Perforce $phrase = trim(substr($result, $index3)); $fields = explode(" ", $phrase); $id = $fields[1]; - $composer_json = substr($identifier, 0, $index) . "/composer.json@" . $id; + $composerJson = substr($identifier, 0, $index) . "/composer.json@" . $id; - return $this->getComposerInformationFromPath($composer_json); + return $this->getComposerInformationFromPath($composerJson); } } @@ -455,9 +448,9 @@ class Perforce public function getBranches() { - $possible_branches = array(); + $possibleBranches = array(); if (!$this->isStream()) { - $possible_branches[$this->p4Branch] = $this->getStream(); + $possibleBranches[$this->p4Branch] = $this->getStream(); } else { $command = $this->generateP4Command("streams //$this->p4Depot/..."); $result = $this->executeCommand($command); @@ -466,12 +459,12 @@ class Perforce $resBits = explode(" ", $line); if (count($resBits) > 4) { $branch = preg_replace("/[^A-Za-z0-9 ]/", '', $resBits[4]); - $possible_branches[$branch] = $resBits[1]; + $possibleBranches[$branch] = $resBits[1]; } } } $branches = array(); - $branches['master'] = $possible_branches[$this->p4Branch]; + $branches['master'] = $possibleBranches[$this->p4Branch]; return $branches; } diff --git a/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php b/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php index 2623007d8..536f2128c 100644 --- a/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php +++ b/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php @@ -146,7 +146,6 @@ class ArchivableFilesFinderTest extends \PHPUnit_Framework_TestCase public function testHgExcludes() { - $this->markTestSkipped('Mercurial test does not work.'); // Ensure that Mercurial is available for testing. if (!$this->isProcessAvailable('hg')) { return $this->markTestSkipped('Mercurial is not available.'); diff --git a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php index 83647aac6..706320bff 100644 --- a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php @@ -54,12 +54,12 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase public function testInitializeCapturesVariablesFromRepoConfig() { $this->setUp(); - $repo_config = array( + $repoConfig = array( 'url' => 'TEST_PERFORCE_URL', 'depot' => 'TEST_DEPOT_CONFIG', 'branch' => 'TEST_BRANCH_CONFIG' ); - $driver = new PerforceDriver($repo_config, $this->io, $this->config, $this->process, $this->remoteFileSystem); + $driver = new PerforceDriver($repoConfig, $this->io, $this->config, $this->process, $this->remoteFileSystem); $process = $this->getMock('Composer\Util\ProcessExecutor'); $arguments = array( array('depot' => 'TEST_DEPOT', 'branch' => 'TEST_BRANCH'), @@ -80,12 +80,12 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase public function testInitializeLogsInAndConnectsClient() { $this->setUp(); - $repo_config = array( + $repoConfig = array( 'url' => 'TEST_PERFORCE_URL', 'depot' => 'TEST_DEPOT_CONFIG', 'branch' => 'TEST_BRANCH_CONFIG' ); - $driver = new PerforceDriver($repo_config, $this->io, $this->config, $this->process, $this->remoteFileSystem); + $driver = new PerforceDriver($repoConfig, $this->io, $this->config, $this->process, $this->remoteFileSystem); $perforce = $this->getMockBuilder('Composer\Util\Perforce')->disableOriginalConstructor()->getMock(); $perforce->expects($this->at(0)) ->method('p4Login') @@ -105,12 +105,12 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase public function testHasComposerFile() { $this->setUp(); - $repo_config = array( + $repoConfig = array( 'url' => 'TEST_PERFORCE_URL', 'depot' => 'TEST_DEPOT_CONFIG', 'branch' => 'TEST_BRANCH_CONFIG' ); - $driver = new PerforceDriver($repo_config, $this->io, $this->config, $this->process, $this->remoteFileSystem); + $driver = new PerforceDriver($repoConfig, $this->io, $this->config, $this->process, $this->remoteFileSystem); $process = $this->getMock('Composer\Util\ProcessExecutor'); $arguments = array( array('depot' => 'TEST_DEPOT', 'branch' => 'TEST_BRANCH'), From 2e737ac43989603722601c86f00489c3ad9bdcde Mon Sep 17 00:00:00 2001 From: mwhittom Date: Mon, 9 Sep 2013 14:48:24 -0500 Subject: [PATCH 074/238] updated to replace double-quotes with single quotes --- .../Downloader/PerforceDownloader.php | 4 +- .../Repository/Vcs/PerforceDriver.php | 6 +- src/Composer/Util/Perforce.php | 178 ++++++------ .../Downloader/PerforceDownloaderTest.php | 16 +- .../Repository/Vcs/PerforceDriverTest.php | 18 +- tests/Composer/Test/Util/PerforceTest.php | 273 +++++++++--------- 6 files changed, 248 insertions(+), 247 deletions(-) diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index 9d3e31e06..ad94d1ad8 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -33,7 +33,7 @@ class PerforceDownloader extends VcsDownloader $ref = $package->getSourceReference(); $label = $package->getPrettyVersion(); - $this->io->write(" Cloning " . $ref); + $this->io->write(' Cloning ' . $ref); $this->initPerforce($package, $path, $ref); $this->perforce->setStream($ref); $this->perforce->queryP4User($this->io); @@ -74,7 +74,7 @@ class PerforceDownloader extends VcsDownloader */ public function getLocalChanges(PackageInterface $package, $path) { - $this->io->write("Perforce driver does not check for local changes before overriding", true); + $this->io->write('Perforce driver does not check for local changes before overriding', true); return; } diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index b6e94c597..03acd0a21 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -35,7 +35,7 @@ class PerforceDriver extends VcsDriver public function initialize() { $this->depot = $this->repoConfig['depot']; - $this->branch = ""; + $this->branch = ''; if (isset($this->repoConfig['branch'])) { $this->branch = $this->repoConfig['branch']; } @@ -56,7 +56,7 @@ class PerforceDriver extends VcsDriver return; } - $repoDir = $this->config->get('cache-vcs-dir') . "/$this->depot"; + $repoDir = $this->config->get('cache-vcs-dir') . '/' . $this->depot; $this->perforce = Perforce::createPerforce($repoConfig, $this->getUrl(), $repoDir, $this->process); } @@ -139,7 +139,7 @@ class PerforceDriver extends VcsDriver */ public function hasComposerFile($identifier) { - $this->composerInfo = $this->perforce->getComposerInformation("//$this->depot/$identifier"); + $this->composerInfo = $this->perforce->getComposerInformation('//' . $this->depot . '/' . $identifier); $this->composerInfoIdentifier = $identifier; $result = false; if (isset($this->composerInfo)) { diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index d5d940e8f..eedc204c9 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -76,7 +76,7 @@ class Perforce if (isset($repoConfig['p4user'])) { $this->p4User = $repoConfig['p4user']; } else { - $this->p4User = $this->getP4variable("P4USER"); + $this->p4User = $this->getP4variable('P4USER'); } if (isset($repoConfig['p4password'])) { $this->p4Password = $repoConfig['p4password']; @@ -101,7 +101,7 @@ class Perforce public function cleanupClientSpec() { $client = $this->getClient(); - $command = "p4 client -d $client"; + $command = 'p4 client -d $client'; $this->executeCommand($command); $clientSpec = $this->getP4ClientSpec(); $fileSystem = new FileSystem($this->process); @@ -119,8 +119,8 @@ class Perforce public function getClient() { if (!isset($this->p4Client)) { - $cleanStreamName = str_replace("@", "", str_replace("/", "_", str_replace("//", "", $this->getStream()))); - $this->p4Client = "composer_perforce_" . $this->uniquePerforceClientName . "_" . $cleanStreamName; + $cleanStreamName = str_replace('@', '', str_replace('/', '_', str_replace('//', '', $this->getStream()))); + $this->p4Client = 'composer_perforce_' . $this->uniquePerforceClientName . '_' . $cleanStreamName; } return $this->p4Client; @@ -139,25 +139,25 @@ class Perforce public function setStream($stream) { $this->p4Stream = $stream; - $index = strrpos($stream, "/"); + $index = strrpos($stream, '/'); //Stream format is //depot/stream, while non-streaming depot is //depot if ($index > 2) { - $this->p4DepotType = "stream"; + $this->p4DepotType = 'stream'; } } public function isStream() { - return (strcmp($this->p4DepotType, "stream") === 0); + return (strcmp($this->p4DepotType, 'stream') === 0); } public function getStream() { if (!isset($this->p4Stream)) { if ($this->isStream()) { - $this->p4Stream = "//$this->p4Depot/$this->p4Branch"; + $this->p4Stream = '//' . $this->p4Depot . '/' . $this->p4Branch; } else { - $this->p4Stream = "//$this->p4Depot"; + $this->p4Stream = '//' . $this->p4Depot; } } return $this->p4Stream; @@ -165,7 +165,7 @@ class Perforce public function getStreamWithoutLabel($stream) { - $index = strpos($stream, "@"); + $index = strpos($stream, '@'); if ($index === false) { return $stream; } @@ -175,7 +175,7 @@ class Perforce public function getP4ClientSpec() { - $p4clientSpec = $this->path . "/" . $this->getClient() . ".p4.spec"; + $p4clientSpec = $this->path . '/' . $this->getClient() . '.p4.spec'; return $p4clientSpec; } @@ -191,15 +191,15 @@ class Perforce if (strlen($this->p4User) > 0) { return; } - $this->p4User = $this->getP4variable("P4USER"); + $this->p4User = $this->getP4variable('P4USER'); if (strlen($this->p4User) > 0) { return; } - $this->p4User = $io->ask("Enter P4 User:"); + $this->p4User = $io->ask('Enter P4 User:'); if ($this->windowsFlag) { - $command = "p4 set P4USER=$this->p4User"; + $command = 'p4 set P4USER=' . $this->p4User; } else { - $command = "export P4USER=$this->p4User"; + $command = 'export P4USER=' . $this->p4User; } $result = $this->executeCommand($command); } @@ -207,13 +207,13 @@ class Perforce protected function getP4variable($name) { if ($this->windowsFlag) { - $command = "p4 set"; + $command = 'p4 set'; $result = $this->executeCommand($command); - $resArray = explode("\n", $result); + $resArray = explode(PHP_EOL, $result); foreach ($resArray as $line) { - $fields = explode("=", $line); + $fields = explode('=', $line); if (strcmp($name, $fields[0]) == 0) { - $index = strpos($fields[1], " "); + $index = strpos($fields[1], ' '); if ($index === false) { $value = $fields[1]; } else { @@ -237,9 +237,9 @@ class Perforce if (isset($this->p4Password)) { return $this->p4Password; } - $password = $this->getP4variable("P4PASSWD"); + $password = $this->getP4variable('P4PASSWD'); if (strlen($password) <= 0) { - $password = $io->askAndHideAnswer("Enter password for Perforce user " . $this->getUser() . ": "); + $password = $io->askAndHideAnswer('Enter password for Perforce user ' . $this->getUser() . ': '); } $this->p4Password = $password; @@ -248,12 +248,12 @@ class Perforce public function generateP4Command($command, $useClient = true) { - $p4Command = "p4 "; - $p4Command = $p4Command . "-u " . $this->getUser() . " "; + $p4Command = 'p4 '; + $p4Command = $p4Command . '-u ' . $this->getUser() . ' '; if ($useClient) { - $p4Command = $p4Command . "-c " . $this->getClient() . " "; + $p4Command = $p4Command . '-c ' . $this->getClient() . ' '; } - $p4Command = $p4Command . "-p " . $this->getPort() . " "; + $p4Command = $p4Command . '-p ' . $this->getPort() . ' '; $p4Command = $p4Command . $command; return $p4Command; @@ -261,7 +261,7 @@ class Perforce public function isLoggedIn() { - $command = $this->generateP4Command("login -s", false); + $command = $this->generateP4Command('login -s', false); $result = trim($this->executeCommand($command)); $index = strpos($result, $this->getUser()); if ($index === false) { @@ -272,7 +272,7 @@ class Perforce public function connectClient() { - $p4CreateClientCommand = $this->generateP4Command("client -i < " . $this->getP4ClientSpec()); + $p4CreateClientCommand = $this->generateP4Command('client -i < ' . $this->getP4ClientSpec()); $this->executeCommand($p4CreateClientCommand); } @@ -281,12 +281,12 @@ class Perforce $prevDir = getcwd(); chdir($this->path); - $this->executeCommand("pwd"); + $this->executeCommand('pwd'); - $p4SyncCommand = $this->generateP4Command("sync -f "); + $p4SyncCommand = $this->generateP4Command('sync -f '); if (isset($label)) { - if (strcmp($label, "dev-master") != 0) { - $p4SyncCommand = $p4SyncCommand . "@" . $label; + if (strcmp($label, 'dev-master') != 0) { + $p4SyncCommand = $p4SyncCommand . '@' . $label; } } $this->executeCommand($p4SyncCommand); @@ -296,27 +296,27 @@ class Perforce public function writeClientSpecToFile($spec) { - fwrite($spec, "Client: " . $this->getClient() . "\n\n"); - fwrite($spec, "Update: " . date("Y/m/d H:i:s") . "\n\n"); - fwrite($spec, "Access: " . date("Y/m/d H:i:s") . "\n"); - fwrite($spec, "Owner: " . $this->getUser() . "\n\n"); - fwrite($spec, "Description:\n"); - fwrite($spec, " Created by " . $this->getUser() . " from composer.\n\n"); - fwrite($spec, "Root: " . $this->getPath() . "\n\n"); - fwrite($spec, "Options: noallwrite noclobber nocompress unlocked modtime rmdir\n\n"); - fwrite($spec, "SubmitOptions: revertunchanged\n\n"); - fwrite($spec, "LineEnd: local\n\n"); + fwrite($spec, 'Client: ' . $this->getClient() . PHP_EOL . PHP_EOL); + fwrite($spec, 'Update: ' . date('Y/m/d H:i:s') . PHP_EOL . PHP_EOL); + fwrite($spec, 'Access: ' . date('Y/m/d H:i:s') . PHP_EOL ); + fwrite($spec, 'Owner: ' . $this->getUser() . PHP_EOL . PHP_EOL); + fwrite($spec, 'Description:' . PHP_EOL); + fwrite($spec, ' Created by ' . $this->getUser() . ' from composer.' . PHP_EOL . PHP_EOL); + fwrite($spec, 'Root: ' . $this->getPath() . PHP_EOL . PHP_EOL); + fwrite($spec, 'Options: noallwrite noclobber nocompress unlocked modtime rmdir' . PHP_EOL . PHP_EOL); + fwrite($spec, 'SubmitOptions: revertunchanged' . PHP_EOL . PHP_EOL); + fwrite($spec, 'LineEnd: local' . PHP_EOL . PHP_EOL); if ($this->isStream()) { - fwrite($spec, "Stream:\n"); - fwrite($spec, " " . $this->getStreamWithoutLabel($this->p4Stream) . "\n"); + fwrite($spec, 'Stream:' . PHP_EOL); + fwrite($spec, ' ' . $this->getStreamWithoutLabel($this->p4Stream) . PHP_EOL); } else { fwrite( $spec, - "View: " . $this->getStream() . "/... //" . $this->getClient() . "/" . str_replace( - "//", - "", + 'View: ' . $this->getStream() . '/... //' . $this->getClient() . '/' . str_replace( + '//', + '', $this->getStream() - ) . "/... \n" + ) . '/... ' . PHP_EOL ); } } @@ -351,11 +351,11 @@ class Perforce public function windowsLogin($password) { $descriptorspec = array( - 0 => array("pipe", "r"), - 1 => array("pipe", "w"), - 2 => array("pipe", "a") + 0 => array('pipe', 'r'), + 1 => array('pipe', 'w'), + 2 => array('pipe', 'a') ); - $command = $this->generateP4Command(" login -a"); + $command = $this->generateP4Command(' login -a'); $process = proc_open($command, $descriptorspec, $pipes); if (!is_resource($process)) { return false; @@ -363,8 +363,8 @@ class Perforce fwrite($pipes[0], $password); fclose($pipes[0]); - $this->read($pipes[1], "Output"); - $this->read($pipes[2], "Error"); + $this->read($pipes[1], 'Output'); + $this->read($pipes[2], 'Error'); fclose($pipes[1]); fclose($pipes[2]); @@ -383,7 +383,7 @@ class Perforce if ($this->windowsFlag) { $this->windowsLogin($password); } else { - $command = "echo $password | " . $this->generateP4Command(" login -a", false); + $command = 'echo ' . $password . ' | ' . $this->generateP4Command(' login -a', false); $this->executeCommand($command); } } @@ -391,16 +391,16 @@ class Perforce public static function checkServerExists($url, ProcessExecutor $processExecutor) { - $result = ""; - $processExecutor->execute("p4 -p $url info -s", $result); - return false === strpos($result, "error"); + $result = ''; + $processExecutor->execute('p4 -p ' . $url . ' info -s', $result); + return false === strpos($result, 'error'); } public function getComposerInformation($identifier) { - $index = strpos($identifier, "@"); + $index = strpos($identifier, '@'); if ($index === false) { - $composerJson = "$identifier/composer.json"; + $composerJson = $identifier. '/composer.json'; return $this->getComposerInformationFromPath($composerJson); } @@ -409,11 +409,11 @@ class Perforce public function getComposerInformationFromPath($composerJson) { - $command = $this->generateP4Command(" print $composerJson"); + $command = $this->generateP4Command(' print ' . $composerJson); $result = $this->executeCommand($command); - $index = strpos($result, "{"); + $index = strpos($result, '{'); if ($index === false) { - return ""; + return ''; } if ($index >= 0) { $rawData = substr($result, $index); @@ -422,22 +422,22 @@ class Perforce return $composer_info; } - return ""; + return ''; } public function getComposerInformationFromLabel($identifier, $index) { - $composerJsonPath = substr($identifier, 0, $index) . "/composer.json" . substr($identifier, $index); - $command = $this->generateP4Command(" files $composerJsonPath", false); + $composerJsonPath = substr($identifier, 0, $index) . '/composer.json' . substr($identifier, $index); + $command = $this->generateP4Command(' files ' . $composerJsonPath, false); $result = $this->executeCommand($command); - $index2 = strpos($result, "no such file(s)."); + $index2 = strpos($result, 'no such file(s).'); if ($index2 === false) { - $index3 = strpos($result, "change"); + $index3 = strpos($result, 'change'); if (!($index3 === false)) { $phrase = trim(substr($result, $index3)); - $fields = explode(" ", $phrase); + $fields = explode(' ', $phrase); $id = $fields[1]; - $composerJson = substr($identifier, 0, $index) . "/composer.json@" . $id; + $composerJson = substr($identifier, 0, $index) . '/composer.json@' . $id; return $this->getComposerInformationFromPath($composerJson); } @@ -452,13 +452,13 @@ class Perforce if (!$this->isStream()) { $possibleBranches[$this->p4Branch] = $this->getStream(); } else { - $command = $this->generateP4Command("streams //$this->p4Depot/..."); + $command = $this->generateP4Command('streams //' . $this->p4Depot . '/...'); $result = $this->executeCommand($command); - $resArray = explode("\n", $result); + $resArray = explode(PHP_EOL, $result); foreach ($resArray as $line) { - $resBits = explode(" ", $line); + $resBits = explode(' ', $line); if (count($resBits) > 4) { - $branch = preg_replace("/[^A-Za-z0-9 ]/", '', $resBits[4]); + $branch = preg_replace('/[^A-Za-z0-9 ]/', '', $resBits[4]); $possibleBranches[$branch] = $resBits[1]; } } @@ -471,15 +471,15 @@ class Perforce public function getTags() { - $command = $this->generateP4Command("labels"); + $command = $this->generateP4Command('labels'); $result = $this->executeCommand($command); - $resArray = explode("\n", $result); + $resArray = explode(PHP_EOL, $result); $tags = array(); foreach ($resArray as $line) { - $index = strpos($line, "Label"); + $index = strpos($line, 'Label'); if (!($index === false)) { - $fields = explode(" ", $line); - $tags[$fields[1]] = $this->getStream() . "@" . $fields[1]; + $fields = explode(' ', $line); + $tags[$fields[1]] = $this->getStream() . '@' . $fields[1]; } } @@ -488,13 +488,13 @@ class Perforce public function checkStream() { - $command = $this->generateP4Command("depots", false); + $command = $this->generateP4Command('depots', false); $result = $this->executeCommand($command); - $resArray = explode("\n", $result); + $resArray = explode(PHP_EOL, $result); foreach ($resArray as $line) { - $index = strpos($line, "Depot"); + $index = strpos($line, 'Depot'); if (!($index === false)) { - $fields = explode(" ", $line); + $fields = explode(' ', $line); if (strcmp($this->p4Depot, $fields[1]) === 0) { $this->p4DepotType = $fields[3]; @@ -508,17 +508,17 @@ class Perforce protected function getChangeList($reference) { - $index = strpos($reference, "@"); + $index = strpos($reference, '@'); if ($index === false) { return; } $label = substr($reference, $index); - $command = $this->generateP4Command(" changes -m1 $label"); + $command = $this->generateP4Command(' changes -m1 ' . $label); $changes = $this->executeCommand($command); - if (strpos($changes, "Change") !== 0) { + if (strpos($changes, 'Change') !== 0) { return; } - $fields = explode(" ", $changes); + $fields = explode(' ', $changes); $changeList = $fields[1]; return $changeList; } @@ -533,9 +533,9 @@ class Perforce if ($toChangeList == null) { return; } - $index = strpos($fromReference, "@"); - $main = substr($fromReference, 0, $index) . "/..."; - $command = $this->generateP4Command("filelog $main@$fromChangeList,$toChangeList"); + $index = strpos($fromReference, '@'); + $main = substr($fromReference, 0, $index) . '/...'; + $command = $this->generateP4Command('filelog ' . $main . '@' . $fromChangeList. ',' . $toChangeList); $result = $this->executeCommand($command); return $result; } diff --git a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php index 46eec7284..b247cfbf3 100644 --- a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php +++ b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php @@ -54,10 +54,10 @@ class PerforceDownloaderTest extends \PHPUnit_Framework_TestCase ); $package->expects($this->at(0)) ->method('getSourceReference') - ->will($this->returnValue("SOURCE_REF")); + ->will($this->returnValue('SOURCE_REF')); $package->expects($this->at(1)) ->method('getPrettyVersion') - ->will($this->returnValue("100")); + ->will($this->returnValue('100')); $package->expects($this->at(2)) ->method('getRepository') ->will($this->returnValue($repository)); @@ -70,17 +70,17 @@ class PerforceDownloaderTest extends \PHPUnit_Framework_TestCase public function testDoDownload() { $downloader = new PerforceDownloader($this->io, $this->config); - $repoConfig = array("depot" => "TEST_DEPOT", "branch" => "TEST_BRANCH", "p4user" => "TEST_USER"); - $port = "TEST_PORT"; - $path = "TEST_PATH"; + $repoConfig = array('depot' => 'TEST_DEPOT', 'branch' => 'TEST_BRANCH', 'p4user' => 'TEST_USER'); + $port = 'TEST_PORT'; + $path = 'TEST_PATH'; $process = $this->getmock('Composer\Util\ProcessExecutor'); $perforce = $this->getMock( 'Composer\Util\Perforce', array('setStream', 'queryP4User', 'writeP4ClientSpec', 'connectClient', 'syncCodeBase'), - array($repoConfig, $port, $path, $process, true, "TEST") + array($repoConfig, $port, $path, $process, true, 'TEST') ); - $ref = "SOURCE_REF"; - $label = "LABEL"; + $ref = 'SOURCE_REF'; + $label = 'LABEL'; $perforce->expects($this->at(0)) ->method('setStream') ->with($this->equalTo($ref)); diff --git a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php index 706320bff..5b0bc43f9 100644 --- a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php @@ -67,14 +67,14 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase 'path' => $this->testPath, $process, true, - "TEST" + 'TEST' ); $perforce = $this->getMock('Composer\Util\Perforce', null, $arguments); $driver->injectPerforce($perforce); $driver->initialize(); - $this->assertEquals("TEST_PERFORCE_URL", $driver->getUrl()); - $this->assertEquals("TEST_DEPOT_CONFIG", $driver->getDepot()); - $this->assertEquals("TEST_BRANCH_CONFIG", $driver->getBranch()); + $this->assertEquals('TEST_PERFORCE_URL', $driver->getUrl()); + $this->assertEquals('TEST_DEPOT_CONFIG', $driver->getDepot()); + $this->assertEquals('TEST_BRANCH_CONFIG', $driver->getBranch()); } public function testInitializeLogsInAndConnectsClient() @@ -92,7 +92,7 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase ->with($this->io); $perforce->expects($this->at(1)) ->method('checkStream') - ->with($this->equalTo("TEST_DEPOT_CONFIG")); + ->with($this->equalTo('TEST_DEPOT_CONFIG')); $perforce->expects($this->at(2)) ->method('writeP4ClientSpec'); $perforce->expects($this->at(3)) @@ -118,16 +118,16 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase 'path' => $this->testPath, $process, true, - "TEST" + 'TEST' ); $perforce = $this->getMock('Composer\Util\Perforce', array('getComposerInformation'), $arguments); $perforce->expects($this->at(0)) ->method('getComposerInformation') - ->with($this->equalTo("//TEST_DEPOT_CONFIG/TEST_IDENTIFIER")) - ->will($this->returnValue("Some json stuff")); + ->with($this->equalTo('//TEST_DEPOT_CONFIG/TEST_IDENTIFIER')) + ->will($this->returnValue('Some json stuff')); $driver->injectPerforce($perforce); $driver->initialize(); - $identifier = "TEST_IDENTIFIER"; + $identifier = 'TEST_IDENTIFIER'; $result = $driver->hasComposerFile($identifier); $this->assertTrue($result); } diff --git a/tests/Composer/Test/Util/PerforceTest.php b/tests/Composer/Test/Util/PerforceTest.php index 912523a31..73b06bc6e 100644 --- a/tests/Composer/Test/Util/PerforceTest.php +++ b/tests/Composer/Test/Util/PerforceTest.php @@ -28,12 +28,12 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); $repoConfig = array( - "depot" => "depot", - "branch" => "branch", - "p4user" => "user", - "unique_perforce_client_name" => "TEST" + 'depot' => 'depot', + 'branch' => 'branch', + 'p4user' => 'user', + 'unique_perforce_client_name' => 'TEST' ); - $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, true); + $this->perforce = new Perforce($repoConfig, 'port', 'path', $this->processExecutor, true); } public function testGetClientWithoutStream() @@ -42,7 +42,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $hostname = gethostname(); $timestamp = time(); - $expected = "composer_perforce_TEST_depot"; + $expected = 'composer_perforce_TEST_depot'; $this->assertEquals($expected, $client); } @@ -52,7 +52,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $client = $this->perforce->getClient(); - $expected = "composer_perforce_TEST_depot_branch"; + $expected = 'composer_perforce_TEST_depot_branch'; $this->assertEquals($expected, $client); } @@ -67,34 +67,34 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->setPerforceToStream(); $stream = $this->perforce->getStream(); - $this->assertEquals("//depot/branch", $stream); + $this->assertEquals('//depot/branch', $stream); } public function testGetStreamWithoutLabelWithStreamWithoutLabel() { - $stream = $this->perforce->getStreamWithoutLabel("//depot/branch"); - $this->assertEquals("//depot/branch", $stream); + $stream = $this->perforce->getStreamWithoutLabel('//depot/branch'); + $this->assertEquals('//depot/branch', $stream); } public function testGetStreamWithoutLabelWithStreamWithLabel() { - $stream = $this->perforce->getStreamWithoutLabel("//depot/branching@label"); - $this->assertEquals("//depot/branching", $stream); + $stream = $this->perforce->getStreamWithoutLabel('//depot/branching@label'); + $this->assertEquals('//depot/branching', $stream); } public function testGetClientSpec() { $clientSpec = $this->perforce->getP4ClientSpec(); - $expected = "path/composer_perforce_TEST_depot.p4.spec"; + $expected = 'path/composer_perforce_TEST_depot.p4.spec'; $this->assertEquals($expected, $clientSpec); } public function testGenerateP4Command() { - $command = "do something"; + $command = 'do something'; $p4Command = $this->perforce->generateP4Command($command); - $expected = "p4 -u user -c composer_perforce_TEST_depot -p port do something"; + $expected = 'p4 -u user -c composer_perforce_TEST_depot -p port do something'; $this->assertEquals($expected, $p4Command); } @@ -102,40 +102,40 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $io = $this->getMock('Composer\IO\IOInterface'); - $repoConfig = array("depot" => "depot", "branch" => "branch", "p4user" => "TEST_USER"); - $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, true, "TEST"); + $repoConfig = array('depot' => 'depot', 'branch' => 'branch', 'p4user' => 'TEST_USER'); + $this->perforce = new Perforce($repoConfig, 'port', 'path', $this->processExecutor, true, 'TEST'); $this->perforce->queryP4user($io); - $this->assertEquals("TEST_USER", $this->perforce->getUser()); + $this->assertEquals('TEST_USER', $this->perforce->getUser()); } public function testQueryP4UserWithUserSetInP4VariablesWithWindowsOS() { - $repoConfig = array("depot" => "depot", "branch" => "branch"); - $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, true, "TEST"); + $repoConfig = array('depot' => 'depot', 'branch' => 'branch'); + $this->perforce = new Perforce($repoConfig, 'port', 'path', $this->processExecutor, true, 'TEST'); $io = $this->getMock('Composer\IO\IOInterface'); - $expectedCommand = "p4 set"; + $expectedCommand = 'p4 set'; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( $this->returnCallback( function ($command, &$output) { - $output = "P4USER=TEST_P4VARIABLE_USER\n"; + $output = 'P4USER=TEST_P4VARIABLE_USER' . PHP_EOL ; return true; } ) ); $this->perforce->queryP4user($io); - $this->assertEquals("TEST_P4VARIABLE_USER", $this->perforce->getUser()); + $this->assertEquals('TEST_P4VARIABLE_USER', $this->perforce->getUser()); } public function testQueryP4UserWithUserSetInP4VariablesNotWindowsOS() { - $repoConfig = array("depot" => "depot", "branch" => "branch"); - $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, false, "TEST"); + $repoConfig = array('depot' => 'depot', 'branch' => 'branch'); + $this->perforce = new Perforce($repoConfig, 'port', 'path', $this->processExecutor, false, 'TEST'); $io = $this->getMock('Composer\IO\IOInterface'); $expectedCommand = 'echo $P4USER'; @@ -145,43 +145,43 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ->will( $this->returnCallback( function ($command, &$output) { - $output = "TEST_P4VARIABLE_USER\n"; + $output = 'TEST_P4VARIABLE_USER' . PHP_EOL; return true; } ) ); $this->perforce->queryP4user($io); - $this->assertEquals("TEST_P4VARIABLE_USER", $this->perforce->getUser()); + $this->assertEquals('TEST_P4VARIABLE_USER', $this->perforce->getUser()); } public function testQueryP4UserQueriesForUser() { - $repoConfig = array("depot" => "depot", "branch" => "branch"); - $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, false, "TEST"); + $repoConfig = array('depot' => 'depot', 'branch' => 'branch'); + $this->perforce = new Perforce($repoConfig, 'port', 'path', $this->processExecutor, false, 'TEST'); $io = $this->getMock('Composer\IO\IOInterface'); - $expectedQuestion = "Enter P4 User:"; + $expectedQuestion = 'Enter P4 User:'; $io->expects($this->at(0)) ->method('ask') ->with($this->equalTo($expectedQuestion)) - ->will($this->returnValue("TEST_QUERY_USER")); + ->will($this->returnValue('TEST_QUERY_USER')); $this->perforce->queryP4user($io); - $this->assertEquals("TEST_QUERY_USER", $this->perforce->getUser()); + $this->assertEquals('TEST_QUERY_USER', $this->perforce->getUser()); } public function testQueryP4UserStoresResponseToQueryForUserWithWindows() { - $repoConfig = array("depot" => "depot", "branch" => "branch"); - $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, true, "TEST"); + $repoConfig = array('depot' => 'depot', 'branch' => 'branch'); + $this->perforce = new Perforce($repoConfig, 'port', 'path', $this->processExecutor, true, 'TEST'); $io = $this->getMock('Composer\IO\IOInterface'); - $expectedQuestion = "Enter P4 User:"; + $expectedQuestion = 'Enter P4 User:'; $io->expects($this->at(0)) ->method('ask') ->with($this->equalTo($expectedQuestion)) - ->will($this->returnValue("TEST_QUERY_USER")); - $expectedCommand = "p4 set P4USER=TEST_QUERY_USER"; + ->will($this->returnValue('TEST_QUERY_USER')); + $expectedCommand = 'p4 set P4USER=TEST_QUERY_USER'; $this->processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) @@ -192,16 +192,16 @@ class PerforceTest extends \PHPUnit_Framework_TestCase public function testQueryP4UserStoresResponseToQueryForUserWithoutWindows() { - $repoConfig = array("depot" => "depot", "branch" => "branch"); - $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, false, "TEST"); + $repoConfig = array('depot' => 'depot', 'branch' => 'branch'); + $this->perforce = new Perforce($repoConfig, 'port', 'path', $this->processExecutor, false, 'TEST'); $io = $this->getMock('Composer\IO\IOInterface'); - $expectedQuestion = "Enter P4 User:"; + $expectedQuestion = 'Enter P4 User:'; $io->expects($this->at(0)) ->method('ask') ->with($this->equalTo($expectedQuestion)) - ->will($this->returnValue("TEST_QUERY_USER")); - $expectedCommand = "export P4USER=TEST_QUERY_USER"; + ->will($this->returnValue('TEST_QUERY_USER')); + $expectedCommand = 'export P4USER=TEST_QUERY_USER'; $this->processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) @@ -213,43 +213,43 @@ class PerforceTest extends \PHPUnit_Framework_TestCase public function testQueryP4PasswordWithPasswordAlreadySet() { $repoConfig = array( - "depot" => "depot", - "branch" => "branch", - "p4user" => "user", - "p4password" => "TEST_PASSWORD" + 'depot' => 'depot', + 'branch' => 'branch', + 'p4user' => 'user', + 'p4password' => 'TEST_PASSWORD' ); - $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, false, "TEST"); + $this->perforce = new Perforce($repoConfig, 'port', 'path', $this->processExecutor, false, 'TEST'); $io = $this->getMock('Composer\IO\IOInterface'); $password = $this->perforce->queryP4Password($io); - $this->assertEquals("TEST_PASSWORD", $password); + $this->assertEquals('TEST_PASSWORD', $password); } public function testQueryP4PasswordWithPasswordSetInP4VariablesWithWindowsOS() { $io = $this->getMock('Composer\IO\IOInterface'); - $expectedCommand = "p4 set"; + $expectedCommand = 'p4 set'; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( $this->returnCallback( function ($command, &$output) { - $output = "P4PASSWD=TEST_P4VARIABLE_PASSWORD\n"; + $output = 'P4PASSWD=TEST_P4VARIABLE_PASSWORD' . PHP_EOL; return true; } ) ); $password = $this->perforce->queryP4Password($io); - $this->assertEquals("TEST_P4VARIABLE_PASSWORD", $password); + $this->assertEquals('TEST_P4VARIABLE_PASSWORD', $password); } public function testQueryP4PasswordWithPasswordSetInP4VariablesNotWindowsOS() { - $repoConfig = array("depot" => "depot", "branch" => "branch", "p4user" => "user"); - $this->perforce = new Perforce($repoConfig, "port", "path", $this->processExecutor, false, "TEST"); + $repoConfig = array('depot' => 'depot', 'branch' => 'branch', 'p4user' => 'user'); + $this->perforce = new Perforce($repoConfig, 'port', 'path', $this->processExecutor, false, 'TEST'); $io = $this->getMock('Composer\IO\IOInterface'); $expectedCommand = 'echo $P4PASSWD'; @@ -259,35 +259,36 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ->will( $this->returnCallback( function ($command, &$output) { - $output = "TEST_P4VARIABLE_PASSWORD\n"; + $output = 'TEST_P4VARIABLE_PASSWORD' . PHP_EOL; return true; } ) ); $password = $this->perforce->queryP4Password($io); - $this->assertEquals("TEST_P4VARIABLE_PASSWORD", $password); + $this->assertEquals('TEST_P4VARIABLE_PASSWORD', $password); } public function testQueryP4PasswordQueriesForPassword() { $io = $this->getMock('Composer\IO\IOInterface'); - $expectedQuestion = "Enter password for Perforce user user: "; + $expectedQuestion = 'Enter password for Perforce user user: '; $io->expects($this->at(0)) ->method('askAndHideAnswer') ->with($this->equalTo($expectedQuestion)) - ->will($this->returnValue("TEST_QUERY_PASSWORD")); + ->will($this->returnValue('TEST_QUERY_PASSWORD')); $password = $this->perforce->queryP4Password($io); - $this->assertEquals("TEST_QUERY_PASSWORD", $password); + $this->assertEquals('TEST_QUERY_PASSWORD', $password); } public function testWriteP4ClientSpecWithoutStream() { - $stream = fopen("php://memory", 'w+'); + $stream = fopen('php://memory', 'w+'); $this->perforce->writeClientSpecToFile($stream); rewind($stream); + $expectedArray = $this->getExpectedClientSpec(false); try { foreach ($expectedArray as $expected) { @@ -304,7 +305,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase public function testWriteP4ClientSpecWithStream() { $this->setPerforceToStream(); - $stream = fopen("php://memory", 'w+'); + $stream = fopen('php://memory', 'w+'); $this->perforce->writeClientSpecToFile($stream); rewind($stream); @@ -324,7 +325,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase public function testIsLoggedIn() { - $expectedCommand = "p4 -u user -p port login -s"; + $expectedCommand = 'p4 -u user -p port login -s'; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand), $this->equalTo(null)) @@ -335,7 +336,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase public function testConnectClient() { - $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot -p port client -i < path/composer_perforce_TEST_depot.p4.spec"; + $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot -p port client -i < path/composer_perforce_TEST_depot.p4.spec'; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand), $this->equalTo(null)) @@ -348,74 +349,74 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->setPerforceToStream(); - $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot_branch -p port streams //depot/..."; + $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot_branch -p port streams //depot/...'; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( $this->returnCallback( function ($command, &$output) { - $output = "Stream //depot/branch mainline none 'branch'\n"; + $output = 'Stream //depot/branch mainline none \'branch\'' . PHP_EOL; return true; } ) ); $branches = $this->perforce->getBranches(); - $this->assertEquals("//depot/branch", $branches['master']); + $this->assertEquals('//depot/branch', $branches['master']); } public function testGetBranchesWithoutStream() { $branches = $this->perforce->getBranches(); - $this->assertEquals("//depot", $branches['master']); + $this->assertEquals('//depot', $branches['master']); } public function testGetTagsWithoutStream() { - $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot -p port labels"; + $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot -p port labels'; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( $this->returnCallback( function ($command, &$output) { - $output = "Label 0.0.1 2013/07/31 'First Label!'\nLabel 0.0.2 2013/08/01 'Second Label!'\n"; + $output = 'Label 0.0.1 2013/07/31 \'First Label!\'' . PHP_EOL . 'Label 0.0.2 2013/08/01 \'Second Label!\'' . PHP_EOL; return true; } ) ); $tags = $this->perforce->getTags(); - $this->assertEquals("//depot@0.0.1", $tags['0.0.1']); - $this->assertEquals("//depot@0.0.2", $tags['0.0.2']); + $this->assertEquals('//depot@0.0.1', $tags['0.0.1']); + $this->assertEquals('//depot@0.0.2', $tags['0.0.2']); } public function testGetTagsWithStream() { $this->setPerforceToStream(); - $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot_branch -p port labels"; + $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot_branch -p port labels'; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( $this->returnCallback( function ($command, &$output) { - $output = "Label 0.0.1 2013/07/31 'First Label!'\nLabel 0.0.2 2013/08/01 'Second Label!'\n"; + $output = 'Label 0.0.1 2013/07/31 \'First Label!\'' . PHP_EOL . 'Label 0.0.2 2013/08/01 \'Second Label!\'' . PHP_EOL; return true; } ) ); $tags = $this->perforce->getTags(); - $this->assertEquals("//depot/branch@0.0.1", $tags['0.0.1']); - $this->assertEquals("//depot/branch@0.0.2", $tags['0.0.2']); + $this->assertEquals('//depot/branch@0.0.1', $tags['0.0.1']); + $this->assertEquals('//depot/branch@0.0.2', $tags['0.0.2']); } public function testCheckStreamWithoutStream() { - $result = $this->perforce->checkStream("depot"); + $result = $this->perforce->checkStream('depot'); $this->assertFalse($result); $this->assertFalse($this->perforce->isStream()); } @@ -426,19 +427,19 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ->will( $this->returnCallback( function ($command, &$output) { - $output = "Depot depot 2013/06/25 stream /p4/1/depots/depot/... 'Created by Me'"; + $output = 'Depot depot 2013/06/25 stream /p4/1/depots/depot/... \'Created by Me\''; return true; } ) ); - $result = $this->perforce->checkStream("depot"); + $result = $this->perforce->checkStream('depot'); $this->assertTrue($result); $this->assertTrue($this->perforce->isStream()); } public function testGetComposerInformationWithoutLabelWithoutStream() { - $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot -p port print //depot/composer.json"; + $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot -p port print //depot/composer.json'; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) @@ -451,32 +452,32 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ) ); - $result = $this->perforce->getComposerInformation("//depot"); + $result = $this->perforce->getComposerInformation('//depot'); $expected = array( - "name" => "test/perforce", - "description" => "Basic project for testing", - "minimum-stability" => "dev", - "autoload" => array("psr-0" => array()) + 'name' => 'test/perforce', + 'description' => 'Basic project for testing', + 'minimum-stability' => 'dev', + 'autoload' => array('psr-0' => array()) ); $this->assertEquals($expected, $result); } public function testGetComposerInformationWithLabelWithoutStream() { - $expectedCommand = "p4 -u user -p port files //depot/composer.json@0.0.1"; + $expectedCommand = 'p4 -u user -p port files //depot/composer.json@0.0.1'; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( $this->returnCallback( function ($command, &$output) { - $output = "//depot/composer.json#1 - branch change 10001 (text)"; + $output = '//depot/composer.json#1 - branch change 10001 (text)'; return true; } ) ); - $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot -p port print //depot/composer.json@10001"; + $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot -p port print //depot/composer.json@10001'; $this->processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) @@ -489,13 +490,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ) ); - $result = $this->perforce->getComposerInformation("//depot@0.0.1"); + $result = $this->perforce->getComposerInformation('//depot@0.0.1'); $expected = array( - "name" => "test/perforce", - "description" => "Basic project for testing", - "minimum-stability" => "dev", - "autoload" => array("psr-0" => array()) + 'name' => 'test/perforce', + 'description' => 'Basic project for testing', + 'minimum-stability' => 'dev', + 'autoload' => array('psr-0' => array()) ); $this->assertEquals($expected, $result); } @@ -504,7 +505,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->setPerforceToStream(); - $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot_branch -p port print //depot/branch/composer.json"; + $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot_branch -p port print //depot/branch/composer.json'; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) @@ -517,13 +518,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ) ); - $result = $this->perforce->getComposerInformation("//depot/branch"); + $result = $this->perforce->getComposerInformation('//depot/branch'); $expected = array( - "name" => "test/perforce", - "description" => "Basic project for testing", - "minimum-stability" => "dev", - "autoload" => array("psr-0" => array()) + 'name' => 'test/perforce', + 'description' => 'Basic project for testing', + 'minimum-stability' => 'dev', + 'autoload' => array('psr-0' => array()) ); $this->assertEquals($expected, $result); } @@ -531,20 +532,20 @@ class PerforceTest extends \PHPUnit_Framework_TestCase public function testGetComposerInformationWithLabelWithStream() { $this->setPerforceToStream(); - $expectedCommand = "p4 -u user -p port files //depot/branch/composer.json@0.0.1"; + $expectedCommand = 'p4 -u user -p port files //depot/branch/composer.json@0.0.1'; $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will( $this->returnCallback( function ($command, &$output) { - $output = "//depot/composer.json#1 - branch change 10001 (text)"; + $output = '//depot/composer.json#1 - branch change 10001 (text)'; return true; } ) ); - $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot_branch -p port print //depot/branch/composer.json@10001"; + $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot_branch -p port print //depot/branch/composer.json@10001'; $this->processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) @@ -557,51 +558,51 @@ class PerforceTest extends \PHPUnit_Framework_TestCase ) ); - $result = $this->perforce->getComposerInformation("//depot/branch@0.0.1"); + $result = $this->perforce->getComposerInformation('//depot/branch@0.0.1'); $expected = array( - "name" => "test/perforce", - "description" => "Basic project for testing", - "minimum-stability" => "dev", - "autoload" => array("psr-0" => array()) + 'name' => 'test/perforce', + 'description' => 'Basic project for testing', + 'minimum-stability' => 'dev', + 'autoload' => array('psr-0' => array()) ); $this->assertEquals($expected, $result); } public function testSyncCodeBaseWithoutStream() { - $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot -p port sync -f @label"; + $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot -p port sync -f @label'; $this->processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand), $this->equalTo(null)) ->will($this->returnValue(0)); - $this->perforce->syncCodeBase("label"); + $this->perforce->syncCodeBase('label'); } public function testSyncCodeBaseWithStream() { $this->setPerforceToStream(); - $expectedCommand = "p4 -u user -c composer_perforce_TEST_depot_branch -p port sync -f @label"; + $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot_branch -p port sync -f @label'; $this->processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnValue(0)); - $this->perforce->syncCodeBase("label"); + $this->perforce->syncCodeBase('label'); } public function testCheckServerExists() { $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); - $expectedCommand = "p4 -p perforce.does.exist:port info -s"; + $expectedCommand = 'p4 -p perforce.does.exist:port info -s'; $processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand), $this->equalTo(null)) ->will($this->returnValue(0)); - $result = $this->perforce->checkServerExists("perforce.does.exist:port", $processExecutor); + $result = $this->perforce->checkServerExists('perforce.does.exist:port', $processExecutor); $this->assertTrue($result); } @@ -609,13 +610,13 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); - $expectedCommand = "p4 -p perforce.does.not.exist:port info -s"; + $expectedCommand = 'p4 -p perforce.does.not.exist:port info -s'; $processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand), $this->equalTo(null)) - ->will($this->returnValue("Perforce client error:")); + ->will($this->returnValue('Perforce client error:')); - $result = $this->perforce->checkServerExists("perforce.does.not.exist:port", $processExecutor); + $result = $this->perforce->checkServerExists('perforce.does.not.exist:port', $processExecutor); $this->assertTrue($result); } @@ -639,30 +640,30 @@ class PerforceTest extends \PHPUnit_Framework_TestCase private function getExpectedClientSpec($withStream) { $expectedArray = array( - "Client: composer_perforce_TEST_depot", - "\n", - "Update:", - "\n", - "Access:", - "Owner: user", - "\n", - "Description:", - " Created by user from composer.", - "\n", - "Root: path", - "\n", - "Options: noallwrite noclobber nocompress unlocked modtime rmdir", - "\n", - "SubmitOptions: revertunchanged", - "\n", - "LineEnd: local", - "\n" + 'Client: composer_perforce_TEST_depot', + PHP_EOL, + 'Update:', + PHP_EOL, + 'Access:', + 'Owner: user', + PHP_EOL, + 'Description:', + ' Created by user from composer.', + PHP_EOL, + 'Root: path', + PHP_EOL, + 'Options: noallwrite noclobber nocompress unlocked modtime rmdir', + PHP_EOL, + 'SubmitOptions: revertunchanged', + PHP_EOL, + 'LineEnd: local', + PHP_EOL ); if ($withStream) { - $expectedArray[] = "Stream:"; - $expectedArray[] = " //depot/branch"; + $expectedArray[] = 'Stream:'; + $expectedArray[] = ' //depot/branch'; } else { - $expectedArray[] = "View: //depot/... //composer_perforce_TEST_depot/depot/..."; + $expectedArray[] = 'View: //depot/... //composer_perforce_TEST_depot/depot/...'; } return $expectedArray; @@ -670,6 +671,6 @@ class PerforceTest extends \PHPUnit_Framework_TestCase private function setPerforceToStream() { - $this->perforce->setStream("//depot/branch"); + $this->perforce->setStream('//depot/branch'); } } From 4acfe1a0790bf950ebfefa316cc584fe9a748632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20Hochd=C3=B6rfer?= Date: Mon, 9 Sep 2013 22:35:21 +0200 Subject: [PATCH 075/238] Added missing semicolon --- doc/articles/plugins.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/articles/plugins.md b/doc/articles/plugins.md index 57296f8fe..400b3452b 100644 --- a/doc/articles/plugins.md +++ b/doc/articles/plugins.md @@ -58,7 +58,7 @@ Example: use Composer\Composer; use Composer\IO\IOInterface; - use Composer\Plugin\PluginInterface + use Composer\Plugin\PluginInterface; class TemplateInstallerPlugin implements PluginInterface { From 114f6c9b6b2c7014e45be2ae57cc4581f13c2bfb Mon Sep 17 00:00:00 2001 From: mwhittom Date: Mon, 9 Sep 2013 15:36:16 -0500 Subject: [PATCH 076/238] Replaced proc_open in windowsLogin method with call to Symfony Process Component --- src/Composer/Util/Perforce.php | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index eedc204c9..1ae0316df 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -13,6 +13,7 @@ namespace Composer\Util; use Composer\IO\IOInterface; +use Symfony\Component\Process\Process; /** * @author Matt Whittom @@ -350,28 +351,9 @@ class Perforce public function windowsLogin($password) { - $descriptorspec = array( - 0 => array('pipe', 'r'), - 1 => array('pipe', 'w'), - 2 => array('pipe', 'a') - ); $command = $this->generateP4Command(' login -a'); - $process = proc_open($command, $descriptorspec, $pipes); - if (!is_resource($process)) { - return false; - } - fwrite($pipes[0], $password); - fclose($pipes[0]); - - $this->read($pipes[1], 'Output'); - $this->read($pipes[2], 'Error'); - - fclose($pipes[1]); - fclose($pipes[2]); - - $returnCode = proc_close($process); - - return $returnCode; + $process = new Process($command, null, null, $password); + return $process->run(); } From 9a54c476eb9dc3f97722b3c146538f4a1e09a9b4 Mon Sep 17 00:00:00 2001 From: Derrick Nelson Date: Mon, 9 Sep 2013 21:03:49 -0400 Subject: [PATCH 077/238] Recursively set write permissions on unzipped package contents to resolve cache unlinking issue. --- src/Composer/Downloader/ZipDownloader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Downloader/ZipDownloader.php b/src/Composer/Downloader/ZipDownloader.php index c2394543d..71958948d 100644 --- a/src/Composer/Downloader/ZipDownloader.php +++ b/src/Composer/Downloader/ZipDownloader.php @@ -38,7 +38,7 @@ class ZipDownloader extends ArchiveDownloader // try to use unzip on *nix if (!defined('PHP_WINDOWS_VERSION_BUILD')) { - $command = 'unzip '.escapeshellarg($file).' -d '.escapeshellarg($path); + $command = 'unzip '.escapeshellarg($file).' -d '.escapeshellarg($path) . ' && chmod -R u+w ' . escapeshellarg($path); if (0 === $this->process->execute($command, $ignoredOutput)) { return; } From 1b68f9151e439e43c42db3c82e5136b0817f7db5 Mon Sep 17 00:00:00 2001 From: mwhittom Date: Tue, 10 Sep 2013 08:08:31 -0500 Subject: [PATCH 078/238] removed excess space at end of function call --- src/Composer/Util/Perforce.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 1ae0316df..7ac147b49 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -299,7 +299,7 @@ class Perforce { fwrite($spec, 'Client: ' . $this->getClient() . PHP_EOL . PHP_EOL); fwrite($spec, 'Update: ' . date('Y/m/d H:i:s') . PHP_EOL . PHP_EOL); - fwrite($spec, 'Access: ' . date('Y/m/d H:i:s') . PHP_EOL ); + fwrite($spec, 'Access: ' . date('Y/m/d H:i:s') . PHP_EOL); fwrite($spec, 'Owner: ' . $this->getUser() . PHP_EOL . PHP_EOL); fwrite($spec, 'Description:' . PHP_EOL); fwrite($spec, ' Created by ' . $this->getUser() . ' from composer.' . PHP_EOL . PHP_EOL); From af53ab94ad7d7c148e0b2c4992eb582d1fb5492e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Wed, 11 Sep 2013 11:29:51 +0200 Subject: [PATCH 079/238] Default installers are available in the factory for a plugin manager --- src/Composer/Factory.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index a1d17232d..cb9463fde 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -253,13 +253,13 @@ class Factory $generator = new AutoloadGenerator($dispatcher); $composer->setAutoloadGenerator($generator); + // add installers to the manager + $this->createDefaultInstallers($im, $composer, $io); + $globalRepository = $this->createGlobalRepository($config, $vendorDir); $pm = $this->createPluginManager($composer, $io, $globalRepository); $composer->setPluginManager($pm); - // add installers to the manager - $this->createDefaultInstallers($im, $composer, $io); - if (!$disablePlugins) { $pm->loadInstalledPlugins(); } From 520e02e0a97abf93c958d261c7291abd0cf3925e Mon Sep 17 00:00:00 2001 From: akorsus Date: Wed, 11 Sep 2013 19:20:29 +0200 Subject: [PATCH 080/238] Fixed Typo JSON didn't validate --- doc/articles/handling-private-packages-with-satis.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/articles/handling-private-packages-with-satis.md b/doc/articles/handling-private-packages-with-satis.md index 9702b55bd..3272ef448 100644 --- a/doc/articles/handling-private-packages-with-satis.md +++ b/doc/articles/handling-private-packages-with-satis.md @@ -124,7 +124,7 @@ Example using HTTP over SSL using a client certificate: "url": "https://example.org", "options": { "ssl": { - "local_cert": "/home/composer/.ssl/composer.pem", + "local_cert": "/home/composer/.ssl/composer.pem" } } } From a9656427692f1548f8831ba2d85a9a8a4cef1544 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 11 Sep 2013 19:37:30 +0200 Subject: [PATCH 081/238] Do not use detected width for output formatting if it is not available --- src/Composer/Command/ShowCommand.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index 166129989..c0b515401 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -185,6 +185,11 @@ EOT } } list($width) = $this->getApplication()->getTerminalDimensions(); + if (null === $width) { + // In case the width is not detected, we're probably running the command + // outside of a real terminal, use space without a limit + $width = INF; + } if (defined('PHP_WINDOWS_VERSION_BUILD')) { $width--; } From 9b7fc0bae78850994d4faca12df594110db94cb3 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Thu, 12 Sep 2013 13:19:27 +0200 Subject: [PATCH 082/238] Update INF to PHP_INT_MAX as recommended by Stof --- src/Composer/Command/ShowCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index c0b515401..92f883226 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -188,7 +188,7 @@ EOT if (null === $width) { // In case the width is not detected, we're probably running the command // outside of a real terminal, use space without a limit - $width = INF; + $width = PHP_INT_MAX; } if (defined('PHP_WINDOWS_VERSION_BUILD')) { $width--; From e949038c0ff0d5b70ddf3ead6259c4aedcaea041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Thu, 12 Sep 2013 13:28:17 +0200 Subject: [PATCH 083/238] Removed duplication of logic of an installation manager in a plugin manager --- src/Composer/Plugin/PluginManager.php | 29 +++++-------------- .../Test/Plugin/PluginInstallerTest.php | 8 +++++ 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index 990096201..40376d145 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -232,28 +232,13 @@ class PluginManager */ public function getInstallPath(PackageInterface $package, $global = false) { - $targetDir = $package->getTargetDir(); - - return $this->getPackageBasePath($package, $global) . ($targetDir ? '/'.$targetDir : ''); - } - - /** - * Retrieves the base path a package gets installed into. - * - * Does not take targetDir into account. - * - * @param PackageInterface $package - * @param bool $global Whether this is a global package - * - * @return string Base path - */ - protected function getPackageBasePath(PackageInterface $package, $global = false) - { - if ($global) { - $vendorDir = $this->composer->getConfig()->get('home').'/vendor'; - } else { - $vendorDir = rtrim($this->composer->getConfig()->get('vendor-dir'), '/'); + if (!$global) { + return $this->composer->getInstallationManager()->getInstallPath($package); } - return ($vendorDir ? $vendorDir.'/' : '') . $package->getPrettyName(); + + $targetDir = $package->getTargetDir(); + $vendorDir = $this->composer->getConfig()->get('home').'/vendor'; + + return ($vendorDir ? $vendorDir.'/' : '').$package->getPrettyName().($targetDir ? '/'.$targetDir : ''); } } diff --git a/tests/Composer/Test/Plugin/PluginInstallerTest.php b/tests/Composer/Test/Plugin/PluginInstallerTest.php index 1c2a4cf31..3b64f2699 100644 --- a/tests/Composer/Test/Plugin/PluginInstallerTest.php +++ b/tests/Composer/Test/Plugin/PluginInstallerTest.php @@ -52,6 +52,13 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase ->method('getLocalRepository') ->will($this->returnValue($this->repository)); + $im = $this->getMock('Composer\Installer\InstallationManager'); + $im->expects($this->any()) + ->method('getInstallPath') + ->will($this->returnCallback(function ($package) { + return __DIR__.'/Fixtures/'.$package->getPrettyName(); + })); + $this->io = $this->getMock('Composer\IO\IOInterface'); $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')->disableOriginalConstructor()->getMock(); @@ -62,6 +69,7 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase $this->composer->setConfig($config); $this->composer->setDownloadManager($dm); $this->composer->setRepositoryManager($rm); + $this->composer->setInstallationManager($im); $this->composer->setAutoloadGenerator($this->autoloadGenerator); $this->pm = new PluginManager($this->composer, $this->io); From 8a319a719b1e8e3bb812ee8797fc6887bac27a05 Mon Sep 17 00:00:00 2001 From: mwhittom Date: Fri, 13 Sep 2013 15:01:00 -0500 Subject: [PATCH 084/238] Fixed issue with non-streaming perforce depots, also fixed issue where PerforceDownloader was not logging in --- src/Composer/Downloader/PerforceDownloader.php | 2 +- src/Composer/Util/Perforce.php | 10 ++-------- tests/Composer/Test/Util/PerforceTest.php | 2 +- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index ad94d1ad8..6ddea153f 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -36,7 +36,7 @@ class PerforceDownloader extends VcsDownloader $this->io->write(' Cloning ' . $ref); $this->initPerforce($package, $path, $ref); $this->perforce->setStream($ref); - $this->perforce->queryP4User($this->io); + $this->perforce->p4Login($this->io); $this->perforce->writeP4ClientSpec(); $this->perforce->connectClient(); $this->perforce->syncCodeBase($label); diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 7ac147b49..2fb0e4bea 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -282,15 +282,13 @@ class Perforce $prevDir = getcwd(); chdir($this->path); - $this->executeCommand('pwd'); - $p4SyncCommand = $this->generateP4Command('sync -f '); if (isset($label)) { if (strcmp($label, 'dev-master') != 0) { $p4SyncCommand = $p4SyncCommand . '@' . $label; } } - $this->executeCommand($p4SyncCommand); + $result = $this->executeCommand($p4SyncCommand); chdir($prevDir); } @@ -313,11 +311,7 @@ class Perforce } else { fwrite( $spec, - 'View: ' . $this->getStream() . '/... //' . $this->getClient() . '/' . str_replace( - '//', - '', - $this->getStream() - ) . '/... ' . PHP_EOL + 'View: ' . $this->getStream() . '/... //' . $this->getClient() . '/... ' . PHP_EOL ); } } diff --git a/tests/Composer/Test/Util/PerforceTest.php b/tests/Composer/Test/Util/PerforceTest.php index 73b06bc6e..6bde3d797 100644 --- a/tests/Composer/Test/Util/PerforceTest.php +++ b/tests/Composer/Test/Util/PerforceTest.php @@ -663,7 +663,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $expectedArray[] = 'Stream:'; $expectedArray[] = ' //depot/branch'; } else { - $expectedArray[] = 'View: //depot/... //composer_perforce_TEST_depot/depot/...'; + $expectedArray[] = 'View: //depot/... //composer_perforce_TEST_depot/...'; } return $expectedArray; From c98bce0446671132bc5e460a7970d904cb95283c Mon Sep 17 00:00:00 2001 From: Derrick Nelson Date: Sat, 14 Sep 2013 13:11:26 -0400 Subject: [PATCH 085/238] Added RarDownloader for downloading RAR archived packages. --- src/Composer/Downloader/RarDownloader.php | 94 +++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/Composer/Downloader/RarDownloader.php diff --git a/src/Composer/Downloader/RarDownloader.php b/src/Composer/Downloader/RarDownloader.php new file mode 100644 index 000000000..bb62ee0a8 --- /dev/null +++ b/src/Composer/Downloader/RarDownloader.php @@ -0,0 +1,94 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Downloader; + +use Composer\Config; +use Composer\Cache; +use Composer\EventDispatcher\EventDispatcher; +use Composer\Util\ProcessExecutor; +use Composer\IO\IOInterface; +use RarArchive; + +/** + * RAR archive downloader. + * + * Based on previous work by Jordi Boggiano ({@see ZipDownloader}). + * + * @author Derrick Nelson + */ +class RarDownloader extends ArchiveDownloader +{ + protected $process; + + public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null) + { + $this->process = $process ?: new ProcessExecutor($io); + parent::__construct($io, $config, $eventDispatcher, $cache); + } + + protected function extract($file, $path) + { + $processError = null; + + // Try to use unrar on *nix + if (!defined('PHP_WINDOWS_VERSION_BUILD')) { + $command = 'unrar x ' . escapeshellarg($file) . ' ' . escapeshellarg($path) . ' && chmod -R u+w ' . escapeshellarg($path); + + if (0 === $this->process->execute($command, $ignoredOutput)) { + return; + } + + $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput(); + } + + if (!class_exists('RarArchive')) { + // php.ini path is added to the error message to help users find the correct file + $iniPath = php_ini_loaded_file(); + + if ($iniPath) { + $iniMessage = 'The php.ini used by your command-line PHP is: ' . $iniPath; + } else { + $iniMessage = 'A php.ini file does not exist. You will have to create one.'; + } + + $error = "Could not decompress the archive, enable the PHP rar extension or install unrar.\n" + . $iniMessage . "\n" . $processError; + + if (!defined('PHP_WINDOWS_VERSION_BUILD')) { + $error = "Could not decompress the archive, enable the PHP rar extension.\n" . $iniMessage; + } + + throw new \RuntimeException($error); + } + + $rarArchive = RarArchive::open($file); + + if (false === $rarArchive) { + throw new \UnexpectedValueException('Could not open RAR archive: ' . $file); + } + + $entries = $rarArchive->getEntries(); + + if (false === $entries) { + throw new \RuntimeException('Could not retrieve RAR archive entries'); + } + + foreach ($entries as $entry) { + if (false === $entry->extract($path)) { + throw new \RuntimeException('Could not extract entry'); + } + } + + $rarArchive->close(); + } +} From 2ba804298675326a4321f84345d70b00d0b357e0 Mon Sep 17 00:00:00 2001 From: Derrick Nelson Date: Sat, 14 Sep 2013 13:12:59 -0400 Subject: [PATCH 086/238] Added package type rar. --- src/Composer/Factory.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index a1d17232d..d7ca80f92 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -357,6 +357,7 @@ class Factory $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config)); $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config)); $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $eventDispatcher, $cache)); + $dm->setDownloader('rar', new Downloader\RarDownloader($io, $config, $eventDispatcher, $cache)); $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $eventDispatcher, $cache)); $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache)); $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache)); From 876314a58d249fc493c321e3565eaa46cbd81683 Mon Sep 17 00:00:00 2001 From: zweifisch Date: Sun, 15 Sep 2013 22:37:16 +0800 Subject: [PATCH 087/238] Update 05-repositories.md --- doc/05-repositories.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/05-repositories.md b/doc/05-repositories.md index dab0abb4d..94773f35a 100644 --- a/doc/05-repositories.md +++ b/doc/05-repositories.md @@ -523,7 +523,7 @@ private packages: Each zip artifact is just a ZIP archive with `composer.json` in root folder: - $ tar -tf acme-corp-parser-10.3.5.zip + $ unzip -l acme-corp-parser-10.3.5.zip composer.json ... From 9d15a324058eb21f1283d9fd3742bd1423cc29ae Mon Sep 17 00:00:00 2001 From: Peter Schultz Date: Mon, 16 Sep 2013 01:39:08 +0200 Subject: [PATCH 088/238] Add missing require to example composer.json --- doc/articles/custom-installers.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/articles/custom-installers.md b/doc/articles/custom-installers.md index 5e1df0eab..feeebe52c 100644 --- a/doc/articles/custom-installers.md +++ b/doc/articles/custom-installers.md @@ -79,6 +79,9 @@ Example: }, "extra": { "class": "phpDocumentor\\Composer\\TemplateInstallerPlugin" + }, + "require": { + "composer-plugin-api": "1.0.0" } } From 5b96caf8ce5d667ca6a80a446a8192ebd4aa2b6b Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 16 Sep 2013 14:08:24 +0200 Subject: [PATCH 089/238] Add version release date to -V output, fixes #2267 --- src/Composer/Compiler.php | 10 ++++++++++ src/Composer/Composer.php | 1 + src/Composer/Console/Application.php | 8 ++++++++ 3 files changed, 19 insertions(+) diff --git a/src/Composer/Compiler.php b/src/Composer/Compiler.php index 94f1a15ff..fa86d7f21 100644 --- a/src/Composer/Compiler.php +++ b/src/Composer/Compiler.php @@ -24,6 +24,7 @@ use Symfony\Component\Process\Process; class Compiler { private $version; + private $versionDate; /** * Compiles composer into a single phar file @@ -43,6 +44,14 @@ class Compiler } $this->version = trim($process->getOutput()); + $process = new Process('git log -n1 --pretty=%ci HEAD', __DIR__); + if ($process->run() != 0) { + throw new \RuntimeException('Can\'t run git log. You must ensure to run compile from composer git repository clone and that git binary is available.'); + } + $date = new \DateTime(trim($process->getOutput())); + $date->setTimezone(new \DateTimeZone('UTC')); + $this->versionDate = $date->format('Y-m-d H:i:s'); + $process = new Process('git describe --tags HEAD'); if ($process->run() == 0) { $this->version = trim($process->getOutput()); @@ -127,6 +136,7 @@ class Compiler } $content = str_replace('@package_version@', $this->version, $content); + $content = str_replace('@release_date@', $this->versionDate, $content); $phar->addFromString($path, $content); } diff --git a/src/Composer/Composer.php b/src/Composer/Composer.php index 20279b5ac..0d1e0aa89 100644 --- a/src/Composer/Composer.php +++ b/src/Composer/Composer.php @@ -29,6 +29,7 @@ use Composer\Autoload\AutoloadGenerator; class Composer { const VERSION = '@package_version@'; + const RELEASE_DATE = '@release_date@'; /** * @var Package\RootPackageInterface diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index 63bb59124..9d622cf67 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -235,6 +235,14 @@ class Application extends BaseApplication return $commands; } + /** + * {@inheritDoc} + */ + public function getLongVersion() + { + return parent::getLongVersion() . ' ' . Composer::RELEASE_DATE; + } + /** * {@inheritDoc} */ From da7ace02ebd07d24d9a114a40bdd25bb3f8e0422 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 19 Sep 2013 11:23:19 +0200 Subject: [PATCH 090/238] Update deps --- composer.lock | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/composer.lock b/composer.lock index 118a55cb2..58bceb299 100644 --- a/composer.lock +++ b/composer.lock @@ -184,12 +184,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Process.git", - "reference": "f1386b09571aa886e3d51691442bee5554dc11da" + "reference": "3d8287117bb7c638a0164cf4ac471256a30e0620" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/f1386b09571aa886e3d51691442bee5554dc11da", - "reference": "f1386b09571aa886e3d51691442bee5554dc11da", + "url": "https://api.github.com/repos/symfony/Process/zipball/3d8287117bb7c638a0164cf4ac471256a30e0620", + "reference": "3d8287117bb7c638a0164cf4ac471256a30e0620", "shasum": "" }, "require": { @@ -222,22 +222,22 @@ ], "description": "Symfony Process Component", "homepage": "http://symfony.com", - "time": "2013-09-07 16:33:27" + "time": "2013-09-18 07:05:46" } ], "packages-dev": [ { "name": "phpunit/php-code-coverage", - "version": "1.2.12", + "version": "1.2.13", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "1.2.12" + "reference": "466e7cd2554b4e264c9e3f31216d25ac0e5f3d94" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1.2.12", - "reference": "1.2.12", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/466e7cd2554b4e264c9e3f31216d25ac0e5f3d94", + "reference": "466e7cd2554b4e264c9e3f31216d25ac0e5f3d94", "shasum": "" }, "require": { @@ -285,7 +285,7 @@ "testing", "xunit" ], - "time": "2013-07-06 06:26:16" + "time": "2013-09-10 08:14:32" }, { "name": "phpunit/php-file-iterator", @@ -422,16 +422,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "1.2.0" + "reference": "5220af2a7929aa35cf663d97c89ad3d50cf5fa3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1.2.0", - "reference": "1.2.0", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/5220af2a7929aa35cf663d97c89ad3d50cf5fa3e", + "reference": "5220af2a7929aa35cf663d97c89ad3d50cf5fa3e", "shasum": "" }, "require": { @@ -468,20 +468,20 @@ "keywords": [ "tokenizer" ], - "time": "2013-08-04 05:57:48" + "time": "2013-09-13 04:58:23" }, { "name": "phpunit/phpunit", - "version": "3.7.24", + "version": "3.7.27", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "3.7.24" + "reference": "4b024e753e3421837afbcca962c8724c58b39376" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3.7.24", - "reference": "3.7.24", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4b024e753e3421837afbcca962c8724c58b39376", + "reference": "4b024e753e3421837afbcca962c8724c58b39376", "shasum": "" }, "require": { @@ -542,7 +542,7 @@ "testing", "xunit" ], - "time": "2013-08-09 06:58:24" + "time": "2013-09-16 03:09:52" }, { "name": "phpunit/phpunit-mock-objects", From b333d7a4856853c224c4dd15efed146333c577c6 Mon Sep 17 00:00:00 2001 From: Karoly Negyesi Date: Fri, 20 Sep 2013 04:31:24 +0200 Subject: [PATCH 091/238] act on target-dir changes during update --- src/Composer/Installer/LibraryInstaller.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index 281ffa11a..a754eb590 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -157,8 +157,12 @@ class LibraryInstaller implements InstallerInterface protected function updateCode(PackageInterface $initial, PackageInterface $target) { - $downloadPath = $this->getInstallPath($initial); - $this->downloadManager->update($initial, $target, $downloadPath); + $initialDownloadPath = $this->getInstallPath($initial); + $targetDownloadPath = $this->getInstallPath($target); + if ($targetDownloadPath != $initialDownloadPath) { + $this->filesystem->copyThenRemove($initialDownloadPath, $targetDownloadPath); + } + $this->downloadManager->update($initial, $target, $targetDownloadPath); } protected function removeCode(PackageInterface $package) From dd4db91ae79ed4ce713afa7bac93bf5b69634940 Mon Sep 17 00:00:00 2001 From: Karoly Negyesi Date: Fri, 20 Sep 2013 05:02:06 +0200 Subject: [PATCH 092/238] using mkdir() in copyThenRemove() leads to errors if the target exists or not a dir, use ensureDirectoryExists() instead --- src/Composer/Util/Filesystem.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index 3dade2ce9..bdef6e402 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -129,15 +129,12 @@ class Filesystem { $it = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS); $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST); - - if (!file_exists($target)) { - mkdir($target, 0777, true); - } + $this->ensureDirectoryExists($target); foreach ($ri as $file) { $targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathName(); if ($file->isDir()) { - mkdir($targetPath); + $this->ensureDirectoryExists($targetPath); } else { copy($file->getPathname(), $targetPath); } From f82c820a32e468c20fa8061989814c51f1407762 Mon Sep 17 00:00:00 2001 From: Karoly Negyesi Date: Fri, 20 Sep 2013 05:39:35 +0200 Subject: [PATCH 093/238] do not try to test update inside fixtures --- .../Test/Plugin/PluginInstallerTest.php | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/Composer/Test/Plugin/PluginInstallerTest.php b/tests/Composer/Test/Plugin/PluginInstallerTest.php index 3b64f2699..4163c0f2e 100644 --- a/tests/Composer/Test/Plugin/PluginInstallerTest.php +++ b/tests/Composer/Test/Plugin/PluginInstallerTest.php @@ -20,6 +20,7 @@ use Composer\Package\Loader\ArrayLoader; use Composer\Package\PackageInterface; use Composer\Plugin\PluginManager; use Composer\Autoload\AutoloadGenerator; +use Composer\Util\Filesystem; class PluginInstallerTest extends \PHPUnit_Framework_TestCase { @@ -30,13 +31,17 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase protected $repository; protected $io; protected $autoloadGenerator; + protected $directory; protected function setUp() { $loader = new JsonLoader(new ArrayLoader()); $this->packages = array(); + $this->directory = sys_get_temp_dir() . '/' . uniqid(); for ($i = 1; $i <= 4; $i++) { - $this->packages[] = $loader->load(__DIR__.'/Fixtures/plugin-v'.$i.'/composer.json'); + $filename = '/Fixtures/plugin-v'.$i.'/composer.json'; + mkdir(dirname($this->directory . $filename), 0777, TRUE); + $this->packages[] = $loader->load(__DIR__ . $filename); } $dm = $this->getMockBuilder('Composer\Downloader\DownloadManager') @@ -77,13 +82,18 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase $config->merge(array( 'config' => array( - 'vendor-dir' => __DIR__.'/Fixtures/', - 'home' => __DIR__.'/Fixtures', - 'bin-dir' => __DIR__.'/Fixtures/bin', + 'vendor-dir' => $this->directory.'/Fixtures/', + 'home' => $this->directory.'/Fixtures', + 'bin-dir' => $this->directory.'/Fixtures/bin', ), )); } + protected function tearDown() { + $filesystem = new Filesystem(); + $filesystem->removeDirectoryPhp($this->directory); + } + public function testInstallNewPlugin() { $this->repository From c6ec739766c53245edd9f18b8d31f91abd04d8d3 Mon Sep 17 00:00:00 2001 From: Karoly Negyesi Date: Fri, 20 Sep 2013 06:02:36 +0200 Subject: [PATCH 094/238] allow injecting a mock filesystem into LibraryInstaller and fix LibraryInstallerTest --- src/Composer/Installer/LibraryInstaller.php | 5 +++-- tests/Composer/Test/Installer/LibraryInstallerTest.php | 8 +++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index a754eb590..cd3a6d947 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -41,15 +41,16 @@ class LibraryInstaller implements InstallerInterface * @param IOInterface $io * @param Composer $composer * @param string $type + * @param Filesystem $filesystem */ - public function __construct(IOInterface $io, Composer $composer, $type = 'library') + public function __construct(IOInterface $io, Composer $composer, $type = 'library', $filesystem = NULL) { $this->composer = $composer; $this->downloadManager = $composer->getDownloadManager(); $this->io = $io; $this->type = $type; - $this->filesystem = new Filesystem(); + $this->filesystem = $filesystem ?: new Filesystem(); $this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/'); $this->binDir = rtrim($composer->getConfig()->get('bin-dir'), '/'); } diff --git a/tests/Composer/Test/Installer/LibraryInstallerTest.php b/tests/Composer/Test/Installer/LibraryInstallerTest.php index dd36e6184..92e0437d6 100644 --- a/tests/Composer/Test/Installer/LibraryInstallerTest.php +++ b/tests/Composer/Test/Installer/LibraryInstallerTest.php @@ -131,7 +131,8 @@ class LibraryInstallerTest extends TestCase */ public function testUpdate() { - $library = new LibraryInstaller($this->io, $this->composer); + $filesystem = $this->getMockBuilder('Composer\Util\Filesystem')->getMock(); + $library = new LibraryInstaller($this->io, $this->composer, 'library', $filesystem); $initial = $this->createPackageMock(); $target = $this->createPackageMock(); @@ -140,6 +141,11 @@ class LibraryInstallerTest extends TestCase ->method('getPrettyName') ->will($this->returnValue('package1')); + $target + ->expects($this->once()) + ->method('getPrettyName') + ->will($this->returnValue('package1')); + $this->repository ->expects($this->exactly(3)) ->method('hasPackage') From 24c9ef72d60f4080b1d16af92a60b8929e9cf1b2 Mon Sep 17 00:00:00 2001 From: Karoly Negyesi Date: Fri, 20 Sep 2013 06:04:15 +0200 Subject: [PATCH 095/238] make LibraryInstallerTest a little more strict --- tests/Composer/Test/Installer/LibraryInstallerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Composer/Test/Installer/LibraryInstallerTest.php b/tests/Composer/Test/Installer/LibraryInstallerTest.php index 92e0437d6..f87a8c9c9 100644 --- a/tests/Composer/Test/Installer/LibraryInstallerTest.php +++ b/tests/Composer/Test/Installer/LibraryInstallerTest.php @@ -137,7 +137,7 @@ class LibraryInstallerTest extends TestCase $target = $this->createPackageMock(); $initial - ->expects($this->any()) + ->expects($this->once()) ->method('getPrettyName') ->will($this->returnValue('package1')); From 6c393c1c696ddd56d5ecbeec0e6387adc7d18c31 Mon Sep 17 00:00:00 2001 From: Karoly Negyesi Date: Fri, 20 Sep 2013 06:31:06 +0200 Subject: [PATCH 096/238] use the more generic removeDirectory --- tests/Composer/Test/Plugin/PluginInstallerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Composer/Test/Plugin/PluginInstallerTest.php b/tests/Composer/Test/Plugin/PluginInstallerTest.php index 4163c0f2e..79e141530 100644 --- a/tests/Composer/Test/Plugin/PluginInstallerTest.php +++ b/tests/Composer/Test/Plugin/PluginInstallerTest.php @@ -91,7 +91,7 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase protected function tearDown() { $filesystem = new Filesystem(); - $filesystem->removeDirectoryPhp($this->directory); + $filesystem->removeDirectory($this->directory); } public function testInstallNewPlugin() From f4e9c74fee1155001683441cc4d960deb9b99fac Mon Sep 17 00:00:00 2001 From: Karoly Negyesi Date: Fri, 20 Sep 2013 09:58:46 +0200 Subject: [PATCH 097/238] style fixes --- src/Composer/Installer/LibraryInstaller.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index cd3a6d947..64b300c35 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -43,7 +43,7 @@ class LibraryInstaller implements InstallerInterface * @param string $type * @param Filesystem $filesystem */ - public function __construct(IOInterface $io, Composer $composer, $type = 'library', $filesystem = NULL) + public function __construct(IOInterface $io, Composer $composer, $type = 'library', $filesystem = null) { $this->composer = $composer; $this->downloadManager = $composer->getDownloadManager(); @@ -160,7 +160,7 @@ class LibraryInstaller implements InstallerInterface { $initialDownloadPath = $this->getInstallPath($initial); $targetDownloadPath = $this->getInstallPath($target); - if ($targetDownloadPath != $initialDownloadPath) { + if ($targetDownloadPath !== $initialDownloadPath) { $this->filesystem->copyThenRemove($initialDownloadPath, $targetDownloadPath); } $this->downloadManager->update($initial, $target, $targetDownloadPath); From 4abaaaf76d664a0f745f33cf6551e6555b354977 Mon Sep 17 00:00:00 2001 From: Haralan Dobrev Date: Sat, 21 Sep 2013 02:10:24 +0300 Subject: [PATCH 098/238] Use default description and license from CLI args When running `composer init` with `--description` and `--license` arguments on the command line they are later suggested as defaults during the interactive flow. However when you press Enter (to use the default suggesstion) Composer does not use it, but instead skip them entirely from the `composer.json` generation. This change provides a default argument not only to `DialogHelper::getQuestion()`, but also to `DialogHelper::ask()`. --- src/Composer/Command/InitCommand.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Composer/Command/InitCommand.php b/src/Composer/Command/InitCommand.php index 1071e949d..a44546b73 100644 --- a/src/Composer/Command/InitCommand.php +++ b/src/Composer/Command/InitCommand.php @@ -208,7 +208,8 @@ EOT $description = $input->getOption('description') ?: false; $description = $dialog->ask( $output, - $dialog->getQuestion('Description', $description) + $dialog->getQuestion('Description', $description), + $description ); $input->setOption('description', $description); @@ -258,7 +259,8 @@ EOT $license = $input->getOption('license') ?: false; $license = $dialog->ask( $output, - $dialog->getQuestion('License', $license) + $dialog->getQuestion('License', $license), + $license ); $input->setOption('license', $license); From eb72e1692c123642de7aee2e2365f9718f21c1fe Mon Sep 17 00:00:00 2001 From: Gerry Vandermaesen Date: Sat, 21 Sep 2013 17:35:07 +0200 Subject: [PATCH 099/238] Added --no-install option to create-project command Added a --no-install option to the create-project command that skips installation of the dependencies in the newly created project. --- src/Composer/Command/CreateProjectCommand.php | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index fe8ccabcb..bdc2376ce 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -66,6 +66,7 @@ class CreateProjectCommand extends Command new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deletion vcs folder.'), + new InputOption('no-install', null, InputOption::VALUE_NONE, 'Whether to skip installation of the package dependencies.'), )) ->setHelp(<<create-project command creates a new project from a given @@ -130,11 +131,12 @@ EOT $input->getOption('no-custom-installers'), $input->getOption('no-scripts'), $input->getOption('keep-vcs'), - $input->getOption('no-progress') + $input->getOption('no-progress'), + $input->getOption('no-install') ); } - public function installProject(IOInterface $io, $config, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repositoryUrl = null, $disableCustomInstallers = false, $noScripts = false, $keepVcs = false, $noProgress = false) + public function installProject(IOInterface $io, $config, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repositoryUrl = null, $disableCustomInstallers = false, $noScripts = false, $keepVcs = false, $noProgress = false, $noInstall = false) { if ($packageName !== null) { $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repositoryUrl, $disableCustomInstallers, $noScripts, $keepVcs, $noProgress); @@ -150,18 +152,20 @@ EOT } // install dependencies of the created project - $installer = Installer::create($io, $composer); - $installer->setPreferSource($preferSource) - ->setPreferDist($preferDist) - ->setDevMode($installDevPackages) - ->setRunScripts( ! $noScripts); + if ($noInstall === false) { + $installer = Installer::create($io, $composer); + $installer->setPreferSource($preferSource) + ->setPreferDist($preferDist) + ->setDevMode($installDevPackages) + ->setRunScripts( ! $noScripts); - if ($disableCustomInstallers) { - $installer->disableCustomInstallers(); - } + if ($disableCustomInstallers) { + $installer->disableCustomInstallers(); + } - if (!$installer->run()) { - return 1; + if (!$installer->run()) { + return 1; + } } $hasVcs = $installedFromVcs; From 4748f16091931c582ca0a016a95c0f7fd5c0f3f4 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sat, 21 Sep 2013 20:31:53 +0200 Subject: [PATCH 100/238] fix CS --- src/Composer/Package/Archiver/ArchiveManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Package/Archiver/ArchiveManager.php b/src/Composer/Package/Archiver/ArchiveManager.php index 6c6be7fda..6e7005a5a 100644 --- a/src/Composer/Package/Archiver/ArchiveManager.php +++ b/src/Composer/Package/Archiver/ArchiveManager.php @@ -144,7 +144,7 @@ class ArchiveManager // Create the archive $archivePath = $usableArchiver->archive($sourcePath, $target, $format, $package->getArchiveExcludes()); - //cleanup temporary download + // cleanup temporary download if (!$package instanceof RootPackage) { $filesystem->removeDirectory($sourcePath); } From 1a69d0a2a757e7d8a07f883e0487ee3d5f8575ec Mon Sep 17 00:00:00 2001 From: Karoly Negyesi Date: Sun, 22 Sep 2013 19:41:54 +0200 Subject: [PATCH 101/238] style fixes --- src/Composer/Installer/LibraryInstaller.php | 2 +- tests/Composer/Test/Plugin/PluginInstallerTest.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index 64b300c35..cb3808295 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -43,7 +43,7 @@ class LibraryInstaller implements InstallerInterface * @param string $type * @param Filesystem $filesystem */ - public function __construct(IOInterface $io, Composer $composer, $type = 'library', $filesystem = null) + public function __construct(IOInterface $io, Composer $composer, $type = 'library', Filesystem $filesystem = null) { $this->composer = $composer; $this->downloadManager = $composer->getDownloadManager(); diff --git a/tests/Composer/Test/Plugin/PluginInstallerTest.php b/tests/Composer/Test/Plugin/PluginInstallerTest.php index 79e141530..2502dded9 100644 --- a/tests/Composer/Test/Plugin/PluginInstallerTest.php +++ b/tests/Composer/Test/Plugin/PluginInstallerTest.php @@ -89,7 +89,8 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase )); } - protected function tearDown() { + protected function tearDown() + { $filesystem = new Filesystem(); $filesystem->removeDirectory($this->directory); } From e32e4ad490b6326e5b71f6982c0dd6879f4be129 Mon Sep 17 00:00:00 2001 From: Karoly Negyesi Date: Sun, 22 Sep 2013 19:42:05 +0200 Subject: [PATCH 102/238] change the test to test for a target dir change --- .../Test/Installer/LibraryInstallerTest.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tests/Composer/Test/Installer/LibraryInstallerTest.php b/tests/Composer/Test/Installer/LibraryInstallerTest.php index f87a8c9c9..fcebc8328 100644 --- a/tests/Composer/Test/Installer/LibraryInstallerTest.php +++ b/tests/Composer/Test/Installer/LibraryInstallerTest.php @@ -131,8 +131,13 @@ class LibraryInstallerTest extends TestCase */ public function testUpdate() { - $filesystem = $this->getMockBuilder('Composer\Util\Filesystem')->getMock(); - $library = new LibraryInstaller($this->io, $this->composer, 'library', $filesystem); + $filesystem = $this->getMockBuilder('Composer\Util\Filesystem') + ->getMock(); + $filesystem + ->expects($this->once()) + ->method('copyThenRemove') + ->with($this->vendorDir.'/package1', $this->vendorDir.'/package1/newtarget'); + $initial = $this->createPackageMock(); $target = $this->createPackageMock(); @@ -146,6 +151,11 @@ class LibraryInstallerTest extends TestCase ->method('getPrettyName') ->will($this->returnValue('package1')); + $target + ->expects($this->once()) + ->method('getTargetDir') + ->will($this->returnValue('newtarget')); + $this->repository ->expects($this->exactly(3)) ->method('hasPackage') @@ -154,7 +164,7 @@ class LibraryInstallerTest extends TestCase $this->dm ->expects($this->once()) ->method('update') - ->with($initial, $target, $this->vendorDir.'/package1'); + ->with($initial, $target, $this->vendorDir.'/package1/newtarget'); $this->repository ->expects($this->once()) @@ -166,6 +176,7 @@ class LibraryInstallerTest extends TestCase ->method('addPackage') ->with($target); + $library = new LibraryInstaller($this->io, $this->composer, 'library', $filesystem); $library->update($this->repository, $initial, $target); $this->assertFileExists($this->vendorDir, 'Vendor dir should be created'); $this->assertFileExists($this->binDir, 'Bin dir should be created'); From 38917c204758f1dd97569af299b3b87b3d0d2c10 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 25 Sep 2013 10:14:42 +0200 Subject: [PATCH 103/238] Add parallel build to travis script --- .travis.yml | 6 ++++-- tests/Composer/Test/Autoload/AutoloadGeneratorTest.php | 2 +- tests/Composer/Test/CacheTest.php | 1 + tests/Composer/Test/Command/InitCommandTest.php | 2 +- tests/Composer/Test/ComposerTest.php | 1 + .../Composer/Test/DependencyResolver/DefaultPolicyTest.php | 2 +- tests/Composer/Test/DependencyResolver/PoolTest.php | 2 +- tests/Composer/Test/DependencyResolver/RequestTest.php | 2 +- tests/Composer/Test/DependencyResolver/RuleSetTest.php | 2 +- tests/Composer/Test/DependencyResolver/RuleTest.php | 2 +- tests/Composer/Test/DependencyResolver/SolverTest.php | 2 +- tests/Composer/Test/EventDispatcher/EventDispatcherTest.php | 2 +- tests/Composer/Test/IO/ConsoleIOTest.php | 2 +- tests/Composer/Test/IO/NullIOTest.php | 2 +- tests/Composer/Test/Installer/LibraryInstallerTest.php | 2 +- tests/Composer/Test/InstallerTest.php | 1 + tests/Composer/Test/Package/CompletePackageTest.php | 2 +- tests/Composer/Test/Repository/ArrayRepositoryTest.php | 2 +- tests/Composer/Test/Repository/ArtifactRepositoryTest.php | 2 +- tests/Composer/Test/Repository/ComposerRepositoryTest.php | 2 +- tests/Composer/Test/Repository/CompositeRepositoryTest.php | 2 +- tests/Composer/Test/Repository/FilesystemRepositoryTest.php | 2 +- tests/Composer/Test/Repository/Pear/ChannelReaderTest.php | 2 +- .../Test/Repository/Pear/ChannelRest10ReaderTest.php | 2 +- .../Test/Repository/Pear/ChannelRest11ReaderTest.php | 2 +- .../Test/Repository/Pear/PackageDependencyParserTest.php | 2 +- tests/Composer/Test/Repository/PearRepositoryTest.php | 2 +- tests/Composer/Test/Util/ErrorHandlerTest.php | 2 +- tests/Composer/Test/Util/FilesystemTest.php | 2 +- tests/Composer/Test/Util/ProcessExecutorTest.php | 2 +- tests/Composer/Test/Util/SpdxLicenseIdentifierTest.php | 2 +- tests/Composer/{Test => }/TestCase.php | 2 +- tests/bootstrap.php | 2 ++ 33 files changed, 37 insertions(+), 30 deletions(-) rename tests/Composer/{Test => }/TestCase.php (98%) diff --git a/.travis.yml b/.travis.yml index a897f3cee..ad72478df 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,10 +6,12 @@ php: - 5.4 - 5.5 -before_script: +before_script: + - sudo apt-get install parallel - echo '' > ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini - composer install --dev --prefer-source - git config --global user.name travis-ci - git config --global user.email travis@example.com -script: ./vendor/bin/phpunit -c tests/complete.phpunit.xml +script: + - ls -d tests/Composer/Test/* | parallel --gnu --keep-order 'echo "Running {} tests"; ./vendor/bin/phpunit -c tests/complete.phpunit.xml {};' || exit 1 diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index 1fe825197..cecdfb4a3 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -17,7 +17,7 @@ use Composer\Package\Link; use Composer\Util\Filesystem; use Composer\Package\AliasPackage; use Composer\Package\Package; -use Composer\Test\TestCase; +use Composer\TestCase; use Composer\Script\ScriptEvents; class AutoloadGeneratorTest extends TestCase diff --git a/tests/Composer/Test/CacheTest.php b/tests/Composer/Test/CacheTest.php index ba2ea77ad..80c7de6bf 100644 --- a/tests/Composer/Test/CacheTest.php +++ b/tests/Composer/Test/CacheTest.php @@ -13,6 +13,7 @@ namespace Composer\Test; use Composer\Cache; +use Composer\TestCase; class CacheTest extends TestCase { diff --git a/tests/Composer/Test/Command/InitCommandTest.php b/tests/Composer/Test/Command/InitCommandTest.php index 4b295ef16..dbcbe0bda 100644 --- a/tests/Composer/Test/Command/InitCommandTest.php +++ b/tests/Composer/Test/Command/InitCommandTest.php @@ -13,7 +13,7 @@ namespace Composer\Test\Command; use Composer\Command\InitCommand; -use Composer\Test\TestCase; +use Composer\TestCase; class InitCommandTest extends TestCase { diff --git a/tests/Composer/Test/ComposerTest.php b/tests/Composer/Test/ComposerTest.php index 023cee1f8..f667e88e5 100644 --- a/tests/Composer/Test/ComposerTest.php +++ b/tests/Composer/Test/ComposerTest.php @@ -13,6 +13,7 @@ namespace Composer\Test; use Composer\Composer; +use Composer\TestCase; class ComposerTest extends TestCase { diff --git a/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php b/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php index 4d50fa6c5..9e9952228 100644 --- a/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php +++ b/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php @@ -19,7 +19,7 @@ use Composer\DependencyResolver\Pool; use Composer\Package\Link; use Composer\Package\AliasPackage; use Composer\Package\LinkConstraint\VersionConstraint; -use Composer\Test\TestCase; +use Composer\TestCase; class DefaultPolicyTest extends TestCase { diff --git a/tests/Composer/Test/DependencyResolver/PoolTest.php b/tests/Composer/Test/DependencyResolver/PoolTest.php index aa38fa31d..14b24fc9f 100644 --- a/tests/Composer/Test/DependencyResolver/PoolTest.php +++ b/tests/Composer/Test/DependencyResolver/PoolTest.php @@ -15,7 +15,7 @@ namespace Composer\Test\DependencyResolver; use Composer\DependencyResolver\Pool; use Composer\Repository\ArrayRepository; use Composer\Package\BasePackage; -use Composer\Test\TestCase; +use Composer\TestCase; class PoolTest extends TestCase { diff --git a/tests/Composer/Test/DependencyResolver/RequestTest.php b/tests/Composer/Test/DependencyResolver/RequestTest.php index 89639bc44..d8cb865a0 100644 --- a/tests/Composer/Test/DependencyResolver/RequestTest.php +++ b/tests/Composer/Test/DependencyResolver/RequestTest.php @@ -15,7 +15,7 @@ namespace Composer\Test\DependencyResolver; use Composer\DependencyResolver\Request; use Composer\DependencyResolver\Pool; use Composer\Repository\ArrayRepository; -use Composer\Test\TestCase; +use Composer\TestCase; class RequestTest extends TestCase { diff --git a/tests/Composer/Test/DependencyResolver/RuleSetTest.php b/tests/Composer/Test/DependencyResolver/RuleSetTest.php index a6b108500..35e3f17d6 100644 --- a/tests/Composer/Test/DependencyResolver/RuleSetTest.php +++ b/tests/Composer/Test/DependencyResolver/RuleSetTest.php @@ -16,7 +16,7 @@ use Composer\DependencyResolver\Rule; use Composer\DependencyResolver\RuleSet; use Composer\DependencyResolver\Pool; use Composer\Repository\ArrayRepository; -use Composer\Test\TestCase; +use Composer\TestCase; class RuleSetTest extends TestCase { diff --git a/tests/Composer/Test/DependencyResolver/RuleTest.php b/tests/Composer/Test/DependencyResolver/RuleTest.php index 8d4c732a2..10667632d 100644 --- a/tests/Composer/Test/DependencyResolver/RuleTest.php +++ b/tests/Composer/Test/DependencyResolver/RuleTest.php @@ -15,7 +15,7 @@ namespace Composer\Test\DependencyResolver; use Composer\DependencyResolver\Rule; use Composer\DependencyResolver\Pool; use Composer\Repository\ArrayRepository; -use Composer\Test\TestCase; +use Composer\TestCase; class RuleTest extends TestCase { diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index 5773d62ee..349f6e3b4 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -18,7 +18,7 @@ use Composer\DependencyResolver\Request; use Composer\DependencyResolver\Solver; use Composer\DependencyResolver\SolverProblemsException; use Composer\Package\Link; -use Composer\Test\TestCase; +use Composer\TestCase; use Composer\Package\LinkConstraint\MultiConstraint; class SolverTest extends TestCase diff --git a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php index 7a15679d1..fd26b0a3c 100644 --- a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php +++ b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php @@ -14,7 +14,7 @@ namespace Composer\Test\EventDispatcher; use Composer\EventDispatcher\Event; use Composer\EventDispatcher\EventDispatcher; -use Composer\Test\TestCase; +use Composer\TestCase; use Composer\Script; use Composer\Util\ProcessExecutor; diff --git a/tests/Composer/Test/IO/ConsoleIOTest.php b/tests/Composer/Test/IO/ConsoleIOTest.php index 0d76758d4..3a4313f69 100644 --- a/tests/Composer/Test/IO/ConsoleIOTest.php +++ b/tests/Composer/Test/IO/ConsoleIOTest.php @@ -13,7 +13,7 @@ namespace Composer\Test\IO; use Composer\IO\ConsoleIO; -use Composer\Test\TestCase; +use Composer\TestCase; class ConsoleIOTest extends TestCase { diff --git a/tests/Composer/Test/IO/NullIOTest.php b/tests/Composer/Test/IO/NullIOTest.php index cb2023d49..feb586f95 100644 --- a/tests/Composer/Test/IO/NullIOTest.php +++ b/tests/Composer/Test/IO/NullIOTest.php @@ -13,7 +13,7 @@ namespace Composer\Test\IO; use Composer\IO\NullIO; -use Composer\Test\TestCase; +use Composer\TestCase; class NullIOTest extends TestCase { diff --git a/tests/Composer/Test/Installer/LibraryInstallerTest.php b/tests/Composer/Test/Installer/LibraryInstallerTest.php index dd36e6184..5ea4f076b 100644 --- a/tests/Composer/Test/Installer/LibraryInstallerTest.php +++ b/tests/Composer/Test/Installer/LibraryInstallerTest.php @@ -14,7 +14,7 @@ namespace Composer\Test\Installer; use Composer\Installer\LibraryInstaller; use Composer\Util\Filesystem; -use Composer\Test\TestCase; +use Composer\TestCase; use Composer\Composer; use Composer\Config; diff --git a/tests/Composer/Test/InstallerTest.php b/tests/Composer/Test/InstallerTest.php index e3ec2b927..bd9e7d3b6 100644 --- a/tests/Composer/Test/InstallerTest.php +++ b/tests/Composer/Test/InstallerTest.php @@ -27,6 +27,7 @@ use Composer\Test\Mock\InstalledFilesystemRepositoryMock; use Composer\Test\Mock\InstallationManagerMock; use Symfony\Component\Console\Input\StringInput; use Symfony\Component\Console\Output\StreamOutput; +use Composer\TestCase; class InstallerTest extends TestCase { diff --git a/tests/Composer/Test/Package/CompletePackageTest.php b/tests/Composer/Test/Package/CompletePackageTest.php index b6f90928c..de119ebaa 100644 --- a/tests/Composer/Test/Package/CompletePackageTest.php +++ b/tests/Composer/Test/Package/CompletePackageTest.php @@ -14,7 +14,7 @@ namespace Composer\Test\Package; use Composer\Package\Package; use Composer\Package\Version\VersionParser; -use Composer\Test\TestCase; +use Composer\TestCase; class CompletePackageTest extends TestCase { diff --git a/tests/Composer/Test/Repository/ArrayRepositoryTest.php b/tests/Composer/Test/Repository/ArrayRepositoryTest.php index 6852f7dd6..434b3da99 100644 --- a/tests/Composer/Test/Repository/ArrayRepositoryTest.php +++ b/tests/Composer/Test/Repository/ArrayRepositoryTest.php @@ -13,7 +13,7 @@ namespace Composer\Test\Repository; use Composer\Repository\ArrayRepository; -use Composer\Test\TestCase; +use Composer\TestCase; class ArrayRepositoryTest extends TestCase { diff --git a/tests/Composer/Test/Repository/ArtifactRepositoryTest.php b/tests/Composer/Test/Repository/ArtifactRepositoryTest.php index 5ffae515a..109b53bfb 100644 --- a/tests/Composer/Test/Repository/ArtifactRepositoryTest.php +++ b/tests/Composer/Test/Repository/ArtifactRepositoryTest.php @@ -12,7 +12,7 @@ namespace Composer\Repository; -use Composer\Test\TestCase; +use Composer\TestCase; use Composer\IO\NullIO; use Composer\Config; use Composer\Package\BasePackage; diff --git a/tests/Composer/Test/Repository/ComposerRepositoryTest.php b/tests/Composer/Test/Repository/ComposerRepositoryTest.php index bad24d6d4..5109ee41f 100644 --- a/tests/Composer/Test/Repository/ComposerRepositoryTest.php +++ b/tests/Composer/Test/Repository/ComposerRepositoryTest.php @@ -15,7 +15,7 @@ namespace Composer\Test\Repository; use Composer\Repository\ComposerRepository; use Composer\IO\NullIO; use Composer\Test\Mock\FactoryMock; -use Composer\Test\TestCase; +use Composer\TestCase; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Version\VersionParser; diff --git a/tests/Composer/Test/Repository/CompositeRepositoryTest.php b/tests/Composer/Test/Repository/CompositeRepositoryTest.php index 978587133..d9f8b70e3 100644 --- a/tests/Composer/Test/Repository/CompositeRepositoryTest.php +++ b/tests/Composer/Test/Repository/CompositeRepositoryTest.php @@ -14,7 +14,7 @@ namespace Composer\Test\Repository; use Composer\Repository\CompositeRepository; use Composer\Repository\ArrayRepository; -use Composer\Test\TestCase; +use Composer\TestCase; class CompositeRepositoryTest extends TestCase { diff --git a/tests/Composer/Test/Repository/FilesystemRepositoryTest.php b/tests/Composer/Test/Repository/FilesystemRepositoryTest.php index f80a91889..fa6214dee 100644 --- a/tests/Composer/Test/Repository/FilesystemRepositoryTest.php +++ b/tests/Composer/Test/Repository/FilesystemRepositoryTest.php @@ -13,7 +13,7 @@ namespace Composer\Repository; use Composer\Repository\FilesystemRepository; -use Composer\Test\TestCase; +use Composer\TestCase; class FilesystemRepositoryTest extends TestCase { diff --git a/tests/Composer/Test/Repository/Pear/ChannelReaderTest.php b/tests/Composer/Test/Repository/Pear/ChannelReaderTest.php index 127c5689c..214d7b702 100644 --- a/tests/Composer/Test/Repository/Pear/ChannelReaderTest.php +++ b/tests/Composer/Test/Repository/Pear/ChannelReaderTest.php @@ -12,7 +12,7 @@ namespace Composer\Repository\Pear; -use Composer\Test\TestCase; +use Composer\TestCase; use Composer\Package\Version\VersionParser; use Composer\Package\LinkConstraint\VersionConstraint; use Composer\Package\Link; diff --git a/tests/Composer/Test/Repository/Pear/ChannelRest10ReaderTest.php b/tests/Composer/Test/Repository/Pear/ChannelRest10ReaderTest.php index ac4f377be..299eae37b 100644 --- a/tests/Composer/Test/Repository/Pear/ChannelRest10ReaderTest.php +++ b/tests/Composer/Test/Repository/Pear/ChannelRest10ReaderTest.php @@ -12,7 +12,7 @@ namespace Composer\Repository\Pear; -use Composer\Test\TestCase; +use Composer\TestCase; use Composer\Test\Mock\RemoteFilesystemMock; class ChannelRest10ReaderTest extends TestCase diff --git a/tests/Composer/Test/Repository/Pear/ChannelRest11ReaderTest.php b/tests/Composer/Test/Repository/Pear/ChannelRest11ReaderTest.php index 58105a5eb..08420786e 100644 --- a/tests/Composer/Test/Repository/Pear/ChannelRest11ReaderTest.php +++ b/tests/Composer/Test/Repository/Pear/ChannelRest11ReaderTest.php @@ -12,7 +12,7 @@ namespace Composer\Repository\Pear; -use Composer\Test\TestCase; +use Composer\TestCase; use Composer\Test\Mock\RemoteFilesystemMock; class ChannelRest11ReaderTest extends TestCase diff --git a/tests/Composer/Test/Repository/Pear/PackageDependencyParserTest.php b/tests/Composer/Test/Repository/Pear/PackageDependencyParserTest.php index c2d77aef0..4f43d39f0 100644 --- a/tests/Composer/Test/Repository/Pear/PackageDependencyParserTest.php +++ b/tests/Composer/Test/Repository/Pear/PackageDependencyParserTest.php @@ -12,7 +12,7 @@ namespace Composer\Repository\Pear; -use Composer\Test\TestCase; +use Composer\TestCase; class PackageDependencyParserTest extends TestCase { diff --git a/tests/Composer/Test/Repository/PearRepositoryTest.php b/tests/Composer/Test/Repository/PearRepositoryTest.php index 35e05fc2c..a42c8e0b3 100644 --- a/tests/Composer/Test/Repository/PearRepositoryTest.php +++ b/tests/Composer/Test/Repository/PearRepositoryTest.php @@ -12,7 +12,7 @@ namespace Composer\Repository; -use Composer\Test\TestCase; +use Composer\TestCase; /** * @group slow diff --git a/tests/Composer/Test/Util/ErrorHandlerTest.php b/tests/Composer/Test/Util/ErrorHandlerTest.php index e24fe3f39..485c2bd39 100644 --- a/tests/Composer/Test/Util/ErrorHandlerTest.php +++ b/tests/Composer/Test/Util/ErrorHandlerTest.php @@ -13,7 +13,7 @@ namespace Composer\Test\Util; use Composer\Util\ErrorHandler; -use Composer\Test\TestCase; +use Composer\TestCase; /** * ErrorHandler test case diff --git a/tests/Composer/Test/Util/FilesystemTest.php b/tests/Composer/Test/Util/FilesystemTest.php index 88fad9289..3b565ded4 100644 --- a/tests/Composer/Test/Util/FilesystemTest.php +++ b/tests/Composer/Test/Util/FilesystemTest.php @@ -13,7 +13,7 @@ namespace Composer\Test\Util; use Composer\Util\Filesystem; -use Composer\Test\TestCase; +use Composer\TestCase; class FilesystemTest extends TestCase { diff --git a/tests/Composer/Test/Util/ProcessExecutorTest.php b/tests/Composer/Test/Util/ProcessExecutorTest.php index 716a2daa7..b15a2763f 100644 --- a/tests/Composer/Test/Util/ProcessExecutorTest.php +++ b/tests/Composer/Test/Util/ProcessExecutorTest.php @@ -13,7 +13,7 @@ namespace Composer\Test\Util; use Composer\Util\ProcessExecutor; -use Composer\Test\TestCase; +use Composer\TestCase; class ProcessExecutorTest extends TestCase { diff --git a/tests/Composer/Test/Util/SpdxLicenseIdentifierTest.php b/tests/Composer/Test/Util/SpdxLicenseIdentifierTest.php index 2ed7c1819..b6cee4ec5 100644 --- a/tests/Composer/Test/Util/SpdxLicenseIdentifierTest.php +++ b/tests/Composer/Test/Util/SpdxLicenseIdentifierTest.php @@ -1,7 +1,7 @@ add('Composer\Test', __DIR__); + +require __DIR__.'/Composer/TestCase.php'; From 807600b255cafa7689071d09d75b1ddffb535c57 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 25 Sep 2013 21:07:55 +0200 Subject: [PATCH 104/238] Fix edge case where one adds a target-dir on a package that didnt have one before, refs #2279 --- src/Composer/Installer/LibraryInstaller.php | 10 +++++++++- tests/Composer/Test/Installer/LibraryInstallerTest.php | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index cb3808295..9d78ba1e6 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -161,7 +161,15 @@ class LibraryInstaller implements InstallerInterface $initialDownloadPath = $this->getInstallPath($initial); $targetDownloadPath = $this->getInstallPath($target); if ($targetDownloadPath !== $initialDownloadPath) { - $this->filesystem->copyThenRemove($initialDownloadPath, $targetDownloadPath); + // if the target is part of the initial dir, we force a remove + install + // to avoid the rename wiping the target dir as part of the initial dir cleanup + if (strpos($initialDownloadPath, $targetDownloadPath) === 0) { + $this->removeCode($initial); + $this->installCode($target); + return; + } + + $this->filesystem->rename($initialDownloadPath, $targetDownloadPath); } $this->downloadManager->update($initial, $target, $targetDownloadPath); } diff --git a/tests/Composer/Test/Installer/LibraryInstallerTest.php b/tests/Composer/Test/Installer/LibraryInstallerTest.php index 245969618..56e7e7415 100644 --- a/tests/Composer/Test/Installer/LibraryInstallerTest.php +++ b/tests/Composer/Test/Installer/LibraryInstallerTest.php @@ -135,7 +135,7 @@ class LibraryInstallerTest extends TestCase ->getMock(); $filesystem ->expects($this->once()) - ->method('copyThenRemove') + ->method('rename') ->with($this->vendorDir.'/package1', $this->vendorDir.'/package1/newtarget'); $initial = $this->createPackageMock(); From 30049637dc1455b72c08763d448869ab82edded7 Mon Sep 17 00:00:00 2001 From: Marc Date: Thu, 26 Sep 2013 01:57:21 +0200 Subject: [PATCH 105/238] Set some phpdoc to isLocalUrl --- src/Composer/Repository/Vcs/VcsDriver.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Composer/Repository/Vcs/VcsDriver.php b/src/Composer/Repository/Vcs/VcsDriver.php index f6d428802..84b209bd3 100644 --- a/src/Composer/Repository/Vcs/VcsDriver.php +++ b/src/Composer/Repository/Vcs/VcsDriver.php @@ -101,6 +101,11 @@ abstract class VcsDriver implements VcsDriverInterface return $this->remoteFilesystem->getContents($this->originUrl, $url, false); } + /** + * Return if current repository url is local + * + * @return boolean Repository url is local + */ protected static function isLocalUrl($url) { return (bool) preg_match('{^(file://|/|[a-z]:[\\\\/])}i', $url); From 3f6227a996bf575af612e3244258c4d1b4a3bf16 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 26 Sep 2013 11:38:33 +0200 Subject: [PATCH 106/238] Add workaround for php bug 53460 glob() can return false, fixes #2278 --- src/Composer/Command/CreateProjectCommand.php | 6 +++--- src/Composer/Downloader/ArchiveDownloader.php | 2 +- src/Composer/Installer/ProjectInstaller.php | 5 ++++- src/Composer/Util/Filesystem.php | 13 +++++++++++++ 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index ccf14fde3..a4c14b162 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -152,6 +152,7 @@ EOT } $composer = Factory::create($io, null, $disablePlugins); + $fs = new Filesystem(); if ($noScripts === false) { // dispatch event @@ -187,7 +188,6 @@ EOT } try { - $fs = new Filesystem(); $dirs = iterator_to_array($finder); unset($finder); foreach ($dirs as $dir) { @@ -222,10 +222,10 @@ EOT chdir($oldCwd); $vendorComposerDir = $composer->getConfig()->get('vendor-dir').'/composer'; - if (is_dir($vendorComposerDir) && glob($vendorComposerDir.'/*') === array() && count(glob($vendorComposerDir.'/.*')) === 2) { + if (is_dir($vendorComposerDir) && $fs->isDirEmpty($vendorComposerDir)) { @rmdir($vendorComposerDir); $vendorDir = $composer->getConfig()->get('vendor-dir'); - if (is_dir($vendorDir) && glob($vendorDir.'/*') === array() && count(glob($vendorDir.'/.*')) === 2) { + if (is_dir($vendorDir) && $fs->isDirEmpty($vendorDir)) { @rmdir($vendorDir); } } diff --git a/src/Composer/Downloader/ArchiveDownloader.php b/src/Composer/Downloader/ArchiveDownloader.php index f53798a00..3f1cc4117 100644 --- a/src/Composer/Downloader/ArchiveDownloader.php +++ b/src/Composer/Downloader/ArchiveDownloader.php @@ -132,7 +132,7 @@ abstract class ArchiveDownloader extends FileDownloader */ private function listFiles($dir) { - $files = array_merge(glob($dir . '/.*'), glob($dir . '/*')); + $files = array_merge(glob($dir . '/.*') ?: array(), glob($dir . '/*') ?: array()); return array_values(array_filter($files, function ($el) { return basename($el) !== '.' && basename($el) !== '..'; diff --git a/src/Composer/Installer/ProjectInstaller.php b/src/Composer/Installer/ProjectInstaller.php index 5d98722c8..c79238b36 100644 --- a/src/Composer/Installer/ProjectInstaller.php +++ b/src/Composer/Installer/ProjectInstaller.php @@ -15,6 +15,7 @@ namespace Composer\Installer; use Composer\Package\PackageInterface; use Composer\Downloader\DownloadManager; use Composer\Repository\InstalledRepositoryInterface; +use Composer\Util\Filesystem; /** * Project Installer is used to install a single package into a directory as @@ -26,11 +27,13 @@ class ProjectInstaller implements InstallerInterface { private $installPath; private $downloadManager; + private $filesystem; public function __construct($installPath, DownloadManager $dm) { $this->installPath = rtrim(strtr($installPath, '\\', '/'), '/').'/'; $this->downloadManager = $dm; + $this->filesystem = new Filesystem; } /** @@ -58,7 +61,7 @@ class ProjectInstaller implements InstallerInterface public function install(InstalledRepositoryInterface $repo, PackageInterface $package) { $installPath = $this->installPath; - if (file_exists($installPath) && (count(glob($installPath.'*')) || (count(glob($installPath.'.*')) > 2))) { + if (file_exists($installPath) && !$this->filesystem->isDirEmpty($installPath)) { throw new \InvalidArgumentException("Project directory $installPath is not empty."); } if (!is_dir($installPath)) { diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index bdef6e402..9b7f04901 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -41,6 +41,19 @@ class Filesystem return false; } + /** + * Checks if a directory is empty + * + * @param string $dir + * @return bool + */ + public function isDirEmpty($dir) + { + $dir = rtrim($dir, '/\\'); + + return count(glob($dir.'/*') ?: array()) === 0 && count(glob($dir.'/.*') ?: array()) === 2; + } + /** * Recursively remove a directory * From 3f8836ff1090ca7f5945c1e893f789ec9f05694c Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 26 Sep 2013 12:00:12 +0200 Subject: [PATCH 107/238] Fix some docs --- doc/03-cli.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index be0b252e8..4202c75eb 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -82,7 +82,7 @@ resolution. * **--dev:** Install packages listed in `require-dev` (this is the default behavior). * **--no-dev:** Skip installing packages listed in `require-dev`. * **--no-scripts:** Skips execution of scripts defined in `composer.json`. -* **--no-custom-installers:** Disables custom installers. +* **--no-plugins:** Disables plugins. * **--no-progress:** Removes the progress display that can mess with some terminals or scripts which don't handle backspace characters. * **--optimize-autoloader (-o):** Convert PSR-0 autoloading to classmap to get a faster @@ -115,7 +115,7 @@ You can also use wildcards to update a bunch of packages at once: * **--dev:** Install packages listed in `require-dev` (this is the default behavior). * **--no-dev:** Skip installing packages listed in `require-dev`. * **--no-scripts:** Skips execution of scripts defined in `composer.json`. -* **--no-custom-installers:** Disables custom installers. +* **--no-plugins:** Disables plugins. * **--no-progress:** Removes the progress display that can mess with some terminals or scripts which don't handle backspace characters. * **--optimize-autoloader (-o):** Convert PSR-0 autoloading to classmap to get a faster @@ -346,7 +346,8 @@ By default the command checks for the packages on packagist.org. * **--prefer-source:** Install packages from `source` when available. * **--prefer-dist:** Install packages from `dist` when available. * **--dev:** Install packages listed in `require-dev`. -* **--no-custom-installers:** Disables custom installers. +* **--no-install:** Disables installation of the vendors. +* **--no-plugins:** Disables plugins. * **--no-scripts:** Disables the execution of the scripts defined in the root package. * **--no-progress:** Removes the progress display that can mess with some From 46e82cb38d96d4b2ca875c877922d84f5f0459cc Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 26 Sep 2013 12:23:57 +0200 Subject: [PATCH 108/238] Retry json file writing 3 times before failing, fixes #2286 --- src/Composer/Json/JsonFile.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Composer/Json/JsonFile.php b/src/Composer/Json/JsonFile.php index f7e1a2126..155f17e6e 100644 --- a/src/Composer/Json/JsonFile.php +++ b/src/Composer/Json/JsonFile.php @@ -117,7 +117,21 @@ class JsonFile ); } } - file_put_contents($this->path, static::encode($hash, $options). ($options & self::JSON_PRETTY_PRINT ? "\n" : '')); + + $retries = 3; + while ($retries--) { + try { + file_put_contents($this->path, static::encode($hash, $options). ($options & self::JSON_PRETTY_PRINT ? "\n" : '')); + break; + } catch (\Exception $e) { + if ($retries) { + usleep(500000); + continue; + } + + throw $e; + } + } } /** From 05ffc605f1f68cc6a7f11429052816ed64f908ba Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 26 Sep 2013 12:49:50 +0200 Subject: [PATCH 109/238] Ignore chmod failures, fixes #1854 --- src/Composer/Command/ConfigCommand.php | 2 +- src/Composer/Command/SelfUpdateCommand.php | 2 +- src/Composer/Config/JsonConfigSource.php | 2 +- src/Composer/Installer/LibraryInstaller.php | 6 +++--- src/Composer/Installer/PearInstaller.php | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Composer/Command/ConfigCommand.php b/src/Composer/Command/ConfigCommand.php index 3459569a7..7f92b2503 100644 --- a/src/Composer/Command/ConfigCommand.php +++ b/src/Composer/Command/ConfigCommand.php @@ -117,7 +117,7 @@ EOT if ($input->getOption('global') && !$this->configFile->exists()) { touch($this->configFile->getPath()); $this->configFile->write(array('config' => new \ArrayObject)); - chmod($this->configFile->getPath(), 0600); + @chmod($this->configFile->getPath(), 0600); } if (!$this->configFile->exists()) { diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index 07ed9eae1..d37598b04 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -72,7 +72,7 @@ EOT } try { - chmod($tempFilename, 0777 & ~umask()); + @chmod($tempFilename, 0777 & ~umask()); // test the phar validity $phar = new \Phar($tempFilename); // free the variable to unlock the file diff --git a/src/Composer/Config/JsonConfigSource.php b/src/Composer/Config/JsonConfigSource.php index 27d922853..5223eb5d2 100644 --- a/src/Composer/Config/JsonConfigSource.php +++ b/src/Composer/Config/JsonConfigSource.php @@ -124,7 +124,7 @@ class JsonConfigSource implements ConfigSourceInterface } if ($newFile) { - chmod($this->file->getPath(), 0600); + @chmod($this->file->getPath(), 0600); } } } diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index 9d78ba1e6..c883120f4 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -205,7 +205,7 @@ class LibraryInstaller implements InstallerInterface // likely leftover from a previous install, make sure // that the target is still executable in case this // is a fresh install of the vendor. - chmod($link, 0777 & ~umask()); + @chmod($link, 0777 & ~umask()); } $this->io->write(' Skipped installation of '.$bin.' for package '.$package->getName().': name conflicts with an existing file'); continue; @@ -214,7 +214,7 @@ class LibraryInstaller implements InstallerInterface // add unixy support for cygwin and similar environments if ('.bat' !== substr($binPath, -4)) { file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link)); - chmod($link, 0777 & ~umask()); + @chmod($link, 0777 & ~umask()); $link .= '.bat'; if (file_exists($link)) { $this->io->write(' Skipped installation of '.$bin.'.bat proxy for package '.$package->getName().': a .bat proxy was already installed'); @@ -238,7 +238,7 @@ class LibraryInstaller implements InstallerInterface } chdir($cwd); } - chmod($link, 0777 & ~umask()); + @chmod($link, 0777 & ~umask()); } } diff --git a/src/Composer/Installer/PearInstaller.php b/src/Composer/Installer/PearInstaller.php index 1a8f674af..b44f61f14 100644 --- a/src/Composer/Installer/PearInstaller.php +++ b/src/Composer/Installer/PearInstaller.php @@ -99,9 +99,9 @@ class PearInstaller extends LibraryInstaller { parent::initializeBinDir(); file_put_contents($this->binDir.'/composer-php', $this->generateUnixyPhpProxyCode()); - chmod($this->binDir.'/composer-php', 0777); + @chmod($this->binDir.'/composer-php', 0777); file_put_contents($this->binDir.'/composer-php.bat', $this->generateWindowsPhpProxyCode()); - chmod($this->binDir.'/composer-php.bat', 0777); + @chmod($this->binDir.'/composer-php.bat', 0777); } protected function generateWindowsProxyCode($bin, $link) From 3c0a620ad5391821e794cc87617fc81200e89e68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Thu, 26 Sep 2013 14:34:41 +0200 Subject: [PATCH 110/238] Fixed path analysis --- src/Composer/Autoload/AutoloadGenerator.php | 2 +- src/Composer/Util/Filesystem.php | 16 +++++----- .../Test/Autoload/AutoloadGeneratorTest.php | 31 +++++++++++++++++++ tests/Composer/Test/Util/FilesystemTest.php | 4 +++ 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 7c5821025..e5cceb43a 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -328,7 +328,7 @@ EOF; $path = $filesystem->normalizePath($path); $baseDir = ''; - if (strpos($path, $vendorPath) === 0) { + if (strpos($path.'/', $vendorPath.'/') === 0) { $path = substr($path, strlen($vendorPath)); $baseDir = '$vendorDir'; diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index 9b7f04901..7ed74dfaf 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -222,12 +222,12 @@ class Filesystem return './'.basename($to); } - $commonPath = $to.'/'; - while (strpos($from, $commonPath) !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) { - $commonPath = strtr(dirname($commonPath), '\\', '/'); + $commonPath = $to; + while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) { + $commonPath = dirname($commonPath); } - if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) { + if (0 !== strpos($from, $commonPath) || '/' === $commonPath) { return $to; } @@ -260,12 +260,12 @@ class Filesystem return $directories ? '__DIR__' : '__FILE__'; } - $commonPath = $to.'/'; - while (strpos($from, $commonPath) !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) { - $commonPath = strtr(dirname($commonPath), '\\', '/'); + $commonPath = $to; + while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) { + $commonPath = dirname($commonPath); } - if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) { + if (0 !== strpos($from, $commonPath) || '/' === $commonPath) { return var_export($to, true); } diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index cecdfb4a3..7a1609926 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -869,6 +869,37 @@ EOF; $this->assertEquals($expectedClassmap, file_get_contents($this->vendorDir.'/composer/autoload_classmap.php')); } + public function testVendorSubstringPath() + { + $package = new Package('a', '1.0', '1.0'); + $package->setAutoload(array( + 'psr-0' => array('Foo' => 'composer-test-autoload-src/src'), + )); + + $this->repository->expects($this->once()) + ->method('getCanonicalPackages') + ->will($this->returnValue(array())); + + $this->fs->ensureDirectoryExists($this->vendorDir.'/a'); + + $expectedNamespace = <<<'EOF' + array($baseDir . '/composer-test-autoload-src/src'), +); + +EOF; + + $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, 'VendorSubstring'); + $this->assertEquals($expectedNamespace, file_get_contents($this->vendorDir.'/composer/autoload_namespaces.php')); + } + private function assertAutoloadFiles($name, $dir, $type = 'namespaces') { $a = __DIR__.'/Fixtures/autoload_'.$name.'.php'; diff --git a/tests/Composer/Test/Util/FilesystemTest.php b/tests/Composer/Test/Util/FilesystemTest.php index 3b565ded4..29e7d8c62 100644 --- a/tests/Composer/Test/Util/FilesystemTest.php +++ b/tests/Composer/Test/Util/FilesystemTest.php @@ -60,6 +60,8 @@ class FilesystemTest extends TestCase array('C:/Temp/../..', 'd:\Temp\..\..\test', true, "'d:/test'"), array('/foo/bar', '/foo/bar_vendor', true, "dirname(__DIR__).'/bar_vendor'"), array('/foo/bar_vendor', '/foo/bar', true, "dirname(__DIR__).'/bar'"), + array('/foo/bar_vendor', '/foo/bar/src', true, "dirname(__DIR__).'/bar/src'"), + array('/foo/bar_vendor/src2', '/foo/bar/src/lib', true, "dirname(dirname(__DIR__)).'/bar/src/lib'"), ); } @@ -107,6 +109,8 @@ class FilesystemTest extends TestCase array('/tmp', '/tmp/../../test', '/test', true), array('/foo/bar', '/foo/bar_vendor', '../bar_vendor', true), array('/foo/bar_vendor', '/foo/bar', '../bar', true), + array('/foo/bar_vendor', '/foo/bar/src', '../bar/src', true), + array('/foo/bar_vendor/src2', '/foo/bar/src/lib', '../../bar/src/lib', true), ); } From e34dae4d42a2bbe2ed9eb581f371ae3b00b8c4e2 Mon Sep 17 00:00:00 2001 From: Nicolas Bastien Date: Sat, 28 Sep 2013 06:51:54 +0200 Subject: [PATCH 111/238] [DOC] add link to Monolog library --- doc/articles/aliases.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/articles/aliases.md b/doc/articles/aliases.md index efd7cc6cb..82c462715 100644 --- a/doc/articles/aliases.md +++ b/doc/articles/aliases.md @@ -59,12 +59,12 @@ is a dependency of your local project. For this reason, you can alias packages in your `require` and `require-dev` fields. Let's say you found a bug in the `monolog/monolog` package. You cloned -Monolog on GitHub and fixed the issue in a branch named `bugfix`. Now you want +[Monolog](https://github.com/Seldaek/monolog) on GitHub and fixed the issue in a branch named `bugfix`. Now you want to install that version of monolog in your local project. You are using `symfony/monolog-bundle` which requires `monolog/monolog` version `1.*`. So you need your `dev-bugfix` to match that constraint. - + Just add this to your project's root `composer.json`: { From 6a435f97c8ab5bace565f5c285723cee9c251b84 Mon Sep 17 00:00:00 2001 From: Nicolas Bastien Date: Mon, 30 Sep 2013 00:10:23 +0200 Subject: [PATCH 112/238] Correct line length Correct GromNaN comment --- doc/articles/aliases.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/articles/aliases.md b/doc/articles/aliases.md index 82c462715..9d0cbd44b 100644 --- a/doc/articles/aliases.md +++ b/doc/articles/aliases.md @@ -59,8 +59,9 @@ is a dependency of your local project. For this reason, you can alias packages in your `require` and `require-dev` fields. Let's say you found a bug in the `monolog/monolog` package. You cloned -[Monolog](https://github.com/Seldaek/monolog) on GitHub and fixed the issue in a branch named `bugfix`. Now you want -to install that version of monolog in your local project. +[Monolog](https://github.com/Seldaek/monolog) on GitHub and fixed the issue in +a branch named `bugfix`. Now you want to install that version of monolog in your +local project. You are using `symfony/monolog-bundle` which requires `monolog/monolog` version `1.*`. So you need your `dev-bugfix` to match that constraint. From 1c2213ef5da84dfc3a321f15515ee1cfbb4053e9 Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Wed, 2 Oct 2013 01:11:53 +0200 Subject: [PATCH 113/238] Format the possible version formats as a table Note I: This syntax is supported by MarkdownExtra, which both getcomposer and github are using. Note II: This patch currently breaks the PDF, because pandoc does not like non-standard markdown tables. Ideas for fixing this appreciated. Note III: The idea for this patch came up a few weeks ago on IRC. We agreed back then that a table would be a good idea. Note IIII: This patch creates a stability section which opens the door for finally documenting how stability works in the composer docs. --- doc/01-basic-usage.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/doc/01-basic-usage.md b/doc/01-basic-usage.md index bc4a88c1e..89b77a43b 100644 --- a/doc/01-basic-usage.md +++ b/doc/01-basic-usage.md @@ -58,31 +58,31 @@ smaller decoupled parts. ### Package Versions -We are requiring version `1.0.*` of monolog. This means any version in the `1.0` -development branch. It would match `1.0.0`, `1.0.2` or `1.0.20`. +In the previous example we were requiring version `1.0.*` of monolog. This +means any version in the `1.0` development branch. It would match `1.0.0`, +`1.0.2` or `1.0.20`. Version constraints can be specified in a few different ways. -* **Exact version:** You can specify the exact version of a package, for - example `1.0.2`. +Name | Example | Description +-------------- | --------------------- | ----------- +Exact version | `1.0.2` | You can specify the exact version of a package. +Range | `>=1.0` `>=1.0,<2.0` | By using comparison operators you can specify ranges of valid versions. Valid operators are `>`, `>=`, `<`, `<=`, `!=`. You can define multiple ranges, separated by a comma, which will be treated as a **logical AND**. +Wildcard | `1.0.*` | You can specify a pattern with a `*` wildcard. `1.0.*` is the equivalent of `>=1.0,<1.1`. +Tilde Operator | `~1.2` | Very useful for projects that follow semantic versioning. `~1.2` is equivalent to `>=1.2,<2.0`. For more details, read the next section below. -* **Range:** By using comparison operators you can specify ranges of valid - versions. Valid operators are `>`, `>=`, `<`, `<=`, `!=`. An example range - would be `>=1.0`. You can define multiple ranges, separated by a comma: - `>=1.0,<2.0`. +### Next Significant Release (Tilde Operator) -* **Wildcard:** You can specify a pattern with a `*` wildcard. `1.0.*` is the - equivalent of `>=1.0,<1.1`. +The `~` operator is best explained by example: `~1.2` is equivalent to +`>=1.2,<2.0`, while `~1.2.3` is equivalent to `>=1.2.3,<1.3`. As you can see +it is mostly useful for projects respecting [semantic +versioning](http://semver.org/). A common usage would be to mark the minimum +minor version you depend on, like `~1.2` (which allows anything up to, but not +including, 2.0). Since in theory there should be no backwards compatibility +breaks until 2.0, that works well. Another way of looking at it is that using +`~` specifies a minimum version, but allows the last digit specified to go up. -* **Next Significant Release (Tilde Operator):** The `~` operator is best - explained by example: `~1.2` is equivalent to `>=1.2,<2.0`, while `~1.2.3` is - equivalent to `>=1.2.3,<1.3`. As you can see it is mostly useful for projects - respecting [semantic versioning](http://semver.org/). A common usage would be - to mark the minimum minor version you depend on, like `~1.2` (which allows - anything up to, but not including, 2.0). Since in theory there should be no - backwards compatibility breaks until 2.0, that works well. Another way of - looking at it is that using `~` specifies a minimum version, but allows the - last digit specified to go up. +### Stability By default only stable releases are taken into consideration. If you would like to also get RC, beta, alpha or dev versions of your dependencies you can do From 30b5d2f1fcbafb3d6b90f788175c64dc3dde3868 Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Wed, 2 Oct 2013 12:52:47 +0200 Subject: [PATCH 114/238] Document logical OR constraints --- doc/01-basic-usage.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/01-basic-usage.md b/doc/01-basic-usage.md index 89b77a43b..c353b8b6f 100644 --- a/doc/01-basic-usage.md +++ b/doc/01-basic-usage.md @@ -64,12 +64,12 @@ means any version in the `1.0` development branch. It would match `1.0.0`, Version constraints can be specified in a few different ways. -Name | Example | Description --------------- | --------------------- | ----------- -Exact version | `1.0.2` | You can specify the exact version of a package. -Range | `>=1.0` `>=1.0,<2.0` | By using comparison operators you can specify ranges of valid versions. Valid operators are `>`, `>=`, `<`, `<=`, `!=`. You can define multiple ranges, separated by a comma, which will be treated as a **logical AND**. -Wildcard | `1.0.*` | You can specify a pattern with a `*` wildcard. `1.0.*` is the equivalent of `>=1.0,<1.1`. -Tilde Operator | `~1.2` | Very useful for projects that follow semantic versioning. `~1.2` is equivalent to `>=1.2,<2.0`. For more details, read the next section below. +Name | Example | Description +-------------- | --------------------- | ----------- +Exact version | `1.0.2` | You can specify the exact version of a package. +Range | `>=1.0` `>=1.0,<2.0` `>=1.0,<1.1 | >=1.2` | By using comparison operators you can specify ranges of valid versions. Valid operators are `>`, `>=`, `<`, `<=`, `!=`.
You can define multiple ranges, separated by a comma, which will be treated as a **logical AND**. A pipe symbol `|` will be treated as a **logical OR**.
AND has higher precedence than OR. +Wildcard | `1.0.*` | You can specify a pattern with a `*` wildcard. `1.0.*` is the equivalent of `>=1.0,<1.1`. +Tilde Operator | `~1.2` | Very useful for projects that follow semantic versioning. `~1.2` is equivalent to `>=1.2,<2.0`. For more details, read the next section below. ### Next Significant Release (Tilde Operator) From 52711d121cac362ebc28aa20ceb029faa0fb5384 Mon Sep 17 00:00:00 2001 From: Nicolas Bastien Date: Mon, 7 Oct 2013 17:11:57 +0200 Subject: [PATCH 115/238] Remove unused use statement. --- src/Composer/Command/GlobalCommand.php | 1 - src/Composer/Command/LicensesCommand.php | 2 -- src/Composer/Command/ShowCommand.php | 1 - src/Composer/Command/StatusCommand.php | 1 - src/Composer/Factory.php | 1 - src/Composer/IO/BaseIO.php | 3 --- src/Composer/Installer/LibraryInstaller.php | 1 - src/Composer/Json/JsonFile.php | 1 - src/Composer/Package/Dumper/ArrayDumper.php | 1 - src/Composer/Plugin/CommandEvent.php | 1 - src/Composer/Plugin/PreFileDownloadEvent.php | 2 -- src/Composer/Repository/Vcs/GitHubDriver.php | 1 - src/Composer/Script/CommandEvent.php | 2 -- src/Composer/Util/Git.php | 2 -- 14 files changed, 20 deletions(-) diff --git a/src/Composer/Command/GlobalCommand.php b/src/Composer/Command/GlobalCommand.php index f03a2f04b..0ddfc4ede 100644 --- a/src/Composer/Command/GlobalCommand.php +++ b/src/Composer/Command/GlobalCommand.php @@ -12,7 +12,6 @@ namespace Composer\Command; -use Composer\Installer; use Composer\Factory; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; diff --git a/src/Composer/Command/LicensesCommand.php b/src/Composer/Command/LicensesCommand.php index a927156c4..861b889a0 100644 --- a/src/Composer/Command/LicensesCommand.php +++ b/src/Composer/Command/LicensesCommand.php @@ -12,14 +12,12 @@ namespace Composer\Command; -use Composer\Package\PackageInterface; use Composer\Json\JsonFile; use Composer\Package\Version\VersionParser; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Symfony\Component\Console\Helper\TableHelper; use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index 92f883226..97e315a5b 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -12,7 +12,6 @@ namespace Composer\Command; -use Composer\Composer; use Composer\DependencyResolver\Pool; use Composer\DependencyResolver\DefaultPolicy; use Composer\Factory; diff --git a/src/Composer/Command/StatusCommand.php b/src/Composer/Command/StatusCommand.php index 5edf3b61e..a125bdd3c 100644 --- a/src/Composer/Command/StatusCommand.php +++ b/src/Composer/Command/StatusCommand.php @@ -16,7 +16,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Composer\Downloader\ChangeReportInterface; -use Composer\Downloader\VcsDownloader; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Script\ScriptEvents; diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index d0eaf9371..6875bbc4f 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -16,7 +16,6 @@ use Composer\Config\JsonConfigSource; use Composer\Json\JsonFile; use Composer\IO\IOInterface; use Composer\Package\Archiver; -use Composer\Repository\ComposerRepository; use Composer\Repository\RepositoryManager; use Composer\Repository\RepositoryInterface; use Composer\Util\ProcessExecutor; diff --git a/src/Composer/IO/BaseIO.php b/src/Composer/IO/BaseIO.php index a9cae3b49..29cae4f07 100644 --- a/src/Composer/IO/BaseIO.php +++ b/src/Composer/IO/BaseIO.php @@ -12,9 +12,6 @@ namespace Composer\IO; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Helper\HelperSet; use Composer\Config; abstract class BaseIO implements IOInterface diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index c883120f4..2e6fe8843 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -14,7 +14,6 @@ namespace Composer\Installer; use Composer\Composer; use Composer\IO\IOInterface; -use Composer\Downloader\DownloadManager; use Composer\Repository\InstalledRepositoryInterface; use Composer\Package\PackageInterface; use Composer\Util\Filesystem; diff --git a/src/Composer/Json/JsonFile.php b/src/Composer/Json/JsonFile.php index 155f17e6e..70b97b18d 100644 --- a/src/Composer/Json/JsonFile.php +++ b/src/Composer/Json/JsonFile.php @@ -12,7 +12,6 @@ namespace Composer\Json; -use Composer\Composer; use JsonSchema\Validator; use Seld\JsonLint\JsonParser; use Seld\JsonLint\ParsingException; diff --git a/src/Composer/Package/Dumper/ArrayDumper.php b/src/Composer/Package/Dumper/ArrayDumper.php index bca932d71..be94adec4 100644 --- a/src/Composer/Package/Dumper/ArrayDumper.php +++ b/src/Composer/Package/Dumper/ArrayDumper.php @@ -16,7 +16,6 @@ use Composer\Package\BasePackage; use Composer\Package\PackageInterface; use Composer\Package\CompletePackageInterface; use Composer\Package\RootPackageInterface; -use Composer\Package\Link; /** * @author Konstantin Kudryashiv diff --git a/src/Composer/Plugin/CommandEvent.php b/src/Composer/Plugin/CommandEvent.php index ac2ad2551..0f75bed9e 100644 --- a/src/Composer/Plugin/CommandEvent.php +++ b/src/Composer/Plugin/CommandEvent.php @@ -12,7 +12,6 @@ namespace Composer\Plugin; -use Composer\IO\IOInterface; use Composer\EventDispatcher\Event; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/Composer/Plugin/PreFileDownloadEvent.php b/src/Composer/Plugin/PreFileDownloadEvent.php index 847477e10..38ea2620a 100644 --- a/src/Composer/Plugin/PreFileDownloadEvent.php +++ b/src/Composer/Plugin/PreFileDownloadEvent.php @@ -12,8 +12,6 @@ namespace Composer\Plugin; -use Composer\Composer; -use Composer\IO\IOInterface; use Composer\EventDispatcher\Event; use Composer\Util\RemoteFilesystem; diff --git a/src/Composer/Repository/Vcs/GitHubDriver.php b/src/Composer/Repository/Vcs/GitHubDriver.php index 5efc82629..6345fa473 100644 --- a/src/Composer/Repository/Vcs/GitHubDriver.php +++ b/src/Composer/Repository/Vcs/GitHubDriver.php @@ -16,7 +16,6 @@ use Composer\Downloader\TransportException; use Composer\Json\JsonFile; use Composer\Cache; use Composer\IO\IOInterface; -use Composer\Util\RemoteFilesystem; use Composer\Util\GitHub; /** diff --git a/src/Composer/Script/CommandEvent.php b/src/Composer/Script/CommandEvent.php index 5d8f732c9..48ea2246a 100644 --- a/src/Composer/Script/CommandEvent.php +++ b/src/Composer/Script/CommandEvent.php @@ -12,8 +12,6 @@ namespace Composer\Script; -use Composer\Composer; - /** * The Command Event. * diff --git a/src/Composer/Util/Git.php b/src/Composer/Util/Git.php index 7df6b1d95..4b6fcd6f2 100644 --- a/src/Composer/Util/Git.php +++ b/src/Composer/Util/Git.php @@ -12,8 +12,6 @@ namespace Composer\Util; -use Composer\IO\IOInterface; - /** * @author Jordi Boggiano */ From 65c10daaf85732b5e216aa5d7028d3bd59f0bd91 Mon Sep 17 00:00:00 2001 From: Ruud Denivel Date: Wed, 9 Oct 2013 18:18:34 +0200 Subject: [PATCH 116/238] disable prepend option on install --- src/Composer/Autoload/AutoloadGenerator.php | 10 +++++----- src/Composer/Command/InstallCommand.php | 4 +++- src/Composer/Installer.php | 15 ++++++++++++++- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index e5cceb43a..56dffdbc2 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -37,7 +37,7 @@ class AutoloadGenerator $this->eventDispatcher = $eventDispatcher; } - public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '') + public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '', $prepend = 'true') { $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP); @@ -180,7 +180,7 @@ EOF; file_put_contents($targetDir.'/autoload_files.php', $includeFilesFile); } file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix)); - file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, true, (bool) $includePathFile, $targetDirLoader, (bool) $includeFilesFile, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath)); + file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, true, (bool) $includePathFile, $targetDirLoader, (bool) $includeFilesFile, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prepend)); // use stream_copy_to_stream instead of copy // to work around https://bugs.php.net/bug.php?id=64634 @@ -364,7 +364,7 @@ return ComposerAutoloaderInit$suffix::getLoader(); AUTOLOAD; } - protected function getAutoloadRealFile($usePSR0, $useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath) + protected function getAutoloadRealFile($usePSR0, $useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prepend) { // TODO the class ComposerAutoloaderInit should be revert to a closure // when APC has been fixed: @@ -395,7 +395,7 @@ class ComposerAutoloaderInit$suffix return self::\$loader; } - spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'), true, $prepend); self::\$loader = \$loader = new \\Composer\\Autoload\\ClassLoader(); spl_autoload_unregister(array('ComposerAutoloaderInit$suffix', 'loadClassLoader')); @@ -454,7 +454,7 @@ REGISTER_AUTOLOAD; } $file .= <<register(true); + \$loader->register($prepend); REGISTER_LOADER; diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index 6138009a3..18ed93192 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -43,7 +43,8 @@ class InstallCommand extends Command new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), - new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump') + new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'), + new InputOption('no-prepend', null, InputOption::VALUE_NONE, 'Disables the prepending of the autoloader') )) ->setHelp(<<install command reads the composer.lock file from @@ -101,6 +102,7 @@ EOT ->setDevMode(!$input->getOption('no-dev')) ->setRunScripts(!$input->getOption('no-scripts')) ->setOptimizeAutoloader($input->getOption('optimize-autoloader')) + ->setPrepend(!$input->getOption('no-prepend')) ; if ($input->getOption('no-plugins')) { diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 3e9a9bf6b..b205f65b4 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -106,6 +106,7 @@ class Installer protected $update = false; protected $runScripts = true; protected $updateWhitelist = null; + protected $prepend = 'true'; /** * @var array @@ -280,7 +281,7 @@ class Installer // write autoloader $this->io->write('Generating autoload files'); - $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader); + $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader, '', $this->prepend); if ($this->runScripts) { // dispatch post event @@ -1055,6 +1056,18 @@ class Installer return $this; } + /** + * Generate autoload_real with/without prepend + * + * @param boolean $prepend + * @return Installer + */ + public function setPrepend($prepend = true) + { + $this->prepend = (boolean) $prepend === true ? 'true' : 'false'; + return $this; + } + /** * Disables plugins. * From 05d218604997af12e93eb6f756eeb3d5a6dd4a11 Mon Sep 17 00:00:00 2001 From: Ruud Denivel Date: Wed, 9 Oct 2013 18:27:59 +0200 Subject: [PATCH 117/238] disable prepend option on update --- src/Composer/Command/UpdateCommand.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index ceabf7ff4..357beda6d 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -44,7 +44,8 @@ class UpdateCommand extends Command new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), - new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump') + new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'), + new InputOption('no-prepend', null, InputOption::VALUE_NONE, 'Disables the prepending of the autoloader') )) ->setHelp(<<update command reads the composer.json file from the @@ -107,6 +108,7 @@ EOT ->setOptimizeAutoloader($input->getOption('optimize-autoloader')) ->setUpdate(true) ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $input->getArgument('packages')) + ->setPrepend(!$input->getOption('no-prepend')) ; if ($input->getOption('no-plugins')) { From cc37e4b0b826bf5dbcbb7b43c69d00ed21ac3e69 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 9 Oct 2013 19:44:33 -0300 Subject: [PATCH 118/238] Show defaulted version if phpversion() returns nothing, fixes #2313 --- src/Composer/DependencyResolver/Problem.php | 2 +- src/Composer/DependencyResolver/Rule.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Composer/DependencyResolver/Problem.php b/src/Composer/DependencyResolver/Problem.php index ac4541eb6..56ac867c4 100644 --- a/src/Composer/DependencyResolver/Problem.php +++ b/src/Composer/DependencyResolver/Problem.php @@ -84,7 +84,7 @@ class Problem // handle php extensions if (0 === stripos($job['packageName'], 'ext-')) { $ext = substr($job['packageName'], 4); - $error = extension_loaded($ext) ? 'has the wrong version ('.phpversion($ext).') installed' : 'is missing from your system'; + $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system'; return "\n - The requested PHP extension ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error.'.'; } diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index 672fe2f4a..a47038431 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -215,7 +215,7 @@ class Rule // handle php extensions if (0 === strpos($targetName, 'ext-')) { $ext = substr($targetName, 4); - $error = extension_loaded($ext) ? 'has the wrong version ('.phpversion($ext).') installed' : 'is missing from your system'; + $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system'; $text .= ' -> the requested PHP extension '.$ext.' '.$error.'.'; } elseif (0 === strpos($targetName, 'lib-')) { From f51aa4fad6a8c254b9d4e2acecc882e9b226925f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Wed, 9 Oct 2013 14:21:51 +0200 Subject: [PATCH 119/238] Add local cache for Git repositories --- src/Composer/Repository/Vcs/GitDriver.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index b220ea573..e2a3a9eb0 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -17,12 +17,14 @@ use Composer\Util\ProcessExecutor; use Composer\Util\Filesystem; use Composer\Util\Git as GitUtil; use Composer\IO\IOInterface; +use Composer\Cache; /** * @author Jordi Boggiano */ class GitDriver extends VcsDriver { + protected $cache; protected $tags; protected $branches; protected $rootIdentifier; @@ -77,6 +79,8 @@ class GitDriver extends VcsDriver $this->getTags(); $this->getBranches(); + + $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url)); } /** @@ -132,6 +136,10 @@ class GitDriver extends VcsDriver */ public function getComposerInformation($identifier) { + if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier)) { + $this->infoCache[$identifier] = JsonFile::parseJson($res); + } + if (!isset($this->infoCache[$identifier])) { $resource = sprintf('%s:composer.json', escapeshellarg($identifier)); $this->process->execute(sprintf('git show %s', $resource), $composer, $this->repoDir); @@ -147,6 +155,11 @@ class GitDriver extends VcsDriver $date = new \DateTime('@'.trim($output), new \DateTimeZone('UTC')); $composer['time'] = $date->format('Y-m-d H:i:s'); } + + if (preg_match('{[a-f0-9]{40}}i', $identifier)) { + $this->cache->write($identifier, json_encode($composer)); + } + $this->infoCache[$identifier] = $composer; } From 836986faf3bfefeada469303aa5fca25bd670a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Thu, 10 Oct 2013 22:57:03 +0200 Subject: [PATCH 120/238] Add temp composer home for GitDriver test using cache --- tests/Composer/Test/Repository/VcsRepositoryTest.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/Composer/Test/Repository/VcsRepositoryTest.php b/tests/Composer/Test/Repository/VcsRepositoryTest.php index b98be6fc2..eaedc82a9 100644 --- a/tests/Composer/Test/Repository/VcsRepositoryTest.php +++ b/tests/Composer/Test/Repository/VcsRepositoryTest.php @@ -25,12 +25,14 @@ use Composer\Config; */ class VcsRepositoryTest extends \PHPUnit_Framework_TestCase { + private static $composerHome; private static $gitRepo; private $skipped; protected function initialize() { $oldCwd = getcwd(); + self::$composerHome = sys_get_temp_dir() . '/composer-home-'.mt_rand().'/'; self::$gitRepo = sys_get_temp_dir() . '/composer-git-'.mt_rand().'/'; $locator = new ExecutableFinder(); @@ -125,6 +127,7 @@ class VcsRepositoryTest extends \PHPUnit_Framework_TestCase public static function tearDownAfterClass() { $fs = new Filesystem; + $fs->removeDirectory(self::$composerHome); $fs->removeDirectory(self::$gitRepo); } @@ -140,7 +143,13 @@ class VcsRepositoryTest extends \PHPUnit_Framework_TestCase 'dev-master' => true, ); - $repo = new VcsRepository(array('url' => self::$gitRepo, 'type' => 'vcs'), new NullIO, new Config()); + $config = new Config(); + $config->merge(array( + 'config' => array( + 'home' => self::$composerHome, + ), + )); + $repo = new VcsRepository(array('url' => self::$gitRepo, 'type' => 'vcs'), new NullIO, $config); $packages = $repo->getPackages(); $dumper = new ArrayDumper(); From f0842213e07dfc51b2a3795112fd566fd44ca9a3 Mon Sep 17 00:00:00 2001 From: Christoph Date: Fri, 11 Oct 2013 14:34:52 +0200 Subject: [PATCH 121/238] make sure relative paths from custom installers to not break the installation of binaries --- src/Composer/Installer/LibraryInstaller.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index c883120f4..f409b4095 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -198,6 +198,12 @@ class LibraryInstaller implements InstallerInterface continue; } + // in case a custom installer returned a relative path for the + // $package, we can now safely turn it into a absolute path (as we + // already checked the binary's existence). The following helpers + // will require absolute paths to work properly. + $binPath = realpath($binPath); + $this->initializeBinDir(); $link = $this->binDir.'/'.basename($bin); if (file_exists($link)) { From 57146c12b42e5140e4c9ae0c909902fdac0a3733 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 11 Oct 2013 19:59:30 -0300 Subject: [PATCH 122/238] Warn user that commands are being run in another directory --- src/Composer/Command/GlobalCommand.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Composer/Command/GlobalCommand.php b/src/Composer/Command/GlobalCommand.php index 0ddfc4ede..5fe7e4f47 100644 --- a/src/Composer/Command/GlobalCommand.php +++ b/src/Composer/Command/GlobalCommand.php @@ -72,6 +72,7 @@ EOT // change to global dir $config = Factory::createConfig(); chdir($config->get('home')); + $output->writeln('Changed current directory to '.$config->get('home').''); // create new input without "global" command prefix $input = new StringInput(preg_replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', $input->__toString(), 1)); From 11a0d16ccc13af9ca9d0ba85aa33f336fbfc7368 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 11 Oct 2013 20:12:02 -0300 Subject: [PATCH 123/238] CS fixes --- src/Composer/Autoload/AutoloadGenerator.php | 1 + src/Composer/Command/GlobalCommand.php | 2 +- src/Composer/DependencyResolver/Pool.php | 1 + .../Downloader/ChangeReportInterface.php | 6 +++--- src/Composer/Downloader/FileDownloader.php | 10 +++++----- src/Composer/Downloader/PerforceDownloader.php | 4 ++-- src/Composer/Downloader/VcsDownloader.php | 4 ++-- src/Composer/EventDispatcher/Event.php | 2 +- .../EventDispatcher/EventDispatcher.php | 2 +- src/Composer/Factory.php | 4 ++-- src/Composer/Installer.php | 5 ++--- src/Composer/Installer/LibraryInstaller.php | 1 + src/Composer/Package/Version/VersionParser.php | 6 +++--- src/Composer/Plugin/PluginInterface.php | 2 +- src/Composer/Plugin/PreFileDownloadEvent.php | 2 +- src/Composer/Repository/PlatformRepository.php | 1 - src/Composer/Repository/Vcs/PerforceDriver.php | 3 +-- src/Composer/Repository/Vcs/VcsDriver.php | 2 +- src/Composer/Util/Filesystem.php | 2 +- src/Composer/Util/NoProxyPattern.php | 2 +- src/Composer/Util/Perforce.php | 14 +++++++++----- .../Test/Autoload/Fixtures/autoload_files.php | 2 +- .../autoload_files_files_by_dependency.php | 2 +- .../Fixtures/autoload_files_functions.php | 2 +- .../Fixtures/autoload_files_target_dir.php | 2 +- .../Test/Downloader/PerforceDownloaderTest.php | 3 +-- .../Package/Archiver/ArchiveManagerTest.php | 2 +- .../Test/Plugin/PluginInstallerTest.php | 2 -- .../Test/Repository/Vcs/PerforceDriverTest.php | 2 +- tests/Composer/Test/Util/PerforceTest.php | 17 +++++++++++++++-- .../Composer/Test/Util/RemoteFilesystemTest.php | 1 - 31 files changed, 62 insertions(+), 49 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index e5cceb43a..cb70700dd 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -317,6 +317,7 @@ EOF; return array( $filesCode); + EOF; } diff --git a/src/Composer/Command/GlobalCommand.php b/src/Composer/Command/GlobalCommand.php index 5fe7e4f47..15f1fff08 100644 --- a/src/Composer/Command/GlobalCommand.php +++ b/src/Composer/Command/GlobalCommand.php @@ -42,7 +42,7 @@ is to add the COMPOSER_HOME/vendor/bin dir to your PATH env var. COMPOSER_HOME is c:\Users\\AppData\Roaming\Composer on Windows and /home//.composer on unix systems. -Note: This path may vary depending on customizations to bin-dir in +Note: This path may vary depending on customizations to bin-dir in composer.json or the environmental variable COMPOSER_BIN_DIR. EOT diff --git a/src/Composer/DependencyResolver/Pool.php b/src/Composer/DependencyResolver/Pool.php index 309c6e471..96198f4d6 100644 --- a/src/Composer/DependencyResolver/Pool.php +++ b/src/Composer/DependencyResolver/Pool.php @@ -377,6 +377,7 @@ class Pool if ($constraint === null) { return self::MATCH; } + return $constraint->matches(new VersionConstraint('==', $candidateVersion)) ? self::MATCH : self::MATCH_NAME; } diff --git a/src/Composer/Downloader/ChangeReportInterface.php b/src/Composer/Downloader/ChangeReportInterface.php index e60615431..3fb1dc5d0 100644 --- a/src/Composer/Downloader/ChangeReportInterface.php +++ b/src/Composer/Downloader/ChangeReportInterface.php @@ -24,9 +24,9 @@ interface ChangeReportInterface /** * Checks for changes to the local copy * - * @param PackageInterface $package package instance - * @param string $path package directory - * @return string|null changes or null + * @param PackageInterface $package package instance + * @param string $path package directory + * @return string|null changes or null */ public function getLocalChanges(PackageInterface $package, $path); } diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index e52fea0c1..6581b6ca7 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -45,12 +45,12 @@ class FileDownloader implements DownloaderInterface /** * Constructor. * - * @param IOInterface $io The IO instance - * @param Config $config The config + * @param IOInterface $io The IO instance + * @param Config $config The config * @param EventDispatcher $eventDispatcher The event dispatcher - * @param Cache $cache Optional cache instance - * @param RemoteFilesystem $rfs The remote filesystem - * @param Filesystem $filesystem The filesystem + * @param Cache $cache Optional cache instance + * @param RemoteFilesystem $rfs The remote filesystem + * @param Filesystem $filesystem The filesystem */ public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, RemoteFilesystem $rfs = null, Filesystem $filesystem = null) { diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index 6ddea153f..be6e2ddb1 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -10,7 +10,6 @@ * file that was distributed with this source code. */ - namespace Composer\Downloader; use Composer\Package\PackageInterface; @@ -75,16 +74,17 @@ class PerforceDownloader extends VcsDownloader public function getLocalChanges(PackageInterface $package, $path) { $this->io->write('Perforce driver does not check for local changes before overriding', true); + return; } - /** * {@inheritDoc} */ protected function getCommitLogs($fromReference, $toReference, $path) { $commitLogs = $this->perforce->getCommitLogs($fromReference, $toReference); + return $commitLogs; } diff --git a/src/Composer/Downloader/VcsDownloader.php b/src/Composer/Downloader/VcsDownloader.php index d3253d956..4e06d63f8 100644 --- a/src/Composer/Downloader/VcsDownloader.php +++ b/src/Composer/Downloader/VcsDownloader.php @@ -148,8 +148,8 @@ abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterfa * Prompt the user to check if changes should be stashed/removed or the operation aborted * * @param PackageInterface $package - * @param string $path - * @param bool $update if true (update) the changes can be stashed and reapplied after an update, + * @param string $path + * @param bool $update if true (update) the changes can be stashed and reapplied after an update, * if false (remove) the changes should be assumed to be lost if the operation is not aborted * @throws \RuntimeException in case the operation must be aborted */ diff --git a/src/Composer/EventDispatcher/Event.php b/src/Composer/EventDispatcher/Event.php index 8a9352653..0b3c9c951 100644 --- a/src/Composer/EventDispatcher/Event.php +++ b/src/Composer/EventDispatcher/Event.php @@ -32,7 +32,7 @@ class Event /** * Constructor. * - * @param string $name The event name + * @param string $name The event name */ public function __construct($name) { diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index 912d4eaea..9c2aee91f 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -202,7 +202,7 @@ class EventDispatcher /** * Retrieves all listeners for a given event * - * @param Event $event + * @param Event $event * @return array All listeners: callables and scripts */ protected function getListeners(Event $event) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 1f794786b..c3367ba4a 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -177,7 +177,7 @@ class Factory * @param IOInterface $io IO instance * @param array|string|null $localConfig either a configuration array or a filename to read from, if null it will * read from the default filename - * @param bool $disablePlugins Whether plugins should not be loaded + * @param bool $disablePlugins Whether plugins should not be loaded * @throws \InvalidArgumentException * @throws \UnexpectedValueException * @return Composer @@ -432,7 +432,7 @@ class Factory * @param IOInterface $io IO instance * @param mixed $config either a configuration array or a filename to read from, if null it will read from * the default filename - * @param bool $disablePlugins Whether plugins should not be loaded + * @param bool $disablePlugins Whether plugins should not be loaded * @return Composer */ public static function create(IOInterface $io, $config = null, $disablePlugins = false) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 3e9a9bf6b..3184cc509 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -539,7 +539,6 @@ class Installer return true; } - /** * Workaround: if your packages depend on plugins, we must be sure * that those are installed / updated first; else it would lead to packages @@ -550,7 +549,7 @@ class Installer * it at least fixes the symptoms and makes usage of composer possible (again) * in such scenarios. * - * @param OperationInterface[] $operations + * @param OperationInterface[] $operations * @return OperationInterface[] reordered operation list */ private function movePluginsToFront(array $operations) @@ -559,7 +558,7 @@ class Installer foreach ($operations as $idx => $op) { if ($op instanceof InstallOperation) { $package = $op->getPackage(); - } else if ($op instanceof UpdateOperation) { + } elseif ($op instanceof UpdateOperation) { $package = $op->getTargetPackage(); } else { continue; diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index d48eb509f..aab3f4737 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -165,6 +165,7 @@ class LibraryInstaller implements InstallerInterface if (strpos($initialDownloadPath, $targetDownloadPath) === 0) { $this->removeCode($initial); $this->installCode($target); + return; } diff --git a/src/Composer/Package/Version/VersionParser.php b/src/Composer/Package/Version/VersionParser.php index f39e21d0f..8b519f943 100644 --- a/src/Composer/Package/Version/VersionParser.php +++ b/src/Composer/Package/Version/VersionParser.php @@ -368,9 +368,9 @@ class VersionParser * * Support function for {@link parseConstraint()} * - * @param array $matches Array with version parts in array indexes 1,2,3,4 + * @param array $matches Array with version parts in array indexes 1,2,3,4 * @param int $position 1,2,3,4 - which segment of the version to decrement - * @param string $pad The string to pad version parts after $position + * @param string $pad The string to pad version parts after $position * @return string The new version */ private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0') @@ -378,7 +378,7 @@ class VersionParser for ($i = 4; $i > 0; $i--) { if ($i > $position) { $matches[$i] = $pad; - } else if ($i == $position && $increment) { + } elseif ($i == $position && $increment) { $matches[$i] += $increment; // If $matches[$i] was 0, carry the decrement if ($matches[$i] < 0) { diff --git a/src/Composer/Plugin/PluginInterface.php b/src/Composer/Plugin/PluginInterface.php index 3a33672a6..dea5828c1 100644 --- a/src/Composer/Plugin/PluginInterface.php +++ b/src/Composer/Plugin/PluginInterface.php @@ -32,7 +32,7 @@ interface PluginInterface /** * Apply plugin modifications to composer * - * @param Composer $composer + * @param Composer $composer * @param IOInterface $io */ public function activate(Composer $composer, IOInterface $io); diff --git a/src/Composer/Plugin/PreFileDownloadEvent.php b/src/Composer/Plugin/PreFileDownloadEvent.php index 38ea2620a..7ae6821ce 100644 --- a/src/Composer/Plugin/PreFileDownloadEvent.php +++ b/src/Composer/Plugin/PreFileDownloadEvent.php @@ -35,7 +35,7 @@ class PreFileDownloadEvent extends Event /** * Constructor. * - * @param string $name The event name + * @param string $name The event name * @param RemoteFilesystem $rfs * @param string $processedUrl */ diff --git a/src/Composer/Repository/PlatformRepository.php b/src/Composer/Repository/PlatformRepository.php index 7c4b72673..dcf791857 100644 --- a/src/Composer/Repository/PlatformRepository.php +++ b/src/Composer/Repository/PlatformRepository.php @@ -43,7 +43,6 @@ class PlatformRepository extends ArrayRepository $version = $versionParser->normalize($prettyVersion); } - $php = new CompletePackage('php', $version, $prettyVersion); $php->setDescription('The PHP interpreter'); parent::addPackage($php); diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 03acd0a21..3c953793c 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -10,12 +10,10 @@ * file that was distributed with this source code. */ - namespace Composer\Repository\Vcs; use Composer\IO\IOInterface; use Composer\Util\ProcessExecutor; -use Composer\Util\Filesystem; use Composer\Util\Perforce; /** @@ -145,6 +143,7 @@ class PerforceDriver extends VcsDriver if (isset($this->composerInfo)) { $result = count($this->composerInfo) > 0; } + return $result; } diff --git a/src/Composer/Repository/Vcs/VcsDriver.php b/src/Composer/Repository/Vcs/VcsDriver.php index 6f49d5b82..6effb2235 100644 --- a/src/Composer/Repository/Vcs/VcsDriver.php +++ b/src/Composer/Repository/Vcs/VcsDriver.php @@ -103,7 +103,7 @@ abstract class VcsDriver implements VcsDriverInterface /** * Return if current repository url is local - * + * * @return boolean Repository url is local */ protected static function isLocalUrl($url) diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index 7ed74dfaf..58d807f40 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -44,7 +44,7 @@ class Filesystem /** * Checks if a directory is empty * - * @param string $dir + * @param string $dir * @return bool */ public function isDirEmpty($dir) diff --git a/src/Composer/Util/NoProxyPattern.php b/src/Composer/Util/NoProxyPattern.php index 930d12e22..b41c8ff52 100644 --- a/src/Composer/Util/NoProxyPattern.php +++ b/src/Composer/Util/NoProxyPattern.php @@ -105,7 +105,7 @@ class NoProxyPattern * http://framework.zend.com/svn/framework/extras/incubator/library/ZendX/Whois/Adapter/Cidr.php * * @param string $cidr IPv4 block in CIDR notation - * @param string $ip IPv4 address + * @param string $ip IPv4 address * * @return boolean */ diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 2fb0e4bea..8a1ce4739 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -1,4 +1,5 @@ p4Stream = '//' . $this->p4Depot; } } + return $this->p4Stream; } @@ -268,6 +268,7 @@ class Perforce if ($index === false) { return false; } + return true; } @@ -329,7 +330,6 @@ class Perforce fclose($spec); } - protected function read($pipe, $name) { if (feof($pipe)) { @@ -347,10 +347,10 @@ class Perforce { $command = $this->generateP4Command(' login -a'); $process = new Process($command, null, null, $password); + return $process->run(); } - public function p4Login(IOInterface $io) { $this->queryP4User($io); @@ -369,6 +369,7 @@ class Perforce { $result = ''; $processExecutor->execute('p4 -p ' . $url . ' info -s', $result); + return false === strpos($result, 'error'); } @@ -380,6 +381,7 @@ class Perforce return $this->getComposerInformationFromPath($composerJson); } + return $this->getComposerInformationFromLabel($identifier, $index); } @@ -496,6 +498,7 @@ class Perforce } $fields = explode(' ', $changes); $changeList = $fields[1]; + return $changeList; } @@ -513,6 +516,7 @@ class Perforce $main = substr($fromReference, 0, $index) . '/...'; $command = $this->generateP4Command('filelog ' . $main . '@' . $fromChangeList. ',' . $toChangeList); $result = $this->executeCommand($command); + return $result; } } diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_files.php b/tests/Composer/Test/Autoload/Fixtures/autoload_files.php index 8ca59a91e..17225d047 100644 --- a/tests/Composer/Test/Autoload/Fixtures/autoload_files.php +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_files.php @@ -8,4 +8,4 @@ $baseDir = dirname($vendorDir); return array( $baseDir . '/foo.php', $baseDir . '/bar.php', -); \ No newline at end of file +); diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_files_files_by_dependency.php b/tests/Composer/Test/Autoload/Fixtures/autoload_files_files_by_dependency.php index d1fde3835..6c8ce0466 100644 --- a/tests/Composer/Test/Autoload/Fixtures/autoload_files_files_by_dependency.php +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_files_files_by_dependency.php @@ -12,4 +12,4 @@ return array( $vendorDir . '/b/bar/testB.php', $vendorDir . '/e/e/testE.php', $baseDir . '/root.php', -); \ No newline at end of file +); diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_files_functions.php b/tests/Composer/Test/Autoload/Fixtures/autoload_files_functions.php index 5eb29028d..0af7f8686 100644 --- a/tests/Composer/Test/Autoload/Fixtures/autoload_files_functions.php +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_files_functions.php @@ -11,4 +11,4 @@ return array( $vendorDir . '/c/c/foo/bar/test3.php', $baseDir . '/root.php', $vendorDir . '/c/c/foo/bar/test4.php', -); \ No newline at end of file +); diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_files_target_dir.php b/tests/Composer/Test/Autoload/Fixtures/autoload_files_target_dir.php index 8ca59a91e..17225d047 100644 --- a/tests/Composer/Test/Autoload/Fixtures/autoload_files_target_dir.php +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_files_target_dir.php @@ -8,4 +8,4 @@ $baseDir = dirname($vendorDir); return array( $baseDir . '/foo.php', $baseDir . '/bar.php', -); \ No newline at end of file +); diff --git a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php index b247cfbf3..85093bf59 100644 --- a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php +++ b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php @@ -1,4 +1,5 @@ io = $this->getMock('Composer\IO\IOInterface'); } - public function testDoDownloadGetRepoConfig() { $downloader = new PerforceDownloader($this->io, $this->config); diff --git a/tests/Composer/Test/Package/Archiver/ArchiveManagerTest.php b/tests/Composer/Test/Package/Archiver/ArchiveManagerTest.php index 427b0d70c..a85555fc8 100644 --- a/tests/Composer/Test/Package/Archiver/ArchiveManagerTest.php +++ b/tests/Composer/Test/Package/Archiver/ArchiveManagerTest.php @@ -49,7 +49,7 @@ class ArchiveManagerTest extends ArchiverTest $target = $this->getTargetName($package, 'tar'); $this->assertFileExists($target); - + $tmppath = sys_get_temp_dir().'/composer_archiver/'.$this->manager->getPackageFilename($package); $this->assertFileNotExists($tmppath); diff --git a/tests/Composer/Test/Plugin/PluginInstallerTest.php b/tests/Composer/Test/Plugin/PluginInstallerTest.php index 2502dded9..08d0d1aab 100644 --- a/tests/Composer/Test/Plugin/PluginInstallerTest.php +++ b/tests/Composer/Test/Plugin/PluginInstallerTest.php @@ -17,7 +17,6 @@ use Composer\Config; use Composer\Installer\PluginInstaller; use Composer\Package\Loader\JsonLoader; use Composer\Package\Loader\ArrayLoader; -use Composer\Package\PackageInterface; use Composer\Plugin\PluginManager; use Composer\Autoload\AutoloadGenerator; use Composer\Util\Filesystem; @@ -166,4 +165,3 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase $this->assertEquals('installer-v3', $plugins[1]->version); } } - diff --git a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php index 5b0bc43f9..0c2ba757e 100644 --- a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php @@ -1,4 +1,5 @@ assertEquals('//depot/branch', $stream); } - public function testGetStreamWithoutLabelWithStreamWithoutLabel() { $stream = $this->perforce->getStreamWithoutLabel('//depot/branch'); @@ -123,6 +122,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->returnCallback( function ($command, &$output) { $output = 'P4USER=TEST_P4VARIABLE_USER' . PHP_EOL ; + return true; } ) @@ -146,6 +146,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->returnCallback( function ($command, &$output) { $output = 'TEST_P4VARIABLE_USER' . PHP_EOL; + return true; } ) @@ -237,6 +238,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->returnCallback( function ($command, &$output) { $output = 'P4PASSWD=TEST_P4VARIABLE_PASSWORD' . PHP_EOL; + return true; } ) @@ -260,6 +262,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->returnCallback( function ($command, &$output) { $output = 'TEST_P4VARIABLE_PASSWORD' . PHP_EOL; + return true; } ) @@ -357,6 +360,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->returnCallback( function ($command, &$output) { $output = 'Stream //depot/branch mainline none \'branch\'' . PHP_EOL; + return true; } ) @@ -382,6 +386,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->returnCallback( function ($command, &$output) { $output = 'Label 0.0.1 2013/07/31 \'First Label!\'' . PHP_EOL . 'Label 0.0.2 2013/08/01 \'Second Label!\'' . PHP_EOL; + return true; } ) @@ -404,6 +409,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->returnCallback( function ($command, &$output) { $output = 'Label 0.0.1 2013/07/31 \'First Label!\'' . PHP_EOL . 'Label 0.0.2 2013/08/01 \'Second Label!\'' . PHP_EOL; + return true; } ) @@ -428,6 +434,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->returnCallback( function ($command, &$output) { $output = 'Depot depot 2013/06/25 stream /p4/1/depots/depot/... \'Created by Me\''; + return true; } ) @@ -447,6 +454,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->returnCallback( function ($command, &$output) { $output = PerforceTest::getComposerJson(); + return true; } ) @@ -472,6 +480,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->returnCallback( function ($command, &$output) { $output = '//depot/composer.json#1 - branch change 10001 (text)'; + return true; } ) @@ -485,6 +494,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->returnCallback( function ($command, &$output) { $output = PerforceTest::getComposerJson(); + return true; } ) @@ -513,6 +523,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->returnCallback( function ($command, &$output) { $output = PerforceTest::getComposerJson(); + return true; } ) @@ -540,6 +551,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->returnCallback( function ($command, &$output) { $output = '//depot/composer.json#1 - branch change 10001 (text)'; + return true; } ) @@ -553,6 +565,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->returnCallback( function ($command, &$output) { $output = PerforceTest::getComposerJson(); + return true; } ) diff --git a/tests/Composer/Test/Util/RemoteFilesystemTest.php b/tests/Composer/Test/Util/RemoteFilesystemTest.php index eb8ebc07e..67696b40f 100644 --- a/tests/Composer/Test/Util/RemoteFilesystemTest.php +++ b/tests/Composer/Test/Util/RemoteFilesystemTest.php @@ -144,7 +144,6 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase } } - public function testCaptureAuthenticationParamsFromUrl() { $io = $this->getMock('Composer\IO\IOInterface'); From 0fbb4cbd16bf1856b0d7f4a7ee81c6736b8aa97e Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 11 Oct 2013 20:21:34 -0300 Subject: [PATCH 124/238] CS fixes and renaming a few methods, refs #2184 --- .../Downloader/PerforceDownloader.php | 8 +- .../Repository/Vcs/PerforceDriver.php | 4 +- src/Composer/Util/Perforce.php | 24 +- .../Downloader/PerforceDownloaderTest.php | 3 +- .../Repository/Vcs/PerforceDriverTest.php | 24 +- tests/Composer/Test/Util/PerforceTest.php | 349 +++++++++--------- 6 files changed, 205 insertions(+), 207 deletions(-) diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index be6e2ddb1..3aa8d0a43 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -44,15 +44,16 @@ class PerforceDownloader extends VcsDownloader private function initPerforce($package, $path, $ref) { - if ($this->perforceInjected) { + if ($this->perforce) { return; } + $repository = $package->getRepository(); $repoConfig = null; if ($repository instanceof VcsRepository) { $repoConfig = $this->getRepoConfig($repository); } - $this->perforce = Perforce::createPerforce($repoConfig, $package->getSourceUrl(), $path); + $this->perforce = Perforce::create($repoConfig, $package->getSourceUrl(), $path); } private function getRepoConfig(VcsRepository $repository) @@ -88,9 +89,8 @@ class PerforceDownloader extends VcsDownloader return $commitLogs; } - public function injectPerforce($perforce) + public function setPerforce($perforce) { $this->perforce = $perforce; - $this->perforceInjected = true; } } diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 3c953793c..a6d52bfb6 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -55,7 +55,7 @@ class PerforceDriver extends VcsDriver } $repoDir = $this->config->get('cache-vcs-dir') . '/' . $this->depot; - $this->perforce = Perforce::createPerforce($repoConfig, $this->getUrl(), $repoDir, $this->process); + $this->perforce = Perforce::create($repoConfig, $this->getUrl(), $repoDir, $this->process); } /** @@ -182,7 +182,7 @@ class PerforceDriver extends VcsDriver return $this->branch; } - public function injectPerforce(Perforce $perforce) + public function setPerforce(Perforce $perforce) { $this->perforce = $perforce; } diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 8a1ce4739..5237e3420 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -34,18 +34,6 @@ class Perforce protected $uniquePerforceClientName; protected $windowsFlag; - public static function createPerforce($repoConfig, $port, $path, ProcessExecutor $process = null) - { - if (!isset($process)) { - $process = new ProcessExecutor; - } - $isWindows = defined('PHP_WINDOWS_VERSION_BUILD'); - - $perforce = new Perforce($repoConfig, $port, $path, $process, $isWindows); - - return $perforce; - } - public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows) { $this->windowsFlag = $isWindows; @@ -57,6 +45,18 @@ class Perforce $this->initialize($repoConfig); } + public static function create($repoConfig, $port, $path, ProcessExecutor $process = null) + { + if (!isset($process)) { + $process = new ProcessExecutor; + } + $isWindows = defined('PHP_WINDOWS_VERSION_BUILD'); + + $perforce = new Perforce($repoConfig, $port, $path, $process, $isWindows); + + return $perforce; + } + public function initialize($repoConfig) { $this->uniquePerforceClientName = $this->generateUniquePerforceClientName(); diff --git a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php index 85093bf59..b632d55d7 100644 --- a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php +++ b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php @@ -21,7 +21,6 @@ use Composer\Repository\VcsRepository; */ class PerforceDownloaderTest extends \PHPUnit_Framework_TestCase { - private $io; private $config; private $testPath; @@ -93,7 +92,7 @@ class PerforceDownloaderTest extends \PHPUnit_Framework_TestCase $perforce->expects($this->at(4)) ->method('syncCodeBase') ->with($this->equalTo($label)); - $downloader->injectPerforce($perforce); + $downloader->setPerforce($perforce); $package = $this->getMock('Composer\Package\PackageInterface'); $package->expects($this->at(0)) ->method('getSourceReference') diff --git a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php index 0c2ba757e..277550e64 100644 --- a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php @@ -70,7 +70,7 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase 'TEST' ); $perforce = $this->getMock('Composer\Util\Perforce', null, $arguments); - $driver->injectPerforce($perforce); + $driver->setPerforce($perforce); $driver->initialize(); $this->assertEquals('TEST_PERFORCE_URL', $driver->getUrl()); $this->assertEquals('TEST_DEPOT_CONFIG', $driver->getDepot()); @@ -88,17 +88,17 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase $driver = new PerforceDriver($repoConfig, $this->io, $this->config, $this->process, $this->remoteFileSystem); $perforce = $this->getMockBuilder('Composer\Util\Perforce')->disableOriginalConstructor()->getMock(); $perforce->expects($this->at(0)) - ->method('p4Login') - ->with($this->io); + ->method('p4Login') + ->with($this->io); $perforce->expects($this->at(1)) - ->method('checkStream') - ->with($this->equalTo('TEST_DEPOT_CONFIG')); + ->method('checkStream') + ->with($this->equalTo('TEST_DEPOT_CONFIG')); $perforce->expects($this->at(2)) - ->method('writeP4ClientSpec'); + ->method('writeP4ClientSpec'); $perforce->expects($this->at(3)) - ->method('connectClient'); + ->method('connectClient'); - $driver->injectPerforce($perforce); + $driver->setPerforce($perforce); $driver->initialize(); } @@ -122,10 +122,10 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase ); $perforce = $this->getMock('Composer\Util\Perforce', array('getComposerInformation'), $arguments); $perforce->expects($this->at(0)) - ->method('getComposerInformation') - ->with($this->equalTo('//TEST_DEPOT_CONFIG/TEST_IDENTIFIER')) - ->will($this->returnValue('Some json stuff')); - $driver->injectPerforce($perforce); + ->method('getComposerInformation') + ->with($this->equalTo('//TEST_DEPOT_CONFIG/TEST_IDENTIFIER')) + ->will($this->returnValue('Some json stuff')); + $driver->setPerforce($perforce); $driver->initialize(); $identifier = 'TEST_IDENTIFIER'; $result = $driver->hasComposerFile($identifier); diff --git a/tests/Composer/Test/Util/PerforceTest.php b/tests/Composer/Test/Util/PerforceTest.php index 2f17be07d..5c76df98e 100644 --- a/tests/Composer/Test/Util/PerforceTest.php +++ b/tests/Composer/Test/Util/PerforceTest.php @@ -20,7 +20,6 @@ use Composer\Util\ProcessExecutor; */ class PerforceTest extends \PHPUnit_Framework_TestCase { - protected $perforce; protected $processExecutor; @@ -116,17 +115,17 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $io = $this->getMock('Composer\IO\IOInterface'); $expectedCommand = 'p4 set'; $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will( - $this->returnCallback( - function ($command, &$output) { - $output = 'P4USER=TEST_P4VARIABLE_USER' . PHP_EOL ; + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = 'P4USER=TEST_P4VARIABLE_USER' . PHP_EOL ; - return true; - } - ) - ); + return true; + } + ) + ); $this->perforce->queryP4user($io); $this->assertEquals('TEST_P4VARIABLE_USER', $this->perforce->getUser()); @@ -140,17 +139,17 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $io = $this->getMock('Composer\IO\IOInterface'); $expectedCommand = 'echo $P4USER'; $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will( - $this->returnCallback( - function ($command, &$output) { - $output = 'TEST_P4VARIABLE_USER' . PHP_EOL; + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = 'TEST_P4VARIABLE_USER' . PHP_EOL; - return true; - } - ) - ); + return true; + } + ) + ); $this->perforce->queryP4user($io); $this->assertEquals('TEST_P4VARIABLE_USER', $this->perforce->getUser()); @@ -163,9 +162,9 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $io = $this->getMock('Composer\IO\IOInterface'); $expectedQuestion = 'Enter P4 User:'; $io->expects($this->at(0)) - ->method('ask') - ->with($this->equalTo($expectedQuestion)) - ->will($this->returnValue('TEST_QUERY_USER')); + ->method('ask') + ->with($this->equalTo($expectedQuestion)) + ->will($this->returnValue('TEST_QUERY_USER')); $this->perforce->queryP4user($io); $this->assertEquals('TEST_QUERY_USER', $this->perforce->getUser()); @@ -179,14 +178,14 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $io = $this->getMock('Composer\IO\IOInterface'); $expectedQuestion = 'Enter P4 User:'; $io->expects($this->at(0)) - ->method('ask') - ->with($this->equalTo($expectedQuestion)) - ->will($this->returnValue('TEST_QUERY_USER')); + ->method('ask') + ->with($this->equalTo($expectedQuestion)) + ->will($this->returnValue('TEST_QUERY_USER')); $expectedCommand = 'p4 set P4USER=TEST_QUERY_USER'; $this->processExecutor->expects($this->at(1)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will($this->returnValue(0)); + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnValue(0)); $this->perforce->queryP4user($io); } @@ -199,14 +198,14 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $io = $this->getMock('Composer\IO\IOInterface'); $expectedQuestion = 'Enter P4 User:'; $io->expects($this->at(0)) - ->method('ask') - ->with($this->equalTo($expectedQuestion)) - ->will($this->returnValue('TEST_QUERY_USER')); + ->method('ask') + ->with($this->equalTo($expectedQuestion)) + ->will($this->returnValue('TEST_QUERY_USER')); $expectedCommand = 'export P4USER=TEST_QUERY_USER'; $this->processExecutor->expects($this->at(1)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will($this->returnValue(0)); + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnValue(0)); $this->perforce->queryP4user($io); } @@ -232,17 +231,17 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $expectedCommand = 'p4 set'; $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will( - $this->returnCallback( - function ($command, &$output) { - $output = 'P4PASSWD=TEST_P4VARIABLE_PASSWORD' . PHP_EOL; + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = 'P4PASSWD=TEST_P4VARIABLE_PASSWORD' . PHP_EOL; - return true; - } - ) - ); + return true; + } + ) + ); $password = $this->perforce->queryP4Password($io); $this->assertEquals('TEST_P4VARIABLE_PASSWORD', $password); @@ -256,17 +255,17 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $io = $this->getMock('Composer\IO\IOInterface'); $expectedCommand = 'echo $P4PASSWD'; $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will( - $this->returnCallback( - function ($command, &$output) { - $output = 'TEST_P4VARIABLE_PASSWORD' . PHP_EOL; + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = 'TEST_P4VARIABLE_PASSWORD' . PHP_EOL; - return true; - } - ) - ); + return true; + } + ) + ); $password = $this->perforce->queryP4Password($io); $this->assertEquals('TEST_P4VARIABLE_PASSWORD', $password); @@ -277,9 +276,9 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $io = $this->getMock('Composer\IO\IOInterface'); $expectedQuestion = 'Enter password for Perforce user user: '; $io->expects($this->at(0)) - ->method('askAndHideAnswer') - ->with($this->equalTo($expectedQuestion)) - ->will($this->returnValue('TEST_QUERY_PASSWORD')); + ->method('askAndHideAnswer') + ->with($this->equalTo($expectedQuestion)) + ->will($this->returnValue('TEST_QUERY_PASSWORD')); $password = $this->perforce->queryP4Password($io); $this->assertEquals('TEST_QUERY_PASSWORD', $password); @@ -330,9 +329,9 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $expectedCommand = 'p4 -u user -p port login -s'; $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand), $this->equalTo(null)) - ->will($this->returnValue(0)); + ->method('execute') + ->with($this->equalTo($expectedCommand), $this->equalTo(null)) + ->will($this->returnValue(0)); $this->perforce->isLoggedIn(); } @@ -341,9 +340,9 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot -p port client -i < path/composer_perforce_TEST_depot.p4.spec'; $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand), $this->equalTo(null)) - ->will($this->returnValue(0)); + ->method('execute') + ->with($this->equalTo($expectedCommand), $this->equalTo(null)) + ->will($this->returnValue(0)); $this->perforce->connectClient(); } @@ -354,17 +353,17 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot_branch -p port streams //depot/...'; $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will( - $this->returnCallback( - function ($command, &$output) { - $output = 'Stream //depot/branch mainline none \'branch\'' . PHP_EOL; + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = 'Stream //depot/branch mainline none \'branch\'' . PHP_EOL; - return true; - } - ) - ); + return true; + } + ) + ); $branches = $this->perforce->getBranches(); $this->assertEquals('//depot/branch', $branches['master']); @@ -380,17 +379,17 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot -p port labels'; $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will( - $this->returnCallback( - function ($command, &$output) { - $output = 'Label 0.0.1 2013/07/31 \'First Label!\'' . PHP_EOL . 'Label 0.0.2 2013/08/01 \'Second Label!\'' . PHP_EOL; + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = 'Label 0.0.1 2013/07/31 \'First Label!\'' . PHP_EOL . 'Label 0.0.2 2013/08/01 \'Second Label!\'' . PHP_EOL; - return true; - } - ) - ); + return true; + } + ) + ); $tags = $this->perforce->getTags(); $this->assertEquals('//depot@0.0.1', $tags['0.0.1']); @@ -403,17 +402,17 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot_branch -p port labels'; $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will( - $this->returnCallback( - function ($command, &$output) { - $output = 'Label 0.0.1 2013/07/31 \'First Label!\'' . PHP_EOL . 'Label 0.0.2 2013/08/01 \'Second Label!\'' . PHP_EOL; + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = 'Label 0.0.1 2013/07/31 \'First Label!\'' . PHP_EOL . 'Label 0.0.2 2013/08/01 \'Second Label!\'' . PHP_EOL; - return true; - } - ) - ); + return true; + } + ) + ); $tags = $this->perforce->getTags(); $this->assertEquals('//depot/branch@0.0.1', $tags['0.0.1']); @@ -430,15 +429,15 @@ class PerforceTest extends \PHPUnit_Framework_TestCase public function testCheckStreamWithStream() { $this->processExecutor->expects($this->any())->method('execute') - ->will( - $this->returnCallback( - function ($command, &$output) { - $output = 'Depot depot 2013/06/25 stream /p4/1/depots/depot/... \'Created by Me\''; + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = 'Depot depot 2013/06/25 stream /p4/1/depots/depot/... \'Created by Me\''; - return true; - } - ) - ); + return true; + } + ) + ); $result = $this->perforce->checkStream('depot'); $this->assertTrue($result); $this->assertTrue($this->perforce->isStream()); @@ -448,17 +447,17 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot -p port print //depot/composer.json'; $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will( - $this->returnCallback( - function ($command, &$output) { - $output = PerforceTest::getComposerJson(); + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = PerforceTest::getComposerJson(); - return true; - } - ) - ); + return true; + } + ) + ); $result = $this->perforce->getComposerInformation('//depot'); $expected = array( @@ -474,31 +473,31 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $expectedCommand = 'p4 -u user -p port files //depot/composer.json@0.0.1'; $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will( - $this->returnCallback( - function ($command, &$output) { - $output = '//depot/composer.json#1 - branch change 10001 (text)'; + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = '//depot/composer.json#1 - branch change 10001 (text)'; - return true; - } - ) - ); + return true; + } + ) + ); $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot -p port print //depot/composer.json@10001'; $this->processExecutor->expects($this->at(1)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will( - $this->returnCallback( - function ($command, &$output) { - $output = PerforceTest::getComposerJson(); + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = PerforceTest::getComposerJson(); - return true; - } - ) - ); + return true; + } + ) + ); $result = $this->perforce->getComposerInformation('//depot@0.0.1'); @@ -517,17 +516,17 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot_branch -p port print //depot/branch/composer.json'; $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will( - $this->returnCallback( - function ($command, &$output) { - $output = PerforceTest::getComposerJson(); + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = PerforceTest::getComposerJson(); - return true; - } - ) - ); + return true; + } + ) + ); $result = $this->perforce->getComposerInformation('//depot/branch'); @@ -545,31 +544,31 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->setPerforceToStream(); $expectedCommand = 'p4 -u user -p port files //depot/branch/composer.json@0.0.1'; $this->processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will( - $this->returnCallback( - function ($command, &$output) { - $output = '//depot/composer.json#1 - branch change 10001 (text)'; + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = '//depot/composer.json#1 - branch change 10001 (text)'; - return true; - } - ) - ); + return true; + } + ) + ); $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot_branch -p port print //depot/branch/composer.json@10001'; $this->processExecutor->expects($this->at(1)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will( - $this->returnCallback( - function ($command, &$output) { - $output = PerforceTest::getComposerJson(); + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will( + $this->returnCallback( + function ($command, &$output) { + $output = PerforceTest::getComposerJson(); - return true; - } - ) - ); + return true; + } + ) + ); $result = $this->perforce->getComposerInformation('//depot/branch@0.0.1'); @@ -586,9 +585,9 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot -p port sync -f @label'; $this->processExecutor->expects($this->at(1)) - ->method('execute') - ->with($this->equalTo($expectedCommand), $this->equalTo(null)) - ->will($this->returnValue(0)); + ->method('execute') + ->with($this->equalTo($expectedCommand), $this->equalTo(null)) + ->will($this->returnValue(0)); $this->perforce->syncCodeBase('label'); } @@ -598,9 +597,9 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $this->setPerforceToStream(); $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot_branch -p port sync -f @label'; $this->processExecutor->expects($this->at(1)) - ->method('execute') - ->with($this->equalTo($expectedCommand)) - ->will($this->returnValue(0)); + ->method('execute') + ->with($this->equalTo($expectedCommand)) + ->will($this->returnValue(0)); $this->perforce->syncCodeBase('label'); } @@ -611,9 +610,9 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $expectedCommand = 'p4 -p perforce.does.exist:port info -s'; $processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand), $this->equalTo(null)) - ->will($this->returnValue(0)); + ->method('execute') + ->with($this->equalTo($expectedCommand), $this->equalTo(null)) + ->will($this->returnValue(0)); $result = $this->perforce->checkServerExists('perforce.does.exist:port', $processExecutor); $this->assertTrue($result); @@ -625,9 +624,9 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $expectedCommand = 'p4 -p perforce.does.not.exist:port info -s'; $processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand), $this->equalTo(null)) - ->will($this->returnValue('Perforce client error:')); + ->method('execute') + ->with($this->equalTo($expectedCommand), $this->equalTo(null)) + ->will($this->returnValue('Perforce client error:')); $result = $this->perforce->checkServerExists('perforce.does.not.exist:port', $processExecutor); $this->assertTrue($result); From 2b36106168e89fa185dfa604a1666fd1b188384e Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 11 Oct 2013 20:22:50 -0300 Subject: [PATCH 125/238] Fix tests, refs #2184 --- tests/Composer/Test/Util/PerforceTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Composer/Test/Util/PerforceTest.php b/tests/Composer/Test/Util/PerforceTest.php index 5c76df98e..6f72713bb 100644 --- a/tests/Composer/Test/Util/PerforceTest.php +++ b/tests/Composer/Test/Util/PerforceTest.php @@ -584,7 +584,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase public function testSyncCodeBaseWithoutStream() { $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot -p port sync -f @label'; - $this->processExecutor->expects($this->at(1)) + $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand), $this->equalTo(null)) ->will($this->returnValue(0)); @@ -596,7 +596,7 @@ class PerforceTest extends \PHPUnit_Framework_TestCase { $this->setPerforceToStream(); $expectedCommand = 'p4 -u user -c composer_perforce_TEST_depot_branch -p port sync -f @label'; - $this->processExecutor->expects($this->at(1)) + $this->processExecutor->expects($this->at(0)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnValue(0)); From 9dcada5e25acb1f67786789050ba3842b0c4a578 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 11 Oct 2013 20:41:32 -0300 Subject: [PATCH 126/238] Remove buggy chunk of code, refs #2312, refs #2305 --- src/Composer/Installer.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 3184cc509..f7169c271 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -852,9 +852,6 @@ class Installer $this->updateWhitelist[$package->getName()] = true; $requires = $package->getRequires(); - if ($devMode) { - $requires = array_merge($requires, $package->getDevRequires()); - } foreach ($requires as $require) { $requirePackages = $pool->whatProvides($require->getTarget()); From bd36f5ef1bdb2716777b33f44125a8eefb22c4a7 Mon Sep 17 00:00:00 2001 From: Sam Evaskitas Date: Sat, 12 Oct 2013 04:58:43 +0100 Subject: [PATCH 127/238] added warning about referencing dependencies in pre-install and pre-update --- doc/articles/scripts.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index be777aa08..fabbc0bc5 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -41,6 +41,8 @@ Composer fires the following named events during its execution process: - **post-create-project-cmd**: occurs after the `create-project` command is executed. +**NOTE: Composer makes no assumptions about the state of your dependencies prior to `install` or `update`. Therefore, you should not specify scripts that require Composer-managed dependencies in the `pre-update` or `pre-install` event hooks. If you need to execute scripts prior to `install` or `update` please make sure they are self-contained within your root package. + ## Defining scripts The root JSON object in `composer.json` should have a property called From ec3e5bf5abe20baee05b6417412acc0316c7fa43 Mon Sep 17 00:00:00 2001 From: Sam Evaskitas Date: Sat, 12 Oct 2013 05:03:08 +0100 Subject: [PATCH 128/238] fix up markdown --- doc/articles/scripts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index fabbc0bc5..ada9a69da 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -41,7 +41,7 @@ Composer fires the following named events during its execution process: - **post-create-project-cmd**: occurs after the `create-project` command is executed. -**NOTE: Composer makes no assumptions about the state of your dependencies prior to `install` or `update`. Therefore, you should not specify scripts that require Composer-managed dependencies in the `pre-update` or `pre-install` event hooks. If you need to execute scripts prior to `install` or `update` please make sure they are self-contained within your root package. +**NOTE: Composer makes no assumptions about the state of your dependencies prior to `install` or `update`. Therefore, you should not specify scripts that require Composer-managed dependencies in the `pre-update-cmd` or `pre-install-cmd` event hooks. If you need to execute scripts prior to `install` or `update` please make sure they are self-contained within your root package.** ## Defining scripts From 2f71d25f31917359f8aebf91b997e1e1f21adfa4 Mon Sep 17 00:00:00 2001 From: Sam Evaskitas Date: Sat, 12 Oct 2013 14:32:57 +0100 Subject: [PATCH 129/238] fix line lengths --- doc/articles/scripts.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index ada9a69da..4e8d3b7d1 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -41,7 +41,12 @@ Composer fires the following named events during its execution process: - **post-create-project-cmd**: occurs after the `create-project` command is executed. -**NOTE: Composer makes no assumptions about the state of your dependencies prior to `install` or `update`. Therefore, you should not specify scripts that require Composer-managed dependencies in the `pre-update-cmd` or `pre-install-cmd` event hooks. If you need to execute scripts prior to `install` or `update` please make sure they are self-contained within your root package.** +**NOTE: Composer makes no assumptions about the state of your dependencies +prior to `install` or `update`. Therefore, you should not specify scripts that +require Composer-managed dependencies in the `pre-update-cmd` or +`pre-install-cmd` event hooks. If you need to execute scripts prior to +`install` or `update` please make sure they are self-contained within your +root package.** ## Defining scripts From c88d461efdf8d17479cbf41517d9a63b2032db43 Mon Sep 17 00:00:00 2001 From: Yuya Takeyama Date: Sun, 13 Oct 2013 18:52:28 +0900 Subject: [PATCH 130/238] Fix link to COMPOSER_HOME --- doc/03-cli.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index 4202c75eb..267d19893 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -151,7 +151,7 @@ to the command. ## global The global command allows you to run other commands like `install`, `require` -or `update` as if you were running them from the [COMPOSER_HOME](#COMPOSER_HOME) +or `update` as if you were running them from the [COMPOSER_HOME](#composer-home) directory. This can be used to install CLI utilities globally and if you add From 5ae5963acd0dcb8dfe0c6d8611f33d6e90b04c84 Mon Sep 17 00:00:00 2001 From: Fabian Grutschus Date: Mon, 14 Oct 2013 14:53:57 +0200 Subject: [PATCH 131/238] Fix for Preforce utility does not check if p4 command exists --- src/Composer/Util/Perforce.php | 4 ++-- tests/Composer/Test/Util/PerforceTest.php | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 5237e3420..dc09a5066 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -368,9 +368,9 @@ class Perforce public static function checkServerExists($url, ProcessExecutor $processExecutor) { $result = ''; - $processExecutor->execute('p4 -p ' . $url . ' info -s', $result); + $exitCode = $processExecutor->execute('p4 -p ' . $url . ' info -s', $result); - return false === strpos($result, 'error'); + return false === strpos($result, 'error') && 127 != $exitCode; } public function getComposerInformation($identifier) diff --git a/tests/Composer/Test/Util/PerforceTest.php b/tests/Composer/Test/Util/PerforceTest.php index 6f72713bb..517c85a75 100644 --- a/tests/Composer/Test/Util/PerforceTest.php +++ b/tests/Composer/Test/Util/PerforceTest.php @@ -631,6 +631,27 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $result = $this->perforce->checkServerExists('perforce.does.not.exist:port', $processExecutor); $this->assertTrue($result); } + + /** + * Test if "p4" command is missing. + * + * @covers \Composer\Util\Perforce::checkServerExists + * + * @return void + */ + public function testCheckServerExistsWithMissingPerforceClient() + { + $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); + + $expectedCommand = 'p4 -p perforce.does.exist:port info -s'; + $processExecutor->expects($this->at(0)) + ->method('execute') + //->with($this->equalTo($expectedCommand), $this->equalTo(null)) + ->will($this->returnValue(127)); + + $result = $this->perforce->checkServerExists('perforce.does.exist:port', $processExecutor); + $this->assertFalse($result); + } public static function getComposerJson() { From 67083e436bb8924869039d7cbe2f5ba8a8ad5ebc Mon Sep 17 00:00:00 2001 From: Fabian Grutschus Date: Mon, 14 Oct 2013 15:07:35 +0200 Subject: [PATCH 132/238] Check for exit code is equal to 0 instead of 127 --- src/Composer/Util/Perforce.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index dc09a5066..663f58be3 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -370,7 +370,7 @@ class Perforce $result = ''; $exitCode = $processExecutor->execute('p4 -p ' . $url . ' info -s', $result); - return false === strpos($result, 'error') && 127 != $exitCode; + return false === strpos($result, 'error') && 0 == $exitCode; } public function getComposerInformation($identifier) From 0c5bd559f27a90facb077c849558a27f1f74d03f Mon Sep 17 00:00:00 2001 From: Fabian Grutschus Date: Mon, 14 Oct 2013 17:25:57 +0200 Subject: [PATCH 133/238] Changes comparsion to strict and removed a comment --- src/Composer/Util/Perforce.php | 2 +- tests/Composer/Test/Util/PerforceTest.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 663f58be3..2ae771345 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -370,7 +370,7 @@ class Perforce $result = ''; $exitCode = $processExecutor->execute('p4 -p ' . $url . ' info -s', $result); - return false === strpos($result, 'error') && 0 == $exitCode; + return false === strpos($result, 'error') && 0 === $exitCode; } public function getComposerInformation($identifier) diff --git a/tests/Composer/Test/Util/PerforceTest.php b/tests/Composer/Test/Util/PerforceTest.php index 517c85a75..ffd0ab321 100644 --- a/tests/Composer/Test/Util/PerforceTest.php +++ b/tests/Composer/Test/Util/PerforceTest.php @@ -646,7 +646,6 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $expectedCommand = 'p4 -p perforce.does.exist:port info -s'; $processExecutor->expects($this->at(0)) ->method('execute') - //->with($this->equalTo($expectedCommand), $this->equalTo(null)) ->will($this->returnValue(127)); $result = $this->perforce->checkServerExists('perforce.does.exist:port', $processExecutor); From 20854a50b4dd63191dc0d96a2ea84691b5507f1e Mon Sep 17 00:00:00 2001 From: Fabian Grutschus Date: Mon, 14 Oct 2013 18:04:09 +0200 Subject: [PATCH 134/238] Removed unnecessary test and just check for return code --- src/Composer/Util/Perforce.php | 5 +---- tests/Composer/Test/Util/PerforceTest.php | 17 ++--------------- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 2ae771345..5bb368575 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -367,10 +367,7 @@ class Perforce public static function checkServerExists($url, ProcessExecutor $processExecutor) { - $result = ''; - $exitCode = $processExecutor->execute('p4 -p ' . $url . ' info -s', $result); - - return false === strpos($result, 'error') && 0 === $exitCode; + return 0 === $processExecutor->execute('p4 -p ' . $url . ' info -s'); } public function getComposerInformation($identifier) diff --git a/tests/Composer/Test/Util/PerforceTest.php b/tests/Composer/Test/Util/PerforceTest.php index ffd0ab321..f2eeb1964 100644 --- a/tests/Composer/Test/Util/PerforceTest.php +++ b/tests/Composer/Test/Util/PerforceTest.php @@ -617,20 +617,6 @@ class PerforceTest extends \PHPUnit_Framework_TestCase $result = $this->perforce->checkServerExists('perforce.does.exist:port', $processExecutor); $this->assertTrue($result); } - - public function testCheckServerExistsWithFailure() - { - $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); - - $expectedCommand = 'p4 -p perforce.does.not.exist:port info -s'; - $processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedCommand), $this->equalTo(null)) - ->will($this->returnValue('Perforce client error:')); - - $result = $this->perforce->checkServerExists('perforce.does.not.exist:port', $processExecutor); - $this->assertTrue($result); - } /** * Test if "p4" command is missing. @@ -639,13 +625,14 @@ class PerforceTest extends \PHPUnit_Framework_TestCase * * @return void */ - public function testCheckServerExistsWithMissingPerforceClient() + public function testCheckServerClientError() { $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); $expectedCommand = 'p4 -p perforce.does.exist:port info -s'; $processExecutor->expects($this->at(0)) ->method('execute') + ->with($this->equalTo($expectedCommand), $this->equalTo(null)) ->will($this->returnValue(127)); $result = $this->perforce->checkServerExists('perforce.does.exist:port', $processExecutor); From c7bb3ad746a0182b501c29eb550e40209fbccf5c Mon Sep 17 00:00:00 2001 From: Ruud Denivel Date: Mon, 14 Oct 2013 18:38:30 +0200 Subject: [PATCH 135/238] refactor prepend autoloader from cli option to config var (prepend-autoloader) in composer.json --- src/Composer/Autoload/AutoloadGenerator.php | 11 ++++++----- src/Composer/Command/InstallCommand.php | 4 +--- src/Composer/Command/UpdateCommand.php | 4 +--- src/Composer/Config.php | 1 + src/Composer/Installer.php | 15 +-------------- 5 files changed, 10 insertions(+), 25 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 56dffdbc2..6322bdd61 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -37,7 +37,7 @@ class AutoloadGenerator $this->eventDispatcher = $eventDispatcher; } - public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '', $prepend = 'true') + public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '') { $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP); @@ -46,6 +46,7 @@ class AutoloadGenerator $basePath = $filesystem->normalizePath(getcwd()); $vendorPath = $filesystem->normalizePath(realpath($config->get('vendor-dir'))); $useGlobalIncludePath = (bool) $config->get('use-include-path'); + $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true'; $targetDir = $vendorPath.'/'.$targetDir; $filesystem->ensureDirectoryExists($targetDir); @@ -180,7 +181,7 @@ EOF; file_put_contents($targetDir.'/autoload_files.php', $includeFilesFile); } file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix)); - file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, true, (bool) $includePathFile, $targetDirLoader, (bool) $includeFilesFile, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prepend)); + file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, true, (bool) $includePathFile, $targetDirLoader, (bool) $includeFilesFile, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader)); // use stream_copy_to_stream instead of copy // to work around https://bugs.php.net/bug.php?id=64634 @@ -364,7 +365,7 @@ return ComposerAutoloaderInit$suffix::getLoader(); AUTOLOAD; } - protected function getAutoloadRealFile($usePSR0, $useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prepend) + protected function getAutoloadRealFile($usePSR0, $useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader) { // TODO the class ComposerAutoloaderInit should be revert to a closure // when APC has been fixed: @@ -395,7 +396,7 @@ class ComposerAutoloaderInit$suffix return self::\$loader; } - spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'), true, $prepend); + spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'), true, $prependAutoloader); self::\$loader = \$loader = new \\Composer\\Autoload\\ClassLoader(); spl_autoload_unregister(array('ComposerAutoloaderInit$suffix', 'loadClassLoader')); @@ -454,7 +455,7 @@ REGISTER_AUTOLOAD; } $file .= <<register($prepend); + \$loader->register($prependAutoloader); REGISTER_LOADER; diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index 18ed93192..6138009a3 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -43,8 +43,7 @@ class InstallCommand extends Command new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), - new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'), - new InputOption('no-prepend', null, InputOption::VALUE_NONE, 'Disables the prepending of the autoloader') + new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump') )) ->setHelp(<<install command reads the composer.lock file from @@ -102,7 +101,6 @@ EOT ->setDevMode(!$input->getOption('no-dev')) ->setRunScripts(!$input->getOption('no-scripts')) ->setOptimizeAutoloader($input->getOption('optimize-autoloader')) - ->setPrepend(!$input->getOption('no-prepend')) ; if ($input->getOption('no-plugins')) { diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index 357beda6d..ceabf7ff4 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -44,8 +44,7 @@ class UpdateCommand extends Command new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), - new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'), - new InputOption('no-prepend', null, InputOption::VALUE_NONE, 'Disables the prepending of the autoloader') + new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump') )) ->setHelp(<<update command reads the composer.json file from the @@ -108,7 +107,6 @@ EOT ->setOptimizeAutoloader($input->getOption('optimize-autoloader')) ->setUpdate(true) ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $input->getArgument('packages')) - ->setPrepend(!$input->getOption('no-prepend')) ; if ($input->getOption('no-plugins')) { diff --git a/src/Composer/Config.php b/src/Composer/Config.php index 601a21344..6151b4f81 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -35,6 +35,7 @@ class Config 'cache-files-ttl' => null, // fallback to cache-ttl 'cache-files-maxsize' => '300MiB', 'discard-changes' => false, + 'prepend-autoloader' => true, ); public static $defaultRepositories = array( diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index b205f65b4..3e9a9bf6b 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -106,7 +106,6 @@ class Installer protected $update = false; protected $runScripts = true; protected $updateWhitelist = null; - protected $prepend = 'true'; /** * @var array @@ -281,7 +280,7 @@ class Installer // write autoloader $this->io->write('Generating autoload files'); - $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader, '', $this->prepend); + $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader); if ($this->runScripts) { // dispatch post event @@ -1056,18 +1055,6 @@ class Installer return $this; } - /** - * Generate autoload_real with/without prepend - * - * @param boolean $prepend - * @return Installer - */ - public function setPrepend($prepend = true) - { - $this->prepend = (boolean) $prepend === true ? 'true' : 'false'; - return $this; - } - /** * Disables plugins. * From 4c8e8ca7020447b2a16baa0a7dc3ec3a7ccf2e41 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Mon, 14 Oct 2013 14:47:55 -0700 Subject: [PATCH 136/238] Allow specifying HHVM as a dependency --- src/Composer/Repository/PlatformRepository.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Composer/Repository/PlatformRepository.php b/src/Composer/Repository/PlatformRepository.php index dcf791857..214c8022f 100644 --- a/src/Composer/Repository/PlatformRepository.php +++ b/src/Composer/Repository/PlatformRepository.php @@ -144,5 +144,19 @@ class PlatformRepository extends ArrayRepository $lib->setDescription('The '.$name.' PHP library'); parent::addPackage($lib); } + + if (defined('HHVM_VERSION')) { + try { + $prettyVersion = HHVM_VERSION; + $version = $versionParser->normalize($prettyVersion); + } catch (\UnexpectedValueException $e) { + $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', HHVM_VERSION); + $version = $versionParser->normalize($prettyVersion); + } + + $hhvm = new CompletePackage('hhvm', $version, $prettyVersion); + $hhvm->setDescription('The HHVM Runtime (64bit)'); + parent::addPackage($hhvm); + } } } From 4f51db72f85c6bee5c65aae9ca78919be5257b49 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Mon, 14 Oct 2013 14:54:08 -0700 Subject: [PATCH 137/238] hhvm version constant still called HPHP on older versions so use it for bc --- src/Composer/Repository/PlatformRepository.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Composer/Repository/PlatformRepository.php b/src/Composer/Repository/PlatformRepository.php index 214c8022f..550d180db 100644 --- a/src/Composer/Repository/PlatformRepository.php +++ b/src/Composer/Repository/PlatformRepository.php @@ -145,12 +145,12 @@ class PlatformRepository extends ArrayRepository parent::addPackage($lib); } - if (defined('HHVM_VERSION')) { + if (defined('HPHP_VERSION')) { try { - $prettyVersion = HHVM_VERSION; + $prettyVersion = HPHP_VERSION; $version = $versionParser->normalize($prettyVersion); } catch (\UnexpectedValueException $e) { - $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', HHVM_VERSION); + $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', HPHP_VERSION); $version = $versionParser->normalize($prettyVersion); } From 42dd2f2ee8dad155ec566fe8405980dea7b2196f Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Mon, 14 Oct 2013 15:15:09 -0700 Subject: [PATCH 138/238] Check only part of the error message as it's different in hhvm --- tests/Composer/Test/Util/ErrorHandlerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Composer/Test/Util/ErrorHandlerTest.php b/tests/Composer/Test/Util/ErrorHandlerTest.php index 485c2bd39..cb16a1e13 100644 --- a/tests/Composer/Test/Util/ErrorHandlerTest.php +++ b/tests/Composer/Test/Util/ErrorHandlerTest.php @@ -38,7 +38,7 @@ class ErrorHandlerTest extends TestCase */ public function testErrorHandlerCaptureWarning() { - $this->setExpectedException('\ErrorException', 'array_merge(): Argument #2 is not an array'); + $this->setExpectedException('\ErrorException', 'array_merge'); ErrorHandler::register(); From 565f86f30d9d9ef5ba6b9993e51a99affa98e14d Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Mon, 14 Oct 2013 17:53:02 -0700 Subject: [PATCH 139/238] Fix stream context option test to really only verify content-type is last --- tests/Composer/Test/Util/StreamContextFactoryTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Composer/Test/Util/StreamContextFactoryTest.php b/tests/Composer/Test/Util/StreamContextFactoryTest.php index a12419afa..9e1bae090 100644 --- a/tests/Composer/Test/Util/StreamContextFactoryTest.php +++ b/tests/Composer/Test/Util/StreamContextFactoryTest.php @@ -192,6 +192,6 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase ); $context = StreamContextFactory::getContext('http://example.org', $options); $ctxoptions = stream_context_get_options($context); - $this->assertEquals(join("\n", $ctxoptions['http']['header']), join("\n", $expectedOptions['http']['header'])); + $this->assertEquals(end($ctxoptions['http']['header']), end($expectedOptions['http']['header'])); } } From 6c96bf6ae672b32fce9550e17c48f10092d66f1f Mon Sep 17 00:00:00 2001 From: Joshua Gigg Date: Tue, 15 Oct 2013 14:07:05 +0100 Subject: [PATCH 140/238] Add documentation for resolve-dependencies --- .../handling-private-packages-with-satis.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/doc/articles/handling-private-packages-with-satis.md b/doc/articles/handling-private-packages-with-satis.md index 3272ef448..11d513293 100644 --- a/doc/articles/handling-private-packages-with-satis.md +++ b/doc/articles/handling-private-packages-with-satis.md @@ -170,3 +170,19 @@ bucket or on a CDN host. A CDN would drastically improve download times and ther Example: A `prefix-url` of `http://my-bucket.s3.amazonaws.com` (and `directory` set to `dist`) creates download URLs which look like the following: `http://my-bucket.s3.amazonaws.com/dist/vendor-package-version-ref.zip`. + + +### Resolving dependencies + +It is possible to make satis automatically resolve and add all dependencies for your projects. This can be used +with the Downloads functionality to have a complete local mirror of packages. Just add the following +to your `satis.json`: + +```json +{ + "require-dependencies": true, +} +``` + +When searching for packages, satis will attempt to resolve all the required packages from the listed repositories. +Therefore, if you are requiring a package from Packagist, you will need to define it in your `satis.json`. From 07a7284ffc07de38758dc4d9c2e20cf864ba6633 Mon Sep 17 00:00:00 2001 From: Phillip Look Date: Mon, 14 Oct 2013 10:49:34 +0200 Subject: [PATCH 141/238] Change dependency processing for update with whitelisted packages By default dependencies of white listed packages are no longer installed automaticaly. To Install dependencies of whitelisted packages use --with-dependencies. - rework after review comments - precise documentation of option - add missing punctuation marks --- doc/03-cli.md | 4 +- src/Composer/Command/UpdateCommand.php | 4 +- src/Composer/Installer.php | 18 +++++++++ .../update-whitelist-locked-require.test | 4 +- .../update-whitelist-with-dependencies.test | 40 +++++++++++++++++++ ...te-whitelist-with-dependency-conflict.test | 38 ++++++++++++++++++ .../Fixtures/installer/update-whitelist.test | 9 ++--- tests/Composer/Test/InstallerTest.php | 3 +- 8 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 tests/Composer/Test/Fixtures/installer/update-whitelist-with-dependencies.test create mode 100644 tests/Composer/Test/Fixtures/installer/update-whitelist-with-dependency-conflict.test diff --git a/doc/03-cli.md b/doc/03-cli.md index 267d19893..9c07776ff 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -122,7 +122,9 @@ You can also use wildcards to update a bunch of packages at once: autoloader. This is recommended especially for production, but can take a bit of time to run so it is currently not done by default. * **--lock:** Only updates the lock file hash to suppress warning about the - lock file being out of date + lock file being out of date. +* **--with-dependencies** Add also all dependencies of whitelisted packages to the whitelist. + So all packages with their dependencies are updated recursively. ## require diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index ceabf7ff4..b2f8298e1 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -43,8 +43,9 @@ class UpdateCommand extends Command new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'), new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), + new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also all dependencies of whitelisted packages to the whitelist.'), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), - new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump') + new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.') )) ->setHelp(<<update command reads the composer.json file from the @@ -107,6 +108,7 @@ EOT ->setOptimizeAutoloader($input->getOption('optimize-autoloader')) ->setUpdate(true) ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $input->getArgument('packages')) + ->setWhitelistDependencies($input->getOption('with-dependencies')) ; if ($input->getOption('no-plugins')) { diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index f7169c271..4c04a7eec 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -106,6 +106,7 @@ class Installer protected $update = false; protected $runScripts = true; protected $updateWhitelist = null; + protected $whitelistDependencies = false; /** * @var array @@ -851,6 +852,10 @@ class Installer $seen[$package->getId()] = true; $this->updateWhitelist[$package->getName()] = true; + if (!$this->whitelistDependencies) { + continue; + } + $requires = $package->getRequires(); foreach ($requires as $require) { @@ -1051,6 +1056,19 @@ class Installer return $this; } + /** + * Should dependencies of whitelisted packages be updated recursively? + * + * @param boolean $updateDependencies + * @return Installer + */ + public function setWhitelistDependencies($updateDependencies = true) + { + $this->whitelistDependencies = (boolean) $updateDependencies; + + return $this; + } + /** * Disables plugins. * diff --git a/tests/Composer/Test/Fixtures/installer/update-whitelist-locked-require.test b/tests/Composer/Test/Fixtures/installer/update-whitelist-locked-require.test index 6586e461f..381416af1 100644 --- a/tests/Composer/Test/Fixtures/installer/update-whitelist-locked-require.test +++ b/tests/Composer/Test/Fixtures/installer/update-whitelist-locked-require.test @@ -1,5 +1,5 @@ --TEST-- -Update with a package whitelist only updates those packages and their dependencies if they are not present in composer.json +Update with a package whitelist only updates those packages if they are not present in composer.json --COMPOSER-- { "repositories": [ @@ -30,7 +30,7 @@ Update with a package whitelist only updates those packages and their dependenci { "name": "fixed-sub-dependency", "version": "1.0.0" } ] --RUN-- -update whitelisted +update whitelisted dependency --EXPECT-- Updating dependency (1.0.0) to dependency (1.1.0) Updating whitelisted (1.0.0) to whitelisted (1.1.0) diff --git a/tests/Composer/Test/Fixtures/installer/update-whitelist-with-dependencies.test b/tests/Composer/Test/Fixtures/installer/update-whitelist-with-dependencies.test new file mode 100644 index 000000000..bb2e04193 --- /dev/null +++ b/tests/Composer/Test/Fixtures/installer/update-whitelist-with-dependencies.test @@ -0,0 +1,40 @@ +--TEST-- +Update with a package whitelist only updates those packages and their dependencies listed as command arguments +--COMPOSER-- +{ + "repositories": [ + { + "type": "package", + "package": [ + { "name": "fixed", "version": "1.1.0" }, + { "name": "fixed", "version": "1.0.0" }, + { "name": "whitelisted", "version": "1.1.0", "require": { "dependency": "1.1.0" } }, + { "name": "whitelisted", "version": "1.0.0", "require": { "dependency": "1.0.0" } }, + { "name": "dependency", "version": "1.1.0" }, + { "name": "dependency", "version": "1.0.0" }, + { "name": "unrelated", "version": "1.1.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated", "version": "1.0.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated-dependency", "version": "1.1.0" }, + { "name": "unrelated-dependency", "version": "1.0.0" } + ] + } + ], + "require": { + "fixed": "1.*", + "whitelisted": "1.*", + "unrelated": "1.*" + } +} +--INSTALLED-- +[ + { "name": "fixed", "version": "1.0.0" }, + { "name": "whitelisted", "version": "1.0.0", "require": { "dependency": "1.0.0" } }, + { "name": "dependency", "version": "1.0.0" }, + { "name": "unrelated", "version": "1.0.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated-dependency", "version": "1.0.0" } +] +--RUN-- +update whitelisted --with-dependencies +--EXPECT-- +Updating dependency (1.0.0) to dependency (1.1.0) +Updating whitelisted (1.0.0) to whitelisted (1.1.0) diff --git a/tests/Composer/Test/Fixtures/installer/update-whitelist-with-dependency-conflict.test b/tests/Composer/Test/Fixtures/installer/update-whitelist-with-dependency-conflict.test new file mode 100644 index 000000000..f63229fbc --- /dev/null +++ b/tests/Composer/Test/Fixtures/installer/update-whitelist-with-dependency-conflict.test @@ -0,0 +1,38 @@ +--TEST-- +Update with a package whitelist only updates whitelisted packages if no dependency conflicts +--COMPOSER-- +{ + "repositories": [ + { + "type": "package", + "package": [ + { "name": "fixed", "version": "1.1.0" }, + { "name": "fixed", "version": "1.0.0" }, + { "name": "whitelisted", "version": "1.1.0", "require": { "dependency": "1.1.0" } }, + { "name": "whitelisted", "version": "1.0.0", "require": { "dependency": "1.0.0" } }, + { "name": "dependency", "version": "1.1.0" }, + { "name": "dependency", "version": "1.0.0" }, + { "name": "unrelated", "version": "1.1.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated", "version": "1.0.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated-dependency", "version": "1.1.0" }, + { "name": "unrelated-dependency", "version": "1.0.0" } + ] + } + ], + "require": { + "fixed": "1.*", + "whitelisted": "1.*", + "unrelated": "1.*" + } +} +--INSTALLED-- +[ + { "name": "fixed", "version": "1.0.0" }, + { "name": "whitelisted", "version": "1.0.0", "require": { "dependency": "1.0.0" } }, + { "name": "dependency", "version": "1.0.0" }, + { "name": "unrelated", "version": "1.0.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated-dependency", "version": "1.0.0" } +] +--RUN-- +update whitelisted +--EXPECT-- diff --git a/tests/Composer/Test/Fixtures/installer/update-whitelist.test b/tests/Composer/Test/Fixtures/installer/update-whitelist.test index 3d7ca30af..751d79e70 100644 --- a/tests/Composer/Test/Fixtures/installer/update-whitelist.test +++ b/tests/Composer/Test/Fixtures/installer/update-whitelist.test @@ -1,5 +1,5 @@ --TEST-- -Update with a package whitelist only updates those packages and their dependencies listed as command arguments +Update with a package whitelist only updates those packages listed as command arguments --COMPOSER-- { "repositories": [ @@ -8,8 +8,8 @@ Update with a package whitelist only updates those packages and their dependenci "package": [ { "name": "fixed", "version": "1.1.0" }, { "name": "fixed", "version": "1.0.0" }, - { "name": "whitelisted", "version": "1.1.0", "require": { "dependency": "1.1.0" } }, - { "name": "whitelisted", "version": "1.0.0", "require": { "dependency": "1.0.0" } }, + { "name": "whitelisted", "version": "1.1.0", "require": { "dependency": "1.*" } }, + { "name": "whitelisted", "version": "1.0.0", "require": { "dependency": "1.*" } }, { "name": "dependency", "version": "1.1.0" }, { "name": "dependency", "version": "1.0.0" }, { "name": "unrelated", "version": "1.1.0", "require": { "unrelated-dependency": "1.*" } }, @@ -28,7 +28,7 @@ Update with a package whitelist only updates those packages and their dependenci --INSTALLED-- [ { "name": "fixed", "version": "1.0.0" }, - { "name": "whitelisted", "version": "1.0.0", "require": { "dependency": "1.0.0" } }, + { "name": "whitelisted", "version": "1.0.0", "require": { "dependency": "1.*" } }, { "name": "dependency", "version": "1.0.0" }, { "name": "unrelated", "version": "1.0.0", "require": { "unrelated-dependency": "1.*" } }, { "name": "unrelated-dependency", "version": "1.0.0" } @@ -36,5 +36,4 @@ Update with a package whitelist only updates those packages and their dependenci --RUN-- update whitelisted --EXPECT-- -Updating dependency (1.0.0) to dependency (1.1.0) Updating whitelisted (1.0.0) to whitelisted (1.1.0) diff --git a/tests/Composer/Test/InstallerTest.php b/tests/Composer/Test/InstallerTest.php index bd9e7d3b6..29c153e88 100644 --- a/tests/Composer/Test/InstallerTest.php +++ b/tests/Composer/Test/InstallerTest.php @@ -214,7 +214,8 @@ class InstallerTest extends TestCase ->setDevMode($input->getOption('dev')) ->setUpdate(true) ->setDryRun($input->getOption('dry-run')) - ->setUpdateWhitelist($input->getArgument('packages')); + ->setUpdateWhitelist($input->getArgument('packages')) + ->setWhitelistDependencies($input->getOption('with-dependencies')); return $installer->run() ? 0 : 1; }); From a6823d2f9b62d4e2244eee6d12da1ef0fc44502b Mon Sep 17 00:00:00 2001 From: Fabian Grutschus Date: Wed, 16 Oct 2013 10:07:10 +0200 Subject: [PATCH 142/238] non-deep check returns allways false --- src/Composer/Repository/Vcs/PerforceDriver.php | 4 ++++ .../Test/Repository/Vcs/PerforceDriverTest.php | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index a6d52bfb6..af20c4667 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -160,6 +160,10 @@ class PerforceDriver extends VcsDriver */ public static function supports(IOInterface $io, $url, $deep = false) { + if (false === $deep) { + return false; + } + return Perforce::checkServerExists($url, new ProcessExecutor); } diff --git a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php index 277550e64..d2c8167b9 100644 --- a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php @@ -131,4 +131,17 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase $result = $driver->hasComposerFile($identifier); $this->assertTrue($result); } + + /** + * Test that supports() simply return false. + * + * @covers \Composer\Repository\Vcs\PerforceDriver::supports + * + * @return void + */ + public function testSupportsReturnsFalseNoDeepCheck() + { + $this->expectOutputString(''); + $this->assertFalse(PerforceDriver::supports($this->io, 'existing.url')); + } } From ce8b475f4c06bd9305709257e33d7cc52b34d273 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 16 Oct 2013 10:53:57 +0200 Subject: [PATCH 143/238] Minor tweaks to perforce support, refs #2329 --- src/Composer/Factory.php | 1 + src/Composer/Repository/Vcs/PerforceDriver.php | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index c3367ba4a..99b5a692b 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -292,6 +292,7 @@ class Factory $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository'); $rm->setRepositoryClass('git', 'Composer\Repository\VcsRepository'); $rm->setRepositoryClass('svn', 'Composer\Repository\VcsRepository'); + $rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository'); $rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository'); $rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository'); diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index af20c4667..54e1d3e7d 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -160,11 +160,11 @@ class PerforceDriver extends VcsDriver */ public static function supports(IOInterface $io, $url, $deep = false) { - if (false === $deep) { - return false; + if ($deep || preg_match('#\b(perforce|p4)\b#i', $url)) { + return Perforce::checkServerExists($url, new ProcessExecutor); } - - return Perforce::checkServerExists($url, new ProcessExecutor); + + return false; } /** From 18da5810c5defd32a0f911ec67b20f88394b6474 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 16 Oct 2013 12:13:34 +0200 Subject: [PATCH 144/238] Update deps --- composer.lock | 76 +++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/composer.lock b/composer.lock index 58bceb299..0522d3f3e 100644 --- a/composer.lock +++ b/composer.lock @@ -79,17 +79,17 @@ }, { "name": "symfony/console", - "version": "v2.3.4", + "version": "v2.3.6", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "db78f8ff7fc9e28d25ff9a0bf6ddf9f0e35fbbe3" + "reference": "f880062d56edefb25b36f2defa65aafe65959dc7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/db78f8ff7fc9e28d25ff9a0bf6ddf9f0e35fbbe3", - "reference": "db78f8ff7fc9e28d25ff9a0bf6ddf9f0e35fbbe3", + "url": "https://api.github.com/repos/symfony/Console/zipball/f880062d56edefb25b36f2defa65aafe65959dc7", + "reference": "f880062d56edefb25b36f2defa65aafe65959dc7", "shasum": "" }, "require": { @@ -128,21 +128,21 @@ ], "description": "Symfony Console Component", "homepage": "http://symfony.com", - "time": "2013-08-17 16:34:49" + "time": "2013-09-25 06:04:15" }, { "name": "symfony/finder", - "version": "v2.3.4", + "version": "v2.3.6", "target-dir": "Symfony/Component/Finder", "source": { "type": "git", "url": "https://github.com/symfony/Finder.git", - "reference": "4a0fee5b86f5bbd9dfdc11ec124eba2915737ce1" + "reference": "a175521f680b178e63c5d0ab87c6b046c0990c3f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/4a0fee5b86f5bbd9dfdc11ec124eba2915737ce1", - "reference": "4a0fee5b86f5bbd9dfdc11ec124eba2915737ce1", + "url": "https://api.github.com/repos/symfony/Finder/zipball/a175521f680b178e63c5d0ab87c6b046c0990c3f", + "reference": "a175521f680b178e63c5d0ab87c6b046c0990c3f", "shasum": "" }, "require": { @@ -175,7 +175,7 @@ ], "description": "Symfony Finder Component", "homepage": "http://symfony.com", - "time": "2013-08-13 20:18:00" + "time": "2013-09-19 09:45:20" }, { "name": "symfony/process", @@ -184,12 +184,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Process.git", - "reference": "3d8287117bb7c638a0164cf4ac471256a30e0620" + "reference": "27b0fc645a557b2fc7bc7735cfb05505de9351be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/3d8287117bb7c638a0164cf4ac471256a30e0620", - "reference": "3d8287117bb7c638a0164cf4ac471256a30e0620", + "url": "https://api.github.com/repos/symfony/Process/zipball/27b0fc645a557b2fc7bc7735cfb05505de9351be", + "reference": "27b0fc645a557b2fc7bc7735cfb05505de9351be", "shasum": "" }, "require": { @@ -222,7 +222,7 @@ ], "description": "Symfony Process Component", "homepage": "http://symfony.com", - "time": "2013-09-18 07:05:46" + "time": "2013-10-10 05:53:18" } ], "packages-dev": [ @@ -289,16 +289,16 @@ }, { "name": "phpunit/php-file-iterator", - "version": "1.3.3", + "version": "1.3.4", "source": { "type": "git", - "url": "git://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "1.3.3" + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" }, "dist": { "type": "zip", - "url": "https://github.com/sebastianbergmann/php-file-iterator/zipball/1.3.3", - "reference": "1.3.3", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", + "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", "shasum": "" }, "require": { @@ -325,25 +325,25 @@ } ], "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "http://www.phpunit.de/", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", "keywords": [ "filesystem", "iterator" ], - "time": "2012-10-11 04:44:38" + "time": "2013-10-10 15:34:57" }, { "name": "phpunit/php-text-template", "version": "1.1.4", "source": { "type": "git", - "url": "git://github.com/sebastianbergmann/php-text-template.git", - "reference": "1.1.4" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5180896f51c5b3648ac946b05f9ec02be78a0b23" }, "dist": { "type": "zip", - "url": "https://github.com/sebastianbergmann/php-text-template/zipball/1.1.4", - "reference": "1.1.4", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5180896f51c5b3648ac946b05f9ec02be78a0b23", + "reference": "5180896f51c5b3648ac946b05f9ec02be78a0b23", "shasum": "" }, "require": { @@ -374,7 +374,7 @@ "keywords": [ "template" ], - "time": "2012-10-31 11:15:28" + "time": "2012-10-31 18:15:28" }, { "name": "phpunit/php-timer", @@ -382,12 +382,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "1.0.5" + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1.0.5", - "reference": "1.0.5", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", "shasum": "" }, "require": { @@ -549,13 +549,13 @@ "version": "1.2.3", "source": { "type": "git", - "url": "git://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "1.2.3" + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875" }, "dist": { "type": "zip", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects/archive/1.2.3.zip", - "reference": "1.2.3", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5794e3c5c5ba0fb037b11d8151add2a07fa82875", + "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875", "shasum": "" }, "require": { @@ -595,17 +595,17 @@ }, { "name": "symfony/yaml", - "version": "v2.3.4", + "version": "v2.3.6", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "5a279f1b5f5e1045a6c432354d9ea727ff3a9847" + "reference": "6bb881b948368482e1abf1a75c08bcf88a1c5fc3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/5a279f1b5f5e1045a6c432354d9ea727ff3a9847", - "reference": "5a279f1b5f5e1045a6c432354d9ea727ff3a9847", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/6bb881b948368482e1abf1a75c08bcf88a1c5fc3", + "reference": "6bb881b948368482e1abf1a75c08bcf88a1c5fc3", "shasum": "" }, "require": { @@ -638,7 +638,7 @@ ], "description": "Symfony Yaml Component", "homepage": "http://symfony.com", - "time": "2013-08-24 15:26:22" + "time": "2013-09-22 18:04:39" } ], "aliases": [ From 6ce0bf7cbf5edc622a8ccfbca226ffc825ca699e Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 16 Oct 2013 12:17:18 +0200 Subject: [PATCH 145/238] Update docs for #2314 --- doc/04-schema.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/04-schema.md b/doc/04-schema.md index 7d2775af1..ec885bf85 100644 --- a/doc/04-schema.md +++ b/doc/04-schema.md @@ -652,6 +652,9 @@ The following options are supported: dist (zip, tar, ..) packages that it downloads. When the garbage collection is periodically ran, this is the maximum size the cache will be able to use. Older (less used) files will be removed first until the cache fits. +* **prepend-autoloader:** Defaults to `true`. If false, the composer autoloader + will not be prepended to existing autoloaders. This is sometimesrequired to fix + interoperability issues with other autoloaders. * **notify-on-install:** Defaults to `true`. Composer allows repositories to define a notification URL, so that they get notified whenever a package from that repository is installed. This option allows you to disable that behaviour. From d21994bdbf629c082c47d62734e6bc3aa14b8dab Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 16 Oct 2013 14:10:42 +0200 Subject: [PATCH 146/238] Point to docs for install instructions, fixes #2336 --- README.md | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 90b3dac90..cc93302e3 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,10 @@ Installation / Usage $ curl -sS https://getcomposer.org/installer | php ``` - 2. Create a composer.json defining your dependencies. Note that this example is a short version for applications that are not meant to be published as packages -themselves. To create libraries/packages please read the [guidelines](https://packagist.org/about). +themselves. To create libraries/packages please read the +[documentation](http://getcomposer.org/doc/02-libraries.md). ``` json { @@ -47,17 +47,9 @@ You can now run Composer by executing the `bin/composer` script: `php /path/to/c Global installation of Composer (manual) ---------------------------------------- -Since Composer works with the current working directory it is possible to install it -in a system wide way. +Follow instructions [in the documentation](http://getcomposer.org/doc/00-intro.md#globally) -1. Change into a directory in your path like `cd /usr/local/bin` -2. Get Composer `curl -sS https://getcomposer.org/installer | php` -3. Make the phar executable `chmod a+x composer.phar` -4. Change into a project directory `cd /path/to/my/project` -5. Use Composer as you normally would `composer.phar install` -6. Optionally you can rename the composer.phar to composer to make it easier - -Global installation of Composer (via homebrew) +Global installation of Composer (for OSX/homebrew) ---------------------------------------------- Composer is part of the homebrew-php project. From 6e3cfb5fea364d726ab3a44876fc09327cd4d97c Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 16 Oct 2013 15:55:53 +0200 Subject: [PATCH 147/238] Code cleanup, refs #2316 --- src/Composer/Repository/Vcs/GitDriver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index e2a3a9eb0..143144712 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -80,7 +80,7 @@ class GitDriver extends VcsDriver $this->getTags(); $this->getBranches(); - $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url)); + $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->url); } /** From 28abb08da8aa051f02c85848f565bff8b336f153 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 16 Oct 2013 16:24:48 +0200 Subject: [PATCH 148/238] Move homebrew docs to the docs --- README.md | 9 --------- doc/00-intro.md | 11 ++++++++++- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index cc93302e3..e0e4e73b0 100644 --- a/README.md +++ b/README.md @@ -49,15 +49,6 @@ Global installation of Composer (manual) Follow instructions [in the documentation](http://getcomposer.org/doc/00-intro.md#globally) -Global installation of Composer (for OSX/homebrew) ----------------------------------------------- - -Composer is part of the homebrew-php project. - -1. Tap the homebrew-php repository into your brew installation if you haven't done yet: `brew tap josegonzalez/homebrew-php` -2. Run `brew install josegonzalez/php/composer`. -3. Use Composer with the `composer` command. - Updating Composer ----------------- diff --git a/doc/00-intro.md b/doc/00-intro.md index 46ec8bba8..487a6a9e5 100644 --- a/doc/00-intro.md +++ b/doc/00-intro.md @@ -91,6 +91,15 @@ You can run these commands to easily access `composer` from anywhere on your sys Then, just run `composer` in order to run Composer instead of `php composer.phar`. +#### Globally (on OSX via homebrew) + +Composer is part of the homebrew-php project. + +1. Tap the homebrew-php repository into your brew installation if you haven't done + so yet: `brew tap josegonzalez/homebrew-php` +2. Run `brew install josegonzalez/php/composer`. +3. Use Composer with the `composer` command. + ## Installation - Windows ### Using the Installer @@ -108,7 +117,7 @@ composer.phar: C:\Users\username>cd C:\bin C:\bin>php -r "eval('?>'.file_get_contents('https://getcomposer.org/installer'));" - + > **Note:** If the above fails due to file_get_contents, use the `http` url or enable php_openssl.dll in php.ini Create a new `composer.bat` file alongside `composer.phar`: From 7f03fad391dfc39b03aa36c9e049b707b6ca7ff1 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 16 Oct 2013 18:07:09 +0200 Subject: [PATCH 149/238] Revert "Code cleanup, refs #2316" This reverts commit 6e3cfb5fea364d726ab3a44876fc09327cd4d97c. --- src/Composer/Repository/Vcs/GitDriver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index 143144712..e2a3a9eb0 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -80,7 +80,7 @@ class GitDriver extends VcsDriver $this->getTags(); $this->getBranches(); - $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->url); + $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url)); } /** From 34dd0e2850b20f6d9e40c9ca6024629cdc1a9aaf Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 16 Oct 2013 18:35:44 +0200 Subject: [PATCH 150/238] Add new config option to json schema --- res/composer-schema.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/res/composer-schema.json b/res/composer-schema.json index eef9aa3d6..1f68c8b43 100644 --- a/res/composer-schema.json +++ b/res/composer-schema.json @@ -175,6 +175,10 @@ "discard-changes": { "type": ["string", "boolean"], "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"." + }, + "prepend-autoloader": { + "type": "boolean", + "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true." } } }, From 9df65ee4c842c1531560426df2a0d3f0a6b826e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Thu, 17 Oct 2013 11:10:16 +0200 Subject: [PATCH 151/238] Fixed filesystem issue on windows --- src/Composer/Util/Filesystem.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index 58d807f40..fe7b90bbd 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -223,11 +223,11 @@ class Filesystem } $commonPath = $to; - while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) { + while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) { $commonPath = dirname($commonPath); } - if (0 !== strpos($from, $commonPath) || '/' === $commonPath) { + if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) { return $to; } @@ -261,11 +261,11 @@ class Filesystem } $commonPath = $to; - while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) { + while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) { $commonPath = dirname($commonPath); } - if (0 !== strpos($from, $commonPath) || '/' === $commonPath) { + if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) { return var_export($to, true); } From 0c5f4d98605e272dc7b18ceb6454abf46f2a6586 Mon Sep 17 00:00:00 2001 From: mwhittom Date: Thu, 17 Oct 2013 13:39:32 -0500 Subject: [PATCH 152/238] Update to fix issue with multiple perforce repositories --- src/Composer/Downloader/PerforceDownloader.php | 1 + src/Composer/Util/Perforce.php | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index 3aa8d0a43..011c0f593 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -45,6 +45,7 @@ class PerforceDownloader extends VcsDownloader private function initPerforce($package, $path, $ref) { if ($this->perforce) { + $this->perforce->initializePath($path); return; } diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 5bb368575..ecaf3a720 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -38,9 +38,7 @@ class Perforce { $this->windowsFlag = $isWindows; $this->p4Port = $port; - $this->path = $path; - $fs = new Filesystem(); - $fs->ensureDirectoryExists($path); + $this->initializePath($path); $this->process = $process; $this->initialize($repoConfig); } @@ -131,6 +129,13 @@ class Perforce return $this->path; } + public function initializePath($path) + { + $this->path = $path; + $fs = new Filesystem(); + $fs->ensureDirectoryExists($path); + } + protected function getPort() { return $this->p4Port; From 3dd3233e209df08f7c9a241b0640090c73275382 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 17 Oct 2013 21:08:23 +0200 Subject: [PATCH 153/238] Clarify tag docs, fixes #2343 --- doc/02-libraries.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/02-libraries.md b/doc/02-libraries.md index 3c6323e9c..12e96ec96 100644 --- a/doc/02-libraries.md +++ b/doc/02-libraries.md @@ -70,8 +70,8 @@ you can just add a `version` field: For every tag that looks like a version, a package version of that tag will be created. It should match 'X.Y.Z' or 'vX.Y.Z', with an optional suffix -of `-dev`, `-patch`, `-alpha`, `-beta` or `-RC`. The patch, alpha, beta and -RC suffixes can also be followed by a number. +of `-patch`, `-alpha`, `-beta` or `-RC`. The suffixes can also be followed by +a number. Here are a few examples of valid tag names: From 08243ce2e3129997461bfe0881983876a304e3a7 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 18 Oct 2013 11:35:09 +0200 Subject: [PATCH 154/238] Fix handling of urlencoded user and password in proxy urls, fixes #2339 --- src/Composer/Util/StreamContextFactory.php | 4 ++-- tests/Composer/Test/Util/StreamContextFactoryTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Composer/Util/StreamContextFactory.php b/src/Composer/Util/StreamContextFactory.php index 892016674..9ed131b02 100644 --- a/src/Composer/Util/StreamContextFactory.php +++ b/src/Composer/Util/StreamContextFactory.php @@ -91,9 +91,9 @@ final class StreamContextFactory } if (isset($proxy['user'])) { - $auth = $proxy['user']; + $auth = urldecode($proxy['user']); if (isset($proxy['pass'])) { - $auth .= ':' . $proxy['pass']; + $auth .= ':' . urldecode($proxy['pass']); } $auth = base64_encode($auth); diff --git a/tests/Composer/Test/Util/StreamContextFactoryTest.php b/tests/Composer/Test/Util/StreamContextFactoryTest.php index 9e1bae090..b0923e6df 100644 --- a/tests/Composer/Test/Util/StreamContextFactoryTest.php +++ b/tests/Composer/Test/Util/StreamContextFactoryTest.php @@ -59,7 +59,7 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase public function testHttpProxy() { - $_SERVER['http_proxy'] = 'http://username:password@proxyserver.net:3128/'; + $_SERVER['http_proxy'] = 'http://username:p%40ssword@proxyserver.net:3128/'; $_SERVER['HTTP_PROXY'] = 'http://proxyserver/'; $context = StreamContextFactory::getContext('http://example.org', array('http' => array('method' => 'GET'))); @@ -69,7 +69,7 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase 'proxy' => 'tcp://proxyserver.net:3128', 'request_fulluri' => true, 'method' => 'GET', - 'header' => array("Proxy-Authorization: Basic " . base64_encode('username:password')), + 'header' => array("Proxy-Authorization: Basic " . base64_encode('username:p@ssword')), 'max_redirects' => 20, 'follow_location' => 1, )), $options); From efb41d467e0e061dffa22ba314e0812daccd7811 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 18 Oct 2013 11:45:05 +0200 Subject: [PATCH 155/238] Skip redirect to URL lines in svn output, fixes #2338 --- src/Composer/Util/Svn.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Composer/Util/Svn.php b/src/Composer/Util/Svn.php index c61c55584..bcc3bb155 100644 --- a/src/Composer/Util/Svn.php +++ b/src/Composer/Util/Svn.php @@ -92,6 +92,9 @@ class Svn if ($type !== 'out') { return; } + if ('Redirecting to URL ' === substr($buffer, 0, 19)) { + return; + } $output .= $buffer; if ($verbose) { $io->write($buffer, false); From 4198688f54bbc9cddf9b58e8d59f1339653aa190 Mon Sep 17 00:00:00 2001 From: Sebastian Schawohl Date: Fri, 18 Oct 2013 16:41:54 +0200 Subject: [PATCH 156/238] Change date format when getting log from mercurial Use rfc3339date format instead of rfc822date to avoid exceptions from DateTime constructor because of localized dates. fix #2346 --- src/Composer/Repository/Vcs/HgDriver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/Vcs/HgDriver.php b/src/Composer/Repository/Vcs/HgDriver.php index 36ed205f2..c3c06e38a 100644 --- a/src/Composer/Repository/Vcs/HgDriver.php +++ b/src/Composer/Repository/Vcs/HgDriver.php @@ -124,7 +124,7 @@ class HgDriver extends VcsDriver $composer = JsonFile::parseJson($composer, $identifier); if (!isset($composer['time'])) { - $this->process->execute(sprintf('hg log --template "{date|rfc822date}" -r %s', escapeshellarg($identifier)), $output, $this->repoDir); + $this->process->execute(sprintf('hg log --template "{date|rfc3339date}" -r %s', escapeshellarg($identifier)), $output, $this->repoDir); $date = new \DateTime(trim($output), new \DateTimeZone('UTC')); $composer['time'] = $date->format('Y-m-d H:i:s'); } From e2671b6510f994cbcae9642be9bdc74c00f25f5b Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 19 Oct 2013 13:38:30 +0200 Subject: [PATCH 157/238] Add test and fix patch for #2304, refs #2341 --- src/Composer/Util/Filesystem.php | 4 ++-- tests/Composer/Test/Util/FilesystemTest.php | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index fe7b90bbd..15ce1cebd 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -223,11 +223,11 @@ class Filesystem } $commonPath = $to; - while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) { + while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '\\' !== $commonPath) { $commonPath = dirname($commonPath); } - if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) { + if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '\\' === $commonPath) { return $to; } diff --git a/tests/Composer/Test/Util/FilesystemTest.php b/tests/Composer/Test/Util/FilesystemTest.php index 29e7d8c62..c74e84a5f 100644 --- a/tests/Composer/Test/Util/FilesystemTest.php +++ b/tests/Composer/Test/Util/FilesystemTest.php @@ -106,6 +106,7 @@ class FilesystemTest extends TestCase array('/tmp/test/.././vendor', '/tmp/test', '../test', true), array('C:/Temp', 'c:\Temp\..\..\test', "../test", true), array('C:/Temp/../..', 'c:\Temp\..\..\test', "./test", true), + array('C:/Temp/../..', 'D:\Temp\..\..\test', "d:/test", true), array('/tmp', '/tmp/../../test', '/test', true), array('/foo/bar', '/foo/bar_vendor', '../bar_vendor', true), array('/foo/bar_vendor', '/foo/bar', '../bar', true), From c4818e5cb4af42ffe41a4bb27404c2ed44a6b2bb Mon Sep 17 00:00:00 2001 From: Joshua Gigg Date: Sat, 19 Oct 2013 15:03:00 +0100 Subject: [PATCH 158/238] Fix code formatting introduced by PR #2333 --- doc/articles/handling-private-packages-with-satis.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/articles/handling-private-packages-with-satis.md b/doc/articles/handling-private-packages-with-satis.md index 11d513293..0219f8108 100644 --- a/doc/articles/handling-private-packages-with-satis.md +++ b/doc/articles/handling-private-packages-with-satis.md @@ -178,9 +178,9 @@ It is possible to make satis automatically resolve and add all dependencies for with the Downloads functionality to have a complete local mirror of packages. Just add the following to your `satis.json`: -```json +``` { - "require-dependencies": true, + "require-dependencies": true } ``` From f5df1d6a9bea08bf16e9924478ada15712bd959f Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 19 Oct 2013 17:59:33 +0200 Subject: [PATCH 159/238] Fix cs --- .../Downloader/PerforceDownloaderTest.php | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php index b632d55d7..ed8948238 100644 --- a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php +++ b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php @@ -51,16 +51,16 @@ class PerforceDownloaderTest extends \PHPUnit_Framework_TestCase array($repoConfig, $this->io, $this->config) ); $package->expects($this->at(0)) - ->method('getSourceReference') - ->will($this->returnValue('SOURCE_REF')); + ->method('getSourceReference') + ->will($this->returnValue('SOURCE_REF')); $package->expects($this->at(1)) - ->method('getPrettyVersion') - ->will($this->returnValue('100')); + ->method('getPrettyVersion') + ->will($this->returnValue('100')); $package->expects($this->at(2)) - ->method('getRepository') - ->will($this->returnValue($repository)); + ->method('getRepository') + ->will($this->returnValue($repository)); $repository->expects($this->at(0)) - ->method('getRepoConfig'); + ->method('getRepoConfig'); $path = $this->testPath; $downloader->doDownload($package, $path); } @@ -80,26 +80,26 @@ class PerforceDownloaderTest extends \PHPUnit_Framework_TestCase $ref = 'SOURCE_REF'; $label = 'LABEL'; $perforce->expects($this->at(0)) - ->method('setStream') - ->with($this->equalTo($ref)); + ->method('setStream') + ->with($this->equalTo($ref)); $perforce->expects($this->at(1)) - ->method('queryP4User') - ->with($this->io); + ->method('queryP4User') + ->with($this->io); $perforce->expects($this->at(2)) - ->method('writeP4ClientSpec'); + ->method('writeP4ClientSpec'); $perforce->expects($this->at(3)) - ->method('connectClient'); + ->method('connectClient'); $perforce->expects($this->at(4)) - ->method('syncCodeBase') - ->with($this->equalTo($label)); + ->method('syncCodeBase') + ->with($this->equalTo($label)); $downloader->setPerforce($perforce); $package = $this->getMock('Composer\Package\PackageInterface'); $package->expects($this->at(0)) - ->method('getSourceReference') - ->will($this->returnValue($ref)); + ->method('getSourceReference') + ->will($this->returnValue($ref)); $package->expects($this->at(1)) - ->method('getPrettyVersion') - ->will($this->returnValue($label)); + ->method('getPrettyVersion') + ->will($this->returnValue($label)); $path = $this->testPath; $downloader->doDownload($package, $path); } From 1e4ace764dd08d3855f4b785eeff0d8a7ad3a225 Mon Sep 17 00:00:00 2001 From: ernest leitch Date: Sat, 19 Oct 2013 18:54:36 -0700 Subject: [PATCH 160/238] Update 00-intro.md Added note to help install PHP via brew if it's missing. --- doc/00-intro.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/00-intro.md b/doc/00-intro.md index 487a6a9e5..3b68fec9b 100644 --- a/doc/00-intro.md +++ b/doc/00-intro.md @@ -100,6 +100,9 @@ Composer is part of the homebrew-php project. 2. Run `brew install josegonzalez/php/composer`. 3. Use Composer with the `composer` command. +> **Note:** If you recieve an error saying PHP53 or higher is missing use this command to install php +> `brew install php53-intl` + ## Installation - Windows ### Using the Installer From 2a8eb9df34801c82abc33cb4957170e9e346c82c Mon Sep 17 00:00:00 2001 From: Chris Testroet Date: Sat, 19 Oct 2013 22:00:40 -0700 Subject: [PATCH 161/238] Remove slashes from package archive filename --- src/Composer/Package/Archiver/ArchiveManager.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Composer/Package/Archiver/ArchiveManager.php b/src/Composer/Package/Archiver/ArchiveManager.php index 6e7005a5a..b57358fa0 100644 --- a/src/Composer/Package/Archiver/ArchiveManager.php +++ b/src/Composer/Package/Archiver/ArchiveManager.php @@ -83,9 +83,11 @@ class ArchiveManager $nameParts[] = substr(sha1($package->getSourceReference()), 0, 6); } - return implode('-', array_filter($nameParts, function ($p) { + $name = implode('-', array_filter($nameParts, function ($p) { return !empty($p); })); + + return str_replace('/', '-', $name); } /** From ebece5a3b9d2fbe6057f09e5a63bc5ed6a04946e Mon Sep 17 00:00:00 2001 From: ernest leitch Date: Sun, 20 Oct 2013 10:14:41 -0700 Subject: [PATCH 162/238] Update 00-intro.md Updated spelling --- doc/00-intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/00-intro.md b/doc/00-intro.md index 3b68fec9b..7b62fee16 100644 --- a/doc/00-intro.md +++ b/doc/00-intro.md @@ -100,7 +100,7 @@ Composer is part of the homebrew-php project. 2. Run `brew install josegonzalez/php/composer`. 3. Use Composer with the `composer` command. -> **Note:** If you recieve an error saying PHP53 or higher is missing use this command to install php +> **Note:** If you receive an error saying PHP53 or higher is missing use this command to install php > `brew install php53-intl` ## Installation - Windows From 50fbfe4d635b976c436d50e0735fd05358278357 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 28 Oct 2013 11:01:17 +0100 Subject: [PATCH 163/238] Filesystem/autoload fixes for windows, refs #2304, #2342, #2365 --- src/Composer/Autoload/AutoloadGenerator.php | 2 +- src/Composer/Util/Filesystem.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index b19548460..1252371d6 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -43,7 +43,7 @@ class AutoloadGenerator $filesystem = new Filesystem(); $filesystem->ensureDirectoryExists($config->get('vendor-dir')); - $basePath = $filesystem->normalizePath(getcwd()); + $basePath = $filesystem->normalizePath(realpath(getcwd())); $vendorPath = $filesystem->normalizePath(realpath($config->get('vendor-dir'))); $useGlobalIncludePath = (bool) $config->get('use-include-path'); $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true'; diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index 15ce1cebd..2e18eb71e 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -223,11 +223,11 @@ class Filesystem } $commonPath = $to; - while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '\\' !== $commonPath) { - $commonPath = dirname($commonPath); + while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) { + $commonPath = strtr(dirname($commonPath), '\\', '/'); } - if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '\\' === $commonPath) { + if (0 !== strpos($from, $commonPath) || '/' === $commonPath) { return $to; } @@ -262,7 +262,7 @@ class Filesystem $commonPath = $to; while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) { - $commonPath = dirname($commonPath); + $commonPath = strtr(dirname($commonPath), '\\', '/'); } if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) { From 7148b224142a7c928c45e59049efb4d82d5677de Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 8 Sep 2012 01:51:33 +0200 Subject: [PATCH 164/238] Add github-domains config value for GitHub Enterprise setups, fixes #728 Signed-off-by: Gennady Feldman --- doc/04-schema.md | 2 ++ res/composer-schema.json | 7 +++++++ src/Composer/Config.php | 1 + src/Composer/Downloader/GitDownloader.php | 13 +++++++++---- .../Composer/Test/Downloader/GitDownloaderTest.php | 5 +---- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/doc/04-schema.md b/doc/04-schema.md index ec885bf85..c4de65150 100644 --- a/doc/04-schema.md +++ b/doc/04-schema.md @@ -655,6 +655,8 @@ The following options are supported: * **prepend-autoloader:** Defaults to `true`. If false, the composer autoloader will not be prepended to existing autoloaders. This is sometimesrequired to fix interoperability issues with other autoloaders. +* **github-domains:** Defaults to `["github.com"]`. A list of domains to use in + github mode. This is used for GitHub Enterprise setups. * **notify-on-install:** Defaults to `true`. Composer allows repositories to define a notification URL, so that they get notified whenever a package from that repository is installed. This option allows you to disable that behaviour. diff --git a/res/composer-schema.json b/res/composer-schema.json index 1f68c8b43..7b52d7733 100644 --- a/res/composer-schema.json +++ b/res/composer-schema.json @@ -179,6 +179,13 @@ "prepend-autoloader": { "type": "boolean", "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true." + }, + "github-domains": { + "type": "array", + "description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].", + "items": { + "type": "string" + } } } }, diff --git a/src/Composer/Config.php b/src/Composer/Config.php index 6151b4f81..c893091c6 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -36,6 +36,7 @@ class Config 'cache-files-maxsize' => '300MiB', 'discard-changes' => false, 'prepend-autoloader' => true, + 'github-domains' => array('github.com'), ); public static $defaultRepositories = array( diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index f320cf931..c8e5744bc 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -293,7 +293,7 @@ class GitDownloader extends VcsDownloader } // public github, autoswitch protocols - if (preg_match('{^(?:https?|git)(://github.com/.*)}', $url, $match)) { + if (preg_match('{^(?:https?|git)(://'.$this->getGitHubDomainsRegex().'/.*)}', $url, $match)) { $protocols = $this->config->get('github-protocols'); if (!is_array($protocols)) { throw new \RuntimeException('Config value "github-protocols" must be an array, got '.gettype($protocols)); @@ -317,7 +317,7 @@ class GitDownloader extends VcsDownloader $command = call_user_func($commandCallable, $url); if (0 !== $this->process->execute($command, $ignoredOutput, $cwd)) { // private github repository without git access, try https with auth - if (preg_match('{^git@(github.com):(.+?)\.git$}i', $url, $match)) { + if (preg_match('{^git@'.$this->getGitHubDomainsRegex().':(.+?)\.git$}i', $url, $match)) { if (!$this->io->hasAuthentication($match[1])) { $gitHubUtil = new GitHub($this->io, $this->config, $this->process); $message = 'Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos'; @@ -368,6 +368,11 @@ class GitDownloader extends VcsDownloader } } + protected function getGitHubDomainsRegex() + { + return '('.implode('|', array_map('preg_quote', $this->config->get('github-domains'))).')'; + } + protected function throwException($message, $url) { if (0 !== $this->process->execute('git --version', $ignoredOutput)) { @@ -385,9 +390,9 @@ class GitDownloader extends VcsDownloader protected function setPushUrl(PackageInterface $package, $path) { // set push url for github projects - if (preg_match('{^(?:https?|git)://github.com/([^/]+)/([^/]+?)(?:\.git)?$}', $package->getSourceUrl(), $match)) { + if (preg_match('{^(?:https?|git)://'.$this->getGitHubDomainsRegex().'/([^/]+)/([^/]+?)(?:\.git)?$}', $package->getSourceUrl(), $match)) { $protocols = $this->config->get('github-protocols'); - $pushUrl = 'git@github.com:'.$match[1].'/'.$match[2].'.git'; + $pushUrl = 'git@'.$match[1].':'.$match[2].'/'.$match[3].'.git'; if ($protocols[0] !== 'git') { $pushUrl = 'https://github.com/'.$match[1].'/'.$match[2].'.git'; } diff --git a/tests/Composer/Test/Downloader/GitDownloaderTest.php b/tests/Composer/Test/Downloader/GitDownloaderTest.php index 1d093574a..7a0816eaf 100644 --- a/tests/Composer/Test/Downloader/GitDownloaderTest.php +++ b/tests/Composer/Test/Downloader/GitDownloaderTest.php @@ -24,10 +24,7 @@ class GitDownloaderTest extends \PHPUnit_Framework_TestCase $executor = $executor ?: $this->getMock('Composer\Util\ProcessExecutor'); $filesystem = $filesystem ?: $this->getMock('Composer\Util\Filesystem'); if (!$config) { - $config = $this->getMock('Composer\Config'); - $config->expects($this->any()) - ->method('has') - ->will($this->returnValue(false)); + $config = new Config(); } return new GitDownloader($io, $config, $executor, $filesystem); From f8376a5b345a151c1701c83844fcabd9ef983195 Mon Sep 17 00:00:00 2001 From: Gennady Feldman Date: Mon, 28 Oct 2013 12:23:06 -0400 Subject: [PATCH 165/238] Updating ConfigCommand so that we can set github-domains from the command line. --- src/Composer/Command/ConfigCommand.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Composer/Command/ConfigCommand.php b/src/Composer/Command/ConfigCommand.php index 7f92b2503..edc370a66 100644 --- a/src/Composer/Command/ConfigCommand.php +++ b/src/Composer/Command/ConfigCommand.php @@ -308,6 +308,18 @@ EOT return $vals; } ), + 'github-domains' => array( + function ($vals) { + if (!is_array($vals)) { + return 'array expected'; + } + + return true; + }, + function ($vals) { + return $vals; + } + ), ); foreach ($uniqueConfigValues as $name => $callbacks) { From e78499d28de4fd72d422fab3c3d6661cc4c88906 Mon Sep 17 00:00:00 2001 From: Gennady Feldman Date: Mon, 28 Oct 2013 12:29:37 -0400 Subject: [PATCH 166/238] First working version of GitHub Enterprise API. --- src/Composer/Repository/Vcs/GitHubDriver.php | 36 ++++++++++++-------- src/Composer/Util/GitHub.php | 8 ++--- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/Composer/Repository/Vcs/GitHubDriver.php b/src/Composer/Repository/Vcs/GitHubDriver.php index 6345fa473..f6cdd16f8 100644 --- a/src/Composer/Repository/Vcs/GitHubDriver.php +++ b/src/Composer/Repository/Vcs/GitHubDriver.php @@ -45,10 +45,10 @@ class GitHubDriver extends VcsDriver */ public function initialize() { - preg_match('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $this->url, $match); - $this->owner = $match[1]; - $this->repository = $match[2]; - $this->originUrl = 'github.com'; + preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git)?$#', $this->url, $match); + $this->owner = $match[3]; + $this->repository = $match[4]; + $this->originUrl = isset($match[1]) ? $match[1] : $match[2]; $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository); $this->fetchRootIdentifier(); @@ -75,7 +75,7 @@ class GitHubDriver extends VcsDriver return $this->gitDriver->getUrl(); } - return 'https://github.com/'.$this->owner.'/'.$this->repository.'.git'; + return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git'; } /** @@ -105,7 +105,8 @@ class GitHubDriver extends VcsDriver if ($this->gitDriver) { return $this->gitDriver->getDist($identifier); } - $url = 'https://api.github.com/repos/'.$this->owner.'/'.$this->repository.'/zipball/'.$identifier; + $apiUrl = ('github.com' === $this->originUrl) ? 'api.github.com' : $this->originUrl . '/api/v3'; + $url = 'https://' . $apiUrl . '/repos/'.$this->owner.'/'.$this->repository.'/zipball/'.$identifier; return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => ''); } @@ -127,7 +128,8 @@ class GitHubDriver extends VcsDriver $notFoundRetries = 2; while ($notFoundRetries) { try { - $resource = 'https://api.github.com/repos/'.$this->owner.'/'.$this->repository.'/contents/composer.json?ref='.urlencode($identifier); + $apiUrl = ('github.com' === $this->originUrl) ? 'api.github.com' : $this->originUrl . '/api/v3'; + $resource = 'https://' . $apiUrl . '/repos/'.$this->owner.'/'.$this->repository.'/contents/composer.json?ref='.urlencode($identifier); $composer = JsonFile::parseJson($this->getContents($resource)); if (empty($composer['content']) || $composer['encoding'] !== 'base64' || !($composer = base64_decode($composer['content']))) { throw new \RuntimeException('Could not retrieve composer.json from '.$resource); @@ -149,16 +151,17 @@ class GitHubDriver extends VcsDriver $composer = JsonFile::parseJson($composer, $resource); if (!isset($composer['time'])) { - $resource = 'https://api.github.com/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier); + $apiUrl = ('github.com' === $this->originUrl) ? 'api.github.com' : $this->originUrl . '/api/v3'; + $resource = 'https://' . $apiUrl . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier); $commit = JsonFile::parseJson($this->getContents($resource), $resource); $composer['time'] = $commit['commit']['committer']['date']; } if (!isset($composer['support']['source'])) { $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier; - $composer['support']['source'] = sprintf('https://github.com/%s/%s/tree/%s', $this->owner, $this->repository, $label); + $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label); } if (!isset($composer['support']['issues']) && $this->hasIssues) { - $composer['support']['issues'] = sprintf('https://github.com/%s/%s/issues', $this->owner, $this->repository); + $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository); } } @@ -181,7 +184,8 @@ class GitHubDriver extends VcsDriver return $this->gitDriver->getTags(); } if (null === $this->tags) { - $resource = 'https://api.github.com/repos/'.$this->owner.'/'.$this->repository.'/tags'; + $apiUrl = ('github.com' === $this->originUrl) ? 'api.github.com' : $this->originUrl . '/api/v3'; + $resource = 'https://' . $apiUrl . '/repos/'.$this->owner.'/'.$this->repository.'/tags'; $tagsData = JsonFile::parseJson($this->getContents($resource), $resource); $this->tags = array(); foreach ($tagsData as $tag) { @@ -201,7 +205,8 @@ class GitHubDriver extends VcsDriver return $this->gitDriver->getBranches(); } if (null === $this->branches) { - $resource = 'https://api.github.com/repos/'.$this->owner.'/'.$this->repository.'/git/refs/heads'; + $apiUrl = ('github.com' === $this->originUrl) ? 'api.github.com' : $this->originUrl . '/api/v3'; + $resource = 'https://' . $apiUrl . '/repos/'.$this->owner.'/'.$this->repository.'/git/refs/heads'; $branchData = JsonFile::parseJson($this->getContents($resource), $resource); $this->branches = array(); foreach ($branchData as $branch) { @@ -218,7 +223,7 @@ class GitHubDriver extends VcsDriver */ public static function supports(IOInterface $io, $url, $deep = false) { - if (!preg_match('#^((?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url)) { + if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git)?$#', $url)) { return false; } @@ -240,7 +245,7 @@ class GitHubDriver extends VcsDriver */ protected function generateSshUrl() { - return 'git@github.com:'.$this->owner.'/'.$this->repository.'.git'; + return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git'; } /** @@ -357,7 +362,8 @@ class GitHubDriver extends VcsDriver */ protected function fetchRootIdentifier() { - $repoDataUrl = 'https://api.github.com/repos/'.$this->owner.'/'.$this->repository; + $apiUrl = ('github.com' === $this->originUrl) ? 'api.github.com' : $this->originUrl . '/api/v3'; + $repoDataUrl = 'https://' . $apiUrl . '/repos/'.$this->owner.'/'.$this->repository; $repoData = JsonFile::parseJson($this->getContents($repoDataUrl, true), $repoDataUrl); if (null === $repoData && null !== $this->gitDriver) { diff --git a/src/Composer/Util/GitHub.php b/src/Composer/Util/GitHub.php index 93894cc76..ed988894b 100644 --- a/src/Composer/Util/GitHub.php +++ b/src/Composer/Util/GitHub.php @@ -51,10 +51,6 @@ class GitHub */ public function authorizeOAuth($originUrl) { - if ('github.com' !== $originUrl) { - return false; - } - // if available use token from git config if (0 === $this->process->execute('git config github.accesstoken', $output)) { $this->io->setAuthentication($originUrl, trim($output), 'x-oauth-basic'); @@ -78,6 +74,8 @@ class GitHub { $attemptCounter = 0; + $apiUrl = ('github.com' === $originUrl) ? 'api.github.com' : $originUrl . '/api/v3'; + if ($message) { $this->io->write($message); } @@ -95,7 +93,7 @@ class GitHub $appName .= ' on ' . trim($output); } - $contents = JsonFile::parseJson($this->remoteFilesystem->getContents($originUrl, 'https://api.github.com/authorizations', false, array( + $contents = JsonFile::parseJson($this->remoteFilesystem->getContents($originUrl, 'https://'. $apiUrl . '/authorizations', false, array( 'http' => array( 'method' => 'POST', 'follow_location' => false, From a4d7fc138a02afa9cc22cb826f5785906f172885 Mon Sep 17 00:00:00 2001 From: Gennady Feldman Date: Mon, 28 Oct 2013 13:08:18 -0400 Subject: [PATCH 167/238] Fixing broken unit test. --- src/Composer/Downloader/GitDownloader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index c8e5744bc..56b55629e 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -394,7 +394,7 @@ class GitDownloader extends VcsDownloader $protocols = $this->config->get('github-protocols'); $pushUrl = 'git@'.$match[1].':'.$match[2].'/'.$match[3].'.git'; if ($protocols[0] !== 'git') { - $pushUrl = 'https://github.com/'.$match[1].'/'.$match[2].'.git'; + $pushUrl = 'https://' . $match[1] . '/'.$match[2].'/'.$match[3].'.git'; } $cmd = sprintf('git remote set-url --push origin %s', escapeshellarg($pushUrl)); $this->process->execute($cmd, $ignoredOutput, $path); From 6419266ea3a25332f2070bf5b6363f1d299a23fc Mon Sep 17 00:00:00 2001 From: Gennady Feldman Date: Mon, 28 Oct 2013 15:32:51 -0400 Subject: [PATCH 168/238] Validate the originUrl against the list of 'github-domains' from the config. --- src/Composer/Util/GitHub.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Composer/Util/GitHub.php b/src/Composer/Util/GitHub.php index ed988894b..49e56f8c9 100644 --- a/src/Composer/Util/GitHub.php +++ b/src/Composer/Util/GitHub.php @@ -51,6 +51,10 @@ class GitHub */ public function authorizeOAuth($originUrl) { + if (!in_array($originUrl, $this->config->get('github-domains'))) { + return false; + } + // if available use token from git config if (0 === $this->process->execute('git config github.accesstoken', $output)) { $this->io->setAuthentication($originUrl, trim($output), 'x-oauth-basic'); From d8dbcab710e16a06d9908986260d81cda912f585 Mon Sep 17 00:00:00 2001 From: Gennady Feldman Date: Mon, 28 Oct 2013 15:38:28 -0400 Subject: [PATCH 169/238] Refactoring my code to use a protected function to generate API Url. --- src/Composer/Repository/Vcs/GitHubDriver.php | 33 +++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/Composer/Repository/Vcs/GitHubDriver.php b/src/Composer/Repository/Vcs/GitHubDriver.php index f6cdd16f8..f84eb74ca 100644 --- a/src/Composer/Repository/Vcs/GitHubDriver.php +++ b/src/Composer/Repository/Vcs/GitHubDriver.php @@ -78,6 +78,20 @@ class GitHubDriver extends VcsDriver return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git'; } + /** + * {@inheritDoc} + */ + protected function getApiUrl() + { + if ('github.com' === $this->originUrl) { + $apiUrl = 'api.github.com'; + } else { + $apiUrl = $this->originUrl . '/api/v3'; + } + + return 'https://' . $apiUrl; + } + /** * {@inheritDoc} */ @@ -105,8 +119,8 @@ class GitHubDriver extends VcsDriver if ($this->gitDriver) { return $this->gitDriver->getDist($identifier); } - $apiUrl = ('github.com' === $this->originUrl) ? 'api.github.com' : $this->originUrl . '/api/v3'; - $url = 'https://' . $apiUrl . '/repos/'.$this->owner.'/'.$this->repository.'/zipball/'.$identifier; + + $url = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/zipball/'.$identifier; return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => ''); } @@ -128,8 +142,7 @@ class GitHubDriver extends VcsDriver $notFoundRetries = 2; while ($notFoundRetries) { try { - $apiUrl = ('github.com' === $this->originUrl) ? 'api.github.com' : $this->originUrl . '/api/v3'; - $resource = 'https://' . $apiUrl . '/repos/'.$this->owner.'/'.$this->repository.'/contents/composer.json?ref='.urlencode($identifier); + $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/composer.json?ref='.urlencode($identifier); $composer = JsonFile::parseJson($this->getContents($resource)); if (empty($composer['content']) || $composer['encoding'] !== 'base64' || !($composer = base64_decode($composer['content']))) { throw new \RuntimeException('Could not retrieve composer.json from '.$resource); @@ -151,8 +164,7 @@ class GitHubDriver extends VcsDriver $composer = JsonFile::parseJson($composer, $resource); if (!isset($composer['time'])) { - $apiUrl = ('github.com' === $this->originUrl) ? 'api.github.com' : $this->originUrl . '/api/v3'; - $resource = 'https://' . $apiUrl . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier); + $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier); $commit = JsonFile::parseJson($this->getContents($resource), $resource); $composer['time'] = $commit['commit']['committer']['date']; } @@ -184,8 +196,7 @@ class GitHubDriver extends VcsDriver return $this->gitDriver->getTags(); } if (null === $this->tags) { - $apiUrl = ('github.com' === $this->originUrl) ? 'api.github.com' : $this->originUrl . '/api/v3'; - $resource = 'https://' . $apiUrl . '/repos/'.$this->owner.'/'.$this->repository.'/tags'; + $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/tags'; $tagsData = JsonFile::parseJson($this->getContents($resource), $resource); $this->tags = array(); foreach ($tagsData as $tag) { @@ -205,8 +216,7 @@ class GitHubDriver extends VcsDriver return $this->gitDriver->getBranches(); } if (null === $this->branches) { - $apiUrl = ('github.com' === $this->originUrl) ? 'api.github.com' : $this->originUrl . '/api/v3'; - $resource = 'https://' . $apiUrl . '/repos/'.$this->owner.'/'.$this->repository.'/git/refs/heads'; + $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/git/refs/heads'; $branchData = JsonFile::parseJson($this->getContents($resource), $resource); $this->branches = array(); foreach ($branchData as $branch) { @@ -362,8 +372,7 @@ class GitHubDriver extends VcsDriver */ protected function fetchRootIdentifier() { - $apiUrl = ('github.com' === $this->originUrl) ? 'api.github.com' : $this->originUrl . '/api/v3'; - $repoDataUrl = 'https://' . $apiUrl . '/repos/'.$this->owner.'/'.$this->repository; + $repoDataUrl = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository; $repoData = JsonFile::parseJson($this->getContents($repoDataUrl, true), $repoDataUrl); if (null === $repoData && null !== $this->gitDriver) { From 93ebfd54b13e3d2cedd55f3a767721e1fb60517f Mon Sep 17 00:00:00 2001 From: Gennady Feldman Date: Mon, 28 Oct 2013 15:57:02 -0400 Subject: [PATCH 170/238] Adding Config as parameter to the Driver::supports(), updating all drivers, user and tests. --- src/Composer/Repository/Vcs/GitBitbucketDriver.php | 3 ++- src/Composer/Repository/Vcs/GitDriver.php | 3 ++- src/Composer/Repository/Vcs/GitHubDriver.php | 10 ++++++++-- src/Composer/Repository/Vcs/HgBitbucketDriver.php | 3 ++- src/Composer/Repository/Vcs/HgDriver.php | 3 ++- src/Composer/Repository/Vcs/PerforceDriver.php | 3 ++- src/Composer/Repository/Vcs/SvnDriver.php | 3 ++- src/Composer/Repository/Vcs/VcsDriverInterface.php | 10 ++++++---- src/Composer/Repository/VcsRepository.php | 4 ++-- .../Test/Repository/Vcs/PerforceDriverTest.php | 9 ++++----- tests/Composer/Test/Repository/Vcs/SvnDriverTest.php | 8 +++----- 11 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/Composer/Repository/Vcs/GitBitbucketDriver.php b/src/Composer/Repository/Vcs/GitBitbucketDriver.php index 950115a79..c9a3c2fdf 100644 --- a/src/Composer/Repository/Vcs/GitBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/GitBitbucketDriver.php @@ -12,6 +12,7 @@ namespace Composer\Repository\Vcs; +use Composer\Config; use Composer\Json\JsonFile; use Composer\IO\IOInterface; @@ -140,7 +141,7 @@ class GitBitbucketDriver extends VcsDriver implements VcsDriverInterface /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, $deep = false) + public static function supports(IOInterface $io, $url, Config $config, $deep = false) { if (!preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)\.git$#', $url)) { return false; diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index e2a3a9eb0..2bcb79e23 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -18,6 +18,7 @@ use Composer\Util\Filesystem; use Composer\Util\Git as GitUtil; use Composer\IO\IOInterface; use Composer\Cache; +use Composer\Config; /** * @author Jordi Boggiano @@ -211,7 +212,7 @@ class GitDriver extends VcsDriver /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, $deep = false) + public static function supports(IOInterface $io, $url, Config $config, $deep = false) { if (preg_match('#(^git://|\.git$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) { return true; diff --git a/src/Composer/Repository/Vcs/GitHubDriver.php b/src/Composer/Repository/Vcs/GitHubDriver.php index f84eb74ca..e84c1d012 100644 --- a/src/Composer/Repository/Vcs/GitHubDriver.php +++ b/src/Composer/Repository/Vcs/GitHubDriver.php @@ -12,6 +12,7 @@ namespace Composer\Repository\Vcs; +use Composer\Config; use Composer\Downloader\TransportException; use Composer\Json\JsonFile; use Composer\Cache; @@ -231,9 +232,14 @@ class GitHubDriver extends VcsDriver /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, $deep = false) + public static function supports(IOInterface $io, $url, Config $config, $deep = false) { - if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git)?$#', $url)) { + if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git)?$#', $url, $matches)) { + return false; + } + + $originUrl = isset($matches[2]) ? $matches[2] : $matches[3]; + if (!in_array($originUrl, $config->get('github-domains'))) { return false; } diff --git a/src/Composer/Repository/Vcs/HgBitbucketDriver.php b/src/Composer/Repository/Vcs/HgBitbucketDriver.php index 80683a465..9c403e71d 100644 --- a/src/Composer/Repository/Vcs/HgBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/HgBitbucketDriver.php @@ -12,6 +12,7 @@ namespace Composer\Repository\Vcs; +use Composer\Config; use Composer\Json\JsonFile; use Composer\IO\IOInterface; @@ -150,7 +151,7 @@ class HgBitbucketDriver extends VcsDriver /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, $deep = false) + public static function supports(IOInterface $io, $url, Config $config, $deep = false) { if (!preg_match('#^https://bitbucket\.org/([^/]+)/([^/]+)/?$#', $url)) { return false; diff --git a/src/Composer/Repository/Vcs/HgDriver.php b/src/Composer/Repository/Vcs/HgDriver.php index c3c06e38a..abfd0de51 100644 --- a/src/Composer/Repository/Vcs/HgDriver.php +++ b/src/Composer/Repository/Vcs/HgDriver.php @@ -12,6 +12,7 @@ namespace Composer\Repository\Vcs; +use Composer\Config; use Composer\Json\JsonFile; use Composer\Util\ProcessExecutor; use Composer\Util\Filesystem; @@ -189,7 +190,7 @@ class HgDriver extends VcsDriver /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, $deep = false) + public static function supports(IOInterface $io, $url, Config $config, $deep = false) { if (preg_match('#(^(?:https?|ssh)://(?:[^@]@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) { return true; diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 54e1d3e7d..6ff51125a 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -12,6 +12,7 @@ namespace Composer\Repository\Vcs; +use Composer\Config; use Composer\IO\IOInterface; use Composer\Util\ProcessExecutor; use Composer\Util\Perforce; @@ -158,7 +159,7 @@ class PerforceDriver extends VcsDriver /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, $deep = false) + public static function supports(IOInterface $io, $url, Config $config, $deep = false) { if ($deep || preg_match('#\b(perforce|p4)\b#i', $url)) { return Perforce::checkServerExists($url, new ProcessExecutor); diff --git a/src/Composer/Repository/Vcs/SvnDriver.php b/src/Composer/Repository/Vcs/SvnDriver.php index c5a67b455..a2e345b07 100644 --- a/src/Composer/Repository/Vcs/SvnDriver.php +++ b/src/Composer/Repository/Vcs/SvnDriver.php @@ -13,6 +13,7 @@ namespace Composer\Repository\Vcs; use Composer\Cache; +use Composer\Config; use Composer\Json\JsonFile; use Composer\Util\ProcessExecutor; use Composer\Util\Filesystem; @@ -241,7 +242,7 @@ class SvnDriver extends VcsDriver /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, $deep = false) + public static function supports(IOInterface $io, $url, Config $config, $deep = false) { $url = self::normalizeUrl($url); if (preg_match('#(^svn://|^svn\+ssh://|svn\.)#i', $url)) { diff --git a/src/Composer/Repository/Vcs/VcsDriverInterface.php b/src/Composer/Repository/Vcs/VcsDriverInterface.php index b29841b68..741cf1dda 100644 --- a/src/Composer/Repository/Vcs/VcsDriverInterface.php +++ b/src/Composer/Repository/Vcs/VcsDriverInterface.php @@ -12,6 +12,7 @@ namespace Composer\Repository\Vcs; +use Composer\Config; use Composer\IO\IOInterface; /** @@ -90,10 +91,11 @@ interface VcsDriverInterface /** * Checks if this driver can handle a given url * - * @param IOInterface $io IO instance - * @param string $url - * @param bool $deep unless true, only shallow checks (url matching typically) should be done + * @param IOInterface $io IO instance + * @param string $url URL to validate/check + * @param Config $config current $config + * @param bool $deep unless true, only shallow checks (url matching typically) should be done * @return bool */ - public static function supports(IOInterface $io, $url, $deep = false); + public static function supports(IOInterface $io, $url, Config $config, $deep = false); } diff --git a/src/Composer/Repository/VcsRepository.php b/src/Composer/Repository/VcsRepository.php index 701db33bb..a18328725 100644 --- a/src/Composer/Repository/VcsRepository.php +++ b/src/Composer/Repository/VcsRepository.php @@ -80,7 +80,7 @@ class VcsRepository extends ArrayRepository } foreach ($this->drivers as $driver) { - if ($driver::supports($this->io, $this->url)) { + if ($driver::supports($this->io, $this->url, $this->config)) { $driver = new $driver($this->repoConfig, $this->io, $this->config); $driver->initialize(); @@ -89,7 +89,7 @@ class VcsRepository extends ArrayRepository } foreach ($this->drivers as $driver) { - if ($driver::supports($this->io, $this->url, true)) { + if ($driver::supports($this->io, $this->url, $this->config, true)) { $driver = new $driver($this->repoConfig, $this->io, $this->config); $driver->initialize(); diff --git a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php index d2c8167b9..ba418b2a2 100644 --- a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php @@ -104,7 +104,6 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase public function testHasComposerFile() { - $this->setUp(); $repoConfig = array( 'url' => 'TEST_PERFORCE_URL', 'depot' => 'TEST_DEPOT_CONFIG', @@ -131,17 +130,17 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase $result = $driver->hasComposerFile($identifier); $this->assertTrue($result); } - + /** * Test that supports() simply return false. - * + * * @covers \Composer\Repository\Vcs\PerforceDriver::supports - * + * * @return void */ public function testSupportsReturnsFalseNoDeepCheck() { $this->expectOutputString(''); - $this->assertFalse(PerforceDriver::supports($this->io, 'existing.url')); + $this->assertFalse(PerforceDriver::supports($this->io, 'existing.url', $this->config)); } } diff --git a/tests/Composer/Test/Repository/Vcs/SvnDriverTest.php b/tests/Composer/Test/Repository/Vcs/SvnDriverTest.php index d9bd53321..1b4437a04 100644 --- a/tests/Composer/Test/Repository/Vcs/SvnDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/SvnDriverTest.php @@ -80,10 +80,8 @@ class SvnDriverTest extends \PHPUnit_Framework_TestCase */ public function testSupport($url, $assertion) { - if ($assertion === true) { - $this->assertTrue(SvnDriver::supports($this->getMock('Composer\IO\IOInterface'), $url)); - } else { - $this->assertFalse(SvnDriver::supports($this->getMock('Composer\IO\IOInterface'), $url)); - } + $config = new Config(); + $result = SvnDriver::supports($this->getMock('Composer\IO\IOInterface'), $url, $config); + $this->assertEquals($assertion, $result); } } From c14e27747675df65908d62a036e966c14fc1b737 Mon Sep 17 00:00:00 2001 From: Elliott Peay Date: Mon, 28 Oct 2013 17:28:26 -0400 Subject: [PATCH 171/238] Update 05-repositories.md Typo, which is best addressed as a small rewrite. --- doc/05-repositories.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/05-repositories.md b/doc/05-repositories.md index 94773f35a..ae947ea49 100644 --- a/doc/05-repositories.md +++ b/doc/05-repositories.md @@ -463,8 +463,8 @@ there are some use cases for hosting your own repository. might want to keep them separate to packagist. An example of this would be wordpress plugins. -When hosting your own package repository it is recommended to use a `composer` -one. This is type that is native to composer and yields the best performance. +For hosting your own packages, a native `composer` type of repository is +recommended, which provides the best performance. There are a few tools that can help you create a `composer` repository. From e5045ce2152c77fefd54f1e3c0c88dcb33af1e02 Mon Sep 17 00:00:00 2001 From: Gennady Feldman Date: Tue, 29 Oct 2013 11:00:00 -0400 Subject: [PATCH 172/238] Per request from Jordi Boggiano (Seldaek) making Config 2nd parameter in supports() --- src/Composer/Repository/Vcs/GitBitbucketDriver.php | 2 +- src/Composer/Repository/Vcs/GitDriver.php | 2 +- src/Composer/Repository/Vcs/GitHubDriver.php | 2 +- src/Composer/Repository/Vcs/HgBitbucketDriver.php | 2 +- src/Composer/Repository/Vcs/HgDriver.php | 2 +- src/Composer/Repository/Vcs/PerforceDriver.php | 2 +- src/Composer/Repository/Vcs/SvnDriver.php | 2 +- src/Composer/Repository/Vcs/VcsDriverInterface.php | 4 ++-- src/Composer/Repository/VcsRepository.php | 4 ++-- tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php | 2 +- tests/Composer/Test/Repository/Vcs/SvnDriverTest.php | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Composer/Repository/Vcs/GitBitbucketDriver.php b/src/Composer/Repository/Vcs/GitBitbucketDriver.php index c9a3c2fdf..12eba6d3a 100644 --- a/src/Composer/Repository/Vcs/GitBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/GitBitbucketDriver.php @@ -141,7 +141,7 @@ class GitBitbucketDriver extends VcsDriver implements VcsDriverInterface /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, Config $config, $deep = false) + public static function supports(IOInterface $io, Config $config, $url, $deep = false) { if (!preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)\.git$#', $url)) { return false; diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index 2bcb79e23..ecfad77db 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -212,7 +212,7 @@ class GitDriver extends VcsDriver /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, Config $config, $deep = false) + public static function supports(IOInterface $io, Config $config, $url, $deep = false) { if (preg_match('#(^git://|\.git$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) { return true; diff --git a/src/Composer/Repository/Vcs/GitHubDriver.php b/src/Composer/Repository/Vcs/GitHubDriver.php index e84c1d012..428c2fdf4 100644 --- a/src/Composer/Repository/Vcs/GitHubDriver.php +++ b/src/Composer/Repository/Vcs/GitHubDriver.php @@ -232,7 +232,7 @@ class GitHubDriver extends VcsDriver /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, Config $config, $deep = false) + public static function supports(IOInterface $io, Config $config, $url, $deep = false) { if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git)?$#', $url, $matches)) { return false; diff --git a/src/Composer/Repository/Vcs/HgBitbucketDriver.php b/src/Composer/Repository/Vcs/HgBitbucketDriver.php index 9c403e71d..c6eac73b9 100644 --- a/src/Composer/Repository/Vcs/HgBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/HgBitbucketDriver.php @@ -151,7 +151,7 @@ class HgBitbucketDriver extends VcsDriver /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, Config $config, $deep = false) + public static function supports(IOInterface $io, Config $config, $url, $deep = false) { if (!preg_match('#^https://bitbucket\.org/([^/]+)/([^/]+)/?$#', $url)) { return false; diff --git a/src/Composer/Repository/Vcs/HgDriver.php b/src/Composer/Repository/Vcs/HgDriver.php index abfd0de51..5de081cca 100644 --- a/src/Composer/Repository/Vcs/HgDriver.php +++ b/src/Composer/Repository/Vcs/HgDriver.php @@ -190,7 +190,7 @@ class HgDriver extends VcsDriver /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, Config $config, $deep = false) + public static function supports(IOInterface $io, Config $config, $url, $deep = false) { if (preg_match('#(^(?:https?|ssh)://(?:[^@]@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) { return true; diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 6ff51125a..484f1e96f 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -159,7 +159,7 @@ class PerforceDriver extends VcsDriver /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, Config $config, $deep = false) + public static function supports(IOInterface $io, Config $config, $url, $deep = false) { if ($deep || preg_match('#\b(perforce|p4)\b#i', $url)) { return Perforce::checkServerExists($url, new ProcessExecutor); diff --git a/src/Composer/Repository/Vcs/SvnDriver.php b/src/Composer/Repository/Vcs/SvnDriver.php index a2e345b07..d69230cce 100644 --- a/src/Composer/Repository/Vcs/SvnDriver.php +++ b/src/Composer/Repository/Vcs/SvnDriver.php @@ -242,7 +242,7 @@ class SvnDriver extends VcsDriver /** * {@inheritDoc} */ - public static function supports(IOInterface $io, $url, Config $config, $deep = false) + public static function supports(IOInterface $io, Config $config, $url, $deep = false) { $url = self::normalizeUrl($url); if (preg_match('#(^svn://|^svn\+ssh://|svn\.)#i', $url)) { diff --git a/src/Composer/Repository/Vcs/VcsDriverInterface.php b/src/Composer/Repository/Vcs/VcsDriverInterface.php index 741cf1dda..dd30baacd 100644 --- a/src/Composer/Repository/Vcs/VcsDriverInterface.php +++ b/src/Composer/Repository/Vcs/VcsDriverInterface.php @@ -92,10 +92,10 @@ interface VcsDriverInterface * Checks if this driver can handle a given url * * @param IOInterface $io IO instance - * @param string $url URL to validate/check * @param Config $config current $config + * @param string $url URL to validate/check * @param bool $deep unless true, only shallow checks (url matching typically) should be done * @return bool */ - public static function supports(IOInterface $io, $url, Config $config, $deep = false); + public static function supports(IOInterface $io, Config $config, $url, $deep = false); } diff --git a/src/Composer/Repository/VcsRepository.php b/src/Composer/Repository/VcsRepository.php index a18328725..c7a543748 100644 --- a/src/Composer/Repository/VcsRepository.php +++ b/src/Composer/Repository/VcsRepository.php @@ -80,7 +80,7 @@ class VcsRepository extends ArrayRepository } foreach ($this->drivers as $driver) { - if ($driver::supports($this->io, $this->url, $this->config)) { + if ($driver::supports($this->io, $this->config, $this->url)) { $driver = new $driver($this->repoConfig, $this->io, $this->config); $driver->initialize(); @@ -89,7 +89,7 @@ class VcsRepository extends ArrayRepository } foreach ($this->drivers as $driver) { - if ($driver::supports($this->io, $this->url, $this->config, true)) { + if ($driver::supports($this->io, $this->config, $this->url, true)) { $driver = new $driver($this->repoConfig, $this->io, $this->config); $driver->initialize(); diff --git a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php index ba418b2a2..36cd69ebc 100644 --- a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php @@ -141,6 +141,6 @@ class PerforceDriverTest extends \PHPUnit_Framework_TestCase public function testSupportsReturnsFalseNoDeepCheck() { $this->expectOutputString(''); - $this->assertFalse(PerforceDriver::supports($this->io, 'existing.url', $this->config)); + $this->assertFalse(PerforceDriver::supports($this->io, $this->config, 'existing.url')); } } diff --git a/tests/Composer/Test/Repository/Vcs/SvnDriverTest.php b/tests/Composer/Test/Repository/Vcs/SvnDriverTest.php index 1b4437a04..2f698565f 100644 --- a/tests/Composer/Test/Repository/Vcs/SvnDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/SvnDriverTest.php @@ -81,7 +81,7 @@ class SvnDriverTest extends \PHPUnit_Framework_TestCase public function testSupport($url, $assertion) { $config = new Config(); - $result = SvnDriver::supports($this->getMock('Composer\IO\IOInterface'), $url, $config); + $result = SvnDriver::supports($this->getMock('Composer\IO\IOInterface'), $config, $url); $this->assertEquals($assertion, $result); } } From f538acc4b06b06ac2309c26b196e1941c4d30766 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Wed, 30 Oct 2013 17:46:35 +0100 Subject: [PATCH 173/238] added support for file:// url to repository file:// is valid url even if it does not define a host. allows to define a repo like this (local directory generated with composer/satis): ```json { "repositories": [ { "type": "composer", "url": "file:///home/cebe/dev/jescali/xeno-core/core/repo" } ], "require": { ... } } ``` --- src/Composer/Repository/ComposerRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 5eab777a4..47b4b94d7 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -63,7 +63,7 @@ class ComposerRepository extends ArrayRepository implements StreamableRepository } $urlBits = parse_url($repoConfig['url']); - if (empty($urlBits['scheme']) || empty($urlBits['host'])) { + if ($urlBits === false || empty($urlBits['scheme'])) { throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']); } From 30502f1cb4963e6bd2e9b71761c6e41f39174e02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Ma=C5=82olepszy?= Date: Wed, 30 Oct 2013 22:03:14 +0100 Subject: [PATCH 174/238] changes size of the line default value --- src/Composer/IO/IOInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/IO/IOInterface.php b/src/Composer/IO/IOInterface.php index b17da6128..f117ce974 100644 --- a/src/Composer/IO/IOInterface.php +++ b/src/Composer/IO/IOInterface.php @@ -71,7 +71,7 @@ interface IOInterface * @param bool $newline Whether to add a newline or not * @param integer $size The size of line */ - public function overwrite($messages, $newline = true, $size = 80); + public function overwrite($messages, $newline = true, $size = null); /** * Asks a question to the user. From 0a3df27403f0b184df5e2633583cb14af93f3b4c Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 31 Oct 2013 22:29:09 +0100 Subject: [PATCH 175/238] Remove dead code, fixes #2363 --- src/Composer/DependencyResolver/Solver.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index f65f6e0e2..0fc860c72 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -756,7 +756,6 @@ class Solver if ($lastLiteral) { unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]); - array_values($this->branches[$lastBranchIndex][self::BRANCH_LITERALS]); $level = $lastLevel; $this->revert($level); From 8398c9f2ab6a5998d90ebc7d6baceab8009c2b60 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 4 Nov 2013 13:36:30 +0100 Subject: [PATCH 176/238] Fix target-dir update checks, fixes #2395 --- src/Composer/Installer/LibraryInstaller.php | 6 ++++-- tests/Composer/Test/Installer/LibraryInstallerTest.php | 7 ++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index aab3f4737..b1677cec2 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -160,9 +160,11 @@ class LibraryInstaller implements InstallerInterface $initialDownloadPath = $this->getInstallPath($initial); $targetDownloadPath = $this->getInstallPath($target); if ($targetDownloadPath !== $initialDownloadPath) { - // if the target is part of the initial dir, we force a remove + install + // if the target and initial dirs intersect, we force a remove + install // to avoid the rename wiping the target dir as part of the initial dir cleanup - if (strpos($initialDownloadPath, $targetDownloadPath) === 0) { + if (substr($initialDownloadPath, 0, strlen($targetDownloadPath)) === $targetDownloadPath + || substr($targetDownloadPath, 0, strlen($initialDownloadPath)) === $initialDownloadPath + ) { $this->removeCode($initial); $this->installCode($target); diff --git a/tests/Composer/Test/Installer/LibraryInstallerTest.php b/tests/Composer/Test/Installer/LibraryInstallerTest.php index 56e7e7415..6230752e5 100644 --- a/tests/Composer/Test/Installer/LibraryInstallerTest.php +++ b/tests/Composer/Test/Installer/LibraryInstallerTest.php @@ -136,7 +136,7 @@ class LibraryInstallerTest extends TestCase $filesystem ->expects($this->once()) ->method('rename') - ->with($this->vendorDir.'/package1', $this->vendorDir.'/package1/newtarget'); + ->with($this->vendorDir.'/package1/oldtarget', $this->vendorDir.'/package1/newtarget'); $initial = $this->createPackageMock(); $target = $this->createPackageMock(); @@ -146,6 +146,11 @@ class LibraryInstallerTest extends TestCase ->method('getPrettyName') ->will($this->returnValue('package1')); + $initial + ->expects($this->once()) + ->method('getTargetDir') + ->will($this->returnValue('oldtarget')); + $target ->expects($this->once()) ->method('getPrettyName') From 0959d8f1346865d4337744244679b8f9870bfbc0 Mon Sep 17 00:00:00 2001 From: smaftoul Date: Mon, 4 Nov 2013 15:14:20 +0100 Subject: [PATCH 177/238] Retry on some 5xx errors `composer install` gives me some intermittent 502 errors on github. Composer already does some retries. I think, on 502, 503 and 504, we should retry. --- src/Composer/Downloader/FileDownloader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index 6581b6ca7..c78e65a31 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -120,7 +120,7 @@ class FileDownloader implements DownloaderInterface break; } catch (TransportException $e) { // if we got an http response with a proper code, then requesting again will probably not help, abort - if ((0 !== $e->getCode() && 500 !== $e->getCode()) || !$retries) { + if ((0 !== $e->getCode() && !in_array($e->getCode(),array(500, 502, 503, 504))) || !$retries) { throw $e; } if ($this->io->isVerbose()) { From 97d52968ab6fcac2d6b4fbb5818f77fe0232c502 Mon Sep 17 00:00:00 2001 From: Wouter Wolters Date: Tue, 5 Nov 2013 18:57:29 +0100 Subject: [PATCH 178/238] Fix authentication issue with subversion 1.8 --- src/Composer/Util/Svn.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Composer/Util/Svn.php b/src/Composer/Util/Svn.php index bcc3bb155..510b45daa 100644 --- a/src/Composer/Util/Svn.php +++ b/src/Composer/Util/Svn.php @@ -112,7 +112,8 @@ class Svn // the error is not auth-related if (false === stripos($output, 'Could not authenticate to server:') && false === stripos($output, 'authorization failed') - && false === stripos($output, 'svn: E170001:')) { + && false === stripos($output, 'svn: E170001:') + && false === stripos($output, 'svn: E215004:')) { throw new \RuntimeException($output); } From d348dd44cda85dee2da36d620240674c35bd3a10 Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Wed, 6 Nov 2013 21:31:26 +0000 Subject: [PATCH 179/238] Fix URL sanitisation regexp being too greedy --- src/Composer/Downloader/GitDownloader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index 56b55629e..322d3f883 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -384,7 +384,7 @@ class GitDownloader extends VcsDownloader protected function sanitizeUrl($message) { - return preg_replace('{://(.+?):.+?@}', '://$1:***@', $message); + return preg_replace('{://([^@]+?):.+?@}', '://$1:***@', $message); } protected function setPushUrl(PackageInterface $package, $path) From a892e6a3bde9c5403b17c7f169bf9804153dc890 Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Wed, 6 Nov 2013 21:37:20 +0000 Subject: [PATCH 180/238] Pass IO instance to ProcessExecutor for logging --- src/Composer/Repository/Vcs/PerforceDriver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 484f1e96f..79500f1d6 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -162,7 +162,7 @@ class PerforceDriver extends VcsDriver public static function supports(IOInterface $io, Config $config, $url, $deep = false) { if ($deep || preg_match('#\b(perforce|p4)\b#i', $url)) { - return Perforce::checkServerExists($url, new ProcessExecutor); + return Perforce::checkServerExists($url, new ProcessExecutor($io)); } return false; From c0316aa9571f3c58edc59eea628ad6ee0e813d97 Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Wed, 6 Nov 2013 21:37:38 +0000 Subject: [PATCH 181/238] Capture output, stopping errors showing up if p4 is not available --- src/Composer/Util/Perforce.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index ecaf3a720..cf663be10 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -372,7 +372,9 @@ class Perforce public static function checkServerExists($url, ProcessExecutor $processExecutor) { - return 0 === $processExecutor->execute('p4 -p ' . $url . ' info -s'); + $output = null; + + return 0 === $processExecutor->execute('p4 -p ' . $url . ' info -s', $output); } public function getComposerInformation($identifier) From fc4cc79a525fa7e36089625c35a727b4957cd3bf Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Thu, 7 Nov 2013 23:33:38 +0100 Subject: [PATCH 182/238] Fix cache directory upgrading - do not try to remove the destination directory. --- src/Composer/Factory.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 99b5a692b..38949c7b6 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -118,7 +118,9 @@ class Factory @rename($child, $dir.'/'.basename($child)); } } - @rmdir($oldPath); + if ($config->get('cache-dir') != $oldPath) { + @rmdir($oldPath); + } } } } From 36712386f9c1b6802a9e84286736e408c8b4bb44 Mon Sep 17 00:00:00 2001 From: Thomas Szteliga Date: Fri, 8 Nov 2013 08:17:11 +0100 Subject: [PATCH 183/238] Composer supports four types. --- doc/04-schema.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/04-schema.md b/doc/04-schema.md index c4de65150..e35803ac2 100644 --- a/doc/04-schema.md +++ b/doc/04-schema.md @@ -86,7 +86,7 @@ that needs some special logic, you can define a custom type. This could be a all be specific to certain projects, and they will need to provide an installer capable of installing packages of that type. -Out of the box, composer supports three types: +Out of the box, composer supports four types: - **library:** This is the default. It will simply copy the files to `vendor`. - **project:** This denotes a project rather than a library. For example From f134e09f458f99e13629331b95c6831070173c9a Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 11 Nov 2013 14:41:21 +0100 Subject: [PATCH 184/238] Add stronger warning in docs about # hack, refs #2410 --- doc/04-schema.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/doc/04-schema.md b/doc/04-schema.md index e35803ac2..299d418d5 100644 --- a/doc/04-schema.md +++ b/doc/04-schema.md @@ -289,10 +289,7 @@ Example: `require` and `require-dev` additionally support explicit references (i.e. commit) for dev versions to make sure they are locked to a given state, even when you run update. These only work if you explicitly require a dev version -and append the reference with `#`. Note that while this is convenient at -times, it should not really be how you use packages in the long term. You -should always try to switch to tagged releases as soon as you can, especially -if the project you work on will not be touched for a while. +and append the reference with `#`. Example: @@ -303,8 +300,15 @@ Example: } } -It is possible to inline-alias a package constraint so that it matches a -constraint that it otherwise would not. For more information [see the +> **Note:** While this is convenient at times, it should not be how you use +> packages in the long term because it comes with a technical limitation. The +> composer.json metadata will still be read from the branch name you specify +> before the hash. Because of that in some cases it will not be a practical +> workaround, and you should always try to switch to tagged releases as soon +> as you can. + +It is also possible to inline-alias a package constraint so that it matches +a constraint that it otherwise would not. For more information [see the aliases article](articles/aliases.md). #### require From fcba5257d9ee46c374eb8e51db5d115da88783bd Mon Sep 17 00:00:00 2001 From: Matthieu Auger Date: Mon, 11 Nov 2013 17:43:11 +0100 Subject: [PATCH 185/238] If installer sets prefer option to false, the manager should too. Fixes #2359 --- src/Composer/Installer.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 4c04a7eec..30766bb70 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -171,12 +171,8 @@ class Installer unset($devRepo, $package); // end BC - if ($this->preferSource) { - $this->downloadManager->setPreferSource(true); - } - if ($this->preferDist) { - $this->downloadManager->setPreferDist(true); - } + $this->downloadManager->setPreferSource($this->preferSource); + $this->downloadManager->setPreferDist($this->preferDist); // clone root package to have one in the installed repo that does not require anything // we don't want it to be uninstallable, but its requirements should not conflict From b92bce5569d894cc0e57bb8900032858dbece389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Wed, 13 Nov 2013 09:15:08 +0200 Subject: [PATCH 186/238] Minor typo fix introduced from 6ce0bf7cbf5edc622a8ccfbca226ffc825ca699e with #2314 --- doc/04-schema.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/04-schema.md b/doc/04-schema.md index 299d418d5..3a250a418 100644 --- a/doc/04-schema.md +++ b/doc/04-schema.md @@ -657,7 +657,7 @@ The following options are supported: is periodically ran, this is the maximum size the cache will be able to use. Older (less used) files will be removed first until the cache fits. * **prepend-autoloader:** Defaults to `true`. If false, the composer autoloader - will not be prepended to existing autoloaders. This is sometimesrequired to fix + will not be prepended to existing autoloaders. This is sometimes required to fix interoperability issues with other autoloaders. * **github-domains:** Defaults to `["github.com"]`. A list of domains to use in github mode. This is used for GitHub Enterprise setups. From 847b33da44bb9032363db257d4e747b013977695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Wed, 13 Nov 2013 22:41:44 +0200 Subject: [PATCH 187/238] drop ^A added probably mistakenly in e34dae4d42a2bbe2ed9eb581f371ae3b00b8c4e2 --- doc/articles/aliases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/articles/aliases.md b/doc/articles/aliases.md index 9d0cbd44b..26a9c46ab 100644 --- a/doc/articles/aliases.md +++ b/doc/articles/aliases.md @@ -65,7 +65,7 @@ local project. You are using `symfony/monolog-bundle` which requires `monolog/monolog` version `1.*`. So you need your `dev-bugfix` to match that constraint. - + Just add this to your project's root `composer.json`: { From dff5e3c54296e2ccc3d403cec9f31ecd2aafca9f Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 14 Nov 2013 21:21:08 +0100 Subject: [PATCH 188/238] Fail hard if anything attempts to wipe the entire filesystem/partition, fixes #2409 --- src/Composer/Util/Filesystem.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index 2e18eb71e..8771776fc 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -69,6 +69,10 @@ class Filesystem return true; } + if (preg_match('{^(?:[a-z]:)?[/\\\\]+$}i', $directory)) { + throw new \RuntimeException('Aborting an attempted deletion of '.$directory.', this was probably not intended, if it is a real use case please report it.'); + } + if (!function_exists('proc_open')) { return $this->removeDirectoryPhp($directory); } From f626f55f410085582884e91b3eb33ebfe74290ae Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Fri, 15 Nov 2013 13:05:04 +0100 Subject: [PATCH 189/238] No need to create hg working copies just to parse tags/branches --- src/Composer/Repository/Vcs/HgDriver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Composer/Repository/Vcs/HgDriver.php b/src/Composer/Repository/Vcs/HgDriver.php index 5de081cca..060a77e45 100644 --- a/src/Composer/Repository/Vcs/HgDriver.php +++ b/src/Composer/Repository/Vcs/HgDriver.php @@ -49,14 +49,14 @@ class HgDriver extends VcsDriver // update the repo if it is a valid hg repository if (is_dir($this->repoDir) && 0 === $this->process->execute('hg summary', $output, $this->repoDir)) { - if (0 !== $this->process->execute('hg pull -u', $output, $this->repoDir)) { + if (0 !== $this->process->execute('hg pull', $output, $this->repoDir)) { $this->io->write('Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')'); } } else { // clean up directory and do a fresh clone into it $fs->removeDirectory($this->repoDir); - if (0 !== $this->process->execute(sprintf('hg clone %s %s', escapeshellarg($this->url), escapeshellarg($this->repoDir)), $output, $cacheDir)) { + if (0 !== $this->process->execute(sprintf('hg clone --noupdate %s %s', escapeshellarg($this->url), escapeshellarg($this->repoDir)), $output, $cacheDir)) { $output = $this->process->getErrorOutput(); if (0 !== $this->process->execute('hg --version', $ignoredOutput)) { From 9477e015bd89f02a007a42761b97c2c11b2078e1 Mon Sep 17 00:00:00 2001 From: Dimitrios Kanellopoulos Date: Sat, 16 Nov 2013 14:13:33 +0100 Subject: [PATCH 190/238] Use cache directory when downloading composer.phar Since there is a cache dir there is no need to populate the project directory with temp files. Plus the permissions on the project dir might not allow that. --- src/Composer/Command/SelfUpdateCommand.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index d37598b04..86ecf1a8a 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -13,6 +13,7 @@ namespace Composer\Command; use Composer\Composer; +use Composer\Factory; use Composer\Util\RemoteFilesystem; use Composer\Downloader\FilesystemException; use Symfony\Component\Console\Input\InputInterface; @@ -42,8 +43,11 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { + $config = Factory::createConfig(); + $cacheDir = $config->get('cache-dir'); + $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0]; - $tempFilename = dirname($localFilename) . '/' . basename($localFilename, '.phar').'-temp.phar'; + $tempFilename = $cacheDir . basename($localFilename, '.phar').'-temp.phar'; // check for permissions in local filesystem before start connection process if (!is_writable($tempDirectory = dirname($tempFilename))) { From 95a9ac880b88e4a25cf7b323d885734ed26a4b8a Mon Sep 17 00:00:00 2001 From: Dimitrios Kanellopoulos Date: Sat, 16 Nov 2013 18:52:44 +0100 Subject: [PATCH 191/238] Check if current dir is writable and if not try the cache dir from settings --- src/Composer/Command/SelfUpdateCommand.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index 86ecf1a8a..e8c373197 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -47,11 +47,14 @@ EOT $cacheDir = $config->get('cache-dir'); $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0]; - $tempFilename = $cacheDir . basename($localFilename, '.phar').'-temp.phar'; + + // Check if current dir is writable and if not try the cache dir from settings + $tmpDir = is_writable(dirname($localFilename))? dirname($localFilename) . '/' : $cacheDir; + $tempFilename = $tmpDir . basename($localFilename, '.phar').'-temp.phar'; // check for permissions in local filesystem before start connection process - if (!is_writable($tempDirectory = dirname($tempFilename))) { - throw new FilesystemException('Composer update failed: the "'.$tempDirectory.'" directory used to download the temp file could not be written'); + if (!is_writable($tmpDir)) { + throw new FilesystemException('Composer update failed: the "'.$tmpDir.'" directory used to download the temp file could not be written'); } if (!is_writable($localFilename)) { From 81820beefc32428a6904d6a8703fc0ef881629cd Mon Sep 17 00:00:00 2001 From: Dimitrios Kanellopoulos Date: Sat, 16 Nov 2013 19:34:06 +0100 Subject: [PATCH 192/238] Cache path never ends with '/' --- src/Composer/Command/SelfUpdateCommand.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index e8c373197..4074d8bad 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -49,8 +49,8 @@ EOT $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0]; // Check if current dir is writable and if not try the cache dir from settings - $tmpDir = is_writable(dirname($localFilename))? dirname($localFilename) . '/' : $cacheDir; - $tempFilename = $tmpDir . basename($localFilename, '.phar').'-temp.phar'; + $tmpDir = is_writable(dirname($localFilename))? dirname($localFilename) : $cacheDir; + $tempFilename = $tmpDir . '/' . basename($localFilename, '.phar').'-temp.phar'; // check for permissions in local filesystem before start connection process if (!is_writable($tmpDir)) { From fbadc19bf6b68cca0ba37d88bb096c4da4543b11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20JOURDIN?= Date: Tue, 19 Nov 2013 17:45:28 +0100 Subject: [PATCH 193/238] Add preFileDownload event on package.json fetch --- src/Composer/Factory.php | 20 ++++++++++--------- .../Repository/ComposerRepository.php | 13 ++++++++++-- src/Composer/Repository/RepositoryManager.php | 7 +++++-- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 38949c7b6..1db8c5864 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -220,8 +220,15 @@ class Factory // setup process timeout ProcessExecutor::setTimeout((int) $config->get('process-timeout')); + // initialize composer + $composer = new Composer(); + $composer->setConfig($config); + + // initialize event dispatcher + $dispatcher = new EventDispatcher($composer, $io); + // initialize repository manager - $rm = $this->createRepositoryManager($io, $config); + $rm = $this->createRepositoryManager($io, $config, $dispatcher); // load local repository $this->addLocalRepository($rm, $vendorDir); @@ -234,16 +241,11 @@ class Factory // initialize installation manager $im = $this->createInstallationManager(); - // initialize composer - $composer = new Composer(); - $composer->setConfig($config); + // Composer composition $composer->setPackage($package); $composer->setRepositoryManager($rm); $composer->setInstallationManager($im); - // initialize event dispatcher - $dispatcher = new EventDispatcher($composer, $io); - // initialize download manager $dm = $this->createDownloadManager($io, $config, $dispatcher); @@ -285,9 +287,9 @@ class Factory * @param Config $config * @return Repository\RepositoryManager */ - protected function createRepositoryManager(IOInterface $io, Config $config) + protected function createRepositoryManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null) { - $rm = new RepositoryManager($io, $config); + $rm = new RepositoryManager($io, $config, $eventDispatcher); $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository'); $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository'); $rm->setRepositoryClass('package', 'Composer\Repository\PackageRepository'); diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 47b4b94d7..1d686cae1 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -22,6 +22,9 @@ use Composer\Cache; use Composer\Config; use Composer\IO\IOInterface; use Composer\Util\RemoteFilesystem; +use Composer\Plugin\PluginEvents; +use Composer\Plugin\PreFileDownloadEvent; +use Composer\EventDispatcher\EventDispatcher; /** * @author Jordi Boggiano @@ -45,12 +48,13 @@ class ComposerRepository extends ArrayRepository implements StreamableRepository protected $loader; protected $rootAliases; protected $allowSslDowngrade = false; + protected $eventDispatcher; private $rawData; private $minimalPackages; private $degradedMode = false; private $rootData; - public function __construct(array $repoConfig, IOInterface $io, Config $config) + public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null) { if (!preg_match('{^[\w.]+\??://}', $repoConfig['url'])) { // assume http as the default protocol @@ -82,6 +86,7 @@ class ComposerRepository extends ArrayRepository implements StreamableRepository $this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$'); $this->loader = new ArrayLoader(); $this->rfs = new RemoteFilesystem($this->io, $this->options); + $this->eventDispatcher = $eventDispatcher; } public function setRootAliases(array $rootAliases) @@ -538,7 +543,11 @@ class ComposerRepository extends ArrayRepository implements StreamableRepository $retries = 3; while ($retries--) { try { - $json = $this->rfs->getContents($filename, $filename, false); + $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename); + if ($this->eventDispatcher) { + $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent); + } + $json = $preFileDownloadEvent->getRemoteFilesystem()->getContents($filename, $filename, false); if ($sha256 && $sha256 !== hash('sha256', $json)) { if ($retries) { usleep(100000); diff --git a/src/Composer/Repository/RepositoryManager.php b/src/Composer/Repository/RepositoryManager.php index ed915707f..1a9054f14 100644 --- a/src/Composer/Repository/RepositoryManager.php +++ b/src/Composer/Repository/RepositoryManager.php @@ -14,6 +14,7 @@ namespace Composer\Repository; use Composer\IO\IOInterface; use Composer\Config; +use Composer\EventDispatcher\EventDispatcher; /** * Repositories manager. @@ -29,11 +30,13 @@ class RepositoryManager private $repositoryClasses = array(); private $io; private $config; + private $eventDispatcher; - public function __construct(IOInterface $io, Config $config) + public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null) { $this->io = $io; $this->config = $config; + $this->eventDispatcher = $eventDispatcher; } /** @@ -98,7 +101,7 @@ class RepositoryManager $class = $this->repositoryClasses[$type]; - return new $class($config, $this->io, $this->config); + return new $class($config, $this->io, $this->config, $this->eventDispatcher); } /** From 09c0d971d3727b0cdffbd566bf8ba92a77ebde14 Mon Sep 17 00:00:00 2001 From: ptarjan Date: Tue, 19 Nov 2013 14:35:24 -0800 Subject: [PATCH 194/238] don't require the error message have the first line of HTTP output in it --- tests/Composer/Test/Util/RemoteFilesystemTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Composer/Test/Util/RemoteFilesystemTest.php b/tests/Composer/Test/Util/RemoteFilesystemTest.php index 67696b40f..eabfe9ed5 100644 --- a/tests/Composer/Test/Util/RemoteFilesystemTest.php +++ b/tests/Composer/Test/Util/RemoteFilesystemTest.php @@ -157,7 +157,6 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase } catch (\Exception $e) { $this->assertInstanceOf('Composer\Downloader\TransportException', $e); $this->assertEquals(404, $e->getCode()); - $this->assertContains('404 Not Found', $e->getMessage()); } } From 61cc291c8aa5b340f7ab5d78eb2a62a04a62a2aa Mon Sep 17 00:00:00 2001 From: Bilal Amarni Date: Wed, 20 Nov 2013 00:47:02 +0100 Subject: [PATCH 195/238] [CreateProject] allowed pretty version constraint --- doc/03-cli.md | 2 +- src/Composer/Command/CreateProjectCommand.php | 28 +++++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index 9c07776ff..38db3f925 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -332,7 +332,7 @@ provide a version as third argument, otherwise the latest version is used. If the directory does not currently exist, it will be created during installation. - php composer.phar create-project doctrine/orm path 2.2.0 + php composer.phar create-project doctrine/orm path 2.2.* It is also possible to run the command without params in a directory with an existing `composer.json` file to bootstrap a project. diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index c4a159675..7a5864ca7 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -57,7 +57,7 @@ class CreateProjectCommand extends Command new InputArgument('package', InputArgument::OPTIONAL, 'Package name to be installed'), new InputArgument('directory', InputArgument::OPTIONAL, 'Directory where the files should be created'), new InputArgument('version', InputArgument::OPTIONAL, 'Version, will defaults to latest'), - new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).', 'stable'), + new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'), new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'), new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'Pick a different repository url to look for the package.'), @@ -239,14 +239,6 @@ EOT protected function installRootPackage(IOInterface $io, $config, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repositoryUrl = null, $disablePlugins = false, $noScripts = false, $keepVcs = false, $noProgress = false) { - $stability = strtolower($stability); - if ($stability === 'rc') { - $stability = 'RC'; - } - if (!isset(BasePackage::$stabilities[$stability])) { - throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities))); - } - if (null === $repositoryUrl) { $sourceRepo = new CompositeRepository(Factory::createDefaultRepositories($io, $config)); } elseif ("json" === pathinfo($repositoryUrl, PATHINFO_EXTENSION)) { @@ -265,10 +257,24 @@ EOT $packageVersion = $requirements[0]['version']; } - $pool = new Pool($packageVersion ? 'dev' : $stability); + if (null === $stability) { + if (preg_match('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) { + $stability = $match[1]; + } else { + $stability = VersionParser::parseStability($packageVersion); + } + } + + $stability = VersionParser::normalizeStability($stability); + + if (!isset(BasePackage::$stabilities[$stability])) { + throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities))); + } + + $pool = new Pool($stability); $pool->addRepository($sourceRepo); - $constraint = $packageVersion ? new VersionConstraint('=', $parser->normalize($packageVersion)) : null; + $constraint = $packageVersion ? $parser->parseConstraints($packageVersion) : null; $candidates = $pool->whatProvides($name, $constraint); foreach ($candidates as $key => $candidate) { if ($candidate->getName() !== $name) { From 0e2959cc32de3a2e2cb80364c4a00c53bc5be5c9 Mon Sep 17 00:00:00 2001 From: Alexey Kupershtokh Date: Wed, 20 Nov 2013 10:14:44 +0700 Subject: [PATCH 196/238] Cache in VersionConstraint --- .../LinkConstraint/VersionConstraint.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Composer/Package/LinkConstraint/VersionConstraint.php b/src/Composer/Package/LinkConstraint/VersionConstraint.php index 0e8a8c3b7..9bf5e515b 100644 --- a/src/Composer/Package/LinkConstraint/VersionConstraint.php +++ b/src/Composer/Package/LinkConstraint/VersionConstraint.php @@ -60,12 +60,27 @@ class VersionConstraint extends SpecificConstraint return version_compare($a, $b, $operator); } + public function matchSpecific(VersionConstraint $provider, $compareBranches = false) + { + static $c = array(); + if (isset($c[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches])) { + //if ($c[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches] != + // $this->_matchSpecific($provider, $compareBranches)) { + // throw new \Exception('Broken cache'); + //} + return $c[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches]; + } + + return $c[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches] = + $this->_matchSpecific($provider, $compareBranches); + } + /** * @param VersionConstraint $provider * @param bool $compareBranches * @return bool */ - public function matchSpecific(VersionConstraint $provider, $compareBranches = false) + public function _matchSpecific(VersionConstraint $provider, $compareBranches = false) { $noEqualOp = str_replace('=', '', $this->operator); $providerNoEqualOp = str_replace('=', '', $provider->operator); From fc3fbdeab3355c2c9d03e496c41b1a3bb9565a49 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 20 Nov 2013 15:17:10 +0100 Subject: [PATCH 197/238] Rename a few things --- .../LinkConstraint/VersionConstraint.php | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Composer/Package/LinkConstraint/VersionConstraint.php b/src/Composer/Package/LinkConstraint/VersionConstraint.php index 9bf5e515b..cd2336227 100644 --- a/src/Composer/Package/LinkConstraint/VersionConstraint.php +++ b/src/Composer/Package/LinkConstraint/VersionConstraint.php @@ -60,19 +60,20 @@ class VersionConstraint extends SpecificConstraint return version_compare($a, $b, $operator); } + /** + * @param VersionConstraint $provider + * @param bool $compareBranches + * @return bool + */ public function matchSpecific(VersionConstraint $provider, $compareBranches = false) { - static $c = array(); - if (isset($c[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches])) { - //if ($c[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches] != - // $this->_matchSpecific($provider, $compareBranches)) { - // throw new \Exception('Broken cache'); - //} - return $c[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches]; + static $cache = array(); + if (isset($cache[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches])) { + return $cache[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches]; } - return $c[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches] = - $this->_matchSpecific($provider, $compareBranches); + return $cache[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches] = + $this->doMatchSpecific($provider, $compareBranches); } /** @@ -80,7 +81,7 @@ class VersionConstraint extends SpecificConstraint * @param bool $compareBranches * @return bool */ - public function _matchSpecific(VersionConstraint $provider, $compareBranches = false) + private function doMatchSpecific(VersionConstraint $provider, $compareBranches = false) { $noEqualOp = str_replace('=', '', $this->operator); $providerNoEqualOp = str_replace('=', '', $provider->operator); From 4fe35ae6937df17d9450045c91952728f697eb4a Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 22 Nov 2013 10:05:08 +0100 Subject: [PATCH 198/238] Fix vcs repo constructor, fixes #2444 --- src/Composer/Repository/VcsRepository.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Composer/Repository/VcsRepository.php b/src/Composer/Repository/VcsRepository.php index c7a543748..62e7acef5 100644 --- a/src/Composer/Repository/VcsRepository.php +++ b/src/Composer/Repository/VcsRepository.php @@ -19,6 +19,7 @@ use Composer\Package\Loader\ArrayLoader; use Composer\Package\Loader\ValidatingArrayLoader; use Composer\Package\Loader\InvalidPackageException; use Composer\Package\Loader\LoaderInterface; +use Composer\EventDispatcher\EventDispatcher; use Composer\IO\IOInterface; use Composer\Config; @@ -38,7 +39,7 @@ class VcsRepository extends ArrayRepository protected $repoConfig; protected $branchErrorOccurred = false; - public function __construct(array $repoConfig, IOInterface $io, Config $config, array $drivers = null) + public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, array $drivers = null) { $this->drivers = $drivers ?: array( 'github' => 'Composer\Repository\Vcs\GitHubDriver', From 4e4fc257e66f7ec2bad80ff92b10a23ae3927d50 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 22 Nov 2013 10:11:04 +0100 Subject: [PATCH 199/238] Fix pear ctor, refs #2444 --- src/Composer/Repository/PearRepository.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 82097e26a..a106385a5 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -17,6 +17,7 @@ use Composer\Package\Version\VersionParser; use Composer\Repository\Pear\ChannelReader; use Composer\Package\CompletePackage; use Composer\Repository\Pear\ChannelInfo; +use Composer\EventDispatcher\EventDispatcher; use Composer\Package\Link; use Composer\Package\LinkConstraint\VersionConstraint; use Composer\Util\RemoteFilesystem; @@ -43,7 +44,7 @@ class PearRepository extends ArrayRepository */ private $vendorAlias; - public function __construct(array $repoConfig, IOInterface $io, Config $config, RemoteFilesystem $rfs = null) + public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, RemoteFilesystem $rfs = null) { if (!preg_match('{^https?://}', $repoConfig['url'])) { $repoConfig['url'] = 'http://'.$repoConfig['url']; From 78edca3ad601a3fd194d0e220ef736c16b37ab1d Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 22 Nov 2013 11:06:22 +0100 Subject: [PATCH 200/238] Only replace version in Composer.php, fix user agent --- src/Composer/Compiler.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Composer/Compiler.php b/src/Composer/Compiler.php index fa86d7f21..c81e300b6 100644 --- a/src/Composer/Compiler.php +++ b/src/Composer/Compiler.php @@ -126,7 +126,7 @@ class Compiler private function addFile($phar, $file, $strip = true) { - $path = str_replace(dirname(dirname(__DIR__)).DIRECTORY_SEPARATOR, '', $file->getRealPath()); + $path = strtr(str_replace(dirname(dirname(__DIR__)).DIRECTORY_SEPARATOR, '', $file->getRealPath()), '\\', '/'); $content = file_get_contents($file); if ($strip) { @@ -135,8 +135,10 @@ class Compiler $content = "\n".$content."\n"; } - $content = str_replace('@package_version@', $this->version, $content); - $content = str_replace('@release_date@', $this->versionDate, $content); + if ($path === 'src/Composer/Composer.php') { + $content = str_replace('@package_version@', $this->version, $content); + $content = str_replace('@release_date@', $this->versionDate, $content); + } $phar->addFromString($path, $content); } From 5156a60216ee0ce41e386d99677b4d36946145de Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 22 Nov 2013 11:10:54 +0100 Subject: [PATCH 201/238] Add test for RepositoryManager repo creation --- .../Test/Repository/RepositoryManagerTest.php | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tests/Composer/Test/Repository/RepositoryManagerTest.php diff --git a/tests/Composer/Test/Repository/RepositoryManagerTest.php b/tests/Composer/Test/Repository/RepositoryManagerTest.php new file mode 100644 index 000000000..94acc8bad --- /dev/null +++ b/tests/Composer/Test/Repository/RepositoryManagerTest.php @@ -0,0 +1,57 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Repository; + +use Composer\TestCase; + +class RepositoryManagerTest extends TestCase +{ + /** + * @dataProvider creationCases + */ + public function testRepoCreation($type, $config) + { + $rm = new RepositoryManager( + $this->getMock('Composer\IO\IOInterface'), + $this->getMock('Composer\Config'), + $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')->disableOriginalConstructor()->getMock() + ); + $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository'); + $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository'); + $rm->setRepositoryClass('package', 'Composer\Repository\PackageRepository'); + $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository'); + $rm->setRepositoryClass('git', 'Composer\Repository\VcsRepository'); + $rm->setRepositoryClass('svn', 'Composer\Repository\VcsRepository'); + $rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository'); + $rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository'); + $rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository'); + + $rm->createRepository('composer', array('url' => 'http://example.org')); + $rm->createRepository('composer', array('url' => 'http://example.org')); + $rm->createRepository('composer', array('url' => 'http://example.org')); + } + + public function creationCases() + { + return array( + array('composer', array('url' => 'http://example.org')), + array('vcs', array('url' => 'http://github.com/foo/bar')), + array('git', array('url' => 'http://github.com/foo/bar')), + array('git', array('url' => 'git@example.org:foo/bar.git')), + array('svn', array('url' => 'svn://example.org/foo/bar')), + array('pear', array('url' => 'http://pear.example.org/foo')), + array('artifact', array('url' => '/path/to/zips')), + array('package', array()), + ); + } +} From 730dcbb80af90f44c84fa323b24c5d0f0f24fc54 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 22 Nov 2013 12:09:24 +0100 Subject: [PATCH 202/238] Detect failed gethostbyname, refs #2449 --- src/Composer/Util/NoProxyPattern.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Composer/Util/NoProxyPattern.php b/src/Composer/Util/NoProxyPattern.php index b41c8ff52..941aedf2b 100644 --- a/src/Composer/Util/NoProxyPattern.php +++ b/src/Composer/Util/NoProxyPattern.php @@ -73,6 +73,9 @@ class NoProxyPattern if (strpos($ruleHost, '/') === false) { $match = $ip === $ruleHost; } else { + if ($ip === $host) { + throw new \RuntimeException('gethostbyname() failed to resolve "'.$host.'" to an IP, can not evaluate NO_PROXY rules'); + } $match = self::inCIDRBlock($ruleHost, $ip); } } else { From 8173b42a8a991f1f6d46c6e469cb5202f9509d14 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 22 Nov 2013 15:38:13 +0100 Subject: [PATCH 203/238] Force unresolvable hosts through proxies, fixes #2449 --- src/Composer/Util/NoProxyPattern.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Composer/Util/NoProxyPattern.php b/src/Composer/Util/NoProxyPattern.php index 941aedf2b..d85a0c29a 100644 --- a/src/Composer/Util/NoProxyPattern.php +++ b/src/Composer/Util/NoProxyPattern.php @@ -73,8 +73,10 @@ class NoProxyPattern if (strpos($ruleHost, '/') === false) { $match = $ip === $ruleHost; } else { + // gethostbyname() failed to resolve $host to an ip, so we assume + // it must be proxied to let the proxy's DNS resolve it if ($ip === $host) { - throw new \RuntimeException('gethostbyname() failed to resolve "'.$host.'" to an IP, can not evaluate NO_PROXY rules'); + $match = false; } $match = self::inCIDRBlock($ruleHost, $ip); } From 5b48abe833e3b2ad004dc4cb28ec605a125894ed Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 22 Nov 2013 15:51:16 +0100 Subject: [PATCH 204/238] Fix previous commit --- src/Composer/Util/NoProxyPattern.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Composer/Util/NoProxyPattern.php b/src/Composer/Util/NoProxyPattern.php index d85a0c29a..16f7488d0 100644 --- a/src/Composer/Util/NoProxyPattern.php +++ b/src/Composer/Util/NoProxyPattern.php @@ -77,8 +77,10 @@ class NoProxyPattern // it must be proxied to let the proxy's DNS resolve it if ($ip === $host) { $match = false; + } else { + // match resolved IP against the rule + $match = self::inCIDRBlock($ruleHost, $ip); } - $match = self::inCIDRBlock($ruleHost, $ip); } } else { // match end of domain From 99e260adf04036c39f4c4042ec27c2ce9da3cd9f Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 22 Nov 2013 16:15:18 +0100 Subject: [PATCH 205/238] Update deps --- composer.lock | 70 +++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/composer.lock b/composer.lock index 0522d3f3e..651ce7887 100644 --- a/composer.lock +++ b/composer.lock @@ -32,16 +32,16 @@ }, { "name": "seld/jsonlint", - "version": "1.1.1", + "version": "1.1.2", "source": { "type": "git", - "url": "http://github.com/Seldaek/jsonlint", - "reference": "1.1.1" + "url": "https://github.com/Seldaek/jsonlint.git", + "reference": "7cd4c4965e17e6e4c07f26d566619a4c76f8c672" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/1.1.1", - "reference": "1.1.1", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/7cd4c4965e17e6e4c07f26d566619a4c76f8c672", + "reference": "7cd4c4965e17e6e4c07f26d566619a4c76f8c672", "shasum": "" }, "require": { @@ -75,21 +75,21 @@ "parser", "validator" ], - "time": "2013-02-11 23:03:12" + "time": "2013-11-04 15:41:11" }, { "name": "symfony/console", - "version": "v2.3.6", + "version": "v2.3.7", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "f880062d56edefb25b36f2defa65aafe65959dc7" + "reference": "00848d3e13cf512e77c7498c2b3b0192f61f4b18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/f880062d56edefb25b36f2defa65aafe65959dc7", - "reference": "f880062d56edefb25b36f2defa65aafe65959dc7", + "url": "https://api.github.com/repos/symfony/Console/zipball/00848d3e13cf512e77c7498c2b3b0192f61f4b18", + "reference": "00848d3e13cf512e77c7498c2b3b0192f61f4b18", "shasum": "" }, "require": { @@ -128,11 +128,11 @@ ], "description": "Symfony Console Component", "homepage": "http://symfony.com", - "time": "2013-09-25 06:04:15" + "time": "2013-11-13 21:27:40" }, { "name": "symfony/finder", - "version": "v2.3.6", + "version": "v2.3.7", "target-dir": "Symfony/Component/Finder", "source": { "type": "git", @@ -184,12 +184,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Process.git", - "reference": "27b0fc645a557b2fc7bc7735cfb05505de9351be" + "reference": "88ccdd7a1fb67a23fe81355c66a09d6908ebcd80" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/27b0fc645a557b2fc7bc7735cfb05505de9351be", - "reference": "27b0fc645a557b2fc7bc7735cfb05505de9351be", + "url": "https://api.github.com/repos/symfony/Process/zipball/88ccdd7a1fb67a23fe81355c66a09d6908ebcd80", + "reference": "88ccdd7a1fb67a23fe81355c66a09d6908ebcd80", "shasum": "" }, "require": { @@ -222,7 +222,7 @@ ], "description": "Symfony Process Component", "homepage": "http://symfony.com", - "time": "2013-10-10 05:53:18" + "time": "2013-11-09 12:03:12" } ], "packages-dev": [ @@ -337,13 +337,13 @@ "version": "1.1.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5180896f51c5b3648ac946b05f9ec02be78a0b23" + "url": "git://github.com/sebastianbergmann/php-text-template.git", + "reference": "1.1.4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5180896f51c5b3648ac946b05f9ec02be78a0b23", - "reference": "5180896f51c5b3648ac946b05f9ec02be78a0b23", + "url": "https://github.com/sebastianbergmann/php-text-template/zipball/1.1.4", + "reference": "1.1.4", "shasum": "" }, "require": { @@ -374,7 +374,7 @@ "keywords": [ "template" ], - "time": "2012-10-31 18:15:28" + "time": "2012-10-31 11:15:28" }, { "name": "phpunit/php-timer", @@ -472,16 +472,16 @@ }, { "name": "phpunit/phpunit", - "version": "3.7.27", + "version": "3.7.28", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "4b024e753e3421837afbcca962c8724c58b39376" + "reference": "3b97c8492bcafbabe6b6fbd2ab35f2f04d932a8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4b024e753e3421837afbcca962c8724c58b39376", - "reference": "4b024e753e3421837afbcca962c8724c58b39376", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3b97c8492bcafbabe6b6fbd2ab35f2f04d932a8d", + "reference": "3b97c8492bcafbabe6b6fbd2ab35f2f04d932a8d", "shasum": "" }, "require": { @@ -542,20 +542,20 @@ "testing", "xunit" ], - "time": "2013-09-16 03:09:52" + "time": "2013-10-17 07:27:40" }, { "name": "phpunit/phpunit-mock-objects", "version": "1.2.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875" + "url": "git://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "1.2.3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5794e3c5c5ba0fb037b11d8151add2a07fa82875", - "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects/archive/1.2.3.zip", + "reference": "1.2.3", "shasum": "" }, "require": { @@ -595,17 +595,17 @@ }, { "name": "symfony/yaml", - "version": "v2.3.6", + "version": "v2.3.7", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "6bb881b948368482e1abf1a75c08bcf88a1c5fc3" + "reference": "c1bda5b459d792cb253de12c65beba3040163b2b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/6bb881b948368482e1abf1a75c08bcf88a1c5fc3", - "reference": "6bb881b948368482e1abf1a75c08bcf88a1c5fc3", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/c1bda5b459d792cb253de12c65beba3040163b2b", + "reference": "c1bda5b459d792cb253de12c65beba3040163b2b", "shasum": "" }, "require": { @@ -638,7 +638,7 @@ ], "description": "Symfony Yaml Component", "homepage": "http://symfony.com", - "time": "2013-09-22 18:04:39" + "time": "2013-10-17 11:48:01" } ], "aliases": [ From e126c925258e6920433b9c57d97042025754dff1 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 22 Nov 2013 16:17:02 +0100 Subject: [PATCH 206/238] Fix exit codes, cc @tyrael --- src/Composer/Command/CreateProjectCommand.php | 5 +++-- src/Composer/Command/InstallCommand.php | 2 +- src/Composer/Command/RequireCommand.php | 7 +++---- src/Composer/Command/UpdateCommand.php | 2 +- src/Composer/Installer.php | 13 ++++++++----- tests/Composer/Test/InstallerTest.php | 6 +++--- 6 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index 7a5864ca7..5aab270ce 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -173,8 +173,9 @@ EOT $installer->disablePlugins(); } - if (!$installer->run()) { - return 1; + $status = $installer->run(); + if (0 !== $status) { + return $status; } } diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index 6138009a3..a163d5ad5 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -107,6 +107,6 @@ EOT $install->disablePlugins(); } - return $install->run() ? 0 : 1; + return $install->run(); } } diff --git a/src/Composer/Command/RequireCommand.php b/src/Composer/Command/RequireCommand.php index 11951dd08..f33c2fd00 100644 --- a/src/Composer/Command/RequireCommand.php +++ b/src/Composer/Command/RequireCommand.php @@ -123,14 +123,13 @@ EOT ->setUpdateWhitelist(array_keys($requirements)); ; - if (!$install->run()) { + $status = $install->run(); + if ($status !== 0) { $output->writeln("\n".'Installation failed, reverting '.$file.' to its original content.'); file_put_contents($json->getPath(), $composerBackup); - - return 1; } - return 0; + return $status; } private function updateFileCleanly($json, array $base, array $new, $requireKey) diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index b2f8298e1..7a1471a65 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -115,6 +115,6 @@ EOT $install->disablePlugins(); } - return $install->run() ? 0 : 1; + return $install->run(); } } diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 30766bb70..0970b75f4 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -146,6 +146,8 @@ class Installer /** * Run installation (or update) + * + * @return int 0 on success or a positive error code on failure */ public function run() { @@ -205,8 +207,9 @@ class Installer try { $this->suggestedPackages = array(); - if (!$this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases, $this->devMode)) { - return false; + $res = $this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases, $this->devMode); + if ($res !== 0) { + return $res; } } catch (\Exception $e) { $this->installationManager->notifyInstalls(); @@ -286,7 +289,7 @@ class Installer } } - return true; + return 0; } protected function doInstall($localRepo, $installedRepo, $platformRepo, $aliases, $withDevReqs) @@ -448,7 +451,7 @@ class Installer $this->io->write('Your requirements could not be resolved to an installable set of packages.'); $this->io->write($e->getMessage()); - return false; + return max(1, $e->getCode()); } // force dev packages to be updated if we update or install from a (potentially new) lock @@ -533,7 +536,7 @@ class Installer } } - return true; + return 0; } /** diff --git a/tests/Composer/Test/InstallerTest.php b/tests/Composer/Test/InstallerTest.php index 29c153e88..0cc17cfb0 100644 --- a/tests/Composer/Test/InstallerTest.php +++ b/tests/Composer/Test/InstallerTest.php @@ -72,7 +72,7 @@ class InstallerTest extends TestCase $installer = new Installer($io, $config, clone $rootPackage, $downloadManager, $repositoryManager, $locker, $installationManager, $eventDispatcher, $autoloadGenerator); $result = $installer->run(); - $this->assertTrue($result); + $this->assertSame(0, $result); $expectedInstalled = isset($options['install']) ? $options['install'] : array(); $expectedUpdated = isset($options['update']) ? $options['update'] : array(); @@ -206,7 +206,7 @@ class InstallerTest extends TestCase ->setDevMode($input->getOption('dev')) ->setDryRun($input->getOption('dry-run')); - return $installer->run() ? 0 : 1; + return $installer->run(); }); $application->get('update')->setCode(function ($input, $output) use ($installer) { @@ -217,7 +217,7 @@ class InstallerTest extends TestCase ->setUpdateWhitelist($input->getArgument('packages')) ->setWhitelistDependencies($input->getOption('with-dependencies')); - return $installer->run() ? 0 : 1; + return $installer->run(); }); if (!preg_match('{^(install|update)\b}', $run)) { From a956ce9bb14f1053ed9087184ba6c1c0c8299900 Mon Sep 17 00:00:00 2001 From: user Date: Sun, 24 Nov 2013 10:55:25 +0100 Subject: [PATCH 207/238] Use 'cache-files-ttl' for cache gc, fixes #2441 The configuration option 'cache-ttl' was used instead of 'cache-files-ttl' to determine whether or not a cache gc should be performed. * changed 'cache-ttl' to 'cache-files-ttl' to determine if a gc should be performed * refactored FileDownloader to allow for easier testing * added test to ensure that the gc is called with the proper config option --- src/Composer/Cache.php | 8 ++++ src/Composer/Downloader/FileDownloader.php | 7 ++-- .../Test/Downloader/FileDownloaderTest.php | 37 +++++++++++++++++-- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/Composer/Cache.php b/src/Composer/Cache.php index 260682d1a..6bdf43d5d 100644 --- a/src/Composer/Cache.php +++ b/src/Composer/Cache.php @@ -23,6 +23,7 @@ use Symfony\Component\Finder\Finder; */ class Cache { + private static $cacheCollected = false; private $io; private $root; private $enabled = true; @@ -126,6 +127,11 @@ class Cache return false; } + public function gcIsNecessary() + { + return (!self::$cacheCollected && !mt_rand(0, 50)); + } + public function remove($file) { $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file); @@ -157,6 +163,8 @@ class Cache } } + self::$cacheCollected = true; + return true; } diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index c78e65a31..3399032c2 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -34,7 +34,6 @@ use Composer\Util\RemoteFilesystem; */ class FileDownloader implements DownloaderInterface { - private static $cacheCollected = false; protected $io; protected $config; protected $rfs; @@ -61,10 +60,10 @@ class FileDownloader implements DownloaderInterface $this->filesystem = $filesystem ?: new Filesystem(); $this->cache = $cache; - if ($this->cache && !self::$cacheCollected && !mt_rand(0, 50)) { - $this->cache->gc($config->get('cache-ttl'), $config->get('cache-files-maxsize')); + + if ($this->cache && $this->cache->gcIsNecessary()) { + $this->cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize')); } - self::$cacheCollected = true; } /** diff --git a/tests/Composer/Test/Downloader/FileDownloaderTest.php b/tests/Composer/Test/Downloader/FileDownloaderTest.php index 8e2b92044..db6f81a5e 100644 --- a/tests/Composer/Test/Downloader/FileDownloaderTest.php +++ b/tests/Composer/Test/Downloader/FileDownloaderTest.php @@ -17,13 +17,13 @@ use Composer\Util\Filesystem; class FileDownloaderTest extends \PHPUnit_Framework_TestCase { - protected function getDownloader($io = null, $config = null, $rfs = null, $filesystem = null) + protected function getDownloader($io = null, $config = null, $eventDispatcher = null, $cache = null, $rfs = null, $filesystem = null) { $io = $io ?: $this->getMock('Composer\IO\IOInterface'); $config = $config ?: $this->getMock('Composer\Config'); $rfs = $rfs ?: $this->getMockBuilder('Composer\Util\RemoteFilesystem')->disableOriginalConstructor()->getMock(); - return new FileDownloader($io, $config, null, null, $rfs, $filesystem); + return new FileDownloader($io, $config, $eventDispatcher, $cache, $rfs, $filesystem); } /** @@ -123,6 +123,37 @@ class FileDownloaderTest extends \PHPUnit_Framework_TestCase } } + public function testCacheGarbageCollectionIsCalled() + { + $expectedTtl = '99999999'; + + $configMock = $this->getMock('Composer\Config'); + $configMock + ->expects($this->at(0)) + ->method('get') + ->with('cache-files-ttl') + ->will($this->returnValue($expectedTtl)); + $configMock + ->expects($this->at(1)) + ->method('get') + ->with('cache-files-maxsize') + ->will($this->returnValue('500M')); + + $cacheMock = $this->getMockBuilder('Composer\Cache') + ->disableOriginalConstructor() + ->getMock(); + $cacheMock + ->expects($this->any()) + ->method('gcIsNecessary') + ->will($this->returnValue(true)); + $cacheMock + ->expects($this->once()) + ->method('gc') + ->with($expectedTtl, $this->anything()); + + $downloader = $this->getDownloader(null, $configMock, null, $cacheMock, null, null); + } + public function testDownloadFileWithInvalidChecksum() { $packageMock = $this->getMock('Composer\Package\PackageInterface'); @@ -140,7 +171,7 @@ class FileDownloaderTest extends \PHPUnit_Framework_TestCase $path = sys_get_temp_dir().'/'.md5(time().mt_rand()); } while (file_exists($path)); - $downloader = $this->getDownloader(null, null, null, $filesystem); + $downloader = $this->getDownloader(null, null, null, null, null, $filesystem); // make sure the file expected to be downloaded is on disk already mkdir($path, 0777, true); From 10f8e564bb8d763ed86a274132f54efa521eb43c Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 25 Nov 2013 14:11:49 +0100 Subject: [PATCH 208/238] Add warnings for xdebug, fixes #2425 --- src/Composer/Command/DiagnoseCommand.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Composer/Command/DiagnoseCommand.php b/src/Composer/Command/DiagnoseCommand.php index 63ce4ee19..879e139d2 100644 --- a/src/Composer/Command/DiagnoseCommand.php +++ b/src/Composer/Command/DiagnoseCommand.php @@ -300,6 +300,12 @@ EOT $warnings['apc_cli'] = true; } + if (ini_get('xdebug.profiler_enabled')) { + $warnings['xdebug_profile'] = true; + } elseif (extension_loaded('xdebug')) { + $warnings['xdebug_loaded'] = true; + } + ob_start(); phpinfo(INFO_GENERAL); $phpinfo = ob_get_clean(); @@ -365,6 +371,18 @@ EOT $text = PHP_EOL."Your PHP ({$current}) is quite old, upgrading to PHP 5.3.4 or higher is recommended.".PHP_EOL; $text .= "Composer works with 5.3.2+ for most people, but there might be edge case issues."; break; + + case 'xdebug_loaded': + $text = PHP_EOL."The xdebug extension is loaded, this can slow down Composer a little.".PHP_EOL; + $text .= "Disabling it when using Composer is recommended, but should not cause issues beyond slowness."; + break; + + case 'xdebug_profile': + $text = PHP_EOL."The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot.".PHP_EOL; + $text .= "Add the following to the end of your `php.ini` to disable it:".PHP_EOL; + $text .= " xdebug.profiler_enabled = 0"; + $displayIniMessage = true; + break; } $out($text, 'warning'); } From 14b463da1c4853b358b9dd05ed387586efd31961 Mon Sep 17 00:00:00 2001 From: Nico Schoenmaker Date: Wed, 27 Nov 2013 12:55:12 +0100 Subject: [PATCH 209/238] Added reference to script events in plugins.md --- doc/articles/plugins.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/articles/plugins.md b/doc/articles/plugins.md index 400b3452b..75706f711 100644 --- a/doc/articles/plugins.md +++ b/doc/articles/plugins.md @@ -84,6 +84,8 @@ The events available for plugins are: you to manipulate the `RemoteFilesystem` object prior to downloading files based on the URL to be downloaded. +> A plugin can also subscribe to [script events][7]. + Example: namespace Naderman\Composer\AWS; @@ -145,3 +147,4 @@ local project plugins are loaded. [4]: https://github.com/composer/composer/blob/master/src/Composer/Composer.php [5]: https://github.com/composer/composer/blob/master/src/Composer/IO/IOInterface.php [6]: https://github.com/composer/composer/blob/master/src/Composer/EventDispatcher/EventSubscriberInterface.php +[7]: ./scripts.md#event-names From 691f784f92d5c5d6e5f742f56ea154a711f76d91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kim=20La=C3=AF=20Trinh?= Date: Thu, 28 Nov 2013 17:53:05 +0100 Subject: [PATCH 210/238] fix bug introduced in https://github.com/composer/composer/pull/2375 --- src/Composer/Repository/Vcs/GitHubDriver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Composer/Repository/Vcs/GitHubDriver.php b/src/Composer/Repository/Vcs/GitHubDriver.php index 428c2fdf4..3cf2befb5 100644 --- a/src/Composer/Repository/Vcs/GitHubDriver.php +++ b/src/Composer/Repository/Vcs/GitHubDriver.php @@ -49,7 +49,7 @@ class GitHubDriver extends VcsDriver preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git)?$#', $this->url, $match); $this->owner = $match[3]; $this->repository = $match[4]; - $this->originUrl = isset($match[1]) ? $match[1] : $match[2]; + $this->originUrl = !empty($match[1]) ? $match[1] : $match[2]; $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository); $this->fetchRootIdentifier(); @@ -238,7 +238,7 @@ class GitHubDriver extends VcsDriver return false; } - $originUrl = isset($matches[2]) ? $matches[2] : $matches[3]; + $originUrl = !empty($matches[2]) ? $matches[2] : $matches[3]; if (!in_array($originUrl, $config->get('github-domains'))) { return false; } From a8084e46ff453a9db173191c622b6a91a315252d Mon Sep 17 00:00:00 2001 From: mwhittom Date: Wed, 27 Nov 2013 09:56:58 -0600 Subject: [PATCH 211/238] Added error handling and error messages around missing perforce driver, invalid username/password --- .../Downloader/PerforceDownloader.php | 4 +- src/Composer/Util/Perforce.php | 64 ++++++++++++------- .../Downloader/PerforceDownloaderTest.php | 10 +-- 3 files changed, 45 insertions(+), 33 deletions(-) diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php index 011c0f593..2bb1ba619 100644 --- a/src/Composer/Downloader/PerforceDownloader.php +++ b/src/Composer/Downloader/PerforceDownloader.php @@ -33,7 +33,7 @@ class PerforceDownloader extends VcsDownloader $label = $package->getPrettyVersion(); $this->io->write(' Cloning ' . $ref); - $this->initPerforce($package, $path, $ref); + $this->initPerforce($package, $path); $this->perforce->setStream($ref); $this->perforce->p4Login($this->io); $this->perforce->writeP4ClientSpec(); @@ -42,7 +42,7 @@ class PerforceDownloader extends VcsDownloader $this->perforce->cleanupClientSpec(); } - private function initPerforce($package, $path, $ref) + public function initPerforce($package, $path) { if ($this->perforce) { $this->perforce->initializePath($path); diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index cf663be10..3781117bf 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -33,6 +33,7 @@ class Perforce protected $process; protected $uniquePerforceClientName; protected $windowsFlag; + protected $commandResult; public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows) { @@ -108,10 +109,9 @@ class Perforce protected function executeCommand($command) { - $result = ""; - $this->process->execute($command, $result); - - return $result; + $this->commandResult = ""; + $exit_code = $this->process->execute($command, $this->commandResult); + return $exit_code; } public function getClient() @@ -207,14 +207,15 @@ class Perforce } else { $command = 'export P4USER=' . $this->p4User; } - $result = $this->executeCommand($command); + $this->executeCommand($command); } protected function getP4variable($name) { if ($this->windowsFlag) { $command = 'p4 set'; - $result = $this->executeCommand($command); + $this->executeCommand($command); + $result = trim($this->commandResult); $resArray = explode(PHP_EOL, $result); foreach ($resArray as $line) { $fields = explode('=', $line); @@ -232,8 +233,8 @@ class Perforce } } else { $command = 'echo $' . $name; - $result = trim($this->executeCommand($command)); - + $this->executeCommand($command); + $result = trim($this->commandResult); return $result; } } @@ -268,12 +269,19 @@ class Perforce public function isLoggedIn() { $command = $this->generateP4Command('login -s', false); - $result = trim($this->executeCommand($command)); - $index = strpos($result, $this->getUser()); - if ($index === false) { - return false; + $exitCode = $this->executeCommand($command); + if ($exitCode){ + $errorOutput = $this->process->getErrorOutput(); + $index = strpos($errorOutput, $this->getUser()); + if ($index === false){ + $index = strpos($errorOutput, 'p4'); + if ($index===false){ + return false; + } + throw new \Exception('p4 command not found in path: ' . $errorOutput); + } + throw new \Exception('Invalid user name: ' . $this->getUser() ); } - return true; } @@ -294,7 +302,7 @@ class Perforce $p4SyncCommand = $p4SyncCommand . '@' . $label; } } - $result = $this->executeCommand($p4SyncCommand); + $this->executeCommand($p4SyncCommand); chdir($prevDir); } @@ -365,7 +373,11 @@ class Perforce $this->windowsLogin($password); } else { $command = 'echo ' . $password . ' | ' . $this->generateP4Command(' login -a', false); - $this->executeCommand($command); + $exitCode = $this->executeCommand($command); + $result = trim($this->commandResult); + if ($exitCode){ + throw new \Exception("Error logging in:" . $this->process->getErrorOutput()); + } } } } @@ -373,7 +385,6 @@ class Perforce public static function checkServerExists($url, ProcessExecutor $processExecutor) { $output = null; - return 0 === $processExecutor->execute('p4 -p ' . $url . ' info -s', $output); } @@ -392,7 +403,8 @@ class Perforce public function getComposerInformationFromPath($composerJson) { $command = $this->generateP4Command(' print ' . $composerJson); - $result = $this->executeCommand($command); + $this->executeCommand($command); + $result = $this->commandResult; $index = strpos($result, '{'); if ($index === false) { return ''; @@ -411,7 +423,8 @@ class Perforce { $composerJsonPath = substr($identifier, 0, $index) . '/composer.json' . substr($identifier, $index); $command = $this->generateP4Command(' files ' . $composerJsonPath, false); - $result = $this->executeCommand($command); + $this->executeCommand($command); + $result = $this->commandResult; $index2 = strpos($result, 'no such file(s).'); if ($index2 === false) { $index3 = strpos($result, 'change'); @@ -435,7 +448,8 @@ class Perforce $possibleBranches[$this->p4Branch] = $this->getStream(); } else { $command = $this->generateP4Command('streams //' . $this->p4Depot . '/...'); - $result = $this->executeCommand($command); + $this->executeCommand($command); + $result = $this->commandResult; $resArray = explode(PHP_EOL, $result); foreach ($resArray as $line) { $resBits = explode(' ', $line); @@ -454,7 +468,8 @@ class Perforce public function getTags() { $command = $this->generateP4Command('labels'); - $result = $this->executeCommand($command); + $this->executeCommand($command); + $result = $this->commandResult; $resArray = explode(PHP_EOL, $result); $tags = array(); foreach ($resArray as $line) { @@ -471,7 +486,8 @@ class Perforce public function checkStream() { $command = $this->generateP4Command('depots', false); - $result = $this->executeCommand($command); + $this->executeCommand($command); + $result = $this->commandResult; $resArray = explode(PHP_EOL, $result); foreach ($resArray as $line) { $index = strpos($line, 'Depot'); @@ -496,7 +512,8 @@ class Perforce } $label = substr($reference, $index); $command = $this->generateP4Command(' changes -m1 ' . $label); - $changes = $this->executeCommand($command); + $this->executeCommand($command); + $changes = $this->commandResult; if (strpos($changes, 'Change') !== 0) { return; } @@ -519,7 +536,8 @@ class Perforce $index = strpos($fromReference, '@'); $main = substr($fromReference, 0, $index) . '/...'; $command = $this->generateP4Command('filelog ' . $main . '@' . $fromChangeList. ',' . $toChangeList); - $result = $this->executeCommand($command); + $this->executeCommand($command); + $result = $this->commandResult; return $result; } diff --git a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php index ed8948238..8a20f67cc 100644 --- a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php +++ b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php @@ -40,7 +40,7 @@ class PerforceDownloaderTest extends \PHPUnit_Framework_TestCase $this->io = $this->getMock('Composer\IO\IOInterface'); } - public function testDoDownloadGetRepoConfig() + public function testInitPerforceGetRepoConfig() { $downloader = new PerforceDownloader($this->io, $this->config); $package = $this->getMock('Composer\Package\PackageInterface'); @@ -51,18 +51,12 @@ class PerforceDownloaderTest extends \PHPUnit_Framework_TestCase array($repoConfig, $this->io, $this->config) ); $package->expects($this->at(0)) - ->method('getSourceReference') - ->will($this->returnValue('SOURCE_REF')); - $package->expects($this->at(1)) - ->method('getPrettyVersion') - ->will($this->returnValue('100')); - $package->expects($this->at(2)) ->method('getRepository') ->will($this->returnValue($repository)); $repository->expects($this->at(0)) ->method('getRepoConfig'); $path = $this->testPath; - $downloader->doDownload($package, $path); + $downloader->initPerforce($package, $path, 'SOURCE_REF'); } public function testDoDownload() From dde9c309fd6885f8d3f59ec01a5c4e62337637b9 Mon Sep 17 00:00:00 2001 From: mwhittom Date: Wed, 27 Nov 2013 10:27:16 -0600 Subject: [PATCH 212/238] incorporated change to Perforce: Capture output, stopping errors showing up if p4 is not available --- src/Composer/Util/Perforce.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 3781117bf..47558557b 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -385,7 +385,7 @@ class Perforce public static function checkServerExists($url, ProcessExecutor $processExecutor) { $output = null; - return 0 === $processExecutor->execute('p4 -p ' . $url . ' info -s', $output); + return 0 === $processExecutor->execute('p4 -p ' . $url . ' info -s', $output); } public function getComposerInformation($identifier) From ca7cb68dd5739b0405b3de5f4854cda44d9660e3 Mon Sep 17 00:00:00 2001 From: Morgan BRUNOT Date: Thu, 5 Dec 2013 15:25:20 +0100 Subject: [PATCH 213/238] Check exclude from downloaded composer.json --- src/Composer/Package/Archiver/ArchiveManager.php | 8 ++++++++ .../Composer/Test/Package/Archiver/ArchiveManagerTest.php | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Composer/Package/Archiver/ArchiveManager.php b/src/Composer/Package/Archiver/ArchiveManager.php index b57358fa0..3dea7f140 100644 --- a/src/Composer/Package/Archiver/ArchiveManager.php +++ b/src/Composer/Package/Archiver/ArchiveManager.php @@ -16,6 +16,7 @@ use Composer\Downloader\DownloadManager; use Composer\Package\PackageInterface; use Composer\Package\RootPackage; use Composer\Util\Filesystem; +use Composer\Json\JsonFile; /** * @author Matthieu Moquet @@ -141,6 +142,13 @@ class ArchiveManager // Download sources $this->downloadManager->download($package, $sourcePath); + + // Check exclude from downloaded composer.json + $jsonFile = new JsonFile($sourcePath.'/composer.json'); + $jsonData = $jsonFile->read(); + if (!empty($jsonData['archive']['exclude'])) { + $package->setArchiveExcludes($jsonData['archive']['exclude']); + } } // Create the archive diff --git a/tests/Composer/Test/Package/Archiver/ArchiveManagerTest.php b/tests/Composer/Test/Package/Archiver/ArchiveManagerTest.php index a85555fc8..5a9f8c2d8 100644 --- a/tests/Composer/Test/Package/Archiver/ArchiveManagerTest.php +++ b/tests/Composer/Test/Package/Archiver/ArchiveManagerTest.php @@ -79,13 +79,13 @@ class ArchiveManagerTest extends ArchiverTest throw new \RuntimeException('Could not init: '.$this->process->getErrorOutput()); } - $result = file_put_contents('b', 'a'); + $result = file_put_contents('composer.json', '{"name":"faker/faker", "description": "description", "license": "MIT"}'); if (false === $result) { chdir($currentWorkDir); throw new \RuntimeException('Could not save file.'); } - $result = $this->process->execute('git add b && git commit -m "commit b" -q', $output, $this->testDir); + $result = $this->process->execute('git add composer.json && git commit -m "commit composer.json" -q', $output, $this->testDir); if ($result > 0) { chdir($currentWorkDir); throw new \RuntimeException('Could not commit: '.$this->process->getErrorOutput()); From afc9069771cf45c54d20f6e36d33ede39aa009ae Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Thu, 5 Dec 2013 21:26:02 +0100 Subject: [PATCH 214/238] Check exception code only if class ZipArchive exists If is for example exception throwed when downloading tar archive on system without installed zip extension, PHP hangs on fatal error " Class 'ZipArchive' not found". --- src/Composer/Downloader/ArchiveDownloader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Downloader/ArchiveDownloader.php b/src/Composer/Downloader/ArchiveDownloader.php index 3f1cc4117..bfe174fb7 100644 --- a/src/Composer/Downloader/ArchiveDownloader.php +++ b/src/Composer/Downloader/ArchiveDownloader.php @@ -69,7 +69,7 @@ abstract class ArchiveDownloader extends FileDownloader $this->filesystem->removeDirectory($temporaryDir); // retry downloading if we have an invalid zip file - if ($retries && $e instanceof \UnexpectedValueException && $e->getCode() === \ZipArchive::ER_NOZIP) { + if ($retries && $e instanceof \UnexpectedValueException && class_exists('ZipArchive') && $e->getCode() === \ZipArchive::ER_NOZIP) { $this->io->write(' Invalid zip file, retrying...'); usleep(500000); continue; From 80499bb02418711b34bba59c1a6d8032429e5702 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 6 Dec 2013 11:57:37 +0100 Subject: [PATCH 215/238] Detect ~> misuse and suggest fix, fixes #2476 --- src/Composer/Package/Version/VersionParser.php | 9 ++++++++- .../Test/Package/Version/VersionParserTest.php | 10 ++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Composer/Package/Version/VersionParser.php b/src/Composer/Package/Version/VersionParser.php index 8b519f943..ea37d821d 100644 --- a/src/Composer/Package/Version/VersionParser.php +++ b/src/Composer/Package/Version/VersionParser.php @@ -275,7 +275,14 @@ class VersionParser // version, to ensure that unstable instances of the current version are allowed. // however, if a stability suffix is added to the constraint, then a >= match on the current version is // used instead - if (preg_match('{^~(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.(\d+))?'.self::$modifierRegex.'?$}i', $constraint, $matches)) { + if (preg_match('{^~>?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.(\d+))?'.self::$modifierRegex.'?$}i', $constraint, $matches)) { + if (substr($constraint, 0, 2) === '~>') { + throw new \UnexpectedValueException( + 'Could not parse version constraint '.$constraint.': '. + 'Invalid operator "~>", you probably meant to use the "~" operator' + ); + } + // Work out which position in the version we are operating at if (isset($matches[4]) && '' !== $matches[4]) { $position = 4; diff --git a/tests/Composer/Test/Package/Version/VersionParserTest.php b/tests/Composer/Test/Package/Version/VersionParserTest.php index e16cdc10c..18b5c493f 100644 --- a/tests/Composer/Test/Package/Version/VersionParserTest.php +++ b/tests/Composer/Test/Package/Version/VersionParserTest.php @@ -181,6 +181,16 @@ class VersionParserTest extends \PHPUnit_Framework_TestCase $this->assertSame((string) new VersionConstraint('=', '1.0.0.0'), (string) $parser->parseConstraints('1.0#trunk/@123')); } + /** + * @expectedException UnexpectedValueException + * @expectedExceptionMessage Invalid operator "~>", you probably meant to use the "~" operator + */ + public function testParseConstraintsNudgesRubyDevsTowardsThePathOfRighteousness() + { + $parser = new VersionParser; + $parser->parseConstraints('~>1.2'); + } + /** * @dataProvider simpleConstraints */ From a300e1d45bd9ffedc81cfb8b448eced14cc324ba Mon Sep 17 00:00:00 2001 From: Morgan Brunot Date: Tue, 10 Dec 2013 21:14:50 +0100 Subject: [PATCH 216/238] Fix error on check exclude from download composer.json --- src/Composer/Package/Archiver/ArchiveManager.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Composer/Package/Archiver/ArchiveManager.php b/src/Composer/Package/Archiver/ArchiveManager.php index 3dea7f140..80865245e 100644 --- a/src/Composer/Package/Archiver/ArchiveManager.php +++ b/src/Composer/Package/Archiver/ArchiveManager.php @@ -144,10 +144,12 @@ class ArchiveManager $this->downloadManager->download($package, $sourcePath); // Check exclude from downloaded composer.json - $jsonFile = new JsonFile($sourcePath.'/composer.json'); - $jsonData = $jsonFile->read(); - if (!empty($jsonData['archive']['exclude'])) { - $package->setArchiveExcludes($jsonData['archive']['exclude']); + if (file_exists($composerJsonPath = $sourcePath.'/composer.json')) { + $jsonFile = new JsonFile($composerJsonPath); + $jsonData = $jsonFile->read(); + if (!empty($jsonData['archive']['exclude'])) { + $package->setArchiveExcludes($jsonData['archive']['exclude']); + } } } From 9ca884944c4b69ecd2e4d3d9972fda5bfc31a0b7 Mon Sep 17 00:00:00 2001 From: Beau Simensen Date: Sun, 15 Dec 2013 23:14:58 -0600 Subject: [PATCH 217/238] Skip aliases packages when looking for plugins. --- src/Composer/Plugin/PluginManager.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index 40376d145..91c28fbde 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -18,6 +18,7 @@ use Composer\IO\IOInterface; use Composer\Package\Package; use Composer\Package\Version\VersionParser; use Composer\Repository\RepositoryInterface; +use Composer\Package\AliasPackage; use Composer\Package\PackageInterface; use Composer\Package\Link; use Composer\Package\LinkConstraint\VersionConstraint; @@ -95,6 +96,9 @@ class PluginManager protected function loadRepository(RepositoryInterface $repo) { foreach ($repo->getPackages() as $package) { + if ($package instanceof AliasPackage) { + continue; + } if ('composer-plugin' === $package->getType()) { $requiresComposer = null; foreach ($package->getRequires() as $link) { From 3620796b7d123e3459bed57b6cec0e896b553311 Mon Sep 17 00:00:00 2001 From: Glen Mailer Date: Mon, 16 Dec 2013 08:51:19 +0000 Subject: [PATCH 218/238] Ensure detected extensions have valid package names --- src/Composer/Repository/PlatformRepository.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Composer/Repository/PlatformRepository.php b/src/Composer/Repository/PlatformRepository.php index 550d180db..2b462fca9 100644 --- a/src/Composer/Repository/PlatformRepository.php +++ b/src/Composer/Repository/PlatformRepository.php @@ -70,7 +70,8 @@ class PlatformRepository extends ArrayRepository $version = $versionParser->normalize($prettyVersion); } - $ext = new CompletePackage('ext-'.$name, $version, $prettyVersion); + $packageName = $this->buildPackageName($name); + $ext = new CompletePackage($packageName, $version, $prettyVersion); $ext->setDescription('The '.$name.' PHP extension'); parent::addPackage($ext); } @@ -159,4 +160,10 @@ class PlatformRepository extends ArrayRepository parent::addPackage($hhvm); } } + + + private function buildPackageName($name) + { + return 'ext-' . str_replace(' ', '-', $name); + } } From 5caee06c44eccc1a1b6aad5dec7731caa5535ebf Mon Sep 17 00:00:00 2001 From: Beau Simensen Date: Mon, 16 Dec 2013 09:21:00 -0600 Subject: [PATCH 219/238] Make PluginManager::loadRepository public --- src/Composer/Plugin/PluginManager.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index 91c28fbde..de4257e6a 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -93,7 +93,16 @@ class PluginManager return $this->plugins; } - protected function loadRepository(RepositoryInterface $repo) + /** + * Load all plugins and installers from a repository + * + * Note that plugins in the specified repository that rely on events that + * have fired prior to loading will be missed. This means you likely want to + * call this method as early as possible. + * + * @param RepositoryInterface $repo Repository to scan for plugins to install + */ + public function loadRepository(RepositoryInterface $repo) { foreach ($repo->getPackages() as $package) { if ($package instanceof AliasPackage) { From f9f144862e334c57377a2db1ae37be8523844bf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ad=C3=A1n=20Lobato?= Date: Tue, 17 Dec 2013 09:33:46 +0100 Subject: [PATCH 220/238] Fixed minor typo on 'require' property --- doc/articles/vendor-binaries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/articles/vendor-binaries.md b/doc/articles/vendor-binaries.md index 5f6918041..b258dccb7 100644 --- a/doc/articles/vendor-binaries.md +++ b/doc/articles/vendor-binaries.md @@ -58,7 +58,7 @@ Say project `my-vendor/project-b` has requirements setup like this: { "name": "my-vendor/project-b", - "requires": { + "require": { "my-vendor/project-a": "*" } } From 8bdffd75ce19c9cfca72c7bd86166a876feca85e Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Wed, 18 Dec 2013 21:58:20 +0000 Subject: [PATCH 221/238] Add information on how to run scripts manually --- doc/articles/scripts.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index 4e8d3b7d1..025eb66eb 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -9,7 +9,7 @@ A script, in Composer's terms, can either be a PHP callback (defined as a static method) or any command-line executable command. Scripts are useful for executing a package's custom code or package-specific commands during -the Composer execution process. +the Composer execution process.r **NOTE: Only scripts defined in the root package's `composer.json` are executed. If a dependency of the root package specifies its own scripts, @@ -115,3 +115,11 @@ PHP callback. This `Event` object has getters for other contextual objects: - `getName()`: returns the name of the event being fired as a string - `getIO()`: returns the current input/output stream which implements `Composer\IO\IOInterface` for writing to the console + +## Running scripts manually + +If you would like to run the scripts for an event manually, the syntax is: + + $ composer run-script [--dev] [--no-dev] script + +For example `composer run-script post-install-cmd` will run any **post-install-cmd** scripts that have been defined. From 7799c27df0c16a8f0e62c3f32ab533daf7098723 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Wed, 18 Dec 2013 21:59:10 +0000 Subject: [PATCH 222/238] Removed sneaky typo --- doc/articles/scripts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index 025eb66eb..06e7c784d 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -9,7 +9,7 @@ A script, in Composer's terms, can either be a PHP callback (defined as a static method) or any command-line executable command. Scripts are useful for executing a package's custom code or package-specific commands during -the Composer execution process.r +the Composer execution process. **NOTE: Only scripts defined in the root package's `composer.json` are executed. If a dependency of the root package specifies its own scripts, From 120f8d92fd1a17e48cad429e2d233d59a1a21c2f Mon Sep 17 00:00:00 2001 From: Glenn Pratt Date: Thu, 19 Dec 2013 09:33:37 -0600 Subject: [PATCH 223/238] Test HHVM on Travis-CI, allowing failures. --- .travis.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ad72478df..5355d5be5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,15 @@ php: - 5.3 - 5.4 - 5.5 + - hhvm + +matrix: + allow_failures: + - php: hhvm before_script: - sudo apt-get install parallel - - echo '' > ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini + - rm -f ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini - composer install --dev --prefer-source - git config --global user.name travis-ci - git config --global user.email travis@example.com From cf676880c181c7009562431a9bf86a3439467b2f Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Fri, 20 Dec 2013 13:41:08 +0100 Subject: [PATCH 224/238] Docs: Added Note about tags vs. version constraint I made this mistake myself a few days ago, so I think it will be useful to note that here. --- doc/02-libraries.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/02-libraries.md b/doc/02-libraries.md index 12e96ec96..27428064f 100644 --- a/doc/02-libraries.md +++ b/doc/02-libraries.md @@ -82,6 +82,10 @@ Here are a few examples of valid tag names: v2.0.0-alpha v2.0.4-p1 +> **Note:** Even if your tag is prefixed with `v`, a [version constraint](01-basic-usage.md#package-versions) +> in a `require` statement has to be specified without prefix +> (e.g. tag `v1.0.0` will result in version `1.0.0`). + ### Branches For every branch, a package development version will be created. If the branch From 2760221767cdbc0ececa359f47a368e793fd7f97 Mon Sep 17 00:00:00 2001 From: chr0n1x Date: Sat, 21 Dec 2013 03:06:10 -0500 Subject: [PATCH 225/238] SelfUpdateCommand: initial groundwork for --rollback --- src/Composer/Command/SelfUpdateCommand.php | 152 ++++++++++++++++----- 1 file changed, 121 insertions(+), 31 deletions(-) diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index 4074d8bad..598be7431 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -17,6 +17,7 @@ use Composer\Factory; use Composer\Util\RemoteFilesystem; use Composer\Downloader\FilesystemException; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** @@ -24,12 +25,32 @@ use Symfony\Component\Console\Output\OutputInterface; */ class SelfUpdateCommand extends Command { + const ROLLBACK = 'rollback'; + const HOMEPAGE = 'getcomposer.org'; + + protected $remoteFS; + protected $latestVersion; + protected $homepageURL; + protected $localFilename; + + public function __construct($name = null) + { + parent::__construct($name); + $protocol = (extension_loaded('openssl') ? 'https' : 'http') . '://'; + $this->homepageURL = $protocol . self::HOMEPAGE; + $this->remoteFS = new RemoteFilesystem($this->getIO()); + $this->localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0]; + } + protected function configure() { $this ->setName('self-update') ->setAliases(array('selfupdate')) ->setDescription('Updates composer.phar to the latest version.') + ->setDefinition(array( + new InputOption(self::ROLLBACK, 'r', InputOption::VALUE_OPTIONAL, 'Revert to an older installation of composer'), + )) ->setHelp(<<self-update command checks getcomposer.org for newer versions of composer and if found, installs the latest. @@ -44,57 +65,126 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { $config = Factory::createConfig(); - $cacheDir = $config->get('cache-dir'); - - $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0]; + $cacheDir = rtrim($config->get('cache-dir'), '/'); + $saveDir = rtrim($config->get('home'), '/'); // Check if current dir is writable and if not try the cache dir from settings - $tmpDir = is_writable(dirname($localFilename))? dirname($localFilename) : $cacheDir; - $tempFilename = $tmpDir . '/' . basename($localFilename, '.phar').'-temp.phar'; + $tmpDir = is_writable(dirname($this->localFilename))? dirname($this->localFilename) : $cacheDir; // check for permissions in local filesystem before start connection process if (!is_writable($tmpDir)) { throw new FilesystemException('Composer update failed: the "'.$tmpDir.'" directory used to download the temp file could not be written'); } - if (!is_writable($localFilename)) { - throw new FilesystemException('Composer update failed: the "'.$localFilename. '" file could not be written'); + if (!is_writable($this->localFilename)) { + throw new FilesystemException('Composer update failed: the "'.$this->localFilename.'" file could not be written'); } - $protocol = extension_loaded('openssl') ? 'https' : 'http'; - $rfs = new RemoteFilesystem($this->getIO()); - $latest = trim($rfs->getContents('getcomposer.org', $protocol . '://getcomposer.org/version', false)); + $rollback = $this->getOption(self::ROLLBACK); - if (Composer::VERSION !== $latest) { - $output->writeln(sprintf("Updating to version %s.", $latest)); + if (is_null($rollback)) { + $rollback = $this->getLastVersion(); + if (!$rollback) { + throw new FilesystemException('Composer rollback failed: no installation to roll back to in "'.$saveDir.'"'); - $remoteFilename = $protocol . '://getcomposer.org/composer.phar'; + return 1; + } + } - $rfs->copy('getcomposer.org', $remoteFilename, $tempFilename); + // if a rollback version is specified, check for permissions and rollback installation + if ($rollback) { + if (!is_writable($saveDir)) { + throw new FilesystemException('Composer rollback failed: the "'.$saveDir.'" dir could not be written to'); + } + $old = $saveDir . "/{$rollback}.phar"; + + if (!is_file($old)) { + throw new FilesystemException('Composer rollback failed: "'.$old.'" could not be found'); + } + if (!is_readable($old)) { + throw new FilesystemException('Composer rollback failed: "'.$old.'" could not be read'); + } + } + + $updateVersion = ($rollback)? $rollback : $this->getLatestVersion(); + + if (Composer::VERSION === $updateVersion) { + $output->writeln("You are already using composer v%s.", $updateVersion); + + return 0; + } + + $tempFilename = $tmpDir . '/' . basename($this->localFilename, '.phar').'-temp.phar'; + + if ($rollback) { + copy($saveDir . "/{$rollback}.phar", $tempFilename); + } else { + $endpoint = ($updateVersion === $this->getLatestVersion()) ? '/composer.phar' : "/download/{$updateVersion}/composer.phar"; + $remoteFilename = $this->homepageURL . $endpoint; + + $output->writeln(sprintf("Updating to version %s.", $updateVersion)); + + $this->remoteFS->copy(self::HOMEPAGE, $remoteFilename, $tempFilename); + + // @todo: handle snapshot versions not being found! if (!file_exists($tempFilename)) { $output->writeln('The download of the new composer version failed for an unexpected reason'); return 1; } + } - try { - @chmod($tempFilename, 0777 & ~umask()); - // test the phar validity - $phar = new \Phar($tempFilename); - // free the variable to unlock the file - unset($phar); - rename($tempFilename, $localFilename); - } catch (\Exception $e) { - @unlink($tempFilename); - if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) { - throw $e; - } - $output->writeln('The download is corrupted ('.$e->getMessage().').'); - $output->writeln('Please re-run the self-update command to try again.'); - } - } else { - $output->writeln("You are using the latest composer version."); + if ($err = $this->setLocalPhar($tempFilename, $saveDir)) { + $output->writeln('The file is corrupted ('.$err->getMessage().').'); + $output->writeln('Please re-run the self-update command to try again.'); + + return 1; } } + + protected function setLocalPhar($filename, $saveDir) + { + try { + @chmod($filename, 0777 & ~umask()); + // test the phar validity + $phar = new \Phar($filename); + // copy current file into installations dir + copy($this->localFilename, $saveDir . Composer::VERSION . '.phar'); + // free the variable to unlock the file + unset($phar); + rename($filename, $this->localFilename); + } catch (\Exception $e) { + @unlink($filename); + if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) { + throw $e; + } + + return $e; + } + } + + protected function getLastVersion($saveDir) + { + $config = Factory::createConfig(); + $files = glob($saveDir . '/*.phar'); + + if (empty($files)) { + return false; + } + + $fileTimes = array_map('filemtime', $files); + $map = array_combine($fileTimes, $files); + $latest = max($fileTimes); + return basename($map[$latest], '.phar'); + } + + protected function getLatestVersion() + { + if (!$this->latestVersion) { + $this->latestVersion = trim($this->remoteFS->getContents(self::HOMEPAGE, $this->homepageURL. '/version', false)); + } + + return $this->latestVersion; + } } From bc5ce1ce04f61e4557f4c08823b77a55831d7c3d Mon Sep 17 00:00:00 2001 From: chr0n1x Date: Sun, 22 Dec 2013 00:22:27 -0500 Subject: [PATCH 226/238] SelfUpdateCommand: only use 1 rollback snapshot at a time --- src/Composer/Command/SelfUpdateCommand.php | 67 ++++++++++++++++------ 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index 598be7431..9f9dce7e0 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -14,6 +14,7 @@ namespace Composer\Command; use Composer\Composer; use Composer\Factory; +use Composer\Util\Filesystem; use Composer\Util\RemoteFilesystem; use Composer\Downloader\FilesystemException; use Symfony\Component\Console\Input\InputInterface; @@ -27,6 +28,7 @@ class SelfUpdateCommand extends Command { const ROLLBACK = 'rollback'; const HOMEPAGE = 'getcomposer.org'; + const OLD_INSTALL_EXT = '-old.phar'; protected $remoteFS; protected $latestVersion; @@ -49,7 +51,7 @@ class SelfUpdateCommand extends Command ->setAliases(array('selfupdate')) ->setDescription('Updates composer.phar to the latest version.') ->setDefinition(array( - new InputOption(self::ROLLBACK, 'r', InputOption::VALUE_OPTIONAL, 'Revert to an older installation of composer'), + new InputOption(self::ROLLBACK, 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer') )) ->setHelp(<<self-update command checks getcomposer.org for newer @@ -66,7 +68,6 @@ EOT { $config = Factory::createConfig(); $cacheDir = rtrim($config->get('cache-dir'), '/'); - $saveDir = rtrim($config->get('home'), '/'); // Check if current dir is writable and if not try the cache dir from settings $tmpDir = is_writable(dirname($this->localFilename))? dirname($this->localFilename) : $cacheDir; @@ -80,24 +81,27 @@ EOT throw new FilesystemException('Composer update failed: the "'.$this->localFilename.'" file could not be written'); } - $rollback = $this->getOption(self::ROLLBACK); + $rollbackVersion = false; - if (is_null($rollback)) { - $rollback = $this->getLastVersion(); - if (!$rollback) { + // rollback specified, get last phar + if ($input->getOption(self::ROLLBACK)) { + $rollbackVersion = $this->getLastVersion($saveDir); + if (!$rollbackVersion) { throw new FilesystemException('Composer rollback failed: no installation to roll back to in "'.$saveDir.'"'); return 1; } } + $saveDir = rtrim($config->get('home'), '/'); + // if a rollback version is specified, check for permissions and rollback installation - if ($rollback) { + if ($rollbackVersion) { if (!is_writable($saveDir)) { throw new FilesystemException('Composer rollback failed: the "'.$saveDir.'" dir could not be written to'); } - $old = $saveDir . "/{$rollback}.phar"; + $old = $saveDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT; if (!is_file($old)) { throw new FilesystemException('Composer rollback failed: "'.$old.'" could not be found'); @@ -107,18 +111,20 @@ EOT } } - $updateVersion = ($rollback)? $rollback : $this->getLatestVersion(); + $updateVersion = ($rollbackVersion)? $rollbackVersion : $this->getLatestVersion(); if (Composer::VERSION === $updateVersion) { - $output->writeln("You are already using composer v%s.", $updateVersion); + $output->writeln('You are already using composer version '.$updateVersion.'.'); return 0; } $tempFilename = $tmpDir . '/' . basename($this->localFilename, '.phar').'-temp.phar'; + $backupFile = ($rollbackVersion)? false : $saveDir . '/' . Composer::VERSION . self::OLD_INSTALL_EXT; - if ($rollback) { - copy($saveDir . "/{$rollback}.phar", $tempFilename); + if ($rollbackVersion) { + rename($saveDir . "/{$rollbackVersion}" . self::OLD_INSTALL_EXT, $tempFilename); + $output->writeln(sprintf("Rolling back to cached version %s.", $rollbackVersion)); } else { $endpoint = ($updateVersion === $this->getLatestVersion()) ? '/composer.phar' : "/download/{$updateVersion}/composer.phar"; $remoteFilename = $this->homepageURL . $endpoint; @@ -133,25 +139,44 @@ EOT return 1; } + + // remove saved installations of composer + $files = $this->getOldInstallationFiles($saveDir); + if (!empty($files)) { + $fs = new Filesystem; + foreach ($files as $file) { + $output->writeln('Removing: '.$file); + $fs->remove($file); + } + } } - if ($err = $this->setLocalPhar($tempFilename, $saveDir)) { + if ($err = $this->setLocalPhar($tempFilename, $backupFile)) { $output->writeln('The file is corrupted ('.$err->getMessage().').'); $output->writeln('Please re-run the self-update command to try again.'); return 1; } + + if ($backupFile) { + $output->writeln('Saved rollback snapshot '.$backupFile); + } } - protected function setLocalPhar($filename, $saveDir) + protected function setLocalPhar($filename, $backupFile) { try { @chmod($filename, 0777 & ~umask()); // test the phar validity $phar = new \Phar($filename); - // copy current file into installations dir - copy($this->localFilename, $saveDir . Composer::VERSION . '.phar'); // free the variable to unlock the file + unset($phar); + + // copy current file into installations dir + if ($backupFile) { + copy($this->localFilename, $backupFile); + } + unset($phar); rename($filename, $this->localFilename); } catch (\Exception $e) { @@ -166,8 +191,7 @@ EOT protected function getLastVersion($saveDir) { - $config = Factory::createConfig(); - $files = glob($saveDir . '/*.phar'); + $files = $this->getOldInstallationFiles($saveDir); if (empty($files)) { return false; @@ -176,7 +200,12 @@ EOT $fileTimes = array_map('filemtime', $files); $map = array_combine($fileTimes, $files); $latest = max($fileTimes); - return basename($map[$latest], '.phar'); + return basename($map[$latest], self::OLD_INSTALL_EXT); + } + + protected function getOldInstallationFiles($saveDir) + { + return glob($saveDir . '/*' . self::OLD_INSTALL_EXT); } protected function getLatestVersion() From 0c76bba8bb001891c8022225262450b7f6d543b3 Mon Sep 17 00:00:00 2001 From: chr0n1x Date: Sun, 22 Dec 2013 00:36:24 -0500 Subject: [PATCH 227/238] SelfUpdateCommand: do not delete old snapshots, allow user to clean them --- src/Composer/Command/SelfUpdateCommand.php | 45 ++++++++++++---------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index 9f9dce7e0..40f71dac7 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -27,6 +27,7 @@ use Symfony\Component\Console\Output\OutputInterface; class SelfUpdateCommand extends Command { const ROLLBACK = 'rollback'; + const CLEAN_ROLLBACKS = 'clean-rollbacks'; const HOMEPAGE = 'getcomposer.org'; const OLD_INSTALL_EXT = '-old.phar'; @@ -51,7 +52,8 @@ class SelfUpdateCommand extends Command ->setAliases(array('selfupdate')) ->setDescription('Updates composer.phar to the latest version.') ->setDefinition(array( - new InputOption(self::ROLLBACK, 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer') + new InputOption(self::ROLLBACK, 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer'), + new InputOption(self::CLEAN_ROLLBACKS, null, InputOption::VALUE_NONE, 'Delete old snapshots during an update. This makes the current version of composer the only rollback snapshot after the update') )) ->setHelp(<<self-update command checks getcomposer.org for newer @@ -82,26 +84,25 @@ EOT } $rollbackVersion = false; + $rollbackDir = rtrim($config->get('home'), '/'); // rollback specified, get last phar if ($input->getOption(self::ROLLBACK)) { - $rollbackVersion = $this->getLastVersion($saveDir); + $rollbackVersion = $this->getLastVersion($rollbackDir); if (!$rollbackVersion) { - throw new FilesystemException('Composer rollback failed: no installation to roll back to in "'.$saveDir.'"'); + throw new FilesystemException('Composer rollback failed: no installation to roll back to in "'.$rollbackDir.'"'); return 1; } } - $saveDir = rtrim($config->get('home'), '/'); - // if a rollback version is specified, check for permissions and rollback installation if ($rollbackVersion) { - if (!is_writable($saveDir)) { - throw new FilesystemException('Composer rollback failed: the "'.$saveDir.'" dir could not be written to'); + if (!is_writable($rollbackDir)) { + throw new FilesystemException('Composer rollback failed: the "'.$rollbackDir.'" dir could not be written to'); } - $old = $saveDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT; + $old = $rollbackDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT; if (!is_file($old)) { throw new FilesystemException('Composer rollback failed: "'.$old.'" could not be found'); @@ -120,10 +121,10 @@ EOT } $tempFilename = $tmpDir . '/' . basename($this->localFilename, '.phar').'-temp.phar'; - $backupFile = ($rollbackVersion)? false : $saveDir . '/' . Composer::VERSION . self::OLD_INSTALL_EXT; + $backupFile = ($rollbackVersion)? false : $rollbackDir . '/' . Composer::VERSION . self::OLD_INSTALL_EXT; if ($rollbackVersion) { - rename($saveDir . "/{$rollbackVersion}" . self::OLD_INSTALL_EXT, $tempFilename); + rename($rollbackDir . "/{$rollbackVersion}" . self::OLD_INSTALL_EXT, $tempFilename); $output->writeln(sprintf("Rolling back to cached version %s.", $rollbackVersion)); } else { $endpoint = ($updateVersion === $this->getLatestVersion()) ? '/composer.phar' : "/download/{$updateVersion}/composer.phar"; @@ -141,12 +142,16 @@ EOT } // remove saved installations of composer - $files = $this->getOldInstallationFiles($saveDir); - if (!empty($files)) { - $fs = new Filesystem; - foreach ($files as $file) { - $output->writeln('Removing: '.$file); - $fs->remove($file); + if ($input->getOption(self::CLEAN_ROLLBACKS)) { + $files = $this->getOldInstallationFiles($rollbackDir); + + if (!empty($files)) { + $fs = new Filesystem; + + foreach ($files as $file) { + $output->writeln('Removing: '.$file); + $fs->remove($file); + } } } } @@ -189,9 +194,9 @@ EOT } } - protected function getLastVersion($saveDir) + protected function getLastVersion($rollbackDir) { - $files = $this->getOldInstallationFiles($saveDir); + $files = $this->getOldInstallationFiles($rollbackDir); if (empty($files)) { return false; @@ -203,9 +208,9 @@ EOT return basename($map[$latest], self::OLD_INSTALL_EXT); } - protected function getOldInstallationFiles($saveDir) + protected function getOldInstallationFiles($rollbackDir) { - return glob($saveDir . '/*' . self::OLD_INSTALL_EXT); + return glob($rollbackDir . '/*' . self::OLD_INSTALL_EXT); } protected function getLatestVersion() From d26355ef65fb271aebe39cc9b50f840304c64b3f Mon Sep 17 00:00:00 2001 From: chr0n1x Date: Sun, 22 Dec 2013 00:59:02 -0500 Subject: [PATCH 228/238] SelfUpdateCommand: removed unneeded return --- src/Composer/Command/SelfUpdateCommand.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index 40f71dac7..d29d50b36 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -91,8 +91,6 @@ EOT $rollbackVersion = $this->getLastVersion($rollbackDir); if (!$rollbackVersion) { throw new FilesystemException('Composer rollback failed: no installation to roll back to in "'.$rollbackDir.'"'); - - return 1; } } From d6c46f2091a0310d37d10940633db585d4ab3e07 Mon Sep 17 00:00:00 2001 From: Stan Lemon Date: Sun, 22 Dec 2013 22:01:42 -0500 Subject: [PATCH 229/238] Allow the autoloader suffix to be configured from a project's composer.json --- res/composer-schema.json | 4 ++++ src/Composer/Autoload/AutoloadGenerator.php | 2 +- src/Composer/Config.php | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/res/composer-schema.json b/res/composer-schema.json index 7b52d7733..e3599485f 100644 --- a/res/composer-schema.json +++ b/res/composer-schema.json @@ -176,6 +176,10 @@ "type": ["string", "boolean"], "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"." }, + "autoloader-suffix": { + "type": ["string", "boolean"], + "description": "Optional string to be used as a suffix to the autoloader generator. When null a random one will be generated." + }, "prepend-autoloader": { "type": "boolean", "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true." diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 1252371d6..7b019e012 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -169,7 +169,7 @@ EOF; $classmapFile .= ");\n"; if (!$suffix) { - $suffix = md5(uniqid('', true)); + $suffix = $config->get('autoloader-suffix') ? $config->get('autoloader-suffix') : md5(uniqid('', true)); } file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile); diff --git a/src/Composer/Config.php b/src/Composer/Config.php index c893091c6..68a3410f3 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -35,6 +35,7 @@ class Config 'cache-files-ttl' => null, // fallback to cache-ttl 'cache-files-maxsize' => '300MiB', 'discard-changes' => false, + 'autoload-suffix' => false, 'prepend-autoloader' => true, 'github-domains' => array('github.com'), ); From 5fd3223aecf56852f06e36cd5d23cce4d9bfc970 Mon Sep 17 00:00:00 2001 From: Stan Lemon Date: Mon, 23 Dec 2013 11:27:33 -0500 Subject: [PATCH 230/238] Updates per @stof --- res/composer-schema.json | 2 +- src/Composer/Autoload/AutoloadGenerator.php | 2 +- src/Composer/Config.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/res/composer-schema.json b/res/composer-schema.json index e3599485f..180656c1d 100644 --- a/res/composer-schema.json +++ b/res/composer-schema.json @@ -177,7 +177,7 @@ "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"." }, "autoloader-suffix": { - "type": ["string", "boolean"], + "type": "string", "description": "Optional string to be used as a suffix to the autoloader generator. When null a random one will be generated." }, "prepend-autoloader": { diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 7b019e012..b26fb5831 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -169,7 +169,7 @@ EOF; $classmapFile .= ");\n"; if (!$suffix) { - $suffix = $config->get('autoloader-suffix') ? $config->get('autoloader-suffix') : md5(uniqid('', true)); + $suffix = $config->get('autoloader-suffix') ?: md5(uniqid('', true)); } file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile); diff --git a/src/Composer/Config.php b/src/Composer/Config.php index 68a3410f3..311c7de85 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -35,7 +35,7 @@ class Config 'cache-files-ttl' => null, // fallback to cache-ttl 'cache-files-maxsize' => '300MiB', 'discard-changes' => false, - 'autoload-suffix' => false, + 'autoload-suffix' => null, 'prepend-autoloader' => true, 'github-domains' => array('github.com'), ); From 4ae5c95c8d36b5b26e0990384dd2f478c66c314f Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 26 Dec 2013 12:30:12 +0100 Subject: [PATCH 231/238] Detect require overrides, fixes #2503 --- src/Composer/Util/ConfigValidator.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Composer/Util/ConfigValidator.php b/src/Composer/Util/ConfigValidator.php index 7c6b321e6..82648d6d3 100644 --- a/src/Composer/Util/ConfigValidator.php +++ b/src/Composer/Util/ConfigValidator.php @@ -108,6 +108,11 @@ class ConfigValidator $warnings[] = "The package type 'composer-installer' is deprecated. Please distribute your custom installers as plugins from now on. See http://getcomposer.org/doc/articles/plugins.md for plugin documentation."; } + $requireOverrides = array_intersect_key($manifest['require'], $manifest['require-dev']); + if (!empty($requireOverrides)) { + $warnings[] = implode(', ', array_keys($requireOverrides)). " is required both in require and require-dev, this can lead to unexpected behavior"; + } + try { $loader = new ValidatingArrayLoader(new ArrayLoader()); if (!isset($manifest['version'])) { From 384ed2822d714618469a222e15f51161886aae5a Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 26 Dec 2013 16:35:20 +0100 Subject: [PATCH 232/238] Fire pre-update|install-cmd event as early as it should be, refs #2520 --- src/Composer/Installer.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 0970b75f4..af1540cef 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -173,6 +173,12 @@ class Installer unset($devRepo, $package); // end BC + if ($this->runScripts) { + // dispatch pre event + $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD; + $this->eventDispatcher->dispatchCommandEvent($eventName, $this->devMode); + } + $this->downloadManager->setPreferSource($this->preferSource); $this->downloadManager->setPreferDist($this->preferDist); @@ -199,12 +205,6 @@ class Installer $aliases = $this->getRootAliases(); $this->aliasPlatformPackages($platformRepo, $aliases); - if ($this->runScripts) { - // dispatch pre event - $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD; - $this->eventDispatcher->dispatchCommandEvent($eventName, $this->devMode); - } - try { $this->suggestedPackages = array(); $res = $this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases, $this->devMode); From 32b18a9409da1573c15bc3d3407a486ecd096a8c Mon Sep 17 00:00:00 2001 From: Marco Vito Moscaritolo Date: Thu, 26 Dec 2013 17:33:03 +0100 Subject: [PATCH 233/238] Fixed missing closed warning tag. In a console output a warning tag is not closed --- src/Composer/Installer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index af1540cef..2bbcefe7d 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -835,7 +835,7 @@ class Installer $depPackages = $pool->whatProvides($packageName); if (count($depPackages) == 0 && !in_array($packageName, $requiredPackageNames) && !in_array($packageName, array('nothing', 'lock'))) { - $this->io->write('Package "' . $packageName . '" listed for update is not installed. Ignoring.'); + $this->io->write('Package "' . $packageName . '" listed for update is not installed. Ignoring.'); } foreach ($depPackages as $depPackage) { From f85a366eb95b634fc63cdc3916ab1ded1e336b55 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 26 Dec 2013 17:40:52 +0100 Subject: [PATCH 234/238] Finalize new autoloader-suffix config value, refs #2524, fixes #1413 --- doc/04-schema.md | 2 ++ res/composer-schema.json | 2 +- src/Composer/Command/ConfigCommand.php | 12 ++++-------- src/Composer/Config.php | 2 +- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/doc/04-schema.md b/doc/04-schema.md index 3a250a418..56e787110 100644 --- a/doc/04-schema.md +++ b/doc/04-schema.md @@ -659,6 +659,8 @@ The following options are supported: * **prepend-autoloader:** Defaults to `true`. If false, the composer autoloader will not be prepended to existing autoloaders. This is sometimes required to fix interoperability issues with other autoloaders. +* **autoloader-suffix:** Defaults to `null`. String to be used as a suffix for + the generated Composer autoloader. When null a random one will be generated. * **github-domains:** Defaults to `["github.com"]`. A list of domains to use in github mode. This is used for GitHub Enterprise setups. * **notify-on-install:** Defaults to `true`. Composer allows repositories to diff --git a/res/composer-schema.json b/res/composer-schema.json index 180656c1d..827e41f5c 100644 --- a/res/composer-schema.json +++ b/res/composer-schema.json @@ -178,7 +178,7 @@ }, "autoloader-suffix": { "type": "string", - "description": "Optional string to be used as a suffix to the autoloader generator. When null a random one will be generated." + "description": "Optional string to be used as a suffix for the generated Composer autoloader. When null a random one will be generated." }, "prepend-autoloader": { "type": "boolean", diff --git a/src/Composer/Command/ConfigCommand.php b/src/Composer/Command/ConfigCommand.php index edc370a66..629cb7fec 100644 --- a/src/Composer/Command/ConfigCommand.php +++ b/src/Composer/Command/ConfigCommand.php @@ -254,18 +254,12 @@ EOT // handle config values $uniqueConfigValues = array( 'process-timeout' => array('is_numeric', 'intval'), - 'use-include-path' => array( - $booleanValidator, - $booleanNormalizer - ), + 'use-include-path' => array($booleanValidator, $booleanNormalizer), 'preferred-install' => array( function ($val) { return in_array($val, array('auto', 'source', 'dist'), true); }, function ($val) { return $val; } ), - 'notify-on-install' => array( - $booleanValidator, - $booleanNormalizer - ), + 'notify-on-install' => array($booleanValidator, $booleanNormalizer), 'vendor-dir' => array('is_string', function ($val) { return $val; }), 'bin-dir' => array('is_string', function ($val) { return $val; }), 'cache-dir' => array('is_string', function ($val) { return $val; }), @@ -288,6 +282,8 @@ EOT return $val !== 'false' && (bool) $val; } ), + 'autoloader-suffix' => array('is_string', function ($val) { return $val === 'null' ? null : $val; }), + 'prepend-autoloader' => array($booleanValidator, $booleanNormalizer), ); $multiConfigValues = array( 'github-protocols' => array( diff --git a/src/Composer/Config.php b/src/Composer/Config.php index 311c7de85..c54bc498c 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -35,7 +35,7 @@ class Config 'cache-files-ttl' => null, // fallback to cache-ttl 'cache-files-maxsize' => '300MiB', 'discard-changes' => false, - 'autoload-suffix' => null, + 'autoloader-suffix' => null, 'prepend-autoloader' => true, 'github-domains' => array('github.com'), ); From 6ead35f189f73f236c69755893181d7b77c90840 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 26 Dec 2013 19:09:06 +0100 Subject: [PATCH 235/238] Add version arg, docs for --rollback and reorganize the code, refs #2522 --- doc/03-cli.md | 11 +- src/Composer/Command/SelfUpdateCommand.php | 195 ++++++++++----------- 2 files changed, 105 insertions(+), 101 deletions(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index 38db3f925..f3fa574fe 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -269,11 +269,20 @@ command. It will replace your `composer.phar` with the latest version. $ php composer.phar self-update +If you would like to instead update to a specific release simply specify it: + + $ composer self-update 1.0.0-alpha7 + If you have installed composer for your entire system (see [global installation](00-intro.md#globally)), -you have to run the command with `root` privileges +you may have to run the command with `root` privileges $ sudo composer self-update +### Options + +* **--rollback (-r):** Rollback to the last version you had installed. +* **--clean-backups:** Delete old backups during an update. This makes the current version of composer the only backup available after the update. + ## config The `config` command allows you to edit some basic composer settings in either diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index d29d50b36..b6830650d 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -19,32 +19,19 @@ use Composer\Util\RemoteFilesystem; use Composer\Downloader\FilesystemException; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Output\OutputInterface; /** * @author Igor Wiedler + * @author Kevin Ran + * @author Jordi Boggiano */ class SelfUpdateCommand extends Command { - const ROLLBACK = 'rollback'; - const CLEAN_ROLLBACKS = 'clean-rollbacks'; const HOMEPAGE = 'getcomposer.org'; const OLD_INSTALL_EXT = '-old.phar'; - protected $remoteFS; - protected $latestVersion; - protected $homepageURL; - protected $localFilename; - - public function __construct($name = null) - { - parent::__construct($name); - $protocol = (extension_loaded('openssl') ? 'https' : 'http') . '://'; - $this->homepageURL = $protocol . self::HOMEPAGE; - $this->remoteFS = new RemoteFilesystem($this->getIO()); - $this->localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0]; - } - protected function configure() { $this @@ -52,8 +39,9 @@ class SelfUpdateCommand extends Command ->setAliases(array('selfupdate')) ->setDescription('Updates composer.phar to the latest version.') ->setDefinition(array( - new InputOption(self::ROLLBACK, 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer'), - new InputOption(self::CLEAN_ROLLBACKS, null, InputOption::VALUE_NONE, 'Delete old snapshots during an update. This makes the current version of composer the only rollback snapshot after the update') + new InputOption('rollback', 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer'), + new InputOption('clean-backups', null, InputOption::VALUE_NONE, 'Delete old backups during an update. This makes the current version of composer the only backup available after the update'), + new InputArgument('version', InputArgument::OPTIONAL, 'The version to update to'), )) ->setHelp(<<self-update command checks getcomposer.org for newer @@ -68,122 +56,140 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { + $baseUrl = (extension_loaded('openssl') ? 'https' : 'http') . '://' . self::HOMEPAGE; + $remoteFilesystem = new RemoteFilesystem($this->getIO()); $config = Factory::createConfig(); - $cacheDir = rtrim($config->get('cache-dir'), '/'); + $cacheDir = $config->get('cache-dir'); + $rollbackDir = $config->get('home'); + $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0]; - // Check if current dir is writable and if not try the cache dir from settings - $tmpDir = is_writable(dirname($this->localFilename))? dirname($this->localFilename) : $cacheDir; + // check if current dir is writable and if not try the cache dir from settings + $tmpDir = is_writable(dirname($localFilename)) ? dirname($localFilename) : $cacheDir; // check for permissions in local filesystem before start connection process if (!is_writable($tmpDir)) { throw new FilesystemException('Composer update failed: the "'.$tmpDir.'" directory used to download the temp file could not be written'); } - - if (!is_writable($this->localFilename)) { - throw new FilesystemException('Composer update failed: the "'.$this->localFilename.'" file could not be written'); + if (!is_writable($localFilename)) { + throw new FilesystemException('Composer update failed: the "'.$localFilename.'" file could not be written'); } - $rollbackVersion = false; - $rollbackDir = rtrim($config->get('home'), '/'); - - // rollback specified, get last phar - if ($input->getOption(self::ROLLBACK)) { - $rollbackVersion = $this->getLastVersion($rollbackDir); - if (!$rollbackVersion) { - throw new FilesystemException('Composer rollback failed: no installation to roll back to in "'.$rollbackDir.'"'); - } + if ($input->getOption('rollback')) { + return $this->rollback($output, $rollbackDir, $localFilename); } - // if a rollback version is specified, check for permissions and rollback installation - if ($rollbackVersion) { - if (!is_writable($rollbackDir)) { - throw new FilesystemException('Composer rollback failed: the "'.$rollbackDir.'" dir could not be written to'); - } + $latestVersion = trim($remoteFilesystem->getContents(self::HOMEPAGE, $baseUrl. '/version', false)); + $updateVersion = $input->getArgument('version') ?: $latestVersion; - $old = $rollbackDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT; + if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) { + $output->writeln('You can not update to a specific SHA-1 as those phars are not available for download'); - if (!is_file($old)) { - throw new FilesystemException('Composer rollback failed: "'.$old.'" could not be found'); - } - if (!is_readable($old)) { - throw new FilesystemException('Composer rollback failed: "'.$old.'" could not be read'); - } + return 1; } - $updateVersion = ($rollbackVersion)? $rollbackVersion : $this->getLatestVersion(); - if (Composer::VERSION === $updateVersion) { $output->writeln('You are already using composer version '.$updateVersion.'.'); return 0; } - $tempFilename = $tmpDir . '/' . basename($this->localFilename, '.phar').'-temp.phar'; - $backupFile = ($rollbackVersion)? false : $rollbackDir . '/' . Composer::VERSION . self::OLD_INSTALL_EXT; + $tempFilename = $tmpDir . '/' . basename($localFilename, '.phar').'-temp.phar'; + $backupFile = sprintf( + '%s/%s-%s%s', + $rollbackDir, + strtr(Composer::RELEASE_DATE, ' :', '_-'), + preg_replace('{^([0-9a-f]{7})[0-9a-f]{33}$}', '$1', Composer::VERSION), + self::OLD_INSTALL_EXT + ); - if ($rollbackVersion) { - rename($rollbackDir . "/{$rollbackVersion}" . self::OLD_INSTALL_EXT, $tempFilename); - $output->writeln(sprintf("Rolling back to cached version %s.", $rollbackVersion)); - } else { - $endpoint = ($updateVersion === $this->getLatestVersion()) ? '/composer.phar' : "/download/{$updateVersion}/composer.phar"; - $remoteFilename = $this->homepageURL . $endpoint; + $output->writeln(sprintf("Updating to version %s.", $updateVersion)); + $remoteFilename = $baseUrl . (preg_match('{^[0-9a-f]{40}$}', $updateVersion) ? '/composer.phar' : "/download/{$updateVersion}/composer.phar"); + $remoteFilesystem->copy(self::HOMEPAGE, $remoteFilename, $tempFilename); + if (!file_exists($tempFilename)) { + $output->writeln('The download of the new composer version failed for an unexpected reason'); - $output->writeln(sprintf("Updating to version %s.", $updateVersion)); + return 1; + } - $this->remoteFS->copy(self::HOMEPAGE, $remoteFilename, $tempFilename); + // remove saved installations of composer + if ($input->getOption('clean-backups')) { + $files = $this->getOldInstallationFiles($rollbackDir); - // @todo: handle snapshot versions not being found! - if (!file_exists($tempFilename)) { - $output->writeln('The download of the new composer version failed for an unexpected reason'); + if (!empty($files)) { + $fs = new Filesystem; - return 1; - } - - // remove saved installations of composer - if ($input->getOption(self::CLEAN_ROLLBACKS)) { - $files = $this->getOldInstallationFiles($rollbackDir); - - if (!empty($files)) { - $fs = new Filesystem; - - foreach ($files as $file) { - $output->writeln('Removing: '.$file); - $fs->remove($file); - } + foreach ($files as $file) { + $output->writeln('Removing: '.$file); + $fs->remove($file); } } } - if ($err = $this->setLocalPhar($tempFilename, $backupFile)) { + if ($err = $this->setLocalPhar($localFilename, $tempFilename, $backupFile)) { $output->writeln('The file is corrupted ('.$err->getMessage().').'); $output->writeln('Please re-run the self-update command to try again.'); return 1; } - if ($backupFile) { - $output->writeln('Saved rollback snapshot '.$backupFile); + if (file_exists($backupFile)) { + $output->writeln('Use composer self-update --rollback to return to version '.Composer::VERSION); + } else { + $output->writeln('A backup of the current version could not be written to '.$backupFile.', no rollback possible'); } } - protected function setLocalPhar($filename, $backupFile) + protected function rollback(OutputInterface $output, $rollbackDir, $localFilename) + { + $rollbackVersion = $this->getLastBackupVersion($rollbackDir); + if (!$rollbackVersion) { + throw new \UnexpectedValueException('Composer rollback failed: no installation to roll back to in "'.$rollbackDir.'"'); + } + + if (!is_writable($rollbackDir)) { + throw new FilesystemException('Composer rollback failed: the "'.$rollbackDir.'" dir could not be written to'); + } + + $old = $rollbackDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT; + + if (!is_file($old)) { + throw new FilesystemException('Composer rollback failed: "'.$old.'" could not be found'); + } + if (!is_readable($old)) { + throw new FilesystemException('Composer rollback failed: "'.$old.'" could not be read'); + } + + $oldFile = $rollbackDir . "/{$rollbackVersion}" . self::OLD_INSTALL_EXT; + $output->writeln(sprintf("Rolling back to version %s.", $rollbackVersion)); + if ($err = $this->setLocalPhar($localFilename, $oldFile)) { + $output->writeln('The backup file was corrupted ('.$err->getMessage().') and has been removed.'); + + return 1; + } + + return 0; + } + + protected function setLocalPhar($localFilename, $newFilename, $backupTarget = null) { try { - @chmod($filename, 0777 & ~umask()); + @chmod($newFilename, 0777 & ~umask()); // test the phar validity - $phar = new \Phar($filename); + $phar = new \Phar($newFilename); // free the variable to unlock the file unset($phar); // copy current file into installations dir - if ($backupFile) { - copy($this->localFilename, $backupFile); + if ($backupTarget && file_exists($localFilename)) { + @copy($localFilename, $backupTarget); } unset($phar); - rename($filename, $this->localFilename); + rename($newFilename, $localFilename); } catch (\Exception $e) { - @unlink($filename); + if ($backupTarget) { + @unlink($newFilename); + } if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) { throw $e; } @@ -192,31 +198,20 @@ EOT } } - protected function getLastVersion($rollbackDir) + protected function getLastBackupVersion($rollbackDir) { $files = $this->getOldInstallationFiles($rollbackDir); - if (empty($files)) { return false; } - $fileTimes = array_map('filemtime', $files); - $map = array_combine($fileTimes, $files); - $latest = max($fileTimes); - return basename($map[$latest], self::OLD_INSTALL_EXT); + sort($files); + + return basename(end($files), self::OLD_INSTALL_EXT); } protected function getOldInstallationFiles($rollbackDir) { - return glob($rollbackDir . '/*' . self::OLD_INSTALL_EXT); - } - - protected function getLatestVersion() - { - if (!$this->latestVersion) { - $this->latestVersion = trim($this->remoteFS->getContents(self::HOMEPAGE, $this->homepageURL. '/version', false)); - } - - return $this->latestVersion; + return glob($rollbackDir . '/*' . self::OLD_INSTALL_EXT) ?: array(); } } From 05af0352193f40448e3b3ce7610cb00affc57ce4 Mon Sep 17 00:00:00 2001 From: Luis Cordova Date: Fri, 27 Dec 2013 05:26:01 -0500 Subject: [PATCH 236/238] add documentation entry for archive command on 03-cli.md --- doc/03-cli.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/03-cli.md b/doc/03-cli.md index 38db3f925..8f914e583 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -395,6 +395,20 @@ problems. $ php composer.phar diagnose +## archive + +This command is used to generate a zip/tar archive for a given package in a +given version. It can also be used to archive your entire project without +excluded/ignored files. + + $ php composer.phar archive vendor/package --format=zip + +### Options + +* **--format (-f):** Format of the resulting archive: tar or zip (default: + "tar") +* **--dir:** Write the archive to this directory (default: ".") + ## help To get more information about a certain command, just use `help`. From 32eba1f142e86cec6570ec15a2176a8a78cc267b Mon Sep 17 00:00:00 2001 From: Luis Cordova Date: Fri, 27 Dec 2013 05:34:52 -0500 Subject: [PATCH 237/238] plug version example to the command call --- doc/03-cli.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index 8f914e583..2e56a00ee 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -401,7 +401,7 @@ This command is used to generate a zip/tar archive for a given package in a given version. It can also be used to archive your entire project without excluded/ignored files. - $ php composer.phar archive vendor/package --format=zip + $ php composer.phar archive vendor/package 2.0.21 --format=zip ### Options From 2f4df9d45901f691cd16719c64dc2bcc1ce392b2 Mon Sep 17 00:00:00 2001 From: Pascal Borreli Date: Fri, 27 Dec 2013 11:36:18 +0000 Subject: [PATCH 238/238] Fixed typos --- src/Composer/EventDispatcher/EventDispatcher.php | 4 ++-- src/Composer/Factory.php | 1 + src/Composer/Package/Version/VersionParser.php | 7 ++++--- src/Composer/Plugin/PluginManager.php | 6 ++++-- src/Composer/Repository/Vcs/VcsDriver.php | 1 + src/Composer/Util/NoProxyPattern.php | 4 ++-- src/Composer/Util/StreamContextFactory.php | 2 +- tests/Composer/Test/Package/BasePackageTest.php | 2 +- 8 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index 9c2aee91f..f1e94e6d5 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -72,8 +72,8 @@ class EventDispatcher /** * Dispatch a script event. * - * @param string $eventName The constant in ScriptEvents - * @param Event $event + * @param string $eventName The constant in ScriptEvents + * @param Script\Event $event */ public function dispatchScript($eventName, Script\Event $event = null) { diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 1db8c5864..f829cb459 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -285,6 +285,7 @@ class Factory /** * @param IOInterface $io * @param Config $config + * @param EventDispatcher $eventDispatcher * @return Repository\RepositoryManager */ protected function createRepositoryManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null) diff --git a/src/Composer/Package/Version/VersionParser.php b/src/Composer/Package/Version/VersionParser.php index ea37d821d..ee13b77a5 100644 --- a/src/Composer/Package/Version/VersionParser.php +++ b/src/Composer/Package/Version/VersionParser.php @@ -375,9 +375,10 @@ class VersionParser * * Support function for {@link parseConstraint()} * - * @param array $matches Array with version parts in array indexes 1,2,3,4 - * @param int $position 1,2,3,4 - which segment of the version to decrement - * @param string $pad The string to pad version parts after $position + * @param array $matches Array with version parts in array indexes 1,2,3,4 + * @param int $position 1,2,3,4 - which segment of the version to decrement + * @param int $increment + * @param string $pad The string to pad version parts after $position * @return string The new version */ private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0') diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index de4257e6a..d7c3ae07a 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -43,7 +43,9 @@ class PluginManager /** * Initializes plugin manager * - * @param Composer $composer + * @param Composer $composer + * @param IOInterface $io + * @param RepositoryInterface $globalRepository */ public function __construct(Composer $composer, IOInterface $io, RepositoryInterface $globalRepository = null) { @@ -126,7 +128,7 @@ class PluginManager $this->registerPackage($package); } - // Backward compatability + // Backward compatibility if ('composer-installer' === $package->getType()) { $this->registerPackage($package); } diff --git a/src/Composer/Repository/Vcs/VcsDriver.php b/src/Composer/Repository/Vcs/VcsDriver.php index 6effb2235..f1112074e 100644 --- a/src/Composer/Repository/Vcs/VcsDriver.php +++ b/src/Composer/Repository/Vcs/VcsDriver.php @@ -104,6 +104,7 @@ abstract class VcsDriver implements VcsDriverInterface /** * Return if current repository url is local * + * @param string $url * @return boolean Repository url is local */ protected static function isLocalUrl($url) diff --git a/src/Composer/Util/NoProxyPattern.php b/src/Composer/Util/NoProxyPattern.php index 16f7488d0..533dbc19c 100644 --- a/src/Composer/Util/NoProxyPattern.php +++ b/src/Composer/Util/NoProxyPattern.php @@ -107,7 +107,7 @@ class NoProxyPattern } /** - * Check an IP adress against a CIDR + * Check an IP address against a CIDR * * http://framework.zend.com/svn/framework/extras/incubator/library/ZendX/Whois/Adapter/Cidr.php * @@ -141,7 +141,7 @@ class NoProxyPattern $check = ($a << 24) + ($b << 16) + ($c << 8) + $d; // If the ip is within the range, including highest/lowest values, - // then it's witin the CIDR range + // then it's within the CIDR range return $check >= $low && $check <= $high; } } diff --git a/src/Composer/Util/StreamContextFactory.php b/src/Composer/Util/StreamContextFactory.php index 9ed131b02..1c3c20e44 100644 --- a/src/Composer/Util/StreamContextFactory.php +++ b/src/Composer/Util/StreamContextFactory.php @@ -120,7 +120,7 @@ final class StreamContextFactory } /** - * A bug in PHP prevents the headers from correctly beeing sent when a content-type header is present and + * A bug in PHP prevents the headers from correctly being sent when a content-type header is present and * NOT at the end of the array * * This method fixes the array by moving the content-type header to the end diff --git a/tests/Composer/Test/Package/BasePackageTest.php b/tests/Composer/Test/Package/BasePackageTest.php index 6e9f8f05a..1fe0ece84 100644 --- a/tests/Composer/Test/Package/BasePackageTest.php +++ b/tests/Composer/Test/Package/BasePackageTest.php @@ -25,7 +25,7 @@ class BasePackageTest extends \PHPUnit_Framework_TestCase try { $package->setRepository($repository); } catch (\Exception $e) { - $this->fail('Set againt the same repository is allowed.'); + $this->fail('Set against the same repository is allowed.'); } }