diff --git a/bundler/lib/bundler/definition.rb b/bundler/lib/bundler/definition.rb index 564530a98cdf..b6809eef7ca6 100644 --- a/bundler/lib/bundler/definition.rb +++ b/bundler/lib/bundler/definition.rb @@ -34,7 +34,10 @@ def self.build(gemfile, lockfile, unlock) raise GemfileNotFound, "#{gemfile} not found" unless gemfile.file? - Dsl.evaluate(gemfile, lockfile, unlock) + Plugin.hook(Plugin::Events::GEM_BEFORE_EVAL, gemfile, lockfile, unlock) + Dsl.evaluate(gemfile, lockfile, unlock).tap do |definition| + Plugin.hook(Plugin::Events::GEM_AFTER_EVAL, definition) + end end # diff --git a/bundler/lib/bundler/plugin/events.rb b/bundler/lib/bundler/plugin/events.rb index bc037d1af507..47f689f5f375 100644 --- a/bundler/lib/bundler/plugin/events.rb +++ b/bundler/lib/bundler/plugin/events.rb @@ -56,6 +56,18 @@ def self.defined_event?(event) # Includes an Array of Bundler::Dependency objects # GEM_AFTER_INSTALL_ALL = "after-install-all" define :GEM_AFTER_INSTALL_ALL, "after-install-all" + + # @!parse + # A hook called before the Gemfile is evaluated + # Includes the Gemfile name, the Lockfile name, and the unlock options + # GEM_BEFORE_EVAL = "before-eval" + define :GEM_BEFORE_EVAL, "before-eval" + + # @!parse + # A hook called after the Gemfile is evaluated + # Includes a Bundler::Definition + # GEM_AFTER_EVAL = "after-eval" + define :GEM_AFTER_EVAL, "after-eval" end end end diff --git a/bundler/spec/plugins/hook_spec.rb b/bundler/spec/plugins/hook_spec.rb index 72feb14d84ee..577a1f2ed380 100644 --- a/bundler/spec/plugins/hook_spec.rb +++ b/bundler/spec/plugins/hook_spec.rb @@ -106,4 +106,55 @@ expect(out).to include "installed gem rack : installed" end end + + context "before-eval hook" do + before do + build_repo2 do + build_plugin "before-eval-plugin" do |s| + s.write "plugins.rb", <<-RUBY + Bundler::Plugin::API.hook Bundler::Plugin::Events::GEM_BEFORE_EVAL do |gemfile, lockfile| + puts "hooked eval start of \#{File.basename(gemfile)} to \#{File.basename(lockfile)}" + end + RUBY + end + end + + bundle "plugin install before-eval-plugin --source #{file_uri_for(gem_repo2)}" + end + + it "runs before all rubygems are installed" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rake" + G + + expect(out).to include "hooked eval start of Gemfile to Gemfile.lock" + end + end + + context "after-eval hook" do + before do + build_repo2 do + build_plugin "after-eval-plugin" do |s| + s.write "plugins.rb", <<-RUBY + Bundler::Plugin::API.hook Bundler::Plugin::Events::GEM_AFTER_EVAL do |defn| + puts "hooked eval after with gems \#{defn.dependencies.map(&:name).join(", ")}" + end + RUBY + end + end + + bundle "plugin install after-eval-plugin --source #{file_uri_for(gem_repo2)}" + end + + it "runs before all rubygems are installed" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "rack" + gem "rake" + G + + expect(out).to include "hooked eval after with gems rack, rake" + end + end end