#! /usr/bin/perl # Copyright © Simon Pepping, 29 June 2002 # License: GNU General Public License Version 2, June 1991. # History # 11/10/2002: better handling of the various unzip exit codes # 04/12/2002: change $textree into an absolute path if given as a relative path # 05/12/2002: added mktexlsr $textree command # protect against empty pattern in dirfiles # 07/12/2002: added another mktexlsr $textree command after format making # 08/03/2003: added tex/context/cont-*.ini files and context/user/cont-sys.rme # to the list of existing context files; # put the lists of existing context files # in separate variables at the top # 13/08/2003: changed context/user/cont-sys.rme to # tex/context/user/cont-sys.rme =head1 NAME install_context.pl - Install a new ConTeXt distribution =head1 SYNOPSIS install_context.pl --textree TeX-tree [ --texexecini texexec.ini ] [ --language lang ] context-zip-file =head1 DESCRIPTION The installation script install_context.pl installs a new ConTeXt distribution in the requested TeX tree. The script works for a kpathsea TeX installation, and uses its properties to determine the best course of action. The script requires that the the unzip command is in the path for executables. It is recommended to use a texexec script that passes the formats directory to the fmtutil script of the TeX installation. The script is written under the assumption that separate ConTeXt installs are done outside the main system tree of the TeX installation. It tries to place the new formats in the installation TeX tree, not in the default formats directory. If no languages are requested on the command line, the languages of the existing ConTeXt distribution are installed. If this is an installation in an existing tree, the languages in that tree are installed again. If this is a new tree, the languages present in texmf-var ('$VARTEXMF') are installed. If ConTeXt is not installed in either tree, language en is installed. If the installation TeX tree exists, the existing ConTeXt distribution in it is removed. If the tree does not exist, it is created. The context zip file is unpacked into it, using the command 'unzip -a -d'. If the installation TeX tree exists and contains a texexec.ini file, it is kept without changes. Otherwise, if an existing texexec.ini file was listed on the command line, the listed file is copied. Else the newly installed texexec.rme is copied. In both cases a line is appended to the new texexec.ini file that puts the new formats in the installation tree. If this is a new TeX tree (i.e., if it is not listed in '$TEXMF'), a new texmf.cnf file is created in the web2c subdirectory. This new configuration file inserts the new tree before those known to the TeX installation (i.e., those listed in '$TEXMF') for the rest of the installation. It contains a comment that explains how the same can be done again later, viz. by setting the variable '$TEXMFCNF'. Finally the formats for all required languages are created in the new tree. This feature only works with a texexec script that passes the formats directory to the fmtutil script of the TeX installation. Otherwise the formats are placed in the default formats directory of the TeX installation, overwriting the existing formats. =cut use File::Copy; use Getopt::Long; use strict vars; my ($textree, $texexecini, @languages); # options my %options = ('textree=s' => \$textree, 'texexecini=s' => \$texexecini, 'language=s' => \@languages); my @context_files = (qw(context/config/texexec.rme tex/context/user/cont-sys.rme dvips/config/context.map)); my @context_dirs = (qw(context/perltk context/data doc/context metapost/context fonts/tfm/hoekwater/context fonts/type1/hoekwater/context pdftex/config/context tex/context/base tex/context/extra tex/context/sample tex/generic/context tex/latex/context)); my @context_inifiles = ([qw(tex/context/config cont-.+\.ini)]); my @context_web2cfiles = ([qw(web2c cont-.+\.(efmt|log))]); GetOptions(%options); die("No TeX tree for the installation given\n") unless $textree; unless ($textree =~ m|^/|) { my $pwd = `pwd`; chomp $pwd; $textree = "$pwd/$textree"; } # new context zip file my $new_context_zip = shift; die("No new context zip file given\n") unless $new_context_zip; die("Cannot find new context zip file $new_context_zip\n") unless -f $new_context_zip; # recursively read directory sub dirfiles { my ($dir, $pat) = @_; $pat = '.*' unless $pat; opendir(DIR, $dir) or die("Could not open directory $dir: $!\n"); my @dir = readdir(DIR); closedir DIR; my @files = map {"$dir/$_"} grep {/$pat/} grep {-f "$dir/$_"} @dir; my @dirs = map {"$dir/$_"} grep {/$pat/ && !/^\.+$/} grep {-d "$dir/$_"} @dir; push(@files, map {dirfiles($_, $pat)} @dirs); @files; } # default $TEXMFCNF value = $TEXMFMAIN/web2c sub default_texmfcnf { my $texmfcnf_syst = `kpsewhich --expand-var \\\$TEXMFMAIN`; chomp $texmfcnf_syst; "$texmfcnf_syst/web2c"; } # set TEXMF variable sub set_texmf_var { my ($tex_installation, $texmf_var) = @_; my $texmf_value = `kpsewhich --expand-var \\\$$texmf_var`; chomp $texmf_value; $tex_installation->{$texmf_var} = $texmf_value; } # set the value of $TEXMFCNF that is needed # to get $textree as the first tree sub set_texmfcnf { my ($tex_installation) = @_; my ($textree, $texmf) = ($tex_installation->{'textree'}, $tex_installation->{'TEXMF'}); $texmf =~ s|[{}]||g; my @texmf = map {s/^!+//; $_} split(/,\s*/, $texmf); if (grep {$_ eq $textree} @texmf) { $tex_installation->{'TEXMFCNF'} = ''; } else { my $texmfcnf_permanent = $ENV{TEXMFCNF} || &default_texmfcnf; $tex_installation->{'TEXMFCNF'} = "$textree/web2c:$texmfcnf_permanent"; } $tex_installation->{'TEXMFCNF'}; } # which context languages are present in $textree? sub existing_languages { my ($textree) = @_; return unless -d "$textree/web2c"; map {s|^.+/cont-(.+)\.efmt$|$1|; $_} dirfiles("$textree/web2c", 'cont-.+\.efmt'); } # construct the list of context languages: # 1. Use the languages present in $textree. # 2. Use the languages present in $VARTEXMF. # 3. Use en. sub set_languages { my ($tex_installation) = @_; my @languages; (@languages = &existing_languages($tex_installation->{'textree'})) || (@languages = &existing_languages($tex_installation->{'VARTEXMF'})) || (@languages = ('en')); $tex_installation->{'languages'} = \@languages; @languages; } # existing context files sub existing_files { my ($tex_installation) = @_; my $textree = $tex_installation->{'textree'}; my @files; push(@files, map {"$textree/$_"} @context_files); push(@files, map {dirfiles("$textree/$_")} @context_dirs); push(@files, map {dirfiles("$textree/$_->[0]", $_->[1])} @context_inifiles, @context_web2cfiles); @files; } # create a texexec.ini; # if an existing texexec.ini file (outside of $textree) # was listed as an option, # and $textree does not yet have a texexec.ini file, # copy the listed file; # append a line that puts the new formats in $textree sub make_texexecini { my ($tex_installation) = @_; my ($textree, $texexecini) = ($tex_installation->{'textree'}, $tex_installation->{'texexecini'}); mkdir "$textree/context", 0777 unless -d "$textree/context"; mkdir "$textree/context/config", 0777 unless -d "$textree/context/config"; my $new_texexecini = "$textree/context/config/texexec.ini"; $texexecini = "$textree/context/config/texexec.rme" unless $texexecini; copy($texexecini, $new_texexecini) unless -f $new_texexecini; open(TEXEXECINI, ">>$new_texexecini") or die("Could not open $new_texexecini: $!\n"); print TEXEXECINI <{'textree'}, $tex_installation->{'TEXMF'}, $tex_installation->{'TEXMFCNF'}); $texmf =~ s|^{(.+)}$|{$textree,$1}|; my $texmfcnf_dir = "$textree/web2c"; my $texmfcnf_file = "$texmfcnf_dir/texmf.cnf"; my $texmfcnf_text = <$texmfcnf_file") or die("Could not open $texmfcnf_file: $!\n"); print TEXMFCNF $texmfcnf_text; close TEXMFCNF; } # make a new tex tree and populate it with texexec.ini and texmf.cnf sub make_tex_tree { my ($tex_installation) = @_; my $textree = $tex_installation->{'textree'}; mkdir $textree, 0777 unless -d $textree; &make_texexecini($tex_installation); &make_texmfcnf($tex_installation); } print "Installing $new_context_zip to $textree\n"; # gather information about the TeX installation my $tex_installation = { 'textree' => $textree, 'texexecini' => $texexecini, }; &set_texmf_var($tex_installation, 'TEXMF'); &set_texmfcnf($tex_installation); unless (@languages) { &set_texmf_var($tex_installation, 'VARTEXMF'); @languages = &set_languages($tex_installation); } my $is_new_tree; # remove existing files or create new TeXMF directory if (-d $textree) { print "Removing existing files in $textree\n"; unlink &existing_files($tex_installation); } else { print "Making new TeX tree $textree\n"; mkdir $textree, 0777; $is_new_tree = 1; } my $exit_value; # unzip the context file print "Unzipping $new_context_zip\n"; my $command = "unzip -a -d $textree $new_context_zip"; system($command); $exit_value = $? >> 8; if ($exit_value == 1) { print<{'TEXMFCNF'} if $tex_installation->{'TEXMFCNF'}; # make sure that the newly added files are seen by tex $command = "mktexlsr $textree"; system($command); $exit_value = $? >> 8; if ($exit_value) { die("Failure executing $command\n"); } print "Making formats for languages @languages\n"; $command = "texexec --make @languages"; system($command); $exit_value = $? >> 8; if ($exit_value) { die("Failure executing $command\n"); } # make sure that the new formats are properly listed to the ls-R database # merely appending them to the ls-R file does not work, # because kpsewhich expects only one entry per directory $command = "mktexlsr $textree"; system($command); $exit_value = $? >> 8; if ($exit_value) { die("Failure executing $command\n"); } print "Finished installing $new_context_zip to $textree\n";