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
add adding integration specs and some crappy helpers
evilchelu (author)
Sun Jul 20 20:10:31 -0700 2008
commit  0d77e1e840c851b114595f5de968f92c82f7b3e1
tree    eab53ec36bc4cc24c2373bcd52f1c2619cdd78d9
parent  21b660817f14333304e51a67fb7f700a1b0f678c
...
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
...
 
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
0
@@ -1,47 +1,19 @@
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
+    class VersionError < BraidError
0
     end
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
-    class Proxy
0
-      include Singleton
0
-
0
-      def self.command; name.split('::').last.downcase; end # hax!
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
       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
@@ -68,7 +40,7 @@ module Braid
0
       end
0
 
0
       def require_version!(required)
0
-        require_version(required) || raise(VersionTooLow.new(self.class.command, version))
0
+        require_version(required) || raise(self.class::VersionTooLow, version)
0
       end
0
 
0
       private
0
@@ -78,7 +50,7 @@ module Braid
0
         end
0
 
0
         def invoke(arg, *args)
0
-          exec!("#{command(arg)} #{args.join(' ')}".strip)[1].strip # return stdout
0
+          exec!("#{command(arg)} #{args.join(' ')}".strip)[1] # return stdout
0
         end
0
 
0
         def method_missing(name, *args)
0
@@ -93,8 +65,8 @@ module Braid
0
 
0
           out, err = nil
0
           status = Open4.popen4(cmd) do |pid, stdin, stdout, stderr|
0
-            out = stdout.read
0
-            err = stderr.read
0
+            out = stdout.read.strip
0
+            err = stderr.read.strip
0
           end.exitstatus
0
           [status, out, err]
0
 
0
@@ -109,9 +81,18 @@ module Braid
0
         end
0
     end
0
 
0
-    class Git < Proxy
0
-      def commit(message, *args)
0
-        status, out, err = exec("git commit -m #{message.inspect} --no-verify #{args.join(' ')}")
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
 
0
         if status == 0
0
           true
0
@@ -125,7 +106,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, "could not fetch" unless $? == 0
0
+        raise ShellExecutionError unless $? == 0
0
         true
0
       end
0
 
0
@@ -219,38 +200,40 @@ module Braid
0
         out[2..-1]
0
       end
0
 
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
+      def apply(diff)
0
+        # always uses index
0
+        status = Open4.popen4("git apply --index -") do |pid, stdin, stdout, stderr|
0
           stdin.puts(diff)
0
           stdin.close
0
-
0
-          err = stderr.read
0
         end.exitstatus
0
-        raise ShellExecutionError, err unless status == 0
0
+        raise ShellExecutionError unless status == 0
0
         true
0
       end
0
 
0
       private
0
         def command(name)
0
-          "#{self.class.command} #{name.to_s.gsub('_', '-')}"
0
+          "#{COMMAND} #{name.to_s.gsub('_', '-')}"
0
         end
0
     end
0
 
0
-    class GitSvn < Proxy
0
-      def self.command; "git svn"; end
0
+    class GitSvn < CommandProxy
0
+      COMMAND = "git svn"
0
+
0
+      class UnknownRevision < BraidError
0
+      end
0
+      class VersionTooLow < VersionError
0
+      end
0
 
0
       def commit_hash(remote, revision)
0
         out = invoke(:log, "--show-commit --oneline", "-r #{revision}", remote)
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
+        part = out.split(" | ")[1]
0
+        raise UnknownRevision, "unknown revision: #{revision}" unless part
0
+        Git.new.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
@@ -261,11 +244,13 @@ module Braid
0
 
0
       private
0
         def command(name)
0
-          "#{self.class.command} #{name}"
0
+          "#{COMMAND} #{name}"
0
         end
0
     end
0
 
0
-    class Svn < Proxy
0
+    class Svn < CommandProxy
0
+      COMMAND = "svn"
0
+
0
       def clean_revision(revision)
0
         revision.to_i if revision
0
       end
0
@@ -279,17 +264,18 @@ module Braid
0
     end
0
 
0
     module VersionControl
0
-      def git
0
-        Git.instance
0
-      end
0
+      private
0
+        def git
0
+          Git.new
0
+        end
0
 
0
-      def git_svn
0
-        GitSvn.instance
0
-      end
0
+        def git_svn
0
+          GitSvn.new
0
+        end
0
 
0
-      def svn
0
-        Svn.instance
0
-      end
0
+        def svn
0
+          Svn.new
0
+        end
0
     end
0
   end
0
 end

Comments