модуль Bundler::Plugin
Этот класс-интерфейс представляет API, который мы планируем предоставить для использования плагинами.
Для независимости плагинов от внутренней реализации Bundler они должны ограничить своё взаимодействие только методами этого класса. Это защитит их от поломок при внутренних изменениях.
В настоящее время мы делегируем методы, определённые в классе Bundler, самому себе. Таким образом, этот класс служит буфером.
Если произойдут изменения в классе Bundler, несовместимые с его предыдущим поведением, или по другим причинам, мы можем переопределить (или реализовать) методы для сохранения совместимости.
Для использования этого класса, либо можно унаследовать его, либо использовать напрямую. Пример обоих способов использования см. в файле `spec/plugins/command.rb`
Для использования без наследования, вам необходимо создать объект этого класса, чтобы использовать функции (за исключением функций объявления, таких как command, source и hooks).
Управляет установкой плагинов и их источниками. Также предполагается сопоставлять, какой плагин за что отвечает (в настоящее время эти возможности не реализованы, поэтому этот класс является заглушкой).
Обрабатывает установку плагина в соответствующие директории.
Этот класс предназначен для обёртки существующей инфраструктуры установки gem, но в настоящее время он сам обрабатывает всё, так как подклассы Source (например, Source::RubyGems) сильно зависят от Gemfile.
SourceList объект, используемый при разборе Gemfile, устанавливая соответствующие параметры для использования с классами Source при установке плагинов
Константы
- PLUGIN_FILE_NAME
Публичные методы экземпляра
# File lib/bundler/plugin.rb, line 109 def add_command(command, cls) @commands[command] = cls end
Вызывается через API для регистрации обработки команды
# File lib/bundler/plugin.rb, line 158
def add_hook(event, &block)
unless Events.defined_event?(event)
raise ArgumentError, "Event '#{event}' not defined in Bundler::Plugin::Events"
end
@hooks_by_event[event.to_s] << block
end Вызывается через API для регистрации хуков и соответствующего блока, который будет вызван для обработки хука
# File lib/bundler/plugin.rb, line 129 def add_source(source, cls) @sources[source] = cls end
Вызывается через API для регистрации обработки плагина источника
# File lib/bundler/plugin.rb, line 279
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 # File lib/bundler/plugin.rb, line 104
def cache
@cache ||= root.join("cache")
end Каталог кэша для плагинов
# File lib/bundler/plugin.rb, line 114 def command?(command) !index.command_plugin(command).nil? end
Проверяет, обрабатывает ли какой-либо плагин команду
# File lib/bundler/plugin.rb, line 120
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 Вызывается из класса Cli для передачи команды и аргументов соответствующему классу плагина
# File lib/bundler/plugin.rb, line 55
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 RuntimeError => e
unless e.is_a?(GemfileError)
Bundler.ui.error "Failed to install plugin: #{e.message}\n #{e.backtrace[0]}"
end
raise
end Оценивает Gemfile с ограниченным DSL и устанавливает плагины, указанные методом плагина
@param [Путь] путь к gemfile @param [Блок] блок, который может быть оценен для (встроенного) Gemfile
# File lib/bundler/plugin.rb, line 99
def global_root
Bundler.user_bundle_path("plugin")
end Глобальный корневой каталог для всех данных, связанных с плагинами
# File lib/bundler/plugin.rb, line 171
def hook(event, *args, &arg_blk)
return unless Bundler.feature_flag.plugins?
unless Events.defined_event?(event)
raise ArgumentError, "Event '#{event}' not defined in Bundler::Plugin::Events"
end
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 Выполняет все зарегистрированные хуки для переданного события
Передает переданные аргументы и блок в зарегистрированный в API блок.
@param [Строка] событие
# File lib/bundler/plugin.rb, line 78 def index @index ||= Index.new end
Объект индекса, используемый для хранения сведений о плагине
# File lib/bundler/plugin.rb, line 37
def install(names, options)
specs = Installer.new.install(names, options)
save_plugins names, specs
rescue PluginError => e
if specs
specs_to_delete = Hash[specs.select {|k, _v| names.include?(k) && !index.commands.values.include?(k) }]
specs_to_delete.values.each {|spec| Bundler.rm_rf(spec.full_gem_path) }
end
Bundler.ui.error "Failed to install plugin #{name}: #{e.message}\n #{e.backtrace.join("\n ")}"
end Устанавливает новый плагин по заданному имени
@param [Массив<Строка>] имена устанавливаемого плагина @param [Хэш] различные параметры, как описано в описании.
Refer to cli/plugin for available options
# File lib/bundler/plugin.rb, line 188 def installed?(plugin) Index.new.installed?(plugin) end
В настоящее время предназначен только для спецификаций
@return [Строка, null] установлен путь
# File lib/bundler/plugin.rb, line 263
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 RuntimeError => e
Bundler.ui.error "Failed loading plugin #{name}: #{e.message}"
raise
end Выполняет файл plugins.rb
@param [Строка] имя плагина
# File lib/bundler/plugin.rb, line 94
def local_root
Bundler.app_config_path.join("plugin")
end # File lib/bundler/plugin.rb, line 227
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 Выполняет файл plugins.rb в изолированном пространстве имен, записывает действия плагина, которые он регистрирует, а затем передает данные индексу для хранения.
@param [Строка] имя плагина @param [Спецификация] спецификация установленного плагина @param [Булево] optional_plugin, удалено, если есть конфликт
other plugin (used for default source plugins)
@raise [MalformattedPlugin] если plugins.rb вызывает какую-либо ошибку
# File lib/bundler/plugin.rb, line 21
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 # File lib/bundler/plugin.rb, line 86
def root
@root ||= if SharedHelpers.in_bundle?
local_root
else
global_root
end
end Корневой каталог для всех данных, связанных с плагинами
Если выполняется в приложении, указывает на локальный корень, в app_config_path Иначе, указывает на глобальный корень, в Bundler.user_bundle_path(“плагин”)
# File lib/bundler/plugin.rb, line 198
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 Обработка после установки и регистрация в индексе
@param [Массив<Строка>] список плагинов для установки @param [Хэш] спецификаций плагинов, сопоставленных с путем установки (в настоящее время они
contain all the installed specs, including plugins)
@param [Массив<Строка>] имена выведенных плагинов-источников, которые можно игнорировать
# File lib/bundler/plugin.rb, line 139
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 @return [Класс] обрабатывающий источник. Класс включает API::Source
# File lib/bundler/plugin.rb, line 134 def source?(name) !index.source_plugin(name.to_s).nil? end
Проверяет, объявляет ли какой-либо плагин источник
# File lib/bundler/plugin.rb, line 150
def source_from_lock(locked_opts)
src = source(locked_opts["type"])
src.new(locked_opts.merge("uri" => locked_opts["remote"]))
end @param [Хэш] параметры, присутствующие в файле блокировки @return [API::Source] экземпляр класса, обрабатывающего источник
type passed in locked_opts
# File lib/bundler/plugin.rb, line 213
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 Проверяет, является ли gem подходящим плагином
В настоящее время проверяется только наличие файла plugins.rb
@param [Путь] путь к установке плагина @raise [MalformattedPlugin] если файл plugins.rb не найден
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.