summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet/util/autoload.rb59
-rwxr-xr-xtest/util/autoload.rb49
2 files changed, 76 insertions, 32 deletions
diff --git a/lib/puppet/util/autoload.rb b/lib/puppet/util/autoload.rb
index ac4939a0b..42aa56c32 100644
--- a/lib/puppet/util/autoload.rb
+++ b/lib/puppet/util/autoload.rb
@@ -3,20 +3,42 @@ class Puppet::Util::Autoload
include Puppet::Util
@autoloaders = {}
-
- attr_accessor :object, :path, :objwarn, :wrap
-
+ @loaded = {}
class << self
attr_reader :autoloaders
private :autoloaders
end
- Puppet::Util.classproxy self, :autoloaders, "[]", "[]=", :clear
- attr_reader :loaded
- private :loaded
+ # Send [], []=, and :clear to the @autloaders hash
+ Puppet::Util.classproxy self, :autoloaders, "[]", "[]="
+
+ # Clear the list of autoloaders and loaded files.
+ def self.clear
+ @autoloaders.clear
+ @loaded.clear
+ end
+
+ # List all loaded files.
+ def self.list_loaded
+ @loaded.sort { |a,b| a[0] <=> b[0] }.collect do |path, hash|
+ "%s: %s" % [path, hash[:file]]
+ end
+ end
+
+ # Has a given path been loaded? This is used for testing whether a
+ # changed file should be loaded or just ignored.
+ def self.loaded?(path)
+ path = path.to_s.sub(/\.rb$/, '')
+ @loaded[path]
+ end
+
+ # Save the fact that a given path has been loaded
+ def self.loaded(path, file, loader)
+ @loaded[path] = {:file => file, :autoloader => loader}
+ end
- Puppet::Util.proxy self, :loaded, :clear
+ attr_accessor :object, :path, :objwarn, :wrap
def initialize(obj, path, options = {})
@path = path.to_s
@@ -39,11 +61,10 @@ class Puppet::Util::Autoload
unless defined? @wrap
@wrap = true
end
-
- @loaded = {}
end
- # Load a single plugin by name.
+ # Load a single plugin by name. We use 'load' here so we can reload a
+ # given plugin.
def load(name)
path = name.to_s + ".rb"
@@ -53,7 +74,7 @@ class Puppet::Util::Autoload
begin
Kernel.load file, @wrap
name = symbolize(name)
- @loaded[name] = true
+ loaded name, file
return true
rescue LoadError => detail
# I have no idea what's going on here, but different versions
@@ -70,11 +91,19 @@ class Puppet::Util::Autoload
return false
end
+ # Mark the named object as loaded. Note that this supports unqualified
+ # queries, while we store the result as a qualified query in the class.
+ def loaded(name, file)
+ self.class.loaded(File.join(@path, name.to_s), file, object)
+ end
+
# Indicate whether the specfied plugin has been loaded.
def loaded?(name)
- @loaded[symbolize(name)]
+ self.class.loaded?(File.join(@path, name.to_s))
end
+ # Load all instances that we can. This uses require, rather than load,
+ # so that already-loaded files don't get reloaded unnecessarily.
def loadall
# Load every instance of everything we can find.
eachdir do |dir|
@@ -84,12 +113,12 @@ class Puppet::Util::Autoload
# believe, but it works as long as real classes
# aren't used.
name = File.basename(file).sub(".rb", '').intern
- next if @loaded.include? name
+ next if loaded?(name)
next if $".include?(File.join(@path, name.to_s + ".rb"))
filepath = File.join(@path, name.to_s + ".rb")
begin
- Kernel.require filepath
- @loaded[name] = true
+ Kernel.require file
+ loaded(name, file)
rescue => detail
if Puppet[:trace]
puts detail.backtrace
diff --git a/test/util/autoload.rb b/test/util/autoload.rb
index 4be6b3930..493fd7f60 100755
--- a/test/util/autoload.rb
+++ b/test/util/autoload.rb
@@ -30,12 +30,7 @@ TestAutoload.newthing(:#{name.to_s})
end
end
- def teardown
- super
- self.class.clear
- end
-
- def test_load
+ def mk_loader(name)
dir = tempfile()
$: << dir
cleanup do
@@ -44,19 +39,26 @@ TestAutoload.newthing(:#{name.to_s})
Dir.mkdir(dir)
- rbdir = File.join(dir, "yayness")
+ rbdir = File.join(dir, name.to_s)
Dir.mkdir(rbdir)
- # An object for specifying autoload
- klass = self.class
-
loader = nil
assert_nothing_raised {
- loader = Puppet::Util::Autoload.new(klass, :yayness)
+ loader = Puppet::Util::Autoload.new(self.class, name)
}
+ return rbdir, loader
+ end
+
+ def teardown
+ super
+ Puppet::Util::Autoload.clear
+ end
+
+ def test_load
+ dir, loader = mk_loader(:yayness)
- assert_equal(loader.object_id, Puppet::Util::Autoload[klass].object_id,
+ assert_equal(loader.object_id, Puppet::Util::Autoload[self.class].object_id,
"Did not retrieve loader object by class")
# Make sure we don't fail on missing files
@@ -66,9 +68,9 @@ TestAutoload.newthing(:#{name.to_s})
}
# Now create a couple of files for testing
- path = File.join(rbdir, "mything.rb")
+ path = File.join(dir, "mything.rb")
mkfile(:mything, path)
- opath = File.join(rbdir, "othing.rb")
+ opath = File.join(dir, "othing.rb")
mkfile(:othing, opath)
# Now try to actually load it.
@@ -79,12 +81,12 @@ TestAutoload.newthing(:#{name.to_s})
assert(loader.loaded?(:mything), "Not considered loaded")
- assert(klass.thing?(:mything),
+ assert(self.class.thing?(:mything),
"Did not get loaded thing")
# Now clear everything, and test loadall
assert_nothing_raised {
- loader.clear
+ Puppet::Util::Autoload.clear
}
self.class.clear
@@ -95,10 +97,23 @@ TestAutoload.newthing(:#{name.to_s})
[:mything, :othing].each do |thing|
assert(loader.loaded?(thing), "#{thing.to_s} not considered loaded")
+ assert(loader.loaded?("%s.rb" % thing), "#{thing.to_s} not considered loaded with .rb")
+ assert(Puppet::Util::Autoload.loaded?("yayness/%s" % thing), "%s not considered loaded by the main class" % thing)
+ assert(Puppet::Util::Autoload.loaded?("yayness/%s.rb" % thing), "%s not considered loaded by the main class with .rb" % thing)
- assert(klass.thing?(thing),
+ loaded = Puppet::Util::Autoload.loaded?("yayness/%s.rb" % thing)
+ assert_equal("%s/%s.rb" % [dir, thing], loaded[:file], "File path was not set correctly in loaded store")
+ assert_equal(self.class, loaded[:autoloader], "Loader was not set correctly in loaded store")
+
+ assert(self.class.thing?(thing),
"Did not get loaded #{thing.to_s}")
end
+
+ Puppet::Util::Autoload.clear
+ [:mything, :othing].each do |thing|
+ assert(! loader.loaded?(thing), "#{thing.to_s} considered loaded after clear")
+ assert(! Puppet::Util::Autoload.loaded?("yayness/%s" % thing), "%s considered loaded by the main class after clear" % thing)
+ end
end
# Make sure that autoload dynamically modifies $: with the libdir as