Commit c1380df9efc6e2753d10f913adad725b834723b2

extracted out partial commit functionality to a polymorphic worker class to handle subtle differences between amend commits and normal commits

Commit diff

Support/app/controllers/commit_controller.rb

 
11CW = ENV['TM_SUPPORT_PATH'] + '/bin/CommitWindow.app/Contents/MacOS/CommitWindow'
2
2require LIB_ROOT + '/partial_commit_worker.rb'
33class CommitController < ApplicationController
44 def index
55 if git.merge_message
2323 end
2424
2525 protected
26
27 def ok_to_proceed_with_partial_commit?
28 (! git.branch.current_name.nil?) || git.initial_commit_pending?
29 end
30
3126 def run_partial_commit
32 @base = git.git_base
33
34 unless ok_to_proceed_with_partial_commit?
35 render "not_on_a_branch"
36 return false
37 end
38
39 target_file_or_dir = git.paths.first
40
41 puts "<h1>"
42 if params[:type] == "amend"
43 puts "Amending the commit"
44 else
45 puts "Committing Files"
46 end
47 puts " in ‘#{htmlize(shorten(target_file_or_dir, ENV['TM_PROJECT_DIRECTORY'] || @base))}’ on branch ‘#{htmlize(git.branch.current_name)}’</h1>"
27 puts "<h2>#{commit_worker.title}</h2>"
4828 flush
49
50 files, statuses = [], []
51 git.status(target_file_or_dir).each do |e|
52 files << e_sh(shorten(e[:path], @base))
53 statuses << e_sh(e[:status][:short])
54 end
55
56 if files.empty?
57 puts (git.clean_directory? ? "Working directory is clean (nothing to commit)" : "No changes to commit within the current scope. (Try selecting the root folder in the project drawer?)")
58 return
59 end
60
61 msg, files = show_commit_dialog(files, statuses)
62
63 unless files.empty?
64 git.auto_add_rm(files)
65 res = git.commit(msg, files, :amend => (params[:type] == "amend"))
66 render "_commit_result", :locals => { :files => files, :message => msg, :result => res}
67 end
29 result = commit_worker.run
30 render "_commit_result", :locals => result if result
31 rescue PartialCommitWorker::NotOnBranchException
32 render "not_on_a_branch"
33 false
34 rescue PartialCommitWorker::NothingToCommitException
35 puts(git.clean_directory? ? "Working directory is clean (nothing to commit)" : "No changes to commit within the current scope. (Try selecting the root folder in the project drawer?)")
36 rescue PartialCommitWorker::CommitCanceledException
37 puts "<strong>Canceled</strong>"
6838 end
6939
70 def show_commit_dialog(files, statuses)
71 status_helper_tool = ENV['TM_BUNDLE_SUPPORT'] + '/gateway/commit_dialog_helper.rb'
72
73 res = %x{#{e_sh CW} \
74 --diff-cmd '#{git.git},diff' \
75 --action-cmd "M,D:Revert,#{status_helper_tool},revert" \
76 --status #{statuses.join ':'} \
77 #{files.join ' '} 2>/dev/console
78 }
79
80 if $? != 0
81 puts "<strong>Cancel</strong>"
82 abort
83 end
84
85 res = Shellwords.shellwords(res)
86 msg = res[1]
87 files = res[2..-1]
88 return msg, files
40 def commit_worker
41 @commit_worker ||= PartialCommitWorker.factory(params[:type], git)
8942 end
9043end
toggle raw diff

Support/lib/partial_commit_worker.rb

 
1module PartialCommitWorker
2 class NotOnBranchException < Exception; end
3 class NothingToCommitException < Exception; end
4 class CommitCanceledException < Exception; end
5
6 def self.factory(_type, *args)
7 klass = case _type
8 when "amend" then
9 PartialCommitWorker::Amend
10 else
11 PartialCommitWorker::Normal
12 end
13
14 klass.new(*args)
15 end
16
17 class Base
18 attr_reader :git
19
20 def initialize(git)
21 @git = git
22 @base = git.git_base
23 end
24
25 def ok_to_proceed_with_partial_commit?
26 (! git.branch.current_name.nil?) || git.initial_commit_pending?
27 end
28
29 def target_file_or_dir
30 @target_file_or_dir ||= git.paths.first
31 end
32
33 def show_commit_dialog(files, statuses)
34 status_helper_tool = ENV['TM_BUNDLE_SUPPORT'] + '/gateway/commit_dialog_helper.rb'
35
36 res = %x{#{e_sh CW} \
37 --diff-cmd '#{git.git},diff' \
38 --action-cmd "M,D:Revert,#{status_helper_tool},revert" \
39 --status #{statuses.join ':'} \
40 #{files.join ' '} 2>/dev/console
41 }
42
43 raise CommitCanceledException if $? != 0
44
45 res = Shellwords.shellwords(res)
46 msg = res[1]
47 files = res[2..-1]
48 return msg, files
49 end
50
51 def run
52 raise NotOnBranchException unless ok_to_proceed_with_partial_commit?
53
54 files, statuses = [], []
55 git.status(target_file_or_dir).each do |e|
56 files << e_sh(shorten(e[:path], @base))
57 statuses << e_sh(e[:status][:short])
58 end
59
60 raise NothingToCommitException if files.empty?
61
62 msg, files = show_commit_dialog(files, statuses)
63
64 git.auto_add_rm(files)
65 res = git.commit(msg, files, :amend => amend)
66 { :files => files, :message => msg, :result => res}
67 end
68
69 def title
70 "#{title_prefix} in ‘#{htmlize(shorten(target_file_or_dir, ENV['TM_PROJECT_DIRECTORY'] || @base))}’ on branch ‘#{htmlize(git.branch.current_name)}’"
71 end
72 end
73
74 class Normal < Base
75 def title_prefix
76 "Committing Files"
77 end
78
79 def amend
80 false
81 end
82 end
83
84 class Amend < Base
85 def title_prefix
86 "Amending the commit"
87 end
88
89 def amend
90 true
91 end
92 end
93end
toggle raw diff

Support/spec/controllers/commit_controller_spec.rb

 
1616 before(:each) do
1717 @message = "My commit message"
1818 @git.should_receive(:merge_message).and_return(nil)
19 @controller.stub!(:show_commit_dialog).and_return([@message, ["file1.txt", "file2.txt"]])
19 @worker = PartialCommitWorker::Normal.singleton_new(@git)
20 @worker.stub!(:show_commit_dialog).and_return([@message, ["file1.txt", "file2.txt"]])
2021
2122 @git.should_receive(:commit).
2223 with("My commit message", ["file1.txt", "file2.txt"], :amend => false).
4646 end
4747 end
4848
49 describe "Ammend commit" do
49 describe "Amend commit" do
5050 before(:each) do
5151 @message = "My commit message"
5252 @git.should_receive(:merge_message).and_return(nil)
53 @controller.stub!(:show_commit_dialog).and_return([@message, ["file1.txt", "file2.txt"]])
53 @worker = PartialCommitWorker::Amend.singleton_new(@git)
54 @worker.stub!(:show_commit_dialog).and_return([@message, ["file1.txt", "file2.txt"]])
5455
5556 @git.should_receive(:commit).
5657 with("My commit message", ["file1.txt", "file2.txt"], :amend => true).
8585 end
8686 end
8787
88 it "should NOT be OK to proceed when not on a branch but performing an initial commit" do
89 @git.branch.should_receive(:current_name).and_return(nil)
90 @git.should_receive(:initial_commit_pending?).and_return(false)
91
92 @controller.send(:ok_to_proceed_with_partial_commit?).should == false
93 end
94
95 it "should be OK to proceed when not on a branch but performing an initial commit" do
96 @git.branch.should_receive(:current_name).and_return(nil)
97 @git.should_receive(:initial_commit_pending?).and_return(true)
98
99 @controller.send(:ok_to_proceed_with_partial_commit?).should == true
100 end
101
10288 describe "when in the middle of a merge" do
10389 it "should run the mege dialog" do
10490 @merge_message = "Merged some branch into another branch..."
toggle raw diff

Support/spec/lib/partial_commit_worker_spec.rb

 
1require File.dirname(__FILE__) + '/../spec_helper'
2require LIB_ROOT + "/partial_commit_worker"
3
4describe PartialCommitWorker do
5 before(:each) do
6 @git = Git.singleton_new
7 end
8
9 it "should NOT be OK to proceed when not on a branch but performing an initial commit" do
10 @git.branch.should_receive(:current_name).and_return(nil)
11 @git.should_receive(:initial_commit_pending?).and_return(false)
12 PartialCommitWorker::Base.new(@git).ok_to_proceed_with_partial_commit?.should == false
13 end
14
15 it "should be OK to proceed when not on a branch but performing an initial commit" do
16 @git.branch.should_receive(:current_name).and_return(nil)
17 @git.should_receive(:initial_commit_pending?).and_return(true)
18 PartialCommitWorker::Base.new(@git).ok_to_proceed_with_partial_commit?.should == true
19 end
20end
toggle raw diff

Support/tmvc/lib/application_controller.rb

 
5353
5454 def initialize
5555 @output_buffer = StringIO.new
56 @params = {}
5657 end
5758
5859 def puts(*args)
toggle raw diff