retitle 28977 [PATCH] libgtkada_0.1a-6(frozen): source cannot be unpacked
retitle 28614 [PATCH] dpkg-dev: Interprets libgtkada_0.1a-6 diff file 
incorrectly
retitle 28979 [PATCH] abacus_0.9.13-1(frozen): Source cannot be unpacked
stop

Hi Ian, Wichert, or whoever feels responsible for dpkg-source...

I finally decided to fix the long-stand "three dashes" bug in
dpkg-source [1]. I did this by completely rewriting the code looking
through the patch and checking it. The new code doesn't follow a
check-if-everything-looks-ok principle, but really parses the diff.

Because I already was at dpkg-source, I also fixed two minor things:

 - A (harmless) typo in an error message.

 - Call patch with -g0, so that it in no case calls rcs or sccs to
   check out things, which doesn't work (#28979)

If anyone of you agrees, I also can make a NMU of dpkg including this
patch. But I'd prefer if somebody else makes a new version, probably
including other fixes. Just don't forget this patch then :-)

Roman

 [1]: see the bugs reports for a description. Briefly: If the diff
changes a line that starts with --, a line with "---" at the start
will be in the diff. dpkg-source misinterpreted this as the start of a
new file and probably complained that it's in a wrong dir.

------------------------------------------------------------------------------
--- dpkg-source~        Fri Aug  6 15:07:50 1999
+++ dpkg-source Fri Aug  6 16:40:46 1999
@@ -453,7 +453,7 @@
 
     $sourcestyle =~ y/X/p/;
     $sourcestyle =~ m/[pun]/ ||
-        &usageerr("source handling style -s$sourcestyle not allowed with -b");
+        &usageerr("source handling style -s$sourcestyle not allowed with -x");
 
     @ARGV==1 || &usageerr("-x needs exactly one argument, the .dsc");
     $dsc= shift(@ARGV);
@@ -509,31 +509,48 @@
             
         &forkgzipread("$dscdir/$difffile");
         $/="\n";
-        while (<GZIP>) {
-            s/\n$// || &error("diff is missing trailing newline");
-            if (/^--- /) {
-                $fn= $';
-                substr($fn,0,length($expectprefix)+1) eq "$expectprefix/" ||
-                    &error("diff patches file ($fn) not in expected 
subdirectory");
-                $fn =~ m/\.dpkg-orig$/ &&
-                    &error("diff patches file with name ending .dpkg-orig");
-                $dirname= $fn;
-                if ($dirname =~ s,/[^/]+$,, && 
!defined($dirincluded{$dirname})) {
-                   $dirtocreate{$dirname} = 1;
+       $_ = <GZIP>;
+       do {
+           # read file header (---/+++ pair)
+           s/\n$// or &error("diff is missing trailing newline");
+           /^--- / or &error("expected ^--- in line $. of diff");
+           $fn= $';
+           substr($fn,0,length($expectprefix)+1) eq "$expectprefix/" ||
+               &error("diff patches file ($fn) not in expected subdirectory");
+           $fn =~ m/\.dpkg-orig$/ &&
+               &error("diff patches file with name ending .dpkg-orig");
+           $dirname= $fn;
+           if ($dirname =~ s,/[^/]+$,, && !defined($dirincluded{$dirname})) {
+               $dirtocreate{$dirname} = 1;
+           }
+           defined($notfileobject{$fn}) &&
+               &error("diff patches something which is not a plain file");
+           $_= <GZIP>; s/\n$// ||
+               &error("diff finishes in middle of ---/+++ (line $.)");
+           $_ eq '+++ '.$newdirectory.substr($fn,length($expectprefix)) ||
+               &error("line after --- for file $fn isn't as expected");
+           $filepatched{$fn}++ && &error("diff patches file $fn twice");
+           # read hunks
+           my $hunk = 0;
+           while (($_ = <GZIP>) && !/^--- /) {
+               # read hunk header (@@)
+               s/\n$// or &error("diff is missing trailing newline");
+               /^@@ -\d+(,(\d+))? \+\d+(,(\d+))? @[EMAIL PROTECTED]/ or
+                   &error("Expected ^@@ in line $. of diff");
+               my ($olines, $nlines) = ($1 ? $2 : 1, $3 ? $4 : 1);
+               ++$hunk;
+               # read hunk
+               while ($olines || $nlines) {
+                   $_ = <GZIP> or &error("unexpected end of diff");
+                   s/\n$// or &error("diff is missing trailing newline");
+                   if (/^ /) { --$olines; --$nlines; }
+                   elsif (/^-/) { --$olines; }
+                   elsif (/^\+/) { --$nlines; }
+                   else { &error("expected [ +-] at start of line $. of 
diff"); }
                }
-                defined($notfileobject{$fn}) &&
-                    &error("diff patches something which is not a plain file");
-                $_= <GZIP>; s/\n$// ||
-                    &error("diff finishes in middle of ---/+++ (line $.)");
-                $_ eq '+++ '.$newdirectory.substr($fn,length($expectprefix)) ||
-                    &error("line after --- for file $fn isn't as expected");
-                $filepatched{$fn}++ && &error("diff patches file $fn twice");
-            } elsif (/^\\ No newline at end of file$/) {
-            } elsif (/^[-+ [EMAIL PROTECTED]/) {
-           } else {
-                &error ("diff contains unknown line \`$_'");
-            }
-        }
+           }
+           $hunk or &error("expected [EMAIL PROTECTED]@ at line $. of diff");
+        } while ($_ || !eof(GZIP));
         close(GZIP);
         
         &reapgzip;
@@ -610,7 +627,7 @@
             open(STDIN,"<&GZIP") || &syserr("reopen gzip for patch");
             chdir($newdirectory) || &syserr("chdir to $newdirectory for 
patch");
             exec('patch','-s','-t','-F','0','-N','-p1','-u',
-                 '-V','never','-b','-z','.dpkg-orig');
+                 '-V','never','-g0','-b','-z','.dpkg-orig');
             &syserr("exec patch");
         }
         close(GZIP);

Reply via email to