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