Skip to content

Commit b504c0e

Browse files
committed
update check-package
1 parent 390be7a commit b504c0e

File tree

1 file changed

+11
-297
lines changed

1 file changed

+11
-297
lines changed

check-package

Lines changed: 11 additions & 297 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,14 @@ BEGIN {
3737
$^W = 1;
3838
$| = 1;
3939
(my $mydir = $0) =~ s,/[^/]*$,,;
40-
my $tlroot = "$mydir/../..";
40+
if ($mydir eq $0) {
41+
$mydir = ".";
42+
}
43+
#my $tlroot = "$mydir/../..";
44+
my $tlroot = "$mydir";
4145
unshift (@INC, "$tlroot/tlpkg");
42-
chomp ($Master = `cd $mydir/../.. && pwd`);
46+
#chomp ($Master = `cd $mydir/../.. && pwd`);
47+
chomp ($Master = `pwd`);
4348
}
4449

4550
use File::Find;
@@ -92,6 +97,8 @@ sub main {
9297

9398
#
9499
my $cmd = shift @ARGV;
100+
die("No command passed") if (!$cmd);
101+
95102

96103
# setup packages to check:
97104
my @packs = @ARGV;
@@ -116,308 +123,18 @@ sub check_rebuild_package {
116123

117124

118125

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-
381126
__END__
382127
383128
=head1 NAME
384129
385-
check-fmttriggers - check that all needed packages trigger format rebuilds
130+
check-package - check package for usability
386131
387132
=head1 SYNOPSIS
388133
389-
check-fmttriggers [I<option>]...
134+
check-package check|rebuild [I<option>]... [I<pkg>]
390135
391136
=head1 OPTIONS
392137
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
421138
422139
The standard options B<-q>, B<-v>, and B<-logfile>=I<file> are also
423140
accepted; see the C<process_logging_options> function in
@@ -427,9 +144,6 @@ will be reported.
427144
428145
=head1 DESCRIPTION
429146
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.
433147
434148
=head1 AUTHORS AND COPYRIGHT
435149

0 commit comments

Comments
 (0)