<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,19 +1,47 @@
+require 'singleton'
 require 'rubygems'
 require 'open4'
 
 module Braid
   module Operations
     class ShellExecutionError &lt; BraidError
+      def initialize(err = nil)
+        @err = err
+      end
+
+      def message
+        @err.to_s.split(&quot;\n&quot;).first
+      end
+    end
+    class VersionTooLow &lt; BraidError
+      def initialize(command, version)
+        @command = command
+        @version = version.to_s.split(&quot;\n&quot;).first
+      end
+
+      def message
+        &quot;#{@command} version too low: #{@version}&quot;
+      end
+    end
+    class UnknownRevision &lt; BraidError
+      def message
+        &quot;unknown revision: #{super}&quot;
+      end
     end
-    class VersionError &lt; BraidError
+    class LocalChangesPresent &lt; BraidError
+      def message
+        &quot;local changes are present&quot;
+      end
     end
 
-    # The command proxy is meant to encapsulate commands such as git, git svn and svn, that work with subcommands.
-    #
-    # It is expected that subclasses override the command method, define a COMMAND constant and have a VersionTooLow exception.
-    class CommandProxy
+    # The command proxy is meant to encapsulate commands such as git, git-svn and svn, that work with subcommands.
+    class Proxy
+      include Singleton
+
+      def self.command; name.split('::').last.downcase; end # hax!
+
       def version
-        status, out, err = exec!(&quot;#{self.class::COMMAND} --version&quot;)
+        status, out, err = exec!(&quot;#{self.class.command} --version&quot;)
         out.sub(/^.* version/, &quot;&quot;).strip
       end
 
@@ -40,7 +68,7 @@ module Braid
       end
 
       def require_version!(required)
-        require_version(required) || raise(self.class::VersionTooLow, version)
+        require_version(required) || raise(VersionTooLow.new(self.class.command, version))
       end
 
       private
@@ -50,7 +78,7 @@ module Braid
         end
 
         def invoke(arg, *args)
-          exec!(&quot;#{command(arg)} #{args.join(' ')}&quot;.strip)[1] # return stdout
+          exec!(&quot;#{command(arg)} #{args.join(' ')}&quot;.strip)[1].strip # return stdout
         end
 
         def method_missing(name, *args)
@@ -65,8 +93,8 @@ module Braid
 
           out, err = nil
           status = Open4.popen4(cmd) do |pid, stdin, stdout, stderr|
-            out = stdout.read.strip
-            err = stderr.read.strip
+            out = stdout.read
+            err = stderr.read
           end.exitstatus
           [status, out, err]
 
@@ -81,18 +109,9 @@ module Braid
         end
     end
 
-    class Git &lt; CommandProxy
-      COMMAND = &quot;git&quot;
-
-      class UnknownRevision &lt; BraidError
-      end
-      class LocalChangesPresent &lt; BraidError
-      end
-      class VersionTooLow &lt; VersionError
-      end
-
-      def commit(message)
-        status, out, err = exec(&quot;git commit -m #{message.inspect} --no-verify&quot;)
+    class Git &lt; Proxy
+      def commit(message, *args)
+        status, out, err = exec(&quot;git commit -m #{message.inspect} --no-verify #{args.join(' ')}&quot;)
 
         if status == 0
           true
@@ -106,7 +125,7 @@ module Braid
       def fetch(remote)
         # open4 messes with the pipes of index-pack
         system(&quot;git fetch -n #{remote} &amp;&gt; /dev/null&quot;)
-        raise ShellExecutionError unless $? == 0
+        raise ShellExecutionError, &quot;could not fetch&quot; unless $? == 0
         true
       end
 
@@ -200,40 +219,38 @@ module Braid
         out[2..-1]
       end
 
-      def apply(diff)
-        # always uses index
-        status = Open4.popen4(&quot;git apply --index -&quot;) do |pid, stdin, stdout, stderr|
+      def apply(diff, *args)
+        err = nil
+        status = Open4.popen4(&quot;git apply --index --whitespace=nowarn #{args.join(' ')} -&quot;) do |pid, stdin, stdout, stderr|
           stdin.puts(diff)
           stdin.close
+
+          err = stderr.read
         end.exitstatus
-        raise ShellExecutionError unless status == 0
+        raise ShellExecutionError, err unless status == 0
         true
       end
 
       private
         def command(name)
-          &quot;#{COMMAND} #{name.to_s.gsub('_', '-')}&quot;
+          &quot;#{self.class.command} #{name.to_s.gsub('_', '-')}&quot;
         end
     end
 
-    class GitSvn &lt; CommandProxy
-      COMMAND = &quot;git svn&quot;
-
-      class UnknownRevision &lt; BraidError
-      end
-      class VersionTooLow &lt; VersionError
-      end
+    class GitSvn &lt; Proxy
+      def self.command; &quot;git svn&quot;; end
 
       def commit_hash(remote, revision)
         out = invoke(:log, &quot;--show-commit --oneline&quot;, &quot;-r #{revision}&quot;, remote)
-        part = out.split(&quot; | &quot;)[1]
-        raise UnknownRevision, &quot;unknown revision: #{revision}&quot; unless part
-        Git.new.rev_parse(part) # FIXME ugly ugly ugly
+        part = out.to_s.split(&quot; | &quot;)[1]
+        raise UnknownRevision, &quot;r#{revision}&quot; unless part
+        Git.instance.rev_parse(part) # FIXME ugly ugly ugly
       end
 
       def fetch(remote)
         # open4 messes with the pipes of index-pack
         system(&quot;git svn fetch #{remote} &amp;&gt; /dev/null&quot;)
+        raise ShellExecutionError, &quot;could not fetch&quot; unless $? == 0
         true
       end
 
@@ -244,13 +261,11 @@ module Braid
 
       private
         def command(name)
-          &quot;#{COMMAND} #{name}&quot;
+          &quot;#{self.class.command} #{name}&quot;
         end
     end
 
-    class Svn &lt; CommandProxy
-      COMMAND = &quot;svn&quot;
-
+    class Svn &lt; Proxy
       def clean_revision(revision)
         revision.to_i if revision
       end
@@ -264,18 +279,19 @@ module Braid
     end
 
     module VersionControl
-      private
-        def git
-          Git.new
-        end
+      def git
+        Git.instance
+      end
 
-        def git_svn
-          GitSvn.new
-        end
+      def git_svn
+        GitSvn.instance
+      end
 
-        def svn
-          Svn.new
-        end
+      def svn
+        Svn.instance
+      end
     end
   end
 end
+
+</diff>
      <filename>lib/braid/operations.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>90e9839804add2f32c4d8817850a2c4d6db36b53</id>
    </parent>
  </parents>
  <author>
    <name>Cristi Balan</name>
    <email>evil@che.lu</email>
  </author>
  <url>http://github.com/evilchelu/braid/commit/b268e9eed612909502d7c49735cb805ac3f71c18</url>
  <id>b268e9eed612909502d7c49735cb805ac3f71c18</id>
  <committed-date>2008-08-19T12:49:23-07:00</committed-date>
  <authored-date>2008-08-19T12:49:23-07:00</authored-date>
  <message>fix stupid merge :o</message>
  <tree>31f1abbda2fc6fbaed5fef7cc01f6d50cdb9969b</tree>
  <committer>
    <name>Cristi Balan</name>
    <email>evil@che.lu</email>
  </committer>
</commit>
