Skip to content

Commit 91229e4

Browse files
committed
Add merge action to file colision menu
Currently, if want to reflect the changed contents, only have to grasp the contents of diff and reflect it manually later or overwrite once to check the difference. This is a little inconvenient. If merge is selected, the specified merge tool will be executed. By doing this, can reflect changes while checking. Merge tool is obtained from environment variables and git config. I doubt that it is appropriate to get a value from git config, but I am thinking that there may be useful.
1 parent 84cea9a commit 91229e4

File tree

3 files changed

+60
-5
lines changed

3 files changed

+60
-5
lines changed

lib/thor/shell/basic.rb

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,11 +247,11 @@ def print_wrapped(message, options = {})
247247
#
248248
# ==== Parameters
249249
# destination<String>:: the destination file to solve conflicts
250-
# block<Proc>:: an optional block that returns the value to be used in diff
250+
# block<Proc>:: an optional block that returns the value to be used in diff and merge
251251
#
252252
def file_collision(destination)
253253
return true if @always_force
254-
options = block_given? ? "[Ynaqdh]" : "[Ynaqh]"
254+
options = block_given? ? "[Ynaqdhm]" : "[Ynaqh]"
255255

256256
loop do
257257
answer = ask(
@@ -275,6 +275,13 @@ def file_collision(destination)
275275
when is?(:diff)
276276
show_diff(destination, yield) if block_given?
277277
say "Retrying..."
278+
when is?(:merge)
279+
if block_given? && !merge_tool.empty?
280+
merge(destination, yield)
281+
return nil
282+
end
283+
284+
say "Please specify merge tool to `THOR_MERGE` env."
278285
else
279286
say file_collision_help
280287
end
@@ -352,6 +359,7 @@ def file_collision_help #:nodoc:
352359
q - quit, abort
353360
d - diff, show the differences between the old and the new
354361
h - help, show this help
362+
m - merge, run merge tool
355363
HELP
356364
end
357365

@@ -440,6 +448,23 @@ def ask_filtered(statement, color, options)
440448
end
441449
correct_answer
442450
end
451+
452+
def merge(destination, content) #:nodoc:
453+
require "tempfile"
454+
Tempfile.open([File.basename(destination), File.extname(destination)], File.dirname(destination)) do |temp|
455+
temp.write content
456+
temp.rewind
457+
system %(#{merge_tool} "#{temp.path}" "#{destination}")
458+
end
459+
end
460+
461+
def merge_tool #:nodoc:
462+
@merge_tool ||= ENV["THOR_MERGE"] || git_merge_tool
463+
end
464+
465+
def git_merge_tool #:nodoc:
466+
`git config merge.tool`.rstrip rescue ""
467+
end
443468
end
444469
end
445470
end

spec/actions/create_file_spec.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def silence!
104104
it "shows conflict status to the user" do
105105
file = File.join(destination_root, "doc/config.rb")
106106
expect(create_file("doc/config.rb")).not_to be_identical
107-
expect(Thor::LineEditor).to receive(:readline).with("Overwrite #{file}? (enter \"h\" for help) [Ynaqdh] ", anything).and_return("s")
107+
expect(Thor::LineEditor).to receive(:readline).with("Overwrite #{file}? (enter \"h\" for help) [Ynaqdhm] ", anything).and_return("s")
108108

109109
content = invoke!
110110
expect(content).to match(%r{conflict doc/config\.rb})
@@ -129,6 +129,14 @@ def silence!
129129
expect(@base.shell).to receive(:system).with(/diff -u/)
130130
invoke!
131131
end
132+
133+
it "executes the block given to run merge tool" do
134+
create_file("doc/config.rb")
135+
allow(@base.shell).to receive(:merge_tool).and_return("meld")
136+
expect(Thor::LineEditor).to receive(:readline).and_return("m")
137+
expect(@base.shell).to receive(:system).with(/meld/)
138+
invoke!
139+
end
132140
end
133141
end
134142

spec/shell/basic_spec.rb

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,8 @@ def #456 Lanç...
356356
end
357357

358358
describe "when a block is given" do
359-
it "displays diff options to the user" do
360-
expect(Thor::LineEditor).to receive(:readline).with('Overwrite foo? (enter "h" for help) [Ynaqdh] ', :add_to_history => false).and_return("s")
359+
it "displays diff and merge options to the user" do
360+
expect(Thor::LineEditor).to receive(:readline).with('Overwrite foo? (enter "h" for help) [Ynaqdhm] ', :add_to_history => false).and_return("s")
361361
shell.file_collision("foo") {}
362362
end
363363

@@ -367,6 +367,28 @@ def #456 Lanç...
367367
expect(shell).to receive(:system).with(/diff -u/)
368368
capture(:stdout) { shell.file_collision("foo") {} }
369369
end
370+
371+
it "invokes the merge tool" do
372+
allow(shell).to receive(:merge_tool).and_return("meld")
373+
expect(Thor::LineEditor).to receive(:readline).and_return("m")
374+
expect(shell).to receive(:system).with(/meld/)
375+
capture(:stdout) { shell.file_collision("foo") {} }
376+
end
377+
378+
it "invokes the merge tool that specified at ENV['THOR_MERGE']" do
379+
allow(ENV).to receive(:[]).with("THOR_MERGE").and_return("meld")
380+
expect(Thor::LineEditor).to receive(:readline).and_return("m")
381+
expect(shell).to receive(:system).with(/meld/)
382+
capture(:stdout) { shell.file_collision("foo") {} }
383+
end
384+
385+
it "show warning if user chooses merge but merge tool is not specified" do
386+
allow(shell).to receive(:merge_tool).and_return("")
387+
expect(Thor::LineEditor).to receive(:readline).and_return("m")
388+
expect(Thor::LineEditor).to receive(:readline).and_return("n")
389+
help = capture(:stdout) { shell.file_collision("foo") {} }
390+
expect(help).to match(/Please specify merge tool to `THOR_MERGE` env/)
391+
end
370392
end
371393
end
372394
end

0 commit comments

Comments
 (0)