ManageIQ / bundler-inject

A bundler plugin that allows extension of a project with personal and overridden gems
Apache License 2.0
21 stars 8 forks source link

[POC][WIP] Inject via a Bundler::Plugin.hook #2

Closed NickLaMuro closed 5 years ago

NickLaMuro commented 5 years ago

NOTE: Does not work! Read below for details!

What this does

This changes a few things:

First, we use the documented for adding a hook:

Bundler::Plugin.add_hook('before-install-all')

from the bundler docs: https://bundler.io/v2.0/guides/bundler_plugins.html

Second, because of the first, this means that we have to update how we load the DslPatch, since the before-install-all is triggered after the second pass of eval_gemfile of the Gemfile (first being to install plugins):

https://github.com/bundler/bundler/blob/d44d803357506895555ff97f73e60d593820a0de/lib/bundler/installer.rb#L24

(<= v1.16.x)

https://github.com/bundler/bundler/blob/c793c38a55559677573d28d4bfadd811e8508b48/lib/bundler/installer.rb#L24

This means that we need to do our own eval_gemfile anyway, so we rebuild a Bundler::Dsl.builder based off the Bundler.definition, and then run eval_gemfile on that to update the variables tied to the Bundler.definition (updating sources, dependencies, etc. as needed).

Why it doesn't work

Unfortunately, this hook only runs on install, so whenever a bundle exec ... or bundler/setup is called, we don't include the eval_gemfile of anything in the bundler.d dirs.

This does bundle install and bundle update every time, so it is a decent start, but probably needs to be re-worked to use a different method.

Possible alternative: Using a "source plugin hack"

The other option for plugins is "source plugins", which inject a new Bundler::Source::* into bundler's repertoire. This should get triggered every time when a bundle exec triggered as well, and we would just have to do something like the following:

Gemfile

plugin 'bundler-inject' # ...
gem 'bundler-inject', :type => :bundler_inject, :require => :false

And then the source just creates a dummy dependecy when installing during the real pass, but can also activate the Bundler::Inject code as well when the source type code is loaded.

At least in theory, it should work...