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]

Reply via email to