<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -46,6 +46,8 @@ BANNER
           &quot;Verbose output&quot;) { |OPTIONS[:verbose]| }
   opts.on(&quot;-c&quot;, &quot;--cloud&quot;,
           &quot;Show powder cloud, ie. package hierarchy and installation order&quot;) { |OPTIONS[:cloud]| }
+  opts.on(&quot;-f&quot;, &quot;--force&quot;,
+          &quot;Force installation of all packages even if it is detected that it has been previously installed&quot;) { |OPTIONS[:force]| }
   opts.on(&quot;-h&quot;, &quot;--help&quot;,
           &quot;Show this help message.&quot;) { puts opts; exit }
   opts.parse!(ARGV)
@@ -55,6 +57,10 @@ BANNER
   end
 end
 
+def force_mode(options)
+  Sprinkle::OPTIONS[:force] = OPTIONS[:force] || false
+end
+
 def operation_mode(options)
   Sprinkle::OPTIONS[:testing] = OPTIONS[:testing] || false
 end
@@ -72,6 +78,7 @@ require 'sprinkle'
 powder = OPTIONS[:path]
 raise &quot;Sprinkle script is not readable: #{powder}&quot; unless File.readable?(powder)
 
+force_mode(OPTIONS)
 operation_mode(OPTIONS)
 powder_cloud(OPTIONS)
 log_level(OPTIONS)</diff>
      <filename>bin/sprinkle</filename>
    </modified>
    <modified>
      <diff>@@ -13,7 +13,7 @@ Dir[File.dirname(__FILE__) + '/sprinkle/extensions/*.rb'].each { |e| require e }
 
 # Configuration options
 module Sprinkle
-  OPTIONS = { :testing =&gt; false, :verbose =&gt; false }
+  OPTIONS = { :testing =&gt; false, :verbose =&gt; false, :force =&gt; false }
 end
 
 # Define a logging target and understand packages, policies and deployment DSL</diff>
      <filename>lib/sprinkle.rb</filename>
    </modified>
    <modified>
      <diff>@@ -52,10 +52,25 @@ module Sprinkle
 
       def process(deployment, roles)
         return if meta_package?
+        
+        # Run a pre-test to see if the software is already installed. If so,
+        # we can skip it, unless we have the force option turned on!
+        unless @verifications.empty? || Sprinkle::OPTIONS[:force]
+          begin
+            process_verifications(deployment, roles)
+            return
+          rescue Sprinkle::VerificationFailed =&gt; e
+            # Continue
+          end
+        end
 
         @installer.defaults(deployment)
         @installer.process(roles)
         
+        process_verifications(deployment, roles)
+      end
+      
+      def process_verifications(deployment, roles)
         @verifications.each do |v|
           v.defaults(deployment)
           v.process(roles)</diff>
      <filename>lib/sprinkle/package.rb</filename>
    </modified>
    <modified>
      <diff>@@ -20,7 +20,11 @@ module Sprinkle
       
       unless Sprinkle::OPTIONS[:testing]
         logger.info &quot;--&gt; Verifying #{@package.name} for roles: #{roles}&quot;
-        @delivery.process(@package.name, @commands, roles).to_s
+        
+        unless @delivery.process(@package.name, @commands, roles, true)
+          # Verification failed, halt sprinkling gracefully.
+          raise Sprinkle::VerificationFailed.new(@package, @description)
+        end
       end
     end
     
@@ -32,4 +36,15 @@ module Sprinkle
       @commands &lt;&lt; &quot;test -d #{dir}&quot;
     end
   end
+  
+  class VerificationFailed &lt; Exception
+    attr_accessor :package, :description
+    
+    def initialize(package, description)
+      super(&quot;Verifying #{package.name}#{description} failed.&quot;)
+      
+      @package = package
+      @description = description
+    end
+  end
 end
\ No newline at end of file</diff>
      <filename>lib/sprinkle/verify.rb</filename>
    </modified>
    <modified>
      <diff>@@ -240,25 +240,83 @@ CODE
         @installer.stub!(:process)
       end
       
-      it 'should request _each_ verification to configure itself against the deployment context' do
-        @pkg.verifications.each do |v|
-          v.should_receive(:defaults).with(@deployment).once
-          v.stub!(:process)
+      describe 'with forcing' do
+        before do
+          # Being explicit
+          Sprinkle::OPTIONS[:force] = true
         end
         
-        @pkg.process(@deployment, @roles)
+        it 'should process verifications only once' do
+          @pkg.should_receive(:process_verifications).once
+          @pkg.process(@deployment, @roles)
+        end
+        
+        after do
+          # Being explicit
+          Sprinkle::OPTIONS[:force] = false
+        end
       end
       
-      it 'should request _each_ verification to process' do
-        @pkg.verifications.each do |v|
-          v.stub!(:defaults)
-          v.should_receive(:process).with(@roles).once
+      describe 'without forcing' do
+        before do
+          # Being explicit
+          Sprinkle::OPTIONS[:force] = false
+        end
+        
+        it 'should process verifications twice' do
+          @pkg.should_receive(:process_verifications).twice.and_raise(Sprinkle::VerificationFailed.new(@pkg, ''))
+        end
+        
+        it 'should continue with installation if pre-verification fails' do
+          @pkg.should_receive(:process_verifications).twice.and_raise(Sprinkle::VerificationFailed.new(@pkg, ''))
+          @installer.should_receive(:defaults)
+          @installer.should_receive(:process)
         end
         
-        @pkg.process(@deployment, @roles)
+        it 'should only process verifications once and should not process installer if verifications succeed' do
+          @pkg.should_receive(:process_verifications).once.and_return(nil)
+          @installer.should_not_receive(:defaults)
+          @installer.should_not_receive(:process)
+        end
+        
+        after do
+          begin
+            @pkg.process(@deployment, @roles)
+          rescue Sprinkle::VerificationFailed =&gt; e; end
+        end
+      end
+    end
+
+  end
+  
+  describe 'when processing verifications' do
+    before do
+      @deployment = mock(Sprinkle::Deployment)
+      @roles = [ :app, :db ]
+      @installer = mock(Sprinkle::Installers::Installer, :defaults =&gt; true, :process =&gt; true)
+      @pkg = create_package_with_blank_verify(3)
+      @pkg.installer = @installer
+      @installer.stub!(:defaults)
+      @installer.stub!(:process)
+    end
+    
+    it 'should request _each_ verification to configure itself against the deployment context' do
+      @pkg.verifications.each do |v|
+        v.should_receive(:defaults).with(@deployment).once
+        v.stub!(:process)
       end
     end
 
+    it 'should request _each_ verification to process' do
+      @pkg.verifications.each do |v|
+        v.stub!(:defaults)
+        v.should_receive(:process).with(@roles).once
+      end
+    end
+    
+    after do
+      @pkg.process_verifications(@deployment, @roles)
+    end
   end
 
   describe 'hierarchies' do</diff>
      <filename>spec/sprinkle/package_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,7 @@ describe Sprinkle::Verify do
     @name = :package
     @package = package @name do
       gem 'nonexistent'
-      verify do
+      verify 'moo' do
         has_file 'my_file.txt'
         has_directory 'mydir'
       end
@@ -55,9 +55,17 @@ describe Sprinkle::Verify do
       end
       
       it 'should call process on the delivery with the correct parameters' do
-        @delivery.should_receive(:process).with(@name, @verification.commands, [:app]).once
+        @delivery.should_receive(:process).with(@name, @verification.commands, [:app], true).once.and_return(true)
         @verification.process([:app])
       end
+      
+      it 'should raise Sprinkle::VerificationFailed exception when commands fail' do
+        @delivery.should_receive(:process).once.and_return(false)
+        lambda { @verification.process([:app]) }.should raise_error(Sprinkle::VerificationFailed) do |error|
+          error.package.should eql(@package)
+          error.description.should eql('moo')
+        end
+      end
     end
     
     describe 'when testing' do</diff>
      <filename>spec/sprinkle/verify_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>8255114c7d49999c95c7aa914e2fdcffc6624c19</id>
    </parent>
  </parents>
  <author>
    <name>Mitchell Hashimoto</name>
    <email>mitchell.hashimoto@gmail.com</email>
  </author>
  <url>http://github.com/crafterm/sprinkle/commit/92d49aa3bba21e3e7b139f7cc836d7e392c0f015</url>
  <id>92d49aa3bba21e3e7b139f7cc836d7e392c0f015</id>
  <committed-date>2008-07-17T02:51:47-07:00</committed-date>
  <authored-date>2008-07-17T02:51:47-07:00</authored-date>
  <message>When a verification fails, the VerificationFailed exception is raised. Verifications are ran BEFORE a package is installed to check if it has already been installed. If so, it skips. The -f flag has been introduced to force the installation regardless of whether the pre-verification is successful.</message>
  <tree>e136afdf403b1b09ba60e5028170050937f1db3f</tree>
  <committer>
    <name>Mitchell Hashimoto</name>
    <email>mitchell.hashimoto@gmail.com</email>
  </committer>
</commit>
