/usr/lib/ruby/vendor_ruby/bundler/plugin.rb is in ruby-bundler 1.13.6-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 | # frozen_string_literal: true
require "bundler/plugin/api"
module Bundler
module Plugin
autoload :DSL, "bundler/plugin/dsl"
autoload :Index, "bundler/plugin/index"
autoload :Installer, "bundler/plugin/installer"
autoload :SourceList, "bundler/plugin/source_list"
class MalformattedPlugin < PluginError; end
class UndefinedCommandError < PluginError; end
class UnknownSourceError < PluginError; end
PLUGIN_FILE_NAME = "plugins.rb".freeze
module_function
def reset!
instance_variables.each {|i| remove_instance_variable(i) }
@sources = {}
@commands = {}
@hooks_by_event = Hash.new {|h, k| h[k] = [] }
@loaded_plugin_names = []
end
reset!
# Installs a new plugin by the given name
#
# @param [Array<String>] names the name of plugin to be installed
# @param [Hash] options various parameters as described in description.
# Refer to cli/plugin for available options
def install(names, options)
specs = Installer.new.install(names, options)
save_plugins names, specs
rescue PluginError => e
specs.values.map {|spec| Bundler.rm_rf(spec.full_gem_path) } if specs
Bundler.ui.error "Failed to install plugin #{name}: #{e.message}\n #{e.backtrace.join("\n ")}"
end
# Evaluates the Gemfile with a limited DSL and installs the plugins
# specified by plugin method
#
# @param [Pathname] gemfile path
# @param [Proc] block that can be evaluated for (inline) Gemfile
def gemfile_install(gemfile = nil, &inline)
builder = DSL.new
if block_given?
builder.instance_eval(&inline)
else
builder.eval_gemfile(gemfile)
end
definition = builder.to_definition(nil, true)
return if definition.dependencies.empty?
plugins = definition.dependencies.map(&:name).reject {|p| index.installed? p }
installed_specs = Installer.new.install_definition(definition)
save_plugins plugins, installed_specs, builder.inferred_plugins
rescue => e
Bundler.ui.error "Failed to install plugin: #{e.message}\n #{e.backtrace[0]}"
raise
end
# The index object used to store the details about the plugin
def index
@index ||= Index.new
end
# The directory root for all plugin related data
#
# Points to root in app_config_path if ran in an app else points to the one
# in user_bundle_path
def root
@root ||= if SharedHelpers.in_bundle?
local_root
else
global_root
end
end
def local_root
Bundler.app_config_path.join("plugin")
end
# The global directory root for all plugin related data
def global_root
Bundler.user_bundle_path.join("plugin")
end
# The cache directory for plugin stuffs
def cache
@cache ||= root.join("cache")
end
# To be called via the API to register to handle a command
def add_command(command, cls)
@commands[command] = cls
end
# Checks if any plugin handles the command
def command?(command)
!index.command_plugin(command).nil?
end
# To be called from Cli class to pass the command and argument to
# approriate plugin class
def exec_command(command, args)
raise UndefinedCommandError, "Command `#{command}` not found" unless command? command
load_plugin index.command_plugin(command) unless @commands.key? command
@commands[command].new.exec(command, args)
end
# To be called via the API to register to handle a source plugin
def add_source(source, cls)
@sources[source] = cls
end
# Checks if any plugin declares the source
def source?(name)
!index.source_plugin(name.to_s).nil?
end
# @return [Class] that handles the source. The calss includes API::Source
def source(name)
raise UnknownSourceError, "Source #{name} not found" unless source? name
load_plugin(index.source_plugin(name)) unless @sources.key? name
@sources[name]
end
# @param [Hash] The options that are present in the lock file
# @return [API::Source] the instance of the class that handles the source
# type passed in locked_opts
def source_from_lock(locked_opts)
src = source(locked_opts["type"])
src.new(locked_opts.merge("uri" => locked_opts["remote"]))
end
# To be called via the API to register a hooks and corresponding block that
# will be called to handle the hook
def add_hook(event, &block)
@hooks_by_event[event.to_s] << block
end
# Runs all the hooks that are registered for the passed event
#
# It passes the passed arguments and block to the block registered with
# the api.
#
# @param [String] event
def hook(event, *args, &arg_blk)
return unless Bundler.settings[:plugins]
plugins = index.hook_plugins(event)
return unless plugins.any?
(plugins - @loaded_plugin_names).each {|name| load_plugin(name) }
@hooks_by_event[event].each {|blk| blk.call(*args, &arg_blk) }
end
# currently only intended for specs
#
# @return [String, nil] installed path
def installed?(plugin)
Index.new.installed?(plugin)
end
# Post installation processing and registering with index
#
# @param [Array<String>] plugins list to be installed
# @param [Hash] specs of plugins mapped to installation path (currently they
# contain all the installed specs, including plugins)
# @param [Array<String>] names of inferred source plugins that can be ignored
def save_plugins(plugins, specs, optional_plugins = [])
plugins.each do |name|
spec = specs[name]
validate_plugin! Pathname.new(spec.full_gem_path)
installed = register_plugin(name, spec, optional_plugins.include?(name))
Bundler.ui.info "Installed plugin #{name}" if installed
end
end
# Checks if the gem is good to be a plugin
#
# At present it only checks whether it contains plugins.rb file
#
# @param [Pathname] plugin_path the path plugin is installed at
# @raise [MalformattedPlugin] if plugins.rb file is not found
def validate_plugin!(plugin_path)
plugin_file = plugin_path.join(PLUGIN_FILE_NAME)
raise MalformattedPlugin, "#{PLUGIN_FILE_NAME} was not found in the plugin." unless plugin_file.file?
end
# Runs the plugins.rb file in an isolated namespace, records the plugin
# actions it registers for and then passes the data to index to be stored.
#
# @param [String] name the name of the plugin
# @param [Specification] spec of installed plugin
# @param [Boolean] optional_plugin, removed if there is conflict with any
# other plugin (used for default source plugins)
#
# @raise [MalformattedPlugin] if plugins.rb raises any error
def register_plugin(name, spec, optional_plugin = false)
commands = @commands
sources = @sources
hooks = @hooks_by_event
@commands = {}
@sources = {}
@hooks_by_event = Hash.new {|h, k| h[k] = [] }
load_paths = spec.load_paths
add_to_load_path(load_paths)
path = Pathname.new spec.full_gem_path
begin
load path.join(PLUGIN_FILE_NAME), true
rescue StandardError => e
raise MalformattedPlugin, "#{e.class}: #{e.message}"
end
if optional_plugin && @sources.keys.any? {|s| source? s }
Bundler.rm_rf(path)
false
else
index.register_plugin(name, path.to_s, load_paths, @commands.keys,
@sources.keys, @hooks_by_event.keys)
true
end
ensure
@commands = commands
@sources = sources
@hooks_by_event = hooks
end
# Executes the plugins.rb file
#
# @param [String] name of the plugin
def load_plugin(name)
# Need to ensure before this that plugin root where the rest of gems
# are installed to be on load path to support plugin deps. Currently not
# done to avoid conflicts
path = index.plugin_path(name)
add_to_load_path(index.load_paths(name))
load path.join(PLUGIN_FILE_NAME)
@loaded_plugin_names << name
rescue => e
Bundler.ui.error "Failed loading plugin #{name}: #{e.message}"
raise
end
def add_to_load_path(load_paths)
if insert_index = Bundler.rubygems.load_path_insert_index
$LOAD_PATH.insert(insert_index, *load_paths)
else
$LOAD_PATH.unshift(*load_paths)
end
end
class << self
private :load_plugin, :register_plugin, :save_plugins, :validate_plugin!,
:add_to_load_path
end
end
end
|