Class: CLAide::Command::PluginManager

Inherits:
Object
  • Object
show all
Defined in:
lib/claide/command/plugin_manager.rb

Overview

Handles plugin related logic logic for the Command class.

Plugins are loaded the first time a command run and are identified by the prefix specified in the command class. Plugins must adopt the following conventions:

  • Support being loaded by a file located under the lib/#{plugin_prefix}_plugin relative path.
  • Be stored in a folder named after the plugin.

Helper Methods collapse

Class Method Summary collapse

Class Method Details

.installed_specifications_for_prefix(plugin_prefix) ⇒ Array<Specification>

Returns The RubyGems specifications for the installed plugins that match the given plugin_prefix.

Returns:

  • (Array<Specification>)

    The RubyGems specifications for the installed plugins that match the given plugin_prefix.


45
46
47
48
# File 'lib/claide/command/plugin_manager.rb', line 45

def self.installed_specifications_for_prefix(plugin_prefix)
  loaded_plugins[plugin_prefix] ||
    plugin_gems_for_prefix(plugin_prefix).map(&:first)
end

.load_plugins(plugin_prefix) ⇒ Array<Gem::Specification>

Returns Loads plugins via RubyGems looking for files named after the PLUGIN_PREFIX_plugin and returns the specifications of the gems loaded successfully. Plugins are required safely.

Returns:

  • (Array<Gem::Specification>)

    Loads plugins via RubyGems looking for files named after the PLUGIN_PREFIX_plugin and returns the specifications of the gems loaded successfully. Plugins are required safely.


28
29
30
31
32
33
# File 'lib/claide/command/plugin_manager.rb', line 28

def self.load_plugins(plugin_prefix)
  loaded_plugins[plugin_prefix] ||=
    plugin_gems_for_prefix(plugin_prefix).map do |spec, paths|
      spec if safe_activate_and_require(spec, paths)
    end.compact
end

.loaded_pluginsHash<String,Gem::Specification>

Returns The loaded plugins, grouped by plugin prefix.

Returns:

  • (Hash<String,Gem::Specification>)

    The loaded plugins, grouped by plugin prefix.


19
20
21
# File 'lib/claide/command/plugin_manager.rb', line 19

def self.loaded_plugins
  @loaded_plugins ||= {}
end

.plugin_gems_for_prefix(prefix) ⇒ Array<[Gem::Specification, Array<String>]>

Returns an array of tuples containing the specifications and plugin files to require for a given plugin prefix.

Returns:

  • (Array<[Gem::Specification, Array<String>]>)

    Returns an array of tuples containing the specifications and plugin files to require for a given plugin prefix.


72
73
74
75
76
77
78
# File 'lib/claide/command/plugin_manager.rb', line 72

def self.plugin_gems_for_prefix(prefix)
  glob = "#{prefix}_plugin#{Gem.suffix_pattern}"
  Gem::Specification.latest_specs(true).map do |spec|
    matches = spec.matches_for_glob(glob)
    [spec, matches] unless matches.empty?
  end.compact
end

.plugins_involved_in_exception(exception) ⇒ Array<String>

Returns The list of the plugins whose root path appears in the backtrace of an exception.

Parameters:

  • exception (Exception)

    The exception to analyze.

Returns:

  • (Array<String>)

    The list of the plugins whose root path appears in the backtrace of an exception.


56
57
58
59
60
61
62
63
64
# File 'lib/claide/command/plugin_manager.rb', line 56

def self.plugins_involved_in_exception(exception)
  specifications.select do |gemspec|
    exception.backtrace.any? do |line|
      full_require_paths_for(gemspec).any? do |plugin_path|
        line.include?(plugin_path)
      end
    end
  end.map(&:name)
end

.safe_activate_and_require(spec, paths) ⇒ Bool

Activates the given spec and requires the given paths. If any exception occurs it is caught and an informative message is printed.

Parameters:

  • spec (Gem::Specification)

    The spec to be activated.

  • paths (String)

    The paths to require.

Returns:

  • (Bool)

    Whether activation and requiring succeeded.


92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/claide/command/plugin_manager.rb', line 92

def self.safe_activate_and_require(spec, paths)
  spec.activate
  paths.each { |path| require(path) }
  true
rescue Exception => exception # rubocop:disable RescueException
  message = "\n---------------------------------------------"
  message << "\nError loading the plugin `#{spec.full_name}`.\n"
  message << "\n#{exception.class} - #{exception.message}"
  message << "\n#{exception.backtrace.join("\n")}"
  message << "\n---------------------------------------------\n"
  warn message.ansi.yellow
  false
end

.specificationsArray<Specification>

Returns The RubyGems specifications for the loaded plugins.

Returns:

  • (Array<Specification>)

    The RubyGems specifications for the loaded plugins.


38
39
40
# File 'lib/claide/command/plugin_manager.rb', line 38

def self.specifications
  loaded_plugins.values.flatten.uniq
end