SOURCES: patch_minimizer (NEW) - script for making patch look pret...
sparky
sparky at pld-linux.org
Thu Nov 23 04:22:31 CET 2006
Author: sparky Date: Thu Nov 23 03:22:31 2006 GMT
Module: SOURCES Tag: HEAD
---- Log message:
- script for making patch look pretty, and minimizing diff between updated
and in-CVS file
---- Files affected:
SOURCES:
patch_minimizer (NONE -> 1.1) (NEW)
---- Diffs:
================================================================
Index: SOURCES/patch_minimizer
diff -u /dev/null SOURCES/patch_minimizer:1.1
--- /dev/null Thu Nov 23 04:22:31 2006
+++ SOURCES/patch_minimizer Thu Nov 23 04:22:26 2006
@@ -0,0 +1,193 @@
+#!/usr/bin/perl
+#
+# If this script works for you, tell me !
+# If it doesn't, don't bother.
+#
+# Licensed under GPL
+# (c) 2006 PLD Linux Distribution
+# Main author: sparky at pld-linux.org
+#
+use strict;
+use warnings;
+
+my @cvs_cmd = qw(cvs -z9 -q up -p);
+my (@branch, @force_branch);
+my $file;
+
+sub strip_suffix($) {
+ my ($n) = @_;
+ my @r = ($n);
+ push @r, $1 if $n =~ m#^(.*)~$#;
+ push @r, $1 if $n =~ m#^(.*)\.new$#;
+ push @r, $1 if $n =~ m#^(.*)\.orig$#;
+ push @r, $1 if $n =~ m#^(.*)~[^/]*?$#;
+ push @r, $1 if $n =~ m#^(.*)\.[^/]*?$#;
+ push @r, $1 if $n =~ m#^(.*)~[^/]*?~[^/]*?$#;
+ push @r, $1 if $n =~ m#^(.*)\.[^/]*?\.[^/]*?$#;
+ return @r;
+}
+
+sub find_common($$) {
+ my ($f1, $f2) = @_;
+ $f2 =~ s#^.*?/##;
+ return $f2 if $f1 eq "/dev/null";
+ $f1 =~ s#^.*?/##;
+ foreach my $s1 (strip_suffix($f1)) {
+ foreach my $s2 (strip_suffix($f2)) {
+ return $s1 if $s1 eq $s2;
+ }
+ }
+ warn "Matching file name not found, using '$f2'\n";
+ return $f2;
+}
+
+sub find_file_common($$) {
+ my ($l1, $l2) = @_;
+ $l1 =~ /^--- (.*)\t(.*?)$/;
+ my $f = $1;
+ $l2 =~ /^\+\+\+ (.*)\t(.*?)$/;
+ my $ret = find_common($f, $1);
+ #warn "FILES: $f, $1 -> $ret\n";
+ return $ret;
+}
+
+sub get_files($) {
+ my ($file) = @_;
+ open CVS_IN, "-|", (@cvs_cmd, @branch, $file);
+ my @old_files = grep /^(\+\+\+|---) /, <CVS_IN>;
+ close CVS_IN;
+ my @ret;
+
+ my $f1;
+ while ($f1 = shift @old_files) {
+ redo unless ($f1 =~ /^-/ and $old_files[0] =~ /^\+/);
+ my $f2 = shift @old_files;
+ my $common = find_file_common( $f1, $f2 );
+ push @ret, [$common, $f1, $f2];
+ }
+
+ return \@ret;
+}
+
+sub split_patch($) {
+ my ($file) = @_;
+ open F_IN, $file;
+ my @patch = <F_IN>;
+ close F_IN;
+
+ my @split_patch;
+ # = ([comment body] , [+,-,body], [+,-,body],...)
+
+ my @comment;
+ while (my $l = shift @patch) {
+ if ($l =~ /^---/) {
+ unshift @patch, $l;
+ pop @comment while scalar @comment and
+ $comment[$#comment] =~ /^(diff .*|Index: .*|={67}|)$/;
+ last;
+ }
+ push @comment, $l;
+ }
+ $split_patch[0] = [@comment];
+
+ my @chunk = (undef, undef, undef);
+ my $l;
+ while ($l = shift @patch) {
+ if ($l =~ /^--- /) {
+ if (defined $chunk[2]) {
+ push @split_patch, [@chunk];
+ @chunk = (undef, undef, undef);
+ }
+ $chunk[0] = find_file_common($l, $chunk[2])
+ if defined $chunk[2];
+ $chunk[1] = $l;
+ next;
+ }
+ if ($l =~ /^\+\+\+ / and defined $chunk[1]) {
+ $chunk[2] = $l;
+ $chunk[0] = find_file_common($chunk[1], $chunk[2]);
+ next;
+ }
+ next unless defined $chunk[0];
+ if ($l !~ /^[+-@ ]/) {
+ push @split_patch, [@chunk];
+ @chunk = (undef, undef, undef);
+ redo;
+ }
+ push @chunk, $l;
+ }
+ push @split_patch, [@chunk] if defined $chunk[0];
+
+ return \@split_patch
+}
+
+sub sort_chunks($$) {
+ my ($new, $old_files) = @_;
+ my $diff;
+ local $" = "";
+ $diff .= "@{$new->[0]}\n" if scalar @{$new->[0]};
+ shift @{$new};
+ my %new_hash = map { $_->[0] => $_ } @{$new};
+
+ foreach my $oldchunk (@{$old_files}) {
+ my $f = $oldchunk->[0];
+ next unless exists $new_hash{$f};
+ my $newchunk = $new_hash{$f};
+ $diff .= "$oldchunk->[1]";
+ $diff .= "$oldchunk->[2]";
+
+ shift @{$newchunk};
+ shift @{$newchunk};
+ shift @{$newchunk};
+ $diff .= "@{$newchunk}";
+ delete $new_hash{$f};
+ }
+
+ foreach my $f (sort keys %new_hash) {
+ my $newchunk = $new_hash{$f};
+ shift @{$newchunk};
+ $diff .= "@{$newchunk}";
+ }
+ return $diff;
+}
+
+sub clean_diff($) {
+ my ($file) = @_;
+ my $old_files = get_files($file);
+ my $splat = split_patch($file);
+ my $new_diff = sort_chunks($splat, $old_files);
+ rename $file, $file.".bak" or die "Can't rename file\n";
+ open F_OUT, ">", $file or die "Dupa: $!\n";
+ print F_OUT $new_diff;
+ close F_OUT;
+}
+
+sub set_branch($) {
+ open F_IN, "CVS/Entries";
+ my ($b, @ent) = grep {
+ my ($f,$b) = (split m#/#, $_)[1,5]; $f eq $_[0] and $_ = $b
+ } grep m#/#, <F_IN>;
+ close F_IN;
+
+ @branch = ("-r", (substr $b,1)) if defined $b;
+ @branch = qw(-A);
+}
+
+while (my $a = shift @ARGV) {
+ if ($a eq "-r") {
+ @force_branch = ("-r",
+ (shift @ARGV or die "Branch not specified\n")
+ );
+ } elsif ($a eq "-A") {
+ @force_branch = qw(-A);
+ } else {
+ if (scalar @force_branch) {
+ @branch = @force_branch;
+ } else {
+ set_branch($a);
+ }
+ clean_diff($a);
+ }
+}
+
+# vim: ts=4:sw=4
================================================================
More information about the pld-cvs-commit
mailing list