summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsutosh Palai <asupalai@gmail.com>2016-07-19 22:49:42 +0530
committerAsutosh Palai <asupalai@gmail.com>2016-08-16 09:41:15 +0530
commit5977342e7ac4600051e7a38977a4e7c7cb420cc1 (patch)
tree57966a0c907829e449a178d485021b8bd7e47554
parentf81446d095c60a162ec57c18fd62c29e9567a0a2 (diff)
downloadbundler-5977342e7ac4600051e7a38977a4e7c7cb420cc1.tar.gz
Hooks implementation
-rw-r--r--lib/bundler/cli/install.rb2
-rw-r--r--lib/bundler/plugin.rb23
-rw-r--r--lib/bundler/plugin/api.rb4
-rw-r--r--lib/bundler/plugin/index.rb17
-rw-r--r--spec/plugins/hook_spec.rb28
5 files changed, 69 insertions, 5 deletions
diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb
index 5c7b8c5b0b..f95b2779c2 100644
--- a/lib/bundler/cli/install.rb
+++ b/lib/bundler/cli/install.rb
@@ -68,6 +68,8 @@ module Bundler
definition = Bundler.definition
definition.validate_ruby!
+ Plugin.hook("before-install-all", definition.dependencies)
+
installer = Installer.install(Bundler.root, definition, options)
Bundler.load.cache if Bundler.app_cache.exist? && !options["no-cache"] && !Bundler.settings[:frozen]
diff --git a/lib/bundler/plugin.rb b/lib/bundler/plugin.rb
index cd3843fc0d..e55f0fcf1b 100644
--- a/lib/bundler/plugin.rb
+++ b/lib/bundler/plugin.rb
@@ -18,6 +18,8 @@ module Bundler
@commands = {}
@sources = {}
+ @hooks = {}
+ @loaded = []
# Installs a new plugin by the given name
#
@@ -137,6 +139,19 @@ module Bundler
src.new(locked_opts.merge("uri" => locked_opts["remote"]))
end
+ def add_hook(event, &block)
+ (@hooks[event.to_s] ||= []) << block
+ end
+
+ def hook(event, *args)
+ plugins = index.hook_plugins(event)
+ return unless plugins
+
+ (plugins - @loaded).each {|name| load_plugin(name) }
+
+ @hooks[event].each {|blk| blk.call(*args) }
+ end
+
# currently only intended for specs
#
# @return [String, nil] installed path
@@ -190,9 +205,11 @@ module Bundler
def register_plugin(name, spec, optional_plugin = false)
commands = @commands
sources = @sources
+ hooks = @hooks
@commands = {}
@sources = {}
+ @hooks = {}
load_paths = spec.load_paths
add_to_load_path(load_paths)
@@ -208,12 +225,14 @@ module Bundler
Bundler.rm_rf(path)
false
else
- index.register_plugin name, path.to_s, load_paths, @commands.keys, @sources.keys
+ index.register_plugin name, path.to_s, load_paths, @commands.keys,
+ @sources.keys, @hooks.keys
true
end
ensure
@commands = commands
@sources = sources
+ @hooks = hooks
end
# Executes the plugins.rb file
@@ -228,6 +247,8 @@ module Bundler
add_to_load_path(index.load_paths(name))
load path.join(PLUGIN_FILE_NAME)
+
+ @loaded << name
rescue => e
Bundler.ui.error "Failed loading plugin #{name}: #{e.message}"
raise
diff --git a/lib/bundler/plugin/api.rb b/lib/bundler/plugin/api.rb
index 9ff4b7385b..5bd8792e55 100644
--- a/lib/bundler/plugin/api.rb
+++ b/lib/bundler/plugin/api.rb
@@ -44,6 +44,10 @@ module Bundler
Plugin.add_source source, cls
end
+ def self.hook(event, &block)
+ Plugin.add_hook(event, &block)
+ end
+
# The cache dir to be used by the plugins for storage
#
# @return [Pathname] path of the cache dir
diff --git a/lib/bundler/plugin/index.rb b/lib/bundler/plugin/index.rb
index 918b3a4392..455fb7b775 100644
--- a/lib/bundler/plugin/index.rb
+++ b/lib/bundler/plugin/index.rb
@@ -24,6 +24,7 @@ module Bundler
@plugin_paths = {}
@commands = {}
@sources = {}
+ @hooks = {}
@load_paths = {}
load_index(global_index_file, true)
@@ -39,7 +40,7 @@ module Bundler
# @param [Array<String>] load_paths for the plugin
# @param [Array<String>] commands that are handled by the plugin
# @param [Array<String>] sources that are handled by the plugin
- def register_plugin(name, path, load_paths, commands, sources)
+ def register_plugin(name, path, load_paths, commands, sources, hooks)
old_commands = @commands.dup
common = commands & @commands.keys
@@ -50,6 +51,8 @@ module Bundler
raise SourceConflict.new(name, common) unless common.empty?
sources.each {|k| @sources[k] = name }
+ hooks.each {|e| (@hooks[e] ||= []) << name }
+
@plugin_paths[name] = path
@load_paths[name] = load_paths
save_index
@@ -98,6 +101,10 @@ module Bundler
@sources[name]
end
+ def hook_plugins(event)
+ @hooks[event]
+ end
+
private
# Reads the index file from the directory and initializes the instance
@@ -119,6 +126,7 @@ module Bundler
@load_paths.merge!(index["load_paths"])
@commands.merge!(index["commands"])
@sources.merge!(index["sources"]) unless global
+ @hooks.merge!(index["hooks"])
end
end
@@ -128,9 +136,10 @@ module Bundler
def save_index
index = {
"plugin_paths" => @plugin_paths,
- "load_paths" => @load_paths,
- "commands" => @commands,
- "sources" => @sources,
+ "load_paths" => @load_paths,
+ "commands" => @commands,
+ "sources" => @sources,
+ "hooks" => @hooks,
}
require "bundler/yaml_serializer"
diff --git a/spec/plugins/hook_spec.rb b/spec/plugins/hook_spec.rb
new file mode 100644
index 0000000000..3622d2a6e9
--- /dev/null
+++ b/spec/plugins/hook_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+require "spec_helper"
+
+describe "hook plugins", :focused do
+ before do
+ build_repo2 do
+ build_plugin "before-install-plugin" do |s|
+ s.write "plugins.rb", <<-RUBY
+ Bundler::Plugin::API.hook "before-install-all" do |deps|
+ puts "gems to be installed \#{deps.map(&:name).join(", ")}"
+ end
+ RUBY
+ end
+ end
+
+ bundle "plugin install before-install-plugin --source file://#{gem_repo2}"
+ end
+
+ it "runs after a rubygem is installed" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "yaml_spec"
+ gem "rake"
+ G
+
+ expect(out).to include "gems to be installed yaml_spec, rake"
+ end
+end