public
Description: The Git TextMate Bundle
Homepage: http://tim.theenchanter.com/
Clone URL: git://github.com/timcharper/git-tmbundle.git
major MVC overhaul - old structure has been 95% eliminated.  Formatters 
eliminated.  more specs and better coverage.
timcharper (author)
Thu Mar 06 03:01:30 -0800 2008
commit  f4e7c4b53ae55e41e3126a59e9a8defe0e40f434
tree    f4fb31c5f5fffac8413afb637ddbe73edf8a4a70
parent  2e7dea82de6023eaa0f1afa49f5707b81a29bf81
...
8
9
10
11
12
13
 
14
15
16
...
8
9
10
 
 
 
11
12
13
14
0
@@ -8,9 +8,7 @@
0
   <string>#!/usr/bin/env ruby
0
 
0
 require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
0
-git = Git::Fetch.new
0
-git.run
0
-</string>
0
+dispatch :controller =&gt; "remote", :action =&gt; "fetch"</string>
0
   <key>input</key>
0
   <string>selection</string>
0
   <key>keyEquivalent</key>
...
8
9
10
11
12
13
14
 
15
16
17
...
8
9
10
 
 
 
 
11
12
13
14
0
@@ -8,10 +8,7 @@
0
   <string>#!/usr/bin/env ruby
0
 
0
 require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
0
-git = Git::Pull.new
0
-git.run
0
-
0
-rescan_project</string>
0
+dispatch :controller =&gt; "remote", :action =&gt; "pull"</string>
0
   <key>input</key>
0
   <string>selection</string>
0
   <key>keyEquivalent</key>
...
8
9
10
11
12
13
 
14
15
16
...
8
9
10
 
 
 
11
12
13
14
0
@@ -8,9 +8,7 @@
0
   <string>#!/usr/bin/env ruby
0
 
0
 require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
0
-git = Git::Push.new
0
-git.run
0
-</string>
0
+dispatch :controller =&gt; "remote", :action =&gt; "push"</string>
0
   <key>input</key>
0
   <string>selection</string>
0
   <key>keyEquivalent</key>
...
6
7
8
9
10
11
12
13
 
 
14
15
16
...
6
7
8
 
 
 
9
 
10
11
12
13
14
0
@@ -6,11 +6,9 @@
0
   <string>nop</string>
0
   <key>command</key>
0
   <string>#!/usr/bin/env ruby
0
-require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
0
-git = SCM::Git::SVNDcommit.new
0
-git.run
0
 
0
-rescan_project</string>
0
+require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
0
+dispatch :controller =&gt; "svn", :action =&gt; "dcommit"</string>
0
   <key>input</key>
0
   <string>selection</string>
0
   <key>keyEquivalent</key>
...
6
7
8
9
10
11
12
13
 
 
14
15
16
...
6
7
8
 
 
 
9
 
10
11
12
13
14
0
@@ -6,11 +6,9 @@
0
   <string>nop</string>
0
   <key>command</key>
0
   <string>#!/usr/bin/env ruby
0
-require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
0
-git = SCM::Git::SVNFetch.new
0
-git.run
0
 
0
-rescan_project</string>
0
+require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
0
+dispatch :controller =&gt; "svn", :action =&gt; "fetch"</string>
0
   <key>input</key>
0
   <string>none</string>
0
   <key>keyEquivalent</key>
...
6
7
8
9
10
11
12
13
 
 
14
15
16
...
6
7
8
 
 
 
9
 
10
11
12
13
14
0
@@ -6,11 +6,9 @@
0
   <string>nop</string>
0
   <key>command</key>
0
   <string>#!/usr/bin/env ruby
0
-require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
0
-git = SCM::Git::SVNRebase.new
0
-git.run
0
 
0
-rescan_project</string>
0
+require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
0
+dispatch :controller =&gt; "svn", :action =&gt; "rebase"</string>
0
   <key>input</key>
0
   <string>selection</string>
0
   <key>keyEquivalent</key>
...
6
7
8
 
9
10
11
12
 
13
14
15
...
6
7
8
9
10
 
 
 
11
12
13
14
0
@@ -6,10 +6,9 @@
0
   <string>nop</string>
0
   <key>command</key>
0
   <string>#!/usr/bin/env ruby
0
+
0
 require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
0
-git = SCM::Git::Log.new
0
-git.run
0
-</string>
0
+dispatch :controller =&gt; "log", :action =&gt; "index"</string>
0
   <key>input</key>
0
   <string>none</string>
0
   <key>keyEquivalent</key>
...
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
 
21
22
23
...
6
7
8
 
 
 
 
9
 
 
 
 
 
 
 
10
11
12
13
14
0
@@ -6,18 +6,9 @@
0
   <string>nop</string>
0
   <key>command</key>
0
   <string>#!/usr/bin/env ruby
0
-require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
0
-git = SCM::Git::Diff.new
0
-paths = git.paths(:fallback =&gt; :current_file, :unique =&gt; true)
0
-base = git.nca(paths)
0
 
0
-Formatters::Diff.new(:base =&gt; base) do |f|
0
- paths.each do |path|
0
- f.header("Uncomitted Changes for ‘#{htmlize(shorten(path, base))}’")
0
- f.open_in_tm_link
0
- f.content(git.diff_file(path))
0
- end
0
-end</string>
0
+require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
0
+dispatch :controller =&gt; "diff", :action =&gt; "uncommitted_changes"</string>
0
   <key>input</key>
0
   <string>none</string>
0
   <key>keyEquivalent</key>
...
2
3
4
5
6
7
8
9
...
12
13
14
15
 
16
17
18
...
2
3
4
 
 
5
6
7
...
10
11
12
 
13
14
15
16
0
@@ -2,8 +2,6 @@ class AnnotateController < ApplicationController
0
   include DateHelpers
0
   layout "application", :except => "update"
0
   def index
0
- log = SCM::Git::Log.new
0
-
0
     @filepath = params[:filepath] || ENV['TM_FILEPATH']
0
     @annotations = git.annotate(@filepath)
0
 
0
@@ -12,7 +10,7 @@ class AnnotateController < ApplicationController
0
       abort
0
     end
0
 
0
- @log_entries = log.log(@filepath)
0
+ @log_entries = git.log(:path => @filepath)
0
     render "index"
0
   end
0
   
...
 
 
 
1
2
3
4
5
6
 
 
 
 
 
 
 
 
7
8
9
...
32
33
34
35
36
37
38
39
40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
42
43
44
45
46
47
48
49
50
51
52
 
 
 
 
 
53
54
55
...
67
68
69
70
 
71
72
73
74
75
76
 
77
78
79
...
83
84
85
86
 
 
 
 
 
 
 
87
 
88
89
 
 
 
 
 
 
 
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
 
 
 
 
121
 
 
 
 
122
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
43
44
45
 
 
 
 
 
 
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
 
 
 
 
 
 
105
106
107
108
109
110
111
112
...
124
125
126
 
127
128
129
130
131
132
 
133
134
135
136
...
140
141
142
 
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
163
164
165
166
167
168
169
170
171
0
@@ -1,9 +1,20 @@
0
+require 'stringio'
0
+require 'thread'
0
+
0
 class ApplicationController
0
   include ApplicationHelper
0
   attr_accessor :params
0
   class << self
0
     attr_writer :layouts_conditions
0
     
0
+ def filters
0
+ @filters ||= {:before => [], :after => []}
0
+ end
0
+
0
+ def before_filter(method)
0
+ filters[:before] << [method, nil]
0
+ end
0
+
0
     def layouts_conditions
0
       @layouts_conditions ||= []
0
     end
0
@@ -32,24 +43,70 @@ class ApplicationController
0
     end
0
   end
0
   
0
- def with_layout(action = nil, &block)
0
- this_actions_layout = self.class.layout_for_action(action || params[:action])
0
- if this_actions_layout
0
- render this_actions_layout, &block
0
- else
0
- yield
0
+ def initialize
0
+ @output_buffer = StringIO.new
0
+ end
0
+
0
+ def puts(*args)
0
+ @output_buffer.puts(*args)
0
+ end
0
+
0
+ def flush
0
+ return if @capturing
0
+ start_layout
0
+ Object::STDOUT << @output_buffer.string
0
+ Object::flush
0
+ @output_buffer.string = ""
0
+ end
0
+
0
+ def start_layout
0
+ return if @layout_started
0
+ @layout_started = true
0
+ this_actions_layout = self.class.layout_for_action(params[:action])
0
+ return unless this_actions_layout
0
+
0
+ current_output = @output_buffer.string
0
+ @output_buffer.string = ""
0
+
0
+ @layout_thread_mutex = Mutex.new
0
+ @layout_thread = Thread.new do
0
+ @layout_thread_mutex.lock
0
+ render(this_actions_layout) { @layout_thread_mutex.unlock; Thread.stop; @layout_thread_mutex.lock }
0
+ @layout_thread_mutex.unlock
0
+ end
0
+ Thread.pass
0
+ @layout_thread_mutex.wait_for_lock
0
+
0
+ @output_buffer << current_output
0
+ end
0
+
0
+ def end_layout
0
+ return unless @layout_started && @layout_thread
0
+ @layout_thread.run
0
+ Thread.pass
0
+ @layout_thread_mutex.wait_for_lock
0
+
0
+ @layout_thread = @layout_thread_mutex = nil
0
+ end
0
+
0
+ def with_filters(&block)
0
+ self.class.filters[:before].each do |method, options|
0
+ return false unless send(method)
0
+ end
0
+ yield
0
+ self.class.filters[:after].each do |method, options|
0
+ return false unless send(method)
0
     end
0
   end
0
   
0
   def call(action, _params = {})
0
     self.params = _params
0
     params[:action] = action.to_s
0
-
0
- if params[:layout].to_s == "false"
0
- send(action)
0
- else
0
- with_layout { send(action) }
0
- end
0
+ @output_buffer = params.delete(:__output_buffer__) if params[:__output_buffer__]
0
+ with_filters { send(action) }
0
+ flush
0
+ end_layout
0
+ flush
0
   end
0
   
0
   def self.call(action, params = {})
0
@@ -67,13 +124,13 @@ class ApplicationController
0
       eval(__options__[:locals].keys * ", " + " = __v__.length == 1 ? __v__[0] : __v__")
0
     end
0
     
0
- __erb__ = ERBStdout.new(___template___, nil, "-", "STDOUT")
0
+ __erb__ = ERBStdout.new(___template___, nil, "-", "@output_buffer")
0
     __erb__.filename = __template_path__
0
     __erb__.run(binding)
0
   end
0
   
0
   def render_component(params = {})
0
- dispatch(params)
0
+ dispatch(params.merge(:layout => false, :__output_buffer__ => @output_buffer))
0
   end
0
   
0
   def self.template_root
0
@@ -83,40 +140,32 @@ class ApplicationController
0
   def content_for(name, &block)
0
     var_name = "@content_for_#{name}"
0
     content = instance_variable_get(var_name) || ""
0
- content << capture_output(&block)
0
+ @capturing = true
0
+ previous_content = @output_buffer.string
0
+ @output_buffer.string = ""
0
+ yield
0
+ content << @output_buffer.string
0
+ @output_buffer.string = ""
0
+ @output_buffer << previous_content
0
     instance_variable_set(var_name, content)
0
+ @capturing = false
0
     ""
0
   end
0
+end
0
+
0
+class Mutex
0
+ def pass_lock
0
+ Thread.pass
0
+ lock
0
+ end
0
   
0
- private
0
- def set_constant_forced(klass, constant_name, constant)
0
- klass.class_eval do
0
- remove_const(constant_name) if const_defined?(constant_name)
0
- const_set(constant_name, constant)
0
- end
0
- end
0
-
0
- def capture_output(&block)
0
- require 'stringio'
0
-
0
- old_stdout = Object::STDOUT
0
- io_stream = StringIO.new
0
- begin
0
- set_constant_forced(Object, "STDOUT", io_stream)
0
- [::Git, ::ApplicationController, ::Formatters].each do |klass|
0
- klass.class_eval do
0
- def puts(*args)
0
- args.each{ |arg| Object::STDOUT.puts arg}
0
- end
0
- end
0
- end
0
- yield
0
- ensure
0
- set_constant_forced(Object, "STDOUT", old_stdout)
0
- end
0
- io_stream.rewind
0
- io_stream.read
0
- end
0
-
0
+ def unlock_pass
0
+ Thread.pass
0
+ unlock
0
+ end
0
   
0
+ def wait_for_lock
0
+ pass_lock
0
+ unlock_pass
0
+ end
0
 end
...
18
19
20
21
22
23
24
25
26
27
 
 
28
29
30
31
32
33
34
35
 
36
37
38
...
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
 
59
60
61
...
18
19
20
 
21
22
23
24
25
 
26
27
28
29
30
31
32
 
33
 
34
35
36
37
...
42
43
44
 
 
 
 
 
 
 
 
45
 
46
47
 
48
49
50
51
0
@@ -18,21 +18,20 @@ class CommitController < ApplicationController
0
   
0
   def merge_commit
0
     message = params[:message]
0
- f = Formatters::Commit.new
0
     statuses = git.status(git.git_base)
0
     files = statuses.map { |status_options| (status_options[:status][:short] == "G") ? git.make_local_path(status_options[:path]) : nil }.compact
0
 
0
     auto_add_rm(files)
0
     res = git.commit(message, [])
0
- f.output_commit_result(res)
0
+
0
+ render "_commit_result", :locals => { :result => res, :files => files, :message => message }
0
   end
0
   
0
   protected
0
       
0
     def run_partial_commit
0
- f = Formatters::Commit.new
0
       target_file_or_dir = git.paths.first
0
- f.header "Committing Files in ‘#{htmlize(shorten(target_file_or_dir))}’"
0
+ puts "<h1>Committing Files in ‘#{htmlize(shorten(target_file_or_dir))}’</h1>"
0
       flush
0
 
0
       files, statuses = [], []
0
@@ -43,19 +42,10 @@ class CommitController < ApplicationController
0
     
0
       msg, files = show_commit_dialog(files, statuses)
0
 
0
- puts "<h2>Commit Files:</h2><ul>"
0
- puts files.map { |e| "<li>#{htmlize(e)}</li>\n" }.join
0
- puts "</ul>"
0
-
0
- puts "<h2>Using Message:</h2>"
0
- puts "<pre>#{htmlize(msg)}</pre>"
0
- STDOUT.flush
0
-
0
       unless files.empty?
0
- puts "<h2>Result:</h2>"
0
         auto_add_rm(files)
0
         res = git.commit(msg, files)
0
- f.output_commit_result(res)
0
+ render "_commit_result", :locals => { :files => files, :message => msg, :result => res}
0
       end
0
     end
0
     
...
1
 
 
 
 
 
 
 
2
3
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
6
7
...
58
59
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
62
...
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
...
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
0
@@ -1,7 +1,42 @@
0
 require ENV['TM_SUPPORT_PATH'] + '/lib/ui.rb'
0
+require "#{ENV["TM_SUPPORT_PATH"]}/lib/osx/plist"
0
+require "#{ENV["TM_SUPPORT_PATH"]}/lib/progress"
0
+require LIB_ROOT + '/date_helpers.rb'
0
+location = ENV["TM_BUNDLE_SUPPORT"]
0
+$nib = "#{location}/nibs/RevisionSelector.nib"
0
+ListNib = File.dirname(__FILE__) + "/../../nibs/RevisionSelector.nib"
0
+
0
 
0
 class LogController < ApplicationController
0
- layout nil
0
+ layout "application", :only => "index"
0
+ before_filter :set_script_at_top
0
+
0
+ def set_script_at_top
0
+ @script_at_top = true
0
+ end
0
+
0
+ DEFAULT_LOG_LIMIT = 50
0
+ include DateHelpers
0
+
0
+ def index
0
+ params[:path] ||= git.make_local_path(git.paths.first)
0
+ params[:limit] ||= DEFAULT_LOG_LIMIT
0
+ path = params[:path]
0
+ # Get the desired revision number
0
+ if File.directory?(git.git_base + path)
0
+ title = "View revision of Directory #{path}"
0
+ else
0
+ title = "View revision of file #{File.basename(path)}"
0
+ end
0
+
0
+ log
0
+ end
0
+
0
+ def log
0
+ @log_entries = git.log(params)
0
+ @branch ||= Git.new.branch.current_name
0
+ render "log_entries"
0
+ end
0
   
0
   def open_revision
0
     filepath = params[:filepath]
0
@@ -58,4 +93,81 @@ class LogController < ApplicationController
0
       TextMate::UI.alert(:warning, "Error!", "#{output}", 'OK')
0
     end
0
   end
0
+
0
+ protected
0
+ # on failure: returns nil
0
+ def choose_revision(path, prompt = "Choose a revision", number_of_revisions = 1, options = {})
0
+ path = make_local_path(path)
0
+ # Validate file
0
+ # puts command("status", path)
0
+ if /error: pathspec .+ did not match any file.+ known to git./.match(command("status", path))
0
+ TextMate::UI.alert(:warning, "File “#{File.basename(path)}” is not in the repository.", "Please add the file to the repository before using this command.")
0
+ return nil
0
+ end
0
+
0
+ # # Get the server name
0
+ # info = YAML::load(svn_cmd("info #{escaped_path}"))
0
+ # repository = info['Repository Root']
0
+ # uri = URI::parse(repository)
0
+
0
+ # the above will fail for users that run a localized system
0
+ # instead we should do ‘svn info --xml’, though since the
0
+ # code is not used, I just commented it. --Allan 2007-02-20
0
+
0
+ # Display progress dialog
0
+ # Show the log
0
+ revision = 0
0
+ log_data = nil
0
+
0
+ TextMate::UI.dialog(:nib => ListNib,
0
+ :center => true,
0
+ :parameters => {'title' => prompt,'entries' => [], 'hideProgressIndicator' => false}) do |dialog|
0
+
0
+ # Parse the log
0
+ log_data = stringify(log(path, :limit => 200))
0
+ dialog.parameters = {'entries' => log_data, 'hideProgressIndicator' => true}
0
+
0
+ dialog.wait_for_input do |params|
0
+ revision = params['returnArgument']
0
+ button_clicked = params['returnButton']
0
+
0
+ if (button_clicked != nil) and (button_clicked == 'Cancel')
0
+ false # exit
0
+ else
0
+ unless (number_of_revisions == :multiple) or (revision.length == number_of_revisions) then
0
+ TextMate::UI.alert(:warning, "Please select #{number_of_revisions} revision#{number_of_revisions == 1 ? '' : 's'}.", "So far, you have selected #{revision.length} revision#{revision.length == 1 ? '' : 's'}.")
0
+ true # continue
0
+ else
0
+ false # exit
0
+ end
0
+ end
0
+ end
0
+ end
0
+
0
+ # Return the revision number or nil
0
+ revision = nil if revision == 0
0
+ if options[:sort] && revision
0
+ time_revision_pairs = []
0
+ selected_entries = log_data.select{ |l| revision.include?(l["rev"]) }
0
+ selected_entries.sort!{ |a,b| a["date"] <=> b["date"] } # sorts them descending (latest on the bottom)
0
+ selected_entries.reverse! if options[:sort] == :asc
0
+ revision = selected_entries.map{|se| se["rev"]}
0
+ end
0
+ revision
0
+ end
0
+
0
+ def stringify(results)
0
+ results.each{|r| r.stringify_keys! }
0
+ end
0
+end
0
+
0
+class Hash
0
+ def stringify_keys!
0
+ keys.each{|k|
0
+ if k.is_a?(Symbol)
0
+ value = delete(k)
0
+ self[k.to_s] = value
0
+ end
0
+ }
0
+ end
0
 end
0
\ No newline at end of file
...
58
59
60
61
 
 
62
63
64
...
58
59
60
 
61
62
63
64
65
0
@@ -58,7 +58,8 @@ class StashController < ApplicationController
0
     render "status/_status", :locals => {:status_data => status_data}
0
     
0
     puts "<h2>Diff of stash applied:</h2>"
0
- Formatters::Diff.new.content(git.stash.diff(stash_item[:name]))
0
+ render("/diff/_diff_results", :locals => {:diff_results => git.stash.diff(stash_item[:name])})
0
+
0
     rescan_project
0
   end
0
   
...
4
5
6
 
7
8
9
10
11
12
13
 
...
4
5
6
7
8
9
10
11
12
 
13
14
0
@@ -4,9 +4,10 @@
0
   <link type="text/css" rel="stylesheet" media="screen" href="<%= resource_url('style.css') %>"/>
0
 </head>
0
 <body id='body'>
0
+ <div id='debug'></div>
0
   <% yield %>
0
 </body>
0
 <!-- we put the script at the end because it messes up TextMate's html rendering, for some reason -->
0
 <%= javascript_include_tag "prototype", "rb_gateway" %>
0
 <%= @content_for_javascript %>
0
-</html>
0
\ No newline at end of file
0
+</html>
...
6
7
8
9
10
11
12
13
14
15
16
17
...
6
7
8
 
 
 
 
 
 
 
 
9
0
@@ -6,12 +6,4 @@ class SCM::Git::SVNRebase < SCM::Git
0
     Dir.chdir(git_base)
0
   end
0
   
0
- def run
0
- puts "<h2>Rebasing Subversion Repository</h2>"
0
- puts htmlize(svn_rebase)
0
- end
0
-
0
- def svn_rebase
0
- command("svn","rebase")
0
- end
0
 end
...
223
224
225
 
226
227
228
229
230
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
232
233
...
262
263
264
265
266
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
268
269
...
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
...
281
282
283
 
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
0
@@ -223,11 +223,30 @@ module SCM
0
     def merge(merge_from_branch)
0
       parse_merge(command("merge", merge_from_branch))
0
     end
0
+
0
     def show(fullpath, revision)