diff options
author | hsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-11-02 23:07:56 +0000 |
---|---|---|
committer | hsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-11-02 23:07:56 +0000 |
commit | 59c8d50653480bef3f24517296e6ddf937fdf6bc (patch) | |
tree | df10aaf4f3307837fe3d1d129d66f6c0c7586bc5 /lib/bundler/plugin/index.rb | |
parent | 7deb37777a230837e865e0a11fb8d7c1dc6d03ce (diff) |
Added bundler as default gems. Revisit [Feature #12733]
* bin/*, lib/bundler/*, lib/bundler.rb, spec/bundler, man/*:
Merge from latest stable branch of bundler/bundler repository and
added workaround patches. I will backport them into upstream.
* common.mk, defs/gmake.mk: Added `test-bundler` task for test suite
of bundler.
* tool/sync_default_gems.rb: Added sync task for bundler.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65509 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/bundler/plugin/index.rb')
-rw-r--r-- | lib/bundler/plugin/index.rb | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/lib/bundler/plugin/index.rb b/lib/bundler/plugin/index.rb new file mode 100644 index 0000000000..f09587dfda --- /dev/null +++ b/lib/bundler/plugin/index.rb @@ -0,0 +1,162 @@ +# frozen_string_literal: true + +module Bundler + # Manages which plugins are installed and their sources. This also is supposed to map + # which plugin does what (currently the features are not implemented so this class is + # now a stub class). + module Plugin + class Index + class CommandConflict < PluginError + def initialize(plugin, commands) + msg = "Command(s) `#{commands.join("`, `")}` declared by #{plugin} are already registered." + super msg + end + end + + class SourceConflict < PluginError + def initialize(plugin, sources) + msg = "Source(s) `#{sources.join("`, `")}` declared by #{plugin} are already registered." + super msg + end + end + + attr_reader :commands + + def initialize + @plugin_paths = {} + @commands = {} + @sources = {} + @hooks = {} + @load_paths = {} + + begin + load_index(global_index_file, true) + rescue GenericSystemCallError + # no need to fail when on a read-only FS, for example + nil + end + load_index(local_index_file) if SharedHelpers.in_bundle? + end + + # This function is to be called when a new plugin is installed. This + # function shall add the functions of the plugin to existing maps and also + # the name to source location. + # + # @param [String] name of the plugin to be registered + # @param [String] path where the plugin is installed + # @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, hooks) + old_commands = @commands.dup + + common = commands & @commands.keys + raise CommandConflict.new(name, common) unless common.empty? + commands.each {|c| @commands[c] = name } + + common = sources & @sources.keys + 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 + rescue StandardError + @commands = old_commands + raise + end + + # Path of default index file + def index_file + Plugin.root.join("index") + end + + # Path where the global index file is stored + def global_index_file + Plugin.global_root.join("index") + end + + # Path where the local index file is stored + def local_index_file + Plugin.local_root.join("index") + end + + def plugin_path(name) + Pathname.new @plugin_paths[name] + end + + def load_paths(name) + @load_paths[name] + end + + # Fetch the name of plugin handling the command + def command_plugin(command) + @commands[command] + end + + def installed?(name) + @plugin_paths[name] + end + + def source?(source) + @sources.key? source + end + + def source_plugin(name) + @sources[name] + end + + # Returns the list of plugin names handling the passed event + def hook_plugins(event) + @hooks[event] || [] + end + + private + + # Reads the index file from the directory and initializes the instance + # variables. + # + # It skips the sources if the second param is true + # @param [Pathname] index file path + # @param [Boolean] is the index file global index + def load_index(index_file, global = false) + SharedHelpers.filesystem_access(index_file, :read) do |index_f| + valid_file = index_f && index_f.exist? && !index_f.size.zero? + break unless valid_file + + data = index_f.read + + require "bundler/yaml_serializer" + index = YAMLSerializer.load(data) + + @commands.merge!(index["commands"]) + @hooks.merge!(index["hooks"]) + @load_paths.merge!(index["load_paths"]) + @plugin_paths.merge!(index["plugin_paths"]) + @sources.merge!(index["sources"]) unless global + end + end + + # Should be called when any of the instance variables change. Stores the + # instance variables in YAML format. (The instance variables are supposed + # to be only String key value pairs) + def save_index + index = { + "commands" => @commands, + "hooks" => @hooks, + "load_paths" => @load_paths, + "plugin_paths" => @plugin_paths, + "sources" => @sources, + } + + require "bundler/yaml_serializer" + SharedHelpers.filesystem_access(index_file) do |index_f| + FileUtils.mkdir_p(index_f.dirname) + File.open(index_f, "w") {|f| f.puts YAMLSerializer.dump(index) } + end + end + end + end +end |