Procházet zdrojové kódy

dpkg-source: improve the patch parser

* 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.
Raphael Hertzog před 18 roky
rodič
revize
1f7cf2a3a6
3 změnil soubory, kde provedl 50 přidání a 20 odebrání
  1. 13 0
      ChangeLog
  2. 2 0
      debian/changelog
  3. 35 20
      scripts/Dpkg/Source/Patch.pm

+ 13 - 0
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

+ 2 - 0
debian/changelog

@@ -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

+ 35 - 20
scripts/Dpkg/Source/Patch.pm

@@ -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 {