class Diecut::PluginLoader
Constants
- NO_VALUE
- PLUGIN_FILENAME
:nocov:
Attributes
issue_handler[W]
local_valise[RW]
plugins[R]
Public Class Methods
new()
click to toggle source
# File lib/diecut/plugin-loader.rb, line 17 def initialize @sources = {} @local_sources = [] @by_gem_name = Hash.new{|h,k| h[k] = []} @plugins = [] end
Public Instance Methods
add_plugin_desc(desc)
click to toggle source
# File lib/diecut/plugin-loader.rb, line 183 def add_plugin_desc(desc) plugins << desc end
choose_source(locations)
click to toggle source
# File lib/diecut/plugin-loader.rb, line 171 def choose_source(locations) locations.each do |loc| path = loc.absolute_path if @sources.has_key?(path) return path end end fallback_location = locations.first.absolute_path issue_handler.unregistered_plugin_source(fallback_location) return fallback_location end
component_sort() { |comp| ... }
click to toggle source
# File lib/diecut/plugin-loader.rb, line 98 def component_sort unless block_given? return enum_for(:component_sort) end child_idxs = {} strongly_connected_components.each_with_index do |component, idx| component.sort_by{|node| child_idxs.fetch(node, -1) }.each do |comp| yield(comp) end component.each do |comp| tsort_each_child(comp) do |child| child_idxs[child] = idx end end end end
dep_path?(from_gem, to_gem)
click to toggle source
# File lib/diecut/plugin-loader.rb, line 150 def dep_path?(from_gem, to_gem) # potential to optimize this: build a map of reachablility and test # against that. closed = {} open = [from_gem] until open.empty? current = open.shift return true if current == to_gem closed[current] = true open += @by_gem_name[current.gem.name].select{|gem| !closed.has_key?(gem)} end return false end
describe_plugin(name) { |desc| ... }
click to toggle source
# File lib/diecut/plugin-loader.rb, line 187 def describe_plugin(name) source_path = choose_source(caller_locations) desc = PluginDescription.new(name, source_path) yield(desc) add_plugin_desc(desc) return desc end
discover(prerelease)
click to toggle source
# File lib/diecut/plugin-loader.rb, line 51 def discover(prerelease) latest_specs(prerelease).map do |spec| spec.matches_for_glob(PLUGIN_FILENAME).map do |match| from_gem(spec, match) end end local_valise.get(PLUGIN_FILENAME).present.map(&:full_path).each do |path| from_local(path) end end
each_path() { |path| ... }
click to toggle source
# File lib/diecut/plugin-loader.rb, line 116 def each_path component_sort.reverse_each do |source| yield source.path end end
from_gem(spec, path)
click to toggle source
# File lib/diecut/plugin-loader.rb, line 62 def from_gem(spec, path) plugin = GemPlugin.new(spec, path) @sources[path] = plugin spec.dependencies.map(&:name).each do |depname| @by_gem_name[depname] << plugin end end
from_local(path)
click to toggle source
# File lib/diecut/plugin-loader.rb, line 71 def from_local(path) source = GemPlugin.new(NO_VALUE, path) @sources[path] = source @local_sources << source end
issue_handler()
click to toggle source
# File lib/diecut/plugin-loader.rb, line 35 def issue_handler @issue_handler ||= Diecut.issue_handler end
latest_specs(prerelease)
click to toggle source
:nocov:
# File lib/diecut/plugin-loader.rb, line 41 def latest_specs(prerelease) Gem::Specification.latest_specs(prerelease) end
load_plugins(prerelease = false)
click to toggle source
# File lib/diecut/plugin-loader.rb, line 164 def load_plugins(prerelease = false) discover(prerelease) each_path do |path| require_plugin(path) end end
require_plugin(path)
click to toggle source
# File lib/diecut/plugin-loader.rb, line 45 def require_plugin(path) require path end
strict_sequence?(to, from)
click to toggle source
Can a chain of “is after” arrows be walked from ‘from’ to ‘to’. The rules are: A plugin defined by a gem that depends on another gem “is after” the plugin defined in the latter gem. A plugin defined in a local config file is after “more general” local files (project config is after personal is after system). All local plugins are after all gem plugins
The rationale for these rules is that decisions made later in time have more information and that decisions made closer to the problem know the problem domain better.
# File lib/diecut/plugin-loader.rb, line 134 def strict_sequence?(to, from) from_source = @sources[from.source_path] to_source = @sources[to.source_path] case [from_source.gem?, to_source.gem?] when [true, true] dep_path?(to_source, from_source) when [true, false] false when [false, true] true when [false, false] @local_sources.index_of(from.source_path) <= @local_sources.index_of(to.source_path) end end
tsort_each_child(node) { |depplugin| ... }
click to toggle source
# File lib/diecut/plugin-loader.rb, line 81 def tsort_each_child(node) if node.gem? @by_gem_name[node.gem.name].each do |depplugin| yield depplugin end @local_sources.each do |local| yield local end else @local_sources.drop_while do |src| src != node end.drop(1).each do |node| yield(node) end end end
tsort_each_node(&block)
click to toggle source
# File lib/diecut/plugin-loader.rb, line 77 def tsort_each_node(&block) @sources.each_value(&block) end