Skip to content

Commit

Permalink
Merge pull request #376 from thomscode/disable-installers
Browse files Browse the repository at this point in the history
Fixes #67: Adds ability to disable all or certain installers
  • Loading branch information
alcohol authored Apr 5, 2018
2 parents a118c5b + 78eb8ca commit 5d15e4e
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 18 deletions.
47 changes: 46 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ is not needed to install packages with these frameworks:
| Decibel | `decibel-app`
| DokuWiki | `dokuwiki-plugin`<br>`dokuwiki-template`
| Dolibarr | `dolibarr-module`
| Drupal | <b>`drupal-core`<br>`drupal-module`<br>`drupal-theme`</b><br>`drupal-library`<br>`drupal-profile`<br>`drupal-drush`
| Drupal | <b>`drupal-core`<br>`drupal-module`<br>`drupal-theme`</b><br>`drupal-library`<br>`drupal-profile`<br>`drupal-drush`<br>`drupal-custom-theme`<br>`drupal-custom-module`
| Elgg | `elgg-plugin`
| Eliasis | `eliasis-component`<br>`eliasis-module`<br>`eliasis-plugin`<br>`eliasis-template`
| ExpressionEngine 3 | `ee3-addon`<br>`ee3-theme`
Expand Down Expand Up @@ -207,6 +207,51 @@ will allow this:
Please note the name entered into `installer-name` will be the final and will
not be inflected.

## Disabling installers

There may be time when you want to disable one or more installers from `composer/installers`.
For example, if you are managing a package or project that uses a framework specific installer that
conflicts with `composer/installers` but also have a dependency on a package that depends on `composer/installers`.

Installers can be disabled for your project by specifying the extra
`installer-disable` property. If set to `true`, `"all"`, or `"*"` all installers
will be disabled.

```json
{
"extra": {
"installer-disable": true
}
}
```

Otherwise a single installer or an array of installers may be specified.

```json
{
"extra": {
"installer-disable": [
"cakephp",
"drupal"
]
}
}
```

**Note:** Using a global disable value (`true`, `"all"`, or `"*"`) will take precedence over individual
installer names if used in an array. The example below will disable all installers.

```json
{
"extra": {
"installer-disable": [
"drupal",
"all"
]
}
}
```

## Should we allow dynamic package types or paths? No.

What are they? The ability for a package author to determine where a package
Expand Down
2 changes: 1 addition & 1 deletion src/Composer/Installers/DrupalInstaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ class DrupalInstaller extends BaseInstaller
'profile' => 'profiles/{$name}/',
'drush' => 'drush/{$name}/',
'custom-theme' => 'themes/custom/{$name}/',
'custom-module' => 'modules/custom/{$name}',
'custom-module' => 'modules/custom/{$name}/',
);
}
75 changes: 74 additions & 1 deletion src/Composer/Installers/Installer.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
<?php

namespace Composer\Installers;

use Composer\IO\IOInterface;
use Composer\Composer;
use Composer\Installer\BinaryInstaller;
use Composer\Installer\LibraryInstaller;
use Composer\IO\IOInterface;
use Composer\Package\PackageInterface;
use Composer\Repository\InstalledRepositoryInterface;
use Composer\Util\Filesystem;

class Installer extends LibraryInstaller
{

/**
* Package types to installer class map
*
Expand Down Expand Up @@ -103,6 +108,30 @@ class Installer extends LibraryInstaller
'prestashop' => 'PrestashopInstaller'
);

/**
* Installer constructor.
*
* Disables installers specified in main composer extra installer-disable
* list
*
* @param IOInterface $io
* @param Composer $composer
* @param string $type
* @param Filesystem|null $filesystem
* @param BinaryInstaller|null $binaryInstaller
*/
public function __construct(
IOInterface $io,
Composer $composer,
$type = 'library',
Filesystem $filesystem = null,
BinaryInstaller $binaryInstaller = null
) {
parent::__construct($io, $composer, $type, $filesystem,
$binaryInstaller);
$this->removeDisabledInstallers();
}

/**
* {@inheritDoc}
*/
Expand Down Expand Up @@ -198,4 +227,48 @@ private function getIO()
{
return $this->io;
}

/**
* Look for installers set to be disabled in composer's extra config and
* remove them from the list of supported installers.
*
* Globals:
* - true, "all", and "*" - disable all installers.
* - false - enable all installers (useful with
* wikimedia/composer-merge-plugin or similar)
*
* @return void
*/
protected function removeDisabledInstallers()
{
$extra = $this->composer->getPackage()->getExtra();

if (!isset($extra['installer-disable']) || $extra['installer-disable'] === false) {
// No installers are disabled
return;
}

// Get installers to disable
$disable = $extra['installer-disable'];

// Ensure $disabled is an array
if (!is_array($disable)) {
$disable = array($disable);
}

// Check which installers should be disabled
$all = array(true, "all", "*");
$intersect = array_intersect($all, $disable);
if (!empty($intersect)) {
// Disable all installers
$this->supportedTypes = array();
} else {
// Disable specified installers
foreach ($disable as $key => $installer) {
if (is_string($installer) && key_exists($installer, $this->supportedTypes)) {
unset($this->supportedTypes[$installer]);
}
}
}
}
}
79 changes: 64 additions & 15 deletions tests/Composer/Installers/Test/InstallerTest.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<?php
namespace Composer\Installers\Test;

use Composer\Composer;
use Composer\Config;
use Composer\Installers\Installer;
use Composer\Util\Filesystem;
use Composer\Package\Package;
use Composer\Package\RootPackage;
use Composer\Composer;
use Composer\Config;
use Composer\Util\Filesystem;

class InstallerTest extends TestCase
{
Expand Down Expand Up @@ -52,6 +52,10 @@ public function setUp()

$this->repository = $this->getMock('Composer\Repository\InstalledRepositoryInterface');
$this->io = $this->getMock('Composer\IO\IOInterface');

$consumerPackage = new RootPackage('foo/bar', '1.0.0', '1.0.0');
$this->composer->setPackage($consumerPackage);

}

/**
Expand Down Expand Up @@ -116,7 +120,14 @@ public function dataForTestSupport()
array('decibel-app', true),
array('dokuwiki-plugin', true),
array('dokuwiki-template', true),
array('drupal-core', true),
array('drupal-module', true),
array('drupal-theme', true),
array('drupal-library', true),
array('drupal-profile', true),
array('drupal-drush', true),
array('drupal-custom-theme', true),
array('drupal-custom-module', true),
array('dolibarr-module', true),
array('ee3-theme', true),
array('ee3-addon', true),
Expand Down Expand Up @@ -279,10 +290,14 @@ public function dataForTestInstallPath()
array('dokuwiki-plugin', 'lib/plugins/someplugin/', 'author/someplugin'),
array('dokuwiki-template', 'lib/tpl/sometemplate/', 'author/sometemplate'),
array('dolibarr-module', 'htdocs/custom/my_module/', 'shama/my_module'),
array('drupal-core', 'core/', 'drupal/core'),
array('drupal-module', 'modules/my_module/', 'shama/my_module'),
array('drupal-theme', 'themes/my_module/', 'shama/my_module'),
array('drupal-profile', 'profiles/my_module/', 'shama/my_module'),
array('drupal-drush', 'drush/my_module/', 'shama/my_module'),
array('drupal-theme', 'themes/my_theme/', 'shama/my_theme'),
array('drupal-library', 'libraries/my_library/', 'shama/my_library'),
array('drupal-profile', 'profiles/my_profile/', 'shama/my_profile'),
array('drupal-drush', 'drush/my_command/', 'shama/my_command'),
array('drupal-custom-theme', 'themes/custom/my_theme/', 'shama/my_theme'),
array('drupal-custom-module', 'modules/custom/my_module/', 'shama/my_module'),
array('elgg-plugin', 'mod/sample_plugin/', 'test/sample_plugin'),
array('eliasis-component', 'components/my_component/', 'shama/my_component'),
array('eliasis-module', 'modules/my_module/', 'shama/my_module'),
Expand Down Expand Up @@ -433,9 +448,7 @@ public function testCustomInstallPath()
$installer = new Installer($this->io, $this->composer);
$package = new Package('shama/ftp', '1.0.0', '1.0.0');
$package->setType('cakephp-plugin');
$consumerPackage = new RootPackage('foo/bar', '1.0.0', '1.0.0');
$this->composer->setPackage($consumerPackage);
$consumerPackage->setExtra(array(
$this->composer->getPackage()->setExtra(array(
'installer-paths' => array(
'my/custom/path/{$name}/' => array(
'shama/ftp',
Expand Down Expand Up @@ -470,9 +483,7 @@ public function testCustomTypePath()
$installer = new Installer($this->io, $this->composer);
$package = new Package('slbmeh/my_plugin', '1.0.0', '1.0.0');
$package->setType('wordpress-plugin');
$consumerPackage = new RootPackage('foo/bar', '1.0.0', '1.0.0');
$this->composer->setPackage($consumerPackage);
$consumerPackage->setExtra(array(
$this->composer->getPackage()->setExtra(array(
'installer-paths' => array(
'my/custom/path/{$name}/' => array(
'type:wordpress-plugin'
Expand All @@ -491,9 +502,7 @@ public function testVendorPath()
$installer = new Installer($this->io, $this->composer);
$package = new Package('penyaskito/my_module', '1.0.0', '1.0.0');
$package->setType('drupal-module');
$consumerPackage = new RootPackage('drupal/drupal', '1.0.0', '1.0.0');
$this->composer->setPackage($consumerPackage);
$consumerPackage->setExtra(array(
$this->composer->getPackage()->setExtra(array(
'installer-paths' => array(
'modules/custom/{$name}/' => array(
'vendor:penyaskito'
Expand Down Expand Up @@ -549,4 +558,44 @@ public function testUninstallAndDeletePackageFromLocalRepo()

$installer->uninstall($repo, $package);
}

/**
* testDisabledInstallers
*
* @dataProvider dataForTestDisabledInstallers
*/
public function testDisabledInstallers($disabled, $type, $expected)
{
$this->composer->getPackage()->setExtra(array(
'installer-disable' => $disabled,
));
$this->testSupports($type, $expected);
}

/**
* dataForTestDisabledInstallers
*
* @return array
*/
public function dataForTestDisabledInstallers()
{
return array(
array(false, "drupal-module", true),
array(true, "drupal-module", false),
array("true", "drupal-module", true),
array("all", "drupal-module", false),
array("*", "drupal-module", false),
array("cakephp", "drupal-module", true),
array("drupal", "cakephp-plugin", true),
array("cakephp", "cakephp-plugin", false),
array("drupal", "drupal-module", false),
array(array("drupal", "cakephp"), "cakephp-plugin", false),
array(array("drupal", "cakephp"), "drupal-module", false),
array(array("cakephp", true), "drupal-module", false),
array(array("cakephp", "all"), "drupal-module", false),
array(array("cakephp", "*"), "drupal-module", false),
array(array("cakephp", "true"), "drupal-module", true),
array(array("drupal", "true"), "cakephp-plugin", true),
);
}
}

0 comments on commit 5d15e4e

Please sign in to comment.