generalredneck/drupal-libraries-installer-plugin

Incompatibility with wikimedia/composer-merge-plugin

lpalgarvio opened this issue · 1 comments

Hello

Theres an incompatibility with wikimedia/composer-merge-plugin, a composer plugin used to merge in memory other composer.json files when issued install/update, including the extras key (where we have the drupal-libraries key). This normally involves at least composer.json and composer.local.json.
https://github.com/wikimedia/composer-merge-plugin

EDIT: There's a similar behavior with drupal-libraries-installer-plugin:
https://github.com/mnsami/composer-custom-directory-installer
mnsami/composer-custom-directory-installer#16

What happens is basically drupal-libraries-installer-plugin does not pick this merge.

If you place a print_r or file_put_contents in composer-merge-plugin/src/Merga/ExtraPackage.php in function mergeExtra, you will notice that the merge does happen. But after drupal-libraries-installer-plugin is run, so it never catches the merge.

Also, by using non-assoc array for libraries in drupal-libraries['libraries'], even if the merge would happen before, these would get replaced, as they are indexed numerically. Which i was noticing with my print_r/file_put_contents in composer-merge-plugin/src/Merga/ExtraPackage.php, function mergeExtra.

Therefor, the array must be built like this, with an associative array (indexed by keys):

{
  "extra": {
    "drupal-libraries": {
      "libraries": {
        "components/backbone": {
          "name": "backbone",
          "package": "components/backbone"
        },
        "ckeditor/ckeditor": {
          "name": "ckeditor",
          "package": "ckeditor/ckeditor"
        }
    }
  }
}

Then it is fine for a merge.
For simplicity, you can from here eventually turn it into this:

{
  "extra": {
    "drupal-libraries": {
      "libraries": {
        "components/backbone": "backbone",
        "ckeditor/ckeditor": "ckeditor"
      }
    }
  }
}

Thus removing the need for an extra level in the array.

So i did this fix in my json files and now they are merging.
However, drupal-libraries-installer-plugin still does not catch it.

I researched a bit and couldn't find a way to prioritize/give weight/re-order plugin execution.
Having this in this specific order is not enough:

  "require": {
    "wikimedia/composer-merge-plugin": "~1.3",
    "cweagans/composer-patches": "~1.3",
    "composer/installers": "~1.0",
    "robloach/component-installer": "~0.2",
    "derhasi/composer-preserve-paths": "~0.1",
    "davidbarratt/drupal-structure": "~1.0@alpha",
    "drupal/drupal-library-installer-plugin": "~0.3",
    "drupal/drupal": "7.*"
  },

So i researched further.
I tried ProcessExecutor (use Composer\Util\ProcessExecutor)
Combined with EventSubscriberInterface (use Composer\EventDispatcher\EventSubscriberInterface), function getSubscribedEvents.
(and use Composer\Installer\PackageEvents and use Composer\Script\ScriptEvents).

For that i used events:
ScriptEvents::PRE_INSTALL_CMD
ScriptEvents::PRE_UPDATE_CMD
ScriptEvents::POST_INSTALL_CMD
ScriptEvents::POST_UPDATE_CMD
PackageEvents::PRE_PACKAGE_INSTALL
PackageEvents::PRE_PACKAGE_UPDATE
PackageEvents::POST_PACKAGE_INSTALL
PackageEvents::POST_PACKAGE_UPDATE

I got it to load drupal-libraries-installer-plugin and with a print_r/file_put_contents in DrupalLibraryInstaller function __construct, i was finally seeing the new picked merged json, with all the missing libraries.

However this would only happen on POST events.
Essentially voiding the use of getInstallPath.

I tried moving code around, functions, etc, but i could not manage to get it working.

I also tried adding the merge plugin to the autoloader and requirements of drupal-libraries-installer-plugin in composer.json, but it had no effect, and still launched drupal-libraries-installer-plugin first, to my understanding and frustration.

Do you have any ideas?

Here's a hacked version of your plugin demonstrating what i tried.
I took ideas from cweagans/composer-patches.

drupal-library-installer-plugin.tar.gz