summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsutosh Palai <asupalai@gmail.com>2016-05-31 12:14:14 +0530
committerAsutosh Palai <asupalai@gmail.com>2016-05-31 12:14:14 +0530
commit24b28696e7b8de8b4214c849a5252b4d58dda5d9 (patch)
tree0b7958965e9da1a31f6c4a21a1970de30f04cf96
parent2054b7dfa2c4573664ed87cf45a1898905aadec0 (diff)
downloadbundler-24b28696e7b8de8b4214c849a5252b4d58dda5d9.tar.gz
Added the command plugin
-rw-r--r--lib/bundler/cli.rb4
-rw-r--r--lib/bundler/cli/install.rb2
-rw-r--r--lib/bundler/plugin.rb41
-rw-r--r--lib/bundler/plugin/api.rb31
-rw-r--r--lib/bundler/plugin/index.rb30
5 files changed, 98 insertions, 10 deletions
diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb
index 75d4581e12..7cde242804 100644
--- a/lib/bundler/cli.rb
+++ b/lib/bundler/cli.rb
@@ -82,6 +82,10 @@ module Bundler
end
def self.handle_no_command_error(command, has_namespace = $thor_runner)
+ if Bundler::Plugin.command? command
+ return Bundler::Plugin.exec_command(command, ARGV[1..-1])
+ end
+
return super unless command_path = Bundler.which("bundler-#{command}")
Kernel.exec(command_path, *ARGV[1..-1])
diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb
index efde762e5a..0589b87d26 100644
--- a/lib/bundler/cli/install.rb
+++ b/lib/bundler/cli/install.rb
@@ -96,7 +96,7 @@ module Bundler
# rubygems plugins sometimes hook into the gem install process
Gem.load_env_plugins if Gem.respond_to?(:load_env_plugins)
- Bundler::Plugin.eval_gemfile(Bundler.default_gemfile)
+ Plugin.eval_gemfile(Bundler.default_gemfile)
definition = Bundler.definition
definition.validate_ruby!
diff --git a/lib/bundler/plugin.rb b/lib/bundler/plugin.rb
index e4ab928735..4bf398e0eb 100644
--- a/lib/bundler/plugin.rb
+++ b/lib/bundler/plugin.rb
@@ -2,11 +2,16 @@
module Bundler
class Plugin
+ autoload :Api, "bundler/plugin/api"
autoload :Dsl, "bundler/plugin/dsl"
autoload :Index, "bundler/plugin/index"
autoload :Installer, "bundler/plugin/installer"
autoload :SourceList, "bundler/plugin/source_list"
+ PLUGIN_FILE_NAME = "plugin.rb".freeze
+
+ @commands = {}
+
class << self
# Installs a new plugin by the given name
#
@@ -60,6 +65,22 @@ module Bundler
@cache ||= root.join("cache")
end
+ def add_command(command, cls)
+ @commands[command] = cls
+ end
+
+ def command?(command)
+ index.command? command
+ end
+
+ def exec_command(command, args)
+ raise "Command #{command} not found" unless command? command
+
+ load_plugin index.command_plugin(command) unless @commands.key? command
+
+ @commands[command].new.exec(command, args)
+ end
+
private
# Checks if the gem is good to be a plugin
@@ -70,8 +91,8 @@ module Bundler
#
# @raise [Error] if plugin.rb file is not found
def validate_plugin!(plugin_path)
- plugin_file = plugin_path.join("plugin.rb")
- raise "plugin.rb was not found in the plugin!" unless plugin_file.file?
+ plugin_file = plugin_path.join(PLUGIN_FILE_NAME)
+ raise "#{PLUGIN_FILE_NAME} was not found in the plugin!" unless plugin_file.file?
end
# Runs the plugin.rb file, records the plugin actions it registers for and
@@ -80,9 +101,21 @@ module Bundler
# @param [String] name the name of the plugin
# @param [Pathname] path the path where the plugin is installed at
def register_plugin(name, path)
- require path.join("plugin.rb") # this shall latter be used to find the actions the plugin performs
+ commands = @commands
+
+ @commands = {}
+
+ require path.join(PLUGIN_FILE_NAME) # this shall latter be used to find the actions the plugin performs
+
+ index.register_plugin name, path.to_s, @commands.keys
+ ensure
+ @commands = commands
+ end
+
+ def load_plugin(name)
+ path = index.plugin_path(name)
- index.register_plugin name, path.to_s
+ load path.join(PLUGIN_FILE_NAME)
end
end
end
diff --git a/lib/bundler/plugin/api.rb b/lib/bundler/plugin/api.rb
new file mode 100644
index 0000000000..267b448cc3
--- /dev/null
+++ b/lib/bundler/plugin/api.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Bundler
+ # This is the interfacing class represents the API that we intend to provide
+ # the plugins to use.
+ #
+ # For plugins to be independent of the Bundler internals they shall limit their
+ # interactions to methods of this class only. This will save them from breaking
+ # when some internal change.
+ class Plugin::Api
+ def self.command(command)
+ Plugin.add_command command, self
+ end
+
+ # The cache dir to be used by the plugins for persistance storage
+ #
+ # @return [Pathname] path of the cache dir
+ def cache
+ Plugin.cache.join("plugins")
+ end
+
+ # A tmp dir to be used by plugins
+ # Note: Its desirable to explicitly remove the dir after use
+ #
+ # @param [String] name unique for the plugin or the purpose
+ # @return [Pathname] object for the new directory created
+ def tmp(name)
+ Bundler.tmp(File.join(["plugin", name]))
+ end
+ end
+end
diff --git a/lib/bundler/plugin/index.rb b/lib/bundler/plugin/index.rb
index 0fc70af27a..5d8e896f30 100644
--- a/lib/bundler/plugin/index.rb
+++ b/lib/bundler/plugin/index.rb
@@ -7,7 +7,8 @@ module Bundler
# now a stub class).
class Plugin::Index
def initialize
- @plugin_sources = {}
+ @plugin_paths = {}
+ @commands = {}
load_index
end
@@ -17,8 +18,13 @@ module Bundler
#
# @param [String] name of the plugin to be registered
# @param [String] path where the plugin is installed
- def register_plugin(name, path)
- @plugin_sources[name] = path
+ # @param [Array<String>] commands that are handled by the plugin
+ def register_plugin(name, path, commands)
+ @plugin_paths[name] = path
+
+ common = commands & @commands.keys
+ raise "Command(s) #{common.join(", ")} are already registered" if common.any?
+ commands.each{|c| @commands[c] = name }
save_index
end
@@ -28,6 +34,18 @@ module Bundler
Plugin.root.join("index")
end
+ def plugin_path(name)
+ Pathname.new @plugin_paths[name]
+ end
+
+ def command?(command)
+ @commands.key? command
+ end
+
+ def command_plugin(command)
+ @commands[command]
+ end
+
private
# Reads the index file from the directory and initializes the instance variables.
@@ -36,7 +54,8 @@ module Bundler
valid_file = index_f && index_f.exist? && !index_f.size.zero?
break unless valid_file
index = YAML.load_file(index_f)
- @plugin_sources = index["plugin_sources"]
+ @plugin_paths = index["plugin_paths"]
+ @commands = index["commands"]
end
end
@@ -44,7 +63,8 @@ module Bundler
# variables in YAML format. (The instance variables are supposed to be only String key value pairs)
def save_index
index = {
- "plugin_sources" => @plugin_sources,
+ "plugin_paths" => @plugin_paths,
+ "commands" => @commands,
}
SharedHelpers.filesystem_access(index_file) do |index_f|