Class: Merge::Diff3

Inherits:
Object
  • Object
show all
Defined in:
lib/merge/diff3.rb

Defined Under Namespace

Classes: Clean, Conflict, Result

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(o, a, b) ⇒ Diff3

Returns a new instance of Diff3.



48
49
50
# File 'lib/merge/diff3.rb', line 48

def initialize(o, a, b)
  @o, @a, @b = o, a, b
end

Class Method Details

.merge(o, a, b) ⇒ Object



40
41
42
43
44
45
46
# File 'lib/merge/diff3.rb', line 40

def self.merge(o, a, b)
  o = o.lines if o.is_a?(String)
  a = a.lines if a.is_a?(String)
  b = b.lines if b.is_a?(String)

  Diff3.new(o, a, b).merge
end

Instance Method Details

#emit_chunk(o, a, b) ⇒ Object



129
130
131
132
133
134
135
136
# File 'lib/merge/diff3.rb', line 129

def emit_chunk(o, a, b)
  write_chunk(
    @o[@line_o ... o - 1],
    @a[@line_a ... a - 1],
    @b[@line_b ... b - 1])

  @line_o, @line_a, @line_b = o - 1, a - 1, b - 1
end

#emit_final_chunkObject



138
139
140
141
142
143
# File 'lib/merge/diff3.rb', line 138

def emit_final_chunk
  write_chunk(
    @o[@line_o .. -1],
    @a[@line_a .. -1],
    @b[@line_b .. -1])
end

#find_next_matchObject



121
122
123
124
125
126
127
# File 'lib/merge/diff3.rb', line 121

def find_next_match
  o = @line_o + 1
  until o > @o.size or (@match_a.has_key?(o) and @match_b.has_key?(o))
    o += 1
  end
  [o, @match_a[o], @match_b[o]]
end

#find_next_mismatchObject



101
102
103
104
105
106
107
108
109
# File 'lib/merge/diff3.rb', line 101

def find_next_mismatch
  i = 1
  while in_bounds?(i) and
        match?(@match_a, @line_a, i) and
        match?(@match_b, @line_b, i)
    i += 1
  end
  in_bounds?(i) ? i : nil
end

#generate_chunksObject



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/merge/diff3.rb', line 77

def generate_chunks
  loop do
    i = find_next_mismatch

    if i == 1
      o, a, b = find_next_match

      if a and b
        emit_chunk(o, a, b)
      else
        emit_final_chunk
        return
      end

    elsif i
      emit_chunk(@line_o + i, @line_a + i, @line_b + i)

    else
      emit_final_chunk
      return
    end
  end
end

#in_bounds?(i) ⇒ Boolean

Returns:

  • (Boolean)


111
112
113
114
115
# File 'lib/merge/diff3.rb', line 111

def in_bounds?(i)
  @line_o + i <= @o.size or
  @line_a + i <= @a.size or
  @line_b + i <= @b.size
end

#match?(matches, offset, i) ⇒ Boolean

Returns:

  • (Boolean)


117
118
119
# File 'lib/merge/diff3.rb', line 117

def match?(matches, offset, i)
  matches[@line_o + i] == offset + i
end

#match_set(file) ⇒ Object



66
67
68
69
70
71
72
73
74
75
# File 'lib/merge/diff3.rb', line 66

def match_set(file)
  matches = {}

  Diff.diff(@o, file).each do |edit|
    next unless edit.type == :eql
    matches[edit.a_line.number] = edit.b_line.number
  end

  matches
end

#mergeObject



52
53
54
55
56
# File 'lib/merge/diff3.rb', line 52

def merge
  setup
  generate_chunks
  Result.new(@chunks)
end

#setupObject



58
59
60
61
62
63
64
# File 'lib/merge/diff3.rb', line 58

def setup
  @chunks = []
  @line_o = @line_a = @line_b = 0

  @match_a = match_set(@a)
  @match_b = match_set(@b)
end

#write_chunk(o, a, b) ⇒ Object



145
146
147
148
149
150
151
152
153
# File 'lib/merge/diff3.rb', line 145

def write_chunk(o, a, b)
  if a == o or a == b
    @chunks.push(Clean.new(b))
  elsif b == o
    @chunks.push(Clean.new(a))
  else
    @chunks.push(Conflict.new(o, a, b))
  end
end