module PowerStencil module Project module Plugins def plugins @plugins ||= {} end def create_new_local_plugin_tree(plugin_name, new_plugin_path, overwrite_files: false) raise PowerStencil::Error, "Plugin '#{plugin_name}' already exists !" if plugins.keys.include? plugin_name raise PowerStencil::Error, "Invalid plugin name '#{plugin_name}'" if (plugin_name.underscore =~ /^[_[:lower:]][_[:alnum:]]*$/).nil? entity_engine.dsl = PowerStencil::Dsl::PluginGeneration entity_engine.render_source entity_type_templates_templates[:plugin_definition], new_plugin_path, overwrite_files: overwrite_files, main_entry_point: plugin_name end def plugins_sorted_by_dependency solver = PowerStencil::Utils::DependencySolver.new plugin_names = plugins.keys plugins.each do |_, plugin| unless plugin.dependencies.nil? plugin.dependencies.each do |dependency_name| raise PowerStencil::Error, "Invalid dependency '#{dependency_name}'declared for plugin '#{plugin.name}' !" unless plugin_names.include? dependency_name end end solver[plugin.name] = plugin.dependencies.nil? ? [] : plugin.dependencies end solver.tsort.map { |plugin_name| plugins[plugin_name] } rescue TSort::Cyclic => e PowerStencil::Error.report_error e raise PowerStencil::Error, 'Plugins cyclical dependency error !' end private def bootstrap_plugins @plugins = {} initialize_gem_plugins initialize_local_plugins require_plugins_entry_points command_line_manager.definition_hash_to_commands register_plugins_processors end def register_plugins_processors plugins.each do |_, plugin| if plugin.capabilities[:processors] plugin.register_processors end end end def require_plugins_entry_points plugins_sorted_by_dependency.each do |plugin| plugin.require_entry_point end end def initialize_gem_plugins if config[:project_plugins].empty? PowerStencil.logger.info 'No gem plugin found in project' return end config[:project_plugins].each do |plugin_definition| (gem_name, gem_req) = PowerStencil::Plugins::Base.plugin_definition_to_name_and_req plugin_definition raise PowerStencil::Error, "Plugin '#{gem_name}' already exists !" unless plugins[gem_name].nil? plugin = PowerStencil::Plugins::Base.new(gem_name, self, type: :gem, gem_req: gem_req) plugins[plugin.name] = plugin end end def initialize_local_plugins unless File.directory? project_local_plugins_path PowerStencil.logger.info "No local plugin found in '#{project_local_plugins_path}'" return end Dir.entries(project_local_plugins_path) .select { |e| File.directory? File.join(project_local_plugins_path, e) } .reject { |d| %w(. ..).include? d } .sort .each do |candidate| begin raise PowerStencil::Error, "Plugin '#{candidate}' already exists !" unless plugins[candidate].nil? plugin = PowerStencil::Plugins::Base.new(candidate, self) plugins[plugin.name] = plugin rescue PowerStencil::Error => pse logger.puts_and_logs pse.message, logs_as: :error logger.puts_and_logs "Discarding invalid plugin '#{candidate}'.", logs_as: :error end end end end end end