[netfilter-cvslog] r4020 - in trunk/patch-o-matic-ng: . patch2pom
laforge at netfilter.org
laforge at netfilter.org
Mon Jun 27 11:10:24 CEST 2005
Author: laforge at netfilter.org
Date: 2005-06-27 11:10:23 +0200 (Mon, 27 Jun 2005)
New Revision: 4020
Added:
trunk/patch-o-matic-ng/patch2pom/
trunk/patch-o-matic-ng/patch2pom/PatchChunk.pm
trunk/patch-o-matic-ng/patch2pom/PatchFile.pm
trunk/patch-o-matic-ng/patch2pom/README
trunk/patch-o-matic-ng/patch2pom/patch2pom
Log:
add the new patch2pom tool by Jonas Berlin
Added: trunk/patch-o-matic-ng/patch2pom/PatchChunk.pm
===================================================================
--- trunk/patch-o-matic-ng/patch2pom/PatchChunk.pm 2005-06-27 09:10:08 UTC (rev 4019)
+++ trunk/patch-o-matic-ng/patch2pom/PatchChunk.pm 2005-06-27 09:10:23 UTC (rev 4020)
@@ -0,0 +1,192 @@
+#!/usr/bin/perl -w
+#
+# PatchChunk.pm helper package for the patch2pom script
+# (C) 2005 by Jonas Berlin <xkr47 at outerspace.dyndns.org>
+#
+# This code is subject to the GNU GPLv2
+#
+# This package represents a chunk of a diff -Nru style file, where a
+# chunk means a block starting with "@@ -1,2 +3,4 @@" and the
+# lines following that belong to that block.
+
+package PatchChunk;
+
+use strict;
+
+our $TYPE_NONE = 0;
+our $TYPE_BOTH = 1;
+our $TYPE_NEW = 2;
+our $TYPE_OLD = 3;
+
+my $NONEWLINE_STR = "\\ No newline at end of file\n";
+
+sub typename {
+ my $this = shift;
+ my $type = shift;
+ if($type == $TYPE_NONE) {
+ return "NONE";
+ } elsif($type == $TYPE_BOTH) {
+ return "BOTH";
+ } elsif($type == $TYPE_NEW) {
+ return "NEW";
+ } elsif($type == $TYPE_OLD) {
+ return "OLD";
+ } else {
+ return "<INVALID $type>";
+ }
+}
+
+
+sub _typechar {
+ my $type = shift;
+ if($type == $TYPE_NONE) {
+ return "";
+ } elsif($type == $TYPE_BOTH) {
+ return " ";
+ } elsif($type == $TYPE_NEW) {
+ return "+";
+ } elsif($type == $TYPE_OLD) {
+ return "-";
+ } else {
+ return "INVALIDTYPE $type ";
+ }
+}
+
+sub _warnonce {
+ my $this = shift;
+ my $warning = shift;
+
+ unless($this->{_warned}->{$warning}) {
+ $this->{_warned}->{$warning} = 1;
+ print STDERR "\033[36;1;40mWarning: $warning\033[m\n";
+ }
+}
+
+sub new {
+ my $class = shift;
+ $class = ref($class) || $class;
+ my $this = {}; # $class->SUPER::new();
+ bless $this, $class;
+
+ my $line = shift;
+ return undef unless($line =~ /^\@\@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? \@\@.*$/);
+
+ $this->{oldstart} = $1;
+ $this->{oldlen} = defined($2) ? $2 : 1;
+ $this->{newstart} = $3;
+ $this->{newlen} = defined($4) ? $4 : 1;
+
+ $this->{_oldleft} = $this->{oldlen};
+ $this->{_newleft} = $this->{newlen};
+
+ $this->{_state} = $TYPE_NONE;
+ $this->{nonewline} = 0;
+ $this->{finished} = 0;
+
+ $this->{_warned} = {};
+
+ return $this;
+}
+
+sub _finish_minichunk {
+ my $this = shift;
+
+ if($this->{_state} != $TYPE_NONE) {
+ push @{$this->{minichunks}}, $this->{lines};
+ push @{$this->{minichunktypes}}, $this->{_state};
+ }
+}
+
+# to be used at EOF or unidentified data
+sub finish {
+ my $this = shift;
+ return if($this->{finished});
+ $this->{finished} = 1;
+ $this->_finish_minichunk();
+ $this->_warnonce("diff counters broken\n") if($this->{_oldleft} != 0 || $this->{_newleft} != 0);
+}
+
+sub add_line {
+ my $this = shift;
+ my $line = shift;
+
+ if($this->{finished}) {
+ return 0;
+ }
+
+ my $newstate;
+ if($line =~ /^ /) {
+ $newstate = $TYPE_BOTH;
+ } elsif($line =~ /^\+/) {
+ $newstate = $TYPE_NEW;
+ } elsif($line =~ /^-/) {
+ $newstate = $TYPE_OLD;
+ } elsif($line eq $NONEWLINE_STR) {
+ $this->{nonewline} = 1;
+ $this->finish();
+ return 1;
+ } else {
+ $this->finish();
+ return 0;
+ }
+
+ if($newstate != $TYPE_NEW) {
+ if($this->{_oldleft} <= 0) {
+ $this->{oldlen}++;
+ $this->_warnonce("diff counters broken\n");
+ } else {
+ $this->{_oldleft}--;
+ }
+ }
+
+ if($newstate != $TYPE_OLD) {
+ if($this->{_newleft} <= 0) {
+ $this->{newlen}++;
+ $this->_warnonce("diff counters broken\n");
+ } else {
+ $this->{_newleft}--;
+ }
+ }
+
+ if($newstate != $this->{_state}) {
+ $this->_finish_minichunk();
+ $this->{lines} = [];
+ $this->{_state} = $newstate;
+ }
+
+ push @{$this->{lines}}, substr($line, 1);
+
+ return 1;
+}
+
+sub adjust_position {
+ my $this = shift;
+ my ($oldoff, $newoff) = @_;
+
+ $this->{oldstart} += $oldoff;
+ $this->{newstart} += $newoff;
+}
+
+sub format_minichunk {
+ my $this = shift;
+ my $idx = shift;
+
+ return "<INVALID IDX $idx>" if($idx < 0 || $idx >= scalar(@{$this->{minichunks}}));
+ my $char = _typechar($this->{minichunktypes}->[$idx]);
+ return $char.join($char,@{$this->{minichunks}->[$idx]});
+}
+
+sub format {
+ my $this = shift;
+ my $str;
+ $str = "@@ -".$this->{oldstart}.($this->{oldlen} != 1 ? ",".$this->{oldlen} : "");
+ $str .= " +".$this->{newstart}.($this->{newlen} != 1 ? ",".$this->{newlen} : "");
+ $str .= " @@\n";
+ for(my $i=0; $i<scalar(@{$this->{minichunks}}); ++$i) {
+ $str .= $this->format_minichunk($i);
+ }
+ $str .= $NONEWLINE_STR if($this->{nonewline});
+ return $str;
+}
+
+1
Added: trunk/patch-o-matic-ng/patch2pom/PatchFile.pm
===================================================================
--- trunk/patch-o-matic-ng/patch2pom/PatchFile.pm 2005-06-27 09:10:08 UTC (rev 4019)
+++ trunk/patch-o-matic-ng/patch2pom/PatchFile.pm 2005-06-27 09:10:23 UTC (rev 4020)
@@ -0,0 +1,133 @@
+#!/usr/bin/perl -w
+#
+# PatchFile.pm helper package for the patch2pom script
+# (C) 2005 by Jonas Berlin <xkr47 at outerspace.dyndns.org>
+#
+# This code is subject to the GNU GPLv2
+#
+# This package represents a single file from a diff -Nru style patch.
+
+package PatchFile;
+
+use strict;
+
+my $STATE_DIFF_OR_MINUS = 0;
+my $STATE_MINUS = 1;
+my $STATE_PLUS = 2;
+my $STATE_CHUNKS = 10;
+
+sub new {
+ my $class = shift;
+ $class = ref($class) || $class;
+ my $this = {}; # $class->SUPER::new();
+ bless $this, $class;
+
+ $this->{_state} = $STATE_DIFF_OR_MINUS;
+ $this->{finished} = 0;
+ $this->{success} = 0;
+ $this->{started} = 0;
+ $this->{chunks} = [];
+
+ return $this;
+}
+
+sub _parse_fileline {
+ my $line = $_[0];
+
+ unless($line =~ /^...\s([^\t]+)\t(.*)/) {
+ print STDERR "\033[36;1;40mInvalid file line:\n$line\033[m\n";
+ exit(10);
+ }
+
+ return { file => $1, date => $2 };
+}
+
+sub _finish_chunk {
+ my $this = shift;
+
+ return unless(defined($this->{_chunk}));
+
+ $this->{_chunk}->finish();
+ push @{$this->{chunks}}, $this->{_chunk};
+ if($this->{_chunk}->{nonewline}) {
+ $this->{finished} = 1;
+ $this->{success} = 1;
+ }
+ $this->{_chunk} = undef;
+}
+
+# call at eof or next /^diff /
+sub finish {
+ my $this = shift;
+
+ $this->_finish_chunk();
+ $this->{finished} = 1;
+ $this->{success} = scalar(@{$this->{chunks}}) > 0;
+}
+
+sub format {
+ my $this = shift;
+ my $str = $this->{diffline};
+ $str .= "--- ".$this->{old}->{file}."\t".$this->{old}->{date}."\n";
+ $str .= "+++ ".$this->{new}->{file}."\t".$this->{new}->{date}."\n";
+ foreach my $chunk (@{$this->{chunks}}) {
+ $str .= $chunk->format();
+ }
+ return $str;
+}
+
+sub add_line {
+ my $this = shift;
+ my $line = shift;
+
+ return 0 if($this->{finished});
+
+ if(/^diff /) {
+ unless($this->{_state} == $STATE_DIFF_OR_MINUS) {
+ $this->finish();
+ return 0;
+ }
+ $this->{diffline} = $line;
+ $this->{_state} = $STATE_MINUS;
+ $this->{started} = 1;
+
+ } elsif(($this->{_state} == $STATE_DIFF_OR_MINUS || $this->{_state} == $STATE_MINUS) && /^--- /) {
+ $this->{old} = _parse_fileline($line);
+ $this->{_state} = $STATE_PLUS;
+ $this->{started} = 1;
+
+ } elsif($this->{_state} == $STATE_PLUS && /^\+\+\+ /) {
+ $this->{new} = _parse_fileline($line);
+ $this->{_state} = $STATE_CHUNKS;
+
+ } elsif($this->{_state} == $STATE_CHUNKS) {
+ my $isnewchunk = $line =~ /^@@/;
+
+ my $ret = 1;
+
+ if(defined($this->{_chunk})) {
+ if($isnewchunk) {
+ $this->{_chunk}->finish();
+ } else {
+ $ret = $this->{_chunk}->add_line($line);
+ }
+
+ if($this->{_chunk}->{finished}) {
+ $this->_finish_chunk();
+ }
+ }
+
+ if($isnewchunk && !$this->{finished}) {
+ $this->{_chunk} = new PatchChunk($_);
+ $ret = 0 unless(defined($this->{_chunk}));
+ }
+
+ if(!$ret) {
+ $this->finish();
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ return 1;
+}
Added: trunk/patch-o-matic-ng/patch2pom/README
===================================================================
--- trunk/patch-o-matic-ng/patch2pom/README 2005-06-27 09:10:08 UTC (rev 4019)
+++ trunk/patch-o-matic-ng/patch2pom/README 2005-06-27 09:10:23 UTC (rev 4020)
@@ -0,0 +1,3 @@
+
+Please see top of patch2pom script for instructions.
+
Added: trunk/patch-o-matic-ng/patch2pom/patch2pom
===================================================================
--- trunk/patch-o-matic-ng/patch2pom/patch2pom 2005-06-27 09:10:08 UTC (rev 4019)
+++ trunk/patch-o-matic-ng/patch2pom/patch2pom 2005-06-27 09:10:23 UTC (rev 4020)
@@ -0,0 +1,350 @@
+#!/usr/bin/perl -w
+#
+# patch2pom, helper script for the patch-o-matic 'next generation' package
+# (C) 2005 by Jonas Berlin <xkr47 at outerspace.dyndns.org>
+#
+# This code is subject to the GNU GPLv2
+#
+# The separate PatchChunk.pm and PatchFile.pm files are required for
+# proper operation.
+#
+# This script takes a diff -Nru on input and converts it to
+# patch-o-matic-ng format by extracting new files from the diff as
+# separate files and making trivial updates to known file types using
+# "ladd" files. Any changes not matching the above criteria are passed
+# forward as a normal diff.
+#
+# If run as
+#
+# ./patch2pom patch-o-matic/foobar/linux-2.6 < mypatch.patch
+#
+# .. then the command will create a directory structure below
+# patch-o-matic/foobar/linux-2.6/ with new files and/or .ladd files
+# when possible. Any parts of the diff that cannot be applied as new
+# files or .ladd files are passed forward to a patch file called
+# patch-o-matic/foobar/linux-2.6.patch. Example output directory
+# structure:
+#
+# pom-ng/foobar/linux-2.6/net/ipv4/netfilter/ipt_foobar.c
+# pom-ng/foobar/linux-2.6/net/ipv4/netfilter/Kconfig.ladd
+# pom-ng/foobar/linux-2.6/net/ipv4/netfilter/Makefile.ladd
+# pom-ng/foobar/linux-2.6/include/linux/netfilter_ipv4/ip_foo.h.ladd
+# pom-ng/foobar/linux-2.6/include/linux/netfilter_ipv4/ip_foo.h.ladd_2
+# ...
+# pom-ng/foobar/linux-2.6.patch
+#
+# Tip: when creating new versions of already existing modules in
+# pom-ng, it might be convenient to give a different destination
+# and then compare the results.
+#
+# Note: If files already exist in the given destination directory,
+# they will not be removed, so before re-running the same
+# command, you probably want to erase the old one first. The
+# same goes for the patch optionally created by this script.
+
+BEGIN {
+ my $scripthome = $0;
+ $scripthome =~ s![^/]+$!!;
+ push @INC, $scripthome;
+}
+
+use strict;
+use File::Path;
+use Date::Parse;
+
+use PatchChunk;
+use PatchFile;
+
+my $pombase = shift @ARGV;
+
+unless(defined($pombase)) {
+
+ print STDERR 'usage: '.$0.' pomdir-base
+The command expects a diff -Nru style diff on standard input.
+
+Examples:
+
+diff -Nru orig-linux linux | '.$0.' patch-o-matic-ng/foobar/linux-2.6
+
+ This will create files in patch-o-matic-ng/foobar/linux-2.6/ and/or
+ a patch file patch-o-matic-ng/foobar/linux-2.6.patch
+
+diff -Nru orig-iptables iptables | '.$0.' patch-o-matic-ng/foobar/iptables
+
+ Creates files in .../iptables and/or patch file .../iptables.patch
+';
+ exit(1);
+}
+
+$pombase =~ s!/+$!!;
+
+sub create_file {
+ my ($file, $date, @content) = @_;
+
+ $file = $pombase.'/'.$file;
+
+ my $dir = $file;
+ $dir =~ s![^/]+$!!;
+
+ mkpath($dir);
+
+ open NEWFILE, '>', $file;
+ print NEWFILE @content;
+ close NEWFILE;
+
+ my $time = str2time($date);
+
+ utime($time, $time, $file);
+}
+
+my $patch_file_opened = 0;
+
+sub pprint {
+ unless($patch_file_opened) {
+ my $pomparent = $pombase;
+ $pomparent =~ s![^/]+$!!;
+ mkpath($pomparent) if(length($pomparent));
+
+ $patch_file_opened = 1 if(open PATCHFILE, '>', $pombase.'.patch');
+ }
+ print PATCHFILE @_;
+}
+
+# ensure that a FilePatch object only contains alternating "common" and "new" lines
+sub check_adds_only {
+ my $file = shift;
+
+ foreach my $chunk (@{$file->{chunks}}) {
+ my $state = 0;
+ foreach my $chunktype (@{$chunk->{minichunktypes}}) {
+ if($chunktype != ($state ? $PatchChunk::TYPE_NEW : $PatchChunk::TYPE_BOTH)) {
+ return 0;
+ }
+ $state = !$state;
+ }
+ }
+
+ return 1;
+}
+
+my %ladd_idx;
+
+
+sub ladd_filename {
+ my $filename = shift;
+
+ $ladd_idx{$filename} = 1 unless(defined($ladd_idx{$filename}));
+ my $ladd_filename = $filename.".ladd";
+ $ladd_filename .= "_".$ladd_idx{$filename} if($ladd_idx{$filename} > 1);
+ $ladd_idx{$filename}++;
+
+ return $ladd_filename;
+}
+
+###### the core logic for creating new and .ladd files and .patch file
+sub handle_file {
+ my $file = shift;
+
+ my $filename = $file->{new}->{file};
+ $filename =~ s!^[^/]+/!!;
+
+ if(scalar(@{$file->{chunks}}) == 1 &&
+ $file->{chunks}->[0]->{oldstart} == 0 &&
+ $file->{chunks}->[0]->{oldlen} == 0 &&
+ scalar(@{$file->{chunks}->[0]->{minichunks}}) == 1 &&
+ $file->{chunks}->[0]->{minichunktypes}->[0] == $PatchChunk::TYPE_NEW) {
+
+ ### It's a totally new file
+
+ my @content = @{$file->{chunks}->[0]->{minichunks}->[0]};
+ chomp $content[$#content] if($file->{chunks}->[0]->{nonewline});
+
+ create_file($filename, $file->{new}->{date}, @content);
+
+ } elsif($filename =~ m!/Kconfig$!) {
+
+ ### 2.6 Kconfig
+
+ my $success = 0;
+
+ if(check_adds_only($file)) {
+
+ $success = 1;
+ kconfig_bail:
+ foreach my $chunk (@{$file->{chunks}}) {
+ for(my $i=0; $i<scalar(@{$chunk->{minichunks}})-1; $i+=2) {
+
+ my @lines = @{$chunk->{minichunks}->[$i+1]};
+ my $state = 0;
+ for($i=0; $i<=$#lines; ++$i) {
+ if($state == 0 && $lines[$i] =~ /^$/) {
+ # do nothing
+ } elsif(($state == 0 || $state == 3) && $lines[$i] =~ /^config \S+$/) {
+ $state = 1;
+ } elsif($state == 0) {
+ $success = 0; last kconfig_bail;
+
+ } elsif($state >= 1 && $state <= 2) {
+ if($lines[$i] =~ /^\t\S/) {
+ $state++;
+ } else {
+ $success = 0; last kconfig_bail;
+ }
+ } elsif($state == 3) {
+ unless($lines[$i] =~ /^\t|^$/) {
+ $success = 0; last kconfig_bail;
+ }
+ } else {
+ die "Internal bug, please report\n";
+ }
+ }
+
+ ##TODO## maybe check that post-context matches /^\S/
+
+ unless($state == 3) {
+ $success = 0; last kconfig_bail;
+ }
+ }
+ }
+
+ if($success) {
+ foreach my $chunk (@{$file->{chunks}}) {
+ for(my $i=0; $i<scalar(@{$chunk->{minichunks}})-1; $i+=2) {
+
+ my $ladd_filename = ladd_filename($filename);
+
+ my @lines = @{$chunk->{minichunks}->[$i+1]};
+
+ while($lines[$#lines] =~ /^$/) {
+ delete $lines[$#lines];
+ }
+
+ create_file($ladd_filename, $file->{new}->{date}, @lines);
+ }
+ }
+ }
+ }
+
+ pprint $file->format() unless($success);
+
+ } elsif($filename =~ m!/Documentation/Configure\.help$!) {
+
+ ### 2.4 Configure.help
+
+ ##TODO## implement algorithm if somebody still wants this
+
+ pprint $file->format();
+
+ } elsif($filename =~ m!/(?:Makefile|Config\.in)$!) {
+
+ ### Makefile
+ ### 2.4 Config.in
+
+ if(check_adds_only($file)) {
+ foreach my $chunk (@{$file->{chunks}}) {
+ for(my $i=0; $i<scalar(@{$chunk->{minichunks}})-1; $i+=2) {
+
+ # pick last line of preceding context lines
+ my $context_minichunk = $chunk->{minichunks}->[$i];
+ my $context = @$context_minichunk[scalar(@{$context_minichunk})-1];
+
+ my $ladd_filename = ladd_filename($filename);
+
+ create_file($ladd_filename, $file->{new}->{date}, $context, @{$chunk->{minichunks}->[$i+1]});
+ }
+ }
+
+ } else {
+ pprint $file->format();
+ }
+
+ } elsif($filename =~ m![^/]\.[ch]$!) {
+
+ ### *.c
+ ### *.h
+
+ my $success = 0;
+
+ if(check_adds_only($file)) {
+ $success = 1;
+
+ source_bail:
+ foreach my $chunk (@{$file->{chunks}}) {
+ for(my $i=0; $i<scalar(@{$chunk->{minichunks}})-1; $i+=2) {
+
+ # pick last line of preceding context lines
+ my $context_minichunk = $chunk->{minichunks}->[$i];
+ my $context = @$context_minichunk[scalar(@{$context_minichunk})-1];
+
+ # if "here" mentioned in comment, we accept
+ unless($context =~ m!/\*(?:\*[^/]|[^*])+\shere(?:\*[^/]|[^*])*\*/!) {
+ $success = 0; last source_bail;
+ }
+ }
+ }
+
+ ##TODO## we could accept partial .ladd conversion and modify the patch
+
+ if($success) {
+ foreach my $chunk (@{$file->{chunks}}) {
+ for(my $i=0; $i<scalar(@{$chunk->{minichunks}})-1; $i+=2) {
+
+ # pick last line of preceding context lines
+ my $context_minichunk = $chunk->{minichunks}->[$i];
+ my $context = @$context_minichunk[scalar(@{$context_minichunk})-1];
+
+ my $ladd_filename = ladd_filename($filename);
+
+ create_file($ladd_filename, $file->{new}->{date}, $context, @{$chunk->{minichunks}->[$i+1]});
+ }
+ }
+ }
+ }
+
+ pprint $file->format() unless($success);
+
+ } else {
+
+ ### default
+
+ pprint $file->format();
+ }
+}
+
+############# main parse loop
+
+my $file = new PatchFile();
+
+while(<>) {
+ while(!$file->add_line($_)) {
+ unless($file->{started}) {
+ if(/^Files .* differ$/) {
+ print STDERR "Ignoring: $_";
+ } elsif(/^Only in/) {
+ print STDERR "ABORTING: It seems you forgot the -N flag from your diff command.. I got: $_";
+ exit(1);
+ } elsif(/^Common /) {
+ print STDERR "ABORTING: It seems you forgot the -r flag from your diff command.. I got: $_";
+ exit(1);
+ } elsif(/^[\d><]/) {
+ print STDERR "ABORTING: It seems you forgot the -u flag from your diff command.. I got: $_";
+ exit(1);
+ } else {
+ print;
+ }
+ last;
+ }
+
+ if($file->{success}) {
+ handle_file($file);
+ }
+
+ $file = new PatchFile();
+ }
+}
+
+$file->finish();
+
+handle_file($file) if($file->{success});
+
+close PATCHFILE if($patch_file_opened);
Property changes on: trunk/patch-o-matic-ng/patch2pom/patch2pom
___________________________________________________________________
Name: svn:executable
+ *
More information about the netfilter-cvslog
mailing list