lib/plugins/pluginmanager.rb in rsence-2.0.0.9.pre vs lib/plugins/pluginmanager.rb in rsence-2.0.0.10.pre
- old
+ new
@@ -400,58 +400,39 @@
end
return [ bundle_path, src_file ]
end
# Returns true, if the bundle is disabled
- def is_disabled?( bundle_path )
+ def disabled?( bundle_path )
File.exists?( File.join( bundle_path, 'disabled' ) )
end
# Returns true, if the bundle is loaded.
- def is_loaded?( bundle_name )
+ def loaded?( bundle_name )
@registry.has_key?( bundle_name )
end
# Scans a directory of plugins, calls +load_plugin+ for bundles that match
# the definition of a plugin bundle.
# - Skips bundles starting with a dot
# - Skips bundles without a ruby source file with the same
# name as the directory (plus '.rb').
# - Skips bundles containing a file or directory named 'disabled'
- def scan_plugindir( path )
+ def find_bundles( path )
bundles_found = []
Dir.entries(path).each do |bundle_name|
bundle_status = valid_plugindir?( path, bundle_name )
if bundle_status
(bundle_path, src_file) = bundle_status
- bundles_found.push( [bundle_path, bundle_name.to_sym, src_file] )
+ unless disabled?( bundle_path )
+ bundles_found.push( [bundle_path, bundle_name.to_sym, src_file] )
+ end
end
end
return bundles_found
end
- # Top-level method for scanning all plugin directories.
- # Clears previously loaded plugins.
- def scan_plugins
- @registry = {} # bundle_name => bundle_instance mapping
- @info = {} # bundle_name => bundle_info mapping
- @aliases = {} # bundle_alias => bundle_name mapping
- @servlets = [] # bundle_name list of Servlet class instances
- bundles_found = []
- @plugin_paths.each do |path|
- next unless File.directory? path
- bundles_found += scan_plugindir( path )
- end
- bundles_found.each do |bundle_path, bundle_name, src_file|
- unless is_disabled?( bundle_path )
- bundle_found( bundle_path, bundle_name, src_file )
- end
- end
- load_bundles
- delegate( :open )
- end
-
# Unloads the plugin bundle named +bundle_name+
def unload_bundle( bundle_name )
if @registry.has_key?( bundle_name )
unload_order = @deps.del_order( bundle_name )
unload_order.each do |unload_dep|
@@ -474,23 +455,24 @@
end
if @info.include?( bundle_name )
@info.delete( bundle_name )
end
@transporter.online = online_status
+ return unload_order
end
end
# Returns true, if a plugin bundle has changed.
# Only compares timestamp, not checksum.
- def plugin_changed?( plugin_name )
+ def changed?( plugin_name )
info = @info[plugin_name]
last_changed = info[:last_changed]
newest_change = most_recent( info[:path], last_changed )
return last_changed < newest_change
end
- # Logs and speaks the message
+ # Logs and speaks the message, if the speech synthesis command "say" exists.
def say( message )
puts message
if RSence.args[:say]
Thread.new do
Thread.pass
@@ -498,51 +480,85 @@
end
end
end
# Checks for changed plugin bundles and unloads/loads/reloads them accordingly.
- def changed_plugins!
- bundles_found = []
+ def update_bundles!
+ (are_found, to_load, to_unload, to_reload) = [[],[],[],[]]
+ found_map = {}
@plugin_paths.each do |path|
- bundles_found += scan_plugindir( path )
+ are_found += find_bundles( path )
end
- bundle_names_found = []
- bundles_found.each do |bundle_path, bundle_name, src_file|
- bundle_names_found.push( bundle_name )
- is_loaded = is_loaded?( bundle_name )
- if is_loaded and is_disabled?( bundle_path )
- # bundle already loaded but disabled now, should be unloaded:
- unload_bundle( bundle_name )
- say( "Unloaded #{bundle_name}." )
- elsif is_loaded and plugin_changed?( bundle_name )
- # bundle changed, should be reloaded:
- unload_bundle( bundle_name )
- unless @info.has_key?( bundle_name ) and not plugin_changed?( bundle_name )
- @info[bundle_name] = bundle_info( bundle_path, bundle_name, src_file )
- end
- if @deps.resolved?( bundle_name )
- load_bundle( bundle_name )
- say( "Reloaded #{bundle_name}." )
- end
+ are_found.each do |item|
+ (path, name, src_file) = item
+ found_map[name] = item
+ is_loaded = loaded?( name )
+ if is_loaded and changed?( name )
+ to_reload.push( name )
elsif not is_loaded
- # bundle not loaded, should be loaded:
- unless @info.has_key?( bundle_name ) and not plugin_changed?( bundle_name )
- @info[bundle_name] = bundle_info( bundle_path, bundle_name, src_file )
- end
- if @deps.resolved?( bundle_name )
- load_bundle( bundle_name )
- say( "Loaded #{bundle_name}." )
- end
+ to_load.push( name )
end
end
- bundles_missing = @info.keys - bundle_names_found
- bundles_missing.each do |bundle_name|
- say( "#{bundle_name} deleted, unloading.." )
- unload_bundle( bundle_name )
+ @registry.keys.each do |name|
+ to_unload.push( name ) if not found_map.has_key?( name )
end
+ to_unload.each do |name|
+ puts "Unloading #{name.inspect}"
+ unload_bundle( name )
+ end
+ to_reload.each do |name|
+ puts "Unloading #{name.inspect}"
+ unload_order = unload_bundle( name )
+ to_load += unload_order
+ end
+ info_map = {}
+ to_load.each do |name|
+ info_map[name] = bundle_info( *found_map[name] )
+ end
+ no_deps = {}
+ to_load.dup.each do |name|
+ if @deps.unresolved?( name )
+ no_deps[ name ] = @deps.deps_on( name )
+ @deps.del_item( name )
+ to_load.delete( name )
+ end
+ end
+ to_open = []
+ @deps.list.each do |name|
+ next unless to_load.include?( name )
+ info = info_map[name]
+ if to_reload.include?( name )
+ puts "Reloading #{name.inspect}"
+ else
+ puts "Loading #{name.inspect}"
+ end
+ @info[name] = info
+ load_bundle( name )
+ to_open.push( name )
+ end
+ unless no_deps.empty?
+ warn "Warning! Unable to load the following bundles; missing dependencies:"
+ no_deps.each do |name,deps|
+ warn " #{name} depends on: #{deps.join(', ')}"
+ end
+ end
+ to_open.each do |name|
+ puts "Opening #{name.inspect}"
+ call( name, :open )
+ end
end
+ # Top-level method for scanning all plugin directories.
+ # Clears previously loaded plugins.
+ def init_bundles!
+ @registry = {} # bundle_name => bundle_instance mapping
+ @info = {} # bundle_name => bundle_info mapping
+ @aliases = {} # bundle_alias => bundle_name mapping
+ @servlets = [] # bundle_name list of Servlet class instances
+ update_bundles!
+ end
+
# Initialize with a list of directories as plugin_paths.
# It's an array containing all plugin directories to scan.
def initialize( plugin_paths, transporter=nil,
autoreload=false, name_prefix=false,
resolved_deps=[], resolved_categories={} )
@@ -552,19 +568,19 @@
end
@name_prefix = name_prefix
@plugin_paths = plugin_paths
@deps = Dependencies.new( resolved_deps, resolved_categories )
puts "Loading #{name_prefix+' ' if name_prefix}plugins..." if RSence.args[:verbose]
- scan_plugins
+ init_bundles!
puts %{Plugins #{"of #{name_prefix} " if name_prefix}loaded.} if RSence.args[:verbose]
if autoreload
@thr = Thread.new do
Thread.pass
while true
begin
- changed_plugins!
+ update_bundles!
rescue => e
- warn e.inspect
+ plugin_error( e, "PluginManager#update_bundles!", "An error occurred while reloading bundles" )
end
sleep 3
end
end
end