[Pkg-puppet-devel] [facter] 240/352: [FACT-239] Cleanly evaluate blocks in resolution context

Stig Sandbeck Mathisen ssm at debian.org
Sun Apr 6 22:21:49 UTC 2014


This is an automated email from the git hooks/post-receive script.

ssm pushed a commit to branch master
in repository facter.

commit 7a581bbb73c2d0f7290047a0e19217085bd78a9b
Author: Adrien Thebo <git at somethingsinistral.net>
Date:   Thu Jan 30 14:32:33 2014 -0800

    [FACT-239] Cleanly evaluate blocks in resolution context
    
    doing an `#instance_eval` on another object is a little bit evil and
    entangles the calling object and object being evaluated. This commit
    defines an `#evaluate` method on resolutions so that resolutions can
    define the behavior of evaluating a block.
---
 lib/facter/core/aggregate.rb      |  4 ++++
 lib/facter/util/fact.rb           |  6 +++---
 lib/facter/util/resolution.rb     | 24 ++++++++++++++++++++++++
 spec/unit/core/aggregate_spec.rb  |  7 +++++++
 spec/unit/util/fact_spec.rb       | 11 -----------
 spec/unit/util/resolution_spec.rb | 16 ++++++++++++++++
 6 files changed, 54 insertions(+), 14 deletions(-)

diff --git a/lib/facter/core/aggregate.rb b/lib/facter/core/aggregate.rb
index fa98dff..5637f94 100644
--- a/lib/facter/core/aggregate.rb
+++ b/lib/facter/core/aggregate.rb
@@ -69,6 +69,10 @@ class Facter::Core::Aggregate
     end
   end
 
+  def evaluate(&block)
+    instance_eval(&block)
+  end
+
   # Define a new chunk for the given aggregate
   #
   # @api public
diff --git a/lib/facter/util/fact.rb b/lib/facter/util/fact.rb
index 75f6580..b4a3e58 100644
--- a/lib/facter/util/fact.rb
+++ b/lib/facter/util/fact.rb
@@ -47,7 +47,7 @@ class Facter::Util::Fact
     begin
       resolve = Facter::Util::Resolution.new(@name, self)
 
-      resolve.instance_eval(&block) if block
+      resolve.evaluate(&block) if block
       @resolves << resolve
 
       resolve
@@ -69,10 +69,10 @@ class Facter::Util::Fact
 
     if resolve.nil?
       resolve = Facter::Util::Resolution.new(resolve_name, self)
-      resolve.instance_eval(&block) if block
+      resolve.evaluate(&block) if block
       @resolves << resolve
     else
-      resolve.instance_eval(&block) if block
+      resolve.evaluate(&block) if block
     end
 
   rescue => e
diff --git a/lib/facter/util/resolution.rb b/lib/facter/util/resolution.rb
index af0c7a3..007a4b8 100644
--- a/lib/facter/util/resolution.rb
+++ b/lib/facter/util/resolution.rb
@@ -62,6 +62,30 @@ class Facter::Util::Resolution
     @weight = nil
   end
 
+  # Evaluate the given block in the context of this resolution. If a block has
+  # already been evaluated emit a warning to that effect.
+  #
+  # @return [void]
+  def evaluate(&block)
+    if @last_evaluated
+      msg = "Already evaluated #{@name}"
+      msg << " at #{@last_evaluated}" if msg.is_a? String
+      msg << ", reevaluating anyways"
+      Facter.warn msg
+    end
+
+    instance_eval(&block)
+
+    # Ruby 1.9+ provides the source location of procs which can provide useful
+    # debugging information if a resolution is being evaluated twice. Since 1.8
+    # doesn't support this we opportunistically provide this information.
+    if block.respond_to? :source_location
+      @last_evaluated = block.source_location.join(':')
+    else
+      @last_evaluated = true
+    end
+  end
+
   def set_options(options)
     if options[:name]
       @name = options.delete(:name)
diff --git a/spec/unit/core/aggregate_spec.rb b/spec/unit/core/aggregate_spec.rb
index 875734b..fd4bcb6 100644
--- a/spec/unit/core/aggregate_spec.rb
+++ b/spec/unit/core/aggregate_spec.rb
@@ -140,4 +140,11 @@ describe Facter::Core::Aggregate do
       subject.value
     end
   end
+
+  describe "evaluating" do
+    it "evaluates the block in the context of the aggregate" do
+      subject.expects(:has_weight).with(5)
+      subject.evaluate { has_weight(5) }
+    end
+  end
 end
diff --git a/spec/unit/util/fact_spec.rb b/spec/unit/util/fact_spec.rb
index e1b2ce0..46624a3 100755
--- a/spec/unit/util/fact_spec.rb
+++ b/spec/unit/util/fact_spec.rb
@@ -23,12 +23,6 @@ describe Facter::Util::Fact do
   end
 
   describe "when adding resolution mechanisms" do
-    it "can create a new resolution instance with a block" do
-      Facter::Util::Resolution.expects(:new).at_least_once.returns resolution
-
-      fact.add { }
-    end
-
     it "instance_evals the passed block on the new resolution" do
       fact.add {
         setcode { "foo" }
@@ -52,7 +46,6 @@ describe Facter::Util::Fact do
   end
 
   describe "adding resolution mechanisms by name" do
-    subject(:fact) { described_class.new('yay') }
 
     it "creates a new resolution if no such resolution exists" do
       res = stub 'resolution', :name => 'named'
@@ -74,10 +67,6 @@ describe Facter::Util::Fact do
     end
   end
 
-  it "can able to return a value" do
-    Facter::Util::Fact.new("yay").should respond_to(:value)
-  end
-
   describe "when returning a value" do
     before do
       fact = Facter::Util::Fact.new("yay")
diff --git a/spec/unit/util/resolution_spec.rb b/spec/unit/util/resolution_spec.rb
index bdbe032..2d7c119 100755
--- a/spec/unit/util/resolution_spec.rb
+++ b/spec/unit/util/resolution_spec.rb
@@ -134,4 +134,20 @@ describe Facter::Util::Resolution do
       end.to raise_error(ArgumentError, /Invalid resolution options.*foo/)
     end
   end
+
+  describe "evaluating" do
+    it "evaluates the block in the context of the given resolution" do
+      subject.expects(:has_weight).with(5)
+      subject.evaluate { has_weight(5) }
+    end
+
+    it "raises a warning if the resolution is evaluated twice" do
+      Facter.expects(:warn).with do |msg|
+        expect(msg).to match /Already evaluated foo at.*reevaluating anyways/
+      end
+
+      subject.evaluate { }
+      subject.evaluate { }
+    end
+  end
 end

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-puppet/facter.git



More information about the Pkg-puppet-devel mailing list