Algorithm-Diff
view release on metacpan or search on metacpan
$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 )