Sat Jul 30 11:33:23 2022 UTC ()
lintpkgsrc: use plain text cache format

Previously, the cache format was Perl code. Now it is a list of lines,
each line containing tab-separated data.

The new format reduces the storage needs by around 50%. It also ensures
that only well-formed data is written to the cache.

The previous format contained lots of IO requests, which made loading
the cache incredibly slow.

Bump version.


(rillig)
diff -r1.40 -r1.41 pkgsrc/pkgtools/lintpkgsrc/Makefile
diff -r1.36 -r1.37 pkgsrc/pkgtools/lintpkgsrc/files/lintpkgsrc.pl

cvs diff -r1.40 -r1.41 pkgsrc/pkgtools/lintpkgsrc/Makefile (switch to unified diff)

--- pkgsrc/pkgtools/lintpkgsrc/Makefile 2022/07/30 10:11:45 1.40
+++ pkgsrc/pkgtools/lintpkgsrc/Makefile 2022/07/30 11:33:23 1.41
@@ -1,56 +1,55 @@ @@ -1,56 +1,55 @@
1# $NetBSD: Makefile,v 1.40 2022/07/30 10:11:45 rillig Exp $ 1# $NetBSD: Makefile,v 1.41 2022/07/30 11:33:23 rillig Exp $
2 2
3PKGNAME= lintpkgsrc-4.98 3PKGNAME= lintpkgsrc-4.99
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}
17USE_LANGUAGES= # none 16USE_LANGUAGES= # none
18AUTO_MKDIRS= yes 17AUTO_MKDIRS= yes
19 18
20SUBST_CLASSES+= lp 19SUBST_CLASSES+= lp
21SUBST_STAGE.lp= post-configure 20SUBST_STAGE.lp= post-configure
22SUBST_FILES.lp+= lintpkgsrc.0 lintpkgsrc.1 lintpkgsrc.pl 21SUBST_FILES.lp+= lintpkgsrc.0 lintpkgsrc.1 lintpkgsrc.pl
23SUBST_SED.lp+= -e 's;@PKGSRCDIR@;${BATCH:D/usr/pkgsrc:U${PKGSRCDIR}};g' 22SUBST_SED.lp+= -e 's;@PKGSRCDIR@;${BATCH:D/usr/pkgsrc:U${PKGSRCDIR}};g'
24SUBST_VARS.lp+= MAKE 23SUBST_VARS.lp+= MAKE
25SUBST_VARS.lp+= PERL5 24SUBST_VARS.lp+= PERL5
26SUBST_VARS.lp+= PKG_SYSCONFDIR 25SUBST_VARS.lp+= PKG_SYSCONFDIR
27SUBST_VARS.lp+= PREFIX 26SUBST_VARS.lp+= PREFIX
28 27
29.include "../../mk/bsd.prefs.mk" 28.include "../../mk/bsd.prefs.mk"
30 29
31do-extract: 30do-extract:
32 cd ${FILESDIR} && cp -R lintpkgsrc.* t ${WRKSRC}/ 31 cd ${FILESDIR} && cp -R lintpkgsrc.* t ${WRKSRC}/
33 32
34do-build: 33do-build:
35 # Nothing 34 # Nothing
36 35
37do-test: 36do-test:
38 ${RUN} cd ${WRKSRC}/t; \ 37 ${RUN} cd ${WRKSRC}/t; \
39 for test in ./*.t; do \ 38 for test in ./*.t; do \
40 perl "$$test"; \ 39 perl "$$test"; \
41 done 40 done
42 41
43do-install: 42do-install:
44 ${INSTALL_SCRIPT} ${WRKSRC}/lintpkgsrc.pl ${DESTDIR}${PREFIX}/bin/lintpkgsrc 43 ${INSTALL_SCRIPT} ${WRKSRC}/lintpkgsrc.pl ${DESTDIR}${PREFIX}/bin/lintpkgsrc
45.if !empty(MANINSTALL:Mcatinstall) 44.if !empty(MANINSTALL:Mcatinstall)
46. if defined(CATMAN_SECTION_SUFFIX) && !empty(CATMAN_SECTION_SUFFIX:M[Yy][Ee][Ss]) 45. if defined(CATMAN_SECTION_SUFFIX) && !empty(CATMAN_SECTION_SUFFIX:M[Yy][Ee][Ss])
47 ${INSTALL_MAN} ${WRKSRC}/lintpkgsrc.0 ${DESTDIR}${PREFIX}/${PKGMANDIR}/cat1/lintpkgsrc.1 46 ${INSTALL_MAN} ${WRKSRC}/lintpkgsrc.0 ${DESTDIR}${PREFIX}/${PKGMANDIR}/cat1/lintpkgsrc.1
48. else 47. else
49 ${INSTALL_MAN} ${WRKSRC}/lintpkgsrc.0 ${DESTDIR}${PREFIX}/${PKGMANDIR}/cat1 48 ${INSTALL_MAN} ${WRKSRC}/lintpkgsrc.0 ${DESTDIR}${PREFIX}/${PKGMANDIR}/cat1
50. endif 49. endif
51.endif 50.endif
52.if !empty(MANINSTALL:Mmaninstall) 51.if !empty(MANINSTALL:Mmaninstall)
53 ${INSTALL_MAN} ${WRKSRC}/lintpkgsrc.1 ${DESTDIR}${PREFIX}/${PKGMANDIR}/man1 52 ${INSTALL_MAN} ${WRKSRC}/lintpkgsrc.1 ${DESTDIR}${PREFIX}/${PKGMANDIR}/man1
54.endif 53.endif
55 54
56.include "../../mk/bsd.pkg.mk" 55.include "../../mk/bsd.pkg.mk"

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

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