Class: Diff::LCS::Ldiff

Inherits:
Object
  • Object
show all
Defined in:
lib/diff/lcs/ldiff.rb

Overview

:nodoc:

Defined Under Namespace

Classes: InputInfo

Constant Summary collapse

"ldiff \#{Diff::LCS::VERSION}\n  Copyright 2004-2025 Austin Ziegler\n\nPart of Diff::LCS.\nhttps://github.com/halostatue/diff-lcs\n\nThis program is free software. It may be redistributed and/or modified under\nthe terms of the GPL version 2 (or later), the Perl Artistic licence, or the\nMIT licence.\n"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeLdiff

Returns a new instance of Ldiff.



38
39
40
41
42
# File 'lib/diff/lcs/ldiff.rb', line 38

def initialize
  @binary = nil
  @format = :old
  @lines = 0
end

Instance Attribute Details

#data_newObject (readonly)

:nodoc:



32
33
34
# File 'lib/diff/lcs/ldiff.rb', line 32

def data_new
  @data_new
end

#data_oldObject (readonly)

:nodoc:



32
33
34
# File 'lib/diff/lcs/ldiff.rb', line 32

def data_old
  @data_old
end

#file_newObject (readonly)

:nodoc:



31
32
33
# File 'lib/diff/lcs/ldiff.rb', line 31

def file_new
  @file_new
end

#file_oldObject (readonly)

:nodoc:



31
32
33
# File 'lib/diff/lcs/ldiff.rb', line 31

def file_old
  @file_old
end

#formatObject (readonly)

:nodoc:



30
31
32
# File 'lib/diff/lcs/ldiff.rb', line 30

def format
  @format
end

#linesObject (readonly)

:nodoc:



30
31
32
# File 'lib/diff/lcs/ldiff.rb', line 30

def lines
  @lines
end

Class Method Details

.run(args, input = $stdin, output = $stdout, error = $stderr) ⇒ Object

:nodoc:



34
35
36
# File 'lib/diff/lcs/ldiff.rb', line 34

def self.run(args, input = $stdin, output = $stdout, error = $stderr) # :nodoc:
  new.run(args, input, output, error)
end

Instance Method Details

#diff?(info_old, info_new, format, output, binary: nil, lines: 0) ⇒ Boolean

Returns:

  • (Boolean)


107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/diff/lcs/ldiff.rb', line 107

def diff?(info_old, info_new, format, output, binary: nil, lines: 0)
  case format
  when :context
    char_old = "*" * 3
    char_new = "-" * 3
  when :unified
    char_old = "-" * 3
    char_new = "+" * 3
  end

  # After we've read up to a certain point in each file, the number of items we've read
  # from each file will differ by FLD (could be 0).
  file_length_difference = 0

  # Test binary status
  if binary.nil?
    old_bin = info_old.data[0, 4096].include?("\0")
    new_bin = info_new.data[0, 4096].include?("\0")
    binary = old_bin || new_bin
  end

  # diff yields lots of pieces, each of which is basically a Block object
  if binary
    has_diffs = (info_old.data != info_new.data)
    if format != :report
      if has_diffs
        output << "Binary files #{info_old.filename} and #{info_new.filename} differ\n"
        return true
      end
      return false
    end
  else
    data_old = info_old.data.lines.to_a
    data_new = info_new.data.lines.to_a
    diffs = Diff::LCS.diff(data_old, data_new)
    return false if diffs.empty?
  end

  case format
  when :report
    output << "Files #{info_old.filename} and #{info_new.filename} differ\n"
    return true
  when :unified, :context
    ft = info_old.mtime.localtime.strftime("%Y-%m-%d %H:%M:%S.000000000 %z")
    output << "#{char_old} #{info_old.filename}\t#{ft}\n"
    ft = info_new.mtime.localtime.strftime("%Y-%m-%d %H:%M:%S.000000000 %z")
    output << "#{char_new} #{info_new.filename}\t#{ft}\n"
  when :ed
    output = []
  end

  # Loop over hunks. If a hunk overlaps with the last hunk, join them. Otherwise, print
  # out the old one.
  oldhunk = hunk = nil
  diffs.each do |piece|
    hunk = Diff::LCS::Hunk.new(data_old, data_new, piece, lines, file_length_difference)
    file_length_difference = hunk.file_length_difference

    next unless oldhunk
    next if lines.positive? && hunk.merge(oldhunk)

    output << oldhunk.diff(format)
    output << "\n" if format == :unified
  ensure
    oldhunk = hunk
  end

  last = oldhunk.diff(format, true)
  last << "\n" unless last.is_a?(Diff::LCS::Hunk) || last.empty? || last.end_with?("\n")

  output << last

  1
end

#run(args, _input = $stdin, output = $stdout, error = $stderr) ⇒ Object

:nodoc:



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/diff/lcs/ldiff.rb', line 44

def run(args, _input = $stdin, output = $stdout, error = $stderr) # :nodoc:
  args.options do |o|
    o.banner = "Usage: #{File.basename($0)} [options] oldfile newfile"
    o.separator ""
    o.on(
      "-c", "-C", "--context [LINES]", Integer,
      "Displays a context diff with LINES lines", "of context. Default 3 lines."
    ) do |ctx|
      @format = :context
      @lines = ctx || 3
    end
    o.on(
      "-u", "-U", "--unified [LINES]", Integer,
      "Displays a unified diff with LINES lines", "of context. Default 3 lines."
    ) do |ctx|
      @format = :unified
      @lines = ctx || 3
    end
    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|
      @binary = false
    end
    o.on("--binary", "Treats the files as binary.") do |_bin|
      @binary = true
    end
    o.on("-q", "--brief", "Report only whether or not the files", "differ, not the details.") do |_ctx|
      @format = :report
    end
    o.on_tail("--help", "Shows this text.") do
      error << o
      return 0
    end
    o.on_tail("--version", "Shows the version of Diff::LCS.") do
      error << Diff::LCS::Ldiff::BANNER
      return 0
    end
    o.on_tail ""
    o.on_tail 'By default, runs produces an "old-style" diff, with output like UNIX diff.'
    o.parse!
  end

  unless args.size == 2
    error << args.options
    return 127
  end

  # Defaults are for old-style diff
  @format ||= :old
  @lines ||= 0

  file_old, file_new = *ARGV
  diff?(
    InputInfo.new(file_old),
    InputInfo.new(file_new),
    @format,
    output,
    binary: @binary,
    lines: @lines
  ) ? 1 : 0
end