@@ -37,9 +37,14 @@ BEGIN {
37
37
$^W = 1;
38
38
$| = 1;
39
39
(my $mydir = $0 ) =~ s ,/[^/]*$, ,;
40
- my $tlroot = " $mydir /../.." ;
40
+ if ($mydir eq $0 ) {
41
+ $mydir = " ." ;
42
+ }
43
+ # my $tlroot = "$mydir/../..";
44
+ my $tlroot = " $mydir " ;
41
45
unshift (@INC , " $tlroot /tlpkg" );
42
- chomp ($Master = ` cd $mydir /../.. && pwd` );
46
+ # chomp ($Master = `cd $mydir/../.. && pwd`);
47
+ chomp ($Master = ` pwd` );
43
48
}
44
49
45
50
use File::Find;
@@ -92,6 +97,8 @@ sub main {
92
97
93
98
#
94
99
my $cmd = shift @ARGV ;
100
+ die (" No command passed" ) if (!$cmd );
101
+
95
102
96
103
# setup packages to check:
97
104
my @packs = @ARGV ;
@@ -116,308 +123,18 @@ sub check_rebuild_package {
116
123
117
124
118
125
119
- # Run fmtutil --fmtdir=$OUTDIR --recorder ..., to recreate the recorder
120
- # files which are the basis for finding the dependencies.
121
- #
122
- # OUTDIR is completely removed first (!!), on the theory that this job
123
- # should only be done in temporary directories.
124
- #
125
- sub run_fmtutil {
126
- my ($outdir ) = @_ ;
127
-
128
- # yep, destroy output directory tree.
129
- TeXLive::TLUtils::rmtree ($outdir );
130
- mkdir ($outdir , 0775) || die " $prg : mkdir($outdir ) failed: $! " ;
131
-
132
- # the output from fmtutil can be useful in debugging.
133
- my $logfile = " $outdir /fmtutil.log" ;
134
- my $cmd = " fmtutil --sys --recorder --strict --fmtdir=$outdir "
135
- . " $opt_fmtargs >$logfile 2>&1" ;
136
- &info (" Running $cmd \n " );
137
- my $retval = system ($cmd );
138
- $retval >>= 8 if $retval > 0;
139
- if ($retval ) {
140
- tlwarn (" fmtutil exit status = $retval ; contents of $logfile =\n " );
141
- tlwarn (` cat $logfile ` );
142
- tldie (" fmtutil failed, goodbye.\n " );
143
- }
144
- return $retval ;
145
- }
146
-
147
-
148
- # Return a hash with each key being a string of the form ENGINE.FORMAT,
149
- # and the corresponding value a reference to the list of files used to
150
- # make that format with that engine. This is based on reading the
151
- # recorder files (format.fls/.ofl) for the format in FMTDIR.
152
- # Uninteresting files are removed from the list, as is the Master
153
- # directory prefix.
154
- #
155
- sub files_per_format {
156
- my ($fmtdir ) = @_ ;
157
- my %ret ;
158
-
159
- # gather all fls files.
160
- my @fls = ();
161
- my $recorder_files = sub {
162
- # fun with perl: we use an anonymous sub because it's lexically scoped,
163
- # hence we can update a my variable inside. Explanation at, e.g.,
164
- # http://stackoverflow.com/questions/8839005
165
- # In this case, we could also pass a lambda sub to find, since
166
- # this sub is so simple, but for purposes of example, do it this way.
167
- push (@fls , $File::Find::name )
168
- if $File::Find::name =~ / \. (fls|ofl)$ /
169
- };
170
- File::Find::find ($recorder_files , $fmtdir );
171
-
172
- # each fls file will become an entry in the return hash.
173
- my $fls_count = @fls ;
174
- &info (" Reading $fls_count fls file(s): @fls \n " );
175
- for my $fls_name (@fls ) {
176
- open (my $fls , $fls_name ) || die " open($fls_name ) failed: $! " ;
177
- my @files = ();
178
- while (<$fls >) {
179
- next unless s / ^INPUT // ;
180
- next if m , /web2c/texmf\. cnf$ , ; # read internally by kpathsea
181
- next if m , /fontname/texfonts\. map$ , ; # likewise
182
- next if m , /texsys\. aux$ , ; # aux file created during run
183
- chomp ;
184
- s ,^${Master} /,,; # rm prefix
185
- push (@files , $_ );
186
- }
187
- close ($fls ) || warn " close($fls_name ) failed: $! " ;
188
-
189
- # The engine name is the directory above the format file,
190
- # and the format name is the format file without extension.
191
- my ($engine ,$format ) = ($fls_name =~ m ! ^.*/([^/]+)/([^/.]+)\. [^/] +$ ! );
192
- #
193
- # we'd have to have a similar special case for mpost if mem files
194
- # were still used (see rebuild_one_format in fmtutil).
195
- $engine = " mf-nowin" if $engine eq " metafont" ;
196
- #
197
- my $ef = " $engine .$format " ;
198
-
199
- # Unfortunately, format filenames themselves are not unique, due to
200
- # cont-en and pdfcsplain. Shouldn't be any engine+format dups, though.
201
- #
202
- tldie (" $prg : already saw format $ef \n (with files @{$ret {$ef }}),\n "
203
- . " files now = @files \n " )
204
- if exists $ret {$ef };
205
- $ret {$ef } = \@files ;
206
- }
207
-
208
- # &debug_hash ("files_per_format returning hash", %ret);
209
- return %ret ;
210
- }
211
-
212
-
213
- # Read TLPDB_FILE and return references to three hashes:
214
- # the first mapping contained files to TL package names,
215
- # the second mapping engine.format names to their specified fmttriggers,
216
- # and the third mapping engine.format names to the package defining them.
217
- #
218
- # Instead of using the general TeXLive::TLPDB functions, read the tlpdb
219
- # file ourselves. We want to build the file->package mapping just once,
220
- # for all files, or things become noticeably slow. (The tlpfiles script
221
- # does this too, but we repeat that code here because we want to find
222
- # the fmttriggers too.)
223
- #
224
- sub tlpdb_by_file {
225
- my ($tlpdb_file ) = @_ ;
226
- my (%tlpfiles , %fmttriggers , %fmtpkgcontainers );
227
-
228
- open (my $tlpdb , $tlpdb_file ) || die " open($tlpdb_file ) failed: $! " ;
229
- my $pkg ;
230
- while (<$tlpdb >) {
231
- chomp ;
232
- if (/ ^name / ) { # notice package names
233
- (undef ,$pkg ) = split (/ / );
234
-
235
- } elsif (s / ^execute +AddFormat +// ) { # notice AddFormat lines
236
- my %af = TeXLive::TLUtils::parse_AddFormat_line ($_ );
237
- if (exists $af {" error" }) {
238
- tldie (" $prg : parse_AddFormat_line failed: $af {error}\n "
239
- . " line = $_ \n " );
240
- }
241
- if ($af {" fmttriggers" }) {
242
- my $ef = " $af {engine}.$af {name}" ;
243
- if (exists ($fmttriggers {$ef })) {
244
- tldie (" $prg : already saw triggers for $ef ($fmttriggers {$ef }),"
245
- . " triggers now = $af {fmttriggers}\n " );
246
- }
247
- $fmttriggers {$ef } = $af {" fmttriggers" };
248
- $fmtpkgcontainers {$ef } = $pkg ;
249
- # warn " fmtpkgcontainers{$ef} = $pkg\n";
250
- } else {
251
- tlwarn (" $prg : no fmttriggers: $_ \n " );
252
- }
253
-
254
- } elsif (s / ^ // ) { # notice file names
255
- # we carefully designed the format so that the only lines with
256
- # leading spaces are the files.
257
- # The installer "package" isn't one, just ignore it.
258
- next if $pkg eq " 00texlive.installer" ;
259
- my $f = $_ ;
260
- tlwarn (" $prg : already saw file $f (package $tlpfiles {$f }),"
261
- . " now in package $pkg \n " )
262
- if exists $tlpfiles {$f }; # should never happen
263
- $tlpfiles {$f } = $pkg ;
264
- }
265
- }
266
- close ($tlpdb ) || warn " close($tlpdb_file ) failed: $! " ;
267
-
268
- &info (" TLPDB files: " . scalar (keys %tlpfiles )
269
- . " triggers: " . scalar (keys %fmttriggers ) . " \n " );
270
- return (\%tlpfiles , \%fmttriggers , \%fmtpkgcontainers );
271
- }
272
-
273
-
274
- # Return a hash with each key being a format name and the corresponding
275
- # value a reference to the list of TL packages which contain the files
276
- # used to make that format, based on the incoming TLPDB and FILES_PER_FORMAT.
277
- #
278
- sub pkgs_per_format {
279
- my ($tlpdb ,%files_per_format ) = @_ ;
280
- my %ret ; # format->pkgs mapping
281
-
282
- for my $format (sort keys %files_per_format ) {
283
- &debug (" finding packages for $format ...\n " );
284
- my %pkgs_for_this_format ;
285
- my $files_ref = $files_per_format {$format };
286
- for my $f (@$files_ref ) {
287
- if (exists $tlpdb -> {$f }) {
288
- my $pkg = $tlpdb -> {$f };
289
- $pkgs_for_this_format {$pkg } = 1;
290
- } else {
291
- tlwarn (" $prg : tl package not found for file: $f \n " );
292
- }
293
- }
294
-
295
- # looked up all files for this format; save our list of packages.
296
- my @pkgs = sort keys %pkgs_for_this_format ;
297
- &debug (" packages for $format : @pkgs \n " );
298
- if (@pkgs == 0) {
299
- tlwarn (" $prg : no packages for format $format ? files = @$files_ref \n " );
300
- }
301
- $ret {$format } = \@pkgs ;
302
- }
303
-
304
- &info (" Formats found: " . scalar (keys %ret ) . " \n " );
305
- # &debug_hash ("pkgs_per_format returning", %ret);
306
- return %ret ;
307
- }
308
-
309
-
310
- # Compare lists of packages required by building (PKGS_PER_FORMAT) with
311
- # lists of existing trigger directives (FMTTRIGGER). Return 0 if
312
- # identical, 1 otherwise (and report differences). Ignore hyphenation
313
- # dependencies and the package itself containing the trigger directive
314
- # (FMTPKGCONTAINERS).
315
- #
316
- sub compare_pkgs_and_triggers {
317
- my ($pkgs_per_format ,$fmttriggers ,$fmtpkgcontainers ) = @_ ;
318
- my $bad_p = 0;
319
- my $all_pkgs = 0;
320
-
321
- # we don't include these as fmttriggers since when they meaningfully
322
- # change, fmtutil should get called anyway due to language.* changing.
323
- my @skip_pkgs = qw( dehyph-exptl hyph-utf8 ruhyphen ukrhyph) ;
324
- # Anything matching hyphen-.* is also ignored.
325
-
326
- for my $ef (sort keys %$pkgs_per_format ) {
327
- my @recorded_pkgs = @{$pkgs_per_format -> {$ef }};
328
- $all_pkgs += @recorded_pkgs ;
329
-
330
- my %recorded_pkgs ;
331
- @recorded_pkgs {@recorded_pkgs } = (); # hash slice for recorded pkgs
332
-
333
- if (defined $fmttriggers -> {$ef }) {
334
- my @tlpdb_pkgs = @{$fmttriggers -> {$ef }};
335
- my %tlpdb_pkgs ;
336
- @tlpdb_pkgs {@tlpdb_pkgs } = (); # hash slice for tlpdb pkgs
337
-
338
- my @recorded_only = ();
339
- for my $r (keys %recorded_pkgs ) {
340
- if (exists $tlpdb_pkgs {$r }) {
341
- delete $tlpdb_pkgs {$r }; # ok, in both
342
- } else {
343
- next if grep ($_ eq $r , @skip_pkgs );
344
- next if $r =~ / hyphen-.*/ ;
345
- next if $r eq $fmtpkgcontainers -> {$ef };
346
- push (@recorded_only , $r );
347
- }
348
- }
349
- if (keys %tlpdb_pkgs ) {
350
- tlwarn (" $prg : $ef triggers only in tlpdb: "
351
- . join (" ," , sort keys %tlpdb_pkgs ) . " \n " );
352
- $bad_p = 1;
353
- }
354
- if (@recorded_only ) {
355
- tlwarn (" $prg : $ef triggers only in recorder: "
356
- . join (" ," , sort @recorded_only ) . " \n " );
357
- $bad_p = 1;
358
- }
359
-
360
- delete $fmttriggers -> {$ef };
361
-
362
- } else {
363
- # not in tlpdb at all; output needed fmttriggers directive.
364
- tlwarn (" $prg : no fmttriggers in tlpdb: $ef \n "
365
- . " fmttriggers=" . join (" ," , @recorded_pkgs ) . " \n " );
366
- $bad_p = 1;
367
- }
368
- }
369
-
370
- for my $ef (sort keys %$fmttriggers ) {
371
- my $trig = join (" ," , sort @{$fmttriggers -> {$ef }});
372
- tlwarn (" $prg : format in tlpdb only: "
373
- . " $ef ($trig )\n " );
374
- $bad_p = 1;
375
- }
376
-
377
- info (" Triggers checked: $all_pkgs (includes duplicates)\n " );
378
- return $bad_p ;
379
- }
380
-
381
126
__END__
382
127
383
128
=head1 NAME
384
129
385
- check-fmttriggers - check that all needed packages trigger format rebuilds
130
+ check-package - check package for usability
386
131
387
132
=head1 SYNOPSIS
388
133
389
- check-fmttriggers [I<option > ]...
134
+ check-package check|rebuild [I<option > ]... [ I< pkg > ]
390
135
391
136
=head1 OPTIONS
392
137
393
- =over 4
394
-
395
- =item B<--fmtargs > I<str >
396
-
397
- Pass I<str > to C<fmtutil > , overriding C<--all > ; e.g., for debugging you
398
- might want C<--fmtargs=--byfmt=tex > to build only C<tex.fmt > . (Many
399
- inconsistencies with the TLPDB will be reported, naturally.)
400
-
401
- =item B<--fmtdir > I<dir >
402
-
403
- Rebuild formats in I<dir > ; default C</tmp/fmttriggers > . This directory
404
- is completely removed before rebuilding, so do not use any system
405
- directory.
406
-
407
- =item B<--no-rerecord >
408
-
409
- Do not rebuild all formats to remake the recorder files; the default
410
- (C<--rerecord > ) is to do so.
411
-
412
- =item B<--help >
413
-
414
- Display this documentation and exit.
415
-
416
- =item B<--version >
417
-
418
- Display version information and exit.
419
-
420
- =back
421
138
422
139
The standard options B<-q > , B<-v > , and B<-logfile > =I<file > are also
423
140
accepted; see the C<process_logging_options > function in
@@ -427,9 +144,6 @@ will be reported.
427
144
428
145
=head1 DESCRIPTION
429
146
430
- Compare the fmttriggers= listed in the tlpsrc files with the actual
431
- dependencies found by running fmtutil -recorder and inspecting the
432
- recorder (.fls) files.
433
147
434
148
=head1 AUTHORS AND COPYRIGHT
435
149
0 commit comments