As preparation for composer plugins, rename custom installers to plugins

main
Nils Adermann 11 years ago
parent ef072ff8c0
commit 01a08a2ff3

@ -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 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 filesystem. As such, it does not require a dist or source key to be
installable. 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 installer for other packages that have a custom type. Read more in the
[dedicated article](articles/custom-installers.md). [dedicated article](articles/custom-installers.md).

@ -9,7 +9,7 @@
"required": true "required": true
}, },
"type": { "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" "type": "string"
}, },
"target-dir": { "target-dir": {
@ -180,7 +180,7 @@
}, },
"extra": { "extra": {
"type": ["object", "array"], "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 "additionalProperties": true
}, },
"autoload": { "autoload": {

@ -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('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('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-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-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('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('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deletion vcs folder.'),
@ -127,19 +127,19 @@ EOT
$preferDist, $preferDist,
!$input->getOption('no-dev'), !$input->getOption('no-dev'),
$input->getOption('repository-url'), $input->getOption('repository-url'),
$input->getOption('no-custom-installers'), $input->getOption('no-plugins'),
$input->getOption('no-scripts'), $input->getOption('no-scripts'),
$input->getOption('keep-vcs'), $input->getOption('keep-vcs'),
$input->getOption('no-progress') $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(); $oldCwd = getcwd();
if ($packageName !== null) { 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 { } else {
$installedFromVcs = false; $installedFromVcs = false;
} }
@ -158,8 +158,8 @@ EOT
->setDevMode($installDevPackages) ->setDevMode($installDevPackages)
->setRunScripts( ! $noScripts); ->setRunScripts( ! $noScripts);
if ($disableCustomInstallers) { if ($disablePlugins) {
$installer->disableCustomInstallers(); $installer->disablePlugins();
} }
if (!$installer->run()) { if (!$installer->run()) {
@ -226,7 +226,7 @@ EOT
return 0; 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); $stability = strtolower($stability);
if ($stability === 'rc') { if ($stability === 'rc') {
@ -285,8 +285,8 @@ EOT
$io->write('<info>Installing ' . $package->getName() . ' (' . VersionParser::formatVersion($package, false) . ')</info>'); $io->write('<info>Installing ' . $package->getName() . ' (' . VersionParser::formatVersion($package, false) . ')</info>');
if ($disableCustomInstallers) { if ($disablePlugins) {
$io->write('<info>Custom installers have been disabled.</info>'); $io->write('<info>Plugins have been disabled.</info>');
} }
if (0 === strpos($package->getPrettyVersion(), 'dev-') && in_array($package->getSourceType(), array('git', 'hg'))) { if (0 === strpos($package->getPrettyVersion(), 'dev-') && in_array($package->getSourceType(), array('git', 'hg'))) {

@ -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('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('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-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-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('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('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')) ->setOptimizeAutoloader($input->getOption('optimize-autoloader'))
; ;
if ($input->getOption('no-custom-installers')) { if ($input->getOption('no-plugins')) {
$install->disableCustomInstallers(); $install->disablePlugins();
} }
return $install->run() ? 0 : 1; return $install->run() ? 0 : 1;

@ -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('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-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('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-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('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('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')) ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $input->getArgument('packages'))
; ;
if ($input->getOption('no-custom-installers')) { if ($input->getOption('no-plugins')) {
$install->disableCustomInstallers(); $install->disablePlugins();
} }
return $install->run() ? 0 : 1; return $install->run() ? 0 : 1;

@ -370,7 +370,7 @@ class Factory
{ {
$im->addInstaller(new Installer\LibraryInstaller($io, $composer, null)); $im->addInstaller(new Installer\LibraryInstaller($io, $composer, null));
$im->addInstaller(new Installer\PearInstaller($io, $composer, 'pear-library')); $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)); $im->addInstaller(new Installer\MetapackageInstaller($io));
} }

@ -461,7 +461,7 @@ class Installer
$this->io->write('Nothing to install or update'); $this->io->write('Nothing to install or update');
} }
$operations = $this->moveCustomInstallersToFront($operations); $operations = $this->movePluginsToFront($operations);
foreach ($operations as $operation) { foreach ($operations as $operation) {
// collect suggestions // 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 * that those are installed / updated first; else it would lead to packages
* being installed multiple times in different folders, when running Composer * being installed multiple times in different folders, when running Composer
* twice. * twice.
@ -552,7 +552,7 @@ class Installer
* @param OperationInterface[] $operations * @param OperationInterface[] $operations
* @return OperationInterface[] reordered operation list * @return OperationInterface[] reordered operation list
*/ */
private function moveCustomInstallersToFront(array $operations) private function movePluginsToFront(array $operations)
{ {
$installerOps = array(); $installerOps = array();
foreach ($operations as $idx => $op) { foreach ($operations as $idx => $op) {
@ -564,7 +564,7 @@ class Installer
continue; continue;
} }
if ($package->getRequires() === array() && $package->getType() === 'composer-installer') { if ($package->getRequires() === array() && ($package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer')) {
$installerOps[] = $op; $installerOps[] = $op;
unset($operations[$idx]); 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 * Call this if you want to ensure that third-party code never gets
* executed. The default is to automatically install, and execute * executed. The default is to automatically install, and execute
@ -1063,9 +1063,9 @@ class Installer
* *
* @return Installer * @return Installer
*/ */
public function disableCustomInstallers() public function disablePlugins()
{ {
$this->installationManager->disableCustomInstallers(); $this->installationManager->disablePlugins();
return $this; return $this;
} }

@ -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 * deactivating the installer for them. This ensure that no third-party
* code is ever executed. * code is ever executed.
*/ */
public function disableCustomInstallers() public function disablePlugins()
{ {
foreach ($this->installers as $i => $installer) { foreach ($this->installers as $i => $installer) {
if (!$installer instanceof InstallerInstaller) { if (!$installer instanceof PluginInstaller) {
continue; continue;
} }

@ -23,7 +23,7 @@ use Composer\Package\PackageInterface;
* *
* @author Jordi Boggiano <j.boggiano@seld.be> * @author Jordi Boggiano <j.boggiano@seld.be>
*/ */
class InstallerInstaller extends LibraryInstaller class PluginInstaller extends LibraryInstaller
{ {
private $installationManager; private $installationManager;
private static $classCounter = 0; private static $classCounter = 0;
@ -37,7 +37,7 @@ class InstallerInstaller extends LibraryInstaller
*/ */
public function __construct(IOInterface $io, Composer $composer, $type = 'library') public function __construct(IOInterface $io, Composer $composer, $type = 'library')
{ {
parent::__construct($io, $composer, 'composer-installer'); parent::__construct($io, $composer, $type);
$this->installationManager = $composer->getInstallationManager(); $this->installationManager = $composer->getInstallationManager();
$repo = $composer->getRepositoryManager()->getLocalRepository(); $repo = $composer->getRepositoryManager()->getLocalRepository();
@ -45,6 +45,9 @@ class InstallerInstaller extends LibraryInstaller
if ('composer-installer' === $package->getType()) { if ('composer-installer' === $package->getType()) {
$this->registerInstaller($package); $this->registerInstaller($package);
} }
if ('composer-plugin' === $package->getType()) {
$this->registerInstaller($package);
}
} }
} }
@ -55,7 +58,7 @@ class InstallerInstaller extends LibraryInstaller
{ {
$extra = $package->getExtra(); $extra = $package->getExtra();
if (empty($extra['class'])) { 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); parent::install($repo, $package);
@ -69,7 +72,7 @@ class InstallerInstaller extends LibraryInstaller
{ {
$extra = $target->getExtra(); $extra = $target->getExtra();
if (empty($extra['class'])) { 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); parent::update($repo, $initial, $target);

@ -8,8 +8,8 @@ Composer installers are installed first if they have no requirements
"package": [ "package": [
{ "name": "pkg", "version": "1.0.0" }, { "name": "pkg", "version": "1.0.0" },
{ "name": "pkg2", "version": "1.0.0" }, { "name": "pkg2", "version": "1.0.0" },
{ "name": "inst", "version": "1.0.0", "type": "composer-installer" }, { "name": "inst", "version": "1.0.0", "type": "composer-plugin" },
{ "name": "inst2", "version": "1.0.0", "type": "composer-installer", "require": { "pkg2": "*" } } { "name": "inst2", "version": "1.0.0", "type": "composer-plugin", "require": { "pkg2": "*" } }
] ]
} }
], ],

@ -1,7 +1,7 @@
{ {
"name": "", "name": "",
"version": "1.0.0", "version": "1.0.0",
"type": "composer-installer", "type": "composer-plugin",
"autoload": { "psr-0": { "Installer": "" } }, "autoload": { "psr-0": { "Installer": "" } },
"extra": { "extra": {
"class": "Installer\\Custom" "class": "Installer\\Custom"

@ -1,7 +1,7 @@
{ {
"name": "", "name": "",
"version": "2.0.0", "version": "2.0.0",
"type": "composer-installer", "type": "composer-plugin",
"autoload": { "psr-0": { "Installer": "" } }, "autoload": { "psr-0": { "Installer": "" } },
"extra": { "extra": {
"class": "Installer\\Custom2" "class": "Installer\\Custom2"

@ -1,7 +1,7 @@
{ {
"name": "", "name": "",
"version": "3.0.0", "version": "3.0.0",
"type": "composer-installer", "type": "composer-plugin",
"autoload": { "psr-0": { "Installer": "" } }, "autoload": { "psr-0": { "Installer": "" } },
"extra": { "extra": {
"class": "Installer\\Custom2" "class": "Installer\\Custom2"

@ -1,7 +1,7 @@
{ {
"name": "", "name": "",
"version": "4.0.0", "version": "4.0.0",
"type": "composer-installer", "type": "composer-plugin",
"autoload": { "psr-0": { "Installer": "" } }, "autoload": { "psr-0": { "Installer": "" } },
"extra": { "extra": {
"class": [ "class": [

@ -14,13 +14,13 @@ namespace Composer\Test\Installer;
use Composer\Composer; use Composer\Composer;
use Composer\Config; use Composer\Config;
use Composer\Installer\InstallerInstaller; use Composer\Installer\PluginInstaller;
use Composer\Package\Loader\JsonLoader; use Composer\Package\Loader\JsonLoader;
use Composer\Package\Loader\ArrayLoader; use Composer\Package\Loader\ArrayLoader;
use Composer\Package\PackageInterface; use Composer\Package\PackageInterface;
use Composer\Autoload\AutoloadGenerator; use Composer\Autoload\AutoloadGenerator;
class InstallerInstallerTest extends \PHPUnit_Framework_TestCase class PluginInstallerTest extends \PHPUnit_Framework_TestCase
{ {
protected $composer; protected $composer;
protected $packages; protected $packages;
@ -81,7 +81,7 @@ class InstallerInstallerTest extends \PHPUnit_Framework_TestCase
->expects($this->once()) ->expects($this->once())
->method('getPackages') ->method('getPackages')
->will($this->returnValue(array())); ->will($this->returnValue(array()));
$installer = new InstallerInstallerMock($this->io, $this->composer); $installer = new PluginInstallerMock($this->io, $this->composer);
$test = $this; $test = $this;
$this->im $this->im
@ -101,7 +101,7 @@ class InstallerInstallerTest extends \PHPUnit_Framework_TestCase
->method('getPackages') ->method('getPackages')
->will($this->returnValue(array())); ->will($this->returnValue(array()));
$installer = new InstallerInstallerMock($this->io, $this->composer); $installer = new PluginInstallerMock($this->io, $this->composer);
$test = $this; $test = $this;
@ -134,7 +134,7 @@ class InstallerInstallerTest extends \PHPUnit_Framework_TestCase
->expects($this->exactly(2)) ->expects($this->exactly(2))
->method('hasPackage') ->method('hasPackage')
->will($this->onConsecutiveCalls(true, false)); ->will($this->onConsecutiveCalls(true, false));
$installer = new InstallerInstallerMock($this->io, $this->composer); $installer = new PluginInstallerMock($this->io, $this->composer);
$test = $this; $test = $this;
$this->im $this->im
@ -157,7 +157,7 @@ class InstallerInstallerTest extends \PHPUnit_Framework_TestCase
->expects($this->exactly(2)) ->expects($this->exactly(2))
->method('hasPackage') ->method('hasPackage')
->will($this->onConsecutiveCalls(true, false)); ->will($this->onConsecutiveCalls(true, false));
$installer = new InstallerInstallerMock($this->io, $this->composer); $installer = new PluginInstallerMock($this->io, $this->composer);
$test = $this; $test = $this;
$this->im $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) public function getInstallPath(PackageInterface $package)
{ {
Loading…
Cancel
Save