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.

Reply via email to