OpenPKG CVS Repository
http://cvs.openpkg.org/
____________________________________________________________________________
Server: cvs.openpkg.org Name: Ralf S. Engelschall
Root: /e/openpkg/cvs Email: [EMAIL PROTECTED]
Module: openpkg-re Date: 05-Mar-2003 17:21:17
Branch: HEAD Handle: 2003030516211700
Added files:
openpkg-re speclint.pl
Log:
first cut for a forthcoming OpenPKG .spec file lint utility
Summary:
Revision Changes Path
1.1 +314 -0 openpkg-re/speclint.pl
____________________________________________________________________________
patch -p0 <<'@@ .'
Index: openpkg-re/speclint.pl
============================================================================
$ cvs diff -u -r0 -r1.1 speclint.pl
--- /dev/null 2003-03-05 17:21:17.000000000 +0100
+++ speclint.pl 2003-03-05 17:21:17.000000000 +0100
@@ -0,0 +1,314 @@
+#!/bin/sh -- # -*- perl -*-
+eval 'exec perl -S $0 ${1+"$@"}'
+ if $running_under_some_shell;
+##
+## speclint -- OpenPKG .spec File Checker
+## Copyright (c) 2003 The OpenPKG Project <http://www.openpkg.org/>
+## Copyright (c) 2003 Ralf S. Engelschall <[EMAIL PROTECTED]>
+## Copyright (c) 2003 Cable & Wireless Germany <http://www.cw.com/de>
+##
+## Permission to use, copy, modify, and distribute this software for
+## any purpose with or without fee is hereby granted, provided that
+## the above copyright notice and this permission notice appear in all
+## copies.
+##
+## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
+## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+## SUCH DAMAGE.
+##
+
+require 5;
+use Getopt::Long;
+use IO;
+use strict;
+
+# program information
+my $progname = "speclint";
+my $progvers = "0.0.1";
+
+# parameters (defaults)
+my $version = 0;
+my $verbose = 0;
+my $help = 0;
+my $check = 'all';
+my $tmpdir = ($ENV{TMPDIR} || $ENV{TEMPDIR} || "/tmp") . "/$progname";
+my $rpm = 'rpm';
+
+# exception handling support
+$SIG{__DIE__} = sub {
+ my ($err) = @_;
+ $err =~ s|\s+at\s+.*||s if (not $verbose);
+ print STDERR "$progname:ERROR: $err ". ($! ? "($!)" : "") . "\n";
+ exit(1);
+};
+
+# command line parsing
+Getopt::Long::Configure("bundling");
+my $result = GetOptions(
+ 'V|version' => \$version,
+ 'v|verbose' => \$verbose,
+ 'h|help' => \$help,
+ 'c|check=s' => \$check,
+ 't|tmpdir=s' => \$tmpdir,
+ 'r|rpm=s' => \$rpm,
+) || die "option parsing failed";
+if ($help) {
+ print "Usage: $progname [options] [SPECFILE ...]\n" .
+ "Available options:\n" .
+ " -v,--verbose enable verbose run-time mode\n" .
+ " -h,--help print out this usage page\n" .
+ " -c,--check=CHECKS select checks to perform (default='all')\n" .
+ " -r,--rpm=FILE filesystem path to RPM program\n" .
+ " -t,--tmpdir=PATH filesystem path to temporary directory\n" .
+ " -V,--version print program version\n" .
+ exit(0);
+}
+if ($version) {
+ print "OpenPKG $progname $progvers\n";
+ exit(0);
+}
+
+# verbose message printing
+sub msg_verbose {
+ my ($msg) = @_;
+ print STDERR "$msg\n" if ($verbose);
+}
+
+# warning message printing
+sub msg_warning {
+ my ($msg) = @_;
+ print STDERR "$progname:WARNING: $msg\n";
+}
+
+# error message printing
+sub msg_error {
+ my ($msg) = @_;
+ print STDERR "$progname:ERROR: $msg\n";
+}
+
+# determine check list
+my @check_list = (qw(
+ blank
+ comment
+ license
+ header
+));
+my @checks = ();
+if ($check eq 'all') {
+ @checks = @check_list;
+}
+else {
+ foreach my $c (split(/,/, $check)) {
+ if (not grep($c, @check_list)) {
+ die "invalid check \"$c\"";
+ }
+ push(@checks, $c);
+ }
+}
+
+# iterate over all .spec files
+foreach my $filename (@ARGV) {
+ my $io = new IO::File "<$filename"
+ || "unable to open file \"$filename\" for reading";
+ my $spec; { local $/ = undef; $spec = <$io>; }
+ $io->close;
+
+ foreach my $check (@checks) {
+ eval "\&check_$check(\$filename, \$spec);";
+ }
+}
+exit(0);
+
+## _________________________________________________________________
+##
+## COMMON SUBROUTINES
+## _________________________________________________________________
+##
+
+sub lines {
+ my ($txt) = @_;
+ my $l = 0;
+ $txt =~ s|\n|$l++, ''|sge;
+ return $l;
+}
+
+sub lint_message {
+ my ($type, $file, $done, $this, $msg) = @_;
+ my $start = &lines($done) + 1;
+ my $end = $start + &lines($this);
+ my $pos = $start;
+ if ($end > $start) {
+ $pos .= "-". $end;
+ }
+ printf("%s: %s:%s: %s\n", $type, $file, $pos, $msg);
+}
+
+sub lint_warning {
+ my ($file, $done, $this, $msg) = @_;
+ &lint_message("WARNING", $file, $done, $this, $msg);
+}
+
+sub lint_error {
+ my ($file, $done, $this, $msg) = @_;
+ &lint_message("ERROR", $file, $done, $this, $msg);
+}
+
+## _________________________________________________________________
+##
+## CHECK "blank": whitespace and blank lines
+## _________________________________________________________________
+##
+
+sub check_blank {
+ my ($file, $spec) = @_;
+
+ # check for CR-LF combination
+ my $done = '';
+ my $todo = $spec;
+ while ($todo =~ m/\r\n/s) {
+ $done .= $`;
+ &lint_warning($file, $done, $&, "carriage-return (CR, 0x0d) line-feed (NL,
0x0a) combination (expected just line-feed)");
+ $todo = $';
+ }
+
+ # check for multiple blank lines
+ $done = '';
+ $todo = $spec;
+ while ($todo =~ m/(\r?\n[ \t]*){3,}/s) {
+ $done .= $`;
+ &lint_warning($file, $done, $&, "multiple subsequent blank lines (expected
single blank line)");
+ $todo = $';
+ }
+
+ # check for trailing whitespaces
+ $done = '';
+ $todo = $spec;
+ while ($todo =~ m/[ \t]+\r?\n/s) {
+ $done .= $`;
+ &lint_warning($file, $done, $&, "trailing whitespace (expected none)");
+ $todo = $';
+ }
+}
+
+## _________________________________________________________________
+##
+## CHECK "comment": sharp-comments
+## _________________________________________________________________
+##
+
+sub check_comment {
+ my ($file, $spec) = @_;
+
+ # check for comment indentation
+ my $done = '';
+ my $todo = $spec;
+ while ($todo =~ m/^([ \t]*)(#+)([ \t]*)(.*?)$/m) {
+ $done .= $`;
+ my $this = $&;
+ $todo = $';
+ my ($lead, $sharp, $pad, $text) = ($1, $2, $3, $4);
+ if (length($lead) % 2 != 0) {
+ &lint_warning($file, $done, $this, "incorrect comment indentation
(expected a multiple of 2 spaces)");
+ }
+ if (length($lead) > 1 && length($sharp) > 1) {
+ &lint_warning($file, $done, $this, "indented comment has introduced
with multiple sharps (expected single sharp character)");
+ }
+ if (length($pad.$text) > 0 && length($sharp.$pad) % 4 != 0) {
+ &lint_warning($file, $done, $this, "incorrect comment text padding
(expected a multiple of 4 sharps or spaces)");
+ }
+ if (length($pad) == 0 && length($text) > 0) {
+ &lint_warning($file, $done, $this, "missing leading space before
comment text (expected padding spaces)");
+ }
+ if (length($pad) > 0 && length($text) == 0) {
+ &lint_warning($file, $done, $this, "empty comment text (expected a
reasonable text)");
+ }
+ }
+}
+
+## _________________________________________________________________
+##
+## CHECK "license": license header
+## _________________________________________________________________
+##
+
+sub check_license {
+ my ($file, $spec) = @_;
+
+ my $re = "";
+ $re .= "##\\n";
+ $re .= "## [a-z][a-z0-9-]+\\.spec -- OpenPKG RPM Specification\\n";
+ $re .= "## Copyright \\(c\\) 200[0-3]-200[0-3] Cable \\& Wireless Deutschland
GmbH\\n";
+ $re .= "## Copyright \\(c\\) 200[0-3]-200[0-3] The OpenPKG Project
<http://www\\.openpkg\\.org/>\\n";
+ $re .= "## Copyright \\(c\\) 200[0-3]-200[0-3] Ralf S\\. Engelschall <[EMAIL
PROTECTED]>\\n";
+ $re .= "##\\n";
+ $re .= "## Permission to use, copy, modify, and distribute this software
for\\n";
+ $re .= "## any purpose with or without fee is hereby granted, provided
that\\n";
+ $re .= "## the above copyright notice and this permission notice appear in
all\\n";
+ $re .= "## copies\\.\\n";
+ $re .= "##\\n";
+ $re .= "## THIS SOFTWARE IS PROVIDED \\`\\`AS IS'' AND ANY EXPRESSED OR
IMPLIED\\n";
+ $re .= "## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF\\n";
+ $re .= "## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED\\.\\n";
+ $re .= "## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR\\n";
+ $re .= "## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\\n";
+ $re .= "## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES \\(INCLUDING, BUT
NOT\\n";
+ $re .= "## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF\\n";
+ $re .= "## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION\\) HOWEVER CAUSED
AND\\n";
+ $re .= "## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY,\\n";
+ $re .= "## OR TORT \\(INCLUDING NEGLIGENCE OR OTHERWISE\\) ARISING IN ANY WAY
OUT\\n";
+ $re .= "## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF\\n";
+ $re .= "## SUCH DAMAGE\\.\\n";
+ $re .= "##\\n";
+ if ($spec !~ m|^$re|os) {
+ &lint_warning($file, "", "", "invalid license header");
+ }
+}
+
+## _________________________________________________________________
+##
+## CHECK "header": RPM headers
+## _________________________________________________________________
+##
+
+sub check_header {
+ my ($file, $spec) = @_;
+
+ my @headers = (qw(
+ Name Summary URL Vendor Packager Distribution Group License Version Release
+ Source\d+ Patch\d+
+ Prefix BuildRoot
+ BuildPreReq PreReq
+ AutoReq AutoReqProv
+ Provides Conflicts
+ ));
+
+ # check for comment indentation
+ my $done = '';
+ my $todo = $spec;
+ while ($todo =~ m/^(\S+):([ \t]*)(.*?)$/m) {
+ $done .= $`;
+ my $this = $&;
+ $todo = $';
+ my ($header, $pad, $value) = ($1, $2, $3);
+ my $ok = 0;
+ foreach my $h (@headers) {
+ if ($header =~ m|^$h$|s) {
+ $ok = 1;
+ last;
+ }
+ }
+ if (not $ok) {
+ &lint_error($file, $done, $this, "invalid header \"$header\"");
+ }
+ }
+}
+
@@ .
______________________________________________________________________
The OpenPKG Project www.openpkg.org
CVS Repository Commit List [EMAIL PROTECTED]