Subject: pkg/25222: patch for pkglint (more checks on patch files)
To: None <gnats-bugs@gnats.netbsd.org>
From: None <roland.illig@gmx.de>
List: pkgsrc-bugs
Date: 04/18/2004 13:23:53
>Number:         25222
>Category:       pkg
>Synopsis:       patch for pkglint (more checks on patch files)
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Apr 18 11:24:00 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator:     Roland Illig
>Release:        Linux 2.4.22-1-k7
>Organization:
>Environment:
System: Linux wwid 2.4.22-1-k7 #5 Sat Oct 4 14:11:12 EST 2003 i686 GNU/Linux
Architecture: i686

	
>Description:
This patch checks all files in the patches/ directory if they contain
exactly one patch per file. It also adds the "-q" (quiet) switch and
gets rid of the implicit global variables $opt_X.

	
>How-To-Repeat:
	
>Fix:
	
Index: pkglint.pl
===================================================================
RCS file: /cvsroot/pkgsrc/pkgtools/pkglint/files/pkglint.pl,v
retrieving revision 1.101
diff -u -r1.101 pkglint.pl
--- pkglint.pl	15 Apr 2004 09:41:22 -0000	1.101
+++ pkglint.pl	18 Apr 2004 11:19:01 -0000
@@ -1,4 +1,4 @@
-#!@PERL@
+#!@PERL@ -w
 #
 # pkglint - lint for package directory
 #
@@ -36,12 +36,14 @@
 $rcsidstr = 'NetBSD';
 $localbase = '@PREFIX@';
 
-getopts('hINB:vV');
+%opts = ();
+getopts('hINB:qvV', \%opts);
 
-if ($opt_h) {
+if ($opts{"h"}) {
 		($prog) = ($0 =~ /([^\/]+)$/);
 		print STDERR <<EOF;
-usage: $prog [-vIN] [-B#] [package_directory]
+usage: $prog [-qvIN] [-B#] [package_directory]
+	-q	quiet
 	-v	verbose mode
 	-V	version (@DISTVER@)
 	-I	show Makefile (with all included files)
@@ -50,14 +52,15 @@
 EOF
 		exit 0;
 };
-$verbose = 1	if $opt_v;
-$newpkg = 1	if $opt_N;
-$showmakefile = 1	if $opt_I;
-$contblank = $opt_B	if $opt_B;
+$quiet = 1	if $opts{"q"};
+$verbose = 1	if $opts{"v"};
+$newpkg = 1	if $opts{"N"};
+$showmakefile = 1	if $opts{"I"};
+$contblank = $opts{"B"}	if $opts{"B"};
 
 $portdir = shift || ".";
 
-if ($opt_V) {
+if ($opts{"V"}) {
 	print "@DISTVER@\n";
 	exit;
 }
@@ -132,7 +135,7 @@
 }
 
 # we need to handle the Makefile first to get some variables
-print "OK: checking Makefile.\n";
+print "OK: checking Makefile.\n" unless $quiet;
 if (! -f "$portdir/Makefile") {
 	&perror("FATAL: no Makefile in \"$portdir\".");
 } else {
@@ -193,7 +196,7 @@
 	}
 }
 foreach $i (@checker) {
-	print "OK: checking $i.\n";
+	print "OK: checking $i.\n" unless $quiet;
 	if (! -f "$portdir/$i") {
 		&perror("FATAL: no $i in \"$portdir\".");
 	} else {
@@ -556,9 +559,9 @@
 }
 
 sub checkpatch {
-	local($file) = @_;
-	local($rcsidseen) = 0;
-	local($whole);
+	my ($file) = @_;
+	my ($rcsidseen, $whole, @lines);
+	$rcsidseen = 0;
 
 	if ($file =~ /.*~$/) {
 		&perror("WARN: is $file a backup file? If so, please remove it \n"
@@ -570,6 +573,7 @@
 	while (<IN>) {
 		$rcsidseen++ if /\$$rcsidstr[:\$]/;
 		$whole .= $_;
+		push(@lines, $_);
 	}
 	if ($committer && $whole =~ /.\$(Author|Date|Header|Id|Locker|Log|Name|RCSfile|Revision|Source|State|NetBSD)(:.*\$|\$)/) { # XXX
 	        # RCS ID in very first line is ok, to identify version
@@ -583,6 +587,45 @@
 			"in patch $file.")
 	}
 	close(IN);
+
+	$files_in_patch = 0;
+	$patch_state = "";
+	foreach my $patch_line (@lines) {
+	    chomp($patch_line);
+	    if (index($patch_line, "--- ") == 0 && $patch_line !~ qr"^--- \d+,\d+ ----$") {
+	        $line_type = "-";
+	    } elsif (index($patch_line, "*** ") == 0 && $patch_line !~ qr"^\*\*\* \d+,\d+ \*\*\*\*$") {
+	        $line_type = "*";
+	    } elsif (index($patch_line, "+++ ") == 0) {
+	        $line_type = "+";
+	    } else {
+	        $line_type = "";
+	    }
+	    if ($patch_state eq "*") {
+	        if ($line_type eq "-") {
+		    $files_in_patch++;
+		    $patch_state = "";
+		} else {
+	            &perror("WARN: $i:$.: unknown patch format (might be an internal error)");
+		}
+	    } elsif ($patch_state eq "-") {
+	        if ($line_type eq "+") {
+		    $files_in_patch++;
+		    $patch_state = "";
+		} else {
+		    &perror("WARN: $i:$.: unknown patch format (might be an internal error)");
+		}
+	    } elsif ($patch_state eq "") {
+	        $patch_state = $line_type;
+	    }
+	    #printf("%s:%d: state=(%s), line=(%s)\n", $i, $., $patch_state, $line_type);
+	}
+	if ($files_in_patch > 1) {
+	    &perror("WARN: patch `$i' contains patches for more than one file, namely $files_in_patch");
+	} elsif ($files_in_patch == 0) {
+	    &perror("WARN: patch `$i' contains no patch");
+	}
+	return 1;
 }
 
 sub readmakefile {
@@ -621,7 +664,7 @@
 						$level--;
 					}
 					if ($level eq 0) {
-						break;
+						last;
 					}
 				}
 				if ($level > 0) {
@@ -631,7 +674,7 @@
 			}
 			else {
 				print("OK: defining $1\n") if $verbose;
-				$definesfound{$1} = true;
+				$definesfound{$1} = 1;
 			}
 		}
 		# try to get any included file
@@ -650,7 +693,7 @@
 			} else {
 				$dirname = dirname($file);
                                 if (-e "$dirname/$includefile") {
-                                    print("OK: including $dirname/$includefile\n");
+                                    print("OK: including $dirname/$includefile\n") unless $quiet;
                                     $contents .= readmakefile("$dirname/$includefile");
                                 }
                                 else {
@@ -1620,7 +1663,6 @@
 	local($sub) = "";
 	local($contents);
 	local(@dirlist);
-	local(%alldirs);
 	local($i);
 
 	$contents = readmakefile("$portdir/$file") or
>Release-Note:
>Audit-Trail:
>Unformatted: