#!/usr/bin/perl use strict; use File::Temp qw/ tempdir /; use File::Path qw/ rmtree /; use File::Compare qw/ compare /; sub print_file($$) { my $prefix = shift; my $file = shift; open FILE, "<", $file; while () { print $prefix . $_; } close FILE; } my $olddir = tempdir(); my $newdir = tempdir(); my @input; while (<>) { push @input, $_; } my ($nr_old, $nr_new); # # Break out the blocks into separate files # my $block; my ($old, $new); foreach (@input) { my $line = $_; if ($line =~ /^(---|\+\+\+)/ || !($line =~ /^[+-]/) || ($old && $line =~ /^[+]/) || ($new && $line =~ /^[-]/)) { $block = ""; $old = 0; $new = 0; next; } if ($line =~ /^[-]{$/) { $block = "{"; $old = 1; next; } if ($line =~ /^[+]{$/) { $block = "{"; $new = 1; next; } $line =~ s/^[+-]//; $block = $block . $line; if ($line =~ /^}$/) { if ($old) { $nr_old++; open OUT, ">", "$olddir/$nr_old"; print OUT "$block"; close OUT; } else { $nr_new++; open OUT, ">", "$newdir/$nr_new"; print OUT "$block"; close OUT; } $block = ""; $old = 0; $new = 0; next; } } # # Find any blocks which are exactly the same # for (my $i = 1; $i <= $nr_old; $i++) { for (my $j = 1; $j <= $nr_new; $j++) { if (compare("$olddir/$i", "$newdir/$j") == 0) { open OUT, ">", "$olddir/$i"; print OUT "- MOVED {$i}\n"; close OUT; open OUT, ">", "$newdir/$j"; print OUT "+ MOVED {$j}\n"; close OUT; } } } # # Find any blocks which are partly the same # for (my $i = 1; $i <= $nr_old; $i++) { for (my $j = 1; $j <= $nr_new; $j++) { my $lines = `cat $olddir/$i | wc -l`; my $after = `diff $olddir/$i $newdir/$j | grep '^<' | wc -l`; my $percent; $lines =~ s/\n//; $after =~ s/\n//; $percent = $after/$lines; if ($percent >= .7) { next; } my $diff = `diff -u $olddir/$i $newdir/$j | tail -n +3`; open OUT, ">", "$olddir/$i"; print OUT "- MOVED {$i}\n"; close OUT; open OUT, ">", "$newdir/$j"; print OUT "+ MOVED {$j} <- begin\n"; print OUT $diff; print OUT "+ MOVED {$j} -> end\n"; close OUT; } } # # Print out the diff... # $nr_old = $nr_new = 0; $old = $new = 0; foreach (@input) { my $line = $_; if ($line =~ /^(---|\+\+\+)/ || !($line =~ /^[+-]/) || ($old && $line =~ /^[+]/) || ($new && $line =~ /^[-]/)) { print $block; print $line; $block = ""; $old = 0; $new = 0; next; } if ($line =~ /^[-]{$/) { print $block; $block = $line; $old = 1; next; } if ($line =~ /^[+]{$/) { print $block; $block = $line; $new = 1; next; } $block = $block . $line; if ($line =~ /^[+-]}$/) { if ($old) { $nr_old++; print_file("-", "$olddir/$nr_old"); } else { $nr_new++; print_file("+", "$newdir/$nr_new"); } $block = ""; $old = 0; $new = 0; next; } } rmtree($olddir); rmtree($newdir);