модуль 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 131 def add_command(command, cls) @commands[command] = cls end
Вызывается через API для регистрации обработки команды
# File lib/bundler/plugin.rb, line 180
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 151 def add_source(source, cls) @sources[source] = cls end
Вызывается через API для регистрации обработки плагина источника
# File lib/bundler/plugin.rb, line 126
def cache
@cache ||= root.join("cache")
end Директория кэша для данных плагина
# File lib/bundler/plugin.rb, line 136 def command?(command) !index.command_plugin(command).nil? end
Проверяет, обрабатывает ли какой-либо плагин команду
# File lib/bundler/plugin.rb, line 142
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 75
def gemfile_install(gemfile = nil, &inline)
Bundler.settings.temporary(:frozen => false, :deployment => false) do
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
end
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 [Pathname] gemfile путь к файлу @param [Proc] блок, который может быть оценен для (встроенного) Gemfile
# File lib/bundler/plugin.rb, line 121
def global_root
Bundler.user_bundle_path("plugin")
end Корневая директория глобальных данных всех плагинов
# File lib/bundler/plugin.rb, line 193
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 [String] событие
# File lib/bundler/plugin.rb, line 100 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 [Array<String>] names имя устанавливаемого плагина @param [Hash] options различные параметры, как описано в описании.
Refer to cli/plugin for available options
# File lib/bundler/plugin.rb, line 210 def installed?(plugin) Index.new.installed?(plugin) end
В настоящее время предназначен только для спецификаций
@return [String, nil] путь к установке
# File lib/bundler/plugin.rb, line 52
def list
installed_plugins = index.installed_plugins
if installed_plugins.any?
output = String.new
installed_plugins.each do |plugin|
output << "#{plugin}\n"
output << "-----\n"
index.plugin_commands(plugin).each do |command|
output << " #{command}\n"
end
output << "\n"
end
else
output = "No plugins installed"
end
Bundler.ui.info output
end Список установленных плагинов и команд
# File lib/bundler/plugin.rb, line 285
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)
Bundler.rubygems.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 [String] имя плагина
# File lib/bundler/plugin.rb, line 116
def local_root
Bundler.app_config_path.join("plugin")
end # File lib/bundler/plugin.rb, line 249
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
Bundler.rubygems.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 [String] name имя плагина @param [Specification] spec установленного плагина @param [Boolean] 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 108
def root
@root ||= if SharedHelpers.in_bundle?
local_root
else
global_root
end
end Корневая директория всех данных, связанных с плагином
Если выполняется в приложении, указывает на local_root, в app_config_path В противном случае указывает на global_root, в Bundler.user_bundle_path(“plugin”)
# File lib/bundler/plugin.rb, line 220
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 [Array<String>] plugins список для установки @param [Hash] specs плагинов, сопоставленных с путем установки (в настоящее время они
contain all the installed specs, including plugins)
@param [Array<String>] имена плагинов-источников, которые могут быть проигнорированы
# File lib/bundler/plugin.rb, line 161
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 [Class] обрабатывающий источник. Класс включает API::Source
# File lib/bundler/plugin.rb, line 156 def source?(name) !index.source_plugin(name.to_s).nil? end
Проверяет, объявляет ли какой-либо плагин источник
# File lib/bundler/plugin.rb, line 172
def source_from_lock(locked_opts)
src = source(locked_opts["type"])
src.new(locked_opts.merge("uri" => locked_opts["remote"]))
end @param [Hash] Параметры, присутствующие в файле блокировки @return [API::Source] экземпляр класса, обрабатывающего источник
type passed in locked_opts
# File lib/bundler/plugin.rb, line 235
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 Проверяет, подходит ли драгоценный камень для плагина
В настоящее время проверяется, содержит ли он файл plugins.rb
@param [Pathname] plugin_path путь, по которому установлен плагин @raise [MalformattedPlugin] если файл plugins.rb не найден
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.