texlive[52673] Master/tlpkg/bin: rename check-* scripts to have tl-

commits+karl at tug.org commits+karl at tug.org
Thu Nov 7 19:38:33 CET 2019


Revision: 52673
          http://tug.org/svn/texlive?view=revision&revision=52673
Author:   karl
Date:     2019-11-07 19:38:33 +0100 (Thu, 07 Nov 2019)
Log Message:
-----------
rename check-* scripts to have tl- prefix (long overdue)

Modified Paths:
--------------
    trunk/Master/tlpkg/bin/tl-update-tlnet

Added Paths:
-----------
    trunk/Master/tlpkg/bin/tl-check-files-by-format
    trunk/Master/tlpkg/bin/tl-check-fmttriggers
    trunk/Master/tlpkg/bin/tl-check-tlnet-consistency
    trunk/Master/tlpkg/bin/tl-check-wrapper-consistency

Removed Paths:
-------------
    trunk/Master/tlpkg/bin/check-files-by-format
    trunk/Master/tlpkg/bin/check-fmttriggers
    trunk/Master/tlpkg/bin/check-tlnet-consistency
    trunk/Master/tlpkg/bin/check-wrapper-consistency

Deleted: trunk/Master/tlpkg/bin/check-files-by-format
===================================================================
--- trunk/Master/tlpkg/bin/check-files-by-format	2019-11-07 18:35:53 UTC (rev 52672)
+++ trunk/Master/tlpkg/bin/check-files-by-format	2019-11-07 18:38:33 UTC (rev 52673)
@@ -1,360 +0,0 @@
-#!/usr/bin/env perl
-# $Id$
-# Copyright Manuel P\'egouri\'e-Gonnard, 2010-2016. WTFPL v2.
-# Check that files in various formats are somewhat valid.
-#
-# This used to be run from cron, but no longer is, because it takes many
-# hours, and there are too many false positives. Inserting all the
-# exclusions got too annoying. Give up. --karl, 2aug19.
-#
-# The following formats are checked currently: pfb, pdf, tfm, vf, otf.
-#
-# For each format, there is one routine &check_<format> and an exclusion
-# 'list' (hash reference) $exclude_<format>: the keys are either a
-# directory name if they have a trailing slash, or a file name. If a key
-# named '*base*' is present, then the paths are relative to this base,
-# otherwise to $tlroot. The values of the keys may be free or have a
-# special meaning depending on the associated check_<format> routine.
-#
-# Formats that might be added:
-# - afm with (afm2pl?)
-
-BEGIN {
-#  $^W = 1;
-  ($mydir = $0) =~ s,/[^/]*$,,;
-  $tlroot = "$mydir/../..";
-  unshift (@INC, "$tlroot/tlpkg");
-}
-
-use File::Basename;
-use File::Temp;
-use Pod::Usage;
-use Getopt::Long;
-
-use TeXLive::TLPDB;
-
-

-# Most of these breakages need to be reported upstream, or documented
-# that they are unavoidable.  Add comments if you pursue any of them.
-
-# value has no meaning here
-my $exclude_otf = { '*base*' => 'texmf-dist/fonts/opentype',
-  'texmf-dist/doc/fonts/cm-unicode/Fontmap.CMU.otf' => 1,
-};
-
-# 1 means pdfinfo issues errors but still exits successfully
-# 2 means pdfinfo exits non-zero
-# -1 means skip completely.
-my $exclude_pdf = {
-     # 14nov11 author cannot fix:
-  'texmf-dist/doc/fonts/frcursive/frcursive.pdf' => 1,
-     # 17apr14 unknown:
-  'texmf-dist/doc/generic/pst-perspective/' => 1,
-     # 2jul16+20dec15 "couldn't read xref table", but seems basically ok:
-  'texmf-dist/doc/latex/bookcover/figures/ekflogo.pdf' => 1,
-  'texmf-dist/doc/latex/dvdcoll/dcexample.pdf' => 1,   # acroform but ok
-  'texmf-dist/doc/latex/visualfaq/visualFAQ.pdf' => 1, # acroform but ok
-  'texmf-dist/doc/latex/ksp-thesis/ksp-thesis.pdf' => 1,
-     # 4aug16 pdfinfo from xpdf 3.03 crashes (reported to derekn):
-  'texmf-dist/doc/latex/ocgx/demo-ocgx.pdf' => -1,
-     # not a PDF file:
-  'texmf-dist/dvips/tetex/config.pdf' => -1,
-};
-
-# the value has no meaning here
-my $exclude_pfb = { '*base*' => 'texmf-dist/fonts/type1',
-  'adobe/courier/' => 1,
-  'adobe/sourcecodepro/' => 1, # SourceCodePro-{Regular,BoldIt}.pfb, 10nov12 contacted
-  'arabi/arabeyes/' => 1,
-  'arabi/farsiweb/' => 1,
-  'arkandis/adfsymbols/' => 1,
-  'arkandis/libris/' => 1,
-  'arkandis/venturis/' => 1,
-  'arphic/bkaiu/' => 1,
-  'arphic/bsmiu/' => 1,
-  'arphic/gbsnu/' => 1,
-  'arphic/gkaiu/' => 1,
-  'gust/poltawski/' => 1,
-  'nowacki/iwona/' => 1,
-  'nowacki/kurier/' => 1,
-  'public/allrunes/' => 1,
-  'public/amsfonts/cm/' => 1,
-  'public/amsfonts/cmextra/' => 1,
-  'public/arev/' => 1,
-  'public/ascii-font/' => 1,
-  'public/aspectratio/' => 1, # 11feb12 reported to author
-  'public/augie/' => 1,
-  'public/aurical/' => 1,
-  'public/bbold-type1/' => 1, # old y&y fonts, won't be changing
-  'public/belleek/' => 1,
-  'public/bera/' => 1,
-  'public/brushscr/' => 1,
-  'public/burmese/' => 1,
-  'public/carolmin-ps/' => 1,
-  'public/chemarrow/' => 1,
-  'public/cjhebrew/' => 1,
-  'public/cm-super/' => 1,
-  'public/cm-unicode/cmunobi.pfb' => 1,
-  'public/cmcyr/' => 1,
-  'public/countriesofeurope/' => 1, # 22apr12 not reported
-  'public/cs/' => 1,
-  'public/doublestroke/' => 1,
-  'public/ebgaramond/' => 1,	# 9jul14 bug in fontforge/t1lint, not reported
-  'public/epiolmec/' => 1,
-  'public/esstix/' => 1,	# 12may11 author fixed some, others will remain
-  'public/ethiop-t1/' => 1,
-  'public/eurosym/' => 1,
-  'public/fbb/' => 1,		# 23aug13 bluevalues, not fixable
-  'public/fira/' => 1,		# 2015 author unable/unwilling
-  'public/foekfont/' => 1,
-  'public/fonetika/' => 1,
-  'public/fontawesome/' => 1,	# 2015 author unable/unwilling
-  'public/fourier/' => 1,
-  'public/gfsartemisia/' => 1,
-  'public/gfsbaskerville/' => 1,
-  'public/gfsbodoni/' => 1,
-  'public/gfscomplutum/' => 1,
-  'public/gfsdidot/' => 1,
-  'public/gfsneohellenic/' => 1,
-  'public/gfssolomos/' => 1,
-  'public/hacm/' => 1,
-  'public/initials/' => 1,
-  'public/ipaex-type1/' => 1,	# 20may13 too many to bother reporting
-  'public/itrans/' => 1,
-  'public/kerkis/' => 1,
-  'public/kpfonts/' => 1,
-  'public/libertine/' => 1,	# 5jan13 maintainer declines to fix triviality
-  'public/libertinust1math/'=>1,# 7apr16 hint triviality not fixed
-  'public/linearA/' => 1,
-  'public/lm/' => 1,
-  'public/lxfonts/' => 1,
-  'public/marvosym/' => 1,
-  'public/mathabx-type1/' => 1, # 14jan11 wrote bnb/preining --karl
-  'public/mathdesign/mdpus/' => 1,# 3jan16 author informed long ago, no release
-  'public/mathpazo/' => 1,
-  'public/newpx/' => 1,		# 21aug16 bluezones not worth fixing
-  'public/newtx/' => 1,		# 21aug16 bluezones not worth fixing
-  'public/ocherokee/' => 1,
-  'public/oinuit/' => 1,
-  'public/old-arrows/' => 1,	# 2015 author unable/unwilling
-  'public/omega/' => 1,
-  'public/phaistos/' => 1,
-  'public/pl/' => 1,
-  'public/playfair/' => 1,	# 15mar14 known hinting issues
-  'public/pxfonts/' => 1,
-  'public/rsfs/' => 1,
-  'public/starfont/' => 1,	# 4oct10 reported to author 
-  'public/staves/' => 1,
-  'public/stmaryrd/' => 1,	# blue values not defined, not maintained
-  'public/tabvar/' => 1,
-  'public/tex-gyre/' => 1,
-  'public/txfonts/' => 1,
-  'public/txfontsb/' => 1,
-  'public/wasy2-ps/' => 1,	# too old, will not be updated
-  'public/xypic/' => 1,
-  'public/yhmath/' => 1,
-  'texmf-dist/doc/fonts/cm-unicode/Fontmap.CMU.pfb' => 1,
-  'uhc/umj/' => 1,
-  'urw/avantgar/' => 1,
-  'urw/bookman/' => 1,
-  'urw/courier/' => 1,
-  'urw/helvetic/' => 1,
-  'urw/ncntrsbk/' => 1,
-  'urw/palatino/' => 1,
-  'urw/symbol/' => 1,
-  'urw/times/' => 1,
-  'urw/zapfding/' => 1,
-  'vntex/arevvn/' => 1,
-  'vntex/comicsansvn/' => 1,
-  'vntex/txttvn/' => 1,
-  'vntex/urwvn/' => 1,
-  'vntex/vnr/' => 1,
-  'wadalab/dgj/' => 1,
-  'wadalab/dmj/' => 1,
-  'wadalab/mcj/' => 1,
-  'wadalab/mrj/' => 1,
-  'tlpkg/texworks/share/fonts/' => 1, # these come from gs
-};
-
-

-# the value has no meaning here
-my $exclude_tfm = { '*base*' => 'texmf-dist/fonts/tfm',
-  'jknappen/ec/' => 1,
-  'jknappen/fc/' => 1,
-  'public/arev/' => 1,
-  'public/chess/' => 1,		# original has extra bytes, not worth fixing
-  'public/cmcyr/' => 1,
-  'public/dozenal/' => 1,	# wrote author 31oct12
-  'public/gfsbodoni/' => 1,	# wrote author 12dec12
-  'public/japanese-otf/' => 1,	# japanese tfm's
-  'public/malayalam/' => 1,
-  'public/mathdesign/mdici/' => 1,# 3jan16 author informed long ago, no release
-  'public/mathdesign/mdpgd/' => 1,
-  'public/mathdesign/mdpus/' => 1,
-  'public/wnri/' => 1,
-  'public/wsuipa/' => 1,
-};
-
-

-# the value has no meaning here
-my $exclude_vf = { '*base*' => 'texmf-dist/fonts/vf',
-  'public/ae/' => 1,
-  'public/bgreek/' => 1,
-  'public/eco/' => 1,
-  'public/epigrafica/' => 1,
-  'public/fonts-tlwg/' => 1,	# reported to author, early 2012
-  'public/gfsartemisia/' => 1,
-  'public/gfscomplutum/' => 1,
-  'public/gfsdidot/' => 1,
-  'public/gfsneohellenic/' => 1,
-  'public/gfsporson/' => 1,
-  'public/gfssolomos/' => 1,
-  'public/hfoldsty/' => 1,
-  'public/kerkis/' => 1,
-  'public/mathdesign/mdbch/' => 1, #3jan16 author informed long ago, no release
-  'public/mathdesign/mdbch/' => 1, #3jan16 author informed long ago, no release
-  'public/mathdesign/mdici/' => 1,
-  'public/mathdesign/mdpgd/' => 1,
-  'public/mathdesign/mdpus/' => 1,
-  'public/mathdesign/mdput/' => 1,
-  'public/mathdesign/mdugm/' => 1,
-  'public/sansmathfonts/' => 2,	# 20may13 ok with cmssbx12.tfm from sauter
-  'public/txfontsb/' => 1,
-  'public/uppunctlm/' => 1,
-  'public/zefonts/' => 1,
-  'vntex/comicsansvn/' => 1,
-};
-
-
-my $tmpdir = File::Temp::tempdir(CLEANUP => 1);
-
-my $opt_all = 0;
-my $opt_help = 0;
-
-TeXLive::TLUtils::process_logging_options ();
-GetOptions ("all" => \$opt_all,
-            "help|?" => \$opt_help) or pod2usage (2);
-pod2usage ("-exitstatus" => 0, "-verbose" => 2) if $opt_help;
-
-
-exit(&main());
-
-

-sub main {
-  my @files = get_file_list();
-
-  for my $file (grep { /\.otf$/ } @files) {
-    check_otf($file);}
-
-  for my $file (grep { /\.pdf$/ } @files) {
-    check_pdf($file); }
-
-  for my $file (grep { /\.pfb$/ } @files) {
-    check_pfb($file); }
-
-  for my $file (grep { /\.tfm$/ } @files) {
-    check_tfm($file); }
-
-  for my $file (grep { /\.vf$/ } @files) {
-    check_vf($file); }
-
-  return 0;
-}
-
-# get the list of files in the database of a TL installation
-sub get_file_list {
-  my $tlpdb = TeXLive::TLPDB->new(root => $tlroot);
-
-  my @files = ();
-  for my $tlpname ($tlpdb->list_packages) {
-    my $tlp = $tlpdb->get_package($tlpname);
-    push(@files, $tlp->docfiles, $tlp->runfiles, $tlp->srcfiles);
-  }
-
-  # [u]ptex font files use their own formats; don't bother checking,
-  # or adding lots of individual entries to the exclude lists.
-  @files = grep ($_ !~ m![-/]u?ptex(-fonts)?/!, @files);
-
-  # It takes a long time (about an hour) to check every file.  And there
-  # is no value in checking unchanged files every day.  So we filter the
-  # file list (unless --all is given) by mtime ... unless this happens
-  # to be the first of the month, when we'll check everything, just to
-  # be reminded of anything that may have crept in.
-  # 
-  if (! ($opt_all || `date +%d` == 1)) {
-    my @filtered = ();
-    for my $f (@files) {
-      push (@filtered, $f) if (-M "$tlroot/$f" < 4);
-    }
-    @files = @filtered;
-  }
-  return @files;
-}
-
-
-# return the value in exclude list associated to a file, or undef
-sub exclude_value {
-  my ($exclude, $file) = @_;
-  my $base = $exclude->{'*base*'};
-  $file =~ s!^$base/!! if $base;
-  (my $filedir = $file) =~ s![^/]*$!!;
-  return $exclude->{$file} || $exclude->{$filedir};
-}
-
-

-# the checking routines for each file type.
-
-sub check_pdf {
-  my ($file) = @_;
-  my $excl_val = exclude_value($exclude_pdf, $file) || 0;
-  return if $excl_val < 0;
-  #
-  my $errfile = "$tmpdir/pdferr";
-  unlink($errfile);
-  my $bad_exit = system("pdfinfo $tlroot/$file >/dev/null 2>$errfile");
-  my $badness = $bad_exit ? 2 : -s $errfile ? 1 : 0;
-  return if $badness <= $excl_val;
-  print "Bad PDF: $file\n" if $badness == 2;
-  print "Damaged PDF: $file\n" if $badness == 1;
-}
-
-sub check_pfb {
-  my ($file) = @_;
-  return if defined exclude_value($exclude_pfb, $file);
-  my $errfile = "$tmpdir/pfberr";
-  unlink($errfile);
-  my $bad = system("t1lint -q $tlroot/$file");
-  print "Bad pfb: $file\n" if $bad;
-}
-
-sub check_tfm {
-  my ($file) = @_;
-  return if defined exclude_value($exclude_tfm, $file);
-  my $outfile = "$tmpdir/tfmout.pl";
-  my $errfile = "$tmpdir/tfmerr";
-  unlink($errfile);
-  system("tftopl $tlroot/$file $outfile 2>$errfile");
-  print "Bad tfm: $file\n" if -s $errfile;
-}
-
-sub check_vf {
-  my ($file) = @_;
-  return if defined exclude_value($exclude_vf, $file);
-  (my $tfmfile = $file) =~ s!/vf/!/tfm/!;
-  $tfmfile =~ s/\.vf$/.tfm/;
-  return if defined exclude_value($exclude_tfm, $tfmfile);
-  my $outfile = "$tmpdir/vfout.vp";
-  my $errfile = "$tmpdir/vferr";
-  unlink($errfile);
-  system("vftovp $tlroot/$file $tlroot/$tfmfile $outfile 2>$errfile");
-  print "Bad vf: $file\n" if -s $errfile;
-}
-
-sub check_otf {
-  my ($file) = @_;
-  return if defined exclude_value($exclude_otf, $file);
-  my $bad = system("otfinfo --info $tlroot/$file >/dev/null 2>&1");
-  print "Bad otf: $file\n" if $bad;
-}
-
-# vim: sw=2 expandtab

Deleted: trunk/Master/tlpkg/bin/check-fmttriggers
===================================================================
--- trunk/Master/tlpkg/bin/check-fmttriggers	2019-11-07 18:35:53 UTC (rev 52672)
+++ trunk/Master/tlpkg/bin/check-fmttriggers	2019-11-07 18:38:33 UTC (rev 52673)
@@ -1,423 +0,0 @@
-#!/usr/bin/env perl
-# $Id$
-# Originally written by Norbert Preining and Karl Berry, 2015.  Public domain.
-# 
-# Determine the files on which each format (fmt/base) depends
-#   (by running fmtutil -recorder),
-# then map those files to TL packages,
-# then check that exactly those packages are listed as triggers in the
-#   corresponding tlpsrc files.
-
-my $vc_id = '$Id$';
-my $Master;
-
-BEGIN {
-  $^W = 1;
-  $| = 1;
-  (my $mydir = $0) =~ s,/[^/]*$,,;
-  my $tlroot = "$mydir/../..";
-  unshift (@INC, "$tlroot/tlpkg");
-  chomp ($Master = `cd $mydir/../.. && pwd`);
-}
-
-use File::Find;
-use Getopt::Long;
-use Pod::Usage;
-
-use TeXLive::TLConfig;
-use TeXLive::TLUtils qw(info debug ddebug debug_hash tlwarn tldie);
-
-my $prg = TeXLive::TLUtils::basename($0);
-
-my $opt_fmtargs = "--all";
-my $opt_fmtdir = "/tmp/fmttriggers";
-my $opt_rerecord = 1;
-my $opt_help = 0;
-my $opt_version = 0;
-
-TeXLive::TLUtils::process_logging_options ();
-GetOptions (
-  "fmtargs=s"  => \$opt_fmtargs,
-  "fmtdir"     => \$opt_fmtdir,
-  "rerecord!"  => \$opt_rerecord,
-  "version"    => \$opt_version,
-  "help|?"     => \$help) || pod2usage(1);
-
-pod2usage ("-exitstatus" => 0, "-verbose" => 2) if $help;
-if ($opt_version) { print "$vc_id\n"; exit 0; } 
-
-$::installerdir = $Master;  # TLUtils.pm should be smarter
-$ENV{'PATH'} = "$Master/bin/" . TeXLive::TLUtils::platform() . ":$ENV{PATH}";
-
-exit (&main());
-
-

-sub main {
-  # no interference from TEXMFHOME, etc.
-  $ENV{'TEXMFHOME'}   = "/nonesuch-home";
-  $ENV{'TEXMFVAR'}    = "/nonesuch-uvar";
-  $ENV{'TEXMFCONFIG'} = "/nonesuch-config";
-  $ENV{'TEXMFLOCAL'}  = "/nonesuch-local";
-
-  if ($opt_rerecord) {  # remake recorder files?
-    my $status = &run_fmtutil ($opt_fmtdir);
-    return $status if $status;
-  }
-  #system ("bytime $opt_fmtdir");
-  
-  # read recorder files.
-  my %files_per_format = &files_per_format ($opt_fmtdir);
-
-  # read tlpdb.
-  my $tlpdb_file = "$Master/tlpkg/texlive.tlpdb";
-  my ($tlpdb,$fmttriggers,$fmtpkgcontainers) = &tlpdb_by_file ($tlpdb_file);
- 
-  # map files used in the format builds to packages.
-  my %pkgs_per_format = &pkgs_per_format ($tlpdb, %files_per_format);
-  
-  # check that those packages are exactly what's listed as needed.
-  return &compare_pkgs_and_triggers (\%pkgs_per_format,
-                                     $fmttriggers, $fmtpkgcontainers);
-}
-
-

-# Run fmtutil --fmtdir=$OUTDIR --recorder ..., to recreate the recorder
-# files which are the basis for finding the dependencies.
-# 
-# OUTDIR is completely removed first (!!), on the theory that this job
-# should only be done in temporary directories.
-# 
-sub run_fmtutil {
-  my ($outdir) = @_;
-  
-  # yep, destroy output directory tree.
-  TeXLive::TLUtils::rmtree ($outdir);
-  mkdir ($outdir, 0775) || die "$prg: mkdir($outdir) failed: $!";
-  
-  # the output from fmtutil can be useful in debugging.
-  my $logfile = "$outdir/fmtutil.log";
-  my $cmd = "fmtutil --sys --recorder --strict --fmtdir=$outdir "
-             . "$opt_fmtargs >$logfile 2>&1";
-  &info ("Running $cmd\n");
-  my $retval = system ($cmd);
-  $retval >>= 8 if $retval > 0;
-  if ($retval) {
-    tlwarn ("fmtutil exit status = $retval; contents of $logfile =\n");
-    tlwarn (`cat $logfile`);
-    tldie ("fmtutil failed, goodbye.\n");
-  }
-  return $retval;
-}
-
-

-# Return a hash with each key being a string of the form ENGINE.FORMAT,
-# and the corresponding value a reference to the list of files used to
-# make that format with that engine.  This is based on reading the
-# recorder files (format.fls/.ofl) for the format in FMTDIR.
-# Uninteresting files are removed from the list, as is the Master
-# directory prefix.
-# 
-sub files_per_format {
-  my ($fmtdir) = @_;
-  my %ret;
-  
-  # gather all fls files.
-  my @fls = ();
-  my $recorder_files = sub {
-    # fun with perl: we use an anonymous sub because it's lexically scoped,
-    #   hence we can update a my variable inside.  Explanation at, e.g.,
-    #   http://stackoverflow.com/questions/8839005
-    # In this case, we could also pass a lambda sub to find, since
-    #   this sub is so simple, but for purposes of example, do it this way.
-    push (@fls, $File::Find::name)
-      if $File::Find::name =~ /\.(fls|ofl)$/
-  };
-  File::Find::find ($recorder_files, $fmtdir);
-  
-  # each fls file will become an entry in the return hash.
-  my $fls_count = @fls;
-  &info ("Reading $fls_count fls file(s): @fls\n");
-  for my $fls_name (@fls) {
-    open (my $fls, $fls_name) || die "open($fls_name) failed: $!";
-    my @files = ();
-    while (<$fls>) {
-      next unless s/^INPUT //;
-      next if m,/web2c/texmf\.cnf$,;       # read internally by kpathsea
-      next if m,/fontname/texfonts\.map$,; # likewise
-      next if m,/texsys\.aux$,;            # aux file created during run
-      chomp;
-      s,^${Master}/,,;			   # rm prefix
-      push (@files, $_);
-    }
-    close ($fls) || warn "close($fls_name) failed: $!";
-    
-    # The engine name is the directory above the format file,
-    # and the format name is the format file without extension.
-    my ($engine,$format) = ($fls_name =~ m!^.*/([^/]+)/([^/.]+)\.[^/]+$!);
-    #
-    # we'd have to have a similar special case for mpost if mem files
-    # were still used (see rebuild_one_format in fmtutil).
-    $engine = "mf-nowin" if $engine eq "metafont";
-    #
-    my $ef = "$engine.$format";
-
-    # Unfortunately, format filenames themselves are not unique, due to
-    # cont-en and pdfcsplain.  Shouldn't be any engine+format dups, though.
-    # 
-    tldie ("$prg: already saw format $ef\n (with files @{$ret{$ef}}),\n"
-           . "  files now = @files\n")
-      if exists $ret{$ef};
-    $ret{$ef} = \@files;
-  }
-
-  #&debug_hash ("files_per_format returning hash", %ret);
-  return %ret;
-}
-
-

-# Read TLPDB_FILE and return references to three hashes:
-# the first mapping contained files to TL package names, 
-# the second mapping engine.format names to their specified fmttriggers,
-# and the third mapping engine.format names to the package defining them.
-# 
-# Instead of using the general TeXLive::TLPDB functions, read the tlpdb
-# file ourselves.  We want to build the file->package mapping just once,
-# for all files, or things become noticeably slow.  (The tlpfiles script
-# does this too, but we repeat that code here because we want to find
-# the fmttriggers too.)
-#
-sub tlpdb_by_file {
-  my ($tlpdb_file) = @_;
-  my (%tlpfiles, %fmttriggers, %fmtpkgcontainers);
-  
-  open (my $tlpdb, $tlpdb_file) || die "open($tlpdb_file) failed: $!";
-  my $pkg;
-  while (<$tlpdb>) {
-    chomp;
-    if (/^name /) {  # notice package names
-      (undef,$pkg) = split (/ /);
-
-    } elsif (s/^execute +AddFormat +//) {  # notice AddFormat lines
-      my %af = TeXLive::TLUtils::parse_AddFormat_line ($_);
-      if (exists $af{"error"}) {
-        tldie ("$prg: parse_AddFormat_line failed: $af{error}\n"
-               . "line = $_\n");
-      }
-      if ($af{"fmttriggers"}) {
-        my $ef = "$af{engine}.$af{name}";
-        if (exists ($fmttriggers{$ef})) {
-          tldie ("$prg: already saw triggers for $ef ($fmttriggers{$ef}),"
-                 . "  triggers now = $af{fmttriggers}\n");
-        }
-        $fmttriggers{$ef} = $af{"fmttriggers"};
-        $fmtpkgcontainers{$ef} = $pkg;
-        #warn "  fmtpkgcontainers{$ef} = $pkg\n";
-      } else {
-        tlwarn ("$prg: no fmttriggers: $_\n");
-      }
-
-    } elsif (s/^ //) { # notice file names
-      # we carefully designed the format so that the only lines with
-      # leading spaces are the files.
-      # The installer "package" isn't one, just ignore it.
-      next if $pkg eq "00texlive.installer";
-      my $f = $_;
-      tlwarn ("$prg: already saw file $f (package $tlpfiles{$f}),"
-              . " now in package $pkg\n")
-        if exists $tlpfiles{$f}; # should never happen
-      $tlpfiles{$f} = $pkg;
-    }
-  }
-  close ($tlpdb) || warn "close($tlpdb_file) failed: $!";
-  
-  &info ("TLPDB files: " . scalar (keys %tlpfiles)
-         . "  triggers: " . scalar (keys %fmttriggers) . "\n");
-  return (\%tlpfiles, \%fmttriggers, \%fmtpkgcontainers);
-}
-  
-

-# Return a hash with each key being a format name and the corresponding
-# value a reference to the list of TL packages which contain the files
-# used to make that format, based on the incoming TLPDB and FILES_PER_FORMAT.
-# 
-sub pkgs_per_format {
-  my ($tlpdb,%files_per_format) = @_;
-  my %ret;  # format->pkgs mapping
-
-  for my $format (sort keys %files_per_format) {
-    &debug ("finding packages for $format...\n");
-    my %pkgs_for_this_format;
-    my $files_ref = $files_per_format{$format};
-    for my $f (@$files_ref) {
-      if (exists $tlpdb->{$f}) {
-        my $pkg = $tlpdb->{$f};
-        $pkgs_for_this_format{$pkg} = 1;
-      } else {
-        tlwarn ("$prg: tl package not found for file: $f\n");
-      }
-    }
-
-    # looked up all files for this format; save our list of packages.
-    my @pkgs = sort keys %pkgs_for_this_format;
-    &debug ("  packages for $format: @pkgs\n");
-    if (@pkgs == 0) {
-      tlwarn ("$prg: no packages for format $format?  files = @$files_ref\n");
-    }
-    $ret{$format} = \@pkgs;
-  }
-
-  &info ("Formats found: " . scalar (keys %ret) . "\n");
-  #&debug_hash ("pkgs_per_format returning", %ret);
-  return %ret;
-}
-
-

-# Compare lists of packages required by building (PKGS_PER_FORMAT) with
-# lists of existing trigger directives (FMTTRIGGERS).  Return 0 if
-# identical, 1 otherwise (and report differences).  Ignore hyphenation
-# dependencies and the package itself containing the trigger directive
-# (FMTPKGCONTAINERS).
-# 
-sub compare_pkgs_and_triggers {
-  my ($pkgs_per_format,$fmttriggers,$fmtpkgcontainers) = @_;
-  my $bad_p = 0;
-  my $all_pkgs = 0;
-  
-  # we don't include these as fmttriggers since when they meaningfully
-  # change, fmtutil should get called anyway due to language.* changing.
-  my @skip_pkgs = qw(dehyph-exptl hyph-utf8 ruhyphen ukrhyph);
-  # Anything matching hyphen-.* is also ignored.
-
-  for my $ef (sort keys %$pkgs_per_format) {
-    my @recorded_pkgs = @{$pkgs_per_format->{$ef}};
-    $all_pkgs += @recorded_pkgs;
-
-    my %recorded_pkgs;
-    @recorded_pkgs{@recorded_pkgs} = ();  # hash slice for recorded pkgs
-
-    if (defined $fmttriggers->{$ef}) {
-      my @tlpdb_pkgs = @{$fmttriggers->{$ef}};
-      my %tlpdb_pkgs;
-      @tlpdb_pkgs{@tlpdb_pkgs} = ();       # hash slice for tlpdb pkgs
-
-      my @recorded_only = ();
-      for my $r (keys %recorded_pkgs) {
-        # no need for a package to include itself as a fmttrigger.
-        next if $r eq $fmtpkgcontainers->{$ef};
-        
-        if (exists $tlpdb_pkgs{$r}) {
-          delete $tlpdb_pkgs{$r}; # ok, in both
-        } else {
-          # sometimes we like to include the hyphenation packages as
-          # triggers in the tlpdb, for no particular reason. Let that be
-          # ok, and only check for the skipped packages when making the
-          # trigger list for an engine.format not in tlpdb.
-          next if grep ($_ eq $r, @skip_pkgs);
-          next if $r =~ /hyphen-.*/;
-          push (@recorded_only, $r);
-        }
-      }
-      if (keys %tlpdb_pkgs) {
-        tlwarn ("$prg: $ef triggers only in tlpdb: "
-                . join (",", sort keys %tlpdb_pkgs) . "\n");
-        $bad_p = 1;
-      }
-      if (@recorded_only) {
-        tlwarn ("$prg: $ef triggers only in recorder: "
-                . join (",", sort @recorded_only) . "\n");
-        $bad_p = 1;
-      }
-      
-      delete $fmttriggers->{$ef};
-
-    } else {
-      # not in tlpdb at all; in a few cases, that is expected.
-      # Otherwise, complain and output needed fmttriggers directive.
-      if ($ef =~ /^(mf-nowin\.mf|(pdf|xe)tex\.cont-en)$/) {
-        delete $fmttriggers->{$ef}; # ok
-      } else {
-        tlwarn ("$prg: no fmttriggers in tlpdb: $ef\n"
-                . "  fmttriggers=" . join (",", @recorded_pkgs) . "\n");
-        $bad_p = 1;
-      }
-    }
-  }
-  
-  for my $ef (sort keys %$fmttriggers) {
-    my $trig = join (",", sort @{$fmttriggers->{$ef}});
-    tlwarn ("$prg: format in tlpdb only: "
-            . "$ef ($trig)\n");
-    $bad_p = 1;
-  }
-  
-  info ("Triggers checked: $all_pkgs (includes duplicates)\n");
-  return $bad_p;
-}
-
-__END__
-

-=head1 NAME
-
-check-fmttriggers - check that all needed packages trigger format rebuilds
-
-=head1 SYNOPSIS
-
-check-fmttriggers [I<option>]...
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<--fmtargs> I<str>
-
-Pass I<str> to C<fmtutil>, overriding C<--all>; e.g., for debugging you
-might want C<--fmtargs=--byfmt=tex> to build only C<tex.fmt>.  (Many
-inconsistencies with the TLPDB will be reported, naturally.)
-
-=item B<--fmtdir> I<dir>
-
-Rebuild formats in I<dir>; default C</tmp/fmttriggers>.  This directory
-is completely removed before rebuilding, so do not use any system
-directory.
-
-=item B<--no-rerecord>
-
-Do not rebuild all formats to remake the recorder files; the default
-(C<--rerecord>) is to do so.
-
-=item B<--help>
-
-Display this documentation and exit.
-
-=item B<--version>
-
-Display version information and exit.
-
-=back
-
-The standard options B<-q>, B<-v>, and B<-logfile>=I<file> are also
-accepted; see the C<process_logging_options> function in
-L<TeXLive::TLUtils> for details.  In particular, with B<-v> or higher,
-the packages found to be needed for each I<engine.format> combination
-will be reported.
-
-=head1 DESCRIPTION
-
-Compare the fmttriggers= listed in the tlpsrc files with the actual
-dependencies found by running fmtutil -recorder and inspecting the
-recorder (.fls) files.
-
-=head1 AUTHORS AND COPYRIGHT
-
-This script and its documentation were written for the TeX Live
-distribution (L<http://tug.org/texlive>) and both are licensed under the
-GNU General Public License Version 2 or later.
-
-=cut
-
-# Local Variables:
-# perl-indent-level: 2
-# tab-width: 2
-# indent-tabs-mode: nil
-# End:
-# vim: sw=2 expandtab

Deleted: trunk/Master/tlpkg/bin/check-tlnet-consistency
===================================================================
--- trunk/Master/tlpkg/bin/check-tlnet-consistency	2019-11-07 18:35:53 UTC (rev 52672)
+++ trunk/Master/tlpkg/bin/check-tlnet-consistency	2019-11-07 18:38:33 UTC (rev 52673)
@@ -1,312 +0,0 @@
-#!/usr/bin/env perl
-# $Id$
-# Copyright 2008-2019 Norbert Preining
-# This file is licensed under the GNU General Public License version 2
-# or any later version.
-# 
-# Checks the consistency of a tlnet tlpkg/texlive.tlpdb and the .tlpobj
-# included in the packages. Takes quite some time.
-
-BEGIN {
-  $vc_id = '$Id$';
-  $^W = 1;
-  ($mydir = $0) =~ s,/[^/]*$,,;
-  unshift (@INC, "$mydir/..");
-}
-
-use strict;
-use TeXLive::TLConfig;
-use TeXLive::TLCrypto;
-use TeXLive::TLPOBJ;
-use TeXLive::TLPDB;
-use TeXLive::TLUtils;
-use Getopt::Long;
-use Pod::Usage;
-use File::Path;
-
-our ($mydir, $vc_id);
-my $opt_location = "./tlnet";
-my $opt_nosetup = 0;
-my $opt_version = 0;
-my $opt_help = 0;
-my $opt_filelists = 0;
-
-TeXLive::TLUtils::process_logging_options();
-GetOptions(
-  "location=s"  => \$opt_location, 
-  "no-setup"    => \$opt_nosetup,
-  "filelists"   => \$opt_filelists,
-  "version"	=> \$opt_version,
-  "help|?"      => \$opt_help) or pod2usage(1);
-
-pod2usage("-exitstatus" => 0, "-verbose" => 2) if $opt_help;
-if ($opt_version) { print "$vc_id\n"; exit 0; } 
-
-exit (&main());
-
-

-sub main {
-  chomp(my $Master = `cd $mydir/../.. && pwd`);
-  # set up the programs ...
-  if ($opt_nosetup) {
-    # do a minimal setup
-    $::progs{'xz'} = "xz";
-    $::progs{'tar'} = "tar";
-  } else {
-    # do a full setup
-    my $ret = &TeXLive::TLUtils::setup_programs("$Master/tlpkg/installer");
-    if (!$ret) {
-      tlwarn("binaries could not be set up, aborting.\n");
-      exit 1;
-    }
-  }
-
-  # get our db, same hierarchy from which we are being run.
-  my $tlpdb = TeXLive::TLPDB->new("root" => $opt_location, 'verify' => 1);
-  die "Cannot init tlpdb from $opt_location ..." unless defined($tlpdb);
-  my $tempbase = "$opt_location/temp";
-  if (! -d $tempbase) {
-    mkdir($tempbase) or die "Cannot create $tempbase directory: $!";
-  }
-  my $temp = `mktemp -d -p \"$tempbase\"`;
-  chomp($temp);
-  die "Cannot create temporary directory in $tempbase: $!" if (! -d $temp);
-  my @notlpobj;
-  my @revisionerror;
-  my @missingsrccontainer;
-  my @missingdoccontainer;
-  my @sizeerror;
-  my %filedifferrors;
-  foreach my $pkg ($tlpdb->list_packages()) {
-    next if ($pkg =~ m/^00texlive/);
-    debug("working on $pkg\n");
-    my $cont = "$opt_location/archive/$pkg.tar.xz";
-    my $srccont = "$opt_location/archive/$pkg.source.tar.xz";
-    my $doccont = "$opt_location/archive/$pkg.doc.tar.xz";
-    my $tlpdbtlpobj = $tlpdb->get_package($pkg);
-    my $dodoc = ($tlpdb->config_doc_container && $tlpdbtlpobj->docfiles);
-    my $dosrc = ($tlpdb->config_src_container && $tlpdbtlpobj->srcfiles);
-    if ($opt_filelists) {
-      system("cat $cont | $::progs{xz} -dcf | $::progs{tar} -C \"$temp\" -xf - ");
-    } else {
-      system("cat $cont | $::progs{xz} -dcf | $::progs{tar} -C \"$temp\" -xf - tlpkg/tlpobj");
-    }
-    if (! -r "$temp/tlpkg/tlpobj/$pkg.tlpobj") {
-      debug("ERROR: no tlpobj: $temp/tlpkg/tlpobj/$pkg.tlpobj\n");
-      push @notlpobj, $pkg;
-    } else {
-      my $tartlpobj = TeXLive::TLPOBJ->new;
-      $tartlpobj->from_file("$temp/tlpkg/tlpobj/$pkg.tlpobj");
-      die "Cannot load tlpobj from $temp/$pkg.tlpobj: $!" unless defined($tartlpobj);
-      # get the src and doc containers unpacked and add the respective files
-      if ($dosrc) {
-        system("cat $srccont | $::progs{xz} -dcf | $::progs{tar} -C \"$temp\" -xf - tlpkg/tlpobj");
-        if (! -r "$temp/tlpkg/tlpobj/$pkg.source.tlpobj") {
-          push @missingsrccontainer, $pkg;
-          debug("ERROR: missing src container\n");
-        } else {
-          my $srctlpobj = TeXLive::TLPOBJ->new;
-          $srctlpobj->from_file("$temp/tlpkg/tlpobj/$pkg.source.tlpobj");
-          die "Cannot load tlpobj from $temp/$pkg.source.tlpobj: $!" unless defined($srctlpobj);
-          $tartlpobj->add_srcfiles($srctlpobj->srcfiles);
-        }
-      }
-      if ($dodoc) {
-        system("cat $doccont | $::progs{xz} -dcf | $::progs{tar} -C \"$temp\" -xf - tlpkg/tlpobj");
-        if (! -r "$temp/tlpkg/tlpobj/$pkg.doc.tlpobj") {
-          push @missingdoccontainer, $pkg;
-          debug("ERROR: missing doc container\n");
-        } else {
-          my $doctlpobj = TeXLive::TLPOBJ->new;
-          $doctlpobj->from_file("$temp/tlpkg/tlpobj/$pkg.doc.tlpobj");
-          die "Cannot load tlpobj from $temp/$pkg.doc.tlpobj: $!" unless defined($doctlpobj);
-          $tartlpobj->add_docfiles($doctlpobj->docfiles);
-        }
-      }
-      # check the revisions
-      if ($tlpdbtlpobj->revision != $tartlpobj->revision) {
-        push @revisionerror, "$pkg (tlpdb: " . $tlpdbtlpobj->revision . ", tar: " . $tartlpobj->revision . ")";
-      }
-      # check that the files are the same
-      my @a = $tlpdbtlpobj->all_files;
-      my @b = $tartlpobj->all_files;
-      my @ret = compare_lists(\@a, \@b);
-      push @{$filedifferrors{$pkg}}, @ret if @ret;
-      # check the file sizes and checksums
-      my $c = check_size_checksum($cont, $tlpdbtlpobj->containersize, 
-                                         $tlpdbtlpobj->containerchecksum);
-      push @sizeerror, "$pkg (" . ($c == 1 ? "size" : "checksum") . ")"
-        if ($c > 0);
-      debug("ERROR: size/checksum error main\n") if ($c > 0);
-      if ($dodoc) {
-        my $c = check_size_checksum($doccont, $tlpdbtlpobj->doccontainersize, 
-                                              $tlpdbtlpobj->doccontainerchecksum);
-        push @sizeerror, "$pkg.doc (" . ($c == 1 ? "size" : "checksum") . ")"
-          if ($c > 0);
-        debug("ERROR: size/checksum error doc\n") if ($c > 0);
-      }
-      if ($dosrc) {
-        my $c = check_size_checksum($srccont, $tlpdbtlpobj->srccontainersize, 
-                                              $tlpdbtlpobj->srccontainerchecksum);
-        push @sizeerror, "$pkg.source (" . ($c == 1 ? "size" : "checksum") . ")"
-          if ($c > 0);
-        debug("ERROR: size/checksum error src\n") if ($c > 0);
-      }
-      # check the actually included files are correct
-      # TODO TODO TODO
-      #
-      #
-      # should we do more checks?
-      # unlink("$temp/tlpkg/tlpobj/$pkg.tlpobj");
-      # unlink("$temp/tlpkg/tlpobj/$pkg.source.tlpobj");
-      # unlink("$temp/tlpkg/tlpobj/$pkg.doc.tlpobj");
-      system("rm -rf \"$temp/tlpkg\"");
-      system("rm -rf \"$temp/texmf\"");
-      system("rm -rf \"$temp/texmf-dist\"");
-      system("rm -rf \"$temp/texmf-doc\"");
-      system("ls \"$temp\"");
-    }
-  }
-  # system("rmdir --ignore-fail-on-non-empty $temp/tlpkg/tlpobj");
-  # system("rmdir --ignore-fail-on-non-empty $temp/tlpkg");
-  system("rmdir --ignore-fail-on-non-empty $temp $tempbase");
-  if (@notlpobj) {
-    print "packages without containing tlpobj file:\n";
-    for my $p (@notlpobj) {
-      print "$p\n";
-    }
-  }
-  if (@revisionerror) {
-    print "packages with revision discrepancy:\n";
-    for my $p (@revisionerror) {
-      print "$p\n";
-    }
-  }
-  if (@missingsrccontainer) {
-    print "packages with missing src containers:\n";
-    for my $p (@missingsrccontainer) {
-      print "$p\n";
-    }
-  }
-  if (@missingdoccontainer) {
-    print "packages with missing doc containers:\n";
-    for my $p (@missingdoccontainer) {
-      print "$p\n";
-    }
-  }
-  if (@sizeerror) {
-    print "packages with wrong container size/checksums:\n";
-    for my $p (@sizeerror) {
-      print "$p\n";
-    }
-  }
-  for my $pkg (keys %filedifferrors) {
-    print "file differences in $pkg:\n";
-    for my $l (@{$filedifferrors{$pkg}}) {
-      print "  $l\n";
-    }
-  }
-}
-
-
-sub compare_lists {
-  my ($la, $lb) = @_;
-  my @la = @$la;
-  my @lb = @$lb;
-  my %onlyfirst;
-  my %onlysecond;
-  my @ret;
-  for my $f (@la) { $onlyfirst{$f} = 1; }
-  for my $f (@lb) { delete($onlyfirst{$f}); $onlysecond{$f} = 1; }
-  for my $f (@la) { delete($onlysecond{$f}); }
-  for my $f (sort keys %onlyfirst) { push @ret, "-$f"; }
-  for my $f (sort keys %onlysecond) { push @ret, "+$f"; }
-  return(@ret);
-}
-
-sub check_size_checksum {
-  my ($cont, $size, $checksum) = @_;
-  my $sizeerror = 0;
-  my $checksumerror = 0;
-  if ($size > -1) {
-    my $s = (stat $cont)[7];
-    if ($s == $size) {
-      if ($checksum) {
-        if (TeXLive::TLCrypto::tlchecksum($cont) ne $checksum) {
-          $checksumerror = 1;
-        }
-      }
-    } else {
-      $sizeerror = 1;
-    }
-  } else {
-    if ($checksum) {
-      if (tlchecksum($cont) ne $checksum) {
-        $checksumerror = 1;
-      }
-    }
-  }
-  return 1 if $sizeerror;
-  return 2 if $checksumerror;
-  return 0;
-}
-
-__END__
-

-=head1 NAME
-
-check-tlnet-consistency - check the consistency of the tlnet distribution
-
-=head1 SYNOPSIS
-
-check-tlnet-consistency [I<option>]...
-
-=head1 OPTIONS
-
-=over 4
-
-=item B<-location> I</container/dir>
-
-The location to find the previously generated containers;
-default is C<./tlnet>.  
-
-=item B<-no-setup>
-
-Does not try to setup the various programs, but uses I<xz> and I<tar>
-from path.
-
-=item B<--help>
-
-Display this documentation and exit.
-
-=item B<--version>
-
-Display version information and exit.
-
-=back
-
-The standard options B<-q>, B<-v>, and B<-logfile>=I<file> are also
-accepted; see the C<process_logging_options> function in
-L<TeXLive::TLUtils> for details.
-
-=head1 DESCRIPTION
-
-This program compares the revisions as found in the C<texlive.tlpdb> of 
-the tlnet distributions with the revisions as specified in the included
-C<tlpobj> files in each package. In case there is a discrepancy this is
-reported to stdout.
-
-=head1 AUTHORS AND COPYRIGHT
-
-This script and its documentation were written for the TeX Live
-distribution (L<http://tug.org/texlive>) and both are licensed under the
-GNU General Public License Version 2 or later.
-
-=cut
-
-### Local Variables:
-### perl-indent-level: 2
-### tab-width: 2
-### indent-tabs-mode: nil
-### End:
-# vim:set tabstop=2 expandtab: #

Deleted: trunk/Master/tlpkg/bin/check-wrapper-consistency
===================================================================
--- trunk/Master/tlpkg/bin/check-wrapper-consistency	2019-11-07 18:35:53 UTC (rev 52672)
+++ trunk/Master/tlpkg/bin/check-wrapper-consistency	2019-11-07 18:38:33 UTC (rev 52673)
@@ -1,152 +0,0 @@
-#!/usr/bin/env perl
-# $Id$
-# Public domain.  Originally written 2008.
-# 
-# Check that the same set of files are wrappers on w32 and symlinks on
-# all others.
-
-BEGIN {
-  $^W = 1;
-  ($mydir = $0) =~ s,/[^/]*$,,;
-  unshift (@INC, "$mydir/..");
-  chomp ($Master = `cd $mydir/../.. && pwd`);
-}
-
-use Getopt::Long;
-use Pod::Usage;
-
-our ($mydir, $Master);
-
-my $help = 0;
-GetOptions("help|?"       => \$help) or pod2usage(1);
-pod2usage(-exitstatus => 0, -verbose => 2) if $help;
-
-exit (&main ());
-
-

-sub main {
-  my $err = 0;
-  
-  my $bindir = "$Master/bin";
-  chdir ($bindir) || die "chdir($bindir) failed: $!";
-  
-  my %w = &unx_wrapper_entries ("i386-linux");
-
-  # add some additional wrappers which are not found 
-  # automatically since they are not .. symlinks on Unix.
-  $w{'updmap'} = 1;
-  $w{'updmap-sys'} = 1;
-
-  chomp (my $srcdir = `cd $Master/../Build/source/texk/texlive && pwd`);
-  $cww = "$srcdir/w32_wrapper/runscript.exe";
-  $err += &check_w32 ("win32", $cww, %w);
-
-  return $err;
-}
-
-
-

-# return all symlinks starting with ".." in DIR as a hash, with symlink
-# targets as the values.  Check that targets are executable.
-# 
-sub unx_wrapper_entries {
-  my ($DIR) = @_;
-  my %ret;
-  
-  chomp (my $olddir = `pwd`);
-  chdir ($DIR) || die "chdir($DIR) failed: $!";
-
-  local *DIR;
-  opendir (DIR, ".") || die "opendir($DIR) failed: $!";
-  while (my $ent = readdir (DIR)) {
-    next unless -l $ent;  # skip all but symlinks
-    next if -d $ent;      # and skip directories (i.e., man/)
-
-    my $target = readlink ($ent);
-    die "readlink($ent) failed: $!" if !defined ($target);
-    next unless $target =~ /^\.\./;  # skip all but .. symlinks
-    
-    # the target of the symlink should be executable.
-    warn "$ent: target $target not executable\n" if ! -x $target;
-
-    $ret{$ent} = $target;  # remember name and link target
-  }
-  closedir (DIR) || warn "closedir($DIR) failed: $!";
-  chdir ($olddir) || die "chdir($olddir) failed: $!";
-
-  return %ret;
-}
-
-
-

-# Windows is painfully special, as usual.  Given the list of wrappers in
-# UW, check that each of those entries (excluding shell scripts) exists
-# in W32DIR as a .exe, and furthermore is a copy of the canonical w32
-# wrapper exe specified in W32CANONICAL.
-# 
-sub check_w32 {
-  my ($w32dir, $w32canonical, %uw) = @_;
-  my $diff = 0;
-  
-  my %is_shell_script = &list_shell_scripts ();
-  for my $k (sort keys %uw) {
-    next if $is_shell_script{$k};    # skip shell scripts
-    #
-    # also skip these special cases:
-    next if $k
-      =~ /^(epspdftk|latexindent|texdoctk|tlcockpit|tlmgr|tlshell|xasy)$/;
-    #
-    # else do the diff with the canonical wrapper:
-    $diff += system ("cmp $w32dir/$k.exe $w32canonical");
-  }
-
-  opendir (DIR, $w32dir) || die "opendir($DIR) failed: $!";
-  my @binfiles = readdir (DIR);
-  closedir (DIR) || warn "closedir($DIR) failed: $!";
-
-  foreach my $f (@binfiles) {
-    next unless ($f =~ s/\.(bat|cmd)$//); # only batch files
-    next if $uw{$f};                      # already checked
-    $diff += system ("cmp $w32dir/$f.exe $w32canonical");
-  }
-
-  # extra check for fmtutil-sys.exe, since fmtutil is an executable.
-  $diff += system ("cmp $w32dir/fmtutil-sys.exe $w32canonical");
-  
-  return $diff;
-}
-
-# As it happens, we already distinguish sh scripts from others in the
-# build process, for basically the same reason.  So return the list
-# maintained there by using a target defined in linked_scripts/Makefie
-# for us.
-# 
-sub list_shell_scripts {
-  my %sh;
-  
-  # has to be the Work/ directory to get the Makefile, not Makefile.{in,am}.
-  my $Work = "$Master/../Build/source/Work";
-  my $Work_linked_scripts = "$Work/texk/texlive/linked_scripts";
-  my $Work_tl_scripts = "$Work/texk/texlive/tl_scripts";
-  
-  -d "$Work_linked_scripts"||die "no linked_scripts dir: $Work_linked_scripts";
-  -d "$Work_tl_scripts" || die "no tl_scripts dir: $Work_tl_scripts";
-  
-  # use make; ensure we get only the last line, although that should be
-  # all there is.
-  my $lst = `make -s -C $Work_linked_scripts echo-shell-scripts | tail -1`;
-    $lst .= `make -s -C $Work_tl_scripts     echo-shell-scripts | tail -1`;
-  
-  for my $script (split (" ", $lst)) {
-    $script =~ s,^.*/,,;
-    $sh{$script} = 1;  # save with extension (for listings-ext.sh)
-    #
-    $script =~ s,\.[^.]*$,,;
-    $sh{$script} = 1;  # save without extension (everything else)
-  }
-
-  # more shell scripts, that are not part of linked_scripts.
-  $sh{"chkweb"} = 1;
-  
-  return %sh;
-}

Copied: trunk/Master/tlpkg/bin/tl-check-files-by-format (from rev 52672, trunk/Master/tlpkg/bin/check-files-by-format)
===================================================================
--- trunk/Master/tlpkg/bin/tl-check-files-by-format	                        (rev 0)
+++ trunk/Master/tlpkg/bin/tl-check-files-by-format	2019-11-07 18:38:33 UTC (rev 52673)
@@ -0,0 +1,360 @@
+#!/usr/bin/env perl
+# $Id$
+# Copyright Manuel P\'egouri\'e-Gonnard, 2010-2016. WTFPL v2.
+# Check that files in various formats are somewhat valid.
+#
+# This used to be run from cron, but no longer is, because it takes many
+# hours, and there are too many false positives. Inserting all the
+# exclusions got too annoying. Give up. --karl, 2aug19.
+#
+# The following formats are checked currently: pfb, pdf, tfm, vf, otf.
+#
+# For each format, there is one routine &check_<format> and an exclusion
+# 'list' (hash reference) $exclude_<format>: the keys are either a
+# directory name if they have a trailing slash, or a file name. If a key
+# named '*base*' is present, then the paths are relative to this base,
+# otherwise to $tlroot. The values of the keys may be free or have a
+# special meaning depending on the associated check_<format> routine.
+#
+# Formats that might be added:
+# - afm with (afm2pl?)
+
+BEGIN {
+#  $^W = 1;
+  ($mydir = $0) =~ s,/[^/]*$,,;
+  $tlroot = "$mydir/../..";
+  unshift (@INC, "$tlroot/tlpkg");
+}
+
+use File::Basename;
+use File::Temp;
+use Pod::Usage;
+use Getopt::Long;
+
+use TeXLive::TLPDB;
+
+

+# Most of these breakages need to be reported upstream, or documented
+# that they are unavoidable.  Add comments if you pursue any of them.
+
+# value has no meaning here
+my $exclude_otf = { '*base*' => 'texmf-dist/fonts/opentype',
+  'texmf-dist/doc/fonts/cm-unicode/Fontmap.CMU.otf' => 1,
+};
+
+# 1 means pdfinfo issues errors but still exits successfully
+# 2 means pdfinfo exits non-zero
+# -1 means skip completely.
+my $exclude_pdf = {
+     # 14nov11 author cannot fix:
+  'texmf-dist/doc/fonts/frcursive/frcursive.pdf' => 1,
+     # 17apr14 unknown:
+  'texmf-dist/doc/generic/pst-perspective/' => 1,
+     # 2jul16+20dec15 "couldn't read xref table", but seems basically ok:
+  'texmf-dist/doc/latex/bookcover/figures/ekflogo.pdf' => 1,
+  'texmf-dist/doc/latex/dvdcoll/dcexample.pdf' => 1,   # acroform but ok
+  'texmf-dist/doc/latex/visualfaq/visualFAQ.pdf' => 1, # acroform but ok
+  'texmf-dist/doc/latex/ksp-thesis/ksp-thesis.pdf' => 1,
+     # 4aug16 pdfinfo from xpdf 3.03 crashes (reported to derekn):
+  'texmf-dist/doc/latex/ocgx/demo-ocgx.pdf' => -1,
+     # not a PDF file:
+  'texmf-dist/dvips/tetex/config.pdf' => -1,
+};
+
+# the value has no meaning here
+my $exclude_pfb = { '*base*' => 'texmf-dist/fonts/type1',
+  'adobe/courier/' => 1,
+  'adobe/sourcecodepro/' => 1, # SourceCodePro-{Regular,BoldIt}.pfb, 10nov12 contacted
+  'arabi/arabeyes/' => 1,
+  'arabi/farsiweb/' => 1,
+  'arkandis/adfsymbols/' => 1,
+  'arkandis/libris/' => 1,
+  'arkandis/venturis/' => 1,
+  'arphic/bkaiu/' => 1,
+  'arphic/bsmiu/' => 1,
+  'arphic/gbsnu/' => 1,
+  'arphic/gkaiu/' => 1,
+  'gust/poltawski/' => 1,
+  'nowacki/iwona/' => 1,
+  'nowacki/kurier/' => 1,
+  'public/allrunes/' => 1,
+  'public/amsfonts/cm/' => 1,
+  'public/amsfonts/cmextra/' => 1,
+  'public/arev/' => 1,
+  'public/ascii-font/' => 1,
+  'public/aspectratio/' => 1, # 11feb12 reported to author
+  'public/augie/' => 1,
+  'public/aurical/' => 1,
+  'public/bbold-type1/' => 1, # old y&y fonts, won't be changing
+  'public/belleek/' => 1,
+  'public/bera/' => 1,
+  'public/brushscr/' => 1,
+  'public/burmese/' => 1,
+  'public/carolmin-ps/' => 1,
+  'public/chemarrow/' => 1,
+  'public/cjhebrew/' => 1,
+  'public/cm-super/' => 1,
+  'public/cm-unicode/cmunobi.pfb' => 1,
+  'public/cmcyr/' => 1,
+  'public/countriesofeurope/' => 1, # 22apr12 not reported
+  'public/cs/' => 1,
+  'public/doublestroke/' => 1,
+  'public/ebgaramond/' => 1,	# 9jul14 bug in fontforge/t1lint, not reported
+  'public/epiolmec/' => 1,
+  'public/esstix/' => 1,	# 12may11 author fixed some, others will remain
+  'public/ethiop-t1/' => 1,
+  'public/eurosym/' => 1,
+  'public/fbb/' => 1,		# 23aug13 bluevalues, not fixable
+  'public/fira/' => 1,		# 2015 author unable/unwilling
+  'public/foekfont/' => 1,
+  'public/fonetika/' => 1,
+  'public/fontawesome/' => 1,	# 2015 author unable/unwilling
+  'public/fourier/' => 1,
+  'public/gfsartemisia/' => 1,
+  'public/gfsbaskerville/' => 1,
+  'public/gfsbodoni/' => 1,
+  'public/gfscomplutum/' => 1,
+  'public/gfsdidot/' => 1,
+  'public/gfsneohellenic/' => 1,
+  'public/gfssolomos/' => 1,
+  'public/hacm/' => 1,
+  'public/initials/' => 1,
+  'public/ipaex-type1/' => 1,	# 20may13 too many to bother reporting
+  'public/itrans/' => 1,
+  'public/kerkis/' => 1,
+  'public/kpfonts/' => 1,
+  'public/libertine/' => 1,	# 5jan13 maintainer declines to fix triviality
+  'public/libertinust1math/'=>1,# 7apr16 hint triviality not fixed
+  'public/linearA/' => 1,
+  'public/lm/' => 1,
+  'public/lxfonts/' => 1,
+  'public/marvosym/' => 1,
+  'public/mathabx-type1/' => 1, # 14jan11 wrote bnb/preining --karl
+  'public/mathdesign/mdpus/' => 1,# 3jan16 author informed long ago, no release
+  'public/mathpazo/' => 1,
+  'public/newpx/' => 1,		# 21aug16 bluezones not worth fixing
+  'public/newtx/' => 1,		# 21aug16 bluezones not worth fixing
+  'public/ocherokee/' => 1,
+  'public/oinuit/' => 1,
+  'public/old-arrows/' => 1,	# 2015 author unable/unwilling
+  'public/omega/' => 1,
+  'public/phaistos/' => 1,
+  'public/pl/' => 1,
+  'public/playfair/' => 1,	# 15mar14 known hinting issues
+  'public/pxfonts/' => 1,
+  'public/rsfs/' => 1,
+  'public/starfont/' => 1,	# 4oct10 reported to author 
+  'public/staves/' => 1,
+  'public/stmaryrd/' => 1,	# blue values not defined, not maintained
+  'public/tabvar/' => 1,
+  'public/tex-gyre/' => 1,
+  'public/txfonts/' => 1,
+  'public/txfontsb/' => 1,
+  'public/wasy2-ps/' => 1,	# too old, will not be updated
+  'public/xypic/' => 1,
+  'public/yhmath/' => 1,
+  'texmf-dist/doc/fonts/cm-unicode/Fontmap.CMU.pfb' => 1,
+  'uhc/umj/' => 1,
+  'urw/avantgar/' => 1,
+  'urw/bookman/' => 1,
+  'urw/courier/' => 1,
+  'urw/helvetic/' => 1,
+  'urw/ncntrsbk/' => 1,
+  'urw/palatino/' => 1,
+  'urw/symbol/' => 1,
+  'urw/times/' => 1,
+  'urw/zapfding/' => 1,
+  'vntex/arevvn/' => 1,
+  'vntex/comicsansvn/' => 1,
+  'vntex/txttvn/' => 1,
+  'vntex/urwvn/' => 1,
+  'vntex/vnr/' => 1,
+  'wadalab/dgj/' => 1,
+  'wadalab/dmj/' => 1,
+  'wadalab/mcj/' => 1,
+  'wadalab/mrj/' => 1,
+  'tlpkg/texworks/share/fonts/' => 1, # these come from gs
+};
+
+

+# the value has no meaning here
+my $exclude_tfm = { '*base*' => 'texmf-dist/fonts/tfm',
+  'jknappen/ec/' => 1,
+  'jknappen/fc/' => 1,
+  'public/arev/' => 1,
+  'public/chess/' => 1,		# original has extra bytes, not worth fixing
+  'public/cmcyr/' => 1,
+  'public/dozenal/' => 1,	# wrote author 31oct12
+  'public/gfsbodoni/' => 1,	# wrote author 12dec12
+  'public/japanese-otf/' => 1,	# japanese tfm's
+  'public/malayalam/' => 1,
+  'public/mathdesign/mdici/' => 1,# 3jan16 author informed long ago, no release
+  'public/mathdesign/mdpgd/' => 1,
+  'public/mathdesign/mdpus/' => 1,
+  'public/wnri/' => 1,
+  'public/wsuipa/' => 1,
+};
+
+

+# the value has no meaning here
+my $exclude_vf = { '*base*' => 'texmf-dist/fonts/vf',
+  'public/ae/' => 1,
+  'public/bgreek/' => 1,
+  'public/eco/' => 1,
+  'public/epigrafica/' => 1,
+  'public/fonts-tlwg/' => 1,	# reported to author, early 2012
+  'public/gfsartemisia/' => 1,
+  'public/gfscomplutum/' => 1,
+  'public/gfsdidot/' => 1,
+  'public/gfsneohellenic/' => 1,
+  'public/gfsporson/' => 1,
+  'public/gfssolomos/' => 1,
+  'public/hfoldsty/' => 1,
+  'public/kerkis/' => 1,
+  'public/mathdesign/mdbch/' => 1, #3jan16 author informed long ago, no release
+  'public/mathdesign/mdbch/' => 1, #3jan16 author informed long ago, no release
+  'public/mathdesign/mdici/' => 1,
+  'public/mathdesign/mdpgd/' => 1,
+  'public/mathdesign/mdpus/' => 1,
+  'public/mathdesign/mdput/' => 1,
+  'public/mathdesign/mdugm/' => 1,
+  'public/sansmathfonts/' => 2,	# 20may13 ok with cmssbx12.tfm from sauter
+  'public/txfontsb/' => 1,
+  'public/uppunctlm/' => 1,
+  'public/zefonts/' => 1,
+  'vntex/comicsansvn/' => 1,
+};
+
+
+my $tmpdir = File::Temp::tempdir(CLEANUP => 1);
+
+my $opt_all = 0;
+my $opt_help = 0;
+
+TeXLive::TLUtils::process_logging_options ();
+GetOptions ("all" => \$opt_all,
+            "help|?" => \$opt_help) or pod2usage (2);
+pod2usage ("-exitstatus" => 0, "-verbose" => 2) if $opt_help;
+
+
+exit(&main());
+
+

+sub main {
+  my @files = get_file_list();
+
+  for my $file (grep { /\.otf$/ } @files) {
+    check_otf($file);}
+
+  for my $file (grep { /\.pdf$/ } @files) {
+    check_pdf($file); }
+
+  for my $file (grep { /\.pfb$/ } @files) {
+    check_pfb($file); }
+
+  for my $file (grep { /\.tfm$/ } @files) {
+    check_tfm($file); }
+
+  for my $file (grep { /\.vf$/ } @files) {
+    check_vf($file); }
+
+  return 0;
+}
+
+# get the list of files in the database of a TL installation
+sub get_file_list {
+  my $tlpdb = TeXLive::TLPDB->new(root => $tlroot);
+
+  my @files = ();
+  for my $tlpname ($tlpdb->list_packages) {
+    my $tlp = $tlpdb->get_package($tlpname);
+    push(@files, $tlp->docfiles, $tlp->runfiles, $tlp->srcfiles);
+  }
+
+  # [u]ptex font files use their own formats; don't bother checking,
+  # or adding lots of individual entries to the exclude lists.
+  @files = grep ($_ !~ m![-/]u?ptex(-fonts)?/!, @files);
+
+  # It takes a long time (about an hour) to check every file.  And there
+  # is no value in checking unchanged files every day.  So we filter the
+  # file list (unless --all is given) by mtime ... unless this happens
+  # to be the first of the month, when we'll check everything, just to
+  # be reminded of anything that may have crept in.
+  # 
+  if (! ($opt_all || `date +%d` == 1)) {
+    my @filtered = ();
+    for my $f (@files) {
+      push (@filtered, $f) if (-M "$tlroot/$f" < 4);
+    }
+    @files = @filtered;
+  }
+  return @files;
+}
+
+
+# return the value in exclude list associated to a file, or undef
+sub exclude_value {
+  my ($exclude, $file) = @_;
+  my $base = $exclude->{'*base*'};
+  $file =~ s!^$base/!! if $base;
+  (my $filedir = $file) =~ s![^/]*$!!;
+  return $exclude->{$file} || $exclude->{$filedir};
+}
+
+

+# the checking routines for each file type.
+
+sub check_pdf {
+  my ($file) = @_;
+  my $excl_val = exclude_value($exclude_pdf, $file) || 0;
+  return if $excl_val < 0;
+  #
+  my $errfile = "$tmpdir/pdferr";
+  unlink($errfile);
+  my $bad_exit = system("pdfinfo $tlroot/$file >/dev/null 2>$errfile");
+  my $badness = $bad_exit ? 2 : -s $errfile ? 1 : 0;
+  return if $badness <= $excl_val;
+  print "Bad PDF: $file\n" if $badness == 2;
+  print "Damaged PDF: $file\n" if $badness == 1;
+}
+
+sub check_pfb {
+  my ($file) = @_;
+  return if defined exclude_value($exclude_pfb, $file);
+  my $errfile = "$tmpdir/pfberr";
+  unlink($errfile);
+  my $bad = system("t1lint -q $tlroot/$file");
+  print "Bad pfb: $file\n" if $bad;
+}
+
+sub check_tfm {
+  my ($file) = @_;
+  return if defined exclude_value($exclude_tfm, $file);
+  my $outfile = "$tmpdir/tfmout.pl";
+  my $errfile = "$tmpdir/tfmerr";
+  unlink($errfile);
+  system("tftopl $tlroot/$file $outfile 2>$errfile");
+  print "Bad tfm: $file\n" if -s $errfile;
+}
+
+sub check_vf {
+  my ($file) = @_;
+  return if defined exclude_value($exclude_vf, $file);
+  (my $tfmfile = $file) =~ s!/vf/!/tfm/!;
+  $tfmfile =~ s/\.vf$/.tfm/;
+  return if defined exclude_value($exclude_tfm, $tfmfile);
+  my $outfile = "$tmpdir/vfout.vp";
+  my $errfile = "$tmpdir/vferr";
+  unlink($errfile);
+  system("vftovp $tlroot/$file $tlroot/$tfmfile $outfile 2>$errfile");
+  print "Bad vf: $file\n" if -s $errfile;
+}
+
+sub check_otf {
+  my ($file) = @_;
+  return if defined exclude_value($exclude_otf, $file);
+  my $bad = system("otfinfo --info $tlroot/$file >/dev/null 2>&1");
+  print "Bad otf: $file\n" if $bad;
+}
+
+# vim: sw=2 expandtab

Copied: trunk/Master/tlpkg/bin/tl-check-fmttriggers (from rev 52672, trunk/Master/tlpkg/bin/check-fmttriggers)
===================================================================
--- trunk/Master/tlpkg/bin/tl-check-fmttriggers	                        (rev 0)
+++ trunk/Master/tlpkg/bin/tl-check-fmttriggers	2019-11-07 18:38:33 UTC (rev 52673)
@@ -0,0 +1,423 @@
+#!/usr/bin/env perl
+# $Id$
+# Originally written by Norbert Preining and Karl Berry, 2015.  Public domain.
+# 
+# Determine the files on which each format (fmt/base) depends
+#   (by running fmtutil -recorder),
+# then map those files to TL packages,
+# then check that exactly those packages are listed as triggers in the
+#   corresponding tlpsrc files.
+
+my $vc_id = '$Id$';
+my $Master;
+
+BEGIN {
+  $^W = 1;
+  $| = 1;
+  (my $mydir = $0) =~ s,/[^/]*$,,;
+  my $tlroot = "$mydir/../..";
+  unshift (@INC, "$tlroot/tlpkg");
+  chomp ($Master = `cd $mydir/../.. && pwd`);
+}
+
+use File::Find;
+use Getopt::Long;
+use Pod::Usage;
+
+use TeXLive::TLConfig;
+use TeXLive::TLUtils qw(info debug ddebug debug_hash tlwarn tldie);
+
+my $prg = TeXLive::TLUtils::basename($0);
+
+my $opt_fmtargs = "--all";
+my $opt_fmtdir = "/tmp/fmttriggers";
+my $opt_rerecord = 1;
+my $opt_help = 0;
+my $opt_version = 0;
+
+TeXLive::TLUtils::process_logging_options ();
+GetOptions (
+  "fmtargs=s"  => \$opt_fmtargs,
+  "fmtdir"     => \$opt_fmtdir,
+  "rerecord!"  => \$opt_rerecord,
+  "version"    => \$opt_version,
+  "help|?"     => \$help) || pod2usage(1);
+
+pod2usage ("-exitstatus" => 0, "-verbose" => 2) if $help;
+if ($opt_version) { print "$vc_id\n"; exit 0; } 
+
+$::installerdir = $Master;  # TLUtils.pm should be smarter
+$ENV{'PATH'} = "$Master/bin/" . TeXLive::TLUtils::platform() . ":$ENV{PATH}";
+
+exit (&main());
+
+

+sub main {
+  # no interference from TEXMFHOME, etc.
+  $ENV{'TEXMFHOME'}   = "/nonesuch-home";
+  $ENV{'TEXMFVAR'}    = "/nonesuch-uvar";
+  $ENV{'TEXMFCONFIG'} = "/nonesuch-config";
+  $ENV{'TEXMFLOCAL'}  = "/nonesuch-local";
+
+  if ($opt_rerecord) {  # remake recorder files?
+    my $status = &run_fmtutil ($opt_fmtdir);
+    return $status if $status;
+  }
+  #system ("bytime $opt_fmtdir");
+  
+  # read recorder files.
+  my %files_per_format = &files_per_format ($opt_fmtdir);
+
+  # read tlpdb.
+  my $tlpdb_file = "$Master/tlpkg/texlive.tlpdb";
+  my ($tlpdb,$fmttriggers,$fmtpkgcontainers) = &tlpdb_by_file ($tlpdb_file);
+ 
+  # map files used in the format builds to packages.
+  my %pkgs_per_format = &pkgs_per_format ($tlpdb, %files_per_format);
+  
+  # check that those packages are exactly what's listed as needed.
+  return &compare_pkgs_and_triggers (\%pkgs_per_format,
+                                     $fmttriggers, $fmtpkgcontainers);
+}
+
+

+# Run fmtutil --fmtdir=$OUTDIR --recorder ..., to recreate the recorder
+# files which are the basis for finding the dependencies.
+# 
+# OUTDIR is completely removed first (!!), on the theory that this job
+# should only be done in temporary directories.
+# 
+sub run_fmtutil {
+  my ($outdir) = @_;
+  
+  # yep, destroy output directory tree.
+  TeXLive::TLUtils::rmtree ($outdir);
+  mkdir ($outdir, 0775) || die "$prg: mkdir($outdir) failed: $!";
+  
+  # the output from fmtutil can be useful in debugging.
+  my $logfile = "$outdir/fmtutil.log";
+  my $cmd = "fmtutil --sys --recorder --strict --fmtdir=$outdir "
+             . "$opt_fmtargs >$logfile 2>&1";
+  &info ("Running $cmd\n");
+  my $retval = system ($cmd);
+  $retval >>= 8 if $retval > 0;
+  if ($retval) {
+    tlwarn ("fmtutil exit status = $retval; contents of $logfile =\n");
+    tlwarn (`cat $logfile`);
+    tldie ("fmtutil failed, goodbye.\n");
+  }
+  return $retval;
+}
+
+

+# Return a hash with each key being a string of the form ENGINE.FORMAT,
+# and the corresponding value a reference to the list of files used to
+# make that format with that engine.  This is based on reading the
+# recorder files (format.fls/.ofl) for the format in FMTDIR.
+# Uninteresting files are removed from the list, as is the Master
+# directory prefix.
+# 
+sub files_per_format {
+  my ($fmtdir) = @_;
+  my %ret;
+  
+  # gather all fls files.
+  my @fls = ();
+  my $recorder_files = sub {
+    # fun with perl: we use an anonymous sub because it's lexically scoped,
+    #   hence we can update a my variable inside.  Explanation at, e.g.,
+    #   http://stackoverflow.com/questions/8839005
+    # In this case, we could also pass a lambda sub to find, since
+    #   this sub is so simple, but for purposes of example, do it this way.
+    push (@fls, $File::Find::name)
+      if $File::Find::name =~ /\.(fls|ofl)$/
+  };
+  File::Find::find ($recorder_files, $fmtdir);
+  
+  # each fls file will become an entry in the return hash.
+  my $fls_count = @fls;
+  &info ("Reading $fls_count fls file(s): @fls\n");
+  for my $fls_name (@fls) {
+    open (my $fls, $fls_name) || die "open($fls_name) failed: $!";
+    my @files = ();
+    while (<$fls>) {
+      next unless s/^INPUT //;
+      next if m,/web2c/texmf\.cnf$,;       # read internally by kpathsea
+      next if m,/fontname/texfonts\.map$,; # likewise
+      next if m,/texsys\.aux$,;            # aux file created during run
+      chomp;
+      s,^${Master}/,,;			   # rm prefix
+      push (@files, $_);
+    }
+    close ($fls) || warn "close($fls_name) failed: $!";
+    
+    # The engine name is the directory above the format file,
+    # and the format name is the format file without extension.
+    my ($engine,$format) = ($fls_name =~ m!^.*/([^/]+)/([^/.]+)\.[^/]+$!);
+    #
+    # we'd have to have a similar special case for mpost if mem files
+    # were still used (see rebuild_one_format in fmtutil).
+    $engine = "mf-nowin" if $engine eq "metafont";
+    #
+    my $ef = "$engine.$format";
+
+    # Unfortunately, format filenames themselves are not unique, due to
+    # cont-en and pdfcsplain.  Shouldn't be any engine+format dups, though.
+    # 
+    tldie ("$prg: already saw format $ef\n (with files @{$ret{$ef}}),\n"
+           . "  files now = @files\n")
+      if exists $ret{$ef};
+    $ret{$ef} = \@files;
+  }
+
+  #&debug_hash ("files_per_format returning hash", %ret);
+  return %ret;
+}
+
+

+# Read TLPDB_FILE and return references to three hashes:
+# the first mapping contained files to TL package names, 
+# the second mapping engine.format names to their specified fmttriggers,
+# and the third mapping engine.format names to the package defining them.
+# 
+# Instead of using the general TeXLive::TLPDB functions, read the tlpdb
+# file ourselves.  We want to build the file->package mapping just once,
+# for all files, or things become noticeably slow.  (The tlpfiles script
+# does this too, but we repeat that code here because we want to find
+# the fmttriggers too.)
+#
+sub tlpdb_by_file {
+  my ($tlpdb_file) = @_;
+  my (%tlpfiles, %fmttriggers, %fmtpkgcontainers);
+  
+  open (my $tlpdb, $tlpdb_file) || die "open($tlpdb_file) failed: $!";
+  my $pkg;
+  while (<$tlpdb>) {
+    chomp;
+    if (/^name /) {  # notice package names
+      (undef,$pkg) = split (/ /);
+
+    } elsif (s/^execute +AddFormat +//) {  # notice AddFormat lines
+      my %af = TeXLive::TLUtils::parse_AddFormat_line ($_);
+      if (exists $af{"error"}) {
+        tldie ("$prg: parse_AddFormat_line failed: $af{error}\n"
+               . "line = $_\n");
+      }
+      if ($af{"fmttriggers"}) {
+        my $ef = "$af{engine}.$af{name}";
+        if (exists ($fmttriggers{$ef})) {
+          tldie ("$prg: already saw triggers for $ef ($fmttriggers{$ef}),"
+                 . "  triggers now = $af{fmttriggers}\n");
+        }
+        $fmttriggers{$ef} = $af{"fmttriggers"};
+        $fmtpkgcontainers{$ef} = $pkg;
+        #warn "  fmtpkgcontainers{$ef} = $pkg\n";
+      } else {
+        tlwarn ("$prg: no fmttriggers: $_\n");
+      }
+
+    } elsif (s/^ //) { # notice file names
+      # we carefully designed the format so that the only lines with
+      # leading spaces are the files.
+      # The installer "package" isn't one, just ignore it.
+      next if $pkg eq "00texlive.installer";
+      my $f = $_;
+      tlwarn ("$prg: already saw file $f (package $tlpfiles{$f}),"
+              . " now in package $pkg\n")
+        if exists $tlpfiles{$f}; # should never happen
+      $tlpfiles{$f} = $pkg;
+    }
+  }
+  close ($tlpdb) || warn "close($tlpdb_file) failed: $!";
+  
+  &info ("TLPDB files: " . scalar (keys %tlpfiles)
+         . "  triggers: " . scalar (keys %fmttriggers) . "\n");
+  return (\%tlpfiles, \%fmttriggers, \%fmtpkgcontainers);
+}
+  
+

+# Return a hash with each key being a format name and the corresponding
+# value a reference to the list of TL packages which contain the files
+# used to make that format, based on the incoming TLPDB and FILES_PER_FORMAT.
+# 
+sub pkgs_per_format {
+  my ($tlpdb,%files_per_format) = @_;
+  my %ret;  # format->pkgs mapping
+
+  for my $format (sort keys %files_per_format) {
+    &debug ("finding packages for $format...\n");
+    my %pkgs_for_this_format;
+    my $files_ref = $files_per_format{$format};
+    for my $f (@$files_ref) {
+      if (exists $tlpdb->{$f}) {
+        my $pkg = $tlpdb->{$f};
+        $pkgs_for_this_format{$pkg} = 1;
+      } else {
+        tlwarn ("$prg: tl package not found for file: $f\n");
+      }
+    }
+
+    # looked up all files for this format; save our list of packages.
+    my @pkgs = sort keys %pkgs_for_this_format;
+    &debug ("  packages for $format: @pkgs\n");
+    if (@pkgs == 0) {
+      tlwarn ("$prg: no packages for format $format?  files = @$files_ref\n");
+    }
+    $ret{$format} = \@pkgs;
+  }
+
+  &info ("Formats found: " . scalar (keys %ret) . "\n");
+  #&debug_hash ("pkgs_per_format returning", %ret);
+  return %ret;
+}
+
+

+# Compare lists of packages required by building (PKGS_PER_FORMAT) with
+# lists of existing trigger directives (FMTTRIGGERS).  Return 0 if
+# identical, 1 otherwise (and report differences).  Ignore hyphenation
+# dependencies and the package itself containing the trigger directive
+# (FMTPKGCONTAINERS).
+# 
+sub compare_pkgs_and_triggers {
+  my ($pkgs_per_format,$fmttriggers,$fmtpkgcontainers) = @_;
+  my $bad_p = 0;
+  my $all_pkgs = 0;
+  
+  # we don't include these as fmttriggers since when they meaningfully
+  # change, fmtutil should get called anyway due to language.* changing.
+  my @skip_pkgs = qw(dehyph-exptl hyph-utf8 ruhyphen ukrhyph);
+  # Anything matching hyphen-.* is also ignored.
+
+  for my $ef (sort keys %$pkgs_per_format) {
+    my @recorded_pkgs = @{$pkgs_per_format->{$ef}};
+    $all_pkgs += @recorded_pkgs;
+
+    my %recorded_pkgs;
+    @recorded_pkgs{@recorded_pkgs} = ();  # hash slice for recorded pkgs
+
+    if (defined $fmttriggers->{$ef}) {
+      my @tlpdb_pkgs = @{$fmttriggers->{$ef}};
+      my %tlpdb_pkgs;
+      @tlpdb_pkgs{@tlpdb_pkgs} = ();       # hash slice for tlpdb pkgs
+
+      my @recorded_only = ();
+      for my $r (keys %recorded_pkgs) {
+        # no need for a package to include itself as a fmttrigger.
+        next if $r eq $fmtpkgcontainers->{$ef};
+        
+        if (exists $tlpdb_pkgs{$r}) {
+          delete $tlpdb_pkgs{$r}; # ok, in both
+        } else {
+          # sometimes we like to include the hyphenation packages as
+          # triggers in the tlpdb, for no particular reason. Let that be
+          # ok, and only check for the skipped packages when making the
+          # trigger list for an engine.format not in tlpdb.
+          next if grep ($_ eq $r, @skip_pkgs);
+          next if $r =~ /hyphen-.*/;
+          push (@recorded_only, $r);
+        }
+      }
+      if (keys %tlpdb_pkgs) {
+        tlwarn ("$prg: $ef triggers only in tlpdb: "
+                . join (",", sort keys %tlpdb_pkgs) . "\n");
+        $bad_p = 1;
+      }
+      if (@recorded_only) {
+        tlwarn ("$prg: $ef triggers only in recorder: "
+                . join (",", sort @recorded_only) . "\n");
+        $bad_p = 1;
+      }
+      
+      delete $fmttriggers->{$ef};
+
+    } else {
+      # not in tlpdb at all; in a few cases, that is expected.
+      # Otherwise, complain and output needed fmttriggers directive.
+      if ($ef =~ /^(mf-nowin\.mf|(pdf|xe)tex\.cont-en)$/) {
+        delete $fmttriggers->{$ef}; # ok
+      } else {
+        tlwarn ("$prg: no fmttriggers in tlpdb: $ef\n"
+                . "  fmttriggers=" . join (",", @recorded_pkgs) . "\n");
+        $bad_p = 1;
+      }
+    }
+  }
+  
+  for my $ef (sort keys %$fmttriggers) {
+    my $trig = join (",", sort @{$fmttriggers->{$ef}});
+    tlwarn ("$prg: format in tlpdb only: "
+            . "$ef ($trig)\n");
+    $bad_p = 1;
+  }
+  
+  info ("Triggers checked: $all_pkgs (includes duplicates)\n");
+  return $bad_p;
+}
+
+__END__
+

+=head1 NAME
+
+check-fmttriggers - check that all needed packages trigger format rebuilds
+
+=head1 SYNOPSIS
+
+check-fmttriggers [I<option>]...
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--fmtargs> I<str>
+
+Pass I<str> to C<fmtutil>, overriding C<--all>; e.g., for debugging you
+might want C<--fmtargs=--byfmt=tex> to build only C<tex.fmt>.  (Many
+inconsistencies with the TLPDB will be reported, naturally.)
+
+=item B<--fmtdir> I<dir>
+
+Rebuild formats in I<dir>; default C</tmp/fmttriggers>.  This directory
+is completely removed before rebuilding, so do not use any system
+directory.
+
+=item B<--no-rerecord>
+
+Do not rebuild all formats to remake the recorder files; the default
+(C<--rerecord>) is to do so.
+
+=item B<--help>
+
+Display this documentation and exit.
+
+=item B<--version>
+
+Display version information and exit.
+
+=back
+
+The standard options B<-q>, B<-v>, and B<-logfile>=I<file> are also
+accepted; see the C<process_logging_options> function in
+L<TeXLive::TLUtils> for details.  In particular, with B<-v> or higher,
+the packages found to be needed for each I<engine.format> combination
+will be reported.
+
+=head1 DESCRIPTION
+
+Compare the fmttriggers= listed in the tlpsrc files with the actual
+dependencies found by running fmtutil -recorder and inspecting the
+recorder (.fls) files.
+
+=head1 AUTHORS AND COPYRIGHT
+
+This script and its documentation were written for the TeX Live
+distribution (L<http://tug.org/texlive>) and both are licensed under the
+GNU General Public License Version 2 or later.
+
+=cut
+
+# Local Variables:
+# perl-indent-level: 2
+# tab-width: 2
+# indent-tabs-mode: nil
+# End:
+# vim: sw=2 expandtab

Copied: trunk/Master/tlpkg/bin/tl-check-tlnet-consistency (from rev 52672, trunk/Master/tlpkg/bin/check-tlnet-consistency)
===================================================================
--- trunk/Master/tlpkg/bin/tl-check-tlnet-consistency	                        (rev 0)
+++ trunk/Master/tlpkg/bin/tl-check-tlnet-consistency	2019-11-07 18:38:33 UTC (rev 52673)
@@ -0,0 +1,312 @@
+#!/usr/bin/env perl
+# $Id$
+# Copyright 2008-2019 Norbert Preining
+# This file is licensed under the GNU General Public License version 2
+# or any later version.
+# 
+# Checks the consistency of a tlnet tlpkg/texlive.tlpdb and the .tlpobj
+# included in the packages. Takes quite some time.
+
+BEGIN {
+  $vc_id = '$Id$';
+  $^W = 1;
+  ($mydir = $0) =~ s,/[^/]*$,,;
+  unshift (@INC, "$mydir/..");
+}
+
+use strict;
+use TeXLive::TLConfig;
+use TeXLive::TLCrypto;
+use TeXLive::TLPOBJ;
+use TeXLive::TLPDB;
+use TeXLive::TLUtils;
+use Getopt::Long;
+use Pod::Usage;
+use File::Path;
+
+our ($mydir, $vc_id);
+my $opt_location = "./tlnet";
+my $opt_nosetup = 0;
+my $opt_version = 0;
+my $opt_help = 0;
+my $opt_filelists = 0;
+
+TeXLive::TLUtils::process_logging_options();
+GetOptions(
+  "location=s"  => \$opt_location, 
+  "no-setup"    => \$opt_nosetup,
+  "filelists"   => \$opt_filelists,
+  "version"	=> \$opt_version,
+  "help|?"      => \$opt_help) or pod2usage(1);
+
+pod2usage("-exitstatus" => 0, "-verbose" => 2) if $opt_help;
+if ($opt_version) { print "$vc_id\n"; exit 0; } 
+
+exit (&main());
+
+

+sub main {
+  chomp(my $Master = `cd $mydir/../.. && pwd`);
+  # set up the programs ...
+  if ($opt_nosetup) {
+    # do a minimal setup
+    $::progs{'xz'} = "xz";
+    $::progs{'tar'} = "tar";
+  } else {
+    # do a full setup
+    my $ret = &TeXLive::TLUtils::setup_programs("$Master/tlpkg/installer");
+    if (!$ret) {
+      tlwarn("binaries could not be set up, aborting.\n");
+      exit 1;
+    }
+  }
+
+  # get our db, same hierarchy from which we are being run.
+  my $tlpdb = TeXLive::TLPDB->new("root" => $opt_location, 'verify' => 1);
+  die "Cannot init tlpdb from $opt_location ..." unless defined($tlpdb);
+  my $tempbase = "$opt_location/temp";
+  if (! -d $tempbase) {
+    mkdir($tempbase) or die "Cannot create $tempbase directory: $!";
+  }
+  my $temp = `mktemp -d -p \"$tempbase\"`;
+  chomp($temp);
+  die "Cannot create temporary directory in $tempbase: $!" if (! -d $temp);
+  my @notlpobj;
+  my @revisionerror;
+  my @missingsrccontainer;
+  my @missingdoccontainer;
+  my @sizeerror;
+  my %filedifferrors;
+  foreach my $pkg ($tlpdb->list_packages()) {
+    next if ($pkg =~ m/^00texlive/);
+    debug("working on $pkg\n");
+    my $cont = "$opt_location/archive/$pkg.tar.xz";
+    my $srccont = "$opt_location/archive/$pkg.source.tar.xz";
+    my $doccont = "$opt_location/archive/$pkg.doc.tar.xz";
+    my $tlpdbtlpobj = $tlpdb->get_package($pkg);
+    my $dodoc = ($tlpdb->config_doc_container && $tlpdbtlpobj->docfiles);
+    my $dosrc = ($tlpdb->config_src_container && $tlpdbtlpobj->srcfiles);
+    if ($opt_filelists) {
+      system("cat $cont | $::progs{xz} -dcf | $::progs{tar} -C \"$temp\" -xf - ");
+    } else {
+      system("cat $cont | $::progs{xz} -dcf | $::progs{tar} -C \"$temp\" -xf - tlpkg/tlpobj");
+    }
+    if (! -r "$temp/tlpkg/tlpobj/$pkg.tlpobj") {
+      debug("ERROR: no tlpobj: $temp/tlpkg/tlpobj/$pkg.tlpobj\n");
+      push @notlpobj, $pkg;
+    } else {
+      my $tartlpobj = TeXLive::TLPOBJ->new;
+      $tartlpobj->from_file("$temp/tlpkg/tlpobj/$pkg.tlpobj");
+      die "Cannot load tlpobj from $temp/$pkg.tlpobj: $!" unless defined($tartlpobj);
+      # get the src and doc containers unpacked and add the respective files
+      if ($dosrc) {
+        system("cat $srccont | $::progs{xz} -dcf | $::progs{tar} -C \"$temp\" -xf - tlpkg/tlpobj");
+        if (! -r "$temp/tlpkg/tlpobj/$pkg.source.tlpobj") {
+          push @missingsrccontainer, $pkg;
+          debug("ERROR: missing src container\n");
+        } else {
+          my $srctlpobj = TeXLive::TLPOBJ->new;
+          $srctlpobj->from_file("$temp/tlpkg/tlpobj/$pkg.source.tlpobj");
+          die "Cannot load tlpobj from $temp/$pkg.source.tlpobj: $!" unless defined($srctlpobj);
+          $tartlpobj->add_srcfiles($srctlpobj->srcfiles);
+        }
+      }
+      if ($dodoc) {
+        system("cat $doccont | $::progs{xz} -dcf | $::progs{tar} -C \"$temp\" -xf - tlpkg/tlpobj");
+        if (! -r "$temp/tlpkg/tlpobj/$pkg.doc.tlpobj") {
+          push @missingdoccontainer, $pkg;
+          debug("ERROR: missing doc container\n");
+        } else {
+          my $doctlpobj = TeXLive::TLPOBJ->new;
+          $doctlpobj->from_file("$temp/tlpkg/tlpobj/$pkg.doc.tlpobj");
+          die "Cannot load tlpobj from $temp/$pkg.doc.tlpobj: $!" unless defined($doctlpobj);
+          $tartlpobj->add_docfiles($doctlpobj->docfiles);
+        }
+      }
+      # check the revisions
+      if ($tlpdbtlpobj->revision != $tartlpobj->revision) {
+        push @revisionerror, "$pkg (tlpdb: " . $tlpdbtlpobj->revision . ", tar: " . $tartlpobj->revision . ")";
+      }
+      # check that the files are the same
+      my @a = $tlpdbtlpobj->all_files;
+      my @b = $tartlpobj->all_files;
+      my @ret = compare_lists(\@a, \@b);
+      push @{$filedifferrors{$pkg}}, @ret if @ret;
+      # check the file sizes and checksums
+      my $c = check_size_checksum($cont, $tlpdbtlpobj->containersize, 
+                                         $tlpdbtlpobj->containerchecksum);
+      push @sizeerror, "$pkg (" . ($c == 1 ? "size" : "checksum") . ")"
+        if ($c > 0);
+      debug("ERROR: size/checksum error main\n") if ($c > 0);
+      if ($dodoc) {
+        my $c = check_size_checksum($doccont, $tlpdbtlpobj->doccontainersize, 
+                                              $tlpdbtlpobj->doccontainerchecksum);
+        push @sizeerror, "$pkg.doc (" . ($c == 1 ? "size" : "checksum") . ")"
+          if ($c > 0);
+        debug("ERROR: size/checksum error doc\n") if ($c > 0);
+      }
+      if ($dosrc) {
+        my $c = check_size_checksum($srccont, $tlpdbtlpobj->srccontainersize, 
+                                              $tlpdbtlpobj->srccontainerchecksum);
+        push @sizeerror, "$pkg.source (" . ($c == 1 ? "size" : "checksum") . ")"
+          if ($c > 0);
+        debug("ERROR: size/checksum error src\n") if ($c > 0);
+      }
+      # check the actually included files are correct
+      # TODO TODO TODO
+      #
+      #
+      # should we do more checks?
+      # unlink("$temp/tlpkg/tlpobj/$pkg.tlpobj");
+      # unlink("$temp/tlpkg/tlpobj/$pkg.source.tlpobj");
+      # unlink("$temp/tlpkg/tlpobj/$pkg.doc.tlpobj");
+      system("rm -rf \"$temp/tlpkg\"");
+      system("rm -rf \"$temp/texmf\"");
+      system("rm -rf \"$temp/texmf-dist\"");
+      system("rm -rf \"$temp/texmf-doc\"");
+      system("ls \"$temp\"");
+    }
+  }
+  # system("rmdir --ignore-fail-on-non-empty $temp/tlpkg/tlpobj");
+  # system("rmdir --ignore-fail-on-non-empty $temp/tlpkg");
+  system("rmdir --ignore-fail-on-non-empty $temp $tempbase");
+  if (@notlpobj) {
+    print "packages without containing tlpobj file:\n";
+    for my $p (@notlpobj) {
+      print "$p\n";
+    }
+  }
+  if (@revisionerror) {
+    print "packages with revision discrepancy:\n";
+    for my $p (@revisionerror) {
+      print "$p\n";
+    }
+  }
+  if (@missingsrccontainer) {
+    print "packages with missing src containers:\n";
+    for my $p (@missingsrccontainer) {
+      print "$p\n";
+    }
+  }
+  if (@missingdoccontainer) {
+    print "packages with missing doc containers:\n";
+    for my $p (@missingdoccontainer) {
+      print "$p\n";
+    }
+  }
+  if (@sizeerror) {
+    print "packages with wrong container size/checksums:\n";
+    for my $p (@sizeerror) {
+      print "$p\n";
+    }
+  }
+  for my $pkg (keys %filedifferrors) {
+    print "file differences in $pkg:\n";
+    for my $l (@{$filedifferrors{$pkg}}) {
+      print "  $l\n";
+    }
+  }
+}
+
+
+sub compare_lists {
+  my ($la, $lb) = @_;
+  my @la = @$la;
+  my @lb = @$lb;
+  my %onlyfirst;
+  my %onlysecond;
+  my @ret;
+  for my $f (@la) { $onlyfirst{$f} = 1; }
+  for my $f (@lb) { delete($onlyfirst{$f}); $onlysecond{$f} = 1; }
+  for my $f (@la) { delete($onlysecond{$f}); }
+  for my $f (sort keys %onlyfirst) { push @ret, "-$f"; }
+  for my $f (sort keys %onlysecond) { push @ret, "+$f"; }
+  return(@ret);
+}
+
+sub check_size_checksum {
+  my ($cont, $size, $checksum) = @_;
+  my $sizeerror = 0;
+  my $checksumerror = 0;
+  if ($size > -1) {
+    my $s = (stat $cont)[7];
+    if ($s == $size) {
+      if ($checksum) {
+        if (TeXLive::TLCrypto::tlchecksum($cont) ne $checksum) {
+          $checksumerror = 1;
+        }
+      }
+    } else {
+      $sizeerror = 1;
+    }
+  } else {
+    if ($checksum) {
+      if (tlchecksum($cont) ne $checksum) {
+        $checksumerror = 1;
+      }
+    }
+  }
+  return 1 if $sizeerror;
+  return 2 if $checksumerror;
+  return 0;
+}
+
+__END__
+

+=head1 NAME
+
+check-tlnet-consistency - check the consistency of the tlnet distribution
+
+=head1 SYNOPSIS
+
+check-tlnet-consistency [I<option>]...
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-location> I</container/dir>
+
+The location to find the previously generated containers;
+default is C<./tlnet>.  
+
+=item B<-no-setup>
+
+Does not try to setup the various programs, but uses I<xz> and I<tar>
+from path.
+
+=item B<--help>
+
+Display this documentation and exit.
+
+=item B<--version>
+
+Display version information and exit.
+
+=back
+
+The standard options B<-q>, B<-v>, and B<-logfile>=I<file> are also
+accepted; see the C<process_logging_options> function in
+L<TeXLive::TLUtils> for details.
+
+=head1 DESCRIPTION
+
+This program compares the revisions as found in the C<texlive.tlpdb> of 
+the tlnet distributions with the revisions as specified in the included
+C<tlpobj> files in each package. In case there is a discrepancy this is
+reported to stdout.
+
+=head1 AUTHORS AND COPYRIGHT
+
+This script and its documentation were written for the TeX Live
+distribution (L<http://tug.org/texlive>) and both are licensed under the
+GNU General Public License Version 2 or later.
+
+=cut
+
+### Local Variables:
+### perl-indent-level: 2
+### tab-width: 2
+### indent-tabs-mode: nil
+### End:
+# vim:set tabstop=2 expandtab: #

Copied: trunk/Master/tlpkg/bin/tl-check-wrapper-consistency (from rev 52672, trunk/Master/tlpkg/bin/check-wrapper-consistency)
===================================================================
--- trunk/Master/tlpkg/bin/tl-check-wrapper-consistency	                        (rev 0)
+++ trunk/Master/tlpkg/bin/tl-check-wrapper-consistency	2019-11-07 18:38:33 UTC (rev 52673)
@@ -0,0 +1,152 @@
+#!/usr/bin/env perl
+# $Id$
+# Public domain.  Originally written 2008.
+# 
+# Check that the same set of files are wrappers on w32 and symlinks on
+# all others.
+
+BEGIN {
+  $^W = 1;
+  ($mydir = $0) =~ s,/[^/]*$,,;
+  unshift (@INC, "$mydir/..");
+  chomp ($Master = `cd $mydir/../.. && pwd`);
+}
+
+use Getopt::Long;
+use Pod::Usage;
+
+our ($mydir, $Master);
+
+my $help = 0;
+GetOptions("help|?"       => \$help) or pod2usage(1);
+pod2usage(-exitstatus => 0, -verbose => 2) if $help;
+
+exit (&main ());
+
+

+sub main {
+  my $err = 0;
+  
+  my $bindir = "$Master/bin";
+  chdir ($bindir) || die "chdir($bindir) failed: $!";
+  
+  my %w = &unx_wrapper_entries ("i386-linux");
+
+  # add some additional wrappers which are not found 
+  # automatically since they are not .. symlinks on Unix.
+  $w{'updmap'} = 1;
+  $w{'updmap-sys'} = 1;
+
+  chomp (my $srcdir = `cd $Master/../Build/source/texk/texlive && pwd`);
+  $cww = "$srcdir/w32_wrapper/runscript.exe";
+  $err += &check_w32 ("win32", $cww, %w);
+
+  return $err;
+}
+
+
+

+# return all symlinks starting with ".." in DIR as a hash, with symlink
+# targets as the values.  Check that targets are executable.
+# 
+sub unx_wrapper_entries {
+  my ($DIR) = @_;
+  my %ret;
+  
+  chomp (my $olddir = `pwd`);
+  chdir ($DIR) || die "chdir($DIR) failed: $!";
+
+  local *DIR;
+  opendir (DIR, ".") || die "opendir($DIR) failed: $!";
+  while (my $ent = readdir (DIR)) {
+    next unless -l $ent;  # skip all but symlinks
+    next if -d $ent;      # and skip directories (i.e., man/)
+
+    my $target = readlink ($ent);
+    die "readlink($ent) failed: $!" if !defined ($target);
+    next unless $target =~ /^\.\./;  # skip all but .. symlinks
+    
+    # the target of the symlink should be executable.
+    warn "$ent: target $target not executable\n" if ! -x $target;
+
+    $ret{$ent} = $target;  # remember name and link target
+  }
+  closedir (DIR) || warn "closedir($DIR) failed: $!";
+  chdir ($olddir) || die "chdir($olddir) failed: $!";
+
+  return %ret;
+}
+
+
+

+# Windows is painfully special, as usual.  Given the list of wrappers in
+# UW, check that each of those entries (excluding shell scripts) exists
+# in W32DIR as a .exe, and furthermore is a copy of the canonical w32
+# wrapper exe specified in W32CANONICAL.
+# 
+sub check_w32 {
+  my ($w32dir, $w32canonical, %uw) = @_;
+  my $diff = 0;
+  
+  my %is_shell_script = &list_shell_scripts ();
+  for my $k (sort keys %uw) {
+    next if $is_shell_script{$k};    # skip shell scripts
+    #
+    # also skip these special cases:
+    next if $k
+      =~ /^(epspdftk|latexindent|texdoctk|tlcockpit|tlmgr|tlshell|xasy)$/;
+    #
+    # else do the diff with the canonical wrapper:
+    $diff += system ("cmp $w32dir/$k.exe $w32canonical");
+  }
+
+  opendir (DIR, $w32dir) || die "opendir($DIR) failed: $!";
+  my @binfiles = readdir (DIR);
+  closedir (DIR) || warn "closedir($DIR) failed: $!";
+
+  foreach my $f (@binfiles) {
+    next unless ($f =~ s/\.(bat|cmd)$//); # only batch files
+    next if $uw{$f};                      # already checked
+    $diff += system ("cmp $w32dir/$f.exe $w32canonical");
+  }
+
+  # extra check for fmtutil-sys.exe, since fmtutil is an executable.
+  $diff += system ("cmp $w32dir/fmtutil-sys.exe $w32canonical");
+  
+  return $diff;
+}
+
+# As it happens, we already distinguish sh scripts from others in the
+# build process, for basically the same reason.  So return the list
+# maintained there by using a target defined in linked_scripts/Makefie
+# for us.
+# 
+sub list_shell_scripts {
+  my %sh;
+  
+  # has to be the Work/ directory to get the Makefile, not Makefile.{in,am}.
+  my $Work = "$Master/../Build/source/Work";
+  my $Work_linked_scripts = "$Work/texk/texlive/linked_scripts";
+  my $Work_tl_scripts = "$Work/texk/texlive/tl_scripts";
+  
+  -d "$Work_linked_scripts"||die "no linked_scripts dir: $Work_linked_scripts";
+  -d "$Work_tl_scripts" || die "no tl_scripts dir: $Work_tl_scripts";
+  
+  # use make; ensure we get only the last line, although that should be
+  # all there is.
+  my $lst = `make -s -C $Work_linked_scripts echo-shell-scripts | tail -1`;
+    $lst .= `make -s -C $Work_tl_scripts     echo-shell-scripts | tail -1`;
+  
+  for my $script (split (" ", $lst)) {
+    $script =~ s,^.*/,,;
+    $sh{$script} = 1;  # save with extension (for listings-ext.sh)
+    #
+    $script =~ s,\.[^.]*$,,;
+    $sh{$script} = 1;  # save without extension (everything else)
+  }
+
+  # more shell scripts, that are not part of linked_scripts.
+  $sh{"chkweb"} = 1;
+  
+  return %sh;
+}

Modified: trunk/Master/tlpkg/bin/tl-update-tlnet
===================================================================
--- trunk/Master/tlpkg/bin/tl-update-tlnet	2019-11-07 18:35:53 UTC (rev 52672)
+++ trunk/Master/tlpkg/bin/tl-update-tlnet	2019-11-07 18:38:33 UTC (rev 52673)
@@ -215,7 +215,7 @@
   for cmd in \
    "$tltryinst/$yyyy/bin/*/tlmgr --repository $tltry update --list" \
    "$tltryinst/$yyyy/bin/*/updmap-sys -n" \
-   "$Master/tlpkg/bin/check-tlnet-consistency --location=$tltry" \
+   "$Master/tlpkg/bin/tl-check-tlnet-consistency --location=$tltry" \
    "$Master/tlpkg/bin/tl-compare-tlpdbs $critical $tltry/tlpkg/texlive.tlpdb" \
   ; do
     cmdname=`echo "$cmd" | awk '{print $1}'`



More information about the tex-live-commits mailing list