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