Thu Dec 17 16:17:45 2020 UTC ()
pkgtools/lintpkgsrc: update to 4.96

Changes since 4.95:

Do not complain about "Bogus: ${_SVN_PKGREVISION:...}" that are
generated by wip/mk/*-package.mk.  Using PKGREVISION to track the
current date of the package is the wrong approach; PKGVERSION_NOREV
should be used instead.  Anyway, this is nothing the average pkgsrc user
should be worried about, so shut up the warning for now.

https://mail-index.netbsd.org/pkgsrc-users/2020/12/16/msg032884.html


(rillig)
diff -r1.34 -r1.35 pkgsrc/pkgtools/lintpkgsrc/Makefile
diff -r1.19 -r1.20 pkgsrc/pkgtools/lintpkgsrc/files/lintpkgsrc.pl

cvs diff -r1.34 -r1.35 pkgsrc/pkgtools/lintpkgsrc/Makefile (switch to unified diff)

--- pkgsrc/pkgtools/lintpkgsrc/Makefile 2020/08/31 18:10:58 1.34
+++ pkgsrc/pkgtools/lintpkgsrc/Makefile 2020/12/17 16:17:44 1.35
@@ -1,52 +1,51 @@ @@ -1,52 +1,51 @@
1# $NetBSD: Makefile,v 1.34 2020/08/31 18:10:58 wiz Exp $ 1# $NetBSD: Makefile,v 1.35 2020/12/17 16:17:44 rillig Exp $
2 2
3PKGNAME= lintpkgsrc-4.95 3PKGNAME= lintpkgsrc-4.96
4PKGREVISION= 1 
5CATEGORIES= pkgtools 4CATEGORIES= pkgtools
6 5
7MAINTAINER= pkgsrc-users@NetBSD.org 6MAINTAINER= pkgsrc-users@NetBSD.org
8HOMEPAGE= https://www.NetBSD.org/Documentation/pkgsrc/ 7HOMEPAGE= https://www.NetBSD.org/Documentation/pkgsrc/
9COMMENT= Sanity checks on the complete pkgsrc tree 8COMMENT= Sanity checks on the complete pkgsrc tree
10 9
11DEPENDS+= digest>=20010101:../../pkgtools/digest 10DEPENDS+= digest>=20010101:../../pkgtools/digest
12CONFLICTS+= pkglint<4.82 11CONFLICTS+= pkglint<4.82
13 12
14USE_TOOLS+= perl:run 13USE_TOOLS+= perl:run
15 14
16WRKSRC= ${WRKDIR} 15WRKSRC= ${WRKDIR}
17NO_BUILD= yes 16NO_BUILD= yes
18USE_LANGUAGES= # none 17USE_LANGUAGES= # none
19AUTO_MKDIRS= yes 18AUTO_MKDIRS= yes
20 19
21SUBST_CLASSES+= lp 20SUBST_CLASSES+= lp
22SUBST_STAGE.lp= post-configure 21SUBST_STAGE.lp= post-configure
23SUBST_FILES.lp+= lintpkgsrc.0 lintpkgsrc.1 lintpkgsrc.pl 22SUBST_FILES.lp+= lintpkgsrc.0 lintpkgsrc.1 lintpkgsrc.pl
24.if defined(BATCH) 23.if defined(BATCH)
25SUBST_SED.lp+= -e 's;@PKGSRCDIR@;/usr/pkgsrc;g' 24SUBST_SED.lp+= -e 's;@PKGSRCDIR@;/usr/pkgsrc;g'
26.else 25.else
27SUBST_VARS.lp+= PKGSRCDIR 26SUBST_VARS.lp+= PKGSRCDIR
28.endif 27.endif
29SUBST_VARS.lp+= MAKE 28SUBST_VARS.lp+= MAKE
30SUBST_VARS.lp+= PERL5 29SUBST_VARS.lp+= PERL5
31SUBST_VARS.lp+= PKG_SYSCONFDIR 30SUBST_VARS.lp+= PKG_SYSCONFDIR
32SUBST_VARS.lp+= PREFIX 31SUBST_VARS.lp+= PREFIX
33 32
34.include "../../mk/bsd.prefs.mk" 33.include "../../mk/bsd.prefs.mk"
35 34
36do-extract: 35do-extract:
37 cd ${FILESDIR} && cp lintpkgsrc.* ${WRKSRC}/ 36 cd ${FILESDIR} && cp lintpkgsrc.* ${WRKSRC}/
38 37
39do-install: 38do-install:
40 ${INSTALL_SCRIPT} ${WRKSRC}/lintpkgsrc.pl ${DESTDIR}${PREFIX}/bin/lintpkgsrc 39 ${INSTALL_SCRIPT} ${WRKSRC}/lintpkgsrc.pl ${DESTDIR}${PREFIX}/bin/lintpkgsrc
41.if !empty(MANINSTALL:Mcatinstall) 40.if !empty(MANINSTALL:Mcatinstall)
42. if defined(CATMAN_SECTION_SUFFIX) && !empty(CATMAN_SECTION_SUFFIX:M[Yy][Ee][Ss]) 41. if defined(CATMAN_SECTION_SUFFIX) && !empty(CATMAN_SECTION_SUFFIX:M[Yy][Ee][Ss])
43 ${INSTALL_MAN} ${WRKSRC}/lintpkgsrc.0 ${DESTDIR}${PREFIX}/${PKGMANDIR}/cat1/lintpkgsrc.1 42 ${INSTALL_MAN} ${WRKSRC}/lintpkgsrc.0 ${DESTDIR}${PREFIX}/${PKGMANDIR}/cat1/lintpkgsrc.1
44. else 43. else
45 ${INSTALL_MAN} ${WRKSRC}/lintpkgsrc.0 ${DESTDIR}${PREFIX}/${PKGMANDIR}/cat1 44 ${INSTALL_MAN} ${WRKSRC}/lintpkgsrc.0 ${DESTDIR}${PREFIX}/${PKGMANDIR}/cat1
46. endif 45. endif
47.endif 46.endif
48.if !empty(MANINSTALL:Mmaninstall) 47.if !empty(MANINSTALL:Mmaninstall)
49 ${INSTALL_MAN} ${WRKSRC}/lintpkgsrc.1 ${DESTDIR}${PREFIX}/${PKGMANDIR}/man1 48 ${INSTALL_MAN} ${WRKSRC}/lintpkgsrc.1 ${DESTDIR}${PREFIX}/${PKGMANDIR}/man1
50.endif 49.endif
51 50
52.include "../../mk/bsd.pkg.mk" 51.include "../../mk/bsd.pkg.mk"

cvs diff -r1.19 -r1.20 pkgsrc/pkgtools/lintpkgsrc/files/lintpkgsrc.pl (switch to unified diff)

--- pkgsrc/pkgtools/lintpkgsrc/files/lintpkgsrc.pl 2020/12/17 16:08:44 1.19
+++ pkgsrc/pkgtools/lintpkgsrc/files/lintpkgsrc.pl 2020/12/17 16:17:45 1.20
@@ -1,1954 +1,1957 @@ @@ -1,1954 +1,1957 @@
1#!@PERL5@ 1#!@PERL5@
2 2
3# $NetBSD: lintpkgsrc.pl,v 1.19 2020/12/17 16:08:44 rillig Exp $ 3# $NetBSD: lintpkgsrc.pl,v 1.20 2020/12/17 16:17:45 rillig Exp $
4 4
5# Written by David Brownlee <abs@netbsd.org>. 5# Written by David Brownlee <abs@netbsd.org>.
6# 6#
7# Caveats: 7# Caveats:
8# The 'Makefile parsing' algorithm used to obtain package versions and 8# The 'Makefile parsing' algorithm used to obtain package versions and
9# DEPENDS information is geared towards speed rather than perfection, 9# DEPENDS information is geared towards speed rather than perfection,
10# though it has gotten somewhat better over time, it only parses the 10# though it has gotten somewhat better over time, it only parses the
11# simpler Makefile conditionals. 11# simpler Makefile conditionals.
12# 12#
13# TODO: Handle fun DEPENDS like avifile-devel with 13# TODO: Handle fun DEPENDS like avifile-devel with
14# {qt2-designer>=2.2.4,qt2-designer-kde>=2.3.1nb1} 14# {qt2-designer>=2.2.4,qt2-designer-kde>=2.3.1nb1}
15 15
16$^W = 1; 16$^W = 1;
17use locale; 17use locale;
18use strict; 18use strict;
19use Getopt::Std; 19use Getopt::Std;
20use File::Find; 20use File::Find;
21use File::Basename; 21use File::Basename;
22use IPC::Open3; 22use IPC::Open3;
23use Cwd 'realpath', 'getcwd'; 23use Cwd 'realpath', 'getcwd';
24 24
25# Buildtime configuration 25# Buildtime configuration
26my $conf_make = '@MAKE@'; 26my $conf_make = '@MAKE@';
27my $conf_pkgsrcdir = '@PKGSRCDIR@'; 27my $conf_pkgsrcdir = '@PKGSRCDIR@';
28my $conf_prefix = '@PREFIX@'; 28my $conf_prefix = '@PREFIX@';
29my $conf_sysconfdir = '@PKG_SYSCONFDIR@'; 29my $conf_sysconfdir = '@PKG_SYSCONFDIR@';
30 30
31my ( 31my (
32 $pkglist, # list of Pkg packages 32 $pkglist, # list of Pkg packages
33 $pkg_installver, # installed version of pkg_install pseudo-pkg 33 $pkg_installver, # installed version of pkg_install pseudo-pkg
34 $default_vars, # Set for Makefiles, inc PACKAGES & PKGSRCDIR 34 $default_vars, # Set for Makefiles, inc PACKAGES & PKGSRCDIR
35 %opt, # Command line options 35 %opt, # Command line options
36 @matched_prebuiltpackages, # List of obsolete prebuilt package paths 36 @matched_prebuiltpackages, # List of obsolete prebuilt package paths
37 @prebuilt_pkgdirs, # Use to follow symlinks in prebuilt pkgdirs 37 @prebuilt_pkgdirs, # Use to follow symlinks in prebuilt pkgdirs
38 %prebuilt_pkgdir_cache, # To avoid symlink loops in prebuilt_pkgdirs 38 %prebuilt_pkgdir_cache, # To avoid symlink loops in prebuilt_pkgdirs
39); 39);
40 40
41$ENV{PATH} .= 41$ENV{PATH} .=
42 ":/bin:/usr/bin:/sbin:/usr/sbin:${conf_prefix}/sbin:${conf_prefix}/bin"; 42 ":/bin:/usr/bin:/sbin:/usr/sbin:${conf_prefix}/sbin:${conf_prefix}/bin";
43 43
44if ( 44if (
45 !getopts( 'BDE:I:K:LM:OP:RSVdg:himopruyz', \%opt ) 45 !getopts( 'BDE:I:K:LM:OP:RSVdg:himopruyz', \%opt )
46 || $opt{h} 46 || $opt{h}
47 || !( 47 || !(
48 defined $opt{d} 48 defined $opt{d}
49 || defined $opt{g} 49 || defined $opt{g}
50 || defined $opt{i} 50 || defined $opt{i}
51 || defined $opt{m} 51 || defined $opt{m}
52 || defined $opt{o} 52 || defined $opt{o}
53 || defined $opt{p} 53 || defined $opt{p}
54 || defined $opt{r} 54 || defined $opt{r}
55 || defined $opt{u} 55 || defined $opt{u}
56 || defined $opt{B} 56 || defined $opt{B}
57 || defined $opt{D} 57 || defined $opt{D}
58 || defined $opt{R} 58 || defined $opt{R}
59 || defined $opt{O} 59 || defined $opt{O}
60 || defined $opt{S} 60 || defined $opt{S}
61 || defined $opt{E} 61 || defined $opt{E}
62 || defined $opt{y} 62 || defined $opt{y}
63 || defined $opt{z} 63 || defined $opt{z}
64 ) 64 )
65 ) 65 )
66{ 66{
67 67
68 usage_and_exit(); 68 usage_and_exit();
69} 69}
70$| = 1; 70$| = 1;
71 71
72# Horrible kludge to ensure we have a value for testing in conditionals, but 72# Horrible kludge to ensure we have a value for testing in conditionals, but
73# gets removed in the final evaluation 73# gets removed in the final evaluation
74my $magic_undefined = 'M_a_G_i_C_uNdEfInEd'; 74my $magic_undefined = 'M_a_G_i_C_uNdEfInEd';
75 75
76get_default_makefile_vars(); # $default_vars 76get_default_makefile_vars(); # $default_vars
77 77
78if ( $opt{D} && @ARGV ) { 78if ( $opt{D} && @ARGV ) {
79 foreach my $file (@ARGV) { 79 foreach my $file (@ARGV) {
80 if ( -d $file ) { 80 if ( -d $file ) {
81 $file .= "/Makefile"; 81 $file .= "/Makefile";
82 } 82 }
83 if ( !-f $file ) { 83 if ( !-f $file ) {
84 fail("No such file: $file"); 84 fail("No such file: $file");
85 } 85 }
86 my ( $pkgname, $vars ) = parse_makefile_pkgsrc($file); 86 my ( $pkgname, $vars ) = parse_makefile_pkgsrc($file);
87 $pkgname ||= 'uNDEFINEd'; 87 $pkgname ||= 'uNDEFINEd';
88 print "$file -> $pkgname\n"; 88 print "$file -> $pkgname\n";
89 foreach my $varname ( sort keys %{$vars} ) { 89 foreach my $varname ( sort keys %{$vars} ) {
90 print "\t$varname = $vars->{$varname}\n"; 90 print "\t$varname = $vars->{$varname}\n";
91 } 91 }
92 92
93 #if ($opt{d}) { 93 #if ($opt{d}) {
94 # pkgsrc_check_depends(); 94 # pkgsrc_check_depends();
95 #} 95 #}
96 } 96 }
97 exit; 97 exit;
98} 98}
99 99
100sub main() { 100sub main() {
101 my ( $pkgsrcdir, $pkgdistdir ); 101 my ( $pkgsrcdir, $pkgdistdir );
102 102
103 $pkgsrcdir = $default_vars->{PKGSRCDIR}; 103 $pkgsrcdir = $default_vars->{PKGSRCDIR};
104 $pkgdistdir = $default_vars->{DISTDIR}; 104 $pkgdistdir = $default_vars->{DISTDIR};
105 105
106 if ( $opt{r} && !$opt{o} && !$opt{m} && !$opt{p} ) { 106 if ( $opt{r} && !$opt{o} && !$opt{m} && !$opt{p} ) {
107 $opt{o} = $opt{m} = $opt{p} = 1; 107 $opt{o} = $opt{m} = $opt{p} = 1;
108 } 108 }
109 if ( $opt{o} || $opt{m} ) { 109 if ( $opt{o} || $opt{m} ) {
110 my (@baddist); 110 my (@baddist);
111 111
112 @baddist = 112 @baddist =
113 scan_pkgsrc_distfiles_vs_distinfo( $pkgsrcdir, $pkgdistdir, $opt{o}, 113 scan_pkgsrc_distfiles_vs_distinfo( $pkgsrcdir, $pkgdistdir, $opt{o},
114 $opt{m} ); 114 $opt{m} );
115 if ( $opt{r} ) { 115 if ( $opt{r} ) {
116 verbose("Unlinking 'bad' distfiles\n"); 116 verbose("Unlinking 'bad' distfiles\n");
117 foreach my $distfile (@baddist) { 117 foreach my $distfile (@baddist) {
118 unlink("$pkgdistdir/$distfile"); 118 unlink("$pkgdistdir/$distfile");
119 } 119 }
120 } 120 }
121 } 121 }
122 122
123 # Remove all distfiles that are / are not part of an installed package 123 # Remove all distfiles that are / are not part of an installed package
124 if ($opt{y} || $opt{z}) 124 if ($opt{y} || $opt{z})
125 { 125 {
126 my(@pkgs, @installed, %distfiles, @pkgdistfiles, @dldistfiles); 126 my(@pkgs, @installed, %distfiles, @pkgdistfiles, @dldistfiles);
127 my(@tmpdistfiles, @orphan, $found, @parent); 127 my(@tmpdistfiles, @orphan, $found, @parent);
128 128
129 @pkgs = list_installed_packages(); 129 @pkgs = list_installed_packages();
130 scan_pkgsrc_makefiles($pkgsrcdir); 130 scan_pkgsrc_makefiles($pkgsrcdir);
131 131
132 # list the installed packages and the directory they live in 132 # list the installed packages and the directory they live in
133 foreach my $pkgname (sort @pkgs) 133 foreach my $pkgname (sort @pkgs)
134 { 134 {
135 if ($pkgname =~ /^([^*?[]+)-([\d*?[].*)/) 135 if ($pkgname =~ /^([^*?[]+)-([\d*?[].*)/)
136 { 136 {
137 foreach my $pkgver ($pkglist->pkgver($1)) 137 foreach my $pkgver ($pkglist->pkgver($1))
138 { 138 {
139 $pkgver->var('dir') =~ /-current/ && next; 139 $pkgver->var('dir') =~ /-current/ && next;
140 push(@installed, $pkgver); 140 push(@installed, $pkgver);
141 last; 141 last;
142 } 142 }
143 } 143 }
144 } 144 }
145 145
146 # distfiles belonging to the currently installed packages 146 # distfiles belonging to the currently installed packages
147 foreach my $pkgver (sort @installed) 147 foreach my $pkgver (sort @installed)
148 { 148 {
149 if (open(DISTINFO, "$pkgsrcdir/" .$pkgver->var('dir'). "/distinfo")) 149 if (open(DISTINFO, "$pkgsrcdir/" .$pkgver->var('dir'). "/distinfo"))
150 { 150 {
151 while( <DISTINFO> ) 151 while( <DISTINFO> )
152 { 152 {
153 if (m/^(\w+) ?\(([^\)]+)\) = (\S+)/) 153 if (m/^(\w+) ?\(([^\)]+)\) = (\S+)/)
154 { 154 {
155 my($dn); 155 my($dn);
156 if ($2 =~ /^patch-[\w.+\-]+$/) 156 if ($2 =~ /^patch-[\w.+\-]+$/)
157 { next; } 157 { next; }
158 $dn = $2; 158 $dn = $2;
159 # Strip leading ./ which sometimes gets added 159 # Strip leading ./ which sometimes gets added
160 # because of DISTSUBDIR=. 160 # because of DISTSUBDIR=.
161 $dn =~ s/^(\.\/)*//; 161 $dn =~ s/^(\.\/)*//;
162 if (!defined $distfiles{$dn}) 162 if (!defined $distfiles{$dn})
163 { 163 {
164 $distfiles{$dn}{name} = $dn; 164 $distfiles{$dn}{name} = $dn;
165 push (@pkgdistfiles, $dn); 165 push (@pkgdistfiles, $dn);
166 } 166 }
167 } 167 }
168 } 168 }
169 close(DISTINFO); 169 close(DISTINFO);
170 } 170 }
171 } 171 }
172 172
173 # distfiles downloaded on the current system 173 # distfiles downloaded on the current system
174 @tmpdistfiles = listdir("$pkgdistdir"); 174 @tmpdistfiles = listdir("$pkgdistdir");
175 foreach my $tmppkg (@tmpdistfiles) 175 foreach my $tmppkg (@tmpdistfiles)
176 { 176 {
177 if ($tmppkg ne "pkg-vulnerabilities") 177 if ($tmppkg ne "pkg-vulnerabilities")
178 { push (@dldistfiles, $tmppkg); } 178 { push (@dldistfiles, $tmppkg); }
179 } 179 }
180 180
181 # sort the two arrays to make searching a bit faster 181 # sort the two arrays to make searching a bit faster
182 @dldistfiles = sort { $a cmp $b } @dldistfiles; 182 @dldistfiles = sort { $a cmp $b } @dldistfiles;
183 @pkgdistfiles = sort { $a cmp $b } @pkgdistfiles; 183 @pkgdistfiles = sort { $a cmp $b } @pkgdistfiles;
184 184
185 if ($opt{y}) 185 if ($opt{y})
186 { 186 {
187 # looking for files that are downloaded on the current system 187 # looking for files that are downloaded on the current system
188 # but do not belong to any currently installed package i.e. orphaned 188 # but do not belong to any currently installed package i.e. orphaned
189 $found = 0; 189 $found = 0;
190 foreach my $dldf (@dldistfiles) 190 foreach my $dldf (@dldistfiles)
191 { 191 {
192 foreach my $pkgdf (@pkgdistfiles) 192 foreach my $pkgdf (@pkgdistfiles)
193 { 193 {
194 if ($dldf eq $pkgdf) 194 if ($dldf eq $pkgdf)
195 { $found = 1; } 195 { $found = 1; }
196 } 196 }
197 if ($found != 1) 197 if ($found != 1)
198 { 198 {
199 push (@orphan, $dldf); 199 push (@orphan, $dldf);
200 print "Orphaned file: $dldf\n"; 200 print "Orphaned file: $dldf\n";
201 } 201 }
202 $found = 0; 202 $found = 0;
203 } 203 }
204 204
205 if ($opt{r}) 205 if ($opt{r})
206 { 206 {
207 safe_chdir("$pkgdistdir"); 207 safe_chdir("$pkgdistdir");
208 verbose("Unlinking 'orphaned' distfiles\n"); 208 verbose("Unlinking 'orphaned' distfiles\n");
209 foreach my $distfile (@orphan) 209 foreach my $distfile (@orphan)
210 { unlink($distfile) } 210 { unlink($distfile) }
211 } 211 }
212 } 212 }
213 213
214 if ($opt{z}) 214 if ($opt{z})
215 { 215 {
216 # looking for files that are downloaded on the current system 216 # looking for files that are downloaded on the current system
217 # but belong to a currently installed package i.e. parented 217 # but belong to a currently installed package i.e. parented
218 $found = 0; 218 $found = 0;
219 foreach my $pkgdf (@pkgdistfiles) 219 foreach my $pkgdf (@pkgdistfiles)
220 { 220 {
221 foreach my $dldf (@dldistfiles) 221 foreach my $dldf (@dldistfiles)
222 { 222 {
223 if ($pkgdf eq $dldf) 223 if ($pkgdf eq $dldf)
224 { $found = 1; } 224 { $found = 1; }
225 } 225 }
226 if ($found == 1) 226 if ($found == 1)
227 { 227 {
228 push (@parent, $pkgdf); 228 push (@parent, $pkgdf);
229 print "Parented file: $pkgdf\n"; 229 print "Parented file: $pkgdf\n";
230 } 230 }
231 $found = 0; 231 $found = 0;
232 } 232 }
233 } 233 }
234 234
235 if ($opt{r}) 235 if ($opt{r})
236 { 236 {
237 safe_chdir("$pkgdistdir"); 237 safe_chdir("$pkgdistdir");
238 verbose("Unlinking 'parented' distfiles\n"); 238 verbose("Unlinking 'parented' distfiles\n");
239 foreach my $distfile (@parent) 239 foreach my $distfile (@parent)
240 { unlink($distfile) } 240 { unlink($distfile) }
241 } 241 }
242 } 242 }
243 243
244 # List BROKEN packages 244 # List BROKEN packages
245 if ( $opt{B} ) { 245 if ( $opt{B} ) {
246 scan_pkgsrc_makefiles($pkgsrcdir); 246 scan_pkgsrc_makefiles($pkgsrcdir);
247 foreach my $pkgver ( $pkglist->pkgver ) { 247 foreach my $pkgver ( $pkglist->pkgver ) {
248 $pkgver->var('BROKEN') || next; 248 $pkgver->var('BROKEN') || next;
249 print $pkgver->pkgname . ': ' . $pkgver->var('BROKEN') . "\n"; 249 print $pkgver->pkgname . ': ' . $pkgver->var('BROKEN') . "\n";
250 } 250 }
251 } 251 }
252 252
253 # List obsolete or NO_BIN_ON_FTP/RESTRICTED prebuilt packages 253 # List obsolete or NO_BIN_ON_FTP/RESTRICTED prebuilt packages
254 # 254 #
255 if ( $opt{p} || $opt{O} || $opt{R} ) { 255 if ( $opt{p} || $opt{O} || $opt{R} ) {
256 scan_pkgsrc_makefiles($pkgsrcdir); 256 scan_pkgsrc_makefiles($pkgsrcdir);
257 257
258 @prebuilt_pkgdirs = ( $default_vars->{PACKAGES} ); 258 @prebuilt_pkgdirs = ( $default_vars->{PACKAGES} );
259 %prebuilt_pkgdir_cache = (); 259 %prebuilt_pkgdir_cache = ();
260 260
261 while (@prebuilt_pkgdirs) { 261 while (@prebuilt_pkgdirs) {
262 find( \&check_prebuilt_packages, shift @prebuilt_pkgdirs ); 262 find( \&check_prebuilt_packages, shift @prebuilt_pkgdirs );
263 } 263 }
264 264
265 if ( $opt{r} ) { 265 if ( $opt{r} ) {
266 verbose("Unlinking listed prebuilt packages\n"); 266 verbose("Unlinking listed prebuilt packages\n");
267 foreach my $pkgfile (@matched_prebuiltpackages) { 267 foreach my $pkgfile (@matched_prebuiltpackages) {
268 unlink($pkgfile); 268 unlink($pkgfile);
269 } 269 }
270 } 270 }
271 } 271 }
272 272
273 if ( $opt{S} ) { 273 if ( $opt{S} ) {
274 my (%in_subdir); 274 my (%in_subdir);
275 275
276 foreach my $cat ( list_pkgsrc_categories($pkgsrcdir) ) { 276 foreach my $cat ( list_pkgsrc_categories($pkgsrcdir) ) {
277 my $vars = parse_makefile_vars("$pkgsrcdir/$cat/Makefile"); 277 my $vars = parse_makefile_vars("$pkgsrcdir/$cat/Makefile");
278 278
279 if ( !$vars->{SUBDIR} ) { 279 if ( !$vars->{SUBDIR} ) {
280 print "Warning - no SUBDIR for $cat\n"; 280 print "Warning - no SUBDIR for $cat\n";
281 next; 281 next;
282 } 282 }
283 foreach my $pkgdir ( split( /\s+/, $vars->{SUBDIR} ) ) { 283 foreach my $pkgdir ( split( /\s+/, $vars->{SUBDIR} ) ) {
284 $in_subdir{"$cat/$pkgdir"} = 1; 284 $in_subdir{"$cat/$pkgdir"} = 1;
285 } 285 }
286 } 286 }
287 287
288 scan_pkgsrc_makefiles($pkgsrcdir); 288 scan_pkgsrc_makefiles($pkgsrcdir);
289 foreach my $pkgver ( $pkglist->pkgver ) { 289 foreach my $pkgver ( $pkglist->pkgver ) {
290 if ( !defined $in_subdir{ $pkgver->var('dir') } ) { 290 if ( !defined $in_subdir{ $pkgver->var('dir') } ) {
291 print $pkgver->var('dir') . ": Not in SUBDIR\n"; 291 print $pkgver->var('dir') . ": Not in SUBDIR\n";
292 } 292 }
293 } 293 }
294 } 294 }
295 295
296 if ( $opt{g} ) { 296 if ( $opt{g} ) {
297 my $tmpfile = "$opt{g}.tmp.$$"; 297 my $tmpfile = "$opt{g}.tmp.$$";
298 298
299 scan_pkgsrc_makefiles($pkgsrcdir); 299 scan_pkgsrc_makefiles($pkgsrcdir);
300 if ( !open( TABLE, ">$tmpfile" ) ) { 300 if ( !open( TABLE, ">$tmpfile" ) ) {
301 fail("Unable to write '$tmpfile': $!"); 301 fail("Unable to write '$tmpfile': $!");
302 } 302 }
303 foreach my $pkgver ( $pkglist->pkgver ) { 303 foreach my $pkgver ( $pkglist->pkgver ) {
304 print TABLE $pkgver->pkg . "\t" 304 print TABLE $pkgver->pkg . "\t"
305 . $pkgver->var('dir') . "\t" 305 . $pkgver->var('dir') . "\t"
306 . $pkgver->ver . "\n"; 306 . $pkgver->ver . "\n";
307 } 307 }
308 if ( !close(TABLE) ) { 308 if ( !close(TABLE) ) {
309 fail("Error while writing '$tmpfile': $!"); 309 fail("Error while writing '$tmpfile': $!");
310 } 310 }
311 if ( !rename( $tmpfile, $opt{g} ) ) { 311 if ( !rename( $tmpfile, $opt{g} ) ) {
312 fail("Error in rename('$tmpfile','$opt{g}'): $!"); 312 fail("Error in rename('$tmpfile','$opt{g}'): $!");
313 } 313 }
314 } 314 }
315 315
316 if ( $opt{d} ) { 316 if ( $opt{d} ) {
317 scan_pkgsrc_makefiles($pkgsrcdir); 317 scan_pkgsrc_makefiles($pkgsrcdir);
318 pkgsrc_check_depends(); 318 pkgsrc_check_depends();
319 } 319 }
320 320
321 if ( $opt{i} || $opt{u} ) { 321 if ( $opt{i} || $opt{u} ) {
322 my ( @pkgs, @update ); 322 my ( @pkgs, @update );
323 323
324 @pkgs = list_installed_packages(); 324 @pkgs = list_installed_packages();
325 scan_pkgsrc_makefiles($pkgsrcdir); 325 scan_pkgsrc_makefiles($pkgsrcdir);
326 326
327 foreach my $pkgname ( sort @pkgs ) { 327 foreach my $pkgname ( sort @pkgs ) {
328 if ( $_ = invalid_version($pkgname) ) { 328 if ( $_ = invalid_version($pkgname) ) {
329 print $_; 329 print $_;
330 330
331 if ( $pkgname =~ /^([^*?[]+)-([\d*?[].*)/ ) { 331 if ( $pkgname =~ /^([^*?[]+)-([\d*?[].*)/ ) {
332 foreach my $pkgver ( $pkglist->pkgver($1) ) { 332 foreach my $pkgver ( $pkglist->pkgver($1) ) {
333 $pkgver->var('dir') =~ /-current/ && next; 333 $pkgver->var('dir') =~ /-current/ && next;
334 push( @update, $pkgver ); 334 push( @update, $pkgver );
335 last; 335 last;
336 } 336 }
337 } 337 }
338 } 338 }
339 } 339 }
340 340
341 if ( $opt{u} ) { 341 if ( $opt{u} ) {
342 print "\nREQUIRED details for packages that could be updated:\n"; 342 print "\nREQUIRED details for packages that could be updated:\n";
343 343
344 foreach my $pkgver (@update) { 344 foreach my $pkgver (@update) {
345 print $pkgver->pkg . ':'; 345 print $pkgver->pkg . ':';
346 if ( open( PKGINFO, 'pkg_info -R ' . $pkgver->pkg . '|' ) ) { 346 if ( open( PKGINFO, 'pkg_info -R ' . $pkgver->pkg . '|' ) ) {
347 my ($list); 347 my ($list);
348 348
349 while (<PKGINFO>) { 349 while (<PKGINFO>) {
350 if (/Required by:/) { 350 if (/Required by:/) {
351 $list = 1; 351 $list = 1;
352 } 352 }
353 elsif ($list) { 353 elsif ($list) {
354 chomp; 354 chomp;
355 s/-\d.*//; 355 s/-\d.*//;
356 print " $_"; 356 print " $_";
357 } 357 }
358 } 358 }
359 close(PKGINFO); 359 close(PKGINFO);
360 } 360 }
361 print "\n"; 361 print "\n";
362 } 362 }
363 363
364 print 364 print
365 "\nRunning '${conf_make} fetch-list | sh' for each package:\n"; 365 "\nRunning '${conf_make} fetch-list | sh' for each package:\n";
366 foreach my $pkgver (@update) { 366 foreach my $pkgver (@update) {
367 my ($pkgdir); 367 my ($pkgdir);
368 368
369 $pkgdir = $pkgver->var('dir'); 369 $pkgdir = $pkgver->var('dir');
370 if ( !defined($pkgdir) ) { 370 if ( !defined($pkgdir) ) {
371 fail( 371 fail(
372 'Unable to determine ' . $pkgver->pkg . ' directory' ); 372 'Unable to determine ' . $pkgver->pkg . ' directory' );
373 } 373 }
374 374
375 print "$pkgsrcdir/$pkgdir\n"; 375 print "$pkgsrcdir/$pkgdir\n";
376 safe_chdir("$pkgsrcdir/$pkgdir"); 376 safe_chdir("$pkgsrcdir/$pkgdir");
377 system("${conf_make} fetch-list | sh"); 377 system("${conf_make} fetch-list | sh");
378 } 378 }
379 } 379 }
380 } 380 }
381 381
382 if ( $opt{E} ) { 382 if ( $opt{E} ) {
383 scan_pkgsrc_makefiles($pkgsrcdir); 383 scan_pkgsrc_makefiles($pkgsrcdir);
384 store_pkgsrc_makefiles( $opt{E} ); 384 store_pkgsrc_makefiles( $opt{E} );
385 } 385 }
386} 386}
387 387
388sub canonicalize_pkgname($) { 388sub canonicalize_pkgname($) {
389 my ($pkgname) = @_; 389 my ($pkgname) = @_;
390 390
391 $pkgname =~ s,^py\d+(?:pth|)-,py-,; 391 $pkgname =~ s,^py\d+(?:pth|)-,py-,;
392 $pkgname =~ s,^ruby\d+-,ruby-,; 392 $pkgname =~ s,^ruby\d+-,ruby-,;
393 $pkgname =~ s,^php\d+-,php-,; 393 $pkgname =~ s,^php\d+-,php-,;
394 return $pkgname; 394 return $pkgname;
395} 395}
396 396
397# Could speed up by building a cache of package names to paths, then processing 397# Could speed up by building a cache of package names to paths, then processing
398# each package name once against the tests. 398# each package name once against the tests.
399sub check_prebuilt_packages() { 399sub check_prebuilt_packages() {
400 400
401 if ( $_ eq 'distfiles' || $_ eq 'pkgsrc' ) { 401 if ( $_ eq 'distfiles' || $_ eq 'pkgsrc' ) {
402 402
403 # Skip these subdirs if present 403 # Skip these subdirs if present
404 $File::Find::prune = 1; 404 $File::Find::prune = 1;
405 405
406 } 406 }
407 elsif (/(.+)-(\d.*)\.t[bg]z$/) { 407 elsif (/(.+)-(\d.*)\.t[bg]z$/) {
408 my ( $pkg, $ver ) = ( $1, $2 ); 408 my ( $pkg, $ver ) = ( $1, $2 );
409 409
410 $pkg = canonicalize_pkgname($pkg); 410 $pkg = canonicalize_pkgname($pkg);
411 411
412 my ($pkgs); 412 my ($pkgs);
413 if ( $pkgs = $pkglist->pkgs($pkg) ) { 413 if ( $pkgs = $pkglist->pkgs($pkg) ) {
414 my ($pkgver) = $pkgs->pkgver($ver); 414 my ($pkgver) = $pkgs->pkgver($ver);
415 415
416 if ( !defined $pkgver ) { 416 if ( !defined $pkgver ) {
417 if ( $opt{p} ) { 417 if ( $opt{p} ) {
418 print "$File::Find::dir/$_\n"; 418 print "$File::Find::dir/$_\n";
419 push( @matched_prebuiltpackages, "$File::Find::dir/$_" ); 419 push( @matched_prebuiltpackages, "$File::Find::dir/$_" );
420 } 420 }
421 421
422 # Pick probably the last version 422 # Pick probably the last version
423 $pkgver = $pkgs->latestver; 423 $pkgver = $pkgs->latestver;
424 } 424 }
425 425
426 if ( $opt{R} && $pkgver->var('RESTRICTED') ) { 426 if ( $opt{R} && $pkgver->var('RESTRICTED') ) {
427 print "$File::Find::dir/$_\n"; 427 print "$File::Find::dir/$_\n";
428 push( @matched_prebuiltpackages, "$File::Find::dir/$_" ); 428 push( @matched_prebuiltpackages, "$File::Find::dir/$_" );
429 } 429 }
430 430
431 if ( $opt{O} && $pkgver->var('OSVERSION_SPECIFIC') ) { 431 if ( $opt{O} && $pkgver->var('OSVERSION_SPECIFIC') ) {
432 print "$File::Find::dir/$_\n"; 432 print "$File::Find::dir/$_\n";
433 push( @matched_prebuiltpackages, "$File::Find::dir/$_" ); 433 push( @matched_prebuiltpackages, "$File::Find::dir/$_" );
434 } 434 }
435 } 435 }
436 436
437 } 437 }
438 elsif ( -d $_ ) { 438 elsif ( -d $_ ) {
439 if ( $prebuilt_pkgdir_cache{"$File::Find::dir/$_"} ) { 439 if ( $prebuilt_pkgdir_cache{"$File::Find::dir/$_"} ) {
440 $File::Find::prune = 1; 440 $File::Find::prune = 1;
441 return; 441 return;
442 } 442 }
443 443
444 $prebuilt_pkgdir_cache{"$File::Find::dir/$_"} = 1; 444 $prebuilt_pkgdir_cache{"$File::Find::dir/$_"} = 1;
445 if ( -l $_ ) { 445 if ( -l $_ ) {
446 my ($dest) = readlink($_); 446 my ($dest) = readlink($_);
447 447
448 if ( substr( $dest, 0, 1 ) ne '/' ) { 448 if ( substr( $dest, 0, 1 ) ne '/' ) {
449 $dest = "$File::Find::dir/$dest"; 449 $dest = "$File::Find::dir/$dest";
450 } 450 }
451 if ( !$prebuilt_pkgdir_cache{$dest} ) { 451 if ( !$prebuilt_pkgdir_cache{$dest} ) {
452 push( @prebuilt_pkgdirs, $dest ); 452 push( @prebuilt_pkgdirs, $dest );
453 } 453 }
454 } 454 }
455 } 455 }
456} 456}
457 457
458# Dewey decimal verson number matching - or thereabouts 458# Dewey decimal verson number matching - or thereabouts
459# Also handles 'nb<N>' suffix (checked iff values otherwise identical) 459# Also handles 'nb<N>' suffix (checked iff values otherwise identical)
460# 460#
461sub deweycmp($$$) { 461sub deweycmp($$$) {
462 my ( $match, $test, $val ) = @_; 462 my ( $match, $test, $val ) = @_;
463 my ( $cmp, $match_nb, $val_nb ); 463 my ( $cmp, $match_nb, $val_nb );
464 464
465 $match_nb = $val_nb = 0; 465 $match_nb = $val_nb = 0;
466 if ( $match =~ /(.*)nb(.*)/ ) { 466 if ( $match =~ /(.*)nb(.*)/ ) {
467 467
468 # Handle nb<N> suffix 468 # Handle nb<N> suffix
469 $match = $1; 469 $match = $1;
470 $match_nb = $2; 470 $match_nb = $2;
471 } 471 }
472 472
473 if ( $val =~ /(.*)nb(.*)/ ) { 473 if ( $val =~ /(.*)nb(.*)/ ) {
474 474
475 # Handle nb<N> suffix 475 # Handle nb<N> suffix
476 $val = $1; 476 $val = $1;
477 $val_nb = $2; 477 $val_nb = $2;
478 } 478 }
479 479
480 $cmp = deweycmp_extract( $match, $val ); 480 $cmp = deweycmp_extract( $match, $val );
481 481
482 if ( !$cmp ) { 482 if ( !$cmp ) {
483 483
484 # Iff otherwise identical, check nb suffix 484 # Iff otherwise identical, check nb suffix
485 $cmp = deweycmp_extract( $match_nb, $val_nb ); 485 $cmp = deweycmp_extract( $match_nb, $val_nb );
486 } 486 }
487 487
488 eval "$cmp $test 0"; 488 eval "$cmp $test 0";
489} 489}
490 490
491sub convert_to_standard_dewey(@) { 491sub convert_to_standard_dewey(@) {
492 my ( $elem, $underscore, @temp ); 492 my ( $elem, $underscore, @temp );
493 493
494 # According to the current implementation in pkg_install/lib/str.c 494 # According to the current implementation in pkg_install/lib/str.c
495 # as of 2002/06/02, '_' before a number, '.', and 'pl' get treated as 0, 495 # as of 2002/06/02, '_' before a number, '.', and 'pl' get treated as 0,
496 # while 'rc' and 'pre' get treated as -1; beta as '-2', alpha as '-3'. 496 # while 'rc' and 'pre' get treated as -1; beta as '-2', alpha as '-3'.
497 # Other characters are converted to lower 497 # Other characters are converted to lower
498 # case and then to a number: a->1, b->2, c->3, etc. Numbers stay the same. 498 # case and then to a number: a->1, b->2, c->3, etc. Numbers stay the same.
499 # 'nb' is a special case that's already been handled when we are here. 499 # 'nb' is a special case that's already been handled when we are here.
500 foreach $elem (@_) { 500 foreach $elem (@_) {
501 if ( $elem =~ /\d+/ ) { 501 if ( $elem =~ /\d+/ ) {
502 push( @temp, $elem ); 502 push( @temp, $elem );
503 503
504 } 504 }
505 elsif ( $elem =~ /^pl$/ or $elem =~ /^\.$/ ) { 505 elsif ( $elem =~ /^pl$/ or $elem =~ /^\.$/ ) {
506 push( @temp, 0 ); 506 push( @temp, 0 );
507 507
508 } 508 }
509 elsif ( $elem =~ /^_$/ ) { 509 elsif ( $elem =~ /^_$/ ) {
510 push( @temp, 0 ); 510 push( @temp, 0 );
511 511
512 } 512 }
513 elsif ( $elem =~ /^pre$/ ) { 513 elsif ( $elem =~ /^pre$/ ) {
514 push( @temp, -1 ); 514 push( @temp, -1 );
515 515
516 } 516 }
517 elsif ( $elem =~ /^rc$/ ) { 517 elsif ( $elem =~ /^rc$/ ) {
518 push( @temp, -1 ); 518 push( @temp, -1 );
519 519
520 } 520 }
521 elsif ( $elem =~ /^beta$/ ) { 521 elsif ( $elem =~ /^beta$/ ) {
522 push( @temp, -2 ); 522 push( @temp, -2 );
523 523
524 } 524 }
525 elsif ( $elem =~ /^alpha$/ ) { 525 elsif ( $elem =~ /^alpha$/ ) {
526 push( @temp, -3 ); 526 push( @temp, -3 );
527 527
528 } 528 }
529 else { 529 else {
530 push( @temp, 0 ); 530 push( @temp, 0 );
531 push( @temp, ord($elem) - ord("a") + 1 ); 531 push( @temp, ord($elem) - ord("a") + 1 );
532 } 532 }
533 } 533 }
534 @temp; 534 @temp;
535} 535}
536 536
537sub deweycmp_extract($$) { 537sub deweycmp_extract($$) {
538 my ( $match, $val ) = @_; 538 my ( $match, $val ) = @_;
539 my ( $cmp, @matchlist, @vallist, $i, $len ); 539 my ( $cmp, @matchlist, @vallist, $i, $len );
540 540
541 @matchlist = convert_to_standard_dewey( split( /(\D+)/, lc($match) ) ); 541 @matchlist = convert_to_standard_dewey( split( /(\D+)/, lc($match) ) );
542 @vallist = convert_to_standard_dewey( split( /(\D+)/, lc($val) ) ); 542 @vallist = convert_to_standard_dewey( split( /(\D+)/, lc($val) ) );
543 $cmp = 0; 543 $cmp = 0;
544 $i = 0; 544 $i = 0;
545 if ( $#matchlist > $#vallist ) { 545 if ( $#matchlist > $#vallist ) {
546 $len = $#matchlist; 546 $len = $#matchlist;
547 } 547 }
548 else { 548 else {
549 $len = $#vallist; 549 $len = $#vallist;
550 } 550 }
551 while ( !$cmp && ( $i++ <= $len ) ) { 551 while ( !$cmp && ( $i++ <= $len ) ) {
552 if ( !@matchlist ) { 552 if ( !@matchlist ) {
553 push( @matchlist, 0 ); 553 push( @matchlist, 0 );
554 } 554 }
555 if ( !@vallist ) { 555 if ( !@vallist ) {
556 push( @vallist, 0 ); 556 push( @vallist, 0 );
557 } 557 }
558 $cmp = ( shift @matchlist <=> shift @vallist ); 558 $cmp = ( shift @matchlist <=> shift @vallist );
559 } 559 }
560 $cmp; 560 $cmp;
561} 561}
562 562
563sub fail(@) { 563sub fail(@) {
564 564
565 print STDERR @_, "\n"; 565 print STDERR @_, "\n";
566 exit(3); 566 exit(3);
567} 567}
568 568
569sub get_default_makefile_vars() { 569sub get_default_makefile_vars() {
570 570
571 chomp( $pkg_installver = `pkg_info -V 2>/dev/null || echo 20010302` ); 571 chomp( $pkg_installver = `pkg_info -V 2>/dev/null || echo 20010302` );
572 572
573 chomp( $_ = `uname -srm` ); 573 chomp( $_ = `uname -srm` );
574 ( 574 (
575 $default_vars->{OPSYS}, 575 $default_vars->{OPSYS},
576 $default_vars->{OS_VERSION}, 576 $default_vars->{OS_VERSION},
577 $default_vars->{MACHINE} 577 $default_vars->{MACHINE}
578 ) = (split); 578 ) = (split);
579 if ( !$default_vars->{MACHINE} ) { 579 if ( !$default_vars->{MACHINE} ) {
580 die('Unable to extract machine from uname'); 580 die('Unable to extract machine from uname');
581 } 581 }
582 582
583 # Handle systems without uname -p (NetBSD pre 1.4) 583 # Handle systems without uname -p (NetBSD pre 1.4)
584 chomp( $default_vars->{MACHINE_ARCH} = `uname -p 2>/dev/null` ); 584 chomp( $default_vars->{MACHINE_ARCH} = `uname -p 2>/dev/null` );
585 585
586 if ( !$default_vars->{MACHINE_ARCH} 586 if ( !$default_vars->{MACHINE_ARCH}
587 && $default_vars->{OS_VERSION} eq 'NetBSD' ) 587 && $default_vars->{OS_VERSION} eq 'NetBSD' )
588 { 588 {
589 chomp( $default_vars->{MACHINE_ARCH} = `sysctl -n hw.machine_arch` ); 589 chomp( $default_vars->{MACHINE_ARCH} = `sysctl -n hw.machine_arch` );
590 } 590 }
591 591
592 if ( !$default_vars->{MACHINE_ARCH} ) { 592 if ( !$default_vars->{MACHINE_ARCH} ) {
593 $default_vars->{MACHINE_ARCH} = $default_vars->{MACHINE}; 593 $default_vars->{MACHINE_ARCH} = $default_vars->{MACHINE};
594 } 594 }
595 595
596 $default_vars->{OBJECT_FMT} = 'x'; 596 $default_vars->{OBJECT_FMT} = 'x';
597 $default_vars->{LOWER_OPSYS} = lc( $default_vars->{OPSYS} ); 597 $default_vars->{LOWER_OPSYS} = lc( $default_vars->{OPSYS} );
598 598
599 if ( $opt{P} ) { 599 if ( $opt{P} ) {
600 $default_vars->{PKGSRCDIR} = realpath($opt{P}); 600 $default_vars->{PKGSRCDIR} = realpath($opt{P});
601 } 601 }
602 else { 602 else {
603 $default_vars->{PKGSRCDIR} = $conf_pkgsrcdir; 603 $default_vars->{PKGSRCDIR} = $conf_pkgsrcdir;
604 } 604 }
605 605
606 $default_vars->{DESTDIR} = ''; 606 $default_vars->{DESTDIR} = '';
607 $default_vars->{LOCALBASE} = '/usr/pkg'; 607 $default_vars->{LOCALBASE} = '/usr/pkg';
608 $default_vars->{X11BASE} = '/usr/X11R6'; 608 $default_vars->{X11BASE} = '/usr/X11R6';
609 609
610 my ($vars); 610 my ($vars);
611 if ( -f '/etc/mk.conf' && ( $vars = parse_makefile_vars('/etc/mk.conf') ) ) 611 if ( -f '/etc/mk.conf' && ( $vars = parse_makefile_vars('/etc/mk.conf') ) )
612 { 612 {
613 foreach my $var ( keys %{$vars} ) { 613 foreach my $var ( keys %{$vars} ) {
614 $default_vars->{$var} = $vars->{$var}; 614 $default_vars->{$var} = $vars->{$var};
615 } 615 }
616 } 616 }
617 elsif ( -f ${conf_sysconfdir} . '/mk.conf' && ( $vars = parse_makefile_vars(${conf_sysconfdir} . '/mk.conf') ) ) 617 elsif ( -f ${conf_sysconfdir} . '/mk.conf' && ( $vars = parse_makefile_vars(${conf_sysconfdir} . '/mk.conf') ) )
618 { 618 {
619 foreach my $var ( keys %{$vars} ) { 619 foreach my $var ( keys %{$vars} ) {
620 $default_vars->{$var} = $vars->{$var}; 620 $default_vars->{$var} = $vars->{$var};
621 } 621 }
622 } 622 }
623 623
624 if ( $opt{P} ) { 624 if ( $opt{P} ) {
625 $default_vars->{PKGSRCDIR} = realpath($opt{P}); 625 $default_vars->{PKGSRCDIR} = realpath($opt{P});
626 } 626 }
627 627
628 if ( $opt{M} ) { 628 if ( $opt{M} ) {
629 $default_vars->{DISTDIR} = realpath($opt{M}); 629 $default_vars->{DISTDIR} = realpath($opt{M});
630 } 630 }
631 else { 631 else {
632 $default_vars->{DISTDIR} ||= $default_vars->{PKGSRCDIR} . '/distfiles'; 632 $default_vars->{DISTDIR} ||= $default_vars->{PKGSRCDIR} . '/distfiles';
633 } 633 }
634 634
635 if ( $opt{K} ) { 635 if ( $opt{K} ) {
636 $default_vars->{PACKAGES} = realpath($opt{K}); 636 $default_vars->{PACKAGES} = realpath($opt{K});
637 } 637 }
638 638
639 # Extract some variables from bsd.pkg.mk 639 # Extract some variables from bsd.pkg.mk
640 my ($mkvars); 640 my ($mkvars);
641 $mkvars = parse_makefile_vars( 641 $mkvars = parse_makefile_vars(
642 "$default_vars->{PKGSRCDIR}/mk/bsd.pkg.mk", 642 "$default_vars->{PKGSRCDIR}/mk/bsd.pkg.mk",
643 "$default_vars->{PKGSRCDIR}/mk/scripts" 643 "$default_vars->{PKGSRCDIR}/mk/scripts"
644 ); 644 );
645 foreach my $varname ( keys %{$mkvars} ) { 645 foreach my $varname ( keys %{$mkvars} ) {
646 if ( $varname =~ /_REQD$/ || $varname eq 'EXTRACT_SUFX' ) { 646 if ( $varname =~ /_REQD$/ || $varname eq 'EXTRACT_SUFX' ) {
647 $default_vars->{$varname} = $mkvars->{$varname}; 647 $default_vars->{$varname} = $mkvars->{$varname};
648 } 648 }
649 } 649 }
650 650
651 $default_vars->{PACKAGES} ||= $default_vars->{PKGSRCDIR} . '/packages'; 651 $default_vars->{PACKAGES} ||= $default_vars->{PKGSRCDIR} . '/packages';
652} 652}
653 653
654# Determine if a package version is current. If not, report correct version 654# Determine if a package version is current. If not, report correct version
655# if found 655# if found
656# 656#
657sub invalid_version($) { 657sub invalid_version($) {
658 my ($pkgmatch) = @_; 658 my ($pkgmatch) = @_;
659 my ( $fail, $ok ); 659 my ( $fail, $ok );
660 my ( @pkgmatches, @todo ); 660 my ( @pkgmatches, @todo );
661 661
662 @todo = ($pkgmatch); 662 @todo = ($pkgmatch);
663 663
664 # We handle {} here, everything else in package_globmatch 664 # We handle {} here, everything else in package_globmatch
665 while ( $pkgmatch = shift @todo ) { 665 while ( $pkgmatch = shift @todo ) {
666 if ( $pkgmatch =~ /(.*)\{([^{}]+)}(.*)/ ) { 666 if ( $pkgmatch =~ /(.*)\{([^{}]+)}(.*)/ ) {
667 foreach ( split( ',', $2 ) ) { 667 foreach ( split( ',', $2 ) ) {
668 push( @todo, "$1$_$3" ); 668 push( @todo, "$1$_$3" );
669 } 669 }
670 } 670 }
671 else { 671 else {
672 push( @pkgmatches, $pkgmatch ); 672 push( @pkgmatches, $pkgmatch );
673 } 673 }
674 } 674 }
675 675
676 foreach $pkgmatch (@pkgmatches) { 676 foreach $pkgmatch (@pkgmatches) {
677 my ( $pkg, $badver ) = package_globmatch($pkgmatch); 677 my ( $pkg, $badver ) = package_globmatch($pkgmatch);
678 678
679 if ( defined($badver) ) { 679 if ( defined($badver) ) {
680 my ($pkgs); 680 my ($pkgs);
681 681
682 if ( $pkgs = $pkglist->pkgs($pkg) ) { 682 if ( $pkgs = $pkglist->pkgs($pkg) ) {
683 $fail .= 683 $fail .=
684 "Version mismatch: '$pkg' $badver vs " 684 "Version mismatch: '$pkg' $badver vs "
685 . join( ',', $pkgs->versions ) . "\n"; 685 . join( ',', $pkgs->versions ) . "\n";
686 } 686 }
687 else { 687 else {
688 $fail .= "Unknown package: '$pkg' version $badver\n"; 688 $fail .= "Unknown package: '$pkg' version $badver\n";
689 } 689 }
690 } 690 }
691 else { 691 else {
692 692
693 # If we find one match, don't bitch about others 693 # If we find one match, don't bitch about others
694 $ok = 1; 694 $ok = 1;
695 } 695 }
696 } 696 }
697 $ok && ( $fail = undef ); 697 $ok && ( $fail = undef );
698 $fail; 698 $fail;
699} 699}
700 700
701# List (recursive) non directory contents of specified directory 701# List (recursive) non directory contents of specified directory
702# 702#
703#TODO this entire sub should be replaced with direct calls to 703#TODO this entire sub should be replaced with direct calls to
704# File::Find 704# File::Find
705sub listdir($$) { 705sub listdir($$) {
706 my ( $base, $dir ) = @_; 706 my ( $base, $dir ) = @_;
707 my ($thisdir); 707 my ($thisdir);
708 my ( @list, @thislist ); 708 my ( @list, @thislist );
709 709
710 $thisdir = $base; 710 $thisdir = $base;
711 if ( defined($dir) ) { 711 if ( defined($dir) ) {
712 $thisdir .= "/$dir"; 712 $thisdir .= "/$dir";
713 $dir .= '/'; 713 $dir .= '/';
714 } 714 }
715 else { 715 else {
716 $dir = ''; 716 $dir = '';
717 } 717 }
718 718
719 opendir( DIR, $thisdir ) || fail("Unable to opendir($thisdir): $!"); 719 opendir( DIR, $thisdir ) || fail("Unable to opendir($thisdir): $!");
720 @thislist = grep( substr( $_, 0, 1 ) ne '.' && $_ ne 'CVS', readdir(DIR) ); 720 @thislist = grep( substr( $_, 0, 1 ) ne '.' && $_ ne 'CVS', readdir(DIR) );
721 closedir(DIR); 721 closedir(DIR);
722 foreach my $entry (@thislist) { 722 foreach my $entry (@thislist) {
723 if ( -d "$thisdir/$entry" ) { 723 if ( -d "$thisdir/$entry" ) {
724 push( @list, listdir( $base, "$dir$entry" ) ); 724 push( @list, listdir( $base, "$dir$entry" ) );
725 } 725 }
726 else { 726 else {
727 push( @list, "$dir$entry" ); 727 push( @list, "$dir$entry" );
728 } 728 }
729 } 729 }
730 @list; 730 @list;
731} 731}
732 732
733# Use pkg_info to list installed packages 733# Use pkg_info to list installed packages
734# 734#
735sub list_installed_packages() { 735sub list_installed_packages() {
736 my (@pkgs); 736 my (@pkgs);
737 737
738 open( PKG_INFO, 'pkg_info -e "*" |' ) || fail("Unable to run pkg_info: $!"); 738 open( PKG_INFO, 'pkg_info -e "*" |' ) || fail("Unable to run pkg_info: $!");
739 while ( defined( my $pkg = <PKG_INFO> ) ) { 739 while ( defined( my $pkg = <PKG_INFO> ) ) {
740 chomp($pkg); 740 chomp($pkg);
741 push( @pkgs, canonicalize_pkgname($pkg) ); 741 push( @pkgs, canonicalize_pkgname($pkg) );
742 } 742 }
743 close(PKG_INFO); 743 close(PKG_INFO);
744 744
745 @pkgs; 745 @pkgs;
746} 746}
747 747
748# List top level pkgsrc categories 748# List top level pkgsrc categories
749# 749#
750sub list_pkgsrc_categories($) { 750sub list_pkgsrc_categories($) {
751 my ($pkgsrcdir) = @_; 751 my ($pkgsrcdir) = @_;
752 my (@categories); 752 my (@categories);
753 753
754 opendir( BASE, $pkgsrcdir ) || die("Unable to opendir($pkgsrcdir): $!"); 754 opendir( BASE, $pkgsrcdir ) || die("Unable to opendir($pkgsrcdir): $!");
755 @categories = 755 @categories =
756 grep( substr( $_, 0, 1 ) ne '.' 756 grep( substr( $_, 0, 1 ) ne '.'
757 && $_ ne 'CVS' 757 && $_ ne 'CVS'
758 && -f "$pkgsrcdir/$_/Makefile", 758 && -f "$pkgsrcdir/$_/Makefile",
759 readdir(BASE) ); 759 readdir(BASE) );
760 closedir(BASE); 760 closedir(BASE);
761 @categories; 761 @categories;
762} 762}
763 763
764# For a given category, list potentially valid pkgdirs 764# For a given category, list potentially valid pkgdirs
765# 765#
766sub list_pkgsrc_pkgdirs($$) { 766sub list_pkgsrc_pkgdirs($$) {
767 my ( $pkgsrcdir, $cat ) = @_; 767 my ( $pkgsrcdir, $cat ) = @_;
768 my (@pkgdirs); 768 my (@pkgdirs);
769 769
770 if ( !opendir( CAT, "$pkgsrcdir/$cat" ) ) { 770 if ( !opendir( CAT, "$pkgsrcdir/$cat" ) ) {
771 die("Unable to opendir($pkgsrcdir/cat): $!"); 771 die("Unable to opendir($pkgsrcdir/cat): $!");
772 } 772 }
773 @pkgdirs = 773 @pkgdirs =
774 sort grep( $_ ne 'Makefile' 774 sort grep( $_ ne 'Makefile'
775 && $_ ne 'pkg' 775 && $_ ne 'pkg'
776 && $_ ne 'CVS' 776 && $_ ne 'CVS'
777 && substr( $_, 0, 1 ) ne '.', 777 && substr( $_, 0, 1 ) ne '.',
778 readdir(CAT) ); 778 readdir(CAT) );
779 closedir(CAT); 779 closedir(CAT);
780 @pkgdirs; 780 @pkgdirs;
781} 781}
782 782
783sub glob2regex($) { 783sub glob2regex($) {
784 my ($glob) = @_; 784 my ($glob) = @_;
785 my ( @chars, $in_alt ); 785 my ( @chars, $in_alt );
786 my ($regex); 786 my ($regex);
787 787
788 @chars = split( //, $glob ); 788 @chars = split( //, $glob );
789 while ( defined( $_ = shift @chars ) ) { 789 while ( defined( $_ = shift @chars ) ) {
790 if ( $_ eq '*' ) { 790 if ( $_ eq '*' ) {
791 $regex .= '.*'; 791 $regex .= '.*';
792 } 792 }
793 elsif ( $_ eq '?' ) { 793 elsif ( $_ eq '?' ) {
794 $regex .= '.'; 794 $regex .= '.';
795 } 795 }
796 elsif ( $_ eq '+' ) { 796 elsif ( $_ eq '+' ) {
797 $regex .= '.'; 797 $regex .= '.';
798 } 798 }
799 elsif ( $_ eq '\\+' ) { 799 elsif ( $_ eq '\\+' ) {
800 $regex .= $_ . shift @chars; 800 $regex .= $_ . shift @chars;
801 } 801 }
802 elsif ( $_ eq '.' || $_ eq '|' ) { 802 elsif ( $_ eq '.' || $_ eq '|' ) {
803 $regex .= quotemeta; 803 $regex .= quotemeta;
804 } 804 }
805 elsif ( $_ eq '{' ) { 805 elsif ( $_ eq '{' ) {
806 $regex .= '('; 806 $regex .= '(';
807 ++$in_alt; 807 ++$in_alt;
808 } 808 }
809 elsif ( $_ eq '}' ) { 809 elsif ( $_ eq '}' ) {
810 if ( !$in_alt ) { 810 if ( !$in_alt ) {
811 811
812 # Error 812 # Error
813 return undef; 813 return undef;
814 } 814 }
815 $regex .= ')'; 815 $regex .= ')';
816 --$in_alt; 816 --$in_alt;
817 } 817 }
818 elsif ( $_ eq ',' && $in_alt ) { 818 elsif ( $_ eq ',' && $in_alt ) {
819 $regex .= '|'; 819 $regex .= '|';
820 } 820 }
821 else { 821 else {
822 $regex .= $_; 822 $regex .= $_;
823 } 823 }
824 } 824 }
825 825
826 if ($in_alt) { 826 if ($in_alt) {
827 827
828 # Error 828 # Error
829 return undef; 829 return undef;
830 } 830 }
831 if ( $regex eq $glob ) { 831 if ( $regex eq $glob ) {
832 return (''); 832 return ('');
833 } 833 }
834 if ( $opt{D} ) { 834 if ( $opt{D} ) {
835 print "glob2regex: $glob -> $regex\n"; 835 print "glob2regex: $glob -> $regex\n";
836 } 836 }
837 '^' . $regex . '$'; 837 '^' . $regex . '$';
838} 838}
839 839
840# Perform some (reasonable) subset of 'pkg_info -e' / glob(3) 840# Perform some (reasonable) subset of 'pkg_info -e' / glob(3)
841# Returns (sometimes best guess at) package name, 841# Returns (sometimes best guess at) package name,
842# and either 'problem version' or undef if all OK 842# and either 'problem version' or undef if all OK
843# 843#
844sub package_globmatch($) { 844sub package_globmatch($) {
845 my ($pkgmatch) = @_; 845 my ($pkgmatch) = @_;
846 my ( $matchpkgname, $matchver, $regex ); 846 my ( $matchpkgname, $matchver, $regex );
847 847
848 if ( $pkgmatch =~ /^([^*?[]+)(<|>|<=|>=|-)(\d[^*?[{]*)$/ ) { 848 if ( $pkgmatch =~ /^([^*?[]+)(<|>|<=|>=|-)(\d[^*?[{]*)$/ ) {
849 849
850 # (package)(cmp)(dewey) 850 # (package)(cmp)(dewey)
851 my ( $test, @pkgvers ); 851 my ( $test, @pkgvers );
852 852
853 ( $matchpkgname, $test, $matchver ) = ( $1, $2, $3 ); 853 ( $matchpkgname, $test, $matchver ) = ( $1, $2, $3 );
854 if ( @pkgvers = $pkglist->pkgver($matchpkgname) ) { 854 if ( @pkgvers = $pkglist->pkgver($matchpkgname) ) {
855 foreach my $pkgver (@pkgvers) { 855 foreach my $pkgver (@pkgvers) {
856 if ( $test eq '-' ) { 856 if ( $test eq '-' ) {
857 if ( $pkgver->ver eq $matchver ) { 857 if ( $pkgver->ver eq $matchver ) {
858 $matchver = undef; 858 $matchver = undef;
859 last; 859 last;
860 } 860 }
861 } 861 }
862 else { 862 else {
863 if ( deweycmp( $pkgver->ver, $test, $matchver ) ) { 863 if ( deweycmp( $pkgver->ver, $test, $matchver ) ) {
864 $matchver = undef; 864 $matchver = undef;
865 last; 865 last;
866 } 866 }
867 } 867 }
868 } 868 }
869 869
870 if ( $matchver && $test ne '-' ) { 870 if ( $matchver && $test ne '-' ) {
871 $matchver = "$test$matchver"; 871 $matchver = "$test$matchver";
872 } 872 }
873 } 873 }
874 874
875 } 875 }
876 elsif ( $pkgmatch =~ /^([^[]+)-([\d*?{[].*)$/ ) { 876 elsif ( $pkgmatch =~ /^([^[]+)-([\d*?{[].*)$/ ) {
877 877
878 # (package)-(globver) 878 # (package)-(globver)
879 my (@pkgnames); 879 my (@pkgnames);
880 880
881 ( $matchpkgname, $matchver ) = ( $1, $2 ); 881 ( $matchpkgname, $matchver ) = ( $1, $2 );
882 882
883 if ( defined $pkglist->pkgs($matchpkgname) ) { 883 if ( defined $pkglist->pkgs($matchpkgname) ) {
884 push( @pkgnames, $matchpkgname ); 884 push( @pkgnames, $matchpkgname );
885 885
886 } 886 }
887 elsif ( $regex = glob2regex($matchpkgname) ) { 887 elsif ( $regex = glob2regex($matchpkgname) ) {
888 foreach my $pkg ( $pkglist->pkgs ) { 888 foreach my $pkg ( $pkglist->pkgs ) {
889 ( $pkg->pkg() =~ /$regex/ ) && push( @pkgnames, $pkg->pkg() ); 889 ( $pkg->pkg() =~ /$regex/ ) && push( @pkgnames, $pkg->pkg() );
890 } 890 }
891 } 891 }
892 892
893 # Try to convert $matchver into regex version 893 # Try to convert $matchver into regex version
894 # 894 #
895 $regex = glob2regex($matchver); 895 $regex = glob2regex($matchver);
896 896
897 foreach my $pkg (@pkgnames) { 897 foreach my $pkg (@pkgnames) {
898 if ( defined $pkglist->pkgver( $pkg, $matchver ) ) { 898 if ( defined $pkglist->pkgver( $pkg, $matchver ) ) {
899 return ($matchver); 899 return ($matchver);
900 } 900 }
901 901
902 if ($regex) { 902 if ($regex) {
903 foreach my $ver ( $pkglist->pkgs($pkg)->versions ) { 903 foreach my $ver ( $pkglist->pkgs($pkg)->versions ) {
904 if ( $ver =~ /$regex/ ) { 904 if ( $ver =~ /$regex/ ) {
905 $matchver = undef; 905 $matchver = undef;
906 last; 906 last;
907 } 907 }
908 } 908 }
909 } 909 }
910 910
911 $matchver || last; 911 $matchver || last;
912 } 912 }
913 913
914 # last ditch attempt to handle the whole DEPENDS as a glob 914 # last ditch attempt to handle the whole DEPENDS as a glob
915 # 915 #
916 if ( $matchver && ( $regex = glob2regex($pkgmatch) ) ) { 916 if ( $matchver && ( $regex = glob2regex($pkgmatch) ) ) {
917 917
918 # (large-glob) 918 # (large-glob)
919 foreach my $pkgver ( $pkglist->pkgver ) { 919 foreach my $pkgver ( $pkglist->pkgver ) {
920 if ( $pkgver->pkgname =~ /$regex/ ) { 920 if ( $pkgver->pkgname =~ /$regex/ ) {
921 $matchver = undef; 921 $matchver = undef;
922 last; 922 last;
923 } 923 }
924 } 924 }
925 } 925 }
926 926
927 } 927 }
928 else { 928 else {
929 ( $matchpkgname, $matchver ) = ( $pkgmatch, 'missing' ); 929 ( $matchpkgname, $matchver ) = ( $pkgmatch, 'missing' );
930 } 930 }
931 931
932 ( $matchpkgname, $matchver ); 932 ( $matchpkgname, $matchver );
933} 933}
934 934
935# Parse a pkgsrc package makefile and return the pkgname and set variables 935# Parse a pkgsrc package makefile and return the pkgname and set variables
936# 936#
937sub parse_makefile_pkgsrc($) { 937sub parse_makefile_pkgsrc($) {
938 my ($file) = @_; 938 my ($file) = @_;
939 my ( $pkgname, $vars ); 939 my ( $pkgname, $vars );
940 940
941 $vars = parse_makefile_vars($file); 941 $vars = parse_makefile_vars($file);
942 942
943 if ( !$vars ) { 943 if ( !$vars ) {
944 944
945 # Missing Makefile 945 # Missing Makefile
946 return undef; 946 return undef;
947 } 947 }
948 948
949 if ( defined $vars->{PKGNAME} ) { 949 if ( defined $vars->{PKGNAME} ) {
950 $pkgname = $vars->{PKGNAME}; 950 $pkgname = $vars->{PKGNAME};
951 951
952 } 952 }
953 elsif ( defined $vars->{DISTNAME} ) { 953 elsif ( defined $vars->{DISTNAME} ) {
954 $pkgname = $vars->{DISTNAME}; 954 $pkgname = $vars->{DISTNAME};
955 } 955 }
956 956
957 if ( defined $vars->{PKGNAME} ) { 957 if ( defined $vars->{PKGNAME} ) {
958 debug("$file: PKGNAME=$vars->{PKGNAME}\n"); 958 debug("$file: PKGNAME=$vars->{PKGNAME}\n");
959 } 959 }
960 if ( defined $vars->{DISTNAME} ) { 960 if ( defined $vars->{DISTNAME} ) {
961 debug("$file: DISTNAME=$vars->{DISTNAME}\n"); 961 debug("$file: DISTNAME=$vars->{DISTNAME}\n");
962 } 962 }
963 963
964 if ( !defined $pkgname || $pkgname !~ /(.*)-(\d.*)/ ) { 964 if ( !defined $pkgname || $pkgname !~ /(.*)-(\d.*)/ ) {
965 965
966 # invoke make here as a last resort 966 # invoke make here as a last resort
967 my ($pkgsrcdir) = ( $file =~ m:(/.*)/: ); 967 my ($pkgsrcdir) = ( $file =~ m:(/.*)/: );
968 my $pid = open3( \*WTR, \*RDR, \*ERR, 968 my $pid = open3( \*WTR, \*RDR, \*ERR,
969 "cd $pkgsrcdir ; ${conf_make} show-vars VARNAMES=PKGNAME" ); 969 "cd $pkgsrcdir ; ${conf_make} show-vars VARNAMES=PKGNAME" );
970 if ( !$pid ) { 970 if ( !$pid ) {
971 warn "$file: Unable to run make: $!"; 971 warn "$file: Unable to run make: $!";
972 } 972 }
973 else { 973 else {
974 close(WTR); 974 close(WTR);
975 my @errors = <ERR>; 975 my @errors = <ERR>;
976 close(ERR); 976 close(ERR);
977 my ($makepkgname) = <RDR>; 977 my ($makepkgname) = <RDR>;
978 close(RDR); 978 close(RDR);
979 wait; 979 wait;
980 chomp @errors; 980 chomp @errors;
981 if (@errors) { warn "\n$file: @errors\n"; } 981 if (@errors) { warn "\n$file: @errors\n"; }
982 982
983 if ( $makepkgname =~ /(.*)-(\d.*)/ ) { 983 if ( $makepkgname =~ /(.*)-(\d.*)/ ) {
984 $pkgname = $makepkgname; 984 $pkgname = $makepkgname;
985 } 985 }
986 } 986 }
987 } 987 }
988 988
989 if ( defined $pkgname ) { 989 if ( defined $pkgname ) {
990 if ( $pkgname =~ /^pkg_install-(\d+)$/ && $1 < $pkg_installver ) { 990 if ( $pkgname =~ /^pkg_install-(\d+)$/ && $1 < $pkg_installver ) {
991 $pkgname = "pkg_install-$pkg_installver"; 991 $pkgname = "pkg_install-$pkg_installver";
992 } 992 }
993 993
994 $pkgname = canonicalize_pkgname($pkgname); 994 $pkgname = canonicalize_pkgname($pkgname);
995 995
996 if ( defined $vars->{PKGREVISION} 996 if ( defined $vars->{PKGREVISION}
997 and not $vars->{PKGREVISION} =~ /^\s*$/ ) 997 and not $vars->{PKGREVISION} =~ /^\s*$/ )
998 { 998 {
999 if ( $vars->{PKGREVISION} =~ /\D/ ) { 999 if ( $vars->{PKGREVISION} =~ /^\$\{(_(CVS|GIT|HG|SVN)_PKGVERSION):.*\}$/ ) {
 1000 # See wip/mk/*-package.mk.
 1001 }
 1002 elsif ( $vars->{PKGREVISION} =~ /\D/ ) {
1000 print 1003 print
1001 "\nBogus: PKGREVISION $vars->{PKGREVISION} (from $file)\n"; 1004 "\nBogus: PKGREVISION $vars->{PKGREVISION} (from $file)\n";
1002 1005
1003 } 1006 }
1004 elsif ( $vars->{PKGREVISION} ) { 1007 elsif ( $vars->{PKGREVISION} ) {
1005 $pkgname .= "nb"; 1008 $pkgname .= "nb";
1006 $pkgname .= $vars->{PKGREVISION}; 1009 $pkgname .= $vars->{PKGREVISION};
1007 } 1010 }
1008 } 1011 }
1009 1012
1010 if ( $pkgname =~ /\$/ ) { 1013 if ( $pkgname =~ /\$/ ) {
1011 print "\nBogus: $pkgname (from $file)\n"; 1014 print "\nBogus: $pkgname (from $file)\n";
1012 1015
1013 } 1016 }
1014 elsif ( $pkgname =~ /(.*)-(\d.*)/ ) { 1017 elsif ( $pkgname =~ /(.*)-(\d.*)/ ) {
1015 if ($pkglist) { 1018 if ($pkglist) {
1016 my ($pkgver) = $pkglist->add( $1, $2 ); 1019 my ($pkgver) = $pkglist->add( $1, $2 );
1017 1020
1018 debug("add $1 $2\n"); 1021 debug("add $1 $2\n");
1019 1022
1020 foreach 1023 foreach
1021 my $var (qw(DEPENDS RESTRICTED OSVERSION_SPECIFIC BROKEN)) 1024 my $var (qw(DEPENDS RESTRICTED OSVERSION_SPECIFIC BROKEN))
1022 { 1025 {
1023 $pkgver->var( $var, $vars->{$var} ); 1026 $pkgver->var( $var, $vars->{$var} );
1024 } 1027 }
1025 1028
1026 if ( defined $vars->{NO_BIN_ON_FTP} ) { 1029 if ( defined $vars->{NO_BIN_ON_FTP} ) {
1027 $pkgver->var( 'RESTRICTED', 'NO_BIN_ON_FTP' ); 1030 $pkgver->var( 'RESTRICTED', 'NO_BIN_ON_FTP' );
1028 } 1031 }
1029 1032
1030 if ( $file =~ m:([^/]+/[^/]+)/Makefile$: ) { 1033 if ( $file =~ m:([^/]+/[^/]+)/Makefile$: ) {
1031 $pkgver->var( 'dir', $1 ); 1034 $pkgver->var( 'dir', $1 );
1032 } 1035 }
1033 else { 1036 else {
1034 $pkgver->var( 'dir', 'unknown' ); 1037 $pkgver->var( 'dir', 'unknown' );
1035 } 1038 }
1036 } 1039 }
1037 } 1040 }
1038 else { 1041 else {
1039 print "Cannot extract $pkgname version ($file)\n"; 1042 print "Cannot extract $pkgname version ($file)\n";
1040 } 1043 }
1041 1044
1042 return ( $pkgname, $vars ); 1045 return ( $pkgname, $vars );
1043 1046
1044 } 1047 }
1045 else { 1048 else {
1046 return (undef); 1049 return (undef);
1047 } 1050 }
1048} 1051}
1049 1052
1050# Extract variable assignments from Makefile 1053# Extract variable assignments from Makefile
1051# Much unpalatable magic to avoid having to use make (all for speed) 1054# Much unpalatable magic to avoid having to use make (all for speed)
1052# 1055#
1053sub parse_makefile_vars($$) { 1056sub parse_makefile_vars($$) {
1054 my ( $file, $cwd ) = @_; 1057 my ( $file, $cwd ) = @_;
1055 my ( 1058 my (
1056 $pkgname, %vars, $plus, $value, @data, 1059 $pkgname, %vars, $plus, $value, @data,
1057 %incfiles, # Cache of previously included fils 1060 %incfiles, # Cache of previously included fils
1058 %incdirs, # Directories in which to check for includes 1061 %incdirs, # Directories in which to check for includes
1059 @if_false 1062 @if_false
1060 ); # 0:true 1:false 2:nested-false&nomore-elsif 1063 ); # 0:true 1:false 2:nested-false&nomore-elsif
1061 1064
1062 if ( !open( FILE, $file ) ) { 1065 if ( !open( FILE, $file ) ) {
1063 return (undef); 1066 return (undef);
1064 } 1067 }
1065 @data = map { chomp; $_ } <FILE>; 1068 @data = map { chomp; $_ } <FILE>;
1066 close(FILE); 1069 close(FILE);
1067 1070
1068 $incdirs{"."} = 1; 1071 $incdirs{"."} = 1;
1069 $incdirs{ dirname($file) } = 1; 1072 $incdirs{ dirname($file) } = 1;
1070 1073
1071 # Some Makefiles depend on these being set 1074 # Some Makefiles depend on these being set
1072 if ( $file eq '/etc/mk.conf' ) { 1075 if ( $file eq '/etc/mk.conf' ) {
1073 $vars{LINTPKGSRC} = 'YES'; 1076 $vars{LINTPKGSRC} = 'YES';
1074 } 1077 }
1075 else { 1078 else {
1076 %vars = %{$default_vars}; 1079 %vars = %{$default_vars};
1077 } 1080 }
1078 $vars{BSD_PKG_MK} = 'YES'; 1081 $vars{BSD_PKG_MK} = 'YES';
1079 1082
1080 if ($cwd) { 1083 if ($cwd) {
1081 $vars{'.CURDIR'} = $cwd; 1084 $vars{'.CURDIR'} = $cwd;
1082 1085
1083 } 1086 }
1084 elsif ( $file =~ m#(.*)/# ) { 1087 elsif ( $file =~ m#(.*)/# ) {
1085 $vars{'.CURDIR'} = $1; 1088 $vars{'.CURDIR'} = $1;
1086 1089
1087 } 1090 }
1088 else { 1091 else {
1089 $vars{'.CURDIR'} = getcwd; 1092 $vars{'.CURDIR'} = getcwd;
1090 } 1093 }
1091 1094
1092 $incdirs{ $vars{'.CURDIR'} } = 1; 1095 $incdirs{ $vars{'.CURDIR'} } = 1;
1093 if ( $opt{L} ) { 1096 if ( $opt{L} ) {
1094 print "$file\n"; 1097 print "$file\n";
1095 } 1098 }
1096 1099
1097 while ( defined( $_ = shift(@data) ) ) { 1100 while ( defined( $_ = shift(@data) ) ) {
1098 s/\s*[^\\]#.*//; 1101 s/\s*[^\\]#.*//;
1099 1102
1100 # Continuation lines 1103 # Continuation lines
1101 # 1104 #
1102 while ( substr( $_, -1 ) eq "\\" ) { 1105 while ( substr( $_, -1 ) eq "\\" ) {
1103 substr( $_, -2 ) = shift @data; 1106 substr( $_, -2 ) = shift @data;
1104 } 1107 }
1105 1108
1106 # Conditionals 1109 # Conditionals
1107 # 1110 #
1108 if (m#^\.\s*if(|def|ndef)\s+(.*)#) { 1111 if (m#^\.\s*if(|def|ndef)\s+(.*)#) {
1109 my ( $type, $false ); 1112 my ( $type, $false );
1110 1113
1111 $type = $1; 1114 $type = $1;
1112 if ( $if_false[$#if_false] ) { 1115 if ( $if_false[$#if_false] ) {
1113 push( @if_false, 2 ); 1116 push( @if_false, 2 );
1114 1117
1115 } 1118 }
1116 elsif ( $type eq '' ) { 1119 elsif ( $type eq '' ) {
1117 1120
1118 # Straight if 1121 # Straight if
1119 push( @if_false, parse_eval_make_false( $2, \%vars ) ); 1122 push( @if_false, parse_eval_make_false( $2, \%vars ) );
1120 1123
1121 } 1124 }
1122 else { 1125 else {
1123 $false = !defined( $vars{ parse_expand_vars( $2, \%vars ) } ); 1126 $false = !defined( $vars{ parse_expand_vars( $2, \%vars ) } );
1124 if ( $type eq 'ndef' ) { 1127 if ( $type eq 'ndef' ) {
1125 $false = !$false; 1128 $false = !$false;
1126 } 1129 }
1127 push( @if_false, $false ? 1 : 0 ); 1130 push( @if_false, $false ? 1 : 0 );
1128 } 1131 }
1129 debug("$file: .if$type (! @if_false)\n"); 1132 debug("$file: .if$type (! @if_false)\n");
1130 next; 1133 next;
1131 } 1134 }
1132 1135
1133 if ( m#^\.\s*elif\s+(.*)# && @if_false ) { 1136 if ( m#^\.\s*elif\s+(.*)# && @if_false ) {
1134 if ( $if_false[$#if_false] == 0 ) { 1137 if ( $if_false[$#if_false] == 0 ) {
1135 $if_false[$#if_false] = 2; 1138 $if_false[$#if_false] = 2;
1136 } 1139 }
1137 elsif ( $if_false[$#if_false] == 1 1140 elsif ( $if_false[$#if_false] == 1
1138 && !parse_eval_make_false( $1, \%vars ) ) 1141 && !parse_eval_make_false( $1, \%vars ) )
1139 { 1142 {
1140 $if_false[$#if_false] = 0; 1143 $if_false[$#if_false] = 0;
1141 } 1144 }
1142 debug("$file: .elif (! @if_false)\n"); 1145 debug("$file: .elif (! @if_false)\n");
1143 next; 1146 next;
1144 } 1147 }
1145 1148
1146 if ( m#^\.\s*else\b# && @if_false ) { 1149 if ( m#^\.\s*else\b# && @if_false ) {
1147 $if_false[$#if_false] = $if_false[$#if_false] == 1 ? 0 : 1; 1150 $if_false[$#if_false] = $if_false[$#if_false] == 1 ? 0 : 1;
1148 debug("$file: .else (! @if_false)\n"); 1151 debug("$file: .else (! @if_false)\n");
1149 next; 1152 next;
1150 } 1153 }
1151 1154
1152 if (m#^\.\s*endif\b#) { 1155 if (m#^\.\s*endif\b#) {
1153 pop(@if_false); 1156 pop(@if_false);
1154 debug("$file: .endif (! @if_false)\n"); 1157 debug("$file: .endif (! @if_false)\n");
1155 next; 1158 next;
1156 } 1159 }
1157 1160
1158 $if_false[$#if_false] && next; 1161 $if_false[$#if_false] && next;
1159 1162
1160 # Included files (just unshift onto @data) 1163 # Included files (just unshift onto @data)
1161 # 1164 #
1162 if (m#^\.\s*include\s+"([^"]+)"#) { 1165 if (m#^\.\s*include\s+"([^"]+)"#) {
1163 my ($incfile) = parse_expand_vars( $1, \%vars ); 1166 my ($incfile) = parse_expand_vars( $1, \%vars );
1164 1167
1165 # At this point just skip any includes which we were not able to 1168 # At this point just skip any includes which we were not able to
1166 # fully expand 1169 # fully expand
1167 if ( $incfile =~ m#/mk/bsd# 1170 if ( $incfile =~ m#/mk/bsd#
1168 || $incfile =~ /$magic_undefined/ 1171 || $incfile =~ /$magic_undefined/
1169 || $incfile =~ /\$\{/ 1172 || $incfile =~ /\$\{/
1170 || ( !$opt{d} && $incfile =~ m#/(buildlink[^/]*\.mk)# ) ) 1173 || ( !$opt{d} && $incfile =~ m#/(buildlink[^/]*\.mk)# ) )
1171 { 1174 {
1172 debug("$file: .include \"$incfile\" skipped\n"); 1175 debug("$file: .include \"$incfile\" skipped\n");
1173 } 1176 }
1174 else { 1177 else {
1175 debug("$file: .include \"$incfile\"\n"); 1178 debug("$file: .include \"$incfile\"\n");
1176 1179
1177 # Expand any simple vars in $incfile 1180 # Expand any simple vars in $incfile
1178 # 1181 #
1179 1182
1180 if ( substr( $incfile, 0, 1 ) ne '/' ) { 1183 if ( substr( $incfile, 0, 1 ) ne '/' ) {
1181 foreach my $dir ( keys %incdirs ) { 1184 foreach my $dir ( keys %incdirs ) {
1182 if ( -f "$dir/$incfile" ) { 1185 if ( -f "$dir/$incfile" ) {
1183 $incfile = "$dir/$incfile"; 1186 $incfile = "$dir/$incfile";
1184 last; 1187 last;
1185 } 1188 }
1186 } 1189 }
1187 } 1190 }
1188 1191
1189 # perl 5.6.1 realpath() cannot handle files, only directories 1192 # perl 5.6.1 realpath() cannot handle files, only directories
1190 # If the last component is a symlink this will give a false 1193 # If the last component is a symlink this will give a false
1191 # negative, but that is not a problem as the duplicate check 1194 # negative, but that is not a problem as the duplicate check
1192 # is for performance 1195 # is for performance
1193 $incfile =~ m#^(.+)(/[^/]+)$#; 1196 $incfile =~ m#^(.+)(/[^/]+)$#;
1194 1197
1195 if ( !-f $incfile ) { 1198 if ( !-f $incfile ) {
1196 if ( !$opt{L} ) { 1199 if ( !$opt{L} ) {
1197 verbose("\n"); 1200 verbose("\n");
1198 } 1201 }
1199 1202
1200 verbose("$file: Cannot locate $incfile in " 1203 verbose("$file: Cannot locate $incfile in "
1201 . join( " ", sort keys %incdirs ) 1204 . join( " ", sort keys %incdirs )
1202 . "\n" ); 1205 . "\n" );
1203 1206
1204 } 1207 }
1205 else { 1208 else {
1206 $incfile = realpath($1) . $2; 1209 $incfile = realpath($1) . $2;
1207 1210
1208 if ( !$incfiles{$incfile} ) { 1211 if ( !$incfiles{$incfile} ) {
1209 if ( $opt{L} ) { 1212 if ( $opt{L} ) {
1210 print "inc $incfile\n"; 1213 print "inc $incfile\n";
1211 } 1214 }
1212 $incfiles{$incfile} = 1; 1215 $incfiles{$incfile} = 1;
1213 1216
1214 if ( !open( FILE, $incfile ) ) { 1217 if ( !open( FILE, $incfile ) ) {
1215 verbose( 1218 verbose(
1216 "Cannot open '$incfile' (from $file): $_ $!\n"); 1219 "Cannot open '$incfile' (from $file): $_ $!\n");
1217 } 1220 }
1218 else { 1221 else {
1219 my $NEWCURDIR = $incfile; 1222 my $NEWCURDIR = $incfile;
1220 $NEWCURDIR =~ s#/[^/]*$##; 1223 $NEWCURDIR =~ s#/[^/]*$##;
1221 $incdirs{$NEWCURDIR} = 1; 1224 $incdirs{$NEWCURDIR} = 1;
1222 unshift( @data, ".CURDIR=$vars{'.CURDIR'}" ); 1225 unshift( @data, ".CURDIR=$vars{'.CURDIR'}" );
1223 unshift( @data, map { chomp; $_ } <FILE> ); 1226 unshift( @data, map { chomp; $_ } <FILE> );
1224 unshift( @data, ".CURDIR=$NEWCURDIR" ); 1227 unshift( @data, ".CURDIR=$NEWCURDIR" );
1225 close(FILE); 1228 close(FILE);
1226 } 1229 }
1227 } 1230 }
1228 } 1231 }
1229 } 1232 }
1230 next; 1233 next;
1231 } 1234 }
1232 1235
1233 if (/^ *([-\w\.]+)\s*([:+?]?)=\s*(.*)/) { 1236 if (/^ *([-\w\.]+)\s*([:+?]?)=\s*(.*)/) {
1234 my ($key); 1237 my ($key);
1235 1238
1236 $key = $1; 1239 $key = $1;
1237 $plus = $2; 1240 $plus = $2;
1238 $value = $3; 1241 $value = $3;
1239 1242
1240 if ( $plus eq ':' ) { 1243 if ( $plus eq ':' ) {
1241 $vars{$key} = parse_expand_vars( $value, \%vars ); 1244 $vars{$key} = parse_expand_vars( $value, \%vars );
1242 } 1245 }
1243 elsif ( $plus eq '+' && defined $vars{$key} ) { 1246 elsif ( $plus eq '+' && defined $vars{$key} ) {
1244 $vars{$key} .= " $value"; 1247 $vars{$key} .= " $value";
1245 } 1248 }
1246 elsif ( $plus ne '?' || !defined $vars{$key} ) { 1249 elsif ( $plus ne '?' || !defined $vars{$key} ) {
1247 $vars{$key} = $value; 1250 $vars{$key} = $value;
1248 } 1251 }
1249 debug("assignment: $key$plus=[$value] ($vars{$key})\n"); 1252 debug("assignment: $key$plus=[$value] ($vars{$key})\n");
1250 1253
1251 # Give python a little hand (XXX - do we wanna consider actually 1254 # Give python a little hand (XXX - do we wanna consider actually
1252 # implementing make .for loops, etc? 1255 # implementing make .for loops, etc?
1253 # 1256 #
1254 if ( $key eq "PYTHON_VERSIONS_ACCEPTED" ) { 1257 if ( $key eq "PYTHON_VERSIONS_ACCEPTED" ) {
1255 my ($pv); 1258 my ($pv);
1256 1259
1257 foreach $pv ( split( /\s+/, $vars{PYTHON_VERSIONS_ACCEPTED} ) ) 1260 foreach $pv ( split( /\s+/, $vars{PYTHON_VERSIONS_ACCEPTED} ) )
1258 { 1261 {
1259 $vars{"_PYTHON_VERSION_FIRSTACCEPTED"} ||= $pv; 1262 $vars{"_PYTHON_VERSION_FIRSTACCEPTED"} ||= $pv;
1260 $vars{"_PYTHON_VERSION_${pv}_OK"} = "yes"; 1263 $vars{"_PYTHON_VERSION_${pv}_OK"} = "yes";
1261 } 1264 }
1262 } 1265 }
1263 } 1266 }
1264 } 1267 }
1265 1268
1266 debug("$file: expand\n"); 1269 debug("$file: expand\n");
1267 1270
1268 # Handle variable substitutions FRED = a-${JIM:S/-/-b-/} 1271 # Handle variable substitutions FRED = a-${JIM:S/-/-b-/}
1269 # 1272 #
1270 my ($loop); 1273 my ($loop);
1271 1274
1272 for ( $loop = 1 ; $loop ; ) { 1275 for ( $loop = 1 ; $loop ; ) {
1273 $loop = 0; 1276 $loop = 0;
1274 foreach my $key ( keys %vars ) { 1277 foreach my $key ( keys %vars ) {
1275 if ( index( $vars{$key}, '$' ) == -1 ) { 1278 if ( index( $vars{$key}, '$' ) == -1 ) {
1276 next; 1279 next;
1277 } 1280 }
1278 1281
1279 $_ = parse_expand_vars( $vars{$key}, \%vars ); 1282 $_ = parse_expand_vars( $vars{$key}, \%vars );
1280 if ( $_ ne $vars{$key} ) { 1283 if ( $_ ne $vars{$key} ) {
1281 $vars{$key} = $_; 1284 $vars{$key} = $_;
1282 $loop = 1; 1285 $loop = 1;
1283 1286
1284 } 1287 }
1285 elsif ( $vars{$key} =~ 1288 elsif ( $vars{$key} =~
1286 m#\$\{([\w.]+):([CS]([^{}])[^{}\3]+\3[^{}\3]*\3[g1]*(|:[^{}]+)|U[^{}]+)\}# ) 1289 m#\$\{([\w.]+):([CS]([^{}])[^{}\3]+\3[^{}\3]*\3[g1]*(|:[^{}]+)|U[^{}]+)\}# )
1287 { 1290 {
1288 my ( $left, $subvar, $right ) = ( $`, $1, $' ); 1291 my ( $left, $subvar, $right ) = ( $`, $1, $' );
1289 my (@patterns) = split( ':', $2 ); 1292 my (@patterns) = split( ':', $2 );
1290 my ($result); 1293 my ($result);
1291 1294
1292 $result = $vars{$subvar}; 1295 $result = $vars{$subvar};
1293 $result ||= ''; 1296 $result ||= '';
1294 1297
1295 # If $vars{$subvar} contains a $ skip it on this pass. 1298 # If $vars{$subvar} contains a $ skip it on this pass.
1296 # Hopefully it will get substituted and we can catch it 1299 # Hopefully it will get substituted and we can catch it
1297 # next time around. 1300 # next time around.
1298 if ( index( $result, '${' ) != -1 ) { 1301 if ( index( $result, '${' ) != -1 ) {
1299 next; 1302 next;
1300 } 1303 }
1301 1304
1302 debug( 1305 debug(
1303 "$file: substitutelist $key ($result) $subvar (@patterns)\n" 1306 "$file: substitutelist $key ($result) $subvar (@patterns)\n"
1304 ); 1307 );
1305 foreach (@patterns) { 1308 foreach (@patterns) {
1306 if (m#(U)(.*)#) { 1309 if (m#(U)(.*)#) {
1307 $result ||= $2; 1310 $result ||= $2;
1308 } elsif (m#([CS])(.)([^/]+)\2([^/]*)\2([1g]*)#) { 1311 } elsif (m#([CS])(.)([^/]+)\2([^/]*)\2([1g]*)#) {
1309 1312
1310 my ( $how, $from, $to, $global ) = ( $1, $3, $4, $5 ); 1313 my ( $how, $from, $to, $global ) = ( $1, $3, $4, $5 );
1311 1314
1312 debug( 1315 debug(
1313"$file: substituteglob $subvar, $how, $from, $to, $global\n" 1316"$file: substituteglob $subvar, $how, $from, $to, $global\n"
1314 ); 1317 );
1315 if ( $how eq 'S' ) { 1318 if ( $how eq 'S' ) {
1316 1319
1317 # Limited substitution - keep ^ and $ 1320 # Limited substitution - keep ^ and $
1318 $from =~ s/([?.{}\]\[*+])/\\$1/g; 1321 $from =~ s/([?.{}\]\[*+])/\\$1/g;
1319 } 1322 }
1320 $to =~ s/\\(\d)/\$$1/g; # Change \1 etc to $1 1323 $to =~ s/\\(\d)/\$$1/g; # Change \1 etc to $1
1321 $to =~ s/\&/\$&/g; # Change & to $1 1324 $to =~ s/\&/\$&/g; # Change & to $1
1322 1325
1323 my ($notfirst); 1326 my ($notfirst);
1324 if ( $global =~ s/1// ) { 1327 if ( $global =~ s/1// ) {
1325 ( $from, $notfirst ) = split( '\s', $from, 2 ); 1328 ( $from, $notfirst ) = split( '\s', $from, 2 );
1326 } 1329 }
1327 1330
1328 debug( 1331 debug(
1329 "$file: substituteperl $subvar, $how, $from, $to\n" 1332 "$file: substituteperl $subvar, $how, $from, $to\n"
1330 ); 1333 );
1331 eval "\$result =~ s/$from/$to/$global"; 1334 eval "\$result =~ s/$from/$to/$global";
1332 if ( defined $notfirst ) { 1335 if ( defined $notfirst ) {
1333 $result .= " $notfirst"; 1336 $result .= " $notfirst";
1334 } 1337 }
1335 } 1338 }
1336 else { 1339 else {
1337 next; 1340 next;
1338 } 1341 }
1339 } 1342 }
1340 1343
1341 $vars{$key} = $left . $result . $right; 1344 $vars{$key} = $left . $result . $right;
1342 $loop = 1; 1345 $loop = 1;
1343 } 1346 }
1344 } 1347 }
1345 } 1348 }
1346 1349
1347 foreach my $key ( keys %vars ) { 1350 foreach my $key ( keys %vars ) {
1348 $vars{$key} =~ s/$magic_undefined//; 1351 $vars{$key} =~ s/$magic_undefined//;
1349 } 1352 }
1350 \%vars; 1353 \%vars;
1351} 1354}
1352 1355
1353sub parse_expand_vars($$) { 1356sub parse_expand_vars($$) {
1354 my ( $line, $vars ) = @_; 1357 my ( $line, $vars ) = @_;
1355 1358
1356 while ( $line =~ /\$\{([-\w.]+)\}/ ) { 1359 while ( $line =~ /\$\{([-\w.]+)\}/ ) {
1357 if ( defined( ${$vars}{$1} ) ) { 1360 if ( defined( ${$vars}{$1} ) ) {
1358 $line = $` . ${$vars}{$1} . $'; 1361 $line = $` . ${$vars}{$1} . $';
1359 } 1362 }
1360 else { 1363 else {
1361 $line = $` . $magic_undefined . $'; 1364 $line = $` . $magic_undefined . $';
1362 } 1365 }
1363 } 1366 }
1364 $line; 1367 $line;
1365} 1368}
1366 1369
1367sub parse_expand_vars_dumb($$) { 1370sub parse_expand_vars_dumb($$) {
1368 my ( $line, $vars ) = @_; 1371 my ( $line, $vars ) = @_;
1369 1372
1370 while ( $line =~ /\$\{([-\w.]+)\}/ ) { 1373 while ( $line =~ /\$\{([-\w.]+)\}/ ) {
1371 if ( defined( ${$vars}{$1} ) ) { 1374 if ( defined( ${$vars}{$1} ) ) {
1372 $line = $` . ${$vars}{$1} . $'; 1375 $line = $` . ${$vars}{$1} . $';
1373 } 1376 }
1374 else { 1377 else {
1375 $line = $` . $magic_undefined . $'; 1378 $line = $` . $magic_undefined . $';
1376 } 1379 }
1377 } 1380 }
1378 $line; 1381 $line;
1379} 1382}
1380 1383
1381sub parse_eval_make_false($$) { 1384sub parse_eval_make_false($$) {
1382 my ( $line, $vars ) = @_; 1385 my ( $line, $vars ) = @_;
1383 my ( $false, $test ); 1386 my ( $false, $test );
1384 1387
1385 $false = 0; 1388 $false = 0;
1386 $test = parse_expand_vars_dumb( $line, $vars ); 1389 $test = parse_expand_vars_dumb( $line, $vars );
1387 1390
1388 # XXX This is _so_ wrong - need to parse this correctly 1391 # XXX This is _so_ wrong - need to parse this correctly
1389 $test =~ s/""/\r/g; 1392 $test =~ s/""/\r/g;
1390 $test =~ s/"//g; # " 1393 $test =~ s/"//g; # "
1391 $test =~ s/\r/""/g; 1394 $test =~ s/\r/""/g;
1392 1395
1393 debug("conditional: $test\n"); 1396 debug("conditional: $test\n");
1394 1397
1395 # XXX Could do something with target 1398 # XXX Could do something with target
1396 while ( $test =~ /(target|empty|make|defined|exists)\s*\(([^()]+)\)/ ) { 1399 while ( $test =~ /(target|empty|make|defined|exists)\s*\(([^()]+)\)/ ) {
1397 my $testname = $1; 1400 my $testname = $1;
1398 my $varname = $2; 1401 my $varname = $2;
1399 my $var; 1402 my $var;
1400 1403
1401 # Implement (some of) make's :M modifier 1404 # Implement (some of) make's :M modifier
1402 if ( $varname =~ /^([^:]+):M(.+)$/ ) { 1405 if ( $varname =~ /^([^:]+):M(.+)$/ ) {
1403 $varname = $1; 1406 $varname = $1;
1404 my $match = $2; 1407 my $match = $2;
1405 1408
1406 $var = $${vars}{$varname}; 1409 $var = $${vars}{$varname};
1407 $var = parse_expand_vars( $var, $vars ) if defined $var; 1410 $var = parse_expand_vars( $var, $vars ) if defined $var;
1408 1411
1409 $match =~ s/([{.+])/\\$1/g; 1412 $match =~ s/([{.+])/\\$1/g;
1410 $match =~ s/\*/.*/g; 1413 $match =~ s/\*/.*/g;
1411 $match =~ s/\?/./g; 1414 $match =~ s/\?/./g;
1412 $match = '^' . $match . '$'; 1415 $match = '^' . $match . '$';
1413 $var = ( $var =~ /$match/ ) if defined $var; 1416 $var = ( $var =~ /$match/ ) if defined $var;
1414 } 1417 }
1415 else { 1418 else {
1416 $var = $${vars}{$varname}; 1419 $var = $${vars}{$varname};
1417 $var = parse_expand_vars( $var, $vars ) if defined $var; 1420 $var = parse_expand_vars( $var, $vars ) if defined $var;
1418 } 1421 }
1419 1422
1420 if ( defined $var && $var eq $magic_undefined ) { 1423 if ( defined $var && $var eq $magic_undefined ) {
1421 $var = undef; 1424 $var = undef;
1422 } 1425 }
1423 1426
1424 if ( $testname eq 'exists' ) { 1427 if ( $testname eq 'exists' ) {
1425 $_ = ( -e $varname ) ? 1 : 0; 1428 $_ = ( -e $varname ) ? 1 : 0;
1426 1429
1427 } 1430 }
1428 elsif ( $testname eq 'defined' ) { 1431 elsif ( $testname eq 'defined' ) {
1429 $_ = defined($var) ? 1 : 0; 1432 $_ = defined($var) ? 1 : 0;
1430 1433
1431 } 1434 }
1432 elsif ( $testname eq 'empty' ) { 1435 elsif ( $testname eq 'empty' ) {
1433 $_ = ( ( not defined($var) or ( length($var) == 0 ) ) ? 1 : 0 ); 1436 $_ = ( ( not defined($var) or ( length($var) == 0 ) ) ? 1 : 0 );
1434 1437
1435 } 1438 }
1436 else { 1439 else {
1437 $_ = 0; 1440 $_ = 0;
1438 } 1441 }
1439 1442
1440 $test =~ s/$testname\s*\([^()]+\)/$_/; 1443 $test =~ s/$testname\s*\([^()]+\)/$_/;
1441 debug("conditional: update to $test\n"); 1444 debug("conditional: update to $test\n");
1442 } 1445 }
1443 1446
1444 while ( $test =~ /([^\s()\|\&]+)\s+(!=|==)\s+([^\s()]+)/ ) { 1447 while ( $test =~ /([^\s()\|\&]+)\s+(!=|==)\s+([^\s()]+)/ ) {
1445 if ( $2 eq '==' ) { 1448 if ( $2 eq '==' ) {
1446 $_ = ( $1 eq $3 ) ? 1 : 0; 1449 $_ = ( $1 eq $3 ) ? 1 : 0;
1447 } 1450 }
1448 else { 1451 else {
1449 $_ = ( $1 ne $3 ) ? 1 : 0; 1452 $_ = ( $1 ne $3 ) ? 1 : 0;
1450 } 1453 }
1451 $test =~ s/[^\s()\|\&]+\s+(!=|==)\s+[^\s()]+/$_/; 1454 $test =~ s/[^\s()\|\&]+\s+(!=|==)\s+[^\s()]+/$_/;
1452 } 1455 }
1453 1456
1454 if ( $test !~ /[^<>\d()\s&|.!]/ ) { 1457 if ( $test !~ /[^<>\d()\s&|.!]/ ) {
1455 $false = eval "($test)?0:1"; 1458 $false = eval "($test)?0:1";
1456 if ( !defined $false ) { 1459 if ( !defined $false ) {
1457 fail("Eval failed $line - $test"); 1460 fail("Eval failed $line - $test");
1458 } 1461 }
1459 debug( "conditional: evaluated to " . ( $false ? 0 : 1 ) . "\n" ); 1462 debug( "conditional: evaluated to " . ( $false ? 0 : 1 ) . "\n" );
1460 1463
1461 } 1464 }
1462 else { 1465 else {
1463 $false = 0; 1466 $false = 0;
1464 debug("conditional: defaulting to 0\n"); 1467 debug("conditional: defaulting to 0\n");
1465 } 1468 }
1466 $false; 1469 $false;
1467} 1470}
1468 1471
1469# chdir() || fail() 1472# chdir() || fail()
1470# 1473#
1471sub safe_chdir($) { 1474sub safe_chdir($) {
1472 my ($dir) = @_; 1475 my ($dir) = @_;
1473 1476
1474 debug("chdir: $dir"); 1477 debug("chdir: $dir");
1475 if ( !chdir($dir) ) { 1478 if ( !chdir($dir) ) {
1476 fail("Unable to chdir($dir): $!"); 1479 fail("Unable to chdir($dir): $!");
1477 } 1480 }
1478} 1481}
1479 1482
1480# Generate pkgname->category/pkg mapping, optionally check DEPENDS 1483# Generate pkgname->category/pkg mapping, optionally check DEPENDS
1481# 1484#
1482sub scan_pkgsrc_makefiles($$) { 1485sub scan_pkgsrc_makefiles($$) {
1483 my ( $pkgsrcdir, $check_depends ) = @_; 1486 my ( $pkgsrcdir, $check_depends ) = @_;
1484 my (@categories); 1487 my (@categories);
1485 1488
1486 if ($pkglist) { 1489 if ($pkglist) {
1487 1490
1488 # Already done 1491 # Already done
1489 return; 1492 return;
1490 } 1493 }
1491 1494
1492 if ( $opt{I} ) { 1495 if ( $opt{I} ) {
1493 load_pkgsrc_makefiles( $opt{I} ); 1496 load_pkgsrc_makefiles( $opt{I} );
1494 return; 1497 return;
1495 } 1498 }
1496 1499
1497 $pkglist = new PkgList; 1500 $pkglist = new PkgList;
1498 @categories = list_pkgsrc_categories($pkgsrcdir); 1501 @categories = list_pkgsrc_categories($pkgsrcdir);
1499 verbose('Scan Makefiles: '); 1502 verbose('Scan Makefiles: ');
1500 1503
1501 if ( !$opt{L} ) { 1504 if ( !$opt{L} ) {
1502 verbose( '_' x @categories . "\b" x @categories ); 1505 verbose( '_' x @categories . "\b" x @categories );
1503 } 1506 }
1504 else { 1507 else {
1505 verbose("\n"); 1508 verbose("\n");
1506 } 1509 }
1507 1510
1508 foreach my $cat ( sort @categories ) { 1511 foreach my $cat ( sort @categories ) {
1509 foreach my $pkgdir ( list_pkgsrc_pkgdirs( $pkgsrcdir, $cat ) ) { 1512 foreach my $pkgdir ( list_pkgsrc_pkgdirs( $pkgsrcdir, $cat ) ) {
1510 my ( $pkg, $vars ) = 1513 my ( $pkg, $vars ) =
1511 parse_makefile_pkgsrc("$pkgsrcdir/$cat/$pkgdir/Makefile"); 1514 parse_makefile_pkgsrc("$pkgsrcdir/$cat/$pkgdir/Makefile");
1512 } 1515 }
1513 1516
1514 if ( !$opt{L} ) { 1517 if ( !$opt{L} ) {
1515 verbose('.'); 1518 verbose('.');
1516 } 1519 }
1517 } 1520 }
1518 1521
1519 if ( !$opt{L} ) { 1522 if ( !$opt{L} ) {
1520 my ($len); 1523 my ($len);
1521 1524
1522 $_ = $pkglist->numpkgver() . ' packages'; 1525 $_ = $pkglist->numpkgver() . ' packages';
1523 $len = @categories - length($_); 1526 $len = @categories - length($_);
1524 verbose( "\b" x @categories, $_, ' ' x $len, "\b" x $len, "\n" ); 1527 verbose( "\b" x @categories, $_, ' ' x $len, "\b" x $len, "\n" );
1525 } 1528 }
1526} 1529}
1527 1530
1528# Cross reference all depends 1531# Cross reference all depends
1529# 1532#
1530sub pkgsrc_check_depends() { 1533sub pkgsrc_check_depends() {
1531 1534
1532 foreach my $pkgver ( $pkglist->pkgver ) { 1535 foreach my $pkgver ( $pkglist->pkgver ) {
1533 my ( $err, $msg ); 1536 my ( $err, $msg );
1534 1537
1535 defined $pkgver->var('DEPENDS') || next; 1538 defined $pkgver->var('DEPENDS') || next;
1536 foreach my $depend ( split( " ", $pkgver->var('DEPENDS') ) ) { 1539 foreach my $depend ( split( " ", $pkgver->var('DEPENDS') ) ) {
1537 1540
1538 $depend =~ s/:.*// || next; 1541 $depend =~ s/:.*// || next;
1539 1542
1540 $depend = canonicalize_pkgname($depend); 1543 $depend = canonicalize_pkgname($depend);
1541 if ( ( $msg = invalid_version($depend) ) ) { 1544 if ( ( $msg = invalid_version($depend) ) ) {
1542 if ( !defined($err) ) { 1545 if ( !defined($err) ) {
1543 print $pkgver->pkgname . " DEPENDS errors:\n"; 1546 print $pkgver->pkgname . " DEPENDS errors:\n";
1544 } 1547 }
1545 $err = 1; 1548 $err = 1;
1546 $msg =~ s/(\n)(.)/$1\t$2/g; 1549 $msg =~ s/(\n)(.)/$1\t$2/g;
1547 print "\t$msg"; 1550 print "\t$msg";
1548 } 1551 }
1549 } 1552 }
1550 } 1553 }
1551} 1554}
1552 1555
1553# Extract all distinfo entries, then verify contents of distfiles 1556# Extract all distinfo entries, then verify contents of distfiles
1554# 1557#
1555sub scan_pkgsrc_distfiles_vs_distinfo($$$$) { 1558sub scan_pkgsrc_distfiles_vs_distinfo($$$$) {
1556 my ( $pkgsrcdir, $pkgdistdir, $check_unref, $check_distinfo ) = @_; 1559 my ( $pkgsrcdir, $pkgdistdir, $check_unref, $check_distinfo ) = @_;
1557 my (@categories); 1560 my (@categories);
1558 my ( %distfiles, %sumfiles, @distwarn, $numpkg ); 1561 my ( %distfiles, %sumfiles, @distwarn, $numpkg );
1559 my (%bad_distfiles); 1562 my (%bad_distfiles);
1560 1563
1561 @categories = list_pkgsrc_categories($pkgsrcdir); 1564 @categories = list_pkgsrc_categories($pkgsrcdir);
1562 1565
1563 verbose( 'Scan distinfo: ' . '_' x @categories . "\b" x @categories ); 1566 verbose( 'Scan distinfo: ' . '_' x @categories . "\b" x @categories );
1564 $numpkg = 0; 1567 $numpkg = 0;
1565 foreach my $cat ( sort @categories ) { 1568 foreach my $cat ( sort @categories ) {
1566 foreach my $pkgdir ( list_pkgsrc_pkgdirs( $pkgsrcdir, $cat ) ) { 1569 foreach my $pkgdir ( list_pkgsrc_pkgdirs( $pkgsrcdir, $cat ) ) {
1567 if ( open( DISTINFO, "$pkgsrcdir/$cat/$pkgdir/distinfo" ) ) { 1570 if ( open( DISTINFO, "$pkgsrcdir/$cat/$pkgdir/distinfo" ) ) {
1568 ++$numpkg; 1571 ++$numpkg;
1569 while (<DISTINFO>) { 1572 while (<DISTINFO>) {
1570 if (m/^(\w+) ?\(([^\)]+)\) = (\S+)/) { 1573 if (m/^(\w+) ?\(([^\)]+)\) = (\S+)/) {
1571 my ( $dn, $ds, $dt ); 1574 my ( $dn, $ds, $dt );
1572 $dt = $1; 1575 $dt = $1;
1573 $dn = $2; 1576 $dn = $2;
1574 $ds = $3; 1577 $ds = $3;
1575 if ( $dn =~ /^patch-[\w.+\-]+$/ ) { 1578 if ( $dn =~ /^patch-[\w.+\-]+$/ ) {
1576 next; 1579 next;
1577 } 1580 }
1578 1581
1579 # Strip leading ./ which sometimes gets added 1582 # Strip leading ./ which sometimes gets added
1580 # because of DISTSUBDIR=. 1583 # because of DISTSUBDIR=.
1581 $dn =~ s/^(\.\/)*//; 1584 $dn =~ s/^(\.\/)*//;
1582 if ( !defined $distfiles{$dn} ) { 1585 if ( !defined $distfiles{$dn} ) {
1583 $distfiles{$dn}{sumtype} = $dt; 1586 $distfiles{$dn}{sumtype} = $dt;
1584 $distfiles{$dn}{sum} = $ds; 1587 $distfiles{$dn}{sum} = $ds;
1585 $distfiles{$dn}{path} = "$cat/$pkgdir"; 1588 $distfiles{$dn}{path} = "$cat/$pkgdir";
1586 1589
1587 } 1590 }
1588 elsif ($distfiles{$dn}{sumtype} eq $dt 1591 elsif ($distfiles{$dn}{sumtype} eq $dt
1589 && $distfiles{$dn}{sum} ne $ds ) 1592 && $distfiles{$dn}{sum} ne $ds )
1590 { 1593 {
1591 push( @distwarn, 1594 push( @distwarn,
1592 "checksum mismatch between '$dt' for '$dn' " 1595 "checksum mismatch between '$dt' for '$dn' "
1593 . "in $cat/$pkgdir and $distfiles{$dn}{path}\n" 1596 . "in $cat/$pkgdir and $distfiles{$dn}{path}\n"
1594 ); 1597 );
1595 } 1598 }
1596 } 1599 }
1597 } 1600 }
1598 close(DISTINFO); 1601 close(DISTINFO);
1599 } 1602 }
1600 } 1603 }
1601 verbose('.'); 1604 verbose('.');
1602 } 1605 }
1603 verbose(" ($numpkg packages)\n"); 1606 verbose(" ($numpkg packages)\n");
1604 1607
1605# check each file in $pkgdistdir 1608# check each file in $pkgdistdir
1606 find ( { wanted => sub { 1609 find ( { wanted => sub {
1607 my ($dist); 1610 my ($dist);
1608 if ( -f $File::Find::name ) 1611 if ( -f $File::Find::name )
1609 { 1612 {
1610 my $distn = $File::Find::name; 1613 my $distn = $File::Find::name;
1611 $distn =~ s/$pkgdistdir\/?//g; 1614 $distn =~ s/$pkgdistdir\/?//g;
1612 #pkg/47516 ignore cvs dirs 1615 #pkg/47516 ignore cvs dirs
1613 return if $distn =~ m/^\.cvsignore/; 1616 return if $distn =~ m/^\.cvsignore/;
1614 return if $distn =~ m/^CVS\//; 1617 return if $distn =~ m/^CVS\//;
1615 if ( !defined ($dist = $distfiles{$distn} ) ) { 1618 if ( !defined ($dist = $distfiles{$distn} ) ) {
1616 $bad_distfiles{$distn} = 1; 1619 $bad_distfiles{$distn} = 1;
1617 } 1620 }
1618 else { 1621 else {
1619 if ( $dist->{sum} ne 'IGNORE' ) { 1622 if ( $dist->{sum} ne 'IGNORE' ) {
1620 push( @{ $sumfiles{ $dist->{sumtype} } }, $distn ); 1623 push( @{ $sumfiles{ $dist->{sumtype} } }, $distn );
1621 } 1624 }
1622 } 1625 }
1623 } 1626 }
1624 } }, 1627 } },
1625 ($pkgdistdir) ); 1628 ($pkgdistdir) );
1626 1629
1627 if ( $check_unref && %bad_distfiles ) { 1630 if ( $check_unref && %bad_distfiles ) {
1628 verbose( scalar( keys %bad_distfiles ), 1631 verbose( scalar( keys %bad_distfiles ),
1629 " unreferenced file(s) in '$pkgdistdir':\n" ); 1632 " unreferenced file(s) in '$pkgdistdir':\n" );
1630 print join( "\n", sort keys %bad_distfiles ), "\n"; 1633 print join( "\n", sort keys %bad_distfiles ), "\n";
1631 } 1634 }
1632 1635
1633 if ($check_distinfo) { 1636 if ($check_distinfo) {
1634 if (@distwarn) { 1637 if (@distwarn) {
1635 verbose(@distwarn); 1638 verbose(@distwarn);
1636 } 1639 }
1637 1640
1638 verbose("checksum mismatches\n"); 1641 verbose("checksum mismatches\n");
1639 safe_chdir($pkgdistdir); 1642 safe_chdir($pkgdistdir);
1640 foreach my $sum ( keys %sumfiles ) { 1643 foreach my $sum ( keys %sumfiles ) {
1641 if ( $sum eq 'Size' ) { 1644 if ( $sum eq 'Size' ) {
1642 foreach my $file ( @{ $sumfiles{$sum} } ) { 1645 foreach my $file ( @{ $sumfiles{$sum} } ) {
1643 if ( !-f $file || -S $file != $distfiles{$file}{sum} ) { 1646 if ( !-f $file || -S $file != $distfiles{$file}{sum} ) {
1644 print $file, " (Size)\n"; 1647 print $file, " (Size)\n";
1645 $bad_distfiles{$file} = 1; 1648 $bad_distfiles{$file} = 1;
1646 } 1649 }
1647 } 1650 }
1648 next; 1651 next;
1649 } 1652 }
1650 1653
1651 my $pid = open3(my $in, my $out, undef, "xargs", "digest", $sum); 1654 my $pid = open3(my $in, my $out, undef, "xargs", "digest", $sum);
1652 defined($pid) || fail "fork"; 1655 defined($pid) || fail "fork";
1653 my $pid2 = fork(); 1656 my $pid2 = fork();
1654 defined($pid2) || fail "fork"; 1657 defined($pid2) || fail "fork";
1655 if ($pid2) { 1658 if ($pid2) {
1656 close($in); 1659 close($in);
1657 } else { 1660 } else {
1658 print $in "@{$sumfiles{$sum}}"; 1661 print $in "@{$sumfiles{$sum}}";
1659 exit 0; 1662 exit 0;
1660 } 1663 }
1661 while (<$out>) { 1664 while (<$out>) {
1662 if (m/^$sum ?\(([^\)]+)\) = (\S+)/) { 1665 if (m/^$sum ?\(([^\)]+)\) = (\S+)/) {
1663 if ( $distfiles{$1}{sum} ne $2 ) { 1666 if ( $distfiles{$1}{sum} ne $2 ) {
1664 print $1, " ($sum)\n"; 1667 print $1, " ($sum)\n";
1665 $bad_distfiles{$1} = 1; 1668 $bad_distfiles{$1} = 1;
1666 } 1669 }
1667 } 1670 }
1668 } 1671 }
1669 close($out); 1672 close($out);
1670 waitpid( $pid, 0 ) || fail "xargs digest $sum"; 1673 waitpid( $pid, 0 ) || fail "xargs digest $sum";
1671 waitpid( $pid2, 0 ) || fail "pipe write to xargs"; 1674 waitpid( $pid2, 0 ) || fail "pipe write to xargs";
1672 } 1675 }
1673 safe_chdir('/'); # Do not want to stay in $pkgdistdir 1676 safe_chdir('/'); # Do not want to stay in $pkgdistdir
1674 } 1677 }
1675 ( sort keys %bad_distfiles ); 1678 ( sort keys %bad_distfiles );
1676} 1679}
1677 1680
1678sub load_pkgsrc_makefiles() { 1681sub load_pkgsrc_makefiles() {
1679 1682
1680 open( STORE, "<$_[0]" ) || die("Cannot read pkgsrc store from $_[0]: $!\n"); 1683 open( STORE, "<$_[0]" ) || die("Cannot read pkgsrc store from $_[0]: $!\n");
1681 my ($pkgver); 1684 my ($pkgver);
1682 our ( $pkgcnt, $pkgnum, $subpkgcnt, $subpkgnum ); 1685 our ( $pkgcnt, $pkgnum, $subpkgcnt, $subpkgnum );
1683 $pkglist = new PkgList; 1686 $pkglist = new PkgList;
1684 while (<STORE>) { 1687 while (<STORE>) {
1685 eval $_; 1688 eval $_;
1686 } 1689 }
1687 close(STORE); 1690 close(STORE);
1688} 1691}
1689 1692
1690sub store_pkgsrc_makefiles() { 1693sub store_pkgsrc_makefiles() {
1691 open( STORE, ">$_[0]" ) || die("Cannot save pkgsrc store to $_[0]: $!\n"); 1694 open( STORE, ">$_[0]" ) || die("Cannot save pkgsrc store to $_[0]: $!\n");
1692 my $was = select(STORE); 1695 my $was = select(STORE);
1693 print( 1696 print(
1694 'sub __pkgcount { $subpkgnum += $_[0]; ', 1697 'sub __pkgcount { $subpkgnum += $_[0]; ',
1695 'verbose("\rReading pkgsrc database: ', 1698 'verbose("\rReading pkgsrc database: ',
1696 '$pkgnum / $pkgcnt ($subpkgnum / $subpkgcnt) pkgs"); }', 1699 '$pkgnum / $pkgcnt ($subpkgnum / $subpkgcnt) pkgs"); }',
1697 "\n" 1700 "\n"
1698 ); 1701 );
1699 $pkglist->store; 1702 $pkglist->store;
1700 print("verbose(\"...done\\n\");\n"); 1703 print("verbose(\"...done\\n\");\n");
1701 select($was); 1704 select($was);
1702 close(STORE); 1705 close(STORE);
1703} 1706}
1704 1707
1705# Remember to update manual page when modifying option list 1708# Remember to update manual page when modifying option list
1706# 1709#
1707sub usage_and_exit() { 1710sub usage_and_exit() {
1708 print "Usage: lintpkgsrc [opts] [makefiles] 1711 print "Usage: lintpkgsrc [opts] [makefiles]
1709opts: 1712opts:
1710 -h : This help. [see lintpkgsrc(1) for more information] 1713 -h : This help. [see lintpkgsrc(1) for more information]
1711 1714
1712Installed package options: Distfile options: 1715Installed package options: Distfile options:
1713 -i : Check version against pkgsrc -m : List distinfo mismatches 1716 -i : Check version against pkgsrc -m : List distinfo mismatches
1714 -u : As -i + fetch dist (may change) -o : List obsolete (no distinfo) 1717 -u : As -i + fetch dist (may change) -o : List obsolete (no distinfo)
1715 -y : Remove orphan distfiles 1718 -y : Remove orphan distfiles
1716 -z : Remove installed distfiles 1719 -z : Remove installed distfiles
1717 1720
1718Prebuilt package options: Makefile options: 1721Prebuilt package options: Makefile options:
1719 -p : List old/obsolete -B : List packages marked as 'BROKEN' 1722 -p : List old/obsolete -B : List packages marked as 'BROKEN'
1720 -O : List OSVERSION_SPECIFIC -d : Check 'DEPENDS' up to date 1723 -O : List OSVERSION_SPECIFIC -d : Check 'DEPENDS' up to date
1721 -R : List NO_BIN_ON_FTP/RESTRICTED -S : List packages not in 'SUBDIRS' 1724 -R : List NO_BIN_ON_FTP/RESTRICTED -S : List packages not in 'SUBDIRS'
1722 1725
1723Misc: 1726Misc:
1724 -E file : Export the internal pkgsrc database to file 1727 -E file : Export the internal pkgsrc database to file
1725 -I file : Import the internal pkgsrc database to file (for use with -i) 1728 -I file : Import the internal pkgsrc database to file (for use with -i)
1726 -g file : Generate 'pkgname pkgdir pkgver' map in file 1729 -g file : Generate 'pkgname pkgdir pkgver' map in file
1727 -r : Remove bad files (Without -m -o -p or -V implies all, can use -R) 1730 -r : Remove bad files (Without -m -o -p or -V implies all, can use -R)
1728 1731
1729Modifiers: 1732Modifiers:
1730 -K path : Set PACKAGES basedir (default PKGSRCDIR/packages) 1733 -K path : Set PACKAGES basedir (default PKGSRCDIR/packages)
1731 -M path : Set DISTDIR (default PKGSRCDIR/distfiles) 1734 -M path : Set DISTDIR (default PKGSRCDIR/distfiles)
1732 -P path : Set PKGSRCDIR (default $conf_pkgsrcdir) 1735 -P path : Set PKGSRCDIR (default $conf_pkgsrcdir)
1733 -D : Debug makefile and glob parsing 1736 -D : Debug makefile and glob parsing
1734 -L : List each Makefile when scanned 1737 -L : List each Makefile when scanned
1735"; 1738";
1736 exit; 1739 exit;
1737} 1740}
1738 1741
1739sub verbose(@) { 1742sub verbose(@) {
1740 1743
1741 if ( -t STDERR ) { 1744 if ( -t STDERR ) {
1742 print STDERR @_; 1745 print STDERR @_;
1743 } 1746 }
1744} 1747}
1745 1748
1746sub debug(@) { 1749sub debug(@) {
1747 1750
1748 ( $opt{D} ) && print STDERR 'DEBUG: ', @_; 1751 ( $opt{D} ) && print STDERR 'DEBUG: ', @_;
1749} 1752}
1750 1753
1751# PkgList is the master list of all packages in pkgsrc. 1754# PkgList is the master list of all packages in pkgsrc.
1752# 1755#
1753package PkgList; 1756package PkgList;
1754 1757
1755sub add($@) { 1758sub add($@) {
1756 my $self = shift; 1759 my $self = shift;
1757 1760
1758 if ( !$self->pkgs( $_[0] ) ) { 1761 if ( !$self->pkgs( $_[0] ) ) {
1759 $self->{_pkgs}{ $_[0] } = new Pkgs $_[0]; 1762 $self->{_pkgs}{ $_[0] } = new Pkgs $_[0];
1760 } 1763 }
1761 $self->pkgs( $_[0] )->add(@_); 1764 $self->pkgs( $_[0] )->add(@_);
1762} 1765}
1763 1766
1764sub new($) { 1767sub new($) {
1765 my $class = shift; 1768 my $class = shift;
1766 my $self = {}; 1769 my $self = {};
1767 bless $self, $class; 1770 bless $self, $class;
1768 return $self; 1771 return $self;
1769} 1772}
1770 1773
1771sub numpkgver($) { 1774sub numpkgver($) {
1772 my $self = shift; 1775 my $self = shift;
1773 scalar( $self->pkgver ); 1776 scalar( $self->pkgver );
1774} 1777}
1775 1778
1776sub pkgver($@) { 1779sub pkgver($@) {
1777 my $self = shift; 1780 my $self = shift;
1778 1781
1779 if ( @_ == 0 ) { 1782 if ( @_ == 0 ) {
1780 my (@list); 1783 my (@list);
1781 foreach my $pkg ( $self->pkgs ) { 1784 foreach my $pkg ( $self->pkgs ) {
1782 push( @list, $pkg->pkgver ); 1785 push( @list, $pkg->pkgver );
1783 } 1786 }
1784 return (@list); 1787 return (@list);
1785 } 1788 }
1786 1789
1787 if ( defined $self->{_pkgs}{ $_[0] } ) { 1790 if ( defined $self->{_pkgs}{ $_[0] } ) {
1788 return ( @_ > 1 ) 1791 return ( @_ > 1 )
1789 ? $self->{_pkgs}{ $_[0] }->pkgver( $_[1] ) 1792 ? $self->{_pkgs}{ $_[0] }->pkgver( $_[1] )
1790 : $self->{_pkgs}{ $_[0] }->pkgver(); 1793 : $self->{_pkgs}{ $_[0] }->pkgver();
1791 } 1794 }
1792 return; 1795 return;
1793} 1796}
1794 1797
1795sub pkgs($@) { 1798sub pkgs($@) {
1796 my $self = shift; 1799 my $self = shift;
1797 1800
1798 if (@_) { 1801 if (@_) {
1799 return $self->{_pkgs}{ $_[0] }; 1802 return $self->{_pkgs}{ $_[0] };
1800 } 1803 }
1801 else { 1804 else {
1802 return ( sort { $a->pkg cmp $b->pkg } values %{ $self->{_pkgs} } ); 1805 return ( sort { $a->pkg cmp $b->pkg } values %{ $self->{_pkgs} } );
1803 } 1806 }
1804 return; 1807 return;
1805} 1808}
1806 1809
1807sub store($) { 1810sub store($) {
1808 my $self = shift; 1811 my $self = shift;
1809 my @pkgs = keys %{ $self->{_pkgs} }; 1812 my @pkgs = keys %{ $self->{_pkgs} };
1810 my ( $cnt, $subcnt ) = $self->count; 1813 my ( $cnt, $subcnt ) = $self->count;
1811 1814
1812 print("\$pkgcnt = $cnt;\n"); 1815 print("\$pkgcnt = $cnt;\n");
1813 print("\$subpkgcnt = $subcnt;\n"); 1816 print("\$subpkgcnt = $subcnt;\n");
1814 map( $self->{_pkgs}{$_}->store, keys %{ $self->{_pkgs} } ); 1817 map( $self->{_pkgs}{$_}->store, keys %{ $self->{_pkgs} } );
1815} 1818}
1816 1819
1817sub count($) { 1820sub count($) {
1818 my $self = shift; 1821 my $self = shift;
1819 my ( $pkgcnt, $pkgsubcnt ); 1822 my ( $pkgcnt, $pkgsubcnt );
1820 1823
1821 map { 1824 map {
1822 $pkgcnt++; 1825 $pkgcnt++;
1823 $pkgsubcnt += $self->{_pkgs}{$_}->count; 1826 $pkgsubcnt += $self->{_pkgs}{$_}->count;
1824 } keys %{ $self->{_pkgs} }; 1827 } keys %{ $self->{_pkgs} };
1825 wantarray ? ( $pkgcnt, $pkgsubcnt ) : $pkgcnt; 1828 wantarray ? ( $pkgcnt, $pkgsubcnt ) : $pkgcnt;
1826} 1829}
1827 1830
1828# Pkgs is all versions of a given package (eg: apache-1.x and apache-2.x) 1831# Pkgs is all versions of a given package (eg: apache-1.x and apache-2.x)
1829# 1832#
1830package Pkgs; 1833package Pkgs;
1831 1834
1832sub add($@) { 1835sub add($@) {
1833 my $self = shift; 1836 my $self = shift;
1834 1837
1835 $self->{_pkgver}{ $_[1] } = new PkgVer @_; 1838 $self->{_pkgver}{ $_[1] } = new PkgVer @_;
1836} 1839}
1837 1840
1838sub new($@) { 1841sub new($@) {
1839 my $class = shift; 1842 my $class = shift;
1840 my $self = {}; 1843 my $self = {};
1841 1844
1842 bless $self, $class; 1845 bless $self, $class;
1843 $self->{_pkg} = $_[0]; 1846 $self->{_pkg} = $_[0];
1844 return $self; 1847 return $self;
1845} 1848}
1846 1849
1847sub versions($) { 1850sub versions($) {
1848 my $self = shift; 1851 my $self = shift;
1849 1852
1850 return sort { $b cmp $a } keys %{ $self->{_pkgver} }; 1853 return sort { $b cmp $a } keys %{ $self->{_pkgver} };
1851} 1854}
1852 1855
1853sub pkg($) { 1856sub pkg($) {
1854 my $self = shift; 1857 my $self = shift;
1855 $self->{_pkg}; 1858 $self->{_pkg};
1856} 1859}
1857 1860
1858sub pkgver($@) { 1861sub pkgver($@) {
1859 my $self = shift; 1862 my $self = shift;
1860 1863
1861 if (@_) { 1864 if (@_) {
1862 if ( $self->{_pkgver}{ $_[0] } ) { 1865 if ( $self->{_pkgver}{ $_[0] } ) {
1863 return ( $self->{_pkgver}{ $_[0] } ); 1866 return ( $self->{_pkgver}{ $_[0] } );
1864 } 1867 }
1865 return; 1868 return;
1866 } 1869 }
1867 return sort { $b->ver() cmp $a->ver() } values %{ $self->{_pkgver} }; 1870 return sort { $b->ver() cmp $a->ver() } values %{ $self->{_pkgver} };
1868} 1871}
1869 1872
1870sub latestver($) { 1873sub latestver($) {
1871 my $self = shift; 1874 my $self = shift;
1872 1875
1873 ( $self->pkgver() )[0]; 1876 ( $self->pkgver() )[0];
1874} 1877}
1875 1878
1876sub store($) { 1879sub store($) {
1877 my $self = shift; 1880 my $self = shift;
1878 1881
1879 print("\$pkgnum++;\n"); 1882 print("\$pkgnum++;\n");
1880 map( $self->{_pkgver}{$_}->store, keys %{ $self->{_pkgver} } ); 1883 map( $self->{_pkgver}{$_}->store, keys %{ $self->{_pkgver} } );
1881} 1884}
1882 1885
1883sub count($) { 1886sub count($) {
1884 my $self = shift; 1887 my $self = shift;
1885 1888
1886 scalar( keys %{ $self->{_pkgver} } ); 1889 scalar( keys %{ $self->{_pkgver} } );
1887} 1890}
1888 1891
1889# PkgVer is a unique package+version 1892# PkgVer is a unique package+version
1890# 1893#
1891package PkgVer; 1894package PkgVer;
1892 1895
1893sub new($$$) { 1896sub new($$$) {
1894 my $class = shift; 1897 my $class = shift;
1895 my $self = {}; 1898 my $self = {};
1896 1899
1897 bless $self, $class; 1900 bless $self, $class;
1898 $self->{_pkg} = $_[0]; 1901 $self->{_pkg} = $_[0];
1899 $self->{_ver} = $_[1]; 1902 $self->{_ver} = $_[1];
1900 return $self; 1903 return $self;
1901} 1904}
1902 1905
1903sub pkgname($) { 1906sub pkgname($) {
1904 my $self = shift; 1907 my $self = shift;
1905 1908
1906 $self->pkg . '-' . $self->ver; 1909 $self->pkg . '-' . $self->ver;
1907} 1910}
1908 1911
1909sub pkg($) { 1912sub pkg($) {
1910 my $self = shift; 1913 my $self = shift;
1911 1914
1912 $self->{_pkg}; 1915 $self->{_pkg};
1913} 1916}
1914 1917
1915sub var($$$) { 1918sub var($$$) {
1916 my $self = shift; 1919 my $self = shift;
1917 my ( $key, $val ) = @_; 1920 my ( $key, $val ) = @_;
1918 1921
1919 ( defined $val ) 1922 ( defined $val )
1920 ? ( $self->{$key} = $val ) 1923 ? ( $self->{$key} = $val )
1921 : $self->{$key}; 1924 : $self->{$key};
1922} 1925}
1923 1926
1924sub ver($) { 1927sub ver($) {
1925 my $self = shift; 1928 my $self = shift;
1926 1929
1927 $self->{_ver}; 1930 $self->{_ver};
1928} 1931}
1929 1932
1930sub vars($) { 1933sub vars($) {
1931 my $self = shift; 1934 my $self = shift;
1932 1935
1933 grep( !/^_(pkg|ver)$/, keys %{$self} ); 1936 grep( !/^_(pkg|ver)$/, keys %{$self} );
1934} 1937}
1935 1938
1936sub store($) { 1939sub store($) {
1937 my $self = shift; 1940 my $self = shift;
1938 my $data; 1941 my $data;
1939 1942
1940 ( $data = $self->{_pkg} ) =~ s/([\\\$\@\%\"])/\\$1/g; 1943 ( $data = $self->{_pkg} ) =~ s/([\\\$\@\%\"])/\\$1/g;
1941 print("\$pkgver = \$pkglist->add(\"$data\", \""); 1944 print("\$pkgver = \$pkglist->add(\"$data\", \"");
1942 1945
1943 ( $data = $self->{_ver} ) =~ s/([\\\$\@\%\"])/\\$1/g; 1946 ( $data = $self->{_ver} ) =~ s/([\\\$\@\%\"])/\\$1/g;
1944 print("$data\"); __pkgcount(1);\n"); 1947 print("$data\"); __pkgcount(1);\n");
1945 1948
1946 foreach ( $self->vars ) { 1949 foreach ( $self->vars ) {
1947 ( $data = $self->{$_} ) =~ s/([\\\$\@\%\"])/\\$1/g; 1950 ( $data = $self->{$_} ) =~ s/([\\\$\@\%\"])/\\$1/g;
1948 print("\$pkgver->var(\"$_\", \"$data\");\n"); 1951 print("\$pkgver->var(\"$_\", \"$data\");\n");
1949 } 1952 }
1950} 1953}
1951 1954
1952package main; 1955package main;
1953 1956
1954main(); 1957main();