class Dyph::Support::Merger
Attributes
diff2[R]
result[R]
Public Class Methods
merge(left, base, right, diff2: Dyph::Differ.default_diff2, diff3: Dyph::Differ.default_diff3)
click to toggle source
# File lib/dyph/support/merger.rb, line 5 def self.merge(left, base, right, diff2: Dyph::Differ.default_diff2, diff3: Dyph::Differ.default_diff3) merger = Merger.new(left: left, base: base, right: right, diff2: diff2, diff3: diff3) merger.execute_three_way_merge() merger.result end
new(left:, base:, right:, diff2:, diff3:)
click to toggle source
# File lib/dyph/support/merger.rb, line 11 def initialize(left:, base:, right:, diff2:, diff3:) @result = [] @diff2 = diff2 @diff3 = diff3 @text3 = Text3.new(left: left, right: right, base: base) end
Public Instance Methods
execute_three_way_merge()
click to toggle source
rubocop:disable Metrics/AbcSize
# File lib/dyph/support/merger.rb, line 19 def execute_three_way_merge d3 = @diff3.execute_diff(@text3.left, @text3.base, @text3.right, @diff2) chunk_descs = d3.map { |raw_chunk_desc| ChunkDesc.new(raw_chunk_desc) } index = 1 chunk_descs.each do |chunk_desc| initial_text = [] (index ... chunk_desc.base_lo).each do |lineno| # exclusive (...) initial_text << @text3.base[lineno - 1] end #initial_text = initial_text.join("\n") + "\n" # @result << Dyph::Outcome::Resolved.new(initial_text) unless initial_text.empty? interpret_chunk(chunk_desc) #assign index to be the line in base after the conflict index = chunk_desc.base_hi + 1 # end #finish by putting all text after the last conflict into the @result body. ending_text = accumulate_lines(index, @text3.base.length, @text3.base) @result << Dyph::Outcome::Resolved.new(ending_text) unless ending_text.empty? end
Protected Instance Methods
_assoc_range(diff, diff_type)
click to toggle source
@param [in] diff conflicts in diff structure @param [in] diff_type type of diff looked for in diff @return diff_type if any conflicts in diff are of type diff_type. otherwise return nil
# File lib/dyph/support/merger.rb, line 125 def _assoc_range(diff, diff_type) diff.each do |d| if d[0] == diff_type return d end end nil end
_conflict_range(chunk_desc)
click to toggle source
# File lib/dyph/support/merger.rb, line 96 def _conflict_range(chunk_desc) right = set_text(@text3.right, chunk_desc.right_lo, chunk_desc.right_hi) left = set_text(@text3.left , chunk_desc.left_lo, chunk_desc.left_hi) d = @diff2.diff(right, left) if (_assoc_range(d, :change) || _assoc_range(d, :delete)) && chunk_desc.base_lo <= chunk_desc.base_hi set_conflict(chunk_desc) else determine_conflict(d, left, right) end end
accumulate_lines(lo, hi, text)
click to toggle source
@param [in] lo indec for beginning of accumulation range @param [in] hi index for end of accumulation range @param [in] text array of lines of text @return a string of lines lo to high joined by new lines, with a trailing new line.
# File lib/dyph/support/merger.rb, line 138 def accumulate_lines(lo, hi, text) lines = [] (lo .. hi).each do |lineno| lines << text[lineno - 1] unless text[lineno - 1].nil? end lines end
determine_conflict(d, left, right)
click to toggle source
# File lib/dyph/support/merger.rb, line 57 def determine_conflict(d, left, right) ia = 1 d.each do |raw_chunk_desc| chunk_desc = ChunkDesc.new(raw_chunk_desc) (ia ... chunk_desc.left_lo).each do |lineno| @result << Dyph::Outcome::Resolved.new(accumulate_lines(ia, lineno, right)) end outcome = determine_outcome(chunk_desc, left, right) ia = chunk_desc.right_hi + 1 @result << outcome if outcome end final_text = accumulate_lines(ia, right.length + 1, right) @result << Dyph::Outcome::Resolved.new(final_text) unless final_text.empty? end
determine_outcome(chunk_desc, left, right)
click to toggle source
# File lib/dyph/support/merger.rb, line 74 def determine_outcome(chunk_desc, left, right) if chunk_desc.action == :change Outcome::Conflicted.new( left: accumulate_lines(chunk_desc.right_lo, chunk_desc.right_hi, left), right: accumulate_lines(chunk_desc.left_lo, chunk_desc.left_hi, right), base: [] ) elsif chunk_desc.action == :add Outcome::Resolved.new( accumulate_lines(chunk_desc.right_lo, chunk_desc.right_hi, left) ) end end
interpret_chunk(chunk_desc)
click to toggle source
# File lib/dyph/support/merger.rb, line 107 def interpret_chunk(chunk_desc) if chunk_desc.action == :choose_left # 0 flag means choose left. put lines chunk_desc[1] .. chunk_desc[2] into the @result body. temp_text = accumulate_lines(chunk_desc.left_lo, chunk_desc.left_hi, @text3.left) # they deleted it, don't use if its only a new line @result << Dyph::Outcome::Resolved.new(temp_text) unless temp_text.empty? elsif chunk_desc.action != :possible_conflict # A flag means choose right. put lines chunk_desc[3] to chunk_desc[4] into the @result body. temp_text = accumulate_lines(chunk_desc.right_lo, chunk_desc.right_hi, @text3.right) @result << Dyph::Outcome::Resolved.new(temp_text) unless temp_text.empty? else _conflict_range(chunk_desc) end end
set_conflict(chunk_desc)
click to toggle source
rubocop:enable Metrics/AbcSize
# File lib/dyph/support/merger.rb, line 48 def set_conflict(chunk_desc) conflict = Dyph::Outcome::Conflicted.new( left: accumulate_lines(chunk_desc.left_lo, chunk_desc.left_hi, @text3.left), base: accumulate_lines(chunk_desc.base_lo, chunk_desc.base_hi, @text3.base), right: accumulate_lines(chunk_desc.right_lo, chunk_desc.right_hi, @text3.right) ) @result << conflict end
set_text(orig_text, lo, hi)
click to toggle source
# File lib/dyph/support/merger.rb, line 88 def set_text(orig_text, lo, hi) text = [] # conflicting lines in right (lo .. hi).each do |i| # inclusive(..) text << orig_text[i - 1] end text end