#!/usr/bin/perl use strict; use File::Temp qw/ tempdir /; use File::Path qw/ rmtree /; use File::Compare; sub filter($) { my $_ = shift(); # remove the first char s/^[ +-]//; return $_; } sub break_out_blocks($) { my $dir = shift(); my $block_nr = 0; open FILE, "<", "$dir/full"; open OUT, ">", "$dir/$block_nr"; while () { if ($block_nr && $_ =~ /^}/) { print OUT $_; close(OUT); $block_nr++; open OUT, ">", "$dir/$block_nr"; next; } if ($_ =~ /^{/ || ($_ =~ /^[a-zA-Z]/ && $_ =~ / {$/)) { close(OUT); $block_nr++; open OUT, ">", "$dir/$block_nr"; } print OUT $_; } close(OUT); } sub files_same($$) { my $one = shift(); my $two = shift(); my $size_one = (stat($one))[7]; my $size_two = (stat($two))[7]; if ($size_one != $size_two) { return 0; } return compare($one, $two) == 0; } sub is_block($) { my $file = shift(); open LINE, "<", "$file"; my $line = ; if ($line =~ /^{/ || ($line =~ /^[a-zA-Z]/ && $line =~ / {$/)) { return 1; } return 0; } sub replace_exact_blocks($$) { my $olddir = shift(); my $newdir = shift(); my $i = -1; while (1) { $i++; if (! -e "$olddir/$i") { last; } if (!is_block("$olddir/$i")) { next; } my $j = -1; while (1) { $j++; if (! -e "$newdir/$j") { last; } if (files_same("$olddir/$i", "$newdir/$j")) { open OUT, ">", "$olddir/$i"; print OUT "- MOVED {$i}\n"; close OUT; open OUT, ">", "$newdir/$j"; print OUT "+ MOVED {$j}\n"; close OUT; last; } } } } sub merge_blocks($) { my $dir = shift(); open MERGED, ">", "$dir/merged"; my $i = -1; while (1) { $i++; if (! -e "$dir/$i") { last; } open FILE, "<", "$dir/$i"; while () { print MERGED $_; } close(FILE); } close(MERGED); } sub show_diff($$) { my $olddir = shift(); my $newdir = shift(); open diff, "diff -uw $olddir/merged $newdir/merged |"; while () { print $_; } } my $output; my $inside = 0; my $olddir = tempdir(); my $newdir = tempdir(); open oldfh, ">", "$olddir/full"; open newfh, ">", "$newdir/full"; #recreate an old file and a new file while (<>) { if ($_ =~ /^(---|\+\+\+)/) { next; } if ($_ =~ /^@/) { $inside = 1; } if ($inside && !(($_ =~ /^[- @+]/) || ($_ =~ /^$/))) { $inside = 0; } if (!$inside) { next; } $output = filter($_); if ($_ =~ /^-/) { print oldfh $output; next; } if ($_ =~ /^\+/) { print newfh $output; next; } print oldfh $output; print newfh $output; } close(oldfh); close(newfh); break_out_blocks($olddir); break_out_blocks($newdir); replace_exact_blocks($olddir, $newdir); merge_blocks($olddir); merge_blocks($newdir); show_diff($olddir, $newdir); #print "old = $olddir/ new = $newdir/\n"; rmtree($olddir); rmtree($newdir);