Algorithm-Diff

 view release on metacpan or  search on metacpan

diffnew.pl  view on Meta::CPAN

    $Diff_Type = "UNIFIED";
  } elsif ($opt =~ /^-u$/) {
    $Context_Lines = 3;
    $opt_u = 1;
    $Diff_Type = "UNIFIED";
  } elsif ($opt =~ /^-q$/) {
    $Context_Lines = 0;
    $opt_q = 1;
    $opt_e = 1;
    $Diff_Type = "ED";
  } elsif ($opt =~ /^-i$/) {
    $opt_i = 1;
    $compareRoutineRef = \&compareRoutine;
  } elsif ($opt =~ /^-w$/) {
    $opt_w = 1;
    $compareRoutineRef = \&compareRoutine;
  } else {
    $opt =~ s/^-//;
    bag("Illegal option -- $opt");
  }
}

if ($opt_q and grep($_,($opt_c, $opt_f, $opt_u)) > 1) {
    bag("Combining -q with other options is nonsensical");
}

if (grep($_,($opt_c, $opt_e, $opt_f, $opt_u)) > 1) {
    bag("Only one of -c, -u, -f, -e are allowed");
}

bag($usage) unless @ARGV == 2;

######## DO THE DIFF!
my ($file1, $file2) = @ARGV;

my ($char1, $char2); # string to print before file names
if ($Diff_Type eq "CONTEXT") {
    $char1 = '*' x 3; $char2 = '-' x 3;
} elsif ($Diff_Type eq "UNIFIED") {
    $char1 = '-' x 3; $char2 = '+' x 3;
}

open (F1, $file1) or bag("Couldn't open $file1: $!");
open (F2, $file2) or bag("Couldn't open $file2: $!");
my (@f1, @f2);
chomp(@f1 = <F1>);
close F1;
chomp(@f2 = <F2>);
close F2;

# diff yields lots of pieces, each of which is basically a Block object
my $diffs = diff(\@f1, \@f2, $compareRoutineRef);
exit 0 unless @$diffs;

if ($opt_q and @$diffs) {
    print "Files $file1 and $file2 differ\n";
    exit 1;
}

if ($Diff_Type =~ /UNIFIED|CONTEXT/) {
    my @st = stat($file1);
    my $MTIME = 9;
    print "$char1 $file1\t", scalar localtime($st[$MTIME]), "\n";
    @st = stat($file2);
    print "$char2 $file2\t", scalar localtime($st[$MTIME]), "\n";
}

my ($hunk,$oldhunk);
# Loop over hunks. If a hunk overlaps with the last hunk, join them.
# Otherwise, print out the old one.
foreach my $piece (@$diffs) {
    $hunk = new Hunk ($piece, $Context_Lines);
    next unless $oldhunk; # first time through

    # Don't need to check for overlap if blocks have no context lines
    if ($Context_Lines && $hunk->does_overlap($oldhunk)) {
	$hunk->prepend_hunk($oldhunk);
    } else {
	$oldhunk->output_diff(\@f1, \@f2, $Diff_Type);
    }

} continue {
    $oldhunk = $hunk;
}

# print the last hunk
$oldhunk->output_diff(\@f1, \@f2, $Diff_Type);

# Print hunks backwards if we're doing an ed diff
map {$_->output_ed_diff(\@f1, \@f2, $Diff_Type)} @Ed_Hunks if @Ed_Hunks;

exit 1;
# END MAIN PROGRAM

sub bag {
  my $msg = shift;
  $msg .= "\n";
  warn $msg;
  exit 2;
}

sub compareRoutine {
  my $line = shift;
  $line =~ s/[ \t\r\n]+//g  if ($opt_w);
  $line = uc( $line )   if ($opt_i);
  return $line;
}

########
# Package Hunk. A Hunk is a group of Blocks which overlap because of the
# context surrounding each block. (So if we're not using context, every
# hunk will contain one block.)
{
package Hunk;

sub new {
# Arg1 is output from &LCS::diff (which corresponds to one Block)
# Arg2 is the number of items (lines, e.g.,) of context around each block
#
# This subroutine changes $File_Length_Difference
#
# Fields in a Hunk:
# blocks      - a list of Block objects
# start       - index in file 1 where first block of the hunk starts



( run in 1.616 second using v1.01-cache-2.11-cpan-e1769b4cff6 )