]> err.no Git - dpkg/commitdiff
dpkg-source: improve the patch parser
authorRaphael Hertzog <hertzog@debian.org>
Wed, 4 Jun 2008 19:26:47 +0000 (21:26 +0200)
committerRaphael Hertzog <hertzog@debian.org>
Sat, 7 Jun 2008 10:51:42 +0000 (12:51 +0200)
* scripts/Dpkg/Source/Patch.pm (analyze): Enhance function to
parse correctly many more patches that are accepted by the patch
utility itself:
- ignore/strip carriage return of patches with Windows end of lines
- accept empty lines as contextual lines (instead of the expected " ")
- accept spaces as separator between filename and timestamp if
  there's no tab
- accept a name that differs on the +++ line if the name in --- is
  correct, and use the name in +++ if this one exists while the one
  on --- doesn't.

ChangeLog
debian/changelog
scripts/Dpkg/Source/Patch.pm

index cb2d2898213ff48f5add80d34b6ff814cb254201..4286dfc7fb7b34180d2bc160baa38706a6353022 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2008-06-04  Raphael Hertzog  <hertzog@debian.org>
+
+       * scripts/Dpkg/Source/Patch.pm (analyze): Enhance function to
+       parse correctly many more patches that are accepted by the patch
+       utility itself:
+       - ignore/strip carriage return of patches with Windows end of lines
+       - accept empty lines as contextual lines (instead of the expected " ")
+       - accept spaces as separator between filename and timestamp if
+         there's no tab
+       - accept a name that differs on the +++ line if the name in --- is
+         correct, and use the name in +++ if this one exists while the one
+         on --- doesn't.
+
 2008-05-28  Raphael Hertzog  <hertzog@debian.org>
 
        * scripts/Dpkg/Source/Package.pm (extract): If we extract a
index 9111662e8226dad31378cc6bb950551d6579b39b..84e5a82d12ff57f267439d518199e92113ec664c 100644 (file)
@@ -11,6 +11,8 @@ dpkg (1.14.20) UNRELEASED; urgency=low
     as default name for the automatic patch created by the format "3.0
     (quilt)". This ensures a saner cohabitation with patch systems that
     apply all of debian/patches/*.{diff,patch}.
+  * Improve patch parser to accept more patches that are accepted by patch
+    itself.
 
   [ Helge Kreutzmann ]
   * Fix a typo in dselect.1
index 26cbe2a629da4087a3449d961c94e86ffa6a6c75..52c35e01a160f56765c477aa140f10fb0d77e0a3 100644 (file)
@@ -279,21 +279,38 @@ sub analyze {
     my %dirtocreate;
     my $diff_count = 0;
 
-    $_ = <$diff_handle>;
+    sub getline {
+        my $handle = shift;
+        my $line = <$handle>;
+        if (defined $line) {
+            # Strip end-of-line chars
+            chomp($line);
+            $line =~ s/\r$//;
+        }
+        return $line;
+    }
+    sub strip_ts { # Strip timestamp
+        my $header = shift;
+        # Tab is the official separator, it's always used when
+        # filename contain spaces. Try it first, otherwise strip on space
+        # if there's no tab
+        $header =~ s/\s.*// unless ($header =~ s/\t.*//);
+        return $header;
+    }
+    $_ = getline($diff_handle);
 
   HUNK:
     while (defined($_) || not eof($diff_handle)) {
        # skip comments leading up to patch (if any)
        until (/^--- /) {
-           last HUNK if not defined($_ = <$diff_handle>);
+           last HUNK if not defined($_ = getline($diff_handle));
        }
-       chomp;
        $diff_count++;
        # read file header (---/+++ pair)
        unless(s/^--- //) {
            error(_g("expected ^--- in line %d of diff `%s'"), $., $diff);
        }
-       s/\t.*//; # Strip any timestamp at the end
+        $_ = strip_ts($_);
        unless ($_ eq '/dev/null' or s{^(\./)?[^/]+/}{$destdir/}) {
            error(_g("diff `%s' patches file with no subdirectory"), $diff);
        }
@@ -302,23 +319,25 @@ sub analyze {
        }
        my $fn = $_;
 
-       unless (defined($_= <$diff_handle>) and chomp) {
+       unless (defined($_ = getline($diff_handle))) {
            error(_g("diff `%s' finishes in middle of ---/+++ (line %d)"), $diff, $.);
        }
-       s/\t.*//; # Strip any timestamp at the end
-       unless (s/^\+\+\+ // and ($_ eq '/dev/null' or s!^(\./)?[^/]+/!!)) {
-           error(_g("line after --- isn't as expected in diff `%s' (line %d)"),
-                 $diff, $.);
+       unless (s/^\+\+\+ //) {
+           error(_g("line after --- isn't as expected in diff `%s' (line %d)"), $diff, $.);
+       }
+        $_ = strip_ts($_);
+       unless (($_ eq '/dev/null') or s!^(\./)?[^/]+/!!) {
+           error(_g("line after --- isn't as expected in diff `%s' (line %d)"), $diff, $.);
        }
 
        if ($fn eq '/dev/null') {
            error(_g("original and modified files are /dev/null in diff `%s' (line %d)"),
                  $diff, $.) if $_ eq '/dev/null';
            $fn = "$destdir/$_";
-       } else {
-           unless ($_ eq '/dev/null' or $_ eq substr($fn, length($destdir) + 1)) {
-               error(_g("line after --- isn't as expected in diff `%s' (line %d)"),
-                     $diff, $.);
+       } elsif ($_ ne '/dev/null') {
+            $fn = "$destdir/$_" if ((not -e $fn) and -e "$destdir/$_");
+           unless ($_ eq substr($fn, length($destdir) + 1)) {
+               error(_g("line after --- isn't as expected in diff `%s' (line %d)"), $diff, $.);
            }
        }
 
@@ -337,23 +356,19 @@ sub analyze {
 
        # read hunks
        my $hunk = 0;
-       while (defined($_ = <$diff_handle>)) {
+       while (defined($_ = getline($diff_handle))) {
            # read hunk header (@@)
-           chomp;
            next if /^\\ No newline/;
            last unless (/^@@ -\d+(,(\d+))? \+\d+(,(\d+))? @\@( .*)?$/);
            my ($olines, $nlines) = ($1 ? $2 : 1, $3 ? $4 : 1);
            # read hunk
            while ($olines || $nlines) {
-               unless (defined($_ = <$diff_handle>)) {
+               unless (defined($_ = getline($diff_handle))) {
                    error(_g("unexpected end of diff `%s'"), $diff);
                }
-               unless (chomp) {
-                   error(_g("diff `%s' is missing trailing newline"), $diff);
-               }
                next if /^\\ No newline/;
                # Check stats
-               if    (/^ /)  { --$olines; --$nlines; }
+               if    (/^ / || /^$/)  { --$olines; --$nlines; }
                elsif (/^-/)  { --$olines; }
                elsif (/^\+/) { --$nlines; }
                else {