public
Rubygem
Description: Simple tool to help track git and svn vendor branches in a git repository
Homepage: http://github.com/evilchelu/braid/wikis/home
Clone URL: git://github.com/evilchelu/braid.git
fix stupid merge :o
evilchelu (author)
Tue Aug 19 12:49:23 -0700 2008
commit  b268e9eed612909502d7c49735cb805ac3f71c18
tree    31f1abbda2fc6fbaed5fef7cc01f6d50cdb9969b
parent  90e9839804add2f32c4d8817850a2c4d6db36b53
...
 
1
2
3
4
5
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
8
 
 
 
 
9
10
11
12
13
14
 
 
 
 
 
 
15
16
 
17
18
19
...
40
41
42
43
 
44
45
46
...
50
51
52
53
 
54
55
56
...
65
66
67
68
69
 
 
70
71
72
...
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
 
 
 
96
97
98
...
106
107
108
109
 
110
111
112
...
200
201
202
203
204
205
 
 
 
206
207
 
 
208
209
 
210
211
212
213
214
215
 
216
217
218
219
220
221
222
223
224
225
 
 
226
227
228
229
230
231
 
 
 
232
233
234
235
236
 
237
238
239
...
244
245
246
247
 
248
249
250
251
252
253
 
254
255
256
...
264
265
266
267
268
269
270
 
 
 
271
272
273
274
 
 
 
275
276
277
278
 
 
 
279
280
281
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
31
32
33
34
35
36
 
 
 
 
37
38
39
40
41
42
43
 
44
45
46
47
...
68
69
70
 
71
72
73
74
...
78
79
80
 
81
82
83
84
...
93
94
95
 
 
96
97
98
99
100
...
109
110
111
 
 
 
 
 
 
 
 
 
 
 
 
112
113
114
115
116
117
...
125
126
127
 
128
129
130
131
...
219
220
221
 
 
 
222
223
224
225
226
227
228
229
 
230
231
232
233
234
235
 
236
237
238
239
 
 
 
 
 
 
 
240
241
242
243
244
 
 
 
245
246
247
248
249
250
251
252
253
254
255
256
...
261
262
263
 
264
265
266
267
 
 
 
268
269
270
271
...
279
280
281
 
 
 
 
282
283
284
285
 
 
 
286
287
288
289
 
 
 
290
291
292
293
294
295
296
297
0
@@ -1,19 +1,47 @@
0
+require 'singleton'
0
 require 'rubygems'
0
 require 'open4'
0
 
0
 module Braid
0
   module Operations
0
     class ShellExecutionError < BraidError
0
+      def initialize(err = nil)
0
+        @err = err
0
+      end
0
+
0
+      def message
0
+        @err.to_s.split("\n").first
0
+      end
0
+    end
0
+    class VersionTooLow < BraidError
0
+      def initialize(command, version)
0
+        @command = command
0
+        @version = version.to_s.split("\n").first
0
+      end
0
+
0
+      def message
0
+        "#{@command} version too low: #{@version}"
0
+      end
0
+    end
0
+    class UnknownRevision < BraidError
0
+      def message
0
+        "unknown revision: #{super}"
0
+      end
0
     end
0
-    class VersionError < BraidError
0
+    class LocalChangesPresent < BraidError
0
+      def message
0
+        "local changes are present"
0
+      end
0
     end
0
 
0
-    # The command proxy is meant to encapsulate commands such as git, git svn and svn, that work with subcommands.
0
-    #
0
-    # It is expected that subclasses override the command method, define a COMMAND constant and have a VersionTooLow exception.
0
-    class CommandProxy
0
+    # The command proxy is meant to encapsulate commands such as git, git-svn and svn, that work with subcommands.
0
+    class Proxy
0
+      include Singleton
0
+
0
+      def self.command; name.split('::').last.downcase; end # hax!
0
+
0
       def version
0
-        status, out, err = exec!("#{self.class::COMMAND} --version")
0
+        status, out, err = exec!("#{self.class.command} --version")
0
         out.sub(/^.* version/, "").strip
0
       end
0
 
0
@@ -40,7 +68,7 @@ module Braid
0
       end
0
 
0
       def require_version!(required)
0
-        require_version(required) || raise(self.class::VersionTooLow, version)
0
+        require_version(required) || raise(VersionTooLow.new(self.class.command, version))
0
       end
0
 
0
       private
0
@@ -50,7 +78,7 @@ module Braid
0
         end
0
 
0
         def invoke(arg, *args)
0
-          exec!("#{command(arg)} #{args.join(' ')}".strip)[1] # return stdout
0
+          exec!("#{command(arg)} #{args.join(' ')}".strip)[1].strip # return stdout
0
         end
0
 
0
         def method_missing(name, *args)
0
@@ -65,8 +93,8 @@ module Braid
0
 
0
           out, err = nil
0
           status = Open4.popen4(cmd) do |pid, stdin, stdout, stderr|
0
-            out = stdout.read.strip
0
-            err = stderr.read.strip
0
+            out = stdout.read
0
+            err = stderr.read
0
           end.exitstatus
0
           [status, out, err]
0
 
0
@@ -81,18 +109,9 @@ module Braid
0
         end
0
     end
0
 
0
-    class Git < CommandProxy
0
-      COMMAND = "git"
0
-
0
-      class UnknownRevision < BraidError
0
-      end
0
-      class LocalChangesPresent < BraidError
0
-      end
0
-      class VersionTooLow < VersionError
0
-      end
0
-
0
-      def commit(message)
0
-        status, out, err = exec("git commit -m #{message.inspect} --no-verify")
0
+    class Git < Proxy
0
+      def commit(message, *args)
0
+        status, out, err = exec("git commit -m #{message.inspect} --no-verify #{args.join(' ')}")
0
 
0
         if status == 0
0
           true
0
@@ -106,7 +125,7 @@ module Braid
0
       def fetch(remote)
0
         # open4 messes with the pipes of index-pack
0
         system("git fetch -n #{remote} &> /dev/null")
0
-        raise ShellExecutionError unless $? == 0
0
+        raise ShellExecutionError, "could not fetch" unless $? == 0
0
         true
0
       end
0
 
0
@@ -200,40 +219,38 @@ module Braid
0
         out[2..-1]
0
       end
0
 
0
-      def apply(diff)
0
-        # always uses index
0
-        status = Open4.popen4("git apply --index -") do |pid, stdin, stdout, stderr|
0
+      def apply(diff, *args)
0
+        err = nil
0
+        status = Open4.popen4("git apply --index --whitespace=nowarn #{args.join(' ')} -") do |pid, stdin, stdout, stderr|
0
           stdin.puts(diff)
0
           stdin.close
0
+
0
+          err = stderr.read
0
         end.exitstatus
0
-        raise ShellExecutionError unless status == 0
0
+        raise ShellExecutionError, err unless status == 0
0
         true
0
       end
0
 
0
       private
0
         def command(name)
0
-          "#{COMMAND} #{name.to_s.gsub('_', '-')}"
0
+          "#{self.class.command} #{name.to_s.gsub('_', '-')}"
0
         end
0
     end
0
 
0
-    class GitSvn < CommandProxy
0
-      COMMAND = "git svn"
0
-
0
-      class UnknownRevision < BraidError
0
-      end
0
-      class VersionTooLow < VersionError
0
-      end
0
+    class GitSvn < Proxy
0
+      def self.command; "git svn"; end
0
 
0
       def commit_hash(remote, revision)
0
         out = invoke(:log, "--show-commit --oneline", "-r #{revision}", remote)
0
-        part = out.split(" | ")[1]
0
-        raise UnknownRevision, "unknown revision: #{revision}" unless part
0
-        Git.new.rev_parse(part) # FIXME ugly ugly ugly
0
+        part = out.to_s.split(" | ")[1]
0
+        raise UnknownRevision, "r#{revision}" unless part
0
+        Git.instance.rev_parse(part) # FIXME ugly ugly ugly
0
       end
0
 
0
       def fetch(remote)
0
         # open4 messes with the pipes of index-pack
0
         system("git svn fetch #{remote} &> /dev/null")
0
+        raise ShellExecutionError, "could not fetch" unless $? == 0
0
         true
0
       end
0
 
0
@@ -244,13 +261,11 @@ module Braid
0
 
0
       private
0
         def command(name)
0
-          "#{COMMAND} #{name}"
0
+          "#{self.class.command} #{name}"
0
         end
0
     end
0
 
0
-    class Svn < CommandProxy
0
-      COMMAND = "svn"
0
-
0
+    class Svn < Proxy
0
       def clean_revision(revision)
0
         revision.to_i if revision
0
       end
0
@@ -264,18 +279,19 @@ module Braid
0
     end
0
 
0
     module VersionControl
0
-      private
0
-        def git
0
-          Git.new
0
-        end
0
+      def git
0
+        Git.instance
0
+      end
0
 
0
-        def git_svn
0
-          GitSvn.new
0
-        end
0
+      def git_svn
0
+        GitSvn.instance
0
+      end
0
 
0
-        def svn
0
-          Svn.new
0
-        end
0
+      def svn
0
+        Svn.instance
0
+      end
0
     end
0
   end
0
 end
0
+
0
+

Comments