TeXLive::TLUtils
- TeX Live infrastructure miscellany
use TeXLive::TLUtils;
TeXLive::TLUtils::platform();
TeXLive::TLUtils::platform_name($canonical_host);
TeXLive::TLUtils::platform_desc($platform);
TeXLive::TLUtils::wndws();
TeXLive::TLUtils::unix();
TeXLive::TLUtils::getenv($string);
TeXLive::TLUtils::which($string);
TeXLive::TLUtils::initialize_global_tmpdir();
TeXLive::TLUtils::tl_tmpdir();
TeXLive::TLUtils::tl_tmpfile();
TeXLive::TLUtils::xchdir($dir);
TeXLive::TLUtils::wsystem($msg,@args);
TeXLive::TLUtils::xsystem(@args);
TeXLive::TLUtils::run_cmd($cmd [, @envvars ]);
TeXLive::TLUtils::run_cmd_with_log($cmd, $logfn);
TeXLive::TLUtils::system_pipe($prog, $infile, $outfile, $removeIn, @args);
TeXLive::TLUtils::diskfree($path);
TeXLive::TLUtils::get_user_home();
TeXLive::TLUtils::expand_tilde($str);
TeXLive::TLUtils::dirname($path);
TeXLive::TLUtils::basename($path);
TeXLive::TLUtils::dirname_and_basename($path);
TeXLive::TLUtils::tl_abs_path($path);
TeXLive::TLUtils::dir_writable($path);
TeXLive::TLUtils::dir_creatable($path);
TeXLive::TLUtils::mkdirhier($path);
TeXLive::TLUtils::rmtree($root, $verbose, $safe);
TeXLive::TLUtils::copy($file, $target_dir);
TeXLive::TLUtils::touch(@files);
TeXLive::TLUtils::collapse_dirs(@files);
TeXLive::TLUtils::all_dirs_and_removed_dirs(@files);
TeXLive::TLUtils::dirs_of_files(@files);
TeXLive::TLUtils::removed_dirs(@files);
TeXLive::TLUtils::download_file($path, $destination);
TeXLive::TLUtils::setup_programs($bindir, $platform);
TeXLive::TLUtils::tlcmp($file, $file);
TeXLive::TLUtils::nulldev();
TeXLive::TLUtils::get_full_line($fh);
TeXLive::TLUtils::make_var_skeleton($path);
TeXLive::TLUtils::make_local_skeleton($path);
TeXLive::TLUtils::create_fmtutil($tlpdb,$dest);
TeXLive::TLUtils::create_updmap($tlpdb,$dest);
TeXLive::TLUtils::create_language_dat($tlpdb,$dest,$localconf);
TeXLive::TLUtils::create_language_def($tlpdb,$dest,$localconf);
TeXLive::TLUtils::create_language_lua($tlpdb,$dest,$localconf);
TeXLive::TLUtils::time_estimate($totalsize, $donesize, $starttime)
TeXLive::TLUtils::install_packages($from_tlpdb,$media,$to_tlpdb,$what,$opt_src, $opt_doc, $retry, $continue);
TeXLive::TLUtils::do_postaction($how, $tlpobj, $do_fileassocs, $do_menu, $do_desktop, $do_script);
TeXLive::TLUtils::update_context_cache($plat_bindir);
TeXLive::TLUtils::announce_execute_actions($how, @executes, $what);
TeXLive::TLUtils::add_symlinks($root, $arch, $sys_bin, $sys_man, $sys_info);
TeXLive::TLUtils::remove_symlinks($root, $arch, $sys_bin, $sys_man, $sys_info);
TeXLive::TLUtils::w32_add_to_path($bindir, $multiuser);
TeXLive::TLUtils::w32_remove_from_path($bindir, $multiuser);
TeXLive::TLUtils::setup_persistent_downloads();
TeXLive::TLUtils::info($str1, ...); # output unless -q
TeXLive::TLUtils::debug($str1, ...); # output if -v
TeXLive::TLUtils::ddebug($str1, ...); # output if -vv
TeXLive::TLUtils::dddebug($str1, ...); # output if -vvv
TeXLive::TLUtils::log($str1, ...); # only to log file
TeXLive::TLUtils::tlwarn($str1, ...); # warn on stderr and log
TeXLive::TLUtils::tldie($str1, ...); # tlwarn and die
TeXLive::TLUtils::debug_hash_str($label, HASH); # stringified HASH
TeXLive::TLUtils::debug_hash($label, HASH); # warn stringified HASH
TeXLive::TLUtils::backtrace(); # return call stack as string
TeXLive::TLUtils::process_logging_options($texdir); # handle -q -v* -logfile
TeXLive::TLUtils::sort_uniq(@list);
TeXLive::TLUtils::push_uniq(\@list, @items);
TeXLive::TLUtils::member($item, @list);
TeXLive::TLUtils::merge_into(\%to, \%from);
TeXLive::TLUtils::texdir_check($texdir);
TeXLive::TLUtils::compare_tlpobjs($tlpA, $tlpB);
TeXLive::TLUtils::compare_tlpdbs($tlpdbA, $tlpdbB);
TeXLive::TLUtils::report_tlpdb_differences(\%ret);
TeXLive::TLUtils::tlnet_disabled_packages($root);
TeXLive::TLUtils::mktexupd();
TeXLive::TLUtils::setup_sys_user_mode($prg,$optsref,$tmfc,$tmfsc,$tmfv,$tmfsv);
TeXLive::TLUtils::prepend_own_path();
TeXLive::TLUtils::repository_to_array($str);
TeXLive::TLUtils::quotify_path_with_spaces($path);
TeXLive::TLUtils::conv_to_w32_path($path);
TeXLive::TLUtils::native_slashify($internal_path);
TeXLive::TLUtils::forward_slashify($path_from_user);
TeXLive::TLUtils::give_ctan_mirror();
TeXLive::TLUtils::give_ctan_mirror_base();
TeXLive::TLUtils::encode_json($ref);
TeXLive::TLUtils::True();
TeXLive::TLUtils::False();
platform
If $^O =~ /MSWin/i
is true we know that we're on Windows and we set the global variable $::_platform_
to windows
. Otherwise we call platform_name
with the output of config.guess
as argument.
The result is stored in a global variable $::_platform_
, and subsequent calls just return that value.
As of 2021, config.guess
unfortunately requires a shell that understands the $(...)
construct. This means that on old-enough systems, such as Solaris, we have to look for a shell. We use the value of the CONFIG_SHELL
environment variable if it is set, else /bin/ksh
if it exists, else /bin/bash
if it exists, else give up. Happily, config.guess
later reverted this change, but we keep our shell-finding code anyway to defend against future mistakes of the same ilk.
platform_name($canonical_host)
Convert the $canonical_host
argument, a system description as returned by config.guess
, into a TeX Live platform name, that is, a name used as a subdirectory of our bin/
dir. Our names have the form CPU-OS, for example, x86_64-linux
.
We need this because what's returned from config.,guess
does not match our historical names, e.g., config.guess
returns linux-gnu
but we need linux
.
The CPU
part of our name is always taken from the argument, with various transformation.
For the OS
part, if the environment variable TEXLIVE_OS_NAME
is set, it is used as-is. Otherwise we do our best to figure it out.
This function still handles old systems which are no longer supported, just in case.
platform_desc($platform)
Return a string which describes a particular platform identifier, e.g., given i386-linux
we return Intel x86 with GNU/Linux
.
wndws
Return 1
if platform is Windows and 0
otherwise. The test is currently based on the value of Perl's $^O
variable.
unix
Return 1
if platform is UNIX and 0
otherwise.
getenv($string)
Get an environment variable. It is assumed that the environment variable contains a path. On Windows all backslashes are replaced by forward slashes as required by Perl. If this behavior is not desired, use $ENV{"$variable"}
instead. 0
is returned if the environment variable is not set.
which($string)
which
does the same as the UNIX command which(1)
, but it is supposed to work on Windows too. On Windows we have to try all the extensions given in the PATHEXT
environment variable. We also try without appending an extension because if $string
comes from an environment variable, an extension might already be present.
initialize_global_tmpdir();
Initializes a directory for all temporary files. This uses File::Temp
and thus honors various env variables like TMPDIR
, TMP
, and TEMP
.
tl_tmpdir
Create a temporary directory which is removed when the program is terminated.
tl_tmpfile
Create a temporary file which is removed when the program is terminated. Returns file handle and file name. Arguments are passed on to File::Temp::tempfile
.
xchdir($dir)
chdir($dir)
or die.
system_ok($cmdline)
Run system($cmdline)
and return true if return status was zero, false if status was nonzero. Throw away stdout and stderr.
wsystem($msg, @args)
Call info
about what is being done starting with $msg
, then run system(@args)
; tlwarn
if unsuccessful and return the exit status.
xsystem(@args)
Call ddebug
about what is being done, then run system(@args)
, and die if unsuccessful.
run_cmd($cmd, @envvars)
Run shell command $cmd
and captures its standard output (not standard error). Returns a list with CMD's output as the first element and its return value (exit code) as second.
If given, @envvars
is a list of environment variable name / value pairs set in %ENV
for the call and reset to their original value (or unset if not defined initially).
run_cmd_with_log($cmd, $logfn)
Run shell command $cmd
and captures both standard output and standard error (as one string), passing them to $logfn
. The return value is the exit status of $cmd
. Environment variable overrides cannot be passed. (This is used for running special post-installation commands in install-tl and tlmgr.)
The info
function is called to report what is happening.
system_pipe($prog, $infile, $outfile, $removeIn, @extraargs)
Runs $prog
with @extraargs
redirecting stdin from $infile
, stdout to $outfile
. Removes $infile
if $removeIn
is true.
diskfree($path)
If a POSIX compliant df
program is found, returns the number of Mb free at $path
, otherwise -1
. If $path
does not exist, check upwards for two levels for an existing parent, and if found, use it for computing the disk space.
get_user_home()
Returns the current user's home directory ($HOME
on Unix, $USERPROFILE
on Windows, and ~
if none of the two are set. Save in package variable $user_home_dir
after computing.
expand_tilde($str)
Expands initial ~
with the user's home directory in $str
if available, else leave ~
in place.
dirname_and_basename($path)
Return both dirname
and basename
. Example:
($dirpart,$filepart) = dirname_and_basename ($path);
dirname($path)
Return $path
with its trailing /component
removed.
basename($path)
Return $path
with any leading directory components removed.
tl_abs_path($path)
# Other than Cwd::abs_path, tl_abs_path also works if the argument does not # yet exist as long as the path does not contain '..' components.
dir_creatable($path)
Tests whether its argument is a directory where we can create a directory.
dir_writable($path)
Tests whether its argument is writable by trying to write to it. This function is necessary because the built-in -w
test just looks at mode and uid/gid, which on Windows always returns true and even on Unix is not always good enough for directories mounted from a fileserver.
mkdirhier($path, [$mode])
The function mkdirhier
does the same as the UNIX command mkdir -p
. It behaves differently depending on the context in which it is called: If called in void context it will die on failure. If called in scalar context, it will return 1/0 on sucess/failure. If called in list context, it returns 1/0 as first element and an error message as second, if an error occurred (and no second element in case of success). The optional parameter sets the permission bits.
rmtree($root, $verbose, $safe)
The rmtree
function provides a convenient way to delete a subtree from the directory structure, much like the Unix command rm -r
. rmtree
takes three arguments:
the root of the subtree to delete, or a reference to a list of roots. All of the files and directories below each root, as well as the roots themselves, will be deleted.
a boolean value, which if TRUE will cause rmtree
to print a message each time it examines a file, giving the name of the file, and indicating whether it's using rmdir
or unlink
to remove it, or that it's skipping it. (defaults to FALSE)
a boolean value, which if TRUE will cause rmtree
to skip any files to which you do not have delete access (if running under VMS) or write access (if running under another OS). This will change in the future when a criterion for 'delete permission' under OSs other than VMS is settled. (defaults to FALSE)
It returns the number of files successfully deleted. Symlinks are simply deleted and not followed.
NOTE: There are race conditions internal to the implementation of rmtree
making it unsafe to use on directory trees which may be altered or moved while rmtree
is running, and in particular on any directory trees with any path components or subdirectories potentially writable by untrusted users.
Additionally, if the third parameter is not TRUE and rmtree
is interrupted, it may leave files and directories with permissions altered to allow deletion (and older versions of this module would even set files and directories to world-read/writable!)
Note also that the occurrence of errors in rmtree
can be determined only by trapping diagnostic messages using $SIG{__WARN__}
; it is not apparent from the return value.
copy($file, $target_dir)
copy("-f", $file, $destfile)
copy("-L", $file, $destfile)
Copy file $file
to directory $target_dir
, or to the $destfile
if the first argument is "-f"
. No external programs are involved. Since we need sysopen()
, the Perl module Fcntl.pm
is required. The time stamps are preserved and symlinks are created on Unix systems. On Windows, (-l $file)
will never return 'true
' and so symlinks will be (uselessly) copied as regular files.
If the first argument is "-L"
and $file
is a symlink, the link is dereferenced before the copying is done. (If both "-f"
and "-L"
are desired, they must be given in that order, although the codebase currently has no need to do this.)
copy
invokes mkdirhier
if target directories do not exist. Files start with mode 0777
if they are executable and 0666
otherwise, with the set bits in umask cleared in each case.
$file
can begin with a file:/
prefix.
If $file
is not readable, we return without copying anything. (This can happen when the database and files are not in perfect sync.) On the other file, if the destination is not writable, or the writing fails, that is a fatal error.
touch(@files)
Update modification and access time of @files
. Non-existent files are created.
collapse_dirs(@files)
Return a (more or less) minimal list of directories and files, given an original list of files @files
. That is, if every file within a given directory is included in @files
, replace all of those files with the absolute directory name in the return list. Any files which have sibling files not included are retained and made absolute.
We try to walk up the tree so that the highest-level directory containing only directories or files that are in @files
is returned. (This logic may not be perfect, though.)
This is not just a string function; we check for other directory entries existing on disk within the directories of @files
. Therefore, if the entries are relative pathnames, the current directory must be set by the caller so that file tests work.
As mentioned above, the returned list is absolute paths to directories and files.
For example, suppose the input list is
dir1/subdir1/file1
dir1/subdir2/file2
dir1/file3
If there are no other entries under dir1/
, the result will be /absolute/path/to/dir1
.
dirs_of_files(@files)
Returns all the directories in which at least one of the given files reside.
all_dirs_and_removed_dirs(@files)
Returns all the directories for files and those from which all content will be removed.
removed_dirs(@files)
Returns all the directories from which all content will be removed.
Here is the idea:
time_estimate($totalsize, $donesize, $starttime)
Returns the current running time and the estimated total time based on the total size, the already done size, and the start time.
install_packages($from_tlpdb, $media, $to_tlpdb, $what, $opt_src, $opt_doc, $retry, $continue)
Installs the list of packages found in @$what
(a ref to a list) into the TLPDB given by $to_tlpdb
. Information on files are taken from the TLPDB $from_tlpdb
.
$opt_src
and $opt_doc
specify whether srcfiles and docfiles should be installed (currently implemented only for installation from uncompressed media).
If $retry
is trueish, retry failed packages a second time.
If $continue
is trueish, installation failure of non-critical packages will be ignored (success is returned).
Returns 1 on success and 0 on error.
Evaluates the postaction
fields in the $tlpobj
. The first parameter can be either install
or remove
. The second gives the TLPOBJ whos postactions should be evaluated, and the last four arguments specify what type of postactions should (or shouldn't) be evaluated.
Returns 1 on success, and 0 on failure.
parse_into_keywords
update_context_cache($bindir,$progext,$run_postinst_cmd)
Run the ConTeXt cache generation commands, using $bindir
and $progext
to check if commands can be run. Use the function reference $run_postinst_cmd
to actually run the commands. The return status is zero if all succeeded, nonzero otherwise. If the main ConTeXt program (luametatex
) cannot be run at all, the return status is zero.
Functions info
and debug
are called with status reports.
announce_execute_actions($how, [$tlpobj[, $what]])
Announces (records) that the actions, usually given in $tlpobj
(but can be omitted for global actions), should be executed after all packages have been unpacked. The optional $what
depends on the action, e.g., a parse_AddFormat_line reference for formats; not sure if it's used for anything else.
This is called for every package that gets installed.
add_symlinks($root, $arch, $sys_bin, $sys_man, $sys_info)
remove_symlinks($root, $arch, $sys_bin, $sys_man, $sys_info)
These two functions try to create/remove symlinks for binaries, man pages, and info files as specified by the options $sys_bin, $sys_man, $sys_info.
The functions return 1 on success and 0 on error. On Windows it returns undefined.
w32_add_to_path($bindir, $multiuser)
=item w32_remove_from_path($bindir, $multiuser)
These two functions try to add/remove the binary directory $bindir on Windows to the registry PATH variable.
If running as admin user and $multiuser is set, the system path will be adjusted, otherwise the user path.
After calling these functions TeXLive::TLWinGoo::broadcast_env() should be called to make the changes immediately visible.
check_file_and_remove($what, $checksum, $checksize
Remove the file $what
if either the given $checksum
or $checksize
for $what
does not agree with our recomputation using TLCrypto::tlchecksum
and stat
, respectively. If a check argument is not given, that check is not performed. If the checksums agree, the size is not checked. The return status is random.
This unusual behavior (removing the given file) is because this is used for newly-downloaded files; see the calls in the unpack
routine (which is the only caller).
unpack($what, $targetdir, @opts
If necessary, downloads C$what>, and then unpacks it into $targetdir
. @opts
is assigned to a hash and can contain the following keys: tmpdir
(use this directory for downloaded files), checksum
(check downloaded file against this checksum), size
(check downloaded file against this size), remove
(remove temporary files after operation).
Returns a pair of values: in case of error return 0 and an additional explanation, in case of success return 1 and the name of the package.
If checksum
or size
is -1
, no warnings about missing checksum/size is printed. This is used during restore and unwinding of failed updates.
untar($tarfile, $targetdir, $remove_tarfile)
Unpacks $tarfile
in $targetdir
(changing directories to $targetdir
and then back to the original directory). If $remove_tarfile
is true, unlink $tarfile
after unpacking.
Assumes the global $::progs{"tar"}
has been set up.
tlcmp($file, $file)
Compare two files considering CR, LF, and CRLF as equivalent. Returns 1 if different, 0 if the same.
read_file_ignore_cr($file)
Return contents of FILE as a string, converting all of CR, LF, and CRLF to just LF.
setup_programs($bindir, $platform, $tlfirst)
Populate the global $::progs
hash containing the paths to the programs lz4
, tar
, wget
, xz
. The $bindir
argument specifies the path to the location of the xz
binaries, the $platform
gives the TeX Live platform name, used as the extension on our executables. If a program is not present in the TeX Live tree, we also check along PATH (without the platform extension.)
If the $tlfirst
argument or the TEXLIVE_PREFER_OWN
envvar is set, prefer TL versions; else prefer system versions (except for Windows tar.exe
, where we always use ours).
Check many different downloads and compressors to determine what is working.
Return 0 if failure, nonzero if success.
download_file( $relpath, $destination )
Try to download the file given in $relpath
from $TeXLiveURL
into $destination
, which can be either a filename of simply |
. In the latter case a file handle is returned.
Downloading first checks for the environment variable TEXLIVE_DOWNLOADER
, which takes various built-in values. If not set, the next check is for TL_DOWNLOAD_PROGRAM
and TL_DOWNLOAD_ARGS
. The former overrides the above specification devolving to wget
, and the latter overrides the default wget arguments.
TL_DOWNLOAD_ARGS
must be defined so that the file the output goes to is the first argument after the TL_DOWNLOAD_ARGS
. Thus, for wget it would end in -O
. Use with care.
nulldev ()
Return /dev/null
on Unix and nul
on Windows.
get_full_line ($fh)
returns the next line from the file handle $fh, taking continuation lines into account (last character of a line is \, and no quoting is parsed).
make_var_skeleton($prefix)
Generate a skeleton of empty directories in the TEXMFSYSVAR
tree.
make_local_skeleton($prefix)
Generate a skeleton of empty directories in the TEXMFLOCAL
tree, unless TEXMFLOCAL
already exists.
create_fmtutil($tlpdb, $dest)
create_updmap($tlpdb, $dest)
create_language_dat($tlpdb, $dest, $localconf)
create_language_def($tlpdb, $dest, $localconf)
create_language_lua($tlpdb, $dest, $localconf)
These five functions create fmtutil.cnf
, updmap.cfg
, language.dat
, language.def
, and language.dat.lua
respectively, in $dest
(which by default is below $TEXMFSYSVAR
). These functions merge the information present in the TLPDB $tlpdb
(formats, maps, hyphenations) with local configuration additions: $localconf
.
Currently the merging is done by omitting disabled entries specified in the local file, and then appending the content of the local configuration files at the end of the file. We should also check for duplicates, maybe even error checking.
Logging and debugging messages.
logit($out,$level,@rest)
Internal routine to write message to both $out
(references to filehandle) and $::LOGFILE
, at level $level
, of concatenated items in @rest
. If the log file is not initialized yet, the message is saved to be logged later (unless the log file never comes into existence).
info ($str1, $str2, ...)
Write a normal informational message, the concatenation of the argument strings. The message will be written unless -q
was specified. If the global $::machinereadable
is set (the --machine-readable
option to tlmgr
), then output is written to stderr, else to stdout. If the log file (see process_logging_options) is defined, it also writes there.
It is best to use this sparingly, mainly to give feedback during lengthy operations and for final results.
debug ($str1, $str2, ...)
Write a debugging message, the concatenation of the argument strings. The message will be omitted unless -v
was specified. If the log file (see process_logging_options) is defined, it also writes there.
This first level debugging message reports on the overall flow of work, but does not include repeated messages about processing of each package.
ddebug ($str1, $str2, ...)
Write a deep debugging message, the concatenation of the argument strings. The message will be omitted unless -v -v
(or higher) was specified. If the log file (see process_logging_options) is defined, it also writes there.
This second level debugging message reports messages about processing each package, in addition to the first level.
dddebug ($str1, $str2, ...)
Write the deepest debugging message, the concatenation of the argument strings. The message will be omitted unless -v -v -v
was specified. If the log file (see process_logging_options) is defined, it also writes there.
In addition to the first and second levels, this third level debugging message reports messages about processing each line of any tlpdb files read, and messages about files tested or matched against tlpsrc patterns. This output is extremely voluminous, so unless you're debugging those parts of the code, it just gets in the way.
log ($str1, $str2, ...)
Write a message to the log file (and nowhere else), the concatenation of the argument strings. The log file may not ever be defined (e.g., the -logfile
option isn't given), in which case the message will never be written anywhere.
tlwarn ($str1, $str2, ...)
Write a warning message, the concatenation of the argument strings. This always and unconditionally writes the message to standard error; if the log file (see process_logging_options) is defined, it also writes there.
tldie ($str1, $str2, ...)
Uses tlwarn
to issue a warning for @_ preceded by a newline, then exits with exit code 1.
debug_hash_str($label, HASH)
Return LABEL followed by HASH elements, followed by a newline, as a single string. If HASH is a reference, it is followed (but no recursive derefencing).
debug_hash($label, HASH)
Write the result of debug_hash_str
to stderr.
backtrace()
Return call(er) stack, as a string.
process_logging_options ($texdir)
This function handles the common logging options for TeX Live scripts. It should be called before GetOptions
for any program-specific option handling. For our conventional calling sequence, see (for example) the tlpfiles script.
These are the options handled here:
Omit normal informational messages.
Include debugging messages. With one -v
, reports overall flow; with -v -v
(or -vv
), also reports per-package processing; with -v -v -v
(or -vvv
), also reports each line read from any tlpdb files. Further repeats of -v
, as in -v -v -v -v
, are accepted but ignored. -vvvv
is an error.
The idea behind these levels is to be able to specify -v
to get an overall idea of what is going on, but avoid terribly voluminous output when processing many packages, as we often are. When debugging a specific problem with a specific package, -vv
can help. When debugging problems with parsing tlpdb files, -vvv
gives that too.
Write all messages (informational, debugging, warnings) to file, in addition to standard output or standard error. In TeX Live, only the installer sets a log file by default; none of the other standard TeX Live scripts use this feature, but you can specify it explicitly.
See also the info, debug, ddebug, and tlwarn functions, which actually write the messages.
A few ideas from Fabrice Popineau's FileUtils.pm
.
sort_uniq(@list)
The sort_uniq
function sorts the given array and throws away multiple occurrences of elements. It returns a sorted and unified array.
push_uniq(\@list, @new_items)
The push_uniq
function pushes each element in the last argument @ITEMS to the $LIST referenced by the first argument, if it is not already in the list.
member($item, @list)
The member
function returns true if the first argument is also inclued in the list of the remaining arguments.
merge_into(\%to, \%from)
Merges the keys of %from into %to.
texdir_check($texdir)
Test whether installation with TEXDIR set to $texdir should be ok, e.g., would be a creatable directory. Return 1 if ok, 0 if not.
Writable or not, we will not allow installation to the root directory (Unix) or the root of a drive (Windows).
We also do not allow paths containing various special characters, and print a message about this if second argument WARN is true. (We only want to do this for the regular text installer, since spewing output in a GUI program wouldn't be good; the generic message will have to do for them.)
This function takes a single argument path and returns it with "
chars surrounding it on Unix. On Windows, the "
chars are only added if path contains special characters, since unconditional quoting leads to errors there. In all cases, any "
chars in path itself are (erroneously) eradicated.
This function returns a "Windows-ized" version of its single argument path, i.e., replaces all forward slashes with backslashes, and adds an additional "
at the beginning and end if path contains any spaces. It also makes the path absolute. So if $path does not start with one (arbitrary) characer followed by :
, we add the output of `cd`
.
The result is suitable for running in shell commands, but not file tests or other manipulations, since in such internal Perl contexts, the quotes would be considered part of the filename.
The next two functions are meant for user input/output in installer menus. They help making the windows user happy by turning slashes into backslashes before displaying a path, and our code happy by turning backslashes into forwars slashes after reading a path. They both are no-ops on Unix.
setup_persistent_downloads()
Set up to use persistent connections using LWP/TLDownload, that is look for a download server. Return the TLDownload object if successful, else false.
query_ctan_mirror()
Return a particular mirror given by the generic CTAN auto-redirecting default (specified in $TLConfig::TexLiveServerURL) if we get a response, else the empty string.
Use curl
if it is listed as a working_downloader
, else wget
, else give up. We can't support arbitrary downloaders here, as we do for regular package downloads, since certain options have to be set and the output has to be parsed.
We try invoking the program three times (hardwired).
check_on_working_mirror($mirror)
Check if MIRROR is functional.
give_ctan_mirror_base()
1. get a mirror (retries 3 times to contact mirror.ctan.org)
- if no mirror found, use one of the backbone servers
- if it is an http server return it (no test is done)
- if it is a ftp server, continue
2. if the ftp mirror is good, return it
3. if the ftp mirror is bad, search for http mirror (5 times)
4. if http mirror is found, return it (again, no test,)
5. if no http mirror is found, return one of the backbone servers
create_mirror_list()
extract_mirror_entry($listentry)
create_mirror_list
returns the lists of viable mirrors according to ctan-mirrors.pl, in a list which also contains continents, and country headers.
extract_mirror_entry
extracts the actual repository data from one of these entries.
# KEEP THESE TWO FUNCTIONS IN SYNC!!!
slurp_file($file)
Reads the whole file and returns the content in a scalar.
download_to_temp_or_file($url)
If $url
is a url, tries to download the file into a temporary file. Otherwise assume that $url
is a local file. In both cases returns the local file.
Returns the local file name if succeeded, otherwise undef.
compare_tlpobjs($tlpA, $tlpB)
Compare the two passed TLPOBJ objects. Returns a hash:
$ret{'revision'} = "revA:revB" # if revisions differ
$ret{'removed'} = \[ list of files removed from A to B ]
$ret{'added'} = \[ list of files added from A to B ]
$ret{'fmttriggers'} = 1 if the fmttriggers have changed
compare_tlpdbs($tlpdbA, $tlpdbB, @more_ignored_pkgs)
Compare the two passed TLPDB objects, ignoring the packages 00texlive.installer
, 00texlive.image
, and any passed @more_ignore_pkgs
. Returns a hash:
$ret{'removed_packages'} = \[ list of removed packages from A to B ]
$ret{'added_packages'} = \[ list of added packages from A to B ]
$ret{'different_packages'}->{$package} = output of compare_tlpobjs
report_tlpdb_differences($rret)
Report, using info function, as given in hash reference argument RET, with keys removed_packages, added_packages, different_packages.
mktexupd ()
Append entries to ls-R
files. Usage example:
my $updLSR=&mktexupd();
$updLSR->{mustexist}(1);
$updLSR->{add}(file1);
$updLSR->{add}(file2);
$updLSR->{add}(file3);
$updLSR->{exec}();
The first line creates a new object. Only one such object should be created in a program in order to avoid duplicate entries in ls-R
files.
add
pushes a filename or a list of filenames to a hash encapsulated in a closure. Filenames must be specified with the full (absolute) path. Duplicate entries are ignored.
exec
checks for each component of $TEXMFDBS
whether there are files in the hash which have to be appended to the corresponding ls-R
files and eventually updates the corresponding ls-R
files. Files which are in directories not stated in $TEXMFDBS
are silently ignored.
If the flag mustexist
is set, exec
aborts with an error message if a file supposed to be appended to an ls-R
file doesn't exist physically on the file system. This option was added for compatibility with the mktexupd
shell script. This option shouldn't be enabled in scripts, except for testing, because it degrades performance on non-cached file systems.
setup_sys_user_mode($prg, $optsref, $tmfc, $tmfsc, $tmfv, $tmfsv)
Return two-element list ($texmfconfig,$texmfvar)
specifying which directories to use, either user or sys. If $optsref-
{'sys'}> is true, we are in sys mode; else if $optsref-
{'user'}> is set, we are in user mode; else a fatal error.
If $prg
eq "mktexfmt"
, and $TEXMFSYSVAR/web2c
is writable, use it instead of $TEXMFVAR
, even if we are in user mode. $TEXMFCONFIG
is not switched, however.
prepend_own_path()
Prepend the location of the TeX Live binaries to the PATH environment variable. This is used by (e.g.) fmtutil
. The location is found by calling Cwd::abs_path
on which('kpsewhich')
. We use kpsewhich because it is known to be a true binary executable; $0
could be a symlink into (say) texmf-dist/scripts/
, which is not a useful directory for PATH.
repository_to_array($r)
Return hash of tags to urls for space-separated list of repositories passed in $r
. If passed undef or empty string, die.
encode_json($ref)
Returns the JSON representation of the object $ref
is pointing at. This tries to load the JSON
Perl module, and uses it if available, otherwise falls back to module internal conversion.
The used backend can be selected by setting the environment variable TL_JSONMODE
to either json
or texlive
(all other values are ignored). If json
is requested and the JSON
module cannot be loaded the program terminates.
True()
False()
These two crazy functions must be used to get proper JSON true
and false
in the output independent of the backend used.
The other modules in Master/tlpkg/TeXLive/
(TeXLive::TLConfig and the rest), and the scripts in Master/tlpg/bin/
(especially tl-update-tlpdb
), the documentation in Master/tlpkg/doc/
, etc.
This script and its documentation were written for the TeX Live distribution (https://tug.org/texlive) and both are licensed under the GNU General Public License Version 2 or later.