diff options
author | Norbert Preining <preining@logic.at> | 2021-05-09 02:23:44 +0000 |
---|---|---|
committer | Norbert Preining <preining@logic.at> | 2021-05-09 02:23:44 +0000 |
commit | d408beb505856c02bbae6121e29e4cb285077719 (patch) | |
tree | 43c532258b957b4428591fc42174725cc4e384b8 | |
parent | e7adfdd20cff7ca275e1383386000088243c1cf9 (diff) |
fmtutil and tlmgr improvements
fmtutil.pl
- if run as mktexfmt and TEXMFSYSVAR is writable, use
it instead of TEXMFVAR (actual code in TLUtils.pm).
- add --dry-run | -n option
it is not guaranteed to be 100% dry-run, though
- add --status-file=FILE where the status of each
format creating is written to
- warn on running fmtutil in user mode the first time
(similar to updmap)
- warn on shadowing formats
- documentation fixes
tlmgr.pl
- use fmtutil --status-file and report back failed
format rebuilds
- regeneration all formats now only exists existing
formats (use --refresh with fmtutil)
- report when commands are logged to the respective
log file
- documentation fixes
TLUtils.pm
- update setup_sys_user_mode for the fmtutil/mktexfmt
changes mentioned above
- documentation fixes
git-svn-id: svn://tug.org/texlive/trunk@59143 c570f23f-e606-0410-a88d-b1316a301751
-rwxr-xr-x | Master/texmf-dist/scripts/texlive/fmtutil.pl | 315 | ||||
-rwxr-xr-x | Master/texmf-dist/scripts/texlive/tlmgr.pl | 75 | ||||
-rw-r--r-- | Master/tlpkg/TeXLive/TLUtils.pm | 37 |
3 files changed, 307 insertions, 120 deletions
diff --git a/Master/texmf-dist/scripts/texlive/fmtutil.pl b/Master/texmf-dist/scripts/texlive/fmtutil.pl index 2823ee3b487..2248c2040a4 100755 --- a/Master/texmf-dist/scripts/texlive/fmtutil.pl +++ b/Master/texmf-dist/scripts/texlive/fmtutil.pl @@ -59,6 +59,12 @@ my $sep = (win32() ? ';' : ':'); my @deferred_stderr; my @deferred_stdout; +# $::opt_verbosity = 3; # manually enable debugging + +my $first_time_creation_in_usermode = 0; + +my $DRYRUN = ""; +my $STATUS_FH; (our $prg = basename($0)) =~ s/\.pl$//; @@ -89,11 +95,12 @@ if (win32()) { } # -# these need to be our since they are used from the -# functions in TLUtils.pm +# these need to be "our" variables since they are used from the +# functions in TLUtils.pm. our $texmfconfig = $TEXMFCONFIG; our $texmfvar = $TEXMFVAR; our $alldata; + # command line options with defaults # 20160623 - switch to turn on strict mode our %opts = ( quiet => 0 , strict => 1 ); @@ -116,6 +123,7 @@ our @cmdline_options = ( # in same order as help message "sys", "user", "cnffile=s@", + "dry-run|n", "fmtdir=s", "no-engine-subdir", "no-error-if-no-engine=s", @@ -123,6 +131,7 @@ our @cmdline_options = ( # in same order as help message "nohash", "recorder", "refresh", + "status-file=s", "strict!", "quiet|silent|q", "catcfg", @@ -156,13 +165,25 @@ sub main { # (and nothing else), since kpathsea can only deal with one. $mktexfmtMode = 1; - # TODO TODO - # which mode are we running in? - # what happens if root runs mktexfmt? + # we default to user mode here, in particular because **if** TEXMFSYSVAR + # is writable we will use it to save format dumps created by mktexfmt + # If root is running mktexfmt, then most probably the formats will end + # up in TEXMFSYSVAR which is fine. $opts{'user'} = 1; - GetOptions ( "help" => \$opts{'help'}, "version" => \$opts{'version'} ) - || die "$prg: Unknown option in mktexfmt command line arguments.\n"; + my @save_argv = @ARGV; + GetOptions ( + "dry-run|n", \$opts{'dry-run'}, + "help" => \$opts{'help'}, + "version" => \$opts{'version'} + ) || die "$prg: Unknown option in mktexfmt command line: @save_argv\n"; + + help() if $opts{'help'}; + if ($opts{'version'}) { + print version(); + exit 0; # no final print_info + } + if ($ARGV[0]) { if ($ARGV[0] =~ m/^(.*)\.(fmt|mem|base?)$/) { $opts{'byfmt'} = $1; @@ -214,11 +235,17 @@ sub main { } } } + + $DRYRUN = "echo " if ($opts{'dry-run'}); + + if ($opts{'status-file'}) { + open $STATUS_FH, '>>', $opts{'status-file'} + || printf STDERR "Cannot open status-file: $opts{'status-file'}\nWill not write status information!\n"; + } - # these two functions should go to TLUtils (for use in updmap) - ($texmfconfig, $texmfvar) = - TeXLive::TLUtils::setup_sys_user_mode($prg, \%opts, - $TEXMFCONFIG, $TEXMFSYSCONFIG, $TEXMFVAR, $TEXMFSYSVAR); + ($texmfconfig, $texmfvar) + = TeXLive::TLUtils::setup_sys_user_mode($prg, \%opts, + $TEXMFCONFIG, $TEXMFSYSCONFIG, $TEXMFVAR, $TEXMFSYSVAR); determine_config_files("fmtutil.cnf"); my $changes_config_file = $alldata->{'changes_config'}; @@ -252,7 +279,7 @@ sub main { touch($bakFile); touch($changes_config_file); } - system($editor, $changes_config_file); + system("$DRYRUN$editor", $changes_config_file); $changed = files_are_different($bakFile, $changes_config_file); } elsif ($opts{'showhyphen'}) { @@ -311,6 +338,10 @@ sub main { return 1; } + if ($STATUS_FH) { + close($STATUS_FH) || print STDERR "Cannot close fh for $opts{'status-file'}.\n"; + } + unless ($opts{'nohash'}) { # TODO should only do this if built something, e.g., not --listcfg print_info("updating ls-R files\n"); @@ -328,6 +359,12 @@ sub dump_data { print Data::Dumper::Dumper($alldata); } +# +sub log_to_status { + if ($STATUS_FH) { + print $STATUS_FH "@_\n"; + } +} # callback_build_formats - (re)builds the formats as selected, # returns exit status or dies. Exit status is always zero unless @@ -341,39 +378,43 @@ sub callback_build_formats { # On W32 it seems that File::Temp creates restrictive permissions (ok) # that are copied over with the files created inside it (not ok). # So make our own temp dir. - my $tmpdir; - if (win32()) { - my $foo; - my $tmp_deflt = File::Spec->tmpdir; - for my $i (1..5) { - # $foo = "$texmfvar/temp.$$." . int(rand(1000000)); - $foo = (($texmfvar =~ m!^//!) ? $tmp_deflt : $texmfvar) - . "/temp.$$." . int(rand(1000000)); - if (! -d $foo) { - TeXLive::TLUtils::mkdirhier($foo); - sleep 1; - if (-d $foo) { - $tmpdir = $foo; - last; + my $tmpdir = ""; + if (! $opts{"dry-run"}) { + if (win32()) { + my $foo; + my $tmp_deflt = File::Spec->tmpdir; + for my $i (1..5) { + # $foo = "$texmfvar/temp.$$." . int(rand(1000000)); + $foo = (($texmfvar =~ m!^//!) ? $tmp_deflt : $texmfvar) + . "/temp.$$." . int(rand(1000000)); + if (! -d $foo) { + TeXLive::TLUtils::mkdirhier($foo); + sleep 1; + if (-d $foo) { + $tmpdir = $foo; + last; + } } } + if (! $tmpdir) { + die "Cannot get a temporary directory after five iterations, sorry!"; + } + if ($texmfvar =~ m!^//!) { + # used File::Spec->tmpdir; fix permissions + TeXLive::TLWinGoo::maybe_make_ro ($tmpdir); + } + } else { + $tmpdir = File::Temp::tempdir(CLEANUP => 1); } - if (! $tmpdir) { - die "Cannot get a temporary directory after five iterations ... sorry!"; - } - if ($texmfvar =~ m!^//!) { - # used File::Spec->tmpdir; fix permissions - TeXLive::TLWinGoo::maybe_make_ro ($tmpdir); - } - } else { - $tmpdir = File::Temp::tempdir(CLEANUP => 1); } # set up destination directory $opts{'fmtdir'} ||= "$texmfvar/web2c"; - TeXLive::TLUtils::mkdirhier($opts{'fmtdir'}) if (! -d $opts{'fmtdir'}); - if (! -w $opts{'fmtdir'}) { - print_error("format directory not writable: $opts{fmtdir}\n"); - exit 1; + if (! $opts{"dry-run"}) { + TeXLive::TLUtils::mkdirhier($opts{'fmtdir'}) if (! -d $opts{'fmtdir'}); + if (! -w $opts{'fmtdir'}) { + print_error("format directory not writable: $opts{fmtdir}\n"); + exit 1; + } } # since the directory does not exist, we can make it absolute with abs_path # without any trickery around non-existing dirs @@ -397,7 +438,8 @@ sub callback_build_formats { $ENV{'TEXFORMATS'} = "$tmpdir$sep$ENV{TEXFORMATS}"; # switch to temporary directory for format generation - chdir($tmpdir) || die "Cannot change to directory $tmpdir: $!"; + $opts{"dry-run"} || chdir($tmpdir) + || die "Cannot change to directory $tmpdir: $!"; # we rebuild formats in two rounds: # round 1: only formats with the same name as engine (pdftex/pdftex) @@ -418,13 +460,28 @@ sub callback_build_formats { next if ($swi eq "format!=engine" && $fmt eq $eng); $total++; my $val = select_and_rebuild_format($fmt, $eng, $what, $whatarg); - if ($val == $FMT_DISABLED) { $disabled++; } - elsif ($val == $FMT_NOTSELECTED) { $nobuild++; } - elsif ($val == $FMT_FAILURE) { $err++; push (@err, "$eng/$fmt"); } - elsif ($val == $FMT_SUCCESS) { $suc++; } - elsif ($val == $FMT_NOTAVAIL) { $notavail++; } - else { print_error("callback_build_format (round 1): unknown return " - . "from select_and_rebuild.\n"); } + if ($val == $FMT_DISABLED) { + log_to_status("DISABLED", $fmt, $eng, $what, $whatarg); + $disabled++; + } elsif ($val == $FMT_NOTSELECTED) { + log_to_status("NOTSELECTED", $fmt, $eng, $what, $whatarg); + $nobuild++; + } elsif ($val == $FMT_FAILURE) { + log_to_status("FAILURE", $fmt, $eng, $what, $whatarg); + $err++; + push (@err, "$eng/$fmt"); + } elsif ($val == $FMT_SUCCESS) { + log_to_status("SUCCESS", $fmt, $eng, $what, $whatarg); + $suc++; + } elsif ($val == $FMT_NOTAVAIL) { + log_to_status("NOTAVAIL", $fmt, $eng, $what, $whatarg); + $notavail++; + } + else { + log_to_status("UNKNOWN", $fmt, $eng, $what, $whatarg); + print_error("callback_build_format (round 1): unknown return " + . "from select_and_rebuild.\n"); + } } } } @@ -455,7 +512,37 @@ sub callback_build_formats { # try to remove the tmpdir with all files TeXLive::TLUtils::rmtree($tmpdir); } - # return + # + # In case of user mode and formats rebuilt, warn that these formats + # will shadow future updates. Can be suppressed with --quiet which + # does not show print_info output + if ($opts{'user'} && $suc && $first_time_creation_in_usermode) { + print_info(" +************************************************************* +* * +* WARNING: you are switching to fmtutil's per-user formats. * +* Please read the following warnings! * +* * +************************************************************* + +You have run fmtutil-user (as opposed to fmtutil-sys) for the first time; +this has created format files which are local to your personal account. + +From now on, any changes in system formats will *not* be automatically +reflected in your files; furthermore, running fmtutil-sys will no longer +have any effect for you. + +As a consequence, you yourself have to rerun fmtutil-user after any +change in the system directories. For example, when one of the LaTeX or +other format source files changes, which happens frequently. +See https://tug.org/texlive/scripts-sys-user.html for details. + +If you want to undo this, remove the files mentioned above. + +Run $prg --help for full documentation of fmtutil. +"); + } + # return return $opts{"strict"} ? $err : 0; } @@ -519,12 +606,28 @@ sub select_and_rebuild_format { } } if ($doit) { + check_and_warn_on_user_format($fmt,$eng); return rebuild_one_format($fmt,$eng,$kpsefmt,$destdir,$fmtfile,$logfile); } else { return $FMT_NOTSELECTED; } } +sub check_and_warn_on_user_format { + my ($fmt, $eng) = @_; + # do nothing if we are updating files in $TEXMFVAR + return if ($opts{'fmtdir'} eq $TEXMFVAR); + my $saved_fmtdir = $opts{'fmtdir'}; + $opts{'fmtdir'} = "$TEXMFVAR/web2c"; + my ($kpsefmt, $destdir, $fmtfile, $logfile) = compute_format_destination($fmt, $eng); + if (-r "$destdir/$fmtfile") { + print_deferred_warning("you have a shadowing format dump in TEXMFVAR for $fmt/$eng!!!\n"); + } + $opts{'fmtdir'} = $saved_fmtdir; +} + + + # compute_format_destination # takes fmt/eng and returns the locations where format and log files # should be saved, that is, a list: (dump file full path, log file full path) @@ -679,7 +782,7 @@ sub rebuild_one_format { # in mktexfmtMode we must redirect *all* output to stderr $cmdline .= " >&2" if $mktexfmtMode; $cmdline .= " <$nul"; - my $retval = system($cmdline); + my $retval = system("$DRYRUN$cmdline"); # report error if it failed. if ($retval != 0) { @@ -689,7 +792,7 @@ sub rebuild_one_format { # Copy the log file after the program is run, so that the log file # is available to inspect even on failure. So we need the dest dir tree. - TeXLive::TLUtils::mkdirhier($destdir); + TeXLive::TLUtils::mkdirhier($destdir) if ! $opts{"dry-run"}; # # Here and in the following we use copy instead of move # to make sure that in SElinux enabled cases the rules of @@ -698,7 +801,8 @@ sub rebuild_one_format { if (File::Copy::copy($logfile, "$destdir/$logfile")) { print_info("log file copied to: $destdir/$logfile\n"); } else { - print_deferred_error("cannot copy log $logfile to: $destdir\n"); + print_deferred_error("cannot copy log $logfile to: $destdir\n") + unless $opts{"dry-run"}; } # original shell script did *not* check the return value @@ -748,8 +852,13 @@ sub rebuild_one_format { } my $destfile = "$destdir/$fmtfile"; + # set flag to warn that new user format was installed + # we check whether the next command **would** create a new file, + # and if it succeeded, we set the actual flag. + my $possibly_warn = ($opts{'user'} && ! -r $destfile); if (File::Copy::copy($fmtfile, $destfile )) { print_info("$destfile installed.\n"); + $first_time_creation_in_usermode = $possibly_warn; # # original fmtutil.sh did some magic trick for mplib-luatex.mem # @@ -1090,30 +1199,14 @@ sub determine_config_files { } } # - # user mode (no -sys): - # ==================== - # TEXMFCONFIG $HOME/.texliveYYYY/texmf-config/web2c/$fn - # TEXMFVAR $HOME/.texliveYYYY/texmf-var/web2c/$fn - # TEXMFHOME $HOME/texmf/web2c/$fn - # TEXMFSYSCONFIG $TEXLIVE/YYYY/texmf-config/web2c/$fn - # TEXMFSYSVAR $TEXLIVE/YYYY/texmf-var/web2c/$fn - # TEXMFLOCAL $TEXLIVE/texmf-local/web2c/$fn - # TEXMFDIST $TEXLIVE/YYYY/texmf-dist/web2c/$fn - # - # root mode (--sys): - # ================== - # TEXMFSYSCONFIG $TEXLIVE/YYYY/texmf-config/web2c/$fn - # TEXMFSYSVAR $TEXLIVE/YYYY/texmf-var/web2c/$fn - # TEXMFLOCAL $TEXLIVE/texmf-local/web2c/$fn - # TEXMFDIST $TEXLIVE/YYYY/texmf-dist/web2c/$fn - # - @{$opts{'cnffile'}} = @used_files; + # See help message for list of locations. + @{$opts{'cnffile'}} = @used_files; # # determine the config file that we will use for changes # if in the list of used files contains either one from - # TEXMFHOME or TEXMFCONFIG (which is TEXMFSYSCONFIG in the -sys case) + # TEXMFHOME or TEXMFCONFIG (TEXMFSYSCONFIG in the -sys case) # then use the *top* file (which will be either one of the two), - # if none of the two exists, create a file in TEXMFCONFIG and use it + # if neither of the two exists, create a file in TEXMFCONFIG and use it. my $use_top = 0; for my $f (@used_files) { if ($f =~ m!(\Q$TEXMFHOME\E|\Q$texmfconfig\E)/web2c/$fn!) { @@ -1316,20 +1409,21 @@ sub help { Usage: $prg [-user|-sys] [OPTION] ... [COMMAND] or: $prg-sys [OPTION] ... [COMMAND] or: $prg-user [OPTION] ... [COMMAND] - or: mktexfmt FORMAT.fmt|BASE.base|FMTNAME.EXT + or: mktexfmt FORMAT.fmt|BASE.base|FMTNAME Rebuild and manage TeX fmts and Metafont bases, collectively called "formats" here. (MetaPost no longer uses the past-equivalent "mems".) +If not operating in mktexfmt mode, exactly one command must be given, +filename suffixes should generally not be specified, no non-option +arguments are allowed, and multiple formats can be generated. + If the command name ends in mktexfmt, only one format can be created. The only options supported are --help and --version, and the command line must be either a format name, with extension, or a plain name that is passed as the argument to --byfmt (see below). The full name of the -generated file (if any) is written to stdout, and nothing else. - -If not operating in mktexfmt mode, exactly one command must be given, -extensions should generally not be specified, no non-option arguments -are allowed, and multiple formats can be generated, as follows. +generated file (if any) is written to stdout, and nothing else. The +system directories are used if they are writable, else the user directories. By default, the return status is zero if all formats requested are successfully built, else nonzero. @@ -1340,16 +1434,18 @@ Options: --cnffile FILE read FILE instead of fmtutil.cnf (can be given multiple times, in which case all the files are used) + --dry-run, -n don't actually build formts --fmtdir DIR write formats under DIR instead of TEXMF[SYS]VAR --no-engine-subdir don't use engine-specific subdir of the fmtdir - --no-error-if-no-format exit successfully if no format is selected + --no-error-if-no-format exit successfully if no format is selected --no-error-if-no-engine=ENGINE1,ENGINE2,... - exit successfully even if a required engine + exit successfully even if a required ENGINE is missing, if it is included in the list. --no-strict exit successfully even if a format fails to build --nohash don't update ls-R files --recorder pass the -recorder option and save .fls files --refresh recreate only existing format files + --status-file FILE append status information about built formats to FILE --quiet be silent --catcfg (does nothing, exists for compatibility) --dolinks (does nothing, exists for compatibility) @@ -1362,8 +1458,8 @@ Commands: --byengine ENGINE (re)create formats built with ENGINE --byfmt FORMAT (re)create format FORMAT --byhyphen HYPHENFILE (re)create formats that depend on HYPHENFILE - --enablefmt FORMAT[/ENGINE] enable FORMAT, as built with ENGINE - --disablefmt FORMAT[/ENGINE] disable FORMAT, as built with ENGINE + --enablefmt FORMAT[/ENGINE] enable FORMAT, as built with ENGINE + --disablefmt FORMAT[/ENGINE] disable FORMAT, as built with ENGINE If multiple formats have the same name and different engines, /ENGINE specifier is required. --listcfg list (enabled and disabled) configurations, @@ -1376,8 +1472,8 @@ Explanation of trees and files normally used: If --cnffile is specified on the command line (possibly multiple times), its value(s) are used. Otherwise, fmtutil reads all the - fmtutil.cnf files found by running \`kpsewhich -all fmtutil.cnf', in the - order returned by kpsewhich. Files passed in via --cnffile are + fmtutil.cnf files found by running "kpsewhich -all fmtutil.cnf", in the + order returned by kpsewhich. Files specified via --cnffile are first tried to be loaded directly, and if not found and the file names don't contain directory parts, are searched via kpsewhich. @@ -1405,32 +1501,35 @@ Explanation of trees and files normally used: (where YYYY is the TeX Live release version). - According to the actions, fmtutil might write to one of the given files - or create a new fmtutil.cnf, described further below. + According to the actions, fmtutil might update one of the existing cnf + files or create a new fmtutil.cnf, as described below. -Where formats are written: - - By default, format files are (re)written in TEXMFSYSVAR/ENGINE by - fmtutil-sys, and TEXMFVAR/ENGINE by fmtutil, where /ENGINE is a - subdirectory named for the engine used, such as "pdftex". +Where format files are written: + + By default, format files are (re)written in \$TEXMFSYSVAR/ENGINE by + fmtutil-sys, and \$TEXMFVAR/ENGINE by fmtutil-user, where /ENGINE is + a subdirectory named for the engine used, such as "pdftex". + + For mktexfmt, TEXMFSYSVAR is used if it is writable, else TEXMFVAR. If the --fmtdir=DIR option is specified, DIR is used instead of TEXMF[SYS]VAR, but the /ENGINE subdir is still used by default. - In any case, if the --no-engine-subdir option is specified, the + In all cases, if the --no-engine-subdir option is specified, the /ENGINE subdir is omitted. Where configuration changes are saved: If config files are given on the command line, then the first one given will be used to save any changes from --enable or --disable. + If the config files are taken from kpsewhich output, then the - algorithm is more complex: + algorithm is more complicated: - 1) If \$TEXMFCONFIG/web2c/fmtutil.cnf or \$TEXMFHOME/web2c/fmtutil.cnf - appears in the list of used files, then the one listed first by - kpsewhich --all (equivalently, the one returned by kpsewhich - fmtutil.cnf), is used. + 1) If \$TEXMFCONFIG/web2c/fmtutil.cnf or + \$TEXMFHOME/web2c/fmtutil.cnf appears in the list of used files, + then the one listed first by kpsewhich --all (equivalently, the one + returned by "kpsewhich fmtutil.cnf"), is used. 2) If neither of the above two are present and changes are made, a new config file is created in \$TEXMFCONFIG/web2c/fmtutil.cnf. @@ -1438,7 +1537,7 @@ Where configuration changes are saved: In general, the idea is that if a given config file is not writable, a higher-level one can be used. That way, the distribution's settings can be overridden system-wide using TEXMFLOCAL, and system settings - can be overridden again in a particular user's TEXMFHOME. + can be overridden again in a particular user's TEXMFHOME or TEXMFCONF. Resolving multiple definitions of a format: @@ -1449,32 +1548,32 @@ Disabling formats: fmtutil.cnf files with higher priority (listed earlier) can disable formats in lower priority (listed later) fmtutil.cnf files by - writing a line like + writing a line like this in the higher-priority fmtutil.cnf file: \#! <fmtname> <enginename> <hyphen> <args> - in the higher-priority fmtutil.cnf file. The \#! must be at the - beginning of the line, with at least one space or tab afterward, and - there must be whitespace between each word on the list. + The \#! must be at the beginning of the line, with at least one space + or tab afterward, and there must be whitespace between each word on + the list. For example, you can disable the luajitlatex format by creating the file \$TEXMFCONFIG/web2c/fmtutil.cnf with the line #! luajitlatex luajittex language.dat,language.dat.lua lualatex.ini (As it happens, the luajittex-related formats are precisely why the --no-error-if-no-engine option exists, since luajittex cannot be - compiled on all platforms.) + compiled on all platforms. So this is not needed.) fmtutil-user (fmtutil -user) vs. fmtutil-sys (fmtutil -sys): - When fmtutil-sys is run or the command line option -sys is used, - TEXMFSYSCONFIG and TEXMFSYSVAR are used instead of TEXMFCONFIG and - TEXMFVAR, respectively. This is the primary difference between + When fmtutil-sys is run or the command line option -sys is used, + TEXMFSYSCONFIG and TEXMFSYSVAR are used instead of TEXMFCONFIG and + TEXMFVAR, respectively. This is the primary difference between fmtutil-sys and fmtutil-user. - See http://tug.org/texlive/scripts-sys-user.html for details. + See https://tug.org/texlive/scripts-sys-user.html for details. Other locations may be used if you give them on the command line, or these trees don't exist, or you are not using the original TeX Live. -Supporting development binaries +Supporting development binaries: If an engine name ends with "-dev", formats are created in the respective directory with the -dev stripped. This allows for @@ -1482,7 +1581,7 @@ Supporting development binaries binaries. Report bugs to: tex-live\@tug.org -TeX Live home page: <http://tug.org/texlive/> +TeX Live home page: <https://tug.org/texlive/> EOF ; print &version(); diff --git a/Master/texmf-dist/scripts/texlive/tlmgr.pl b/Master/texmf-dist/scripts/texlive/tlmgr.pl index f57d5ec348e..a468d7e05a3 100755 --- a/Master/texmf-dist/scripts/texlive/tlmgr.pl +++ b/Master/texmf-dist/scripts/texlive/tlmgr.pl @@ -24,6 +24,7 @@ our $Master; our $loadmediasrcerror; our $packagelogfile; our $packagelogged; +our $commandslogged; our $commandlogfile; our $tlmgr_config_file; our $pinfile; @@ -632,6 +633,7 @@ for the full story.\n"; # package related actions (install, remove, update) to # the package-log file TEXMFSYSVAR/web2c/tlmgr.log $packagelogged = 0; # how many msgs we logged + $commandslogged = 0; chomp (my $texmfsysvar = `kpsewhich -var-value=TEXMFSYSVAR`); $packagelogfile = $opts{"package-logfile"}; if ($opts{"usermode"}) { @@ -699,9 +701,15 @@ for the full story.\n"; my $ret = execute_action($action, @ARGV); # close the special log file - if ($packagelogfile && !$::gui_mode) { - info("$prg: package log updated: $packagelogfile\n") if $packagelogged; - close(PACKAGELOG); + if (!$::gui_mode) { + if ($packagelogfile) { + info("$prg: package log updated: $packagelogfile\n") if $packagelogged; + close(PACKAGELOG); + } + if ($commandlogfile) { + info("$prg: command log updated: $commandlogfile\n") if $commandslogged; + close(COMMANDLOG); + } } # F_ERROR stops processing immediately, and prevents postactions from @@ -828,6 +836,7 @@ sub do_cmd_and_check { # and show it to the user before the possibly long delay. info("running $cmd ...\n"); logcommand("running $cmd"); + logpackage("command: $cmd"); my ($out, $ret); if ($opts{"dry-run"}) { $ret = $F_OK; @@ -867,12 +876,15 @@ sub handle_execute_actions { my $errors = 0; my $sysmode = ($opts{"usermode"} ? "-user" : "-sys"); - my $invoke_fmtutil = "fmtutil$sysmode $common_fmtutil_args"; + my $fmtutil_cmd = "fmtutil$sysmode"; + my $status_file = TeXLive::TLUtils::tl_tmpfile(); + my $fmtutil_args = "$common_fmtutil_args --status-file=$status_file"; + # if create_formats is false (NOT the default) we add --refresh so that # only existing formats are recreated if (!$localtlpdb->option("create_formats")) { - $invoke_fmtutil .= " --refresh"; + $fmtutil_args .= " --refresh"; debug("refreshing only existing formats per user option (create_formats=0)\n"); } @@ -973,7 +985,9 @@ sub handle_execute_actions { for my $e (keys %updated_engines) { debug ("updating formats based on $e\n"); $errors += do_cmd_and_check - ("$invoke_fmtutil --no-error-if-no-format --byengine $e"); + ("$fmtutil_cmd --byengine $e --no-error-if-no-format $fmtutil_args"); + read_and_report_fmtutil_status_file($status_file); + unlink($status_file); } # now rebuild all other formats for my $f (keys %do_enable) { @@ -981,7 +995,9 @@ sub handle_execute_actions { # ignore disabled formats next if !$::execute_actions{'enable'}{'formats'}{$f}{'mode'}; debug ("(re)creating format dump $f\n"); - $errors += do_cmd_and_check ("$invoke_fmtutil --byfmt $f"); + $errors += do_cmd_and_check ("$fmtutil_cmd --byfmt $f $fmtutil_args"); + read_and_report_fmtutil_status_file($status_file); + unlink($status_file); $done_formats{$f} = 1; } } @@ -1000,7 +1016,9 @@ sub handle_execute_actions { $lang = "$TEXMFSYSVAR/tex/generic/config/$lang"; } if (!$::regenerate_all_formats) { - $errors += do_cmd_and_check ("$invoke_fmtutil --byhyphen \"$lang\""); + $errors += do_cmd_and_check ("$fmtutil_cmd --byhyphen \"$lang\" $fmtutil_args"); + read_and_report_fmtutil_status_file($status_file); + unlink($status_file); } } } @@ -1010,7 +1028,9 @@ sub handle_execute_actions { if ($::regenerate_all_formats) { info("Regenerating existing formats, this may take some time ..."); # --refresh might already be in $invoke_fmtutil, but we don't care - $errors += do_cmd_and_check("$invoke_fmtutil --refresh --all"); + $errors += do_cmd_and_check("$fmtutil_cmd --refresh --all $fmtutil_args"); + read_and_report_fmtutil_status_file($status_file); + unlink($status_file); info("done\n"); $::regenerate_all_formats = 0; } @@ -1028,6 +1048,42 @@ sub handle_execute_actions { } } +sub read_and_report_fmtutil_status_file { + my $status_file = shift; + my $fh; + if (!open($fh, '<', $status_file)) { + printf STDERR "Cannot read status file $status_file, strange!\n"; + return; + } + chomp(my @lines = <$fh>); + close $fh; + my @failed; + my @success; + for my $l (@lines) { + my ($status, $fmt, $eng, $what, $whatargs) = split(' ', $l, 5); + if ($status eq "DISABLED") { + # ignore for now + } elsif ($status eq "NOTSELECTED") { + # ignore for now + } elsif ($status eq "FAILURE") { + push @failed, "${fmt}.fmt/$eng"; + } elsif ($status eq "SUCCESS") { + push @success, "${fmt}.fmt/$eng"; + } elsif ($status eq "NOTAVAIL") { + # ignore for now + } elsif ($status eq "UNKNOWN") { + # ignore for now + } else { + # ignore for now + } + } + logpackage(" OK: @success") if (@success); + logpackage(" ERROR: @failed") if (@failed); + logcommand(" OK: @success") if (@success); + logcommand(" ERROR: @failed") if (@failed); + info(" OK: @success\n") if (@success); + info(" ERROR: @failed\n") if (@failed); +} # GET_MIRROR # @@ -7543,6 +7599,7 @@ sub logpackage { } sub logcommand { if ($commandlogfile) { + $commandslogged++; my $tim = localtime(); print COMMANDLOG "[$tim] @_\n"; } diff --git a/Master/tlpkg/TeXLive/TLUtils.pm b/Master/tlpkg/TeXLive/TLUtils.pm index 0e68de0e011..128902db921 100644 --- a/Master/tlpkg/TeXLive/TLUtils.pm +++ b/Master/tlpkg/TeXLive/TLUtils.pm @@ -4585,7 +4585,11 @@ sub mktexupd { } -=item C<setup_sys_user_mode($user,$sys,$tmfc, $tmfsc, $tmfv, $tmfsv)> +=item C<setup_sys_user_mode($prg, $optsref, $tmfc, $tmfsc, $tmfv, $tmfsv)> + +Return two-element list C<($texmfconfig,$texmfvar)> of which directories +to use, either user or sys. If C<$prg> is C<mktexfmt>, and the system +dirs are writable, use them even if we are in user mode. =cut @@ -4613,7 +4617,8 @@ sub setup_sys_user_mode { exit(1); } if (!$optsref->{'sys'}) { - print STDERR "$prg [WARNING]: hidden sys mode found, switching to sys mode.\n" if (!$optsref->{'quiet'}); + print STDERR "$prg [WARNING]: hidden sys mode found, switching to sys mode.\n" + if (!$optsref->{'quiet'}); $optsref->{'sys'} = 1; } } @@ -4623,16 +4628,42 @@ sub setup_sys_user_mode { # we are running as updmap-sys, make sure that the right tree is used $texmfconfig = $TEXMFSYSCONFIG; $texmfvar = $TEXMFSYSVAR; + &debug("TLUtils::setup_sys_user_mode: sys mode\n"); + } elsif ($optsref->{'user'}) { $texmfconfig = $TEXMFCONFIG; $texmfvar = $TEXMFVAR; + &debug("TLUtils::setup_sys_user_mode: user mode\n"); + + # mktexfmt is run (accidentally or on purpose) by a user with + # missing formats; we want to put the resulting format dumps in + # TEXMFSYSVAR if possible, so that future format updates will just + # work. Until 2021, they were put in TEXMFVAR, causing problems. + # + # We only do this for mktexfmt, not fmtutil; if fmtutil is called + # explicitly with fmtutil -user, ok, do what they said to do. + # + if ($prg eq "mktexfmt") { + my $switchit = 0; + if (-d "$TEXMFSYSVAR/web2c") { + $switchit = 1 if (-w "$TEXMFSYSVAR/web2c"); + } elsif (-d $TEXMFSYSVAR && -w $TEXMFSYSVAR) { + $switchit = 1; + } + if ($switchit) { + $texmfvar = $TEXMFSYSVAR; + &ddebug(" switched to $texmfvar for mktexfmt\n"); + } + } } else { - print STDERR "" . + print STDERR "$prg [ERROR]: Either -sys or -user mode is required.\n" . "$prg [ERROR]: In nearly all cases you should use $prg -sys.\n" . "$prg [ERROR]: For special cases see https://tug.org/texlive/scripts-sys-user.html\n" ; exit(1); } + + &debug(" returning: ($texmfconfig,$texmfvar)\n"); return ($texmfconfig, $texmfvar); } |