diff-lcs 1.2.5 → 1.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +6 -14
 - data/.rspec +0 -1
 - data/Code-of-Conduct.md +74 -0
 - data/Contributing.md +118 -0
 - data/History.md +319 -0
 - data/{License.rdoc → License.md} +0 -0
 - data/Manifest.txt +15 -8
 - data/README.rdoc +18 -19
 - data/Rakefile +57 -24
 - data/autotest/discover.rb +3 -1
 - data/bin/htmldiff +7 -4
 - data/bin/ldiff +4 -1
 - data/lib/diff-lcs.rb +1 -1
 - data/lib/diff/lcs.rb +188 -254
 - data/lib/diff/lcs/array.rb +1 -1
 - data/lib/diff/lcs/backports.rb +9 -0
 - data/lib/diff/lcs/block.rb +1 -1
 - data/lib/diff/lcs/callbacks.rb +15 -12
 - data/lib/diff/lcs/change.rb +33 -36
 - data/lib/diff/lcs/htmldiff.rb +17 -16
 - data/lib/diff/lcs/hunk.rb +156 -74
 - data/lib/diff/lcs/internals.rb +43 -40
 - data/lib/diff/lcs/ldiff.rb +51 -75
 - data/lib/diff/lcs/string.rb +1 -1
 - data/spec/change_spec.rb +31 -7
 - data/spec/diff_spec.rb +24 -20
 - data/spec/fixtures/aX +1 -0
 - data/spec/fixtures/bXaX +1 -0
 - data/spec/fixtures/ds1.csv +50 -0
 - data/spec/fixtures/ds2.csv +51 -0
 - data/spec/fixtures/ldiff/output.diff +4 -0
 - data/spec/fixtures/ldiff/output.diff-c +7 -0
 - data/spec/fixtures/ldiff/output.diff-e +3 -0
 - data/spec/fixtures/ldiff/output.diff-f +3 -0
 - data/spec/fixtures/ldiff/output.diff-u +5 -0
 - data/spec/hunk_spec.rb +54 -43
 - data/spec/issues_spec.rb +147 -17
 - data/spec/lcs_spec.rb +24 -22
 - data/spec/ldiff_spec.rb +87 -0
 - data/spec/patch_spec.rb +182 -180
 - data/spec/sdiff_spec.rb +91 -91
 - data/spec/spec_helper.rb +143 -58
 - data/spec/traverse_balanced_spec.rb +177 -177
 - data/spec/traverse_sequences_spec.rb +63 -63
 - metadata +87 -143
 - checksums.yaml.gz.sig +0 -0
 - data.tar.gz.sig +0 -3
 - data/.autotest +0 -3
 - data/.gemtest +0 -0
 - data/.hoerc +0 -2
 - data/.travis.yml +0 -22
 - data/Contributing.rdoc +0 -64
 - data/Gemfile +0 -20
 - data/History.rdoc +0 -152
 - metadata.gz.sig +0 -2
 
    
        data/lib/diff/lcs/array.rb
    CHANGED
    
    
    
        data/lib/diff/lcs/block.rb
    CHANGED
    
    
    
        data/lib/diff/lcs/callbacks.rb
    CHANGED
    
    | 
         @@ -1,8 +1,8 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            #  
     | 
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require 'diff/lcs/change'
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
            module Diff::LCS
         
     | 
| 
      
 5 
     | 
    
         
            +
            module Diff::LCS # rubocop:disable Style/Documentation
         
     | 
| 
       6 
6 
     | 
    
         
             
              # This callback object implements the default set of callback events,
         
     | 
| 
       7 
7 
     | 
    
         
             
              # which only returns the event itself. Note that #finished_a and
         
     | 
| 
       8 
8 
     | 
    
         
             
              # #finished_b are not implemented -- I haven't yet figured out where they
         
     | 
| 
         @@ -17,14 +17,17 @@ module Diff::LCS 
     | 
|
| 
       17 
17 
     | 
    
         
             
                  def match(event)
         
     | 
| 
       18 
18 
     | 
    
         
             
                    event
         
     | 
| 
       19 
19 
     | 
    
         
             
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
       20 
21 
     | 
    
         
             
                  # Called when the old value is discarded in favour of the new value.
         
     | 
| 
       21 
22 
     | 
    
         
             
                  def discard_a(event)
         
     | 
| 
       22 
23 
     | 
    
         
             
                    event
         
     | 
| 
       23 
24 
     | 
    
         
             
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
       24 
26 
     | 
    
         
             
                  # Called when the new value is discarded in favour of the old value.
         
     | 
| 
       25 
27 
     | 
    
         
             
                  def discard_b(event)
         
     | 
| 
       26 
28 
     | 
    
         
             
                    event
         
     | 
| 
       27 
29 
     | 
    
         
             
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
       28 
31 
     | 
    
         
             
                  # Called when both the old and new values have changed.
         
     | 
| 
       29 
32 
     | 
    
         
             
                  def change(event)
         
     | 
| 
       30 
33 
     | 
    
         
             
                    event
         
     | 
| 
         @@ -108,12 +111,12 @@ class Diff::LCS::DiffCallbacks 
     | 
|
| 
       108 
111 
     | 
    
         
             
                @hunk = []
         
     | 
| 
       109 
112 
     | 
    
         
             
                @diffs = []
         
     | 
| 
       110 
113 
     | 
    
         | 
| 
       111 
     | 
    
         
            -
                 
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
       114 
     | 
    
         
            -
                   
     | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
       116 
     | 
    
         
            -
                   
     | 
| 
      
 114 
     | 
    
         
            +
                return unless block_given?
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                begin
         
     | 
| 
      
 117 
     | 
    
         
            +
                  yield self
         
     | 
| 
      
 118 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 119 
     | 
    
         
            +
                  finish
         
     | 
| 
       117 
120 
     | 
    
         
             
                end
         
     | 
| 
       118 
121 
     | 
    
         
             
              end
         
     | 
| 
       119 
122 
     | 
    
         | 
| 
         @@ -123,7 +126,7 @@ class Diff::LCS::DiffCallbacks 
     | 
|
| 
       123 
126 
     | 
    
         
             
                finish_hunk
         
     | 
| 
       124 
127 
     | 
    
         
             
              end
         
     | 
| 
       125 
128 
     | 
    
         | 
| 
       126 
     | 
    
         
            -
              def match( 
     | 
| 
      
 129 
     | 
    
         
            +
              def match(_event)
         
     | 
| 
       127 
130 
     | 
    
         
             
                finish_hunk
         
     | 
| 
       128 
131 
     | 
    
         
             
              end
         
     | 
| 
       129 
132 
     | 
    
         | 
| 
         @@ -190,7 +193,7 @@ end 
     | 
|
| 
       190 
193 
     | 
    
         
             
            # Diff::LCS::SDiffCallbacks. They may be compared as:
         
     | 
| 
       191 
194 
     | 
    
         
             
            #
         
     | 
| 
       192 
195 
     | 
    
         
             
            #     s = Diff::LCS.sdiff(seq1, seq2).reject { |e| e.action == "=" }
         
     | 
| 
       193 
     | 
    
         
            -
            #     c = Diff::LCS.sdiff(seq1, seq2, Diff::LCS::ContextDiffCallbacks).flatten
         
     | 
| 
      
 196 
     | 
    
         
            +
            #     c = Diff::LCS.sdiff(seq1, seq2, Diff::LCS::ContextDiffCallbacks).flatten(1)
         
     | 
| 
       194 
197 
     | 
    
         
             
            #
         
     | 
| 
       195 
198 
     | 
    
         
             
            #     s == c # -> true
         
     | 
| 
       196 
199 
     | 
    
         
             
            #
         
     | 
| 
         @@ -241,7 +244,7 @@ end 
     | 
|
| 
       241 
244 
     | 
    
         
             
            # will compute and display the necessary components to show two sequences
         
     | 
| 
       242 
245 
     | 
    
         
             
            # and their minimized differences side by side, just like the Unix utility
         
     | 
| 
       243 
246 
     | 
    
         
             
            # +sdiff+.
         
     | 
| 
       244 
     | 
    
         
            -
            # 
     | 
| 
      
 247 
     | 
    
         
            +
            #
         
     | 
| 
       245 
248 
     | 
    
         
             
            #     same             same
         
     | 
| 
       246 
249 
     | 
    
         
             
            #     before     |     after
         
     | 
| 
       247 
250 
     | 
    
         
             
            #     old        <     -
         
     | 
| 
         @@ -270,7 +273,7 @@ end 
     | 
|
| 
       270 
273 
     | 
    
         
             
            # Diff::LCS::ContextDiffCallbacks. They may be compared as:
         
     | 
| 
       271 
274 
     | 
    
         
             
            #
         
     | 
| 
       272 
275 
     | 
    
         
             
            #     s = Diff::LCS.sdiff(seq1, seq2).reject { |e| e.action == "=" }
         
     | 
| 
       273 
     | 
    
         
            -
            #     c = Diff::LCS.sdiff(seq1, seq2, Diff::LCS::ContextDiffCallbacks).flatten
         
     | 
| 
      
 276 
     | 
    
         
            +
            #     c = Diff::LCS.sdiff(seq1, seq2, Diff::LCS::ContextDiffCallbacks).flatten(1)
         
     | 
| 
       274 
277 
     | 
    
         
             
            #
         
     | 
| 
       275 
278 
     | 
    
         
             
            #     s == c # -> true
         
     | 
| 
       276 
279 
     | 
    
         
             
            #
         
     | 
    
        data/lib/diff/lcs/change.rb
    CHANGED
    
    | 
         @@ -1,14 +1,16 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            #  
     | 
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            # Represents a simplistic (non-contextual) change. Represents the removal or
         
     | 
| 
       4 
4 
     | 
    
         
             
            # addition of an element from either the old or the new sequenced
         
     | 
| 
       5 
5 
     | 
    
         
             
            # enumerable.
         
     | 
| 
       6 
6 
     | 
    
         
             
            class Diff::LCS::Change
         
     | 
| 
      
 7 
     | 
    
         
            +
              IntClass = 1.class # Fixnum is deprecated in Ruby 2.4 # rubocop:disable Naming/ConstantName
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
       7 
9 
     | 
    
         
             
              # The only actions valid for changes are '+' (add), '-' (delete), '='
         
     | 
| 
       8 
10 
     | 
    
         
             
              # (no change), '!' (changed), '<' (tail changes from first sequence), or
         
     | 
| 
       9 
11 
     | 
    
         
             
              # '>' (tail changes from second sequence). The last two ('<>') are only
         
     | 
| 
       10 
12 
     | 
    
         
             
              # found with Diff::LCS::diff and Diff::LCS::sdiff.
         
     | 
| 
       11 
     | 
    
         
            -
              VALID_ACTIONS = % 
     | 
| 
      
 13 
     | 
    
         
            +
              VALID_ACTIONS = %w(+ - = ! > <).freeze
         
     | 
| 
       12 
14 
     | 
    
         | 
| 
       13 
15 
     | 
    
         
             
              def self.valid_action?(action)
         
     | 
| 
       14 
16 
     | 
    
         
             
                VALID_ACTIONS.include? action
         
     | 
| 
         @@ -25,20 +27,20 @@ class Diff::LCS::Change 
     | 
|
| 
       25 
27 
     | 
    
         
             
              def initialize(*args)
         
     | 
| 
       26 
28 
     | 
    
         
             
                @action, @position, @element = *args
         
     | 
| 
       27 
29 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
                unless Diff::LCS::Change.valid_action?(@action)
         
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
                end
         
     | 
| 
       31 
     | 
    
         
            -
                raise "Invalid Position Type" unless @position.kind_of? Fixnum
         
     | 
| 
      
 30 
     | 
    
         
            +
                fail "Invalid Change Action '#{@action}'" unless Diff::LCS::Change.valid_action?(@action)
         
     | 
| 
      
 31 
     | 
    
         
            +
                fail 'Invalid Position Type' unless @position.kind_of? IntClass
         
     | 
| 
       32 
32 
     | 
    
         
             
              end
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
       34 
     | 
    
         
            -
              def inspect
         
     | 
| 
       35 
     | 
    
         
            -
                to_a.inspect
         
     | 
| 
      
 34 
     | 
    
         
            +
              def inspect(*_args)
         
     | 
| 
      
 35 
     | 
    
         
            +
                "#<#{self.class}: #{to_a.inspect}>"
         
     | 
| 
       36 
36 
     | 
    
         
             
              end
         
     | 
| 
       37 
37 
     | 
    
         | 
| 
       38 
38 
     | 
    
         
             
              def to_a
         
     | 
| 
       39 
     | 
    
         
            -
                [ 
     | 
| 
      
 39 
     | 
    
         
            +
                [@action, @position, @element]
         
     | 
| 
       40 
40 
     | 
    
         
             
              end
         
     | 
| 
       41 
41 
     | 
    
         | 
| 
      
 42 
     | 
    
         
            +
              alias to_ary to_a
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
       42 
44 
     | 
    
         
             
              def self.from_a(arr)
         
     | 
| 
       43 
45 
     | 
    
         
             
                arr = arr.flatten(1)
         
     | 
| 
       44 
46 
     | 
    
         
             
                case arr.size
         
     | 
| 
         @@ -47,22 +49,23 @@ class Diff::LCS::Change 
     | 
|
| 
       47 
49 
     | 
    
         
             
                when 3
         
     | 
| 
       48 
50 
     | 
    
         
             
                  Diff::LCS::Change.new(*(arr[0...3]))
         
     | 
| 
       49 
51 
     | 
    
         
             
                else
         
     | 
| 
       50 
     | 
    
         
            -
                   
     | 
| 
      
 52 
     | 
    
         
            +
                  fail 'Invalid change array format provided.'
         
     | 
| 
       51 
53 
     | 
    
         
             
                end
         
     | 
| 
       52 
54 
     | 
    
         
             
              end
         
     | 
| 
       53 
55 
     | 
    
         | 
| 
       54 
56 
     | 
    
         
             
              include Comparable
         
     | 
| 
       55 
57 
     | 
    
         | 
| 
       56 
58 
     | 
    
         
             
              def ==(other)
         
     | 
| 
       57 
     | 
    
         
            -
                (self. 
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
      
 59 
     | 
    
         
            +
                (self.class == other.class) and
         
     | 
| 
      
 60 
     | 
    
         
            +
                  (action == other.action) and
         
     | 
| 
      
 61 
     | 
    
         
            +
                  (position == other.position) and
         
     | 
| 
      
 62 
     | 
    
         
            +
                  (element == other.element)
         
     | 
| 
       60 
63 
     | 
    
         
             
              end
         
     | 
| 
       61 
64 
     | 
    
         | 
| 
       62 
65 
     | 
    
         
             
              def <=>(other)
         
     | 
| 
       63 
     | 
    
         
            -
                r =  
     | 
| 
       64 
     | 
    
         
            -
                r =  
     | 
| 
       65 
     | 
    
         
            -
                r =  
     | 
| 
      
 66 
     | 
    
         
            +
                r = action <=> other.action
         
     | 
| 
      
 67 
     | 
    
         
            +
                r = position <=> other.position if r.zero?
         
     | 
| 
      
 68 
     | 
    
         
            +
                r = element <=> other.element if r.zero?
         
     | 
| 
       66 
69 
     | 
    
         
             
                r
         
     | 
| 
       67 
70 
     | 
    
         
             
              end
         
     | 
| 
       68 
71 
     | 
    
         | 
| 
         @@ -111,27 +114,20 @@ class Diff::LCS::ContextChange < Diff::LCS::Change 
     | 
|
| 
       111 
114 
     | 
    
         
             
              def initialize(*args)
         
     | 
| 
       112 
115 
     | 
    
         
             
                @action, @old_position, @old_element, @new_position, @new_element = *args
         
     | 
| 
       113 
116 
     | 
    
         | 
| 
       114 
     | 
    
         
            -
                unless Diff::LCS::Change.valid_action?(@action)
         
     | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
       116 
     | 
    
         
            -
                 
     | 
| 
       117 
     | 
    
         
            -
                unless @old_position.nil? or @old_position.kind_of? Fixnum
         
     | 
| 
       118 
     | 
    
         
            -
                  raise "Invalid (Old) Position Type"
         
     | 
| 
       119 
     | 
    
         
            -
                end
         
     | 
| 
       120 
     | 
    
         
            -
                unless @new_position.nil? or @new_position.kind_of? Fixnum
         
     | 
| 
       121 
     | 
    
         
            -
                  raise "Invalid (New) Position Type"
         
     | 
| 
       122 
     | 
    
         
            -
                end
         
     | 
| 
      
 117 
     | 
    
         
            +
                fail "Invalid Change Action '#{@action}'" unless Diff::LCS::Change.valid_action?(@action)
         
     | 
| 
      
 118 
     | 
    
         
            +
                fail 'Invalid (Old) Position Type' unless @old_position.nil? or @old_position.kind_of? IntClass
         
     | 
| 
      
 119 
     | 
    
         
            +
                fail 'Invalid (New) Position Type' unless @new_position.nil? or @new_position.kind_of? IntClass
         
     | 
| 
       123 
120 
     | 
    
         
             
              end
         
     | 
| 
       124 
121 
     | 
    
         | 
| 
       125 
122 
     | 
    
         
             
              def to_a
         
     | 
| 
       126 
     | 
    
         
            -
                [ 
     | 
| 
       127 
     | 
    
         
            -
                   
     | 
| 
       128 
     | 
    
         
            -
                  [ 
     | 
| 
      
 123 
     | 
    
         
            +
                [
         
     | 
| 
      
 124 
     | 
    
         
            +
                  @action,
         
     | 
| 
      
 125 
     | 
    
         
            +
                  [@old_position, @old_element],
         
     | 
| 
      
 126 
     | 
    
         
            +
                  [@new_position, @new_element]
         
     | 
| 
       129 
127 
     | 
    
         
             
                ]
         
     | 
| 
       130 
128 
     | 
    
         
             
              end
         
     | 
| 
       131 
129 
     | 
    
         | 
| 
       132 
     | 
    
         
            -
               
     | 
| 
       133 
     | 
    
         
            -
                to_a.inspect
         
     | 
| 
       134 
     | 
    
         
            -
              end
         
     | 
| 
      
 130 
     | 
    
         
            +
              alias to_ary to_a
         
     | 
| 
       135 
131 
     | 
    
         | 
| 
       136 
132 
     | 
    
         
             
              def self.from_a(arr)
         
     | 
| 
       137 
133 
     | 
    
         
             
                Diff::LCS::Change.from_a(arr)
         
     | 
| 
         @@ -159,11 +155,12 @@ class Diff::LCS::ContextChange < Diff::LCS::Change 
     | 
|
| 
       159 
155 
     | 
    
         
             
              end
         
     | 
| 
       160 
156 
     | 
    
         | 
| 
       161 
157 
     | 
    
         
             
              def ==(other)
         
     | 
| 
       162 
     | 
    
         
            -
                ( 
     | 
| 
       163 
     | 
    
         
            -
             
     | 
| 
       164 
     | 
    
         
            -
             
     | 
| 
       165 
     | 
    
         
            -
             
     | 
| 
       166 
     | 
    
         
            -
             
     | 
| 
      
 158 
     | 
    
         
            +
                (self.class == other.class) and
         
     | 
| 
      
 159 
     | 
    
         
            +
                  (@action == other.action) and
         
     | 
| 
      
 160 
     | 
    
         
            +
                  (@old_position == other.old_position) and
         
     | 
| 
      
 161 
     | 
    
         
            +
                  (@new_position == other.new_position) and
         
     | 
| 
      
 162 
     | 
    
         
            +
                  (@old_element == other.old_element) and
         
     | 
| 
      
 163 
     | 
    
         
            +
                  (@new_element == other.new_element)
         
     | 
| 
       167 
164 
     | 
    
         
             
              end
         
     | 
| 
       168 
165 
     | 
    
         | 
| 
       169 
166 
     | 
    
         
             
              def <=>(other)
         
     | 
    
        data/lib/diff/lcs/htmldiff.rb
    CHANGED
    
    | 
         @@ -1,14 +1,15 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            #  
     | 
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require 'cgi'
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
      
 5 
     | 
    
         
            +
            # Produce a simple HTML diff view.
         
     | 
| 
       5 
6 
     | 
    
         
             
            class Diff::LCS::HTMLDiff
         
     | 
| 
       6 
7 
     | 
    
         
             
              class << self
         
     | 
| 
       7 
8 
     | 
    
         
             
                attr_accessor :can_expand_tabs #:nodoc:
         
     | 
| 
       8 
9 
     | 
    
         
             
              end
         
     | 
| 
       9 
10 
     | 
    
         
             
              self.can_expand_tabs = true
         
     | 
| 
       10 
11 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
              class Callbacks
         
     | 
| 
      
 12 
     | 
    
         
            +
              class Callbacks #:nodoc:
         
     | 
| 
       12 
13 
     | 
    
         
             
                attr_accessor :output
         
     | 
| 
       13 
14 
     | 
    
         
             
                attr_accessor :match_class
         
     | 
| 
       14 
15 
     | 
    
         
             
                attr_accessor :only_a_class
         
     | 
| 
         @@ -18,14 +19,14 @@ class Diff::LCS::HTMLDiff 
     | 
|
| 
       18 
19 
     | 
    
         
             
                  @output = output
         
     | 
| 
       19 
20 
     | 
    
         
             
                  options ||= {}
         
     | 
| 
       20 
21 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
                  @match_class = options[:match_class] ||  
     | 
| 
       22 
     | 
    
         
            -
                  @only_a_class = options[:only_a_class] ||  
     | 
| 
       23 
     | 
    
         
            -
                  @only_b_class = options[:only_b_class] ||  
     | 
| 
      
 22 
     | 
    
         
            +
                  @match_class = options[:match_class] || 'match'
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @only_a_class = options[:only_a_class] || 'only_a'
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @only_b_class = options[:only_b_class] || 'only_b'
         
     | 
| 
       24 
25 
     | 
    
         
             
                end
         
     | 
| 
       25 
26 
     | 
    
         | 
| 
       26 
27 
     | 
    
         
             
                def htmlize(element, css_class)
         
     | 
| 
       27 
     | 
    
         
            -
                  element =  
     | 
| 
       28 
     | 
    
         
            -
                  %Q 
     | 
| 
      
 28 
     | 
    
         
            +
                  element = ' ' if element.empty?
         
     | 
| 
      
 29 
     | 
    
         
            +
                  %Q(<pre class="#{__send__(css_class)}">#{element}</pre>\n)
         
     | 
| 
       29 
30 
     | 
    
         
             
                end
         
     | 
| 
       30 
31 
     | 
    
         
             
                private :htmlize
         
     | 
| 
       31 
32 
     | 
    
         | 
| 
         @@ -49,8 +50,8 @@ class Diff::LCS::HTMLDiff 
     | 
|
| 
       49 
50 
     | 
    
         
             
                :expand_tabs => nil,
         
     | 
| 
       50 
51 
     | 
    
         
             
                :output => nil,
         
     | 
| 
       51 
52 
     | 
    
         
             
                :css => nil,
         
     | 
| 
       52 
     | 
    
         
            -
                :title => nil 
     | 
| 
       53 
     | 
    
         
            -
              }
         
     | 
| 
      
 53 
     | 
    
         
            +
                :title => nil
         
     | 
| 
      
 54 
     | 
    
         
            +
              }.freeze
         
     | 
| 
       54 
55 
     | 
    
         | 
| 
       55 
56 
     | 
    
         
             
              DEFAULT_CSS = <<-CSS
         
     | 
| 
       56 
57 
     | 
    
         
             
            body { margin: 0; }
         
     | 
| 
         @@ -96,13 +97,13 @@ h1 { margin-left: 2em; } 
     | 
|
| 
       96 
97 
     | 
    
         | 
| 
       97 
98 
     | 
    
         
             
              def verify_options
         
     | 
| 
       98 
99 
     | 
    
         
             
                @options[:expand_tabs] ||= 4
         
     | 
| 
       99 
     | 
    
         
            -
                @options[:expand_tabs] = 4 if @options[:expand_tabs] 
     | 
| 
      
 100 
     | 
    
         
            +
                @options[:expand_tabs] = 4 if @options[:expand_tabs].negative?
         
     | 
| 
       100 
101 
     | 
    
         | 
| 
       101 
102 
     | 
    
         
             
                @options[:output] ||= $stdout
         
     | 
| 
       102 
103 
     | 
    
         | 
| 
       103 
104 
     | 
    
         
             
                @options[:css] ||= DEFAULT_CSS.dup
         
     | 
| 
       104 
105 
     | 
    
         | 
| 
       105 
     | 
    
         
            -
                @options[:title] ||=  
     | 
| 
      
 106 
     | 
    
         
            +
                @options[:title] ||= 'diff'
         
     | 
| 
       106 
107 
     | 
    
         
             
              end
         
     | 
| 
       107 
108 
     | 
    
         
             
              private :verify_options
         
     | 
| 
       108 
109 
     | 
    
         | 
| 
         @@ -111,16 +112,16 @@ h1 { margin-left: 2em; } 
     | 
|
| 
       111 
112 
     | 
    
         
             
              def run
         
     | 
| 
       112 
113 
     | 
    
         
             
                verify_options
         
     | 
| 
       113 
114 
     | 
    
         | 
| 
       114 
     | 
    
         
            -
                if @options[:expand_tabs]  
     | 
| 
      
 115 
     | 
    
         
            +
                if @options[:expand_tabs].positive? && self.class.can_expand_tabs
         
     | 
| 
       115 
116 
     | 
    
         
             
                  formatter = Text::Format.new
         
     | 
| 
       116 
117 
     | 
    
         
             
                  formatter.tabstop = @options[:expand_tabs]
         
     | 
| 
       117 
118 
     | 
    
         | 
| 
       118 
     | 
    
         
            -
                  @left 
     | 
| 
       119 
     | 
    
         
            -
                  @right 
     | 
| 
      
 119 
     | 
    
         
            +
                  @left.map! do |line| formatter.expand(line.chomp) end
         
     | 
| 
      
 120 
     | 
    
         
            +
                  @right.map! do |line| formatter.expand(line.chomp) end
         
     | 
| 
       120 
121 
     | 
    
         
             
                end
         
     | 
| 
       121 
122 
     | 
    
         | 
| 
       122 
     | 
    
         
            -
                @left.map!  
     | 
| 
       123 
     | 
    
         
            -
                @right.map!  
     | 
| 
      
 123 
     | 
    
         
            +
                @left.map! do |line| CGI.escapeHTML(line.chomp) end
         
     | 
| 
      
 124 
     | 
    
         
            +
                @right.map! do |line| CGI.escapeHTML(line.chomp) end
         
     | 
| 
       124 
125 
     | 
    
         | 
| 
       125 
126 
     | 
    
         
             
                @options[:output] << <<-OUTPUT
         
     | 
| 
       126 
127 
     | 
    
         
             
            <html>
         
     | 
    
        data/lib/diff/lcs/hunk.rb
    CHANGED
    
    | 
         @@ -1,30 +1,43 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            #  
     | 
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require 'diff/lcs/block'
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
            # A Hunk is a group of Blocks which overlap because of the context
         
     | 
| 
       6 
     | 
    
         
            -
            #  
     | 
| 
       7 
     | 
    
         
            -
            #  
     | 
| 
      
 5 
     | 
    
         
            +
            # A Hunk is a group of Blocks which overlap because of the context surrounding
         
     | 
| 
      
 6 
     | 
    
         
            +
            # each block. (So if we're not using context, every hunk will contain one
         
     | 
| 
      
 7 
     | 
    
         
            +
            # block.) Used in the diff program (bin/ldiff).
         
     | 
| 
       8 
8 
     | 
    
         
             
            class Diff::LCS::Hunk
         
     | 
| 
       9 
     | 
    
         
            -
               
     | 
| 
       10 
     | 
    
         
            -
               
     | 
| 
      
 9 
     | 
    
         
            +
              OLD_DIFF_OP_ACTION = { '+' => 'a', '-' => 'd', '!' => 'c' }.freeze #:nodoc:
         
     | 
| 
      
 10 
     | 
    
         
            +
              ED_DIFF_OP_ACTION = { '+' => 'a', '-' => 'd', '!' => 'c' }.freeze #:nodoc:
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              private_constant :OLD_DIFF_OP_ACTION, :ED_DIFF_OP_ACTION if respond_to?(:private_constant)
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              # Create a hunk using references to both the old and new data, as well as the
         
     | 
| 
      
 15 
     | 
    
         
            +
              # piece of data.
         
     | 
| 
       11 
16 
     | 
    
         
             
              def initialize(data_old, data_new, piece, flag_context, file_length_difference)
         
     | 
| 
       12 
17 
     | 
    
         
             
                # At first, a hunk will have just one Block in it
         
     | 
| 
       13 
     | 
    
         
            -
                @blocks = [ 
     | 
| 
      
 18 
     | 
    
         
            +
                @blocks = [Diff::LCS::Block.new(piece)]
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                if @blocks[0].remove.empty? && @blocks[0].insert.empty?
         
     | 
| 
      
 21 
     | 
    
         
            +
                  fail "Cannot build a hunk from #{piece.inspect}; has no add or remove actions"
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
       14 
24 
     | 
    
         
             
                if String.method_defined?(:encoding)
         
     | 
| 
       15 
     | 
    
         
            -
                  @preferred_data_encoding = data_old.fetch(0, data_new.fetch(0,'') 
     | 
| 
      
 25 
     | 
    
         
            +
                  @preferred_data_encoding = data_old.fetch(0, data_new.fetch(0, '')).encoding
         
     | 
| 
       16 
26 
     | 
    
         
             
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
       17 
28 
     | 
    
         
             
                @data_old = data_old
         
     | 
| 
       18 
29 
     | 
    
         
             
                @data_new = data_new
         
     | 
| 
       19 
30 
     | 
    
         | 
| 
       20 
31 
     | 
    
         
             
                before = after = file_length_difference
         
     | 
| 
       21 
32 
     | 
    
         
             
                after += @blocks[0].diff_size
         
     | 
| 
       22 
33 
     | 
    
         
             
                @file_length_difference = after # The caller must get this manually
         
     | 
| 
      
 34 
     | 
    
         
            +
                @max_diff_size = @blocks.map { |e| e.diff_size.abs }.max
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
       23 
36 
     | 
    
         | 
| 
       24 
37 
     | 
    
         
             
                # Save the start & end of each array. If the array doesn't exist (e.g.,
         
     | 
| 
       25 
     | 
    
         
            -
                # we're only adding items in this block), then figure out the line
         
     | 
| 
       26 
     | 
    
         
            -
                #  
     | 
| 
       27 
     | 
    
         
            -
                #  
     | 
| 
      
 38 
     | 
    
         
            +
                # we're only adding items in this block), then figure out the line number
         
     | 
| 
      
 39 
     | 
    
         
            +
                # based on the line number of the other file and the current difference in
         
     | 
| 
      
 40 
     | 
    
         
            +
                # file lengths.
         
     | 
| 
       28 
41 
     | 
    
         
             
                if @blocks[0].remove.empty?
         
     | 
| 
       29 
42 
     | 
    
         
             
                  a1 = a2 = nil
         
     | 
| 
       30 
43 
     | 
    
         
             
                else
         
     | 
| 
         @@ -54,20 +67,27 @@ class Diff::LCS::Hunk 
     | 
|
| 
       54 
67 
     | 
    
         | 
| 
       55 
68 
     | 
    
         
             
              # Change the "start" and "end" fields to note that context should be added
         
     | 
| 
       56 
69 
     | 
    
         
             
              # to this hunk.
         
     | 
| 
       57 
     | 
    
         
            -
              attr_accessor :flag_context
         
     | 
| 
       58 
     | 
    
         
            -
              undef :flag_context 
     | 
| 
       59 
     | 
    
         
            -
              def flag_context=(context) #:nodoc:
         
     | 
| 
      
 70 
     | 
    
         
            +
              attr_accessor :flag_context # rubocop:disable Layout/EmptyLinesAroundAttributeAccessor
         
     | 
| 
      
 71 
     | 
    
         
            +
              undef :flag_context=
         
     | 
| 
      
 72 
     | 
    
         
            +
              def flag_context=(context) #:nodoc: # rubocop:disable Lint/DuplicateMethods
         
     | 
| 
       60 
73 
     | 
    
         
             
                return if context.nil? or context.zero?
         
     | 
| 
       61 
74 
     | 
    
         | 
| 
       62 
     | 
    
         
            -
                add_start =  
     | 
| 
      
 75 
     | 
    
         
            +
                add_start = context > @start_old ? @start_old : context
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
       63 
77 
     | 
    
         
             
                @start_old -= add_start
         
     | 
| 
       64 
78 
     | 
    
         
             
                @start_new -= add_start
         
     | 
| 
       65 
79 
     | 
    
         | 
| 
       66 
     | 
    
         
            -
                 
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
                 
     | 
| 
       69 
     | 
    
         
            -
                   
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
      
 80 
     | 
    
         
            +
                old_size = @data_old.size
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                add_end =
         
     | 
| 
      
 83 
     | 
    
         
            +
                  if (@end_old + context) > old_size
         
     | 
| 
      
 84 
     | 
    
         
            +
                    old_size - @end_old
         
     | 
| 
      
 85 
     | 
    
         
            +
                  else
         
     | 
| 
      
 86 
     | 
    
         
            +
                    context
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                add_end = @max_diff_size if add_end >= old_size
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
       71 
91 
     | 
    
         
             
                @end_old += add_end
         
     | 
| 
       72 
92 
     | 
    
         
             
                @end_new += add_end
         
     | 
| 
       73 
93 
     | 
    
         
             
              end
         
     | 
| 
         @@ -76,15 +96,13 @@ class Diff::LCS::Hunk 
     | 
|
| 
       76 
96 
     | 
    
         
             
              # a truthy value so that if there is no overlap, you can know the merge
         
     | 
| 
       77 
97 
     | 
    
         
             
              # was skipped.
         
     | 
| 
       78 
98 
     | 
    
         
             
              def merge(hunk)
         
     | 
| 
       79 
     | 
    
         
            -
                 
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
       82 
     | 
    
         
            -
             
     | 
| 
       83 
     | 
    
         
            -
                 
     | 
| 
       84 
     | 
    
         
            -
                  nil
         
     | 
| 
       85 
     | 
    
         
            -
                end
         
     | 
| 
      
 99 
     | 
    
         
            +
                return unless overlaps?(hunk)
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                @start_old = hunk.start_old
         
     | 
| 
      
 102 
     | 
    
         
            +
                @start_new = hunk.start_new
         
     | 
| 
      
 103 
     | 
    
         
            +
                blocks.unshift(*hunk.blocks)
         
     | 
| 
       86 
104 
     | 
    
         
             
              end
         
     | 
| 
       87 
     | 
    
         
            -
               
     | 
| 
      
 105 
     | 
    
         
            +
              alias unshift merge
         
     | 
| 
       88 
106 
     | 
    
         | 
| 
       89 
107 
     | 
    
         
             
              # Determines whether there is an overlap between this hunk and the
         
     | 
| 
       90 
108 
     | 
    
         
             
              # provided hunk. This will be true if the difference between the two hunks
         
     | 
| 
         @@ -95,47 +113,53 @@ class Diff::LCS::Hunk 
     | 
|
| 
       95 
113 
     | 
    
         
             
              end
         
     | 
| 
       96 
114 
     | 
    
         | 
| 
       97 
115 
     | 
    
         
             
              # Returns a diff string based on a format.
         
     | 
| 
       98 
     | 
    
         
            -
              def diff(format)
         
     | 
| 
      
 116 
     | 
    
         
            +
              def diff(format, last = false)
         
     | 
| 
       99 
117 
     | 
    
         
             
                case format
         
     | 
| 
       100 
118 
     | 
    
         
             
                when :old
         
     | 
| 
       101 
     | 
    
         
            -
                  old_diff
         
     | 
| 
      
 119 
     | 
    
         
            +
                  old_diff(last)
         
     | 
| 
       102 
120 
     | 
    
         
             
                when :unified
         
     | 
| 
       103 
     | 
    
         
            -
                  unified_diff
         
     | 
| 
      
 121 
     | 
    
         
            +
                  unified_diff(last)
         
     | 
| 
       104 
122 
     | 
    
         
             
                when :context
         
     | 
| 
       105 
     | 
    
         
            -
                  context_diff
         
     | 
| 
      
 123 
     | 
    
         
            +
                  context_diff(last)
         
     | 
| 
       106 
124 
     | 
    
         
             
                when :ed
         
     | 
| 
       107 
125 
     | 
    
         
             
                  self
         
     | 
| 
       108 
126 
     | 
    
         
             
                when :reverse_ed, :ed_finish
         
     | 
| 
       109 
     | 
    
         
            -
                  ed_diff(format)
         
     | 
| 
      
 127 
     | 
    
         
            +
                  ed_diff(format, last)
         
     | 
| 
       110 
128 
     | 
    
         
             
                else
         
     | 
| 
       111 
     | 
    
         
            -
                   
     | 
| 
      
 129 
     | 
    
         
            +
                  fail "Unknown diff format #{format}."
         
     | 
| 
       112 
130 
     | 
    
         
             
                end
         
     | 
| 
       113 
131 
     | 
    
         
             
              end
         
     | 
| 
       114 
132 
     | 
    
         | 
| 
       115 
133 
     | 
    
         
             
              # Note that an old diff can't have any context. Therefore, we know that
         
     | 
| 
       116 
134 
     | 
    
         
             
              # there's only one block in the hunk.
         
     | 
| 
       117 
     | 
    
         
            -
              def old_diff
         
     | 
| 
       118 
     | 
    
         
            -
                warn  
     | 
| 
       119 
     | 
    
         
            -
                op_act = { "+" => 'a', "-" => 'd', "!" => "c" }
         
     | 
| 
      
 135 
     | 
    
         
            +
              def old_diff(_last = false)
         
     | 
| 
      
 136 
     | 
    
         
            +
                warn 'Expecting only one block in an old diff hunk!' if @blocks.size > 1
         
     | 
| 
       120 
137 
     | 
    
         | 
| 
       121 
138 
     | 
    
         
             
                block = @blocks[0]
         
     | 
| 
       122 
139 
     | 
    
         | 
| 
       123 
140 
     | 
    
         
             
                # Calculate item number range. Old diff range is just like a context
         
     | 
| 
       124 
141 
     | 
    
         
             
                # diff range, except the ranges are on one line with the action between
         
     | 
| 
       125 
142 
     | 
    
         
             
                # them.
         
     | 
| 
       126 
     | 
    
         
            -
                s = encode("#{context_range(:old)}#{ 
     | 
| 
      
 143 
     | 
    
         
            +
                s = encode("#{context_range(:old, ',')}#{OLD_DIFF_OP_ACTION[block.op]}#{context_range(:new, ',')}\n")
         
     | 
| 
       127 
144 
     | 
    
         
             
                # If removing anything, just print out all the remove lines in the hunk
         
     | 
| 
       128 
145 
     | 
    
         
             
                # which is just all the remove lines in the block.
         
     | 
| 
       129 
     | 
    
         
            -
                 
     | 
| 
       130 
     | 
    
         
            -
             
     | 
| 
       131 
     | 
    
         
            -
                 
     | 
| 
      
 146 
     | 
    
         
            +
                unless block.remove.empty?
         
     | 
| 
      
 147 
     | 
    
         
            +
                  @data_old[@start_old..@end_old].each { |e| s << encode('< ') + e.chomp + encode("\n") }
         
     | 
| 
      
 148 
     | 
    
         
            +
                end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                s << encode("---\n") if block.op == '!'
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                unless block.insert.empty?
         
     | 
| 
      
 153 
     | 
    
         
            +
                  @data_new[@start_new..@end_new].each { |e| s << encode('> ') + e.chomp + encode("\n") }
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
       132 
156 
     | 
    
         
             
                s
         
     | 
| 
       133 
157 
     | 
    
         
             
              end
         
     | 
| 
       134 
158 
     | 
    
         
             
              private :old_diff
         
     | 
| 
       135 
159 
     | 
    
         | 
| 
       136 
     | 
    
         
            -
              def unified_diff
         
     | 
| 
      
 160 
     | 
    
         
            +
              def unified_diff(last = false)
         
     | 
| 
       137 
161 
     | 
    
         
             
                # Calculate item number range.
         
     | 
| 
       138 
     | 
    
         
            -
                s = encode("@@ -#{unified_range(:old)} +#{unified_range(:new)} @@\n")
         
     | 
| 
      
 162 
     | 
    
         
            +
                s = encode("@@ -#{unified_range(:old, last)} +#{unified_range(:new, last)} @@\n")
         
     | 
| 
       139 
163 
     | 
    
         | 
| 
       140 
164 
     | 
    
         
             
                # Outlist starts containing the hunk of the old file. Removing an item
         
     | 
| 
       141 
165 
     | 
    
         
             
                # just means putting a '-' in front of it. Inserting an item requires
         
     | 
| 
         @@ -148,7 +172,14 @@ class Diff::LCS::Hunk 
     | 
|
| 
       148 
172 
     | 
    
         
             
                # file -- don't take removed items into account.
         
     | 
| 
       149 
173 
     | 
    
         
             
                lo, hi, num_added, num_removed = @start_old, @end_old, 0, 0
         
     | 
| 
       150 
174 
     | 
    
         | 
| 
       151 
     | 
    
         
            -
                outlist = @data_old[lo 
     | 
| 
      
 175 
     | 
    
         
            +
                outlist = @data_old[lo..hi].map { |e| String.new("#{encode(' ')}#{e.chomp}") }
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                last_block = blocks[-1]
         
     | 
| 
      
 178 
     | 
    
         
            +
             
     | 
| 
      
 179 
     | 
    
         
            +
                if last
         
     | 
| 
      
 180 
     | 
    
         
            +
                  old_missing_newline = missing_last_newline?(@data_old)
         
     | 
| 
      
 181 
     | 
    
         
            +
                  new_missing_newline = missing_last_newline?(@data_new)
         
     | 
| 
      
 182 
     | 
    
         
            +
                end
         
     | 
| 
       152 
183 
     | 
    
         | 
| 
       153 
184 
     | 
    
         
             
                @blocks.each do |block|
         
     | 
| 
       154 
185 
     | 
    
         
             
                  block.remove.each do |item|
         
     | 
| 
         @@ -157,66 +188,100 @@ class Diff::LCS::Hunk 
     | 
|
| 
       157 
188 
     | 
    
         
             
                    outlist[offset][0, 1] = encode(op)
         
     | 
| 
       158 
189 
     | 
    
         
             
                    num_removed += 1
         
     | 
| 
       159 
190 
     | 
    
         
             
                  end
         
     | 
| 
      
 191 
     | 
    
         
            +
             
     | 
| 
      
 192 
     | 
    
         
            +
                  if last && block == last_block && old_missing_newline && !new_missing_newline
         
     | 
| 
      
 193 
     | 
    
         
            +
                    outlist << encode('\')
         
     | 
| 
      
 194 
     | 
    
         
            +
                    num_removed += 1
         
     | 
| 
      
 195 
     | 
    
         
            +
                  end
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
       160 
197 
     | 
    
         
             
                  block.insert.each do |item|
         
     | 
| 
       161 
198 
     | 
    
         
             
                    op     = item.action.to_s # +
         
     | 
| 
       162 
199 
     | 
    
         
             
                    offset = item.position - @start_new + num_removed
         
     | 
| 
       163 
     | 
    
         
            -
                    outlist[offset, 0] = encode(op) + @data_new[item.position]
         
     | 
| 
      
 200 
     | 
    
         
            +
                    outlist[offset, 0] = encode(op) + @data_new[item.position].chomp
         
     | 
| 
       164 
201 
     | 
    
         
             
                    num_added += 1
         
     | 
| 
       165 
202 
     | 
    
         
             
                  end
         
     | 
| 
       166 
203 
     | 
    
         
             
                end
         
     | 
| 
       167 
204 
     | 
    
         | 
| 
      
 205 
     | 
    
         
            +
                outlist << encode('\') if last && new_missing_newline
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
       168 
207 
     | 
    
         
             
                s << outlist.join(encode("\n"))
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
                s
         
     | 
| 
       169 
210 
     | 
    
         
             
              end
         
     | 
| 
       170 
211 
     | 
    
         
             
              private :unified_diff
         
     | 
| 
       171 
212 
     | 
    
         | 
| 
       172 
     | 
    
         
            -
              def context_diff
         
     | 
| 
      
 213 
     | 
    
         
            +
              def context_diff(last = false)
         
     | 
| 
       173 
214 
     | 
    
         
             
                s = encode("***************\n")
         
     | 
| 
       174 
     | 
    
         
            -
                s << encode("*** #{context_range(:old)} ****\n")
         
     | 
| 
       175 
     | 
    
         
            -
                r = context_range(:new)
         
     | 
| 
      
 215 
     | 
    
         
            +
                s << encode("*** #{context_range(:old, ',', last)} ****\n")
         
     | 
| 
      
 216 
     | 
    
         
            +
                r = context_range(:new, ',', last)
         
     | 
| 
      
 217 
     | 
    
         
            +
             
     | 
| 
      
 218 
     | 
    
         
            +
                if last
         
     | 
| 
      
 219 
     | 
    
         
            +
                  old_missing_newline = missing_last_newline?(@data_old)
         
     | 
| 
      
 220 
     | 
    
         
            +
                  new_missing_newline = missing_last_newline?(@data_new)
         
     | 
| 
      
 221 
     | 
    
         
            +
                end
         
     | 
| 
       176 
222 
     | 
    
         | 
| 
       177 
223 
     | 
    
         
             
                # Print out file 1 part for each block in context diff format if there
         
     | 
| 
       178 
224 
     | 
    
         
             
                # are any blocks that remove items
         
     | 
| 
       179 
225 
     | 
    
         
             
                lo, hi = @start_old, @end_old
         
     | 
| 
       180 
     | 
    
         
            -
                removes = @blocks. 
     | 
| 
       181 
     | 
    
         
            -
             
     | 
| 
       182 
     | 
    
         
            -
             
     | 
| 
      
 226 
     | 
    
         
            +
                removes = @blocks.reject { |e| e.remove.empty? }
         
     | 
| 
      
 227 
     | 
    
         
            +
             
     | 
| 
      
 228 
     | 
    
         
            +
                unless removes.empty?
         
     | 
| 
      
 229 
     | 
    
         
            +
                  outlist = @data_old[lo..hi].map { |e| String.new("#{encode('  ')}#{e.chomp}") }
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
                  last_block = removes[-1]
         
     | 
| 
       183 
232 
     | 
    
         | 
| 
       184 
233 
     | 
    
         
             
                  removes.each do |block|
         
     | 
| 
       185 
234 
     | 
    
         
             
                    block.remove.each do |item|
         
     | 
| 
       186 
235 
     | 
    
         
             
                      outlist[item.position - lo][0, 1] = encode(block.op) # - or !
         
     | 
| 
       187 
236 
     | 
    
         
             
                    end
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                    if last && block == last_block && old_missing_newline
         
     | 
| 
      
 239 
     | 
    
         
            +
                      outlist << encode('\')
         
     | 
| 
      
 240 
     | 
    
         
            +
                    end
         
     | 
| 
       188 
241 
     | 
    
         
             
                  end
         
     | 
| 
       189 
     | 
    
         
            -
             
     | 
| 
      
 242 
     | 
    
         
            +
             
     | 
| 
      
 243 
     | 
    
         
            +
                  s << outlist.join(encode("\n")) << encode("\n")
         
     | 
| 
       190 
244 
     | 
    
         
             
                end
         
     | 
| 
       191 
245 
     | 
    
         | 
| 
       192 
     | 
    
         
            -
                s << encode(" 
     | 
| 
      
 246 
     | 
    
         
            +
                s << encode("--- #{r} ----\n")
         
     | 
| 
       193 
247 
     | 
    
         
             
                lo, hi = @start_new, @end_new
         
     | 
| 
       194 
     | 
    
         
            -
                inserts = @blocks. 
     | 
| 
       195 
     | 
    
         
            -
             
     | 
| 
       196 
     | 
    
         
            -
             
     | 
| 
      
 248 
     | 
    
         
            +
                inserts = @blocks.reject { |e| e.insert.empty? }
         
     | 
| 
      
 249 
     | 
    
         
            +
             
     | 
| 
      
 250 
     | 
    
         
            +
                unless inserts.empty?
         
     | 
| 
      
 251 
     | 
    
         
            +
                  outlist = @data_new[lo..hi].map { |e| String.new("#{encode('  ')}#{e.chomp}") }
         
     | 
| 
      
 252 
     | 
    
         
            +
             
     | 
| 
      
 253 
     | 
    
         
            +
                  last_block = inserts[-1]
         
     | 
| 
      
 254 
     | 
    
         
            +
             
     | 
| 
       197 
255 
     | 
    
         
             
                  inserts.each do |block|
         
     | 
| 
       198 
256 
     | 
    
         
             
                    block.insert.each do |item|
         
     | 
| 
       199 
257 
     | 
    
         
             
                      outlist[item.position - lo][0, 1] = encode(block.op) # + or !
         
     | 
| 
       200 
258 
     | 
    
         
             
                    end
         
     | 
| 
      
 259 
     | 
    
         
            +
             
     | 
| 
      
 260 
     | 
    
         
            +
                    if last && block == last_block && new_missing_newline
         
     | 
| 
      
 261 
     | 
    
         
            +
                      outlist << encode('\')
         
     | 
| 
      
 262 
     | 
    
         
            +
                    end
         
     | 
| 
       201 
263 
     | 
    
         
             
                  end
         
     | 
| 
       202 
     | 
    
         
            -
                  s << outlist.join("\n")
         
     | 
| 
      
 264 
     | 
    
         
            +
                  s << outlist.join(encode("\n"))
         
     | 
| 
       203 
265 
     | 
    
         
             
                end
         
     | 
| 
      
 266 
     | 
    
         
            +
             
     | 
| 
       204 
267 
     | 
    
         
             
                s
         
     | 
| 
       205 
268 
     | 
    
         
             
              end
         
     | 
| 
       206 
269 
     | 
    
         
             
              private :context_diff
         
     | 
| 
       207 
270 
     | 
    
         | 
| 
       208 
     | 
    
         
            -
              def ed_diff(format)
         
     | 
| 
       209 
     | 
    
         
            -
                 
     | 
| 
       210 
     | 
    
         
            -
                warn "Expecting only one block in an old diff hunk!" if @blocks.size > 1
         
     | 
| 
      
 271 
     | 
    
         
            +
              def ed_diff(format, _last = false)
         
     | 
| 
      
 272 
     | 
    
         
            +
                warn 'Expecting only one block in an old diff hunk!' if @blocks.size > 1
         
     | 
| 
       211 
273 
     | 
    
         | 
| 
       212 
     | 
    
         
            -
                 
     | 
| 
       213 
     | 
    
         
            -
                   
     | 
| 
       214 
     | 
    
         
            -
             
     | 
| 
       215 
     | 
    
         
            -
                   
     | 
| 
       216 
     | 
    
         
            -
             
     | 
| 
      
 274 
     | 
    
         
            +
                s =
         
     | 
| 
      
 275 
     | 
    
         
            +
                  if format == :reverse_ed
         
     | 
| 
      
 276 
     | 
    
         
            +
                    encode("#{ED_DIFF_OP_ACTION[@blocks[0].op]}#{context_range(:old, ',')}\n")
         
     | 
| 
      
 277 
     | 
    
         
            +
                  else
         
     | 
| 
      
 278 
     | 
    
         
            +
                    encode("#{context_range(:old, ' ')}#{ED_DIFF_OP_ACTION[@blocks[0].op]}\n")
         
     | 
| 
      
 279 
     | 
    
         
            +
                  end
         
     | 
| 
       217 
280 
     | 
    
         | 
| 
       218 
281 
     | 
    
         
             
                unless @blocks[0].insert.empty?
         
     | 
| 
       219 
     | 
    
         
            -
                  @data_new[@start_new 
     | 
| 
      
 282 
     | 
    
         
            +
                  @data_new[@start_new..@end_new].each do |e|
         
     | 
| 
      
 283 
     | 
    
         
            +
                    s << e.chomp + encode("\n")
         
     | 
| 
      
 284 
     | 
    
         
            +
                  end
         
     | 
| 
       220 
285 
     | 
    
         
             
                  s << encode(".\n")
         
     | 
| 
       221 
286 
     | 
    
         
             
                end
         
     | 
| 
       222 
287 
     | 
    
         
             
                s
         
     | 
| 
         @@ -225,7 +290,7 @@ class Diff::LCS::Hunk 
     | 
|
| 
       225 
290 
     | 
    
         | 
| 
       226 
291 
     | 
    
         
             
              # Generate a range of item numbers to print. Only print 1 number if the
         
     | 
| 
       227 
292 
     | 
    
         
             
              # range has only one item in it. Otherwise, it's 'start,end'
         
     | 
| 
       228 
     | 
    
         
            -
              def context_range(mode, op =  
     | 
| 
      
 293 
     | 
    
         
            +
              def context_range(mode, op, last = false)
         
     | 
| 
       229 
294 
     | 
    
         
             
                case mode
         
     | 
| 
       230 
295 
     | 
    
         
             
                when :old
         
     | 
| 
       231 
296 
     | 
    
         
             
                  s, e = (@start_old + 1), (@end_old + 1)
         
     | 
| 
         @@ -233,14 +298,17 @@ class Diff::LCS::Hunk 
     | 
|
| 
       233 
298 
     | 
    
         
             
                  s, e = (@start_new + 1), (@end_new + 1)
         
     | 
| 
       234 
299 
     | 
    
         
             
                end
         
     | 
| 
       235 
300 
     | 
    
         | 
| 
       236 
     | 
    
         
            -
                 
     | 
| 
      
 301 
     | 
    
         
            +
                e -= 1 if last
         
     | 
| 
      
 302 
     | 
    
         
            +
                e = 1 if e.zero?
         
     | 
| 
      
 303 
     | 
    
         
            +
             
     | 
| 
      
 304 
     | 
    
         
            +
                s < e ? "#{s}#{op}#{e}" : e.to_s
         
     | 
| 
       237 
305 
     | 
    
         
             
              end
         
     | 
| 
       238 
306 
     | 
    
         
             
              private :context_range
         
     | 
| 
       239 
307 
     | 
    
         | 
| 
       240 
308 
     | 
    
         
             
              # Generate a range of item numbers to print for unified diff. Print number
         
     | 
| 
       241 
309 
     | 
    
         
             
              # where block starts, followed by number of lines in the block
         
     | 
| 
       242 
310 
     | 
    
         
             
              # (don't print number of lines if it's 1)
         
     | 
| 
       243 
     | 
    
         
            -
              def unified_range(mode)
         
     | 
| 
      
 311 
     | 
    
         
            +
              def unified_range(mode, last)
         
     | 
| 
       244 
312 
     | 
    
         
             
                case mode
         
     | 
| 
       245 
313 
     | 
    
         
             
                when :old
         
     | 
| 
       246 
314 
     | 
    
         
             
                  s, e = (@start_old + 1), (@end_old + 1)
         
     | 
| 
         @@ -248,12 +316,25 @@ class Diff::LCS::Hunk 
     | 
|
| 
       248 
316 
     | 
    
         
             
                  s, e = (@start_new + 1), (@end_new + 1)
         
     | 
| 
       249 
317 
     | 
    
         
             
                end
         
     | 
| 
       250 
318 
     | 
    
         | 
| 
       251 
     | 
    
         
            -
                length = e - s + 1
         
     | 
| 
       252 
     | 
    
         
            -
             
     | 
| 
       253 
     | 
    
         
            -
                 
     | 
| 
      
 319 
     | 
    
         
            +
                length = e - s + (last ? 0 : 1)
         
     | 
| 
      
 320 
     | 
    
         
            +
             
     | 
| 
      
 321 
     | 
    
         
            +
                first = length < 2 ? e : s # "strange, but correct"
         
     | 
| 
      
 322 
     | 
    
         
            +
                length <= 1 ? first.to_s : "#{first},#{length}"
         
     | 
| 
       254 
323 
     | 
    
         
             
              end
         
     | 
| 
       255 
324 
     | 
    
         
             
              private :unified_range
         
     | 
| 
       256 
325 
     | 
    
         | 
| 
      
 326 
     | 
    
         
            +
              def missing_last_newline?(data)
         
     | 
| 
      
 327 
     | 
    
         
            +
                newline = encode("\n")
         
     | 
| 
      
 328 
     | 
    
         
            +
             
     | 
| 
      
 329 
     | 
    
         
            +
                if data[-2]
         
     | 
| 
      
 330 
     | 
    
         
            +
                  data[-2].end_with?(newline) && !data[-1].end_with?(newline)
         
     | 
| 
      
 331 
     | 
    
         
            +
                elsif data[-1]
         
     | 
| 
      
 332 
     | 
    
         
            +
                  !data[-1].end_with?(newline)
         
     | 
| 
      
 333 
     | 
    
         
            +
                else
         
     | 
| 
      
 334 
     | 
    
         
            +
                  true
         
     | 
| 
      
 335 
     | 
    
         
            +
                end
         
     | 
| 
      
 336 
     | 
    
         
            +
              end
         
     | 
| 
      
 337 
     | 
    
         
            +
             
     | 
| 
       257 
338 
     | 
    
         
             
              if String.method_defined?(:encoding)
         
     | 
| 
       258 
339 
     | 
    
         
             
                def encode(literal, target_encoding = @preferred_data_encoding)
         
     | 
| 
       259 
340 
     | 
    
         
             
                  literal.encode target_encoding
         
     | 
| 
         @@ -263,10 +344,11 @@ class Diff::LCS::Hunk 
     | 
|
| 
       263 
344 
     | 
    
         
             
                  args.map { |arg| arg.encode(string.encoding) }
         
     | 
| 
       264 
345 
     | 
    
         
             
                end
         
     | 
| 
       265 
346 
     | 
    
         
             
              else
         
     | 
| 
       266 
     | 
    
         
            -
                def encode(literal,  
     | 
| 
      
 347 
     | 
    
         
            +
                def encode(literal, _target_encoding = nil)
         
     | 
| 
       267 
348 
     | 
    
         
             
                  literal
         
     | 
| 
       268 
349 
     | 
    
         
             
                end
         
     | 
| 
       269 
     | 
    
         
            -
             
     | 
| 
      
 350 
     | 
    
         
            +
             
     | 
| 
      
 351 
     | 
    
         
            +
                def encode_as(_string, *args)
         
     | 
| 
       270 
352 
     | 
    
         
             
                  args
         
     | 
| 
       271 
353 
     | 
    
         
             
                end
         
     | 
| 
       272 
354 
     | 
    
         
             
              end
         
     |