class Origen::Utility::Diff

Diff provides an easy way to diff the contents of two files while optionally ignoring any differences in file comments.

differ = Origen::Utility::Diff.new(:ignore_blank_lines => true, :comment_char => "//")

differ.file_a = "#{Origen.root}/my/file1.v"
differ.file_b = "#{Origen.root}/my/file2.v"

if differ.diffs?
  puts "You've changed something!"
end

Attributes

comment_char[RW]

Set this attribute to the comment char used by the given file and comments will be ignored by the diff. An array of strings can be passed in to mask multiple comment identifiers.

file_a[RW]

Full path to File A, this attribute must be set before calling any diff actions

file_b[RW]

Full path to File B, this attribute must be set before calling any diff actions

ignore_blank_lines[RW]

When true the diff will ignore blank lines, or lines that contain only whitespace

Public Class Methods

new(options = {}) click to toggle source

Create a new diff, attributes can be initialized via the options, or can be set later.

# File lib/origen/utility/diff.rb, line 28
def initialize(options = {})
  @file_a = options[:file_a]
  @file_b = options[:file_b]
  @ignore_blank_lines = options[:ignore_blank_lines]
  @comment_char = options[:comment_char]
  @suspend_string = options[:suspend_string] # permits suspending diff check based on a string
  @resume_string  = options[:resume_string]  # permits resuming diff check based on a string
  @suspend_diff = false
  @resume_diff = false
end

Public Instance Methods

diffs?() click to toggle source

Returns true if there are differences between the two files based on the current configuration

# File lib/origen/utility/diff.rb, line 41
def diffs?
  initialize_counters
  result = false
  content_a = File.readlines(@file_a)
  content_b = File.readlines(@file_b)

  changes = false
  lines_remaining = true

  while lines_remaining
    a = get_next_line_a(content_a) # Get the next vectors
    b = get_next_line_b(content_b)
    if !a && !b       # If both patterns finished
      lines_remaining = false
    elsif !a || !b    # If only 1 pattern finished
      lines_remaining = false
      changes = true unless @suspend_diff # There are extra vectors in one of the patterns
    elsif a != b # If the vectors don't match
      changes = true unless @suspend_diff
    end
    if @resume_diff # resume checking diffs for subsequent lines
      @suspend_diff = false
      @resume_diff = false
    end
  end

  changes
end

Private Instance Methods

get_line(array, ix) click to toggle source

Fetches the line from the given array and does some pre-processing

# File lib/origen/utility/diff.rb, line 97
def get_line(array, ix)
  line = array[ix]
  if line
    set_suspend_diff(line)
    if @comment_char
      # Screen off any inline comments at the end of line
      begin
        [@comment_char].flatten.each do |comchar|
          unless line =~ /^\s*#{comchar}/
            if line =~ /(.*)\s*#{comchar}.*/
              return Regexp.last_match[1].strip
            else
              return line.strip
            end
          end
        end
      # This rescue is a crude way to guard against non-ASCII files that find
      # their way in here
      rescue
        line
      end
    else
      line.strip
    end
  end
end
get_next_line_a(array) click to toggle source
# File lib/origen/utility/diff.rb, line 91
def get_next_line_a(array)
  @a_ix = next_index(array, @a_ix)
  get_line(array, @a_ix)
end
get_next_line_b(array) click to toggle source
# File lib/origen/utility/diff.rb, line 86
def get_next_line_b(array)
  @b_ix = next_index(array, @b_ix)
  get_line(array, @b_ix)
end
initialize_counters() click to toggle source
# File lib/origen/utility/diff.rb, line 156
def initialize_counters
  @a_ix = nil
  @b_ix = nil
end
next_index(array, ix = nil) click to toggle source

Find the next line in the given array and return the new index pointer

# File lib/origen/utility/diff.rb, line 125
def next_index(array, ix = nil)
  ix = ix ? ix + 1 : 0
  matched = false
  while !matched && ix < array.size
    begin
      comment_matched = false
      # Skip comment lines
      if @comment_char
        [@comment_char].flatten.each do |char|
          if array[ix] =~ /^\s*#{char}.*/
            comment_matched = true
          end
        end
      end
      # Skip blank lines
      if comment_matched
        ix += 1
      elsif @ignore_blank_lines && array[ix] =~ /^\s*$/
        ix += 1
      else
        matched = true
      end
    # This rescue is a crude way to guard against non-ASCII files that find
    # there way in here
    rescue
      matched = true
    end
  end
  ix
end
set_suspend_diff(line) click to toggle source
# File lib/origen/utility/diff.rb, line 72
def set_suspend_diff(line)
  if line.valid_encoding?
    if @suspend_string && !@suspend_diff
      if line =~ /#{@suspend_string}/
        @suspend_diff = true
      end
    elsif @resume_string && @suspend_diff
      if line =~ /#{@resume_string}/
        @resume_diff = true
      end
    end
  end
end