2001-04-27 18:10:36 +02:00
|
|
|
#!@PREFIX@/bin/perl
|
1999-04-19 09:32:09 +02:00
|
|
|
|
2002-08-13 17:05:30 +02:00
|
|
|
# $NetBSD: lintpkgsrc.pl,v 1.69 2002/08/13 15:05:31 wiz Exp $
|
1999-04-19 09:32:09 +02:00
|
|
|
|
1999-12-22 22:04:17 +01:00
|
|
|
# Written by David Brownlee <abs@netbsd.org>.
|
|
|
|
#
|
1999-04-19 09:32:09 +02:00
|
|
|
# Caveats:
|
|
|
|
# The 'Makefile parsing' algorithym used to obtain package versions
|
1999-12-22 22:04:17 +01:00
|
|
|
# and DEPENDS information is geared towards speed rather than perfection,
|
|
|
|
# though it has got somewhat better over time, it only parses the
|
|
|
|
# simplest Makefile conditionals. (a == b, no && etc).
|
1999-04-19 09:32:09 +02:00
|
|
|
#
|
2001-12-27 13:42:08 +01:00
|
|
|
# TODO: Handle fun DEPENDS like avifile-devel with
|
|
|
|
# {qt2-designer>=2.2.4,qt2-designer-kde>=2.3.1nb1}
|
1999-04-19 09:32:09 +02:00
|
|
|
|
1999-12-16 12:59:13 +01:00
|
|
|
$^W = 1;
|
2002-06-02 23:52:28 +02:00
|
|
|
use locale;
|
1999-06-25 01:40:13 +02:00
|
|
|
use strict;
|
1999-12-16 12:59:13 +01:00
|
|
|
use Getopt::Std;
|
1999-06-25 01:40:13 +02:00
|
|
|
use File::Find;
|
2001-12-03 19:20:49 +01:00
|
|
|
use Cwd;
|
2001-12-27 13:42:08 +01:00
|
|
|
my( $pkglist, # list of Pkg packages
|
2000-10-02 16:32:21 +02:00
|
|
|
$default_vars, # Set for Makefiles, inc PACKAGES & PKGSRCDIR
|
1999-12-22 22:04:17 +01:00
|
|
|
%opt, # Command line options
|
2000-10-12 17:07:41 +02:00
|
|
|
%vuln, # vulnerability data
|
|
|
|
@matched_prebuiltpackages,# List of obsolete prebuilt package paths
|
2000-01-10 16:06:48 +01:00
|
|
|
@prebuilt_pkgdirs, # Use to follow symlinks in prebuilt pkgdirs
|
2002-01-03 12:04:49 +01:00
|
|
|
%prebuilt_pkgdir_cache, # To avoid symlink loops in prebuilt_pkgdirs
|
2000-10-12 17:07:41 +02:00
|
|
|
);
|
1999-06-25 01:40:13 +02:00
|
|
|
|
1999-12-16 12:59:13 +01:00
|
|
|
$ENV{PATH} .= ':/usr/sbin';
|
1999-09-25 18:06:54 +02:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
if (! getopts('BDK:LM:OP:RSVdg:hilmopru', \%opt) || $opt{h} ||
|
2001-12-03 19:20:49 +01:00
|
|
|
! ( defined($opt{d}) || defined($opt{g}) || defined($opt{i}) ||
|
|
|
|
defined($opt{l}) || defined($opt{m}) || defined($opt{o}) ||
|
|
|
|
defined($opt{p}) || defined($opt{r}) || defined($opt{u}) ||
|
|
|
|
defined($opt{B}) || defined($opt{D}) || defined($opt{R}) ||
|
|
|
|
defined($opt{O}) || defined($opt{S}) || defined($opt{V}) ))
|
2001-12-27 13:42:08 +01:00
|
|
|
{ usage_and_exit(); }
|
1999-12-16 12:59:13 +01:00
|
|
|
$| = 1;
|
1999-04-19 09:32:09 +02:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
get_default_makefile_vars(); # $default_vars
|
2000-01-10 03:01:20 +01:00
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{D} && @ARGV)
|
1999-12-16 15:04:19 +01:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $file (@ARGV)
|
1999-12-16 15:04:19 +01:00
|
|
|
{
|
|
|
|
if ( -d $file)
|
|
|
|
{ $file .= "/Makefile"; }
|
2000-09-23 00:41:07 +02:00
|
|
|
if (! -f $file)
|
2001-12-27 13:42:08 +01:00
|
|
|
{ fail("No such file: $file"); }
|
2000-09-11 12:39:04 +02:00
|
|
|
my($pkgname, $vars);
|
2001-12-03 19:20:49 +01:00
|
|
|
($pkgname, $vars) = parse_makefile_pkgsrc($file);
|
2001-05-18 12:38:47 +02:00
|
|
|
$pkgname ||= 'UNDEFINED';
|
1999-12-16 15:04:19 +01:00
|
|
|
print "$file -> $pkgname\n";
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $varname (sort keys %{$vars})
|
|
|
|
{ print "\t$varname = $vars->{$varname}\n"; }
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{d})
|
2001-12-27 13:42:08 +01:00
|
|
|
{ pkgsrc_check_depends(); }
|
1999-12-16 15:04:19 +01:00
|
|
|
}
|
2000-09-23 00:41:07 +02:00
|
|
|
exit;
|
1999-12-16 15:04:19 +01:00
|
|
|
}
|
1999-04-19 09:32:09 +02:00
|
|
|
|
|
|
|
# main
|
|
|
|
{
|
2000-11-17 13:45:30 +01:00
|
|
|
my($pkglint_flags, $pkgsrcdir, $pkgdistdir);
|
1999-04-19 09:32:09 +02:00
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
$pkgsrcdir = $default_vars->{PKGSRCDIR};
|
|
|
|
$pkgdistdir = $default_vars->{DISTDIR};
|
2000-09-05 02:02:15 +02:00
|
|
|
$pkglint_flags = '-v';
|
1999-04-19 09:32:09 +02:00
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{r} && !$opt{o} && !$opt{m} && !$opt{p})
|
|
|
|
{ $opt{o} = $opt{m} = $opt{p} = 1; }
|
|
|
|
if ($opt{o} || $opt{m})
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
|
|
|
my(@baddist);
|
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
@baddist = scan_pkgsrc_distfiles_vs_distinfo($pkgsrcdir, $pkgdistdir,
|
2001-12-03 19:20:49 +01:00
|
|
|
$opt{o}, $opt{m});
|
|
|
|
if ($opt{r})
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-12-03 19:20:49 +01:00
|
|
|
safe_chdir("$pkgdistdir");
|
2001-12-27 13:42:08 +01:00
|
|
|
verbose("Unlinking 'bad' distfiles\n");
|
|
|
|
foreach my $distfile (@baddist)
|
|
|
|
{ unlink($distfile); }
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
|
|
|
}
|
1999-06-25 01:40:13 +02:00
|
|
|
|
2000-11-14 18:11:42 +01:00
|
|
|
# List BROKEN packages
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{B})
|
2000-11-14 18:11:42 +01:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
scan_pkgsrc_makefiles($pkgsrcdir);
|
|
|
|
foreach my $pkgver ($pkglist->pkgver)
|
|
|
|
{
|
|
|
|
$pkgver->var('BROKEN') || next;
|
|
|
|
print $pkgver->pkgname.': '.$pkgver->var('BROKEN')."\n";
|
2000-11-14 18:11:42 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-08-17 18:16:01 +02:00
|
|
|
# List obsolete or NO_BIN_ON_FTP/RESTRICTED prebuilt packages
|
1999-12-22 22:04:17 +01:00
|
|
|
#
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{p} || $opt{O} || $opt{R} || $opt{V})
|
1999-06-25 01:40:13 +02:00
|
|
|
{
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{V})
|
2000-10-12 17:07:41 +02:00
|
|
|
{
|
2000-11-14 18:11:42 +01:00
|
|
|
my($vuln) = "$pkgdistdir/vulnerabilities";
|
2000-10-12 17:07:41 +02:00
|
|
|
if (! open(VULN, $vuln))
|
2001-12-27 13:42:08 +01:00
|
|
|
{ fail("Unable to open '$vuln': $!"); }
|
2000-10-12 17:07:41 +02:00
|
|
|
while (<VULN>)
|
|
|
|
{
|
|
|
|
s/#.*//;
|
|
|
|
if ( /([^*?[]+)(<|>|<=|>=)(\d\S+)/ )
|
2001-12-27 13:42:08 +01:00
|
|
|
{
|
|
|
|
my($pkg, $cmp, $ver) = ($1, $2, $3);
|
|
|
|
push(@{$vuln{$pkg}},"$cmp $ver");
|
|
|
|
}
|
2000-10-12 17:07:41 +02:00
|
|
|
}
|
|
|
|
close(VULN);
|
|
|
|
}
|
2002-07-11 12:22:25 +02:00
|
|
|
if ($opt{p} || $opt{O} || $opt{R} || $opt{V})
|
2001-12-27 13:42:08 +01:00
|
|
|
{ scan_pkgsrc_makefiles($pkgsrcdir); }
|
2001-12-03 19:20:49 +01:00
|
|
|
@prebuilt_pkgdirs = ($default_vars->{PACKAGES});
|
2002-01-03 12:04:49 +01:00
|
|
|
%prebuilt_pkgdir_cache = ();
|
2000-01-10 16:06:48 +01:00
|
|
|
while (@prebuilt_pkgdirs)
|
|
|
|
{ find(\&check_prebuilt_packages, shift @prebuilt_pkgdirs); }
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{r})
|
1999-06-25 01:40:13 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
verbose("Unlinking listed prebuiltpackages\n");
|
|
|
|
foreach my $pkgfile (@matched_prebuiltpackages)
|
|
|
|
{ unlink($pkgfile); }
|
1999-06-25 01:40:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{S})
|
2000-11-17 13:45:30 +01:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
my(%in_subdir);
|
2000-11-17 13:45:30 +01:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $cat (list_pkgsrc_categories($pkgsrcdir))
|
2000-11-17 13:45:30 +01:00
|
|
|
{
|
|
|
|
my($vars) = parse_makefile_vars("$pkgsrcdir/$cat/Makefile");
|
2001-12-03 19:20:49 +01:00
|
|
|
if (! $vars->{SUBDIR})
|
2000-11-17 13:45:30 +01:00
|
|
|
{ print "Warning - no SUBDIR for $cat\n"; next; }
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $pkgdir (split(/\s+/, $vars->{SUBDIR}))
|
|
|
|
{ $in_subdir{"$cat/$pkgdir"} = 1; }
|
2000-11-17 13:45:30 +01:00
|
|
|
}
|
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
scan_pkgsrc_makefiles($pkgsrcdir);
|
|
|
|
foreach my $pkgver ($pkglist->pkgver)
|
|
|
|
{
|
|
|
|
if (!defined $in_subdir{$pkgver->var('dir')})
|
|
|
|
{ print $pkgver->var('dir').": Not in SUBDIR\n"; }
|
2000-11-17 13:45:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{g})
|
2000-10-20 13:00:13 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
my($tmpfile);
|
2000-10-20 13:00:13 +02:00
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
$tmpfile = "$opt{g}.tmp.$$";
|
2000-10-20 13:00:13 +02:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
scan_pkgsrc_makefiles($pkgsrcdir);
|
2000-10-20 13:00:13 +02:00
|
|
|
if (!open(TABLE, ">$tmpfile"))
|
2001-12-27 13:42:08 +01:00
|
|
|
{ fail("Unable to write '$tmpfile': $!"); }
|
|
|
|
foreach my $pkgver ($pkglist->pkgver)
|
|
|
|
{
|
|
|
|
print TABLE $pkgver->pkg."\t".$pkgver->var('dir')."\t".
|
|
|
|
$pkgver->ver."\n";
|
2000-10-20 13:00:13 +02:00
|
|
|
}
|
|
|
|
if (!close(TABLE))
|
2001-12-27 13:42:08 +01:00
|
|
|
{ fail("Error while writing '$tmpfile': $!"); }
|
2001-12-03 19:20:49 +01:00
|
|
|
if (!rename($tmpfile, $opt{g}))
|
2001-12-27 13:42:08 +01:00
|
|
|
{ fail("Error in rename('$tmpfile','$opt{g}'): $!"); }
|
2000-10-20 13:00:13 +02:00
|
|
|
}
|
2000-11-17 13:45:30 +01:00
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{d})
|
2000-09-23 00:41:07 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
scan_pkgsrc_makefiles($pkgsrcdir);
|
|
|
|
pkgsrc_check_depends();
|
2000-09-23 00:41:07 +02:00
|
|
|
}
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{i} || $opt{u})
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
my(@pkgs, @update);
|
1999-04-19 09:32:09 +02:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
@pkgs = list_installed_packages();
|
|
|
|
scan_pkgsrc_makefiles($pkgsrcdir);
|
2000-10-20 13:00:13 +02:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $pkgname (sort @pkgs)
|
1999-12-16 12:59:13 +01:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
if ($_ = invalid_version($pkgname))
|
2000-01-10 16:06:48 +01:00
|
|
|
{
|
|
|
|
print $_;
|
2001-12-27 13:42:08 +01:00
|
|
|
if ($pkgname =~ /^([^*?[]+)-([\d*?[].*)/)
|
2001-05-18 12:38:47 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $pkgver ($pkglist->pkgver($1))
|
2001-05-18 12:38:47 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
$pkgver->var('dir') =~ /-current/ && next;
|
|
|
|
push(@update, $pkgver);
|
2001-05-18 12:38:47 +02:00
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
2000-01-10 16:06:48 +01:00
|
|
|
}
|
|
|
|
}
|
2000-10-20 13:00:13 +02:00
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{u})
|
2000-01-10 16:06:48 +01:00
|
|
|
{
|
2001-05-18 12:38:47 +02:00
|
|
|
print "\nREQUIRED details for packages that could be updated:\n";
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $pkgver (@update)
|
2001-05-18 12:38:47 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
print $pkgver->pkg.':';
|
|
|
|
if (open(PKGINFO, 'pkg_info -R '.$pkgver->pkg.'|'))
|
2001-05-18 12:38:47 +02:00
|
|
|
{
|
|
|
|
my($list);
|
|
|
|
while (<PKGINFO>)
|
|
|
|
{
|
|
|
|
if (/Required by:/)
|
|
|
|
{ $list = 1; }
|
|
|
|
elsif ($list)
|
|
|
|
{
|
|
|
|
chomp;
|
|
|
|
s/-\d.*//;
|
|
|
|
print " $_";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close(PKGINFO);
|
|
|
|
}
|
|
|
|
print "\n";
|
|
|
|
}
|
|
|
|
print "\nRunning 'make fetch-list | sh' for each package:\n";
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $pkgver (@update)
|
2000-01-10 16:06:48 +01:00
|
|
|
{
|
|
|
|
my($pkgdir);
|
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
$pkgdir = $pkgver->var('dir');
|
2000-01-10 16:06:48 +01:00
|
|
|
if (!defined($pkgdir))
|
2001-12-27 13:42:08 +01:00
|
|
|
{ fail('Unable to determine '.$pkgver->pkg.' directory'); }
|
2000-10-02 16:32:21 +02:00
|
|
|
print "$pkgsrcdir/$pkgdir\n";
|
|
|
|
safe_chdir("$pkgsrcdir/$pkgdir");
|
2000-01-10 16:06:48 +01:00
|
|
|
system('make fetch-list | sh');
|
|
|
|
}
|
1999-12-16 12:59:13 +01:00
|
|
|
}
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{l})
|
2001-12-27 13:42:08 +01:00
|
|
|
{ pkglint_all_pkgsrc($pkgsrcdir, $pkglint_flags); }
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
|
|
|
exit;
|
|
|
|
|
2000-10-12 17:07:41 +02:00
|
|
|
# Could speed up by building a cache of package names to paths, then processing
|
|
|
|
# each package name once against the tests.
|
1999-06-25 01:40:13 +02:00
|
|
|
sub check_prebuilt_packages
|
|
|
|
{
|
2000-11-14 18:11:42 +01:00
|
|
|
if ($_ eq 'distfiles' || $_ eq 'pkgsrc') # Skip these subdirs if present
|
1999-12-22 23:07:29 +01:00
|
|
|
{ $File::Find::prune = 1; }
|
2000-09-26 17:57:05 +02:00
|
|
|
elsif (/(.+)-(\d.*)\.tgz$/)
|
1999-06-25 01:40:13 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
my($pkg, $ver);
|
|
|
|
($pkg, $ver) = ($1, $2);
|
2000-10-12 17:07:41 +02:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
if ($opt{V} && $vuln{$pkg})
|
1999-06-25 01:40:13 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $chk (@{$vuln{$pkg}})
|
2000-10-12 17:07:41 +02:00
|
|
|
{
|
|
|
|
my($test, $matchver) = split(' ',$chk);
|
|
|
|
if (deweycmp($ver, $test, $matchver))
|
|
|
|
{
|
|
|
|
print "$File::Find::dir/$_\n";
|
|
|
|
push(@matched_prebuiltpackages, "$File::Find::dir/$_");
|
2001-05-31 19:37:25 +02:00
|
|
|
last;
|
2000-10-12 17:07:41 +02:00
|
|
|
}
|
|
|
|
}
|
1999-12-22 22:04:17 +01:00
|
|
|
}
|
2000-10-12 17:07:41 +02:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
my($pkgs);
|
|
|
|
if ($pkgs = $pkglist->pkgs($pkg))
|
1999-12-22 22:04:17 +01:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
my($pkgver) = $pkgs->pkgver($ver);
|
|
|
|
if (!defined $pkgver)
|
2000-10-12 17:07:41 +02:00
|
|
|
{
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{p})
|
2000-10-12 17:07:41 +02:00
|
|
|
{
|
|
|
|
print "$File::Find::dir/$_\n";
|
|
|
|
push(@matched_prebuiltpackages, "$File::Find::dir/$_");
|
|
|
|
}
|
2000-10-20 13:00:13 +02:00
|
|
|
# Pick probably the last version
|
2001-12-27 13:42:08 +01:00
|
|
|
$pkgver = $pkgs->latestver;
|
2000-10-12 17:07:41 +02:00
|
|
|
}
|
2001-12-27 13:42:08 +01:00
|
|
|
if ($opt{R} && $pkgver->var('RESTRICTED'))
|
2000-10-12 17:07:41 +02:00
|
|
|
{
|
|
|
|
print "$File::Find::dir/$_\n";
|
|
|
|
push(@matched_prebuiltpackages, "$File::Find::dir/$_");
|
|
|
|
}
|
2001-12-27 13:42:08 +01:00
|
|
|
if ($opt{O} && $pkgver->var('OSVERSION_SPECIFIC'))
|
2001-07-07 20:21:29 +02:00
|
|
|
{
|
|
|
|
print "$File::Find::dir/$_\n";
|
|
|
|
push(@matched_prebuiltpackages, "$File::Find::dir/$_");
|
|
|
|
}
|
1999-06-25 01:40:13 +02:00
|
|
|
}
|
2000-10-12 17:07:41 +02:00
|
|
|
|
1999-06-25 01:40:13 +02:00
|
|
|
}
|
2002-01-03 12:04:49 +01:00
|
|
|
elsif (-d $_)
|
|
|
|
{
|
|
|
|
if ($prebuilt_pkgdir_cache{"$File::Find::dir/$_"})
|
|
|
|
{ $File::Find::prune = 1; return; }
|
|
|
|
$prebuilt_pkgdir_cache{"$File::Find::dir/$_"} = 1;
|
|
|
|
if (-l $_)
|
|
|
|
{
|
|
|
|
my($dest) = readlink($_);
|
|
|
|
if (substr($dest, 0, 1) ne '/')
|
|
|
|
{ $dest = "$File::Find::dir/$dest"; }
|
|
|
|
if (!$prebuilt_pkgdir_cache{$dest})
|
|
|
|
{ push(@prebuilt_pkgdirs, $dest); }
|
|
|
|
}
|
|
|
|
}
|
1999-06-25 01:40:13 +02:00
|
|
|
}
|
|
|
|
|
1999-12-22 22:04:17 +01:00
|
|
|
# Dewey decimal verson number matching - or thereabouts
|
2000-02-03 13:05:20 +01:00
|
|
|
# Also handles 'nb<N>' suffix (checked iff values otherwise identical)
|
1999-12-22 22:04:17 +01:00
|
|
|
#
|
2000-02-07 12:38:53 +01:00
|
|
|
sub deweycmp
|
1999-12-22 22:04:17 +01:00
|
|
|
{
|
|
|
|
my($match, $test, $val) = @_;
|
2000-02-07 12:38:53 +01:00
|
|
|
my($cmp, $match_nb, $val_nb);
|
1999-12-22 22:04:17 +01:00
|
|
|
|
2000-02-03 13:05:20 +01:00
|
|
|
$match_nb = $val_nb = 0;
|
2000-02-07 12:38:53 +01:00
|
|
|
if ($match =~ /(.*)nb(.*)/) # Handle nb<N> suffix
|
2000-02-03 13:05:20 +01:00
|
|
|
{
|
|
|
|
$match = $1;
|
|
|
|
$match_nb = $2;
|
|
|
|
}
|
|
|
|
|
2000-02-07 12:38:53 +01:00
|
|
|
if ($val =~ /(.*)nb(.*)/) # Handle nb<N> suffix
|
2000-02-03 13:05:20 +01:00
|
|
|
{
|
|
|
|
$val = $1;
|
|
|
|
$val_nb = $2;
|
|
|
|
}
|
|
|
|
|
2000-02-07 12:38:53 +01:00
|
|
|
$cmp = deweycmp_extract($match, $val);
|
|
|
|
|
|
|
|
if (!$cmp) # Iff otherwise identical, check nb suffix
|
|
|
|
{ $cmp = deweycmp_extract($match_nb, $val_nb); }
|
|
|
|
|
|
|
|
eval "$cmp $test 0";
|
|
|
|
}
|
|
|
|
|
2002-06-02 23:52:28 +02:00
|
|
|
sub convert_to_standard_dewey
|
|
|
|
{
|
|
|
|
# According to the current implementation in pkg_install/lib/str.c
|
|
|
|
# as of 2002/06/02, '_' before a number, '.', and 'pl' get treated as 0,
|
|
|
|
# while 'rc' gets treated as -1; other characters are converted to lower
|
|
|
|
# case and then to a number: a->1, b->2, c->3, etc. Numbers stay the same.
|
|
|
|
# 'nb' is a special case that's already been handled when we are here.
|
|
|
|
my($elem, $underscore, @temp);
|
|
|
|
foreach $elem (@_) {
|
|
|
|
if ($elem =~ /\d+/) {
|
|
|
|
push(@temp, $elem);
|
|
|
|
}
|
|
|
|
elsif ($elem =~ /^pl$/ or $elem =~ /^\.$/) {
|
|
|
|
push(@temp, 0);
|
|
|
|
}
|
|
|
|
elsif ($elem =~ /^_$/) {
|
|
|
|
push(@temp, 0);
|
|
|
|
}
|
|
|
|
elsif ($elem =~ /^rc$/) {
|
|
|
|
push(@temp, -1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
push(@temp, 0);
|
|
|
|
push(@temp, ord($elem)-ord("a")+1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@temp;
|
|
|
|
}
|
|
|
|
|
2000-02-07 12:38:53 +01:00
|
|
|
sub deweycmp_extract
|
|
|
|
{
|
|
|
|
my($match, $val) = @_;
|
|
|
|
my($cmp, @matchlist, @vallist);
|
|
|
|
|
2002-06-02 23:52:28 +02:00
|
|
|
@matchlist = convert_to_standard_dewey(split(/(\D+)/, lc($match)));
|
|
|
|
@vallist = convert_to_standard_dewey(split(/(\D+)/, lc($val)));
|
1999-12-22 22:04:17 +01:00
|
|
|
$cmp = 0;
|
|
|
|
while( ! $cmp && (@matchlist || @vallist))
|
|
|
|
{
|
|
|
|
if (!@matchlist)
|
|
|
|
{ $cmp = -1; }
|
|
|
|
elsif (!@vallist)
|
|
|
|
{ $cmp = 1; }
|
|
|
|
else
|
|
|
|
{ $cmp = (shift @matchlist <=> shift @vallist) }
|
|
|
|
}
|
2000-02-07 12:38:53 +01:00
|
|
|
$cmp;
|
1999-12-22 22:04:17 +01:00
|
|
|
}
|
|
|
|
|
1999-04-19 09:32:09 +02:00
|
|
|
sub fail
|
1999-12-16 12:59:13 +01:00
|
|
|
{ print STDERR @_, "\n"; exit(3); }
|
1999-04-19 09:32:09 +02:00
|
|
|
|
2000-01-10 03:01:20 +01:00
|
|
|
sub get_default_makefile_vars
|
|
|
|
{
|
2001-01-18 12:40:33 +01:00
|
|
|
chomp($_ = `uname -srm`);
|
2001-12-03 19:20:49 +01:00
|
|
|
( $default_vars->{OPSYS},
|
|
|
|
$default_vars->{OS_VERSION},
|
|
|
|
$default_vars->{MACHINE} ) = (split);
|
2001-01-29 11:48:09 +01:00
|
|
|
|
2001-01-18 12:40:33 +01:00
|
|
|
# Handle systems without uname -p (NetBSD pre 1.4)
|
2001-12-03 19:20:49 +01:00
|
|
|
chomp($default_vars->{MACHINE_ARCH} = `uname -p 2>/dev/null`);
|
|
|
|
if (! $default_vars->{MACHINE_ARCH} &&
|
|
|
|
$default_vars->{OS_VERSION} eq 'NetBSD')
|
|
|
|
{ chomp($default_vars->{MACHINE_ARCH} = `sysctl -n hw.machine_arch`);}
|
|
|
|
if (! $default_vars->{MACHINE_ARCH})
|
|
|
|
{ $default_vars->{MACHINE_ARCH} = $default_vars->{MACHINE}; }
|
|
|
|
|
|
|
|
$default_vars->{OBJECT_FMT} = 'x';
|
|
|
|
$default_vars->{LOWER_OPSYS} = lc($default_vars->{OPSYS});
|
|
|
|
|
|
|
|
if ($opt{P})
|
|
|
|
{ $default_vars->{PKGSRCDIR} = $opt{P}; }
|
2000-10-02 16:32:21 +02:00
|
|
|
else
|
2001-12-03 19:20:49 +01:00
|
|
|
{ $default_vars->{PKGSRCDIR} = '/usr/pkgsrc'; }
|
2000-10-02 16:32:21 +02:00
|
|
|
|
|
|
|
my($vars);
|
2001-12-03 19:20:49 +01:00
|
|
|
if (-f '/etc/mk.conf' && ($vars = parse_makefile_vars('/etc/mk.conf')))
|
2001-05-21 15:27:14 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $var (keys %{$vars})
|
|
|
|
{ $default_vars->{$var} = $vars->{$var}; }
|
2001-05-21 15:27:14 +02:00
|
|
|
}
|
2000-10-02 16:32:21 +02:00
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{P})
|
|
|
|
{ $default_vars->{PKGSRCDIR} = $opt{P}; }
|
2000-10-02 16:32:21 +02:00
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{M})
|
|
|
|
{ $default_vars->{DISTDIR} = $opt{M}; }
|
|
|
|
$default_vars->{DISTDIR} ||= $default_vars->{PKGSRCDIR}.'/distfiles';
|
2000-11-17 13:45:30 +01:00
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{K})
|
|
|
|
{ $default_vars->{PACKAGES} = $opt{K}; }
|
2001-12-27 13:42:08 +01:00
|
|
|
|
|
|
|
# Extract some variables from bsd.pkg.mk
|
|
|
|
my($mkvars);
|
|
|
|
$mkvars = parse_makefile_vars("$default_vars->{PKGSRCDIR}/mk/bsd.pkg.mk");
|
|
|
|
foreach my $varname (keys %{$mkvars})
|
|
|
|
{
|
|
|
|
if ($varname =~ /_REQD$/ || $varname eq 'EXTRACT_SUFX')
|
|
|
|
{ $default_vars->{$varname} = $mkvars->{$varname}; }
|
|
|
|
}
|
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
$default_vars->{PACKAGES} ||= $default_vars->{PKGSRCDIR}.'/packages';
|
2000-01-10 03:01:20 +01:00
|
|
|
}
|
|
|
|
|
1999-12-18 15:39:20 +01:00
|
|
|
# Determine if a package version is current. If not, report correct version
|
|
|
|
# if found
|
1999-04-19 09:32:09 +02:00
|
|
|
#
|
1999-12-16 12:59:13 +01:00
|
|
|
sub invalid_version
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-12-27 14:31:45 +01:00
|
|
|
my($pkgmatch) = @_;
|
2001-12-27 20:13:13 +01:00
|
|
|
my($fail, $ok);
|
2001-12-27 14:31:45 +01:00
|
|
|
my(@pkgmatches, @todo);
|
1999-04-19 09:32:09 +02:00
|
|
|
|
2001-12-27 14:31:45 +01:00
|
|
|
@todo = ($pkgmatch);
|
1999-12-22 22:04:17 +01:00
|
|
|
|
2001-12-27 20:13:13 +01:00
|
|
|
# We handle {} here, everything else in package_globmatch
|
2001-12-27 14:31:45 +01:00
|
|
|
while ($pkgmatch = shift @todo)
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-12-27 14:31:45 +01:00
|
|
|
if ($pkgmatch =~ /(.*){([^{}]+)}(.*)/)
|
2001-05-18 12:38:47 +02:00
|
|
|
{
|
2001-12-27 14:31:45 +01:00
|
|
|
foreach (split(',', $2))
|
|
|
|
{ push(@todo, "$1$_$3"); }
|
2001-05-18 12:38:47 +02:00
|
|
|
}
|
1999-12-18 15:39:20 +01:00
|
|
|
else
|
2001-12-27 14:31:45 +01:00
|
|
|
{ push (@pkgmatches, $pkgmatch); }
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach $pkgmatch (@pkgmatches)
|
|
|
|
{
|
|
|
|
my($pkg, $badver) = package_globmatch($pkgmatch);
|
|
|
|
|
|
|
|
if (defined($badver))
|
|
|
|
{
|
|
|
|
my($pkgs);
|
|
|
|
if ($pkgs = $pkglist->pkgs($pkg))
|
|
|
|
{
|
|
|
|
$fail .= "Version mismatch: '$pkg' $badver vs ".
|
|
|
|
join(',', $pkgs->versions)."\n";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ $fail .= "Unknown package: '$pkg' version $badver\n"; }
|
|
|
|
}
|
2001-12-27 20:13:13 +01:00
|
|
|
else
|
|
|
|
{ $ok = 1; } # If we find one match, don't bitch about others
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
2001-12-27 20:13:13 +01:00
|
|
|
$ok && ($fail = undef);
|
1999-04-19 09:32:09 +02:00
|
|
|
$fail;
|
|
|
|
}
|
|
|
|
|
1999-06-05 02:32:39 +02:00
|
|
|
# List (recursive) non directory contents of specified directory
|
1999-04-19 09:32:09 +02:00
|
|
|
#
|
|
|
|
sub listdir
|
|
|
|
{
|
1999-12-16 12:59:13 +01:00
|
|
|
my($base, $dir) = @_;
|
2001-12-27 13:42:08 +01:00
|
|
|
my($thisdir);
|
1999-12-16 12:59:13 +01:00
|
|
|
my(@list, @thislist);
|
1999-04-19 09:32:09 +02:00
|
|
|
|
1999-12-16 12:59:13 +01:00
|
|
|
$thisdir = $base;
|
1999-04-19 09:32:09 +02:00
|
|
|
if (defined($dir))
|
|
|
|
{
|
1999-12-16 12:59:13 +01:00
|
|
|
$thisdir .= "/$dir";
|
|
|
|
$dir .= '/';
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
|
|
|
else
|
1999-12-16 12:59:13 +01:00
|
|
|
{ $dir = ''; }
|
2001-12-27 13:42:08 +01:00
|
|
|
opendir(DIR, $thisdir) || fail("Unable to opendir($thisdir): $!");
|
1999-12-16 12:59:13 +01:00
|
|
|
@thislist = grep(substr($_, 0, 1) ne '.' && $_ ne 'CVS', readdir(DIR));
|
1999-04-19 09:32:09 +02:00
|
|
|
closedir(DIR);
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $entry (@thislist)
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
|
|
|
if (-d "$thisdir/$entry")
|
2001-12-27 13:42:08 +01:00
|
|
|
{ push(@list, listdir($base, "$dir$entry")); }
|
1999-04-19 09:32:09 +02:00
|
|
|
else
|
1999-12-16 12:59:13 +01:00
|
|
|
{ push(@list, "$dir$entry"); }
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
|
|
|
@list;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Use pkg_info to list installed packages
|
|
|
|
#
|
|
|
|
sub list_installed_packages
|
|
|
|
{
|
|
|
|
my(@pkgs);
|
2002-03-22 16:57:53 +01:00
|
|
|
my $pkgver;
|
1999-04-19 09:32:09 +02:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
open(PKG_INFO, 'pkg_info -a|') || fail("Unable to run pkg_info: $!");
|
1999-04-19 09:32:09 +02:00
|
|
|
while ( <PKG_INFO> )
|
1999-12-16 12:59:13 +01:00
|
|
|
{ push(@pkgs, (split)[0]); }
|
1999-04-19 09:32:09 +02:00
|
|
|
close(PKG_INFO);
|
2002-03-22 16:57:53 +01:00
|
|
|
|
|
|
|
# pkg_install is not in the pkg_info -a output, add it manually
|
|
|
|
$pkgver = `pkg_info -V 2>/dev/null || echo 20010302`;
|
|
|
|
chomp($pkgver);
|
|
|
|
push(@pkgs, "pkg_install-$pkgver");
|
1999-04-19 09:32:09 +02:00
|
|
|
@pkgs;
|
|
|
|
}
|
|
|
|
|
|
|
|
# List top level pkgsrc categories
|
|
|
|
#
|
|
|
|
sub list_pkgsrc_categories
|
|
|
|
{
|
1999-12-16 12:59:13 +01:00
|
|
|
my($pkgsrcdir) = @_;
|
1999-04-19 09:32:09 +02:00
|
|
|
my(@categories);
|
|
|
|
|
1999-12-16 12:59:13 +01:00
|
|
|
opendir(BASE, $pkgsrcdir) || die("Unable to opendir($pkgsrcdir): $!");
|
2000-09-11 12:39:04 +02:00
|
|
|
@categories = grep(substr($_, 0, 1) ne '.' && $_ ne 'CVS' &&
|
|
|
|
-f "$pkgsrcdir/$_/Makefile", readdir(BASE));
|
1999-04-19 09:32:09 +02:00
|
|
|
closedir(BASE);
|
|
|
|
@categories;
|
|
|
|
}
|
|
|
|
|
2000-09-11 12:39:04 +02:00
|
|
|
# For a given category, list potentially valid pkgdirs
|
|
|
|
#
|
|
|
|
sub list_pkgsrc_pkgdirs
|
|
|
|
{
|
2000-09-26 17:57:05 +02:00
|
|
|
my($pkgsrcdir, $cat) = @_;
|
2000-09-11 12:39:04 +02:00
|
|
|
my(@pkgdirs);
|
|
|
|
|
|
|
|
if (! opendir(CAT, "$pkgsrcdir/$cat"))
|
2000-09-26 17:57:05 +02:00
|
|
|
{ die("Unable to opendir($pkgsrcdir/cat): $!"); }
|
2000-09-11 12:39:04 +02:00
|
|
|
@pkgdirs = sort grep($_ ne 'Makefile' && $_ ne 'pkg' && $_ ne 'CVS' &&
|
|
|
|
substr($_, 0, 1) ne '.', readdir(CAT));
|
|
|
|
close(CAT);
|
|
|
|
@pkgdirs;
|
|
|
|
}
|
|
|
|
|
2000-08-28 16:14:59 +02:00
|
|
|
sub glob2regex
|
|
|
|
{
|
|
|
|
my($glob) = @_;
|
|
|
|
my(@chars, $in_alt);
|
|
|
|
my($regex);
|
|
|
|
|
|
|
|
@chars = split(//, $glob);
|
|
|
|
while (defined($_ = shift @chars))
|
|
|
|
{
|
|
|
|
if ($_ eq '*')
|
|
|
|
{ $regex .= '.*'; }
|
|
|
|
elsif ($_ eq '?')
|
|
|
|
{ $regex .= '.'; }
|
2001-05-30 18:44:46 +02:00
|
|
|
elsif ($_ eq '+')
|
|
|
|
{ $regex .= '.'; }
|
|
|
|
elsif ($_ eq '\\+')
|
2000-08-28 16:14:59 +02:00
|
|
|
{ $regex .= $_ . shift @chars; }
|
|
|
|
elsif ($_ eq '.' || $_ eq '|' )
|
|
|
|
{ $regex .= quotemeta; }
|
|
|
|
elsif ($_ eq '{' )
|
2000-11-17 13:45:30 +01:00
|
|
|
{ $regex .= '('; ++$in_alt; }
|
2000-08-28 16:14:59 +02:00
|
|
|
elsif ($_ eq '}' )
|
2000-09-20 08:39:27 +02:00
|
|
|
{
|
2000-09-23 00:41:07 +02:00
|
|
|
if (!$in_alt) # Error
|
|
|
|
{ return undef; }
|
|
|
|
$regex .= ')';
|
2000-11-17 13:45:30 +01:00
|
|
|
--$in_alt;
|
2000-09-20 08:39:27 +02:00
|
|
|
}
|
2000-08-28 16:14:59 +02:00
|
|
|
elsif ($_ eq ',' && $in_alt)
|
|
|
|
{ $regex .= '|'; }
|
|
|
|
else
|
|
|
|
{ $regex .= $_; }
|
|
|
|
}
|
2000-09-23 00:41:07 +02:00
|
|
|
if ($in_alt) # Error
|
|
|
|
{ return undef; }
|
|
|
|
if ($regex eq $glob)
|
|
|
|
{ return(''); }
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($opt{D})
|
2000-11-17 13:45:30 +01:00
|
|
|
{ print "glob2regex: $glob -> $regex\n"; }
|
2000-09-23 00:41:07 +02:00
|
|
|
'^'.$regex.'$';
|
2000-08-28 16:14:59 +02:00
|
|
|
}
|
|
|
|
|
1999-12-18 15:39:20 +01:00
|
|
|
# Perform some (reasonable) subset of 'pkg_info -e' / glob(3)
|
1999-12-22 22:04:17 +01:00
|
|
|
# Returns (sometimes best guess at) package name,
|
|
|
|
# and either 'problem version' or undef if all OK
|
1999-12-18 15:39:20 +01:00
|
|
|
#
|
|
|
|
sub package_globmatch
|
|
|
|
{
|
1999-12-22 22:04:17 +01:00
|
|
|
my($pkgmatch) = @_;
|
2000-09-23 00:41:07 +02:00
|
|
|
my($matchpkgname, $matchver, $regex);
|
1999-12-18 15:39:20 +01:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
if ($pkgmatch =~ /^([^*?[]+)(<|>|<=|>=|-)(\d[^*?[{]*)$/)
|
2000-09-23 00:41:07 +02:00
|
|
|
{ # (package)(cmp)(dewey)
|
2001-12-27 13:42:08 +01:00
|
|
|
my($test, @pkgvers);
|
2000-09-23 00:41:07 +02:00
|
|
|
|
|
|
|
($matchpkgname, $test, $matchver) = ($1, $2, $3);
|
|
|
|
|
2002-06-02 23:52:28 +02:00
|
|
|
if ($test ne '-' && $matchver !~ /^[\d.]+(pl\d+|p\d+|rc\d+|nb\d+|)*$/ )
|
2000-09-23 00:41:07 +02:00
|
|
|
{ $matchver = "invalid-dewey($test$matchver)"; }
|
2001-12-27 13:42:08 +01:00
|
|
|
elsif (@pkgvers = $pkglist->pkgver($matchpkgname))
|
2000-09-23 00:41:07 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $pkgver (@pkgvers)
|
2000-09-23 00:41:07 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
if ($test eq '-')
|
2000-09-23 00:41:07 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
if ($pkgver->ver eq $matchver)
|
|
|
|
{ $matchver = undef; last }
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (deweycmp($pkgver->ver, $test, $matchver))
|
2000-09-23 00:41:07 +02:00
|
|
|
{ $matchver = undef; last }
|
|
|
|
}
|
|
|
|
}
|
2001-12-27 13:42:08 +01:00
|
|
|
if ($matchver && $test ne '-')
|
|
|
|
{ $matchver = "$test$matchver"; }
|
2000-09-23 00:41:07 +02:00
|
|
|
}
|
|
|
|
}
|
2001-12-27 13:42:08 +01:00
|
|
|
elsif ( $pkgmatch =~ /^([^[]+)-([\d*?{[].*)$/ ) # }
|
1999-12-22 22:04:17 +01:00
|
|
|
{ # (package)-(globver)
|
2001-12-27 13:42:08 +01:00
|
|
|
my(@pkgnames);
|
2000-09-23 00:41:07 +02:00
|
|
|
|
2000-08-28 16:14:59 +02:00
|
|
|
($matchpkgname, $matchver) = ($1, $2);
|
1999-12-22 22:04:17 +01:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
if (defined $pkglist->pkgs($matchpkgname))
|
2000-08-28 16:14:59 +02:00
|
|
|
{ push(@pkgnames, $matchpkgname); }
|
2000-09-23 00:41:07 +02:00
|
|
|
elsif ($regex = glob2regex($matchpkgname))
|
1999-12-18 15:39:20 +01:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $pkg ($pkglist->pkgs)
|
|
|
|
{ ($pkg->pkg() =~ /$regex/) && push(@pkgnames, $pkg->pkg()); }
|
2000-08-28 16:14:59 +02:00
|
|
|
}
|
2000-11-17 13:45:30 +01:00
|
|
|
|
|
|
|
# Try to convert $matchver into regex version
|
|
|
|
#
|
|
|
|
$regex = glob2regex($matchver);
|
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $pkg (@pkgnames)
|
2000-08-28 16:14:59 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
if (defined $pkglist->pkgver($pkg, $matchver))
|
2000-08-28 16:14:59 +02:00
|
|
|
{ return($matchver); }
|
|
|
|
|
2000-11-17 13:45:30 +01:00
|
|
|
if ($regex)
|
2000-08-28 16:14:59 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $ver ($pkglist->pkgs($pkg)->versions)
|
2000-09-23 00:41:07 +02:00
|
|
|
{
|
|
|
|
if( $ver =~ /$regex/ )
|
|
|
|
{ $matchver = undef; last }
|
|
|
|
}
|
1999-12-22 22:04:17 +01:00
|
|
|
}
|
2000-08-28 16:14:59 +02:00
|
|
|
$matchver || last;
|
1999-12-22 22:04:17 +01:00
|
|
|
}
|
2000-11-17 13:45:30 +01:00
|
|
|
|
2000-09-23 00:41:07 +02:00
|
|
|
# last ditch attempt to handle the whole DEPENDS as a glob
|
2000-11-17 13:45:30 +01:00
|
|
|
#
|
2000-09-23 00:41:07 +02:00
|
|
|
if ($matchver && ($regex = glob2regex($pkgmatch))) # (large-glob)
|
1999-12-22 22:04:17 +01:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $pkgver ($pkglist->pkgver)
|
2000-08-28 16:14:59 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
if( $pkgver->pkgname =~ /$regex/ )
|
2001-12-27 14:31:45 +01:00
|
|
|
{ $matchver = undef; last }
|
2000-08-28 16:14:59 +02:00
|
|
|
}
|
1999-12-18 15:39:20 +01:00
|
|
|
}
|
|
|
|
}
|
1999-12-22 22:04:17 +01:00
|
|
|
else
|
2000-08-28 16:14:59 +02:00
|
|
|
{ ($matchpkgname, $matchver) = ($pkgmatch, 'missing'); }
|
|
|
|
($matchpkgname, $matchver);
|
1999-12-18 15:39:20 +01:00
|
|
|
}
|
|
|
|
|
2000-09-11 12:39:04 +02:00
|
|
|
# Parse a pkgsrc package makefile and return the pkgname and set variables
|
|
|
|
#
|
|
|
|
sub parse_makefile_pkgsrc
|
|
|
|
{
|
|
|
|
my($file) = @_;
|
|
|
|
my($pkgname, $vars);
|
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
$vars = parse_makefile_vars($file);
|
2000-09-11 12:39:04 +02:00
|
|
|
|
|
|
|
if (!$vars) # Missing Makefile
|
|
|
|
{ return(undef); }
|
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
if (defined $vars->{PKGNAME})
|
|
|
|
{ $pkgname = $vars->{PKGNAME}; }
|
|
|
|
elsif (defined $vars->{DISTNAME})
|
2001-12-27 13:42:08 +01:00
|
|
|
{ $pkgname = $vars->{DISTNAME}; }
|
2000-09-11 12:39:04 +02:00
|
|
|
if (defined $pkgname)
|
|
|
|
{
|
2001-12-03 22:55:48 +01:00
|
|
|
if (defined $vars->{PKGREVISION}
|
|
|
|
and not $vars->{PKGREVISION} =~ /^\s*$/ )
|
2001-12-03 18:52:24 +01:00
|
|
|
{
|
|
|
|
$pkgname .= "nb";
|
2001-12-03 19:20:49 +01:00
|
|
|
$pkgname .= $vars->{PKGREVISION};
|
2001-12-03 18:52:24 +01:00
|
|
|
}
|
2000-09-11 12:39:04 +02:00
|
|
|
if ( $pkgname =~ /\$/ )
|
|
|
|
{ print "\rBogus: $pkgname (from $file)\n"; }
|
2000-09-20 08:39:27 +02:00
|
|
|
elsif ($pkgname =~ /(.*)-(\d.*)/)
|
2000-09-11 12:39:04 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
if ($pkglist)
|
2000-09-23 00:41:07 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
my($pkgver) = $pkglist->add($1, $2);
|
|
|
|
|
|
|
|
foreach my $var (qw(DEPENDS RESTRICTED OSVERSION_SPECIFIC BROKEN))
|
|
|
|
{ $pkgver->var($var, $vars->{$var}); }
|
|
|
|
if (defined $vars->{NO_BIN_ON_FTP})
|
|
|
|
{ $pkgver->var('RESTRICTED', 'NO_BIN_ON_FTP'); }
|
|
|
|
if ($file =~ m:([^/]+/[^/]+)/Makefile$:)
|
|
|
|
{ $pkgver->var('dir', $1); }
|
|
|
|
else
|
|
|
|
{ $pkgver->var('dir', 'unknown'); }
|
2000-09-23 00:41:07 +02:00
|
|
|
}
|
2000-09-11 12:39:04 +02:00
|
|
|
}
|
2001-12-27 13:42:08 +01:00
|
|
|
else
|
2001-12-27 14:31:45 +01:00
|
|
|
{ print "Cannot extract $pkgname version ($file)\n"; }
|
2000-09-11 12:39:04 +02:00
|
|
|
return($pkgname, $vars);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ return(undef); }
|
|
|
|
}
|
|
|
|
|
|
|
|
# Extract variable assignments from Makefile
|
1999-04-19 09:32:09 +02:00
|
|
|
# Much unpalatable magic to avoid having to use make (all for speed)
|
|
|
|
#
|
2000-09-11 12:39:04 +02:00
|
|
|
sub parse_makefile_vars
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
1999-12-16 12:59:13 +01:00
|
|
|
my($file) = @_;
|
2001-12-27 13:42:08 +01:00
|
|
|
my($pkgname, %vars, $plus, $value, @data,
|
|
|
|
%incfiles,
|
2000-01-10 03:01:20 +01:00
|
|
|
@if_false); # 0:true 1:false 2:nested-false&nomore-elsif
|
1999-04-19 09:32:09 +02:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
|
1999-12-16 12:59:13 +01:00
|
|
|
if (! open(FILE, $file))
|
|
|
|
{ return(undef); }
|
2000-01-10 03:01:20 +01:00
|
|
|
@data = map {chomp; $_} <FILE>;
|
1999-12-16 12:59:13 +01:00
|
|
|
close(FILE);
|
|
|
|
|
1999-12-16 15:04:19 +01:00
|
|
|
# Some Makefiles depend on these being set
|
2001-05-31 19:37:25 +02:00
|
|
|
if ($file eq '/etc/mk.conf')
|
2001-12-03 19:20:49 +01:00
|
|
|
{ $vars{LINTPKGSRC} = 'YES'; }
|
2001-05-31 19:37:25 +02:00
|
|
|
else
|
2001-05-18 12:38:47 +02:00
|
|
|
{ %vars = %{$default_vars}; }
|
2001-12-03 19:20:49 +01:00
|
|
|
$vars{BSD_PKG_MK} = 'YES';
|
2001-05-31 19:37:25 +02:00
|
|
|
|
1999-12-18 15:39:20 +01:00
|
|
|
if ($file =~ m#(.*)/#)
|
|
|
|
{ $vars{'.CURDIR'} = $1; }
|
2001-12-03 19:20:49 +01:00
|
|
|
else
|
|
|
|
{ $vars{'.CURDIR'} = getcwd; }
|
|
|
|
if ($opt{L})
|
2000-01-14 02:02:01 +01:00
|
|
|
{ print "$file\n"; }
|
1999-12-16 15:04:19 +01:00
|
|
|
|
2000-01-10 03:01:20 +01:00
|
|
|
while( defined($_ = shift(@data)) )
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-12-11 04:47:20 +01:00
|
|
|
s/\s*#.*//;
|
1999-12-22 22:04:17 +01:00
|
|
|
|
|
|
|
# Continuation lines
|
|
|
|
#
|
2000-01-26 16:25:25 +01:00
|
|
|
while ( substr($_, -1) eq "\\" )
|
|
|
|
{ substr($_, -2) = shift @data; }
|
1999-12-22 22:04:17 +01:00
|
|
|
|
|
|
|
# Conditionals
|
|
|
|
#
|
2000-01-10 03:01:20 +01:00
|
|
|
if (m#^\.if(|def|ndef)\s+(.*)#)
|
1999-12-22 22:04:17 +01:00
|
|
|
{
|
2000-01-10 03:01:20 +01:00
|
|
|
my($type, $false);
|
|
|
|
|
|
|
|
$type = $1;
|
|
|
|
if ($if_false[$#if_false])
|
|
|
|
{ push(@if_false, 2); }
|
|
|
|
elsif( $type eq '') # Straight if
|
2001-12-27 13:42:08 +01:00
|
|
|
{ push(@if_false, parse_eval_make_false($2, \%vars)); }
|
1999-12-22 22:04:17 +01:00
|
|
|
else
|
|
|
|
{
|
2000-01-10 03:01:20 +01:00
|
|
|
$false = ! defined($vars{parse_expand_vars($2, \%vars)});
|
|
|
|
if ( $type eq 'ndef' )
|
|
|
|
{ $false = ! $false ; }
|
|
|
|
push(@if_false, $false ?1 :0);
|
1999-12-22 22:04:17 +01:00
|
|
|
}
|
2000-01-10 03:01:20 +01:00
|
|
|
debug("$file: .if$type (@if_false)\n");
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
if (m#^\.elif\s+(.*)# && @if_false)
|
|
|
|
{
|
|
|
|
if ($if_false[$#if_false] == 0)
|
|
|
|
{ $if_false[$#if_false] = 2; }
|
|
|
|
elsif ($if_false[$#if_false] == 1 &&
|
2001-12-27 13:42:08 +01:00
|
|
|
! parse_eval_make_false($1, \%vars) )
|
2000-01-10 03:01:20 +01:00
|
|
|
{ $if_false[$#if_false] = 0; }
|
|
|
|
debug("$file: .elif (@if_false)\n");
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
if (m#^\.else\b# && @if_false)
|
|
|
|
{
|
2002-06-02 23:52:28 +02:00
|
|
|
$if_false[$#if_false] = $if_false[$#if_false] == 1?0:1;
|
2000-01-10 03:01:20 +01:00
|
|
|
debug("$file: .else (@if_false)\n");
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
if (m#^\.endif\b#)
|
|
|
|
{
|
|
|
|
pop(@if_false);
|
|
|
|
debug("$file: .endif (@if_false)\n");
|
|
|
|
next;
|
1999-12-22 22:04:17 +01:00
|
|
|
}
|
|
|
|
|
2000-01-10 03:01:20 +01:00
|
|
|
$if_false[$#if_false] && next;
|
1999-12-22 22:04:17 +01:00
|
|
|
|
|
|
|
# Included files (just unshift onto @data)
|
|
|
|
#
|
|
|
|
if (m#^\.include\s+"([^"]+)"#)
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
1999-12-16 12:59:13 +01:00
|
|
|
$_ = $1;
|
|
|
|
if (! m#/mk/#)
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
my($incfile) = ($_);
|
1999-12-18 15:39:20 +01:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
# Expand any simple vars in $incfile
|
1999-12-18 15:39:20 +01:00
|
|
|
#
|
2001-12-27 13:42:08 +01:00
|
|
|
$incfile = parse_expand_vars($incfile, \%vars);
|
1999-12-22 22:04:17 +01:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
# Handle relative path incfile
|
1999-12-18 15:39:20 +01:00
|
|
|
#
|
2001-12-27 13:42:08 +01:00
|
|
|
if (substr($incfile, 0, 1) ne '/')
|
|
|
|
{ $incfile = "$vars{'.CURDIR'}/$incfile"; }
|
|
|
|
if (!$incfiles{$incfile})
|
1999-12-16 12:59:13 +01:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
$incfiles{$incfile} = 1;
|
|
|
|
if (!open(FILE, $incfile))
|
|
|
|
{ verbose("Cannot open '$incfile' (from $file): $!\n");}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unshift(@data, map {chomp; $_} <FILE>);
|
|
|
|
close(FILE);
|
|
|
|
}
|
1999-12-16 12:59:13 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
next;
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
1999-12-16 12:59:13 +01:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
if (/^ *([-\w\.]+)\s*([:+?]?)=\s*(.*)/)
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
my($key);
|
1999-12-16 12:59:13 +01:00
|
|
|
$key = $1;
|
|
|
|
$plus = $2;
|
|
|
|
$value = $3;
|
2001-12-27 13:42:08 +01:00
|
|
|
if ($plus eq ':')
|
|
|
|
{ $vars{$key} = parse_expand_vars($value, \%vars); }
|
|
|
|
elsif ($plus eq '+' && defined $vars{$key} )
|
1999-12-16 15:04:19 +01:00
|
|
|
{ $vars{$key} .= " $value"; }
|
2001-05-18 12:38:47 +02:00
|
|
|
elsif ($plus ne '?' || !defined $vars{$key} )
|
1999-12-16 12:59:13 +01:00
|
|
|
{ $vars{$key} = $value; }
|
|
|
|
}
|
|
|
|
}
|
1999-12-16 15:04:19 +01:00
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
debug("$file: expand\n");
|
2000-08-28 16:14:59 +02:00
|
|
|
|
|
|
|
# Handle variable substitutions FRED = a-${JIM:S/-/-b-/}
|
1999-12-16 15:04:19 +01:00
|
|
|
#
|
|
|
|
my($loop);
|
|
|
|
for ($loop = 1 ; $loop ;)
|
1999-12-16 12:59:13 +01:00
|
|
|
{
|
1999-12-16 15:04:19 +01:00
|
|
|
$loop = 0;
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $key (keys %vars)
|
1999-12-16 12:59:13 +01:00
|
|
|
{
|
2000-08-28 16:14:59 +02:00
|
|
|
if ( index($vars{$key}, '$') == -1 )
|
|
|
|
{ next; }
|
2000-01-14 02:02:01 +01:00
|
|
|
$_ = parse_expand_vars($vars{$key}, \%vars);
|
2000-08-28 16:14:59 +02:00
|
|
|
if ($_ ne $vars{$key})
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2000-01-14 02:02:01 +01:00
|
|
|
$vars{$key} = $_;
|
1999-12-18 15:39:20 +01:00
|
|
|
$loop = 1;
|
1999-12-16 15:04:19 +01:00
|
|
|
}
|
2001-05-01 17:52:50 +02:00
|
|
|
elsif ($vars{$key} =~ m#\${(\w+):([CS]([^{}])[^{}\3]+\3[^{}\3]*\3[g1]*(|:[^{}]+))}#)
|
1999-12-16 15:04:19 +01:00
|
|
|
{
|
2000-09-20 08:39:27 +02:00
|
|
|
my($left, $subvar, $right) = ($`, $1, $');
|
|
|
|
my(@patterns) = split(':', $2);
|
|
|
|
my($result);
|
1999-12-16 15:04:19 +01:00
|
|
|
|
2000-09-20 08:39:27 +02:00
|
|
|
$result = $vars{$subvar};
|
|
|
|
$result ||= '';
|
|
|
|
|
|
|
|
# If $vars{$subvar} contains a $ skip it on this pass.
|
|
|
|
# Hopefully it will get substituted and we can catch it
|
2000-08-28 16:14:59 +02:00
|
|
|
# next time around.
|
2000-09-20 08:39:27 +02:00
|
|
|
if (index($result, '${') != -1)
|
|
|
|
{ next; }
|
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
debug("$file: substitutelist $key ($result) $subvar (@patterns)\n");
|
2000-09-20 08:39:27 +02:00
|
|
|
foreach (@patterns)
|
2000-08-28 16:14:59 +02:00
|
|
|
{
|
2001-05-01 17:52:50 +02:00
|
|
|
if (! m#([CS])/([^/]+)/([^/]*)/([1g]*)#)
|
2000-09-20 08:39:27 +02:00
|
|
|
{ next; }
|
|
|
|
|
|
|
|
my($how, $from, $to, $global) = ($1, $2, $3, $4);
|
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
debug("$file: substituteglob $subvar, $how, $from, $to, $global\n");
|
2000-09-21 12:28:44 +02:00
|
|
|
if ($how eq 'S') # Limited substitution - keep ^ and $
|
2000-09-23 00:41:07 +02:00
|
|
|
{ $from =~ s/([?.{}\]\[*+])/\\$1/g; }
|
2000-09-21 12:28:44 +02:00
|
|
|
$to =~ s/\\(\d)/\$$1/g; # Change \1 etc to $1
|
2001-05-01 17:52:50 +02:00
|
|
|
|
|
|
|
my($notfirst);
|
|
|
|
if ($global =~ s/1//)
|
|
|
|
{ ($from, $notfirst) = split('\s', $from, 2); }
|
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
debug("$file: substituteperl $subvar, $how, $from, $to\n");
|
2000-09-21 12:28:44 +02:00
|
|
|
eval "\$result =~ s/$from/$to/$global";
|
2001-05-01 17:52:50 +02:00
|
|
|
if (defined $notfirst)
|
|
|
|
{ $result .= " $notfirst"; }
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
2000-09-20 08:39:27 +02:00
|
|
|
$vars{$key} = $left . $result . $right;
|
|
|
|
$loop = 1;
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-09-11 12:39:04 +02:00
|
|
|
\%vars;
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
|
|
|
|
1999-12-22 22:04:17 +01:00
|
|
|
sub parse_expand_vars
|
|
|
|
{
|
|
|
|
my($line, $vars) = @_;
|
|
|
|
|
2001-12-20 04:31:51 +01:00
|
|
|
while ( $line =~ /\$\{([-\w.]+)\}/ )
|
1999-12-22 22:04:17 +01:00
|
|
|
{
|
|
|
|
if (defined(${$vars}{$1}))
|
|
|
|
{ $line = $`.${$vars}{$1}.$'; }
|
|
|
|
else
|
|
|
|
{ $line = $`.'UNDEFINED'.$'; }
|
|
|
|
}
|
|
|
|
$line;
|
|
|
|
}
|
|
|
|
|
2001-12-27 14:31:45 +01:00
|
|
|
sub parse_expand_vars_dumb
|
|
|
|
{
|
|
|
|
my($line, $vars) = @_;
|
|
|
|
|
|
|
|
while ( $line =~ /\$\{([-\w.]+)\}/ )
|
|
|
|
{
|
|
|
|
if (defined(${$vars}{$1}))
|
|
|
|
{ $line = $`.${$vars}{$1}.$'; }
|
|
|
|
else
|
|
|
|
{ $line = $`.'UNDEFINED'.$'; }
|
|
|
|
}
|
|
|
|
$line;
|
|
|
|
}
|
|
|
|
|
2000-01-10 03:01:20 +01:00
|
|
|
sub parse_eval_make_false
|
|
|
|
{
|
|
|
|
my($line, $vars) = @_;
|
|
|
|
my($false, $test);
|
|
|
|
|
|
|
|
$false = 0;
|
2001-12-27 14:31:45 +01:00
|
|
|
$test = parse_expand_vars_dumb($line, $vars);
|
|
|
|
# XXX This is _so_ wrong - need to parse this correctly
|
2001-12-27 13:42:08 +01:00
|
|
|
$test =~ s/""/\r/g;
|
2000-01-10 03:01:20 +01:00
|
|
|
$test =~ s/"//g;
|
2001-12-27 13:42:08 +01:00
|
|
|
$test =~ s/\r/""/g;
|
2000-01-10 03:01:20 +01:00
|
|
|
|
2000-01-10 16:06:48 +01:00
|
|
|
debug("conditional: $test\n");
|
2001-12-27 14:31:45 +01:00
|
|
|
# XXX Could do something with target and empty
|
|
|
|
while ( $test =~ /(target|empty|make|defined|exists)\s*\(([^()]+)\)/ )
|
2000-01-10 16:06:48 +01:00
|
|
|
{
|
2001-12-27 14:31:45 +01:00
|
|
|
if ($1 eq 'exists')
|
|
|
|
{ $_ = (-e $2) ?1 :0; }
|
|
|
|
elsif( $1 eq 'defined')
|
|
|
|
{ $_ = (defined($${vars}{$2}) ?1 :0); }
|
|
|
|
else
|
|
|
|
{ $_ = 0; }
|
|
|
|
$test =~ s/$1\s*\([^()]+\)/$_/;
|
2000-01-10 16:06:48 +01:00
|
|
|
}
|
2000-09-23 00:41:07 +02:00
|
|
|
while ( $test =~ /([^\s()]+)\s+(!=|==)\s+([^\s()]+)/ )
|
2000-01-10 16:06:48 +01:00
|
|
|
{
|
2000-09-23 00:41:07 +02:00
|
|
|
if ($2 eq '==')
|
|
|
|
{ $_ = ($1 eq $3) ?1 :0; }
|
|
|
|
else
|
|
|
|
{ $_ = ($1 ne $3) ?1 :0; }
|
2001-12-27 13:42:08 +01:00
|
|
|
$test =~ s/[^\s()]+\s+(!=|==)\s+[^\s()]+/$_/;
|
2000-01-10 16:06:48 +01:00
|
|
|
}
|
2001-12-27 14:31:45 +01:00
|
|
|
if ($test !~ /[^<>\d()\s&|.]/ )
|
2001-12-27 13:42:08 +01:00
|
|
|
{
|
|
|
|
$false = eval "($test)?0:1";
|
|
|
|
if (!defined $false)
|
|
|
|
{ fail("Eval failed $line - $test"); }
|
2001-12-27 14:31:45 +01:00
|
|
|
debug("conditional: evaluated to ".($false?0:1)."\n");
|
2001-12-27 13:42:08 +01:00
|
|
|
}
|
2000-01-10 16:06:48 +01:00
|
|
|
else
|
2001-12-27 14:31:45 +01:00
|
|
|
{
|
|
|
|
$false = 0;
|
|
|
|
debug("conditional: defaulting to 0\n");
|
|
|
|
}
|
2000-01-10 03:01:20 +01:00
|
|
|
$false;
|
|
|
|
}
|
|
|
|
|
1999-04-19 09:32:09 +02:00
|
|
|
# Run pkglint on every pkgsrc entry
|
|
|
|
#
|
|
|
|
sub pkglint_all_pkgsrc
|
|
|
|
{
|
1999-12-16 12:59:13 +01:00
|
|
|
my($pkgsrcdir, $pkglint_flags) = @_;
|
2001-12-27 13:42:08 +01:00
|
|
|
my(@categories, @output);
|
1999-04-19 09:32:09 +02:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
@categories = list_pkgsrc_categories($pkgsrcdir);
|
|
|
|
foreach my $cat ( sort @categories )
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-12-03 19:20:49 +01:00
|
|
|
safe_chdir("$pkgsrcdir/$cat");
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $pkgdir (list_pkgsrc_pkgdirs($pkgsrcdir, $cat))
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2000-09-11 12:39:04 +02:00
|
|
|
if (-f "$pkgdir/Makefile")
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2000-09-11 12:39:04 +02:00
|
|
|
if (!open(PKGLINT, "cd $pkgdir ; pkglint $pkglint_flags|"))
|
2001-12-27 13:42:08 +01:00
|
|
|
{ fail("Unable to run pkglint: $!"); }
|
1999-12-16 12:59:13 +01:00
|
|
|
@output = grep(!/^OK:/ &&
|
2000-09-05 02:02:15 +02:00
|
|
|
!/^WARN: be sure to cleanup .*work.* before/ &&
|
|
|
|
!/^WARN: is it a new package/ &&
|
1999-04-19 09:32:09 +02:00
|
|
|
!/^\d+ fatal errors and \d+ warnings found/
|
1999-12-16 12:59:13 +01:00
|
|
|
, <PKGLINT> );
|
1999-04-19 09:32:09 +02:00
|
|
|
close(PKGLINT);
|
|
|
|
if (@output)
|
2000-09-11 12:39:04 +02:00
|
|
|
{ print "===> $cat/$pkgdir\n", @output, "\n"; }
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
# chdir() || fail()
|
1999-04-19 09:32:09 +02:00
|
|
|
#
|
|
|
|
sub safe_chdir
|
|
|
|
{
|
1999-12-16 12:59:13 +01:00
|
|
|
my($dir) = @_;
|
1999-04-19 09:32:09 +02:00
|
|
|
|
|
|
|
if (! chdir($dir))
|
2001-12-27 13:42:08 +01:00
|
|
|
{ fail("Unable to chdir($dir): $!"); }
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
# Generate pkgname->category/pkg mapping, optionally check DEPENDS
|
|
|
|
#
|
|
|
|
sub scan_pkgsrc_makefiles
|
|
|
|
{
|
1999-12-16 12:59:13 +01:00
|
|
|
my($pkgsrcdir, $check_depends) = @_;
|
2001-12-27 13:42:08 +01:00
|
|
|
my(@categories);
|
1999-04-19 09:32:09 +02:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
if ($pkglist) # Already done
|
2000-11-14 18:11:42 +01:00
|
|
|
{ return; }
|
2001-12-27 13:42:08 +01:00
|
|
|
$pkglist = new PkgList;
|
|
|
|
@categories = list_pkgsrc_categories($pkgsrcdir);
|
|
|
|
verbose("Scanning pkgsrc Makefiles: ");
|
2001-12-03 19:20:49 +01:00
|
|
|
if (!$opt{L})
|
2001-12-27 13:42:08 +01:00
|
|
|
{ verbose('_'x@categories."\b"x@categories); }
|
2000-01-14 02:02:01 +01:00
|
|
|
else
|
2001-12-27 13:42:08 +01:00
|
|
|
{ verbose("\n"); }
|
1999-12-16 15:04:19 +01:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $cat ( sort @categories )
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $pkgdir (list_pkgsrc_pkgdirs($pkgsrcdir, $cat))
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
my($pkg, $vars) =
|
2001-12-03 19:20:49 +01:00
|
|
|
parse_makefile_pkgsrc("$pkgsrcdir/$cat/$pkgdir/Makefile");
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
2001-12-03 19:20:49 +01:00
|
|
|
if (!$opt{L})
|
2001-12-27 13:42:08 +01:00
|
|
|
{ verbose('.'); }
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
1999-12-18 15:53:32 +01:00
|
|
|
|
2001-12-03 19:20:49 +01:00
|
|
|
if (!$opt{L})
|
2000-01-14 02:02:01 +01:00
|
|
|
{
|
|
|
|
my ($len);
|
2001-12-27 13:42:08 +01:00
|
|
|
$_ = $pkglist->numpkgver().' packages';
|
2000-01-14 02:02:01 +01:00
|
|
|
$len = @categories - length($_);
|
2001-12-27 13:42:08 +01:00
|
|
|
verbose("\b"x@categories, $_, ' 'x$len, "\b"x$len, "\n");
|
2000-01-14 02:02:01 +01:00
|
|
|
}
|
2000-09-23 00:41:07 +02:00
|
|
|
}
|
1999-04-19 09:32:09 +02:00
|
|
|
|
2000-09-23 00:41:07 +02:00
|
|
|
# Cross reference all depends
|
|
|
|
#
|
|
|
|
sub pkgsrc_check_depends
|
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $pkgver ($pkglist->pkgver)
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
my($err, $msg);
|
|
|
|
defined $pkgver->var('DEPENDS') || next;
|
|
|
|
foreach my $depend (split(" ", $pkgver->var('DEPENDS')))
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
$depend =~ s/:.*// || next;
|
|
|
|
if (($msg = invalid_version($depend)))
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
if (!defined($err))
|
|
|
|
{ print $pkgver->pkgname." DEPENDS errors:\n"; }
|
|
|
|
$err = 1;
|
2001-12-27 14:31:45 +01:00
|
|
|
$msg =~ s/(\n)(.)/$1\t$2/g;
|
2001-12-27 13:42:08 +01:00
|
|
|
print "\t$msg";
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-04-17 19:08:41 +02:00
|
|
|
# Extract all distinfo entries, then verify contents of distfiles
|
1999-04-19 09:32:09 +02:00
|
|
|
#
|
2001-04-17 19:08:41 +02:00
|
|
|
sub scan_pkgsrc_distfiles_vs_distinfo
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-04-17 19:08:41 +02:00
|
|
|
my($pkgsrcdir, $pkgdistdir, $check_unref, $check_distinfo) = @_;
|
2001-12-27 13:42:08 +01:00
|
|
|
my(@categories);
|
|
|
|
my(%distfiles, %sumfiles, @distwarn, $numpkg);
|
2001-06-21 17:53:54 +02:00
|
|
|
my(%bad_distfiles);
|
1999-04-19 09:32:09 +02:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
@categories = list_pkgsrc_categories($pkgsrcdir);
|
1999-04-19 09:32:09 +02:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
verbose("Scanning pkgsrc distinfo: ".'_'x@categories."\b"x@categories);
|
1999-12-16 12:59:13 +01:00
|
|
|
$numpkg = 0;
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $cat (sort @categories)
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $pkgdir (list_pkgsrc_pkgdirs($pkgsrcdir, $cat))
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-04-17 19:08:41 +02:00
|
|
|
if (open(DISTINFO, "$pkgsrcdir/$cat/$pkgdir/distinfo"))
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
|
|
|
++$numpkg;
|
2001-04-17 19:08:41 +02:00
|
|
|
while( <DISTINFO> )
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-03-30 18:30:24 +02:00
|
|
|
if (m/^(\w+) ?\(([^\)]+)\) = (\S+)/)
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2002-08-13 17:05:30 +02:00
|
|
|
my($dn,$ds,$dt);
|
2001-11-02 00:24:44 +01:00
|
|
|
if ($2 =~ /^patch-[a-z0-9]+$/)
|
2001-04-17 19:08:41 +02:00
|
|
|
{ next; }
|
2002-08-13 17:05:30 +02:00
|
|
|
$dt = $1;
|
|
|
|
$dn = $2;
|
|
|
|
$ds = $3;
|
|
|
|
# Strip leading ./ which sometimes gets added
|
|
|
|
# because of DISTSUBDIR=.
|
|
|
|
$dn =~ s/^(\.\/)*//;
|
|
|
|
if (!defined $distfiles{$dn})
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2002-08-13 17:05:30 +02:00
|
|
|
$distfiles{$dn}{sumtype} = $dt;
|
|
|
|
$distfiles{$dn}{sum} = $ds;
|
|
|
|
$distfiles{$dn}{path} = "$cat/$pkgdir";
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
2002-08-13 17:05:30 +02:00
|
|
|
elsif ($distfiles{$dn}{sumtype} eq $dt &&
|
|
|
|
$distfiles{$dn}{sum} ne $ds)
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2002-08-13 17:05:30 +02:00
|
|
|
push(@distwarn, "checksum mismatch between '$dt' ".
|
|
|
|
"in $cat/$pkgdir and $distfiles{$dn}{path}\n");
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-04-17 19:08:41 +02:00
|
|
|
close(DISTINFO);
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
|
|
|
}
|
2001-12-27 13:42:08 +01:00
|
|
|
verbose('.');
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
2001-12-27 13:42:08 +01:00
|
|
|
verbose(" ($numpkg packages)\n");
|
1999-04-19 09:32:09 +02:00
|
|
|
|
2000-11-17 13:45:30 +01:00
|
|
|
# Do not mark the vulnerabilities file as unknown
|
2001-12-03 19:20:49 +01:00
|
|
|
$distfiles{vulnerabilities} = { path => 'vulnerabilities',
|
2001-03-30 18:30:24 +02:00
|
|
|
sum => 'IGNORE'};
|
2000-10-12 17:07:41 +02:00
|
|
|
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $file (listdir("$pkgdistdir"))
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-03-30 18:30:24 +02:00
|
|
|
my($dist);
|
|
|
|
if (!defined($dist = $distfiles{$file}))
|
2001-06-21 17:53:54 +02:00
|
|
|
{ $bad_distfiles{$file} = 1; }
|
1999-04-19 09:32:09 +02:00
|
|
|
else
|
2001-03-30 18:30:24 +02:00
|
|
|
{
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($dist->{sum} ne 'IGNORE')
|
|
|
|
{ push(@{$sumfiles{$dist->{sumtype}}}, $file); }
|
2001-03-30 18:30:24 +02:00
|
|
|
}
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
2001-03-30 18:30:24 +02:00
|
|
|
|
2001-06-21 17:53:54 +02:00
|
|
|
if ($check_unref && %bad_distfiles)
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-12-27 13:42:08 +01:00
|
|
|
verbose(scalar(keys %bad_distfiles),
|
2000-05-29 21:44:27 +02:00
|
|
|
" unreferenced file(s) in '$pkgdistdir':\n");
|
2001-06-21 17:53:54 +02:00
|
|
|
print join("\n", sort keys %bad_distfiles), "\n";
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
2001-03-30 18:30:24 +02:00
|
|
|
|
2001-04-17 19:08:41 +02:00
|
|
|
if ($check_distinfo)
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
|
|
|
if (@distwarn)
|
2001-12-27 13:42:08 +01:00
|
|
|
{ verbose(@distwarn); }
|
|
|
|
verbose("checksum mismatches\n");
|
2001-12-03 19:20:49 +01:00
|
|
|
safe_chdir("$pkgdistdir");
|
2001-12-27 13:42:08 +01:00
|
|
|
foreach my $sum (keys %sumfiles)
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-06-21 17:53:54 +02:00
|
|
|
if ($sum eq 'Size')
|
|
|
|
{
|
|
|
|
foreach (@{$sumfiles{$sum}})
|
|
|
|
{
|
2001-12-03 19:20:49 +01:00
|
|
|
if (! -f $_ || -S $_ != $distfiles{$_}{sum})
|
2001-06-21 17:53:54 +02:00
|
|
|
{
|
|
|
|
print $_, " (Size)\n";
|
|
|
|
$bad_distfiles{$_} = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
next;
|
|
|
|
}
|
2001-03-30 18:30:24 +02:00
|
|
|
open(DIGEST, "digest $sum @{$sumfiles{$sum}}|") ||
|
2001-12-27 13:42:08 +01:00
|
|
|
fail("Run digest: $!");
|
2001-03-30 18:30:24 +02:00
|
|
|
while (<DIGEST>)
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-03-30 18:30:24 +02:00
|
|
|
if (m/^$sum ?\(([^\)]+)\) = (\S+)/)
|
1999-04-19 09:32:09 +02:00
|
|
|
{
|
2001-12-03 19:20:49 +01:00
|
|
|
if ($distfiles{$1}{sum} ne $2)
|
2001-03-30 18:30:24 +02:00
|
|
|
{
|
2001-06-21 17:53:54 +02:00
|
|
|
print $1, " ($sum)\n";
|
|
|
|
$bad_distfiles{$1} = 1;
|
2001-03-30 18:30:24 +02:00
|
|
|
}
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
|
|
|
}
|
2001-03-30 18:30:24 +02:00
|
|
|
close(DIGEST);
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
|
|
|
}
|
2001-06-21 17:53:54 +02:00
|
|
|
(sort keys %bad_distfiles);
|
1999-04-19 09:32:09 +02:00
|
|
|
}
|
|
|
|
|
2000-01-10 16:06:48 +01:00
|
|
|
# Remember to update manual page when modifying option list
|
|
|
|
#
|
1999-04-19 09:32:09 +02:00
|
|
|
sub usage_and_exit
|
|
|
|
{
|
2000-11-17 13:45:30 +01:00
|
|
|
print "Usage: lintpkgsrc [opts] [makefiles]
|
1999-12-22 22:04:17 +01:00
|
|
|
opts:
|
2000-11-17 13:45:30 +01:00
|
|
|
-h : This help. [see lintpkgsrc(1) for more information]
|
|
|
|
|
|
|
|
Installed package options: Distfile options:
|
2001-04-17 19:08:41 +02:00
|
|
|
-i : Check version against pkgsrc -m : List distinfo mismatches
|
2001-05-18 12:38:47 +02:00
|
|
|
-u : As -i + fetch dist (may change) -o : List obsolete (no distinfo)
|
2000-11-17 13:45:30 +01:00
|
|
|
|
|
|
|
Prebuilt package options: Makefile options:
|
|
|
|
-p : List old/obsolete -B : List packages marked as 'BROKEN'
|
2001-07-07 20:21:29 +02:00
|
|
|
-O : List OSVERSION_SPECIFIC -d : Check 'DEPENDS' up to date
|
|
|
|
-R : List NO_BIN_ON_FTP/RESTRICTED -S : List packages not in 'SUBDIRS'
|
|
|
|
-V : List known vulnerabilities
|
2000-11-17 13:45:30 +01:00
|
|
|
|
|
|
|
Misc:
|
|
|
|
-g file : Generate 'pkgname pkgdir pkgver' map in file
|
|
|
|
-l : Pkglint all packages
|
|
|
|
-r : Remove bad files (Without -m -o -p or -V implies all, can use -R)
|
|
|
|
|
|
|
|
Modifiers:
|
|
|
|
-K path : Set PACKAGES basedir (default PKGSRCDIR/packages)
|
|
|
|
-M path : Set DISTDIR (default PKGSRCDIR/distfiles)
|
|
|
|
-P path : Set PKGSRCDIR (default /usr/pkgsrc)
|
|
|
|
-D : Debug makefile and glob parsing
|
|
|
|
-L : List each Makefile when scanned
|
1999-04-19 09:32:09 +02:00
|
|
|
";
|
|
|
|
exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub verbose
|
2000-11-17 13:45:30 +01:00
|
|
|
{
|
|
|
|
if (-t STDERR)
|
|
|
|
{ print STDERR @_; }
|
|
|
|
}
|
2000-01-10 03:01:20 +01:00
|
|
|
|
|
|
|
sub debug
|
|
|
|
{
|
2001-12-03 19:20:49 +01:00
|
|
|
($opt{D}) && print STDERR 'DEBUG: ', @_;
|
2000-01-10 03:01:20 +01:00
|
|
|
}
|
2001-12-27 13:42:08 +01:00
|
|
|
|
|
|
|
# PkgList is the master list of all packages in pkgsrc.
|
|
|
|
#
|
|
|
|
package PkgList;
|
|
|
|
|
|
|
|
sub add
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
if (!$self->pkgs($_[0]))
|
|
|
|
{ $self->{_pkgs}{$_[0]} = new Pkgs $_[0]; }
|
|
|
|
$self->pkgs($_[0])->add(@_);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub new
|
|
|
|
{
|
|
|
|
my $class = shift;
|
|
|
|
my $self = {};
|
|
|
|
bless $self, $class;
|
|
|
|
return $self;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub numpkgver
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
scalar($self->pkgver);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub pkgver
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
if (@_ == 0)
|
|
|
|
{
|
|
|
|
my(@list);
|
|
|
|
foreach my $pkg ($self->pkgs)
|
|
|
|
{ push(@list, $pkg->pkgver); }
|
|
|
|
return (@list);
|
|
|
|
}
|
|
|
|
if (defined $self->{_pkgs}{$_[0]})
|
|
|
|
{
|
|
|
|
return (@_>1)?$self->{_pkgs}{$_[0]}->pkgver($_[1])
|
|
|
|
:$self->{_pkgs}{$_[0]}->pkgver();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub pkgs
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
if(@_)
|
|
|
|
{ return $self->{_pkgs}{$_[0]} }
|
|
|
|
else
|
|
|
|
{ return (sort {$a->pkg cmp $b->pkg} values %{$self->{_pkgs}}); }
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Pkgs is all versions of a given package (eg: apache-1.x and apache-2.x)
|
|
|
|
#
|
|
|
|
package Pkgs;
|
|
|
|
|
|
|
|
sub add
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
$self->{_pkgver}{$_[1]} = new PkgVer @_;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub new
|
|
|
|
{
|
|
|
|
my $class = shift;
|
|
|
|
my $self = {};
|
|
|
|
bless $self, $class;
|
|
|
|
$self->{_pkg} = $_[0];
|
|
|
|
return $self;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub versions
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
return sort {$b cmp $a} keys %{$self->{_pkgver}};
|
|
|
|
}
|
|
|
|
|
|
|
|
sub pkg
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
$self->{_pkg};
|
|
|
|
}
|
|
|
|
|
|
|
|
sub pkgver
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
if (@_)
|
|
|
|
{
|
|
|
|
if ($self->{_pkgver}{$_[0]})
|
|
|
|
{ return ($self->{_pkgver}{$_[0]}) }
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
return sort {$b->ver() cmp $a->ver()} values %{$self->{_pkgver}};
|
|
|
|
}
|
|
|
|
|
|
|
|
sub latestver
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
($self->pkgver())[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
# PkgVer is a unique package+version
|
|
|
|
#
|
|
|
|
package PkgVer;
|
|
|
|
|
|
|
|
sub new
|
|
|
|
{
|
|
|
|
my $class = shift;
|
|
|
|
my $self = {};
|
|
|
|
bless $self, $class;
|
|
|
|
$self->{_pkg} = $1;
|
|
|
|
$self->{_ver} = $2;
|
|
|
|
return $self;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub pkgname
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
$self->pkg.'-'.$self->ver;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub pkg
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
$self->{_pkg};
|
|
|
|
}
|
|
|
|
|
|
|
|
sub var
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
my($key, $val) = @_;
|
|
|
|
(defined $val) ? ($self->{$key} = $val)
|
|
|
|
: $self->{$key};
|
|
|
|
}
|
|
|
|
|
|
|
|
sub ver
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
$self->{_ver};
|
|
|
|
}
|