This allows rubygems to be used to extend or override puppet behavior. Unfortunately the features system uses the autoloader so checking for the rubygems feature causes a call loop. It's possible that a more elegant way to avoid this exist rather than just checking the @path but this did what I needed to do.
Without caching the directories the tests would take forever to run and eventually crash my server. Caching seems to avoid the biggest of the performance hit. Signed-off-by: R.I.Pienaar <r...@devco.net> --- Local-branch: feature/master/7788 lib/puppet/util/autoload.rb | 21 +++++++++++++++++++-- spec/unit/util/autoload_spec.rb | 10 +++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/lib/puppet/util/autoload.rb b/lib/puppet/util/autoload.rb index 6537a4a..828f069 100644 --- a/lib/puppet/util/autoload.rb +++ b/lib/puppet/util/autoload.rb @@ -124,9 +124,26 @@ class Puppet::Util::Autoload searchpath.map { |dir| Dir.glob("#{dir}/*.rb") }.flatten end - # The list of directories to search through for loadable plugins. + # features uses the autoloader which causes a loop so avoid trying to + # ask Gem for its path during feature loading. + # + # We're using a per-thread cache based on the code in #module_directories. + def gemsearchpaths + unless @path == "puppet/feature" + if Puppet.features.rubygems? + Thread.current[:gemsearch_directories] ||= [] + Thread.current[:gemsearch_directories] = Gem.all_load_paths if Thread.current[:gemsearch_directories].empty? + return Thread.current[:gemsearch_directories] + end + end + + return [] + end + + # The list of directories to search through for loadable plugins. We search gem paths first + # so that people can use the gem packages to override core puppet features if they wish. def searchpath(env=nil) - search_directories(env).uniq.collect { |d| File.join(d, @path) }.find_all { |d| FileTest.directory?(d) } + [gemsearchpaths, search_directories(env)].flatten.uniq.collect { |d| File.join(d, @path) }.find_all { |d| FileTest.directory?(d) } end def module_directories(env=nil) diff --git a/spec/unit/util/autoload_spec.rb b/spec/unit/util/autoload_spec.rb index d61b768..e962b1e 100755 --- a/spec/unit/util/autoload_spec.rb +++ b/spec/unit/util/autoload_spec.rb @@ -51,13 +51,21 @@ describe Puppet::Util::Autoload do @autoload.search_directories.should == %w{/one /two /libdir1 /lib/dir/two /third/lib/dir} + $LOAD_PATH end + it "should not try to merge rubygems dirs when called from the feature system" do + @autoload = Puppet::Util::Autoload.new("foo", "puppet/feature") + Puppet.features.expects(:rubygems?).never + @autoload.gemsearchpaths + end + it "should include in its search path all of the unique search directories that have a subdirectory matching the autoload path" do @autoload = Puppet::Util::Autoload.new("foo", "loaddir") @autoload.expects(:search_directories).returns %w{/one /two /three /three} + @autoload.expects(:gemsearchpaths).returns %w{/four /four} FileTest.expects(:directory?).with("/one/loaddir").returns true FileTest.expects(:directory?).with("/two/loaddir").returns false FileTest.expects(:directory?).with("/three/loaddir").returns true - @autoload.searchpath.should == ["/one/loaddir", "/three/loaddir"] + FileTest.expects(:directory?).with("/four/loaddir").returns true + @autoload.searchpath.should == ["/four/loaddir", "/one/loaddir", "/three/loaddir"] end end -- 1.7.1 -- You received this message because you are subscribed to the Google Groups "Puppet Developers" group. To post to this group, send email to puppet-dev@googlegroups.com. To unsubscribe from this group, send email to puppet-dev+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-dev?hl=en.