diff-lcs 1.1.3 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,300 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+
3
+ class << Diff::LCS
4
+ def diff_traversal(method, seq1, seq2, callbacks, &block)
5
+ callbacks = callbacks_for(callbacks)
6
+ case method
7
+ when :diff
8
+ traverse_sequences(seq1, seq2, callbacks)
9
+ when :sdiff
10
+ traverse_balanced(seq1, seq2, callbacks)
11
+ end
12
+ callbacks.finish if callbacks.respond_to? :finish
13
+
14
+ if block
15
+ callbacks.diffs.map do |hunk|
16
+ if hunk.kind_of? Array
17
+ hunk.map { |hunk_block| block[hunk_block] }
18
+ else
19
+ block[hunk]
20
+ end
21
+ end
22
+ else
23
+ callbacks.diffs
24
+ end
25
+ end
26
+ private :diff_traversal
27
+ end
28
+
29
+ module Diff::LCS::Internals # :nodoc:
30
+ end
31
+
32
+ class << Diff::LCS::Internals
33
+ # Compute the longest common subsequence between the sequenced
34
+ # Enumerables +a+ and +b+. The result is an array whose contents is such
35
+ # that
36
+ #
37
+ # result = Diff::LCS::Internals.lcs(a, b)
38
+ # result.each_with_index do |e, i|
39
+ # assert_equal(a[i], b[e]) unless e.nil?
40
+ # end
41
+ def lcs(a, b)
42
+ a_start = b_start = 0
43
+ a_finish = a.size - 1
44
+ b_finish = b.size - 1
45
+ vector = []
46
+
47
+ # Prune off any common elements at the beginning...
48
+ while ((a_start <= a_finish) and (b_start <= b_finish) and
49
+ (a[a_start] == b[b_start]))
50
+ vector[a_start] = b_start
51
+ a_start += 1
52
+ end
53
+ b_start = a_start
54
+
55
+ # Now the end...
56
+ while ((a_start <= a_finish) and (b_start <= b_finish) and
57
+ (a[a_finish] == b[b_finish]))
58
+ vector[a_finish] = b_finish
59
+ a_finish -= 1
60
+ b_finish -= 1
61
+ end
62
+
63
+ # Now, compute the equivalence classes of positions of elements.
64
+ b_matches = position_hash(b, b_start..b_finish)
65
+
66
+ thresh = []
67
+ links = []
68
+ string = a.kind_of?(String)
69
+
70
+ (a_start .. a_finish).each do |i|
71
+ ai = string ? a[i, 1] : a[i]
72
+ bm = b_matches[ai]
73
+ k = nil
74
+ bm.reverse_each do |j|
75
+ if k and (thresh[k] > j) and (thresh[k - 1] < j)
76
+ thresh[k] = j
77
+ else
78
+ k = replace_next_larger(thresh, j, k)
79
+ end
80
+ links[k] = [ (k > 0) ? links[k - 1] : nil, i, j ] unless k.nil?
81
+ end
82
+ end
83
+
84
+ unless thresh.empty?
85
+ link = links[thresh.size - 1]
86
+ while not link.nil?
87
+ vector[link[1]] = link[2]
88
+ link = link[0]
89
+ end
90
+ end
91
+
92
+ vector
93
+ end
94
+
95
+ # This method will analyze the provided patchset to provide a
96
+ # single-pass normalization (conversion of the array form of
97
+ # Diff::LCS::Change objects to the object form of same) and detection of
98
+ # whether the patchset represents changes to be made.
99
+ def analyze_patchset(patchset, depth = 0)
100
+ raise "Patchset too complex" if depth > 1
101
+
102
+ has_changes = false
103
+
104
+ # Format:
105
+ # [ # patchset
106
+ # # hunk (change)
107
+ # [ # hunk
108
+ # # change
109
+ # ]
110
+ # ]
111
+
112
+ patchset = patchset.map do |hunk|
113
+ case hunk
114
+ when Diff::LCS::Change
115
+ has_changes ||= !hunk.unchanged?
116
+ hunk
117
+ when Array
118
+ # Detect if the 'hunk' is actually an array-format
119
+ # Change object.
120
+ if Diff::LCS::Change.valid_action? hunk[0]
121
+ hunk = Diff::LCS::Change.from_a(hunk)
122
+ has_changes ||= !hunk.unchanged?
123
+ hunk
124
+ else
125
+ with_changes, hunk = analyze_patchset(hunk, depth + 1)
126
+ has_changes ||= with_changes
127
+ hunk.flatten
128
+ end
129
+ else
130
+ raise ArgumentError, "Cannot normalise a hunk of class #{hunk.class}."
131
+ end
132
+ end
133
+
134
+ [ has_changes, patchset.flatten(1) ]
135
+ end
136
+
137
+ # Examine the patchset and the source to see in which direction the
138
+ # patch should be applied.
139
+ #
140
+ # WARNING: By default, this examines the whole patch, so this could take
141
+ # some time. This also works better with Diff::LCS::ContextChange or
142
+ # Diff::LCS::Change as its source, as an array will cause the creation
143
+ # of one of the above.
144
+ #
145
+ # Note: This will be deprecated as a public function in a future release.
146
+ def intuit_diff_direction(src, patchset, limit = nil)
147
+ string = src.kind_of?(String)
148
+ count = left_match = left_miss = right_match = right_miss = 0
149
+
150
+ patchset.each do |change|
151
+ count += 1
152
+
153
+ case change
154
+ when Diff::LCS::ContextChange
155
+ le = string ? src[change.old_position, 1] : src[change.old_position]
156
+ re = string ? src[change.new_position, 1] : src[change.new_position]
157
+
158
+ case change.action
159
+ when '-' # Remove details from the old string
160
+ if le == change.old_element
161
+ left_match += 1
162
+ else
163
+ left_miss += 1
164
+ end
165
+ when '+'
166
+ if re == change.new_element
167
+ right_match += 1
168
+ else
169
+ right_miss += 1
170
+ end
171
+ when '='
172
+ left_miss += 1 if le != change.old_element
173
+ right_miss += 1 if re != change.new_element
174
+ when '!'
175
+ if le == change.old_element
176
+ left_match += 1
177
+ else
178
+ if re == change.new_element
179
+ right_match += 1
180
+ else
181
+ left_miss += 1
182
+ right_miss += 1
183
+ end
184
+ end
185
+ end
186
+ when Diff::LCS::Change
187
+ # With a simplistic change, we can't tell the difference between
188
+ # the left and right on '!' actions, so we ignore those. On '='
189
+ # actions, if there's a miss, we miss both left and right.
190
+ element = string ? src[change.position, 1] : src[change.position]
191
+
192
+ case change.action
193
+ when '-'
194
+ if element == change.element
195
+ left_match += 1
196
+ else
197
+ left_miss += 1
198
+ end
199
+ when '+'
200
+ if element == change.element
201
+ right_match += 1
202
+ else
203
+ right_miss += 1
204
+ end
205
+ when '='
206
+ if element != change.element
207
+ left_miss += 1
208
+ right_miss += 1
209
+ end
210
+ end
211
+ end
212
+
213
+ break if (not limit.nil?) && (count > limit)
214
+ end
215
+
216
+ no_left = (left_match == 0) && (left_miss > 0)
217
+ no_right = (right_match == 0) && (right_miss > 0)
218
+
219
+ case [no_left, no_right]
220
+ when [false, true]
221
+ :patch
222
+ when [true, false]
223
+ :unpatch
224
+ else
225
+ case left_match <=> right_match
226
+ when 1
227
+ :patch
228
+ when -1
229
+ :unpatch
230
+ else
231
+ raise "The provided patchset does not appear to apply to the provided value as either source or destination value."
232
+ end
233
+ end
234
+ end
235
+
236
+ # Find the place at which +value+ would normally be inserted into the
237
+ # Enumerable. If that place is already occupied by +value+, do nothing
238
+ # and return +nil+. If the place does not exist (i.e., it is off the end
239
+ # of the Enumerable), add it to the end. Otherwise, replace the element
240
+ # at that point with +value+. It is assumed that the Enumerable's values
241
+ # are numeric.
242
+ #
243
+ # This operation preserves the sort order.
244
+ def replace_next_larger(enum, value, last_index = nil)
245
+ # Off the end?
246
+ if enum.empty? or (value > enum[-1])
247
+ enum << value
248
+ return enum.size - 1
249
+ end
250
+
251
+ # Binary search for the insertion point
252
+ last_index ||= enum.size
253
+ first_index = 0
254
+ while (first_index <= last_index)
255
+ i = (first_index + last_index) >> 1
256
+
257
+ found = enum[i]
258
+
259
+ if value == found
260
+ return nil
261
+ elsif value > found
262
+ first_index = i + 1
263
+ else
264
+ last_index = i - 1
265
+ end
266
+ end
267
+
268
+ # The insertion point is in first_index; overwrite the next larger
269
+ # value.
270
+ enum[first_index] = value
271
+ return first_index
272
+ end
273
+ private :replace_next_larger
274
+
275
+ # If +vector+ maps the matching elements of another collection onto this
276
+ # Enumerable, compute the inverse of +vector+ that maps this Enumerable
277
+ # onto the collection. (Currently unused.)
278
+ def inverse_vector(a, vector)
279
+ inverse = a.dup
280
+ (0...vector.size).each do |i|
281
+ inverse[vector[i]] = i unless vector[i].nil?
282
+ end
283
+ inverse
284
+ end
285
+ private :inverse_vector
286
+
287
+ # Returns a hash mapping each element of an Enumerable to the set of
288
+ # positions it occupies in the Enumerable, optionally restricted to the
289
+ # elements specified in the range of indexes specified by +interval+.
290
+ def position_hash(enum, interval)
291
+ string = enum.kind_of?(String)
292
+ hash = Hash.new { |h, k| h[k] = [] }
293
+ interval.each do |i|
294
+ k = string ? enum[i, 1] : enum[i]
295
+ hash[k] << i
296
+ end
297
+ hash
298
+ end
299
+ private :position_hash
300
+ end
@@ -1,39 +1,39 @@
1
- #!/usr/bin/env ruby
1
+ # -*- ruby encoding: utf-8 -*-
2
2
 
3
3
  require 'optparse'
4
4
  require 'ostruct'
5
5
  require 'diff/lcs/hunk'
6
6
 
7
- # == ldiff Usage
8
- # ldiff [options] oldfile newfile
9
- #
10
- # -c:: Displays a context diff with 3 lines of context.
11
- # -C [LINES], --context [LINES]:: Displays a context diff with LINES lines of context. Default 3 lines.
12
- # -u:: Displays a unified diff with 3 lines of context.
13
- # -U [LINES], --unified [LINES]:: Displays a unified diff with LINES lines of context. Default 3 lines.
14
- # -e:: Creates an 'ed' script to change oldfile to newfile.
15
- # -f:: Creates an 'ed' script to change oldfile to newfile in reverse order.
16
- # -a, --text:: Treats the files as text and compares them line-by-line, even if they do not seem to be text.
17
- # --binary:: Treats the files as binary.
18
- # -q, --brief:: Reports only whether or not the files differ, not the details.
19
- # --help:: Shows the command-line help.
20
- # --version:: Shows the version of Diff::LCS.
21
- #
22
- # By default, runs produces an "old-style" diff, with output like UNIX diff.
23
- #
24
- # == Copyright
25
- # Copyright &copy; 2004 Austin Ziegler
26
- #
27
- # Part of Diff::LCS <http://rubyforge.org/projects/ruwiki/>
28
- # Austin Ziegler <diff-lcs@halostatue.ca>
29
- #
30
- # This program is free software. It may be redistributed and/or modified under
31
- # the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
32
- # Ruby licence.
7
+ # == ldiff Usage
8
+ # ldiff [options] oldfile newfile
9
+ #
10
+ # -c:: Displays a context diff with 3 lines of context.
11
+ # -C [LINES], --context [LINES]:: Displays a context diff with LINES lines of context. Default 3 lines.
12
+ # -u:: Displays a unified diff with 3 lines of context.
13
+ # -U [LINES], --unified [LINES]:: Displays a unified diff with LINES lines of context. Default 3 lines.
14
+ # -e:: Creates an 'ed' script to change oldfile to newfile.
15
+ # -f:: Creates an 'ed' script to change oldfile to newfile in reverse order.
16
+ # -a, --text:: Treats the files as text and compares them line-by-line, even if they do not seem to be text.
17
+ # --binary:: Treats the files as binary.
18
+ # -q, --brief:: Reports only whether or not the files differ, not the details.
19
+ # --help:: Shows the command-line help.
20
+ # --version:: Shows the version of Diff::LCS.
21
+ #
22
+ # By default, runs produces an "old-style" diff, with output like UNIX diff.
23
+ #
24
+ # == Copyright
25
+ # Copyright &copy; 2004 Austin Ziegler
26
+ #
27
+ # Part of Diff::LCS <http://rubyforge.org/projects/ruwiki/>
28
+ # Austin Ziegler <diff-lcs@halostatue.ca>
29
+ #
30
+ # This program is free software. It may be redistributed and/or modified under
31
+ # the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
32
+ # Ruby licence.
33
33
  module Diff::LCS::Ldiff
34
34
  BANNER = <<-COPYRIGHT
35
35
  ldiff #{Diff::LCS::VERSION}
36
- Copyright 2004-2011 Austin Ziegler
36
+ Copyright 2004-2013 Austin Ziegler
37
37
 
38
38
  Part of Diff::LCS.
39
39
  http://rubyforge.org/projects/ruwiki/
@@ -43,168 +43,153 @@ ldiff #{Diff::LCS::VERSION}
43
43
  This program is free software. It may be redistributed and/or modified under
44
44
  the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
45
45
  MIT licence.
46
-
47
- $Id$
48
46
  COPYRIGHT
47
+ end
49
48
 
50
- class << self
51
- attr_reader :format, :lines #:nodoc:
52
- attr_reader :file_old, :file_new #:nodoc:
53
- attr_reader :data_old, :data_new #:nodoc:
54
-
55
- def run(args, input = $stdin, output = $stdout, error = $stderr) #:nodoc:
56
- @binary = nil
57
-
58
- args.options do |o|
59
- o.banner = "Usage: #{File.basename($0)} [options] oldfile newfile"
60
- o.separator ""
61
- o.on('-c', 'Displays a context diff with 3 lines of', 'context.') do |ctx|
62
- @format = :context
63
- @lines = 3
64
- end
65
- o.on('-C', '--context [LINES]', Numeric, 'Displays a context diff with LINES lines', 'of context. Default 3 lines.') do |ctx|
66
- @format = :context
67
- @lines = ctx || 3
68
- end
69
- o.on('-u', 'Displays a unified diff with 3 lines of', 'context.') do |ctx|
70
- @format = :unified
71
- @lines = 3
72
- end
73
- o.on('-U', '--unified [LINES]', Numeric, 'Displays a unified diff with LINES lines', 'of context. Default 3 lines.') do |ctx|
74
- @format = :unified
75
- @lines = ctx || 3
76
- end
77
- o.on('-e', 'Creates an \'ed\' script to change', 'oldfile to newfile.') do |ctx|
78
- @format = :ed
79
- end
80
- o.on('-f', 'Creates an \'ed\' script to change', 'oldfile to newfile in reverse order.') do |ctx|
81
- @format = :reverse_ed
82
- end
83
- o.on('-a', '--text', 'Treat the files as text and compare them', 'line-by-line, even if they do not seem', 'to be text.') do |txt|
84
- @binary = false
85
- end
86
- o.on('--binary', 'Treats the files as binary.') do |bin|
87
- @binary = true
88
- end
89
- o.on('-q', '--brief', 'Report only whether or not the files', 'differ, not the details.') do |ctx|
90
- @format = :report
91
- end
92
- o.on_tail('--help', 'Shows this text.') do
93
- error << o
94
- return 0
95
- end
96
- o.on_tail('--version', 'Shows the version of Diff::LCS.') do
97
- error << BANNER
98
- return 0
99
- end
100
- o.on_tail ""
101
- o.on_tail 'By default, runs produces an "old-style" diff, with output like UNIX diff.'
102
- o.parse!
103
- end
49
+ class << Diff::LCS::Ldiff
50
+ attr_reader :format, :lines #:nodoc:
51
+ attr_reader :file_old, :file_new #:nodoc:
52
+ attr_reader :data_old, :data_new #:nodoc:
104
53
 
105
- unless args.size == 2
106
- error << args.options
107
- return 127
54
+ def run(args, input = $stdin, output = $stdout, error = $stderr) #:nodoc:
55
+ @binary = nil
56
+
57
+ args.options do |o|
58
+ o.banner = "Usage: #{File.basename($0)} [options] oldfile newfile"
59
+ o.separator ""
60
+ o.on('-c', '-C', '--context [LINES]', Numeric, 'Displays a context diff with LINES lines', 'of context. Default 3 lines.') do |ctx|
61
+ @format = :context
62
+ @lines = ctx || 3
63
+ end
64
+ o.on('-u', '-U', '--unified [LINES]', Numeric, 'Displays a unified diff with LINES lines', 'of context. Default 3 lines.') do |ctx|
65
+ @format = :unified
66
+ @lines = ctx || 3
67
+ end
68
+ o.on('-e', 'Creates an \'ed\' script to change', 'oldfile to newfile.') do |ctx|
69
+ @format = :ed
70
+ end
71
+ o.on('-f', 'Creates an \'ed\' script to change', 'oldfile to newfile in reverse order.') do |ctx|
72
+ @format = :reverse_ed
73
+ end
74
+ o.on('-a', '--text', 'Treat the files as text and compare them', 'line-by-line, even if they do not seem', 'to be text.') do |txt|
75
+ @binary = false
76
+ end
77
+ o.on('--binary', 'Treats the files as binary.') do |bin|
78
+ @binary = true
108
79
  end
80
+ o.on('-q', '--brief', 'Report only whether or not the files', 'differ, not the details.') do |ctx|
81
+ @format = :report
82
+ end
83
+ o.on_tail('--help', 'Shows this text.') do
84
+ error << o
85
+ return 0
86
+ end
87
+ o.on_tail('--version', 'Shows the version of Diff::LCS.') do
88
+ error << BANNER
89
+ return 0
90
+ end
91
+ o.on_tail ""
92
+ o.on_tail 'By default, runs produces an "old-style" diff, with output like UNIX diff.'
93
+ o.parse!
94
+ end
109
95
 
110
- # Defaults are for old-style diff
111
- @format ||= :old
112
- @lines ||= 0
96
+ unless args.size == 2
97
+ error << args.options
98
+ return 127
99
+ end
113
100
 
114
- file_old, file_new = *ARGV
101
+ # Defaults are for old-style diff
102
+ @format ||= :old
103
+ @lines ||= 0
115
104
 
116
- case @format
117
- when :context
118
- char_old = '*' * 3
119
- char_new = '-' * 3
120
- when :unified
121
- char_old = '-' * 3
122
- char_new = '+' * 3
123
- end
105
+ file_old, file_new = *ARGV
124
106
 
125
- # After we've read up to a certain point in each file, the number of
126
- # items we've read from each file will differ by FLD (could be 0).
127
- file_length_difference = 0
128
-
129
- if @binary.nil? or @binary
130
- data_old = IO::read(file_old)
131
- data_new = IO::read(file_new)
132
-
133
- # Test binary status
134
- if @binary.nil?
135
- old_txt = data_old[0...4096].grep(/\0/).empty?
136
- new_txt = data_new[0...4096].grep(/\0/).empty?
137
- @binary = (not old_txt) or (not new_txt)
138
- old_txt = new_txt = nil
139
- end
140
-
141
- unless @binary
142
- data_old = data_old.split(/\n/).map! { |e| e.chomp }
143
- data_new = data_new.split(/\n/).map! { |e| e.chomp }
144
- end
145
- else
146
- data_old = IO::readlines(file_old).map! { |e| e.chomp }
147
- data_new = IO::readlines(file_new).map! { |e| e.chomp }
148
- end
107
+ case @format
108
+ when :context
109
+ char_old = '*' * 3
110
+ char_new = '-' * 3
111
+ when :unified
112
+ char_old = '-' * 3
113
+ char_new = '+' * 3
114
+ end
149
115
 
150
- # diff yields lots of pieces, each of which is basically a Block object
151
- if @binary
152
- diffs = (data_old == data_new)
153
- else
154
- diffs = Diff::LCS.diff(data_old, data_new)
155
- diffs = nil if diffs.empty?
156
- end
116
+ # After we've read up to a certain point in each file, the number of
117
+ # items we've read from each file will differ by FLD (could be 0).
118
+ file_length_difference = 0
157
119
 
158
- return 0 unless diffs
120
+ if @binary.nil? or @binary
121
+ data_old = IO::read(file_old)
122
+ data_new = IO::read(file_new)
159
123
 
160
- if (@format == :report) and diffs
161
- output << "Files #{file_old} and #{file_new} differ\n"
162
- return 1
124
+ # Test binary status
125
+ if @binary.nil?
126
+ old_txt = data_old[0...4096].scan(/\0/).empty?
127
+ new_txt = data_new[0...4096].scan(/\0/).empty?
128
+ @binary = (not old_txt) or (not new_txt)
129
+ old_txt = new_txt = nil
163
130
  end
164
131
 
165
- if (@format == :unified) or (@format == :context)
166
- ft = File.stat(file_old).mtime.localtime.strftime('%Y-%m-%d %H:%M:%S %z')
167
- puts "#{char_old} #{file_old}\t#{ft}"
168
- ft = File.stat(file_new).mtime.localtime.strftime('%Y-%m-%d %H:%M:%S %z')
169
- puts "#{char_new} #{file_new}\t#{ft}"
132
+ unless @binary
133
+ data_old = data_old.split($/).map { |e| e.chomp }
134
+ data_new = data_new.split($/).map { |e| e.chomp }
170
135
  end
136
+ else
137
+ data_old = IO::readlines(file_old).map { |e| e.chomp }
138
+ data_new = IO::readlines(file_new).map { |e| e.chomp }
139
+ end
171
140
 
172
- # Loop over hunks. If a hunk overlaps with the last hunk, join them.
173
- # Otherwise, print out the old one.
174
- oldhunk = hunk = nil
141
+ # diff yields lots of pieces, each of which is basically a Block object
142
+ if @binary
143
+ diffs = (data_old == data_new)
144
+ else
145
+ diffs = Diff::LCS.diff(data_old, data_new)
146
+ diffs = nil if diffs.empty?
147
+ end
175
148
 
176
- if @format == :ed
177
- real_output = output
178
- output = []
179
- end
149
+ return 0 unless diffs
180
150
 
181
- diffs.each do |piece|
182
- begin
183
- hunk = Diff::LCS::Hunk.new(data_old, data_new, piece, @lines,
184
- file_length_difference)
185
- file_length_difference = hunk.file_length_difference
186
-
187
- next unless oldhunk
188
-
189
- if (@lines > 0) and hunk.overlaps?(oldhunk)
190
- hunk.unshift(oldhunk)
191
- else
192
- output << oldhunk.diff(@format)
193
- end
194
- ensure
195
- oldhunk = hunk
196
- output << "\n"
197
- end
198
- end
151
+ if (@format == :report) and diffs
152
+ output << "Files #{file_old} and #{file_new} differ\n"
153
+ return 1
154
+ end
155
+
156
+ if (@format == :unified) or (@format == :context)
157
+ ft = File.stat(file_old).mtime.localtime.strftime('%Y-%m-%d %H:%M:%S.%N %z')
158
+ puts "#{char_old} #{file_old}\t#{ft}"
159
+ ft = File.stat(file_new).mtime.localtime.strftime('%Y-%m-%d %H:%M:%S.%N %z')
160
+ puts "#{char_new} #{file_new}\t#{ft}"
161
+ end
199
162
 
200
- output << oldhunk.diff(@format)
201
- output << "\n"
163
+ # Loop over hunks. If a hunk overlaps with the last hunk, join them.
164
+ # Otherwise, print out the old one.
165
+ oldhunk = hunk = nil
202
166
 
203
- if @format == :ed
204
- output.reverse_each { |e| real_output << e.diff(:ed_finish) }
167
+ if @format == :ed
168
+ real_output = output
169
+ output = []
170
+ end
171
+
172
+ diffs.each do |piece|
173
+ begin
174
+ hunk = Diff::LCS::Hunk.new(data_old, data_new, piece, @lines,
175
+ file_length_difference)
176
+ file_length_difference = hunk.file_length_difference
177
+
178
+ next unless oldhunk
179
+ next if (@lines > 0) and hunk.merge(oldhunk)
180
+
181
+ output << oldhunk.diff(@format) << "\n"
182
+ ensure
183
+ oldhunk = hunk
205
184
  end
185
+ end
206
186
 
207
- return 1
187
+ output << oldhunk.diff(@format) << "\n"
188
+
189
+ if @format == :ed
190
+ output.reverse_each { |e| real_output << e.diff(:ed_finish) }
208
191
  end
192
+
193
+ return 1
209
194
  end
210
195
  end