1#!/usr/bin/env perl 2# $Id: tlmgr.pl 37289 2015-05-09 02:43:37Z preining $ 3# 4# Copyright 2008-2015 Norbert Preining 5# This file is licensed under the GNU General Public License version 2 6# or any later version. 7# 8 9my $svnrev = '$Revision: 37289 $'; 10my $datrev = '$Date: 2015-05-09 04:43:37 +0200 (Sat, 09 May 2015) $'; 11my $tlmgrrevision; 12my $prg; 13if ($svnrev =~ m/: ([0-9]+) /) { 14 $tlmgrrevision = $1; 15} else { 16 $tlmgrrevision = "unknown"; 17} 18$datrev =~ s/^.*Date: //; 19$datrev =~ s/ \(.*$//; 20$tlmgrrevision .= " ($datrev)"; 21 22our $Master; 23our $ismain; 24our $loadmediasrcerror; 25our $packagelogfile; 26our $packagelogged; 27our $tlmgr_config_file; 28our $pinfile; 29our $action; # for the pod2usage -sections call 30our %opts; 31 32END { 33 if ($opts{"pause"}) { 34 print "Press Enter to exit the program.\n"; 35 <STDIN>; 36 } 37} 38 39BEGIN { 40 $^W = 1; 41 $ismain = (__FILE__ eq $0); 42 # WARNING 43 # The only use anticipated for tlmgr.pl as library for the 2009 release 44 # is the Windows w32client prototype script. 45 # Unix-specific problems with use as library will probably go undetected. 46 47 # make subprograms (including kpsewhich) have the right path: 48 my ($bindir, $kpsewhichname); 49 if ($^O =~ /^MSWin/i) { 50 # on w32 $0 and __FILE__ point directly to tlmgr.pl; they can be relative 51 $Master = __FILE__; 52 $Master =~ s!\\!/!g; 53 $Master =~ s![^/]*$!../../..! 54 unless ($Master =~ s!/texmf-dist/scripts/texlive/tlmgr\.pl$!!i); 55 $bindir = "$Master/bin/win32"; 56 $kpsewhichname = "kpsewhich.exe"; 57 # path already set by wrapper batchfile 58 } else { 59 $Master = __FILE__; 60 $Master =~ s,/*[^/]*$,,; 61 if ($ismain) { 62 $bindir = $Master; 63 $Master = "$Master/../.."; 64 } else { 65 # for the time being, this code will not be used or tested 66 $Master = "$Master/../../.."; 67 # no code yet for $bindir; would have to detect platform 68 } 69 # make subprograms (including kpsewhich) have the right path: 70 $ENV{"PATH"} = "$bindir:$ENV{PATH}"; 71 $kpsewhichname = "kpsewhich"; 72 } 73 if (-r "$bindir/$kpsewhichname") { 74 # if not in bootstrapping mode => kpsewhich exists, so use it to get $Master 75 chomp($Master = `kpsewhich -var-value=TEXMFROOT`); 76 } 77 $::installerdir = $Master; 78 79 # 80 # make Perl find our packages first: 81 unshift (@INC, "$Master/tlpkg"); 82 unshift (@INC, "$Master/texmf-dist/scripts/texlive"); 83} 84 85use Cwd qw/abs_path/; 86use File::Spec; 87use Digest::MD5; 88use Pod::Usage; 89use Getopt::Long qw(:config no_autoabbrev permute); 90use strict; 91 92use TeXLive::TLConfig; 93use TeXLive::TLPDB; 94use TeXLive::TLPOBJ; 95use TeXLive::TLUtils; 96use TeXLive::TLWinGoo; 97use TeXLive::TLDownload; 98use TeXLive::TLConfFile; 99TeXLive::TLUtils->import(qw(member info give_ctan_mirror win32 dirname 100 mkdirhier copy log debug tlcmp)); 101use TeXLive::TLPaper; 102 103# 104# set up $prg for warning messages 105$prg = TeXLive::TLUtils::basename($0); 106 107binmode(STDOUT, ":utf8"); 108binmode(STDERR, ":utf8"); 109 110our %config; # hash of config settings from config file 111our $remotetlpdb; 112our $location; # location from which the new packages come 113our $localtlpdb; # local installation which we are munging 114 115# flags for machine-readable form 116our $FLAG_REMOVE = "d"; 117our $FLAG_FORCIBLE_REMOVED = "f"; 118our $FLAG_UPDATE = "u"; 119our $FLAG_REVERSED_UPDATE = "r"; 120our $FLAG_AUTOINSTALL = "a"; 121our $FLAG_INSTALL = "i"; 122our $FLAG_REINSTALL = "I"; 123 124# keep in sync with install-tl. 125our $common_fmtutil_args = 126 "--no-error-if-no-engine=$TeXLive::TLConfig::PartialEngineSupport"; 127 128# return flags for error handling 129# 130# all fine 131our $F_OK = 0; 132# 133# some warnings, but we still try to run post actions 134our $F_WARNING = 1; 135# 136# error, terminating 137our $F_ERROR = 2; 138# 139# all fine, but no need to run post actions 140our $F_NOPOSTACTION = 4; 141 142# option variables 143$::gui_mode = 0; 144$::machinereadable = 0; 145 146my %globaloptions = ( 147 "gui" => 1, 148 "gui-lang" => "=s", 149 "debug-translation" => 1, 150 "location|repository|repo" => "=s", 151 "machine-readable" => 1, 152 "package-logfile" => "=s", 153 "persistent-downloads" => "!", 154 "no-execute-actions" => 1, 155 "pin-file" => "=s", 156 "pause" => 1, 157 "print-platform|print-arch" => 1, 158 "version" => 1, 159 "help" => 1, 160 "h|?" => 1); 161 162my %action_specification = ( 163 '_include_tlpobj' => { 164 "run-post" => 0, 165 "function" => \&action_include_tlpobj 166 }, 167 "backup" => { 168 "options" => { 169 "backupdir" => "=s", 170 "clean" => ":-99", 171 "all" => 1, 172 "dry-run|n" => 1 173 }, 174 "run-post" => 1, 175 "function" => \&action_backup 176 }, 177 "candidates" => { 178 "run-post" => 0, 179 "function" => \&action_candidates 180 }, 181 "check" => { 182 "options" => { "use-svn" => 1 }, 183 "run-post" => 1, 184 "function" => \&action_check 185 }, 186 "conf" => { 187 "options" => { 188 "conffile" => "=s", 189 "delete" => 1, 190 }, 191 "run-post" => 0, 192 "function" => \&action_conf 193 }, 194 "dump-tlpdb" => { 195 "options" => { "local" => 1, remote => 1 }, 196 "run-post" => 0, 197 "function" => \&action_dumptlpdb 198 }, 199 "generate" => { 200 "options" => { 201 "localcfg" => "=s", 202 "dest" => "=s", 203 "rebuild-sys" => 1 204 }, 205 "run-post" => 1, 206 "function" => \&action_generate 207 }, 208 "get-mirror" => { 209 "run-post" => 0, 210 "function" => \&action_get_mirror 211 }, 212 "gui" => { 213 "options" => { "load" => 1 }, 214 "run-post" => 1, 215 "function" => \&action_gui 216 }, 217 "info" => { 218 "options" => { "list" => 1, "only-installed" => 1 }, 219 "run-post" => 0, 220 "function" => \&action_info 221 }, 222 "init-usertree" => { 223 "run-post" => 0, 224 "function" => \&action_init_usertree 225 }, 226 "install" => { 227 "options" => { 228 "no-depends" => 1, 229 "no-depends-at-all" => 1, 230 "file" => 1, 231 "reinstall" => 1, 232 "force" => 1, 233 "dry-run|n" => 1, 234 "with-doc" => 1, 235 "with-src" => 1, 236 }, 237 "run-post" => 1, 238 "function" => \&action_install 239 }, 240 "option" => { 241 "run-post" => 1, 242 "function" => \&action_option 243 }, 244 "paper" => { 245 "options" => { "list" => 1 }, 246 "run-post" => 1, 247 "function" => \&action_paper 248 }, 249 "path" => { 250 "options" => { "w32mode" => "=s" }, 251 "run-post" => 0, 252 "function" => \&action_path 253 }, 254 "pinning" => { 255 "options" => { "all" => 1 }, 256 "run-post" => 1, 257 "function" => \&action_pinning 258 }, 259 "platform" => { 260 "options" => { "dry-run|n" => 1 }, 261 "run-post" => 1, 262 "function" => \&action_platform 263 }, 264 "postaction" => { 265 "options" => { 266 "w32mode" => "=s", 267 "all" => 1, 268 "fileassocmode" => "=i" 269 }, 270 "run-post" => 0, 271 "function" => \&action_postaction 272 }, 273 "recreate-tlpdb" => { 274 "options" => { "platform|arch" => "=s" }, 275 "run-post" => 0, 276 "function" => \&action_recreate_tlpdb 277 }, 278 "remove" => { 279 "options" => { 280 "no-depends" => 1, 281 "no-depends-at-all" => 1, 282 "force" => 1, 283 "dry-run|n" => 1 284 }, 285 "run-post" => 1, 286 "function" => \&action_remove 287 }, 288 repository => { 289 "options" => { "with-platforms" => 1 }, 290 "run-post" => 1, 291 "function" => \&action_repository 292 }, 293 "restore" => { 294 "options" => { 295 "backupdir" => "=s", 296 "dry-run|n" => 1, 297 "all" => 1, 298 "force" => 1 299 }, 300 "run-post" => 1, 301 "function" => \&action_restore 302 }, 303 "search" => { 304 "options" => { 305 "global" => 1, 306 "word" => 1, 307 "file" => 1, 308 "all" => 1, 309 }, 310 "run-post" => 1, 311 "function" => \&action_search 312 }, 313 "uninstall" => { 314 "options" => { "force" => 1 }, 315 "run-post" => 0, 316 "function" => \&action_uninstall 317 }, 318 "update" => { 319 "options" => { 320 "no-depends" => 1, 321 "no-depends-at-all" => 1, 322 "all" => 1, 323 "self" => 1, 324 "list" => 1, 325 "no-auto-remove" => 1, 326 "no-auto-install" => 1, 327 "reinstall-forcibly-removed" => 1, 328 "force" => 1, 329 "backupdir" => "=s", 330 "backup" => 1, 331 "exclude" => "=s@", 332 "dry-run|n" => 1 333 }, 334 "run-post" => 1, 335 "function" => \&action_update 336 }, 337 "version" => { }, # handled separately 338); 339 340main() if $ismain; 341 342##################################################################### 343 344 345sub main { 346 my %options; # TL options from local tlpdb 347 348 my %globaloptions = ( 349 "gui" => 1, 350 "gui-lang" => "=s", 351 "debug-translation" => 1, 352 "h|?" => 1, 353 "help" => 1, 354 "location|repository|repo" => "=s", 355 "machine-readable" => 1, 356 "no-execute-actions" => 1, 357 "package-logfile" => "=s", 358 "persistent-downloads" => "!", 359 "pause" => 1, 360 "pin-file" => "=s", 361 "print-platform|print-arch" => 1, 362 "usermode|user-mode" => 1, 363 "usertree|user-tree" => "=s", 364 "version" => 1, 365 ); 366 367 my %optarg; 368 for my $k (keys %globaloptions) { 369 if ($globaloptions{$k} eq "1") { 370 $optarg{$k} = 1; 371 } else { 372 $optarg{"$k" . $globaloptions{$k}} = 1; 373 } 374 } 375 for my $v (values %action_specification) { 376 if (defined($v->{'options'})) { 377 my %opts = %{$v->{'options'}}; 378 for my $k (keys %opts) { 379 if ($opts{$k} eq "1") { 380 $optarg{$k} = 1; 381 } else { 382 $optarg{"$k" . $opts{$k}} = 1; 383 } 384 } 385 } 386 } 387 388 # save command line options for later restart, if necessary 389 @::SAVEDARGV = @ARGV; 390 391 TeXLive::TLUtils::process_logging_options(); 392 393 GetOptions(\%opts, keys(%optarg)) or pod2usage(2); 394 395 $::debug_translation = 0; 396 $::debug_translation = 1 if $opts{"debug-translation"}; 397 398 $::machinereadable = $opts{"machine-readable"} 399 if (defined($opts{"machine-readable"})); 400 401 $action = shift @ARGV; 402 if (!defined($action)) { 403 if ($opts{"gui"}) { # -gui = gui 404 $action = "gui"; 405 } elsif ($opts{"print-platform"}) { # -print-arch = print-arch 406 $action = "print-platform"; 407 } else { 408 $action = ""; 409 } 410 } 411 $action = lc($action); 412 413 $action = "platform" if ($action eq "arch"); 414 415 ddebug("action = $action\n"); 416 for my $k (keys %opts) { 417 ddebug("$k => $opts{$k}\n"); 418 } 419 ddebug("arguments: @ARGV\n") if @ARGV; 420 421 if ($opts{"version"} || (defined $action && $action eq "version")) { 422 info(give_version()); 423 exit(0); 424 } 425 426 if (defined($action) && $action eq "help") { 427 $opts{"help"} = 1; 428 } 429 430 if (defined($action) && $action eq "print-platform") { 431 print TeXLive::TLUtils::platform(), "\n"; 432 exit 0; 433 } 434 435 # 436 # ACTION massaging 437 # for backward compatibility and usability 438 439 # unify arguments so that the $action contains paper in all cases 440 # and push the first arg back to @ARGV for action_paper processing 441 if ($action =~ /^(paper|xdvi|psutils|pdftex|dvips|dvipdfmx?|context)$/) { 442 unshift(@ARGV, $action); 443 $action = "paper"; 444 } 445 446 # backward compatibility with action "show" and "list" from before 447 if ($action =~ /^(show|list)$/) { 448 $action = "info"; 449 } 450 451 # now $action should be part of %actionoptions, otherwise this is 452 # an error 453 if (defined($action) && $action && !exists $action_specification{$action}) { 454 die "$prg: unknown action: $action; try --help if you need it.\n"; 455 } 456 457 if ((!defined($action) || !$action) && !$opts{"help"} && !$opts{"h"}) { 458 die "$prg: missing action; try --help if you need it.\n"; 459 } 460 461 if ($opts{"help"} || $opts{"h"}) { 462 # perldoc does ASCII emphasis on the output, and runs it through 463 # $PAGER, so people want it. But not all Unix platforms have it, 464 # and on Windows our Config.pm can apparently interfere, so always 465 # skip it there. Or if users have NOPERLDOC set in the environment. 466 my @noperldoc = (); 467 if (win32() || $ENV{"NOPERLDOC"}) { 468 @noperldoc = ("-noperldoc", "1"); 469 } else { 470 if (!TeXLive::TLUtils::which("perldoc")) { 471 @noperldoc = ("-noperldoc", "1"); 472 } else { 473 # checking only for the existence of perldoc is not enough 474 # because Debian/Ubuntu unfortunately ship a stub that does nothing; 475 # try to check for that, too. 476 my $ret = system("perldoc -V >/dev/null 2>&1"); 477 if ($ret == 0) { 478 debug("working perldoc found, using it\n"); 479 } else { 480 tlwarn("$prg: perldoc seems to be non-functional, not using it.\n"); 481 @noperldoc = ("-noperldoc", "1"); 482 } 483 } 484 } 485 # less can break control characters and thus the output of pod2usage 486 # is broken. We add/set LESS=-R in the environment and unset 487 # LESSPIPE and LESSOPEN to try to help. 488 # 489 if (defined($ENV{'LESS'})) { 490 $ENV{'LESS'} .= " -R"; 491 } else { 492 $ENV{'LESS'} = "-R"; 493 } 494 delete $ENV{'LESSPIPE'}; 495 delete $ENV{'LESSOPEN'}; 496 if ($action && ($action ne "help")) { 497 # 1) Must use [...] form for -sections arg because otherwise the 498 # /$action subsection selector applies to all sections. 499 # https://rt.cpan.org/Public/Bug/Display.html?id=102116 500 # 2) Must use "..." for that so the $action value is interpolated. 501 pod2usage(-exitstatus => 0, -verbose => 99, 502 -sections => [ 'NAME', 'SYNOPSIS', "ACTIONS/$::action.*" ], 503 @noperldoc); 504 } else { 505 if ($opts{"help"}) { 506 pod2usage(-exitstatus => 0, -verbose => 2, @noperldoc); 507 } else { 508 # give a short message about usage 509 print " 510tlmgr revision $tlmgrrevision 511usage: tlmgr OPTION... ACTION ARGUMENT... 512where ACTION is one of:\n"; 513 for my $k (sort keys %action_specification) { 514 # don't print internal options 515 next if ($k =~ m/^_/); 516 print " $k\n"; 517 } 518 print "\nUse\n tlmgr ACTION --help 519for more details on a specific option, and 520 tlmgr --help 521for the full story.\n"; 522 exit 0; 523 } 524 } 525 } 526 527 # --machine-readable is only supported by update. 528 if ($::machinereadable && 529 $action ne "update" && $action ne "install" && $action ne "option") { 530 tlwarn("$prg: --machine-readable output not supported for $action\n"); 531 } 532 533 # 534 # bail out of it is unknown action 535 if (!defined($action_specification{$action})) { 536 tlwarn("$prg: action unknown: $action\n"); 537 exit ($F_ERROR); 538 } 539 540 # check on supported arguments 541 # 542 my %suppargs; 543 %suppargs = %{$action_specification{$action}{'options'}} 544 if defined($action_specification{$action}{'options'}); 545 my @notvalidargs; 546 for my $k (keys %opts) { 547 my @allargs = keys %suppargs; 548 push @allargs, keys %globaloptions; 549 my $found = 0; 550 for my $ok (@allargs) { 551 my @variants = split '\|', $ok; 552 if (TeXLive::TLUtils::member($k, @variants)) { 553 $found = 1; 554 last; 555 } 556 } 557 push @notvalidargs, $k if !$found; 558 } 559 if (@notvalidargs) { 560 my $msg = "The action $action does not support the following option(s):\n"; 561 for my $c (@notvalidargs) { 562 $msg .= " $c"; 563 } 564 tlwarn("$prg: $msg\n"); 565 tldie("$prg: Try --help if you need it.\n"); 566 } 567 568 # 569 # the main tree we will be working on 570 $::maintree = $Master; 571 if ($opts{"usermode"}) { 572 # we could also try to detect that we don't have write permissions 573 # and switch to user mode automatically 574 if (defined($opts{"usertree"})) { 575 $::maintree = $opts{"usertree"}; 576 } else { 577 chomp($::maintree = `kpsewhich -var-value TEXMFHOME`); 578 } 579 } 580 581 # besides doing normal logging if -logfile is specified, we try to log 582 # package related actions (install, remove, update) to 583 # the package-log file TEXMFSYSVAR/web2c/tlmgr.log 584 # 585 # *** FreeBSD specific: FreeBSD port uses /var/db/tlpkg/tlmgr.log. 586 # 587 $packagelogged = 0; # how many msgs we logged 588 chomp (my $texmfsysvar = `kpsewhich -var-value=TEXMFSYSVAR`); 589 $packagelogfile = $opts{"package-logfile"}; 590 if ($opts{"usermode"}) { 591 $packagelogfile ||= "$::maintree/web2c/tlmgr.log"; 592 } else { 593 $packagelogfile ||= "/var/db/tlpkg/tlmgr.log"; 594 } 595 # 596 # Try to open the packagelog file, but do NOT die when that does not work 597 if (!open(PACKAGELOG, ">>$packagelogfile")) { 598 debug("Cannot open package log file $packagelogfile for appending\n"); 599 debug("Will not log package installation/removal/update for that run\n"); 600 $packagelogfile = ""; 601 } 602 603 $loadmediasrcerror = "Cannot load TeX Live database from "; 604 605 # load the config file and set the config options 606 # load it BEFORE starting downloads as we set persistent-downloads there! 607 load_config_file(); 608 609 # set global variable if execute actions should be suppressed 610 $::no_execute_actions = 1 if (defined($opts{'no-execute-actions'})); 611 612 613 # if we are asked to use persistent connections try to start it here 614 { 615 my $do_persistent; 616 if (defined($opts{'persistent-downloads'})) { 617 # a command line argument for persistent-downloads has been given, 618 # either with --no-... or --... that overrides any other setting 619 $do_persistent = $opts{'persistent-downloads'}; 620 } else { 621 # check if it is set in the config file 622 if (defined($config{'persistent-downloads'})) { 623 $do_persistent = $config{'persistent-downloads'}; 624 } 625 } 626 # default method is doing persistent downloads: 627 if (!defined($do_persistent)) { 628 $do_persistent = 1; 629 } 630 ddebug("tlmgr:main: do persistent downloads = $do_persistent\n"); 631 if ($do_persistent) { 632 TeXLive::TLUtils::setup_persistent_downloads() ; 633 } 634 if (!defined($::tldownload_server)) { 635 debug("tlmgr:main: ::tldownload_server not defined\n"); 636 } else { 637 debug("tlmgr:main: ::tldownload_server defined\n"); 638 } 639 } 640 641 my $ret = execute_action($action, @ARGV); 642 643 if ($ret & $F_ERROR) { 644 tlwarn("$prg: An error has occurred. See above messages. Exiting.\n"); 645 } 646 647 # end of main program, returns also error codes 648 exit ($ret); 649 650} # end main 651 652sub give_version { 653 if (!defined($::version_string)) { 654 $::version_string = ""; 655 $::version_string .= "tlmgr revision $tlmgrrevision\n"; 656 $::version_string .= "tlmgr using installation: $Master/tlpkg\n"; 657 if (open (REL_TL, "$Master/tlpkg/release-texlive.txt")) { 658 # print first and last lines, which have the TL version info. 659 my @rel_tl = <REL_TL>; 660 $::version_string .= $rel_tl[0]; 661 $::version_string .= $rel_tl[$#rel_tl]; 662 close (REL_TL); 663 } 664 } 665 # 666 # add the list of revisions 667 if ($::opt_verbosity > 0) { 668 $::version_string .= "Revisions of TeXLive:: modules:"; 669 $::version_string .= "\nTLConfig: " . TeXLive::TLConfig->module_revision(); 670 $::version_string .= "\nTLUtils: " . TeXLive::TLUtils->module_revision(); 671 $::version_string .= "\nTLPOBJ: " . TeXLive::TLPOBJ->module_revision(); 672 $::version_string .= "\nTLPDB: " . TeXLive::TLPDB->module_revision(); 673 $::version_string .= "\nTLPaper: " . TeXLive::TLPaper->module_revision(); 674 $::version_string .= "\nTLWinGoo: " . TeXLive::TLWinGoo->module_revision(); 675 $::version_string .= "\n"; 676 } 677 return $::version_string; 678} 679 680 681sub execute_action { 682 my ($action, @argv) = @_; 683 684 # we have to set @ARGV to the @argv since many of the action_* subs 685 # use GetOption 686 @ARGV = @argv; 687 688 # actions which shouldn't have any lasting effects, such as search or 689 # list, end by calling finish(0), which skips postinstall actions. 690 if (!defined($action_specification{$action})) { 691 tlwarn ("$prg: unknown action: $action; try --help if you need it.\n"); 692 return ($F_ERROR); 693 } 694 695 if (!defined($action_specification{$action}{"function"})) { 696 tlwarn ("$prg: action $action defined, but no way to execute it.\n"); 697 return ($F_ERROR); 698 } 699 700 my $ret = $F_OK; 701 my $foo = &{$action_specification{$action}{"function"}}(); 702 if (defined($foo)) { 703 if ($foo & $F_ERROR) { 704 # warnings etc are given at the highest level, i.e., in main 705 return($foo); 706 } 707 if ($foo & $F_WARNING) { 708 tlwarn("$prg: action $action returned a warning.\n"); 709 $ret = $foo; 710 } 711 } else { 712 $ret = $F_OK; 713 tlwarn("$prg: didn't get return value from action $action, assuming ok.\n"); 714 } 715 my $run_post = 1; 716 if ($ret & $F_NOPOSTACTION) { 717 # clear the postaction bit 718 $ret ^= $F_NOPOSTACTION; 719 $run_post = 0; 720 } 721 if (!$action_specification{$action}{"run-post"}) { 722 $run_post = 0; 723 } 724 725 # close the special log file 726 if ($packagelogfile && !$::gui_mode) { 727 info("$prg: package log updated: $packagelogfile\n") if $packagelogged; 728 close(PACKAGELOG); 729 } 730 731 return ($ret) if (!$run_post); 732 733 # run external programs. 734 $ret |= &handle_execute_actions(); 735 736 return $ret; 737} 738 739 740 741# run CMD with notice to the user and if exit status is nonzero, complain. 742# return exit status. 743# 744sub do_cmd_and_check 745{ 746 my $cmd = shift; 747 # we output the pre-running notice on a separate line so that 748 # tlmgr front ends (MacOSX's TeX Live Utility) can read it 749 # and show it to the user before the possibly long delay. 750 info("running $cmd ...\n"); 751 my ($out, $ret); 752 if ($opts{"dry-run"}) { 753 $ret = $F_OK; 754 $out = ""; 755 } else { 756 ($out, $ret) = TeXLive::TLUtils::run_cmd("$cmd 2>&1"); 757 } 758 if ($ret == 0) { 759 info("done running $cmd.\n"); 760 log("--output of $cmd:\n$out\n--end of output of $cmd."); 761 return ($F_OK); 762 } else { 763 info("\n"); 764 tlwarn("$cmd failed (status $ret), output:\n$out\n"); 765 return ($F_ERROR); 766 } 767} 768 769# run external programs (mktexlsr, updmap-sys, etc.) as specified by the 770# keys in the RET hash. We return the number of unsuccessful runs, zero 771# if all ok. 772# 773# If the "map" key is specified, the value may be a reference to a list 774# of map command strings to pass to updmap, e.g., "enable Map=ascii.map". 775# 776sub handle_execute_actions { 777 my $errors = 0; 778 779 my $sysmode = ($opts{"usermode"} ? "" : "-sys"); 780 my $invoke_fmtutil = "fmtutil$sysmode $common_fmtutil_args"; 781 782 if ($::files_changed) { 783 $errors += do_cmd_and_check("mktexlsr"); 784 if (defined($localtlpdb->get_package('context'))) { 785 $errors += do_cmd_and_check("mtxrun --generate"); 786 } 787 $::files_changed = 0; 788 } 789 790 chomp(my $TEXMFSYSVAR = `kpsewhich -var-value=TEXMFSYSVAR`); 791 chomp(my $TEXMFSYSCONFIG = `kpsewhich -var-value=TEXMFSYSCONFIG`); 792 chomp(my $TEXMFLOCAL = `kpsewhich -var-value=TEXMFLOCAL`); 793 chomp(my $TEXMFDIST = `kpsewhich -var-value=TEXMFDIST`); 794 795 # maps handling 796 { 797 my $updmap_run_needed = 0; 798 for my $m (keys %{$::execute_actions{'enable'}{'maps'}}) { 799 $updmap_run_needed = 1; 800 } 801 for my $m (keys %{$::execute_actions{'disable'}{'maps'}}) { 802 $updmap_run_needed = 1; 803 } 804 my $dest = $opts{"usermode"} ? "$::maintree/web2c/updmap.cfg" 805 : "$TEXMFDIST/web2c/updmap.cfg"; 806 if ($updmap_run_needed) { 807 TeXLive::TLUtils::create_updmap($localtlpdb, $dest); 808 } 809 $errors += do_cmd_and_check("updmap$sysmode") if $updmap_run_needed; 810 } 811 812 # format relevant things 813 # we first have to check if the config files, that is fmtutil.cnf 814 # or one of the language* files have changed, regenerate them 815 # if necessary, and then run the necessary fmtutil calls. 816 { 817 # first check for language* files 818 my $regenerate_language = 0; 819 for my $m (keys %{$::execute_actions{'enable'}{'hyphens'}}) { 820 $regenerate_language = 1; 821 last; 822 } 823 for my $m (keys %{$::execute_actions{'disable'}{'hyphens'}}) { 824 $regenerate_language = 1; 825 last; 826 } 827 if ($regenerate_language) { 828 for my $ext ("dat", "def", "dat.lua") { 829 my $lang = "language.$ext"; 830 info("regenerating $lang\n"); 831 my $arg1 = "$TEXMFSYSVAR/tex/generic/config/language.$ext"; 832 my $arg2 = "$TEXMFLOCAL/tex/generic/config/language-local.$ext"; 833 if ($ext eq "dat") { 834 TeXLive::TLUtils::create_language_dat($localtlpdb, $arg1, $arg2); 835 } elsif ($ext eq "def") { 836 TeXLive::TLUtils::create_language_def($localtlpdb, $arg1, $arg2); 837 } else { 838 TeXLive::TLUtils::create_language_lua($localtlpdb, $arg1, $arg2); 839 } 840 } 841 } 842 843 # 844 # check if *depending* formats have been changed 845 # we are currently only caring for package "latex" and "tex". If 846 # one of these has changed, we search for all packages *depending* 847 # on latex/tex and regenerate all formats in these packages. 848 # 849 # do this only if we are not in --list or --dry-run mode 850 if (!$opts{"list"}) { 851 my @check_indirect_formats; 852 # TODO: 853 # in case that hyphenation patterns are changed, ie $regenerate_language 854 # then maybe we don't need to update latex based ones? 855 push @check_indirect_formats, $localtlpdb->needed_by("latex") 856 if ($::latex_updated); 857 push @check_indirect_formats, $localtlpdb->needed_by("tex") 858 if ($::tex_updated); 859 for my $p (@check_indirect_formats) { 860 my $tlp = $localtlpdb->get_package($p); 861 if (!defined($tlp)) { 862 tlwarn("$p mentioned but not found in local tlpdb, strange!\n"); 863 next; 864 } 865 TeXLive::TLUtils::announce_execute_actions("enable", $tlp, "format"); 866 } 867 } 868 869 # format-regenerate is used when the paper size changes. In that 870 # case, if option("create_formats") is set, we simply want to generate 871 # all formats 872 # 873 my %done_formats; 874 my %updated_engines; 875 my %format_to_engine; 876 my %do_enable; 877 my $do_full = 0; 878 for my $m (keys %{$::execute_actions{'enable'}{'formats'}}) { 879 $do_full = 1; 880 $do_enable{$m} = 1; 881 # here we check whether an engine is updated 882 my %foo = %{$::execute_actions{'enable'}{'formats'}{$m}}; 883 if (!defined($foo{'name'}) || !defined($foo{'engine'})) { 884 tlwarn("$prg: Very strange error, please report ", %foo); 885 } else { 886 $format_to_engine{$m} = $foo{'engine'}; 887 if ($foo{'name'} eq $foo{'engine'}) { 888 $updated_engines{$m} = 1; 889 } 890 } 891 } 892 for my $m (keys %{$::execute_actions{'disable'}{'formats'}}) { 893 $do_full = 1; 894 } 895 my $opt_fmt = $localtlpdb->option("create_formats"); 896 if ($do_full) { 897 info("regenerating fmtutil.cnf in $TEXMFDIST\n"); 898 TeXLive::TLUtils::create_fmtutil($localtlpdb, 899 "$TEXMFDIST/web2c/fmtutil.cnf"); 900 } 901 if ($opt_fmt && !$::regenerate_all_formats) { 902 # first regenerate all formats --byengine 903 for my $e (keys %updated_engines) { 904 log ("updating formats based on $e\n"); 905 $errors += do_cmd_and_check 906 ("$invoke_fmtutil --no-error-if-no-format --byengine $e"); 907 } 908 # now rebuild all other formats 909 for my $f (keys %do_enable) { 910 next if defined($updated_engines{$format_to_engine{$f}}); 911 # ignore disabled formats 912 next if !$::execute_actions{'enable'}{'formats'}{$f}{'mode'}; 913 log ("(re)creating format dump $f\n"); 914 $errors += do_cmd_and_check ("$invoke_fmtutil --byfmt $f"); 915 $done_formats{$f} = 1; 916 } 917 } 918 919 # now go back to the hyphenation patterns and regenerate formats 920 # based on the various language files 921 # this of course will in some cases duplicate fmtutil calls, 922 # but it is much easier than actually checking which formats 923 # don't need to be updated 924 925 if ($regenerate_language) { 926 for my $ext ("dat", "def", "dat.lua") { 927 my $lang = "language.$ext"; 928 if (! TeXLive::TLUtils::win32()) { 929 # Use full path for external command, except on Windows. 930 $lang = "$TEXMFSYSVAR/tex/generic/config/$lang"; 931 } 932 if ($localtlpdb->option("create_formats") 933 && !$::regenerate_all_formats) { 934 $errors += do_cmd_and_check ("$invoke_fmtutil --byhyphen \"$lang\""); 935 } 936 } 937 } 938 } 939 940 # 941 if ($::regenerate_all_formats) { 942 info("Regenerating all formats, this may take some time ..."); 943 $errors += do_cmd_and_check("$invoke_fmtutil --all"); 944 info("done\n"); 945 $::regenerate_all_formats = 0; 946 } 947 948 # undefine the global var, otherwise in GUI mode the actions 949 # are accumulating 950 undef %::execute_actions; 951 952 if ($errors > 0) { 953 # should we return warning here? 954 return $F_ERROR; 955 } else { 956 return $F_OK; 957 } 958} 959 960 961# GET_MIRROR 962# 963# just return a mirror 964sub action_get_mirror { 965 my $loc = give_ctan_mirror(); 966 print "$loc\n"; 967 return ($F_OK | $F_NOPOSTACTION); 968} 969 970# 971# includes a .tlpobj in the db, also searchers for sub-tlpobj 972# for doc and source files 973# 974 975# _INCLUDE_TLPOBJ 976# 977# includes a .tlpobj in the db, also searchers for sub-tlpobj 978# for doc and source files 979# 980sub action_include_tlpobj { 981 # this is an internal function that should not be used outside 982 init_local_db(); 983 for my $f (@ARGV) { 984 my $tlpobj = TeXLive::TLPOBJ->new; 985 $tlpobj->from_file($f); 986 # we now have to check whether that is a .doc or .src package, so shipping 987 # src or doc files from a different package. 988 # We should have that package already installed ... 989 my $pkg = $tlpobj->name; 990 if ($pkg =~ m/^(.*)\.(source|doc)$/) { 991 # got a .src or .doc package 992 my $type = $2; 993 my $mothership = $1; 994 my $mothertlp = $localtlpdb->get_package($mothership); 995 if (!defined($mothertlp)) { 996 tlwarn("We are trying to add ${type} files to a nonexistent package $mothership!\n"); 997 tlwarn("Trying to continue!\n"); 998 # the best we can do is rename that package to $mothername and add it! 999 $tlpobj->name($mothership); 1000 # add the src/docfiles tlpobj under the mothership name 1001 $localtlpdb->add_tlpobj($tlpobj); 1002 } else { 1003 if ($type eq "source") { 1004 $mothertlp->srcfiles($tlpobj->srcfiles); 1005 $mothertlp->srcsize($tlpobj->srcsize); 1006 } else { 1007 # must be "doc" 1008 $mothertlp->docfiles($tlpobj->docfiles); 1009 $mothertlp->docsize($tlpobj->docsize); 1010 } 1011 # that make sure that the original entry is overwritten 1012 $localtlpdb->add_tlpobj($mothertlp); 1013 } 1014 } else { 1015 # completely normal package, just add it 1016 $localtlpdb->add_tlpobj($tlpobj); 1017 } 1018 $localtlpdb->save; 1019 } 1020 # no error checking here for now 1021 return ($F_OK); 1022} 1023 1024 1025# REMOVE 1026# 1027# tlmgr remove foo bar baz 1028# will remove the packages foo bar baz itself 1029# and will remove all .ARCH dependencies, too 1030# and if some of them are collections it will also remove the 1031# depending packages which are NOT Collections|Schemes. 1032# if some of them are referenced somewhere they will not be removed 1033# unless --force given 1034# 1035# tlmgr remove --no-depends foo bar baz 1036# will remove the packages foo bar baz itself without any dependencies 1037# but it will still remove all .ARCH dependency 1038# if some of them are referenced somewhere they will not be removed 1039# unless --force given 1040# 1041# tlmgr remove --no-depends-at-all foo bar baz 1042# will absolutely only install foo bar baz not even taking .ARCH into 1043# account 1044# 1045sub action_remove { 1046 my $ret = $F_OK; 1047 # we do the following: 1048 # - (not implemented) order collections such that those depending on 1049 # other collections are first removed, and then those which only 1050 # depend on packages. Otherwise 1051 # remove collection-latex collection-latexrecommended 1052 # will not succeed 1053 # - first loop over all cmd line args and consider only the collections 1054 # - for each to be removed collection: 1055 # . check that no other collections/scheme asks for that collection 1056 # . remove the collection 1057 # . remove all dependencies 1058 # - for each normal package not already removed (via the above) 1059 # . check that no collection/scheme still depends on this package 1060 # . remove the package 1061 # 1062 $opts{"no-depends"} = 1 if $opts{"no-depends-at-all"}; 1063 my %already_removed; 1064 my @more_removal; 1065 init_local_db(); 1066 return($F_ERROR) if !check_on_writable(); 1067 info("$prg remove: dry run, no changes will be made\n") if $opts{"dry-run"}; 1068 my @packs = @ARGV; 1069 # 1070 # we have to be carefull not to remove too many packages. The idea is 1071 # as follows: 1072 # - let A be the set of all packages to be removed from the cmd line 1073 # - let A* be the set of A with all dependencies expanded 1074 # - let B be the set of all packages 1075 # - let C = B \ A*, ie the set of all packages without those packages 1076 # in the set of A* 1077 # - let C* be the set of C with all dependencies expanded 1078 # - let D = A* \ C*, ie the set of all packages to be removed (A*) 1079 # without all the package that are still needed (C*) 1080 # - remove all package in D 1081 # - for any package in A (not in A*, in A, ie on the cmd line) that is 1082 # also in C* (so a package that was asked for to be removed on the 1083 # cmd line, but it isn't because someone else asks for it), warn the 1084 # user that it is still needed 1085 # 1086 # remove all .ARCH dependencies, too, unless $opts{"no-depends-at-all"} 1087 @packs = $localtlpdb->expand_dependencies("-only-arch", $localtlpdb, @packs) 1088 unless $opts{"no-depends-at-all"}; 1089 # remove deps unless $opts{"no-depends"} 1090 @packs = $localtlpdb->expand_dependencies("-no-collections", $localtlpdb, @packs) unless $opts{"no-depends"}; 1091 my %allpacks; 1092 for my $p ($localtlpdb->list_packages) { $allpacks{$p} = 1; } 1093 for my $p (@packs) { delete($allpacks{$p}); } 1094 my @neededpacks = $localtlpdb->expand_dependencies($localtlpdb, keys %allpacks); 1095 my %packs; 1096 my %origpacks; 1097 my @origpacks = $localtlpdb->expand_dependencies("-only-arch", $localtlpdb, @ARGV) unless $opts{"no-depends-at-all"}; 1098 for my $p (@origpacks) { $origpacks{$p} = 1; } 1099 for my $p (@packs) { $packs{$p} = 1; } 1100 for my $p (@neededpacks) { 1101 if (defined($origpacks{$p})) { 1102 # that package was asked for to be removed on the cmd line 1103 my @needed = $localtlpdb->needed_by($p); 1104 if ($opts{"force"}) { 1105 info("$prg: $p is needed by " . join(" ", @needed) . "\n"); 1106 info("$prg: removing it anyway, due to --force\n"); 1107 } else { 1108 delete($packs{$p}); 1109 tlwarn("$prg: not removing $p, needed by " . 1110 join(" ", @needed) . "\n"); 1111 $ret |= $F_WARNING; 1112 } 1113 } else { 1114 delete($packs{$p}); 1115 } 1116 } 1117 @packs = keys %packs; 1118 foreach my $pkg (sort @packs) { 1119 my $tlp = $localtlpdb->get_package($pkg); 1120 next if defined($already_removed{$pkg}); 1121 if (!defined($tlp)) { 1122 info("$pkg: package not present, cannot remove\n"); 1123 $ret |= $F_WARNING; 1124 } else { 1125 # in the first round we only remove collections, nothing else 1126 # but removing collections will remove all dependencies, too 1127 # save the information of which packages have already been removed 1128 # into %already_removed. 1129 if ($tlp->category eq "Collection") { 1130 my $foo = 0; 1131 info ("$prg: removing $pkg\n"); 1132 if (!$opts{"dry-run"}) { 1133 $foo = $localtlpdb->remove_package($pkg); 1134 logpackage("remove: $pkg"); 1135 } 1136 if ($foo) { 1137 # removal was successful, so the return is at least 0x0001 mktexlsr 1138 # remove dependencies, too 1139 $already_removed{$pkg} = 1; 1140 } 1141 } else { 1142 # save all the other packages into the @more_removal list to 1143 # be removed at the second state. Note that if a package has 1144 # already been removed due to a removal of a collection 1145 # it will be marked as such in %already_removed and not tried again 1146 push (@more_removal, $pkg); 1147 } 1148 } 1149 } 1150 foreach my $pkg (sort @more_removal) { 1151 if (!defined($already_removed{$pkg})) { 1152 info ("$prg: removing package $pkg\n"); 1153 if (!$opts{"dry-run"}) { 1154 if ($localtlpdb->remove_package($pkg)) { 1155 # removal was successful 1156 logpackage("remove: $pkg"); 1157 $already_removed{$pkg} = 1; 1158 } 1159 } 1160 } 1161 } 1162 if ($opts{"dry-run"}) { 1163 # stop here, don't do any postinstall actions 1164 return ($ret | $F_NOPOSTACTION); 1165 } else { 1166 $localtlpdb->save; 1167 my @foo = sort keys %already_removed; 1168 if (@foo) { 1169 info("$prg: ultimately removed these packages: @foo\n"); 1170 } else { 1171 info("$prg: no packages removed.\n"); 1172 } 1173 } 1174 return ($ret); 1175} 1176 1177 1178# PAPER 1179# ARGV can look like: 1180# paper a4 1181# paper letter 1182# [xdvi|...|context] paper [help|papersize|--list] 1183# 1184sub action_paper { 1185 init_local_db(); 1186 my $texmfconfig; 1187 if ($opts{"usermode"}) { 1188 chomp($texmfconfig = `kpsewhich -var-value=TEXMFCONFIG`); 1189 } else { 1190 chomp($texmfconfig = `kpsewhich -var-value=TEXMFSYSCONFIG`); 1191 } 1192 $ENV{"TEXMFCONFIG"} = $texmfconfig; 1193 1194 my $action = shift @ARGV; 1195 if ($action =~ m/^paper$/i) { # generic paper 1196 my $newpaper = shift @ARGV; 1197 if ($opts{"list"}) { # tlmgr paper --list => complain. 1198 tlwarn("$prg: ignoring paper setting to $newpaper with --list\n") 1199 if $newpaper; # complain if they tried to set, too. 1200 tlwarn("$prg: please specify a program before paper --list, ", 1201 "as in: tlmgr pdftex paper --list\n"); 1202 return($F_ERROR) 1203 1204 } elsif (!defined($newpaper)) { # tlmgr paper => show all current sizes. 1205 return TeXLive::TLPaper::paper_all($texmfconfig,undef); 1206 1207 } elsif ($newpaper !~ /^(a4|letter)$/) { # tlmgr paper junk => complain. 1208 $newpaper = "the empty string" if !defined($newpaper); 1209 tlwarn("$prg: expected `a4' or `letter' after paper, not $newpaper\n"); 1210 return($F_ERROR); 1211 1212 } else { # tlmgr paper {a4|letter} => do it. 1213 return ($F_ERROR) if !check_on_writable(); 1214 return (TeXLive::TLPaper::paper_all($texmfconfig,$newpaper)); 1215 } 1216 1217 } else { # program-specific paper 1218 my $prog = $action; # first argument is the program to change 1219 my $arg = shift @ARGV; # get "paper" argument 1220 if (!defined($arg) || $arg ne "paper") { 1221 $arg = "the empty string." if ! $arg; 1222 tlwarn("$prg: expected `paper' after $prog, not $arg\n"); 1223 return ($F_ERROR); 1224 } 1225 # the do_paper progs check for the argument --list, so if given 1226 # restore it to the cmd line. 1227 if (@ARGV) { 1228 return ($F_ERROR) if !check_on_writable(); 1229 } 1230 unshift(@ARGV, "--list") if $opts{"list"}; 1231 return(TeXLive::TLPaper::do_paper($prog,$texmfconfig,@ARGV)); 1232 } 1233 # we should not come here anyway 1234 return($F_OK); 1235} 1236 1237 1238# PATH 1239# 1240sub action_path { 1241 if ($opts{"usermode"}) { 1242 tlwarn("action `path' not supported in usermode!\n"); 1243 exit 1; 1244 } 1245 my $what = shift @ARGV; 1246 if (!defined($what) || ($what !~ m/^(add|remove)$/i)) { 1247 $what = "" if ! $what; 1248 tlwarn("$prg: action path requires add or remove, not: $what\n"); 1249 return ($F_ERROR); 1250 } 1251 init_local_db(); 1252 my $winadminmode = 0; 1253 if (win32()) { 1254 # 1255 # for w32 we do system wide vs user setting detection as follows: 1256 # - if --w32mode is NOT given, 1257 # - if admin 1258 # --> honor opt_w32_multi_user setting in tlpdb 1259 # - if not admin 1260 # - if opt_w32_multi_user == NO 1261 # --> do user path adjustment 1262 # - if opt_w32_multi_user == YES 1263 # --> do nothing, warn that the setting is on, suggest --w32mode user 1264 # - if --w32mode admin 1265 # - if admin 1266 # --> ignore opt_w32_multi_user and do system path adjustment 1267 # - if non-admin 1268 # --> do nothing but warn that user does not have privileges 1269 # - if --w32mode user 1270 # - if admin 1271 # --> ignore opt_w32_multi_user and do user path adjustment 1272 # - if non-admin 1273 # --> ignore opt_w32_multi_user and do user path adjustment 1274 if (!$opts{"w32mode"}) { 1275 $winadminmode = $localtlpdb->option("w32_multi_user"); 1276 if (!TeXLive::TLWinGoo::admin()) { 1277 if ($winadminmode) { 1278 tlwarn("The TLPDB specifies system wide path adjustments\nbut you don't have admin privileges.\nFor user path adjustment please use\n\t--w32mode user\n"); 1279 # and do nothing 1280 return ($F_ERROR); 1281 } 1282 } 1283 } else { 1284 # we are in the block where a --w32mode argument is given 1285 # we reverse the tests: 1286 if (TeXLive::TLWinGoo::admin()) { 1287 # in admin mode we simply use what is given on the cmd line 1288 if ($opts{"w32mode"} eq "user") { 1289 $winadminmode = 0; 1290 } elsif ($opts{"w32mode"} eq "admin") { 1291 $winadminmode = 1; 1292 } else { 1293 tlwarn("Unknown --w32admin mode: $opts{w32mode}, should be 'admin' or 'user'\n"); 1294 return ($F_ERROR); 1295 } 1296 } else { 1297 # we are non-admin 1298 if ($opts{"w32mode"} eq "user") { 1299 $winadminmode = 0; 1300 } elsif ($opts{"w32mode"} eq "admin") { 1301 tlwarn("You don't have the privileges to work in --w32mode admin\n"); 1302 return ($F_ERROR); 1303 } else { 1304 tlwarn("Unknown --w32admin mode: $opts{w32mode}, should be 'admin' or 'user'\n"); 1305 return ($F_ERROR); 1306 } 1307 } 1308 } 1309 } 1310 my $ret = $F_OK; 1311 if ($what =~ m/^add$/i) { 1312 if (win32()) { 1313 $ret |= TeXLive::TLUtils::w32_add_to_path( 1314 $localtlpdb->root . "/bin/win32", 1315 $winadminmode); 1316 $ret |= TeXLive::TLWinGoo::broadcast_env(); 1317 } else { 1318 $ret |= TeXLive::TLUtils::add_symlinks($localtlpdb->root, 1319 $localtlpdb->platform(), 1320 $localtlpdb->option("sys_bin"), 1321 $localtlpdb->option("sys_man"), 1322 $localtlpdb->option("sys_info")); 1323 } 1324 } elsif ($what =~ m/^remove$/i) { 1325 if (win32()) { 1326 $ret |= TeXLive::TLUtils::w32_remove_from_path( 1327 $localtlpdb->root . "/bin/win32", 1328 $winadminmode); 1329 $ret |= TeXLive::TLWinGoo::broadcast_env(); 1330 } else { 1331 # remove symlinks 1332 $ret |= TeXLive::TLUtils::remove_symlinks($localtlpdb->root, 1333 $localtlpdb->platform(), 1334 $localtlpdb->option("sys_bin"), 1335 $localtlpdb->option("sys_man"), 1336 $localtlpdb->option("sys_info")); 1337 } 1338 } else { 1339 tlwarn("\n$prg: Should not happen, action_path what=$what\n"); 1340 return ($F_ERROR); 1341 } 1342 # we should not need to run any post actions here, since 1343 # that changes only integrations, but no rebuild of formats etc etc 1344 # is needed 1345 return ($ret | $F_NOPOSTACTION); 1346} 1347 1348# DUMP TLPDB 1349# 1350sub action_dumptlpdb { 1351 init_local_db(); 1352 1353 # we are basically doing machine-readable output. 1354 my $savemr = $::machinereadable; 1355 $::machinereadable = 1; 1356 1357 if ($opts{"local"} && !$opts{"remote"}) { 1358 # for consistency we write out the location of the installation, 1359 # too, in the same format as when dumping the remote tlpdb 1360 print "location-url\t", $localtlpdb->root, "\n"; 1361 $localtlpdb->writeout; 1362 1363 } elsif ($opts{"remote"} && !$opts{"local"}) { 1364 init_tlmedia_or_die(); 1365 $remotetlpdb->writeout; 1366 1367 } else { 1368 tlwarn("tlmgr dump-tlpdb: need exactly one of --local and --remote.\n"); 1369 return ($F_ERROR); 1370 } 1371 1372 $::machinereadable = $savemr; 1373 return ($F_OK | $F_NOPOSTACTION); 1374} 1375 1376# INFO 1377# 1378sub action_info { 1379 init_local_db(); 1380 my ($what,@todo) = @ARGV; 1381 my $ret = $F_OK | $F_NOPOSTACTION; 1382 # 1383 # tlmgr info 1384 # tlmgr info collection 1385 # tlmgr info scheme 1386 # these commands just list the packages/collections/schemes installed with 1387 # a short list 1388 if (!defined($what) || ($what =~ m/^(collections|schemes)$/i)) { 1389 show_list_of_packages($what); 1390 return ($F_OK | $F_NOPOSTACTION); 1391 } 1392 # we are still here, so $what is defined and neither collection nor scheme, 1393 # so assume the arguments are package names 1394 foreach my $ppp ($what, @todo) { 1395 my ($pkg, $tag) = split ('@', $ppp, 2); 1396 my $tlpdb = $localtlpdb; 1397 my $source_found; 1398 my $tlp = $localtlpdb->get_package($pkg); 1399 my $installed = 0; 1400 if (!$tlp) { 1401 if (!$remotetlpdb) { 1402 init_tlmedia_or_die(); 1403 } 1404 if (defined($tag)) { 1405 if (!$remotetlpdb->is_virtual) { 1406 tlwarn("$prg: specifying implicit tags is not allowed for non-virtual databases!\n"); 1407 $ret |= $F_WARNING; 1408 next; 1409 } else { 1410 if (!$remotetlpdb->is_repository($tag)) { 1411 tlwarn("$prg: no such repository tag defined: $tag\n"); 1412 $ret |= $F_WARNING; 1413 next; 1414 } 1415 } 1416 } 1417 $tlp = $remotetlpdb->get_package($pkg, $tag); 1418 if (!$tlp) { 1419 if (defined($tag)) { 1420 # we already searched for the package in a specific tag, don't retry 1421 # all candidates! 1422 tlwarn("$prg: Cannot find package $pkg in repository $tag\n"); 1423 $ret |= $F_WARNING; 1424 next; 1425 } 1426 if ($remotetlpdb->is_virtual) { 1427 # we might have a package that is available in a 1428 # subsidiary repository, but not installable 1429 # because it is not pinned 1430 # we will list it but warn about this fact 1431 my @cand = $remotetlpdb->candidates($pkg); 1432 if (@cand) { 1433 my $first = shift @cand; 1434 if (defined($first)) { 1435 tlwarn("strange, we have a first candidate but no tlp: $pkg\n"); 1436 $ret |= $F_WARNING; 1437 next; 1438 } 1439 # already shifted away the first element 1440 if ($#cand >= 0) { 1441 # recursively showing all tags, but warn 1442 print "package: ", $pkg, "\n"; 1443 print "WARNING: This package is not pinned but present in subsidiary repositories\n"; 1444 print "WARNING: As long as it is not pinned it is not installable.\n"; 1445 print "WARNING: Listing all available copies of the package.\n"; 1446 my @aaa; 1447 for my $a (@cand) { 1448 my ($t,$r) = split(/\//, $a, 2); 1449 push @aaa, "$pkg" . '@' . $t; 1450 } 1451 $ret |= action_info(@aaa); 1452 next; 1453 } else { 1454 tlwarn("strange, package listed but no residual candidates: $pkg\n"); 1455 next; 1456 } 1457 } else { 1458 tlwarn("strange, package listed but no candidates: $pkg\n"); 1459 $ret |= $F_WARNING; 1460 next; 1461 } 1462 } 1463 # we didn't find a package like this, so use search 1464 info("$prg: cannot find package $pkg, searching for other matches:\n"); 1465 my ($foundfile, $founddesc) = search_tlpdb($remotetlpdb, $pkg, 1, 1, 0); 1466 print "\nPackages containing \`$pkg\' in their title/description:\n"; 1467 print $founddesc; 1468 print "\nPackages containing files matching \`$pkg\':\n"; 1469 print $foundfile; 1470 #$ret |= $F_WARNING; 1471 next; 1472 } 1473 # we want to also show the source if it is known 1474 if (defined($tag)) { 1475 $source_found = $tag; 1476 } else { 1477 if ($remotetlpdb->is_virtual) { 1478 my ($firsttag, @cand) = $remotetlpdb->candidates($pkg); 1479 $source_found = $firsttag; 1480 } else { 1481 # might be single user repository, don't mention anything 1482 } 1483 } 1484 $tlpdb = $remotetlpdb; 1485 } else { 1486 $installed = 1; 1487 } 1488 my @colls; 1489 if ($tlp->category ne "Collection" && $tlp->category ne "Scheme") { 1490 @colls = $localtlpdb->needed_by($pkg); 1491 if (!@colls) { 1492 # not referenced in the local tlpdb, so try the remote here, too 1493 if (!$remotetlpdb) { 1494 init_tlmedia_or_die(); 1495 } 1496 @colls = $remotetlpdb->needed_by($pkg); 1497 } 1498 } 1499 # some packages might depend on other packages, so do not 1500 # include arbitrary package in the list of collections, but 1501 # only collectons: 1502 @colls = grep {m;^collection-;} @colls; 1503 print "package: ", $tlp->name, "\n"; 1504 print "repository: ", $source_found, "\n" if (defined($source_found)); 1505 print "category: ", $tlp->category, "\n"; 1506 print "shortdesc: ", $tlp->shortdesc, "\n" if ($tlp->shortdesc); 1507 print "longdesc: ", $tlp->longdesc, "\n" if ($tlp->longdesc); 1508 print "installed: ", ($installed ? "Yes" : "No"), "\n"; 1509 print "revision: ", $tlp->revision, "\n" if ($installed); 1510 # print out sizes 1511 my $sizestr = ""; 1512 my $srcsize = $tlp->srcsize * $TeXLive::TLConfig::BlockSize; 1513 $sizestr = sprintf("%ssrc: %dk", $sizestr, int($srcsize / 1024) + 1) 1514 if ($srcsize > 0); 1515 my $docsize = $tlp->docsize * $TeXLive::TLConfig::BlockSize; 1516 $sizestr .= sprintf("%sdoc: %dk", 1517 ($sizestr ? ", " : ""), int($docsize / 1024) + 1) 1518 if ($docsize > 0); 1519 my $runsize = $tlp->runsize * $TeXLive::TLConfig::BlockSize; 1520 $sizestr .= sprintf("%srun: %dk", 1521 ($sizestr ? ", " : ""), int($runsize / 1024) + 1) 1522 if ($runsize > 0); 1523 # check for .ARCH expansions 1524 my $do_archs = 0; 1525 for my $d ($tlp->depends) { 1526 if ($d =~ m/^(.*)\.ARCH$/) { 1527 $do_archs = 1; 1528 last; 1529 } 1530 } 1531 if ($do_archs) { 1532 my @a = $localtlpdb->available_architectures; 1533 my %binsz = %{$tlp->binsize}; 1534 my $binsize = 0; 1535 for my $a (@a) { 1536 $binsize += $binsz{$a} if defined($binsz{$a}); 1537 my $atlp = $tlpdb->get_package($tlp->name . ".$a"); 1538 if (!$atlp) { 1539 tlwarn("$prg: cannot find depending package" . $tlp->name . ".$a\n"); 1540 $ret |= $F_WARNING; 1541 next; 1542 } 1543 my %abinsz = %{$atlp->binsize}; 1544 $binsize += $abinsz{$a} if defined($abinsz{$a}); 1545 } 1546 $binsize *= $TeXLive::TLConfig::BlockSize; 1547 $sizestr .= sprintf("%sbin: %dk", 1548 ($sizestr ? ", " : ""), int($binsize / 1024) + 1) 1549 if ($binsize > 0); 1550 } 1551 print "sizes: ", $sizestr, "\n"; 1552 print "relocatable: ", ($tlp->relocated ? "Yes" : "No"), "\n"; 1553 print "cat-version: ", $tlp->cataloguedata->{'version'}, "\n" 1554 if $tlp->cataloguedata->{'version'}; 1555 print "cat-date: ", $tlp->cataloguedata->{'date'}, "\n" 1556 if $tlp->cataloguedata->{'date'}; 1557 print "cat-license: ", $tlp->cataloguedata->{'license'}, "\n" 1558 if $tlp->cataloguedata->{'license'}; 1559 print "collection: ", @colls, "\n" if (@colls); 1560 if ($opts{"list"}) { 1561 if ($tlp->category eq "Collection" || $tlp->category eq "Scheme") { 1562 # in the case of collections of schemes we list the deps 1563 my @deps = $tlp->depends; 1564 if (@deps) { 1565 print "depends:\n"; 1566 for my $d (@deps) { 1567 print "\t$d\n"; 1568 } 1569 } 1570 } 1571 print "Included files, by type:\n"; 1572 # if the package has a .ARCH dependency we also list the files for 1573 # those packages 1574 my @todo = $tlpdb->expand_dependencies("-only-arch", $tlpdb, ($pkg)); 1575 for my $d (sort @todo) { 1576 my $foo = $tlpdb->get_package($d); 1577 if (!$foo) { 1578 tlwarn ("\nShould not happen, no dependent package $d\n"); 1579 $ret |= $F_WARNING; 1580 next; 1581 } 1582 if ($d ne $pkg) { 1583 print "depending package $d:\n"; 1584 } 1585 if ($foo->runfiles) { 1586 print "run files:\n"; 1587 for my $f (sort $foo->runfiles) { print " $f\n"; } 1588 } 1589 if ($foo->srcfiles) { 1590 print "source files:\n"; 1591 for my $f (sort $foo->srcfiles) { print " $f\n"; } 1592 } 1593 if ($foo->docfiles) { 1594 print "doc files:\n"; 1595 for my $f (sort $foo->docfiles) { 1596 print " $f"; 1597 my $dfd = $foo->docfiledata; 1598 if (defined($dfd->{$f})) { 1599 for my $k (keys %{$dfd->{$f}}) { 1600 print " $k=\"", $dfd->{$f}->{$k}, '"'; 1601 } 1602 } 1603 print "\n"; 1604 } 1605 } 1606 # in case we have them 1607 if ($foo->allbinfiles) { 1608 print "bin files (all platforms):\n"; 1609 for my $f (sort $foo->allbinfiles) { print " $f\n"; } 1610 } 1611 } 1612 } 1613 print "\n"; 1614 } 1615 return ($ret); 1616} 1617 1618 1619# SEARCH 1620# 1621sub action_search { 1622 my ($r) = @ARGV; 1623 my $tlpdb; 1624 # check the arguments 1625 my $search_type_nr = 0; 1626 $search_type_nr++ if $opts{"file"}; 1627 $search_type_nr++ if $opts{"all"}; 1628 if ($search_type_nr > 1) { 1629 tlwarn("$prg: please specify only one thing to search for\n"); 1630 return ($F_ERROR); 1631 } 1632 # 1633 if (!defined($r) || !$r) { 1634 tlwarn("$prg: nothing to search for.\n"); 1635 return ($F_ERROR); 1636 } 1637 1638 init_local_db(); 1639 if ($opts{"global"}) { 1640 init_tlmedia_or_die(); 1641 $tlpdb = $remotetlpdb; 1642 } else { 1643 $tlpdb = $localtlpdb; 1644 } 1645 1646 my ($foundfile, $founddesc) = search_tlpdb($tlpdb, $r, 1647 $opts{'file'} || $opts{'all'}, 1648 (!$opts{'file'} || $opts{'all'}), 1649 $opts{'word'}); 1650 1651 print $founddesc; 1652 print $foundfile; 1653 1654 return ($F_OK | $F_NOPOSTACTION); 1655} 1656 1657sub search_tlpdb { 1658 my ($tlpdb, $what, $dofile, $dodesc, $inword) = @_; 1659 my $retfile = ''; 1660 my $retdesc = ''; 1661 foreach my $pkg ($tlpdb->list_packages) { 1662 my $tlp = $tlpdb->get_package($pkg); 1663 1664 # --file or --all -> search (full) file names 1665 if ($dofile) { 1666 my @ret = search_pkg_files($tlp, $what); 1667 if (@ret) { 1668 $retfile .= "$pkg:\n"; 1669 foreach (@ret) { 1670 $retfile .= "\t$_\n"; 1671 } 1672 } 1673 } 1674 # 1675 # no options or --all -> search package names/descriptions 1676 if ($dodesc) { 1677 next if ($pkg =~ m/\./); 1678 my $matched = search_pkg_desc($tlp, $what, $inword); 1679 $retdesc .= "$matched\n" if ($matched); 1680 } 1681 } 1682 return($retfile, $retdesc); 1683} 1684 1685sub search_pkg_desc { 1686 my ($tlp, $what, $inword) = @_; 1687 my $pkg = $tlp->name; 1688 my $t = "$pkg\n"; 1689 $t = $t . $tlp->shortdesc . "\n" if (defined($tlp->shortdesc)); 1690 $t = $t . $tlp->longdesc . "\n" if (defined($tlp->longdesc)); 1691 my $pat = $what; 1692 $pat = '\W' . $what . '\W' if ($inword); 1693 my $matched = ""; 1694 if ($t =~ m/$pat/i) { 1695 my $shortdesc = $tlp->shortdesc || ""; 1696 $matched .= "$pkg - $shortdesc"; 1697 } 1698 return $matched; 1699} 1700 1701sub search_pkg_files { 1702 my ($tlp, $what) = @_; 1703 my @files = $tlp->all_files; 1704 if ($tlp->relocated) { 1705 for (@files) { s:^$RelocPrefix/:$RelocTree/:; } 1706 } 1707 my @ret = grep(m;$what;, @files); 1708 return @ret; 1709} 1710 1711# RESTORE 1712# 1713# read the directory and check what files/package/rev are available 1714# for restore 1715sub get_available_backups { 1716 my $bd = shift; 1717 my $do_stat = shift; 1718 # initialize the hash(packages) of hash(revisions) 1719 my %backups; 1720 opendir (DIR, $bd) || die "opendir($bd) failed: $!"; 1721 my @dirents = readdir (DIR); 1722 closedir (DIR) || warn "closedir($bd) failed: $!"; 1723 # 1724 # see below for explanation, this has effects only on W32 1725 my $oldwsloppy = ${^WIN32_SLOPPY_STAT}; 1726 ${^WIN32_SLOPPY_STAT} = 1; 1727 # 1728 for my $dirent (@dirents) { 1729 next if (-d $dirent); 1730 next if ($dirent !~ m/^(.*)\.r([0-9]+)\.tar\.xz$/); 1731 if (!$do_stat) { 1732 $backups{$1}->{$2} = 1; 1733 next; 1734 } 1735 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, 1736 $atime,$mtime,$ctime,$blksize,$blocks) = stat("$bd/$dirent"); 1737 # times: as we want to be portable we try the following times: 1738 # - first choice is ctime which hopefully works nicely 1739 # - on UFS (OSX) ctime is not supported, so use mtime 1740 # furthermore, if we are on W32 we want to be fast and make only 1741 # a sloppy stat 1742 # for more on that please see man perlport 1743 my $usedt = $ctime; 1744 if (!$usedt) { 1745 # can happen on 1746 $usedt = $mtime; 1747 } 1748 if (!$usedt) { 1749 # stat failed, set key to -1 as a sign that there is a backup 1750 # but we cannot stat it 1751 $backups{$1}->{$2} = -1; 1752 } else { 1753 $backups{$1}->{$2} = $usedt; 1754 } 1755 } 1756 # reset the original value of the w32 sloppy mode for stating files 1757 ${^WIN32_SLOPPY_STAT} = $oldwsloppy; 1758 return %backups; 1759} 1760 1761sub restore_one_package { 1762 my ($pkg, $rev, $bd) = @_; 1763 # first remove the package, then reinstall it 1764 # this way we get rid of useless files 1765 my $restore_file = "$bd/${pkg}.r${rev}.tar.xz"; 1766 if (! -r $restore_file) { 1767 tlwarn("Cannot read $restore_file, no action taken\n"); 1768 return ($F_ERROR); 1769 } 1770 $localtlpdb->remove_package($pkg); 1771 TeXLive::TLPDB->_install_package($restore_file , 0, [] ,$localtlpdb); 1772 logpackage("restore: $pkg ($rev)"); 1773 # now we have to read the .tlpobj file and add it to the DB 1774 my $tlpobj = TeXLive::TLPOBJ->new; 1775 $tlpobj->from_file($localtlpdb->root . "/tlpkg/tlpobj/$pkg.tlpobj"); 1776 $localtlpdb->add_tlpobj($tlpobj); 1777 TeXLive::TLUtils::announce_execute_actions("enable", 1778 $localtlpdb->get_package($pkg)); 1779 $localtlpdb->save; 1780 # TODO_ERROCHECKING we should check the return values of the 1781 # various calls above 1782 return ($F_OK); 1783} 1784 1785sub check_backupdir_selection { 1786 my $warntext = ""; 1787 if ($opts{"backupdir"}) { 1788 my $ob = abs_path($opts{"backupdir"}); 1789 $ob && ($opts{"backupdir"} = $ob); 1790 if (! -d $opts{"backupdir"}) { 1791 $warntext .= "$prg: backupdir argument\n"; 1792 $warntext .= " $opts{'backupdir'}\n"; 1793 $warntext .= "is not a directory.\n"; 1794 return ($F_ERROR, $warntext); 1795 } 1796 } else { 1797 # no argument, check for presence in TLPDB 1798 init_local_db(1); 1799 $opts{"backupdir"} = norm_tlpdb_path($localtlpdb->option("backupdir")); 1800 if (!$opts{"backupdir"}) { 1801 return (0, "$prg: No way to determine backupdir.\n"); 1802 } 1803 # we are still here, there is something set in tlpdb 1804 my $ob = abs_path($opts{"backupdir"}); 1805 $ob && ($opts{"backupdir"} = $ob); 1806 if (! -d $opts{"backupdir"}) { 1807 $warntext = "$prg: backupdir as set in tlpdb\n"; 1808 $warntext .= " $opts{'backupdir'}\n"; 1809 $warntext .= "is not a directory.\n"; 1810 return ($F_ERROR, $warntext); 1811 } 1812 } 1813 return $F_OK; 1814} 1815 1816sub action_restore { 1817 # tlmgr restore [--backupdir dir] --all 1818 # restores of all packages found in backupdir the latest version 1819 # tlmgr restore --backupdir dir 1820 # lists all packages with all revisions 1821 # tlmgr restore --backupdir dir pkg 1822 # lists all revisions of pkg 1823 # tlmgr restore --backupdir dir pkg rev 1824 # restores pkg to revision rev 1825 # check the backup dir argument 1826 1827 { 1828 my ($a, $b) = check_backupdir_selection(); 1829 if ($a & $F_ERROR) { 1830 # in all these cases we want to terminate in the non-gui mode 1831 tlwarn($b); 1832 return ($F_ERROR); 1833 } 1834 } 1835 info("$prg restore: dry run, no changes will be made\n") if $opts{"dry-run"}; 1836 1837 # initialize the hash(packages) of hash(revisions), do stat files! (the 1) 1838 my %backups = get_available_backups($opts{"backupdir"}, 1); 1839 my ($pkg, $rev) = @ARGV; 1840 if (defined($pkg) && $opts{"all"}) { 1841 tlwarn("$prg: Specify either --all or individual package(s) ($pkg)\n"); 1842 tlwarn("$prg: to restore, not both. Terminating.\n"); 1843 return ($F_ERROR); 1844 } 1845 if ($opts{"all"}) { 1846 init_local_db(1); 1847 return ($F_ERROR) if !check_on_writable(); 1848 if (!$opts{"force"}) { 1849 print "Do you really want to restore all packages to the latest revision found in\n\t$opts{'backupdir'}\n===> (y/N): "; 1850 my $yesno = <STDIN>; 1851 if ($yesno !~ m/^y(es)?$/i) { 1852 print "Ok, cancelling the restore!\n"; 1853 return ($F_OK | $F_NOPOSTACTION); 1854 } 1855 } 1856 for my $p (sort keys %backups) { 1857 my @tmp = sort {$b <=> $a} (keys %{$backups{$p}}); 1858 my $rev = $tmp[0]; 1859 print "Restoring $p, $rev from $opts{'backupdir'}/${p}.r${rev}.tar.xz\n"; 1860 if (!$opts{"dry-run"}) { 1861 # first remove the package, then reinstall it 1862 # this way we get rid of useless files 1863 # TODO_ERRORCHECK needs check for return values!! 1864 restore_one_package($p, $rev, $opts{"backupdir"}); 1865 } 1866 } 1867 # localtlpdb already saved, so we are finished 1868 return ($F_OK); 1869 } 1870 # 1871 # intermediate sub 1872 sub report_backup_revdate { 1873 my $p = shift; 1874 my %revs = @_; 1875 my @rs = sort {$b <=> $a} (keys %revs); 1876 for my $rs (@rs) { 1877 my $dstr; 1878 if ($revs{$rs} == -1) { 1879 $dstr = "unknown"; 1880 } else { 1881 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = 1882 localtime($revs{$rs}); 1883 # localtime returns dates starting from 1900, and the month is 0..11 1884 $dstr = sprintf "%04d-%02d-%02d %02d:%02d", 1885 $year+1900, $mon+1, $mday, $hour, $min; 1886 } 1887 print "$rs ($dstr) "; 1888 } 1889 } 1890 # end sub 1891 if (!defined($pkg)) { 1892 if (keys %backups) { 1893 print "Available backups:\n"; 1894 foreach my $p (sort keys %backups) { 1895 print "$p: "; 1896 report_backup_revdate($p, %{$backups{$p}}); 1897 print "\n"; 1898 } 1899 } else { 1900 print "No backups available in $opts{'backupdir'}\n"; 1901 } 1902 return ($F_OK | $F_NOPOSTACTION); 1903 } 1904 if (!defined($rev)) { 1905 print "Available backups for $pkg: "; 1906 report_backup_revdate($pkg, %{$backups{$pkg}}); 1907 print "\n"; 1908 return ($F_OK | $F_NOPOSTACTION); 1909 } 1910 # we did arrive here, so we try to restore ... 1911 if (defined($backups{$pkg}->{$rev})) { 1912 return if !check_on_writable(); 1913 if (!$opts{"force"}) { 1914 print "Do you really want to restore $pkg to revision $rev (y/N): "; 1915 my $yesno = <STDIN>; 1916 if ($yesno !~ m/^y(es)?$/i) { 1917 print "Ok, cancelling the restore!\n"; 1918 return ($F_OK | $F_NOPOSTACTION); 1919 } 1920 } 1921 print "Restoring $pkg, $rev from $opts{'backupdir'}/${pkg}.r${rev}.tar.xz\n"; 1922 if (!$opts{"dry-run"}) { 1923 init_local_db(1); 1924 # first remove the package, then reinstall it 1925 # this way we get rid of useless files 1926 restore_one_package($pkg, $rev, $opts{"backupdir"}); 1927 } 1928 # TODO_ERRORCHECKING check return value of restore_one_package 1929 return ($F_OK); 1930 } else { 1931 print "revision $rev for $pkg is not present in $opts{'backupdir'}\n"; 1932 return ($F_ERROR); 1933 } 1934} 1935 1936sub action_backup { 1937 init_local_db(1); 1938 # --clean argument 1939 # can be either -1 ... don't clean 1940 # 0 ... remove all backups 1941 # N ... keep only N backups 1942 # that parallels the value of autoclean in the configuration 1943 # we have to be careful, because if simply --clean is given, we should 1944 # check for the value saved in the tlpdb, and if that is not present 1945 # do nothing. 1946 # We have set clean to clean:-99 which makes -99 the default value 1947 # if only --clean is given without any argument 1948 # !defined($opts{"clean"}) -> no --clean given 1949 # $opts{"clean"} = -99 -> --clean without argument given, check tlpdb 1950 # $opts{"clean"} = -1, 0, N -> --clean=N given, check argument 1951 # 1952 my $clean_mode = 0; 1953 $clean_mode = 1 if defined($opts{"clean"}); 1954 if ($clean_mode) { 1955 if ($opts{"clean"} == -99) { 1956 # we need to check the tlpdb 1957 my $tlpdb_option = $localtlpdb->option("autobackup"); 1958 if (!defined($tlpdb_option)) { 1959 tlwarn ("--clean given without an argument, but no default clean\n"); 1960 tlwarn ("mode specified in the tlpdb.\n"); 1961 return ($F_ERROR); 1962 } 1963 $opts{"clean"} = $tlpdb_option; 1964 } 1965 # now $opts{"clean"} is something, but maybe not a number, check for 1966 # validity 1967 if ($opts{"clean"} =~ m/^(-1|[0-9]+)$/) { 1968 # get rid of leading zeros etc etc 1969 $opts{"clean"} = $opts{"clean"} + 0; 1970 } else { 1971 tlwarn ("clean mode as specified on the command line or as given by default\n"); 1972 tlwarn ("must be an integer larger or equal than -1, terminating.\n"); 1973 return($F_ERROR); 1974 } 1975 } 1976 # check the backup dir argument 1977 { 1978 my ($a, $b) = check_backupdir_selection(); 1979 if ($a & $F_ERROR) { 1980 # in all these cases we want to terminate in the non-gui mode 1981 tlwarn($b); 1982 return($F_ERROR); 1983 } 1984 } 1985 1986 # if we do --clean --all we also want to remove packages that 1987 # are not present anymore in the tlpdb, so use the readdir mode 1988 # to determine backups 1989 if ($opts{"all"} && $clean_mode) { 1990 # initialize the hash(packages) of hash(revisions) 1991 # no need to stat the files 1992 my %backups = get_available_backups($opts{"backupdir"}, 0); 1993 init_local_db(1); 1994 for my $p (sort keys %backups) { 1995 clear_old_backups ($p, $opts{"backupdir"}, $opts{"clean"}, $opts{"dry-run"}); 1996 } 1997 return ($F_OK | $F_NOPOSTACTION); 1998 } 1999 2000 # in case we are not cleaning or cleaning only specific packages 2001 # use the one-by-one mode 2002 my @todo; 2003 if ($opts{"all"}) { 2004 @todo = $localtlpdb->list_packages; 2005 } else { 2006 @todo = @ARGV; 2007 @todo = $localtlpdb->expand_dependencies("-only-arch", $localtlpdb, @todo); 2008 } 2009 if (!@todo) { 2010 printf "tlmgr backup takes either a list of packages or --all\n"; 2011 return ($F_ERROR); 2012 } 2013 foreach my $pkg (@todo) { 2014 if ($clean_mode) { 2015 clear_old_backups ($pkg, $opts{"backupdir"}, $opts{"clean"}, $opts{"dry-run"}); 2016 } else { 2017 my $tlp = $localtlpdb->get_package($pkg); 2018 info("saving current status of $pkg to $opts{'backupdir'}/${pkg}.r" . 2019 $tlp->revision . ".tar.xz\n"); 2020 if (!$opts{"dry-run"}) { 2021 $tlp->make_container("xz", $localtlpdb->root, 2022 $opts{"backupdir"}, "${pkg}.r" . $tlp->revision); 2023 } 2024 } 2025 } 2026 # TODO_ERRORCHECKING neets checking of the above 2027 return ($F_OK); 2028} 2029 2030# ===================================================================== 2031# INFRASTRUCTURE UPDATE ON WINDOWS 2032# ===================================================================== 2033# Infrastructure files cannot be updated directly from the 2034# tlmgr.pl script due to file locking problem on Windows - files that 2035# are in use (either open or executing) cannot be removed or replaced. 2036# For that reason the update process is performed by a batch script 2037# outside of tlmgr.pl. 2038# There are three pieces involved in the update: tlmgr.bat 2039# launcher, write_w32_updater subroutine below and a batch 2040# updater script. Their roles are as follows: 2041# * tlmgr.bat is a watchdog, it launches tlmgr.pl and watches for 2042# the updater script that is to be executed. If the updater script 2043# exists before tlmgr.pl is launched, it will be removed or 2044# tlmgr.bat will abort if it fails to do so. This means that the 2045# updater script has to be created by the current invocation of 2046# tlmgr.pl. Futhermore, the updater script is renamed from 2047# updater-w32 to updater-w32.bat just before it is run, and thus 2048# it can be executed only once. 2049# * write_w32_updater subroutine in tlmgr.pl prepares the update 2050# and writes the updater script. Packages in .xz archives are 2051# dowloaded/copied and uncompressed to .tar files. Also .tar 2052# backups of the current packages are made. If everything is 2053# successful, the update script is created from the template. 2054# Otherwise the update is aborted. 2055# * updater-w32[.bat] batch script, triggers and executes the actual 2056# update. It first restarts itself in a separate instance of cmd.exe 2057# (and in a new console window in gui mode) and runs the update 2058# from there. The update is run with echo on and all output is 2059# logged to a file (or stderr in verbose mode). After successful 2060# infrastructure update, tlmgr is optionally restarted if update 2061# of other packages is asked for. 2062# The infrastructure update itself proceeds as follows: 2063# (1) untar all package archives 2064# (2) include .tlpobj files into tlpdb 2065# (3) print update info to console 2066# Any error during (1) or (2) triggers the rollback sequence: 2067# (1) print failed update info to console 2068# (2) untar all package backups 2069# (3) include .tlpobj files (from backup) into tlpdb 2070# (4) print restore info to console 2071# Any error during (2) or (3) and we go into panic state. At this 2072# point there is no guarantee that the installation is still working. 2073# There is not much we can do but to print failed restore info and 2074# give instructions to download and run 'update-tlmgr-latest.exe' 2075# to repair the installation. 2076# ===================================================================== 2077# 2078sub write_w32_updater { 2079 my ($restart_tlmgr, $ref_files_to_be_removed, @w32_updated) = @_; 2080 my @infra_files_to_be_removed = @$ref_files_to_be_removed; 2081 # TODO do something with these files TODO 2082 my $media = $remotetlpdb->media; 2083 # we have to download/copy also the src/doc files if necessary! 2084 my $container_src_split = $remotetlpdb->config_src_container; 2085 my $container_doc_split = $remotetlpdb->config_doc_container; 2086 # get options about src/doc splitting from $totlpdb 2087 # TT: should we use local options to decide about install of doc & src? 2088 my $opt_src = $localtlpdb->option("install_srcfiles"); 2089 my $opt_doc = $localtlpdb->option("install_docfiles"); 2090 my $root = $localtlpdb->root; 2091 my $temp = "$root/tlpkg/temp"; 2092 TeXLive::TLUtils::mkdirhier($temp); 2093 tlwarn("Backup option not implemented for infrastructure update.\n") if ($opts{"backup"}); 2094 if ($media eq 'local_uncompressed') { 2095 tlwarn("Creating updater from local_uncompressed currently not implemented!\n"); 2096 tlwarn("But it should not be necessary!\n"); 2097 return 1; # abort 2098 } 2099 my (@upd_tar, @upd_tlpobj, @upd_info, @rst_tar, @rst_tlpobj, @rst_info); 2100 foreach my $pkg (@w32_updated) { 2101 my $repo; 2102 my $mediatlp; 2103 if ($media eq "virtual") { 2104 my $maxtlpdb; 2105 (undef, undef, $mediatlp, $maxtlpdb) = 2106 $remotetlpdb->virtual_candidate($pkg); 2107 $repo = $maxtlpdb->root . "/$Archive"; 2108 # update the media type of the used tlpdb 2109 # otherwise later on we stumble when preparing the updater 2110 $media = $maxtlpdb->media; 2111 } else { 2112 $mediatlp = $remotetlpdb->get_package($pkg); 2113 $repo = $remotetlpdb->root . "/$Archive"; 2114 } 2115 my $localtlp = $localtlpdb->get_package($pkg); 2116 my $oldrev = $localtlp->revision; 2117 my $newrev = $mediatlp->revision; 2118 # we do install documenation files for category Documentation even if 2119 # option("install_docfiles") is false 2120 my $opt_real_doc = ($mediatlp->category =~ m/documentation/i) ? 1 : $opt_doc; 2121 my @pkg_parts = ($pkg); 2122 push(@pkg_parts, "$pkg.source") if ($container_src_split && $opt_src && $mediatlp->srcfiles); 2123 push(@pkg_parts, "$pkg.doc") if ($container_doc_split && $opt_real_doc && $mediatlp->docfiles); 2124 foreach my $pkg_part (@pkg_parts) { 2125 push (@upd_tar, "$pkg_part.tar"); 2126 push (@upd_tlpobj, "tlpkg\\tlpobj\\$pkg_part.tlpobj"); 2127 } 2128 push (@upd_info, "$pkg ^($oldrev -^> $newrev^)"); 2129 push (@rst_tar, "__BACKUP_$pkg.r$oldrev.tar"); 2130 push (@rst_tlpobj, "tlpkg\\tlpobj\\$pkg.tlpobj"); 2131 push (@rst_info, "$pkg ^($oldrev^)"); 2132 next if ($opts{"dry-run"}); 2133 # create backup; make_container expects file name in a format: some-name.r[0-9]+ 2134 my ($size, $md5, $fullname) = $localtlp->make_container("tar", $root, $temp, "__BACKUP_$pkg.r$oldrev"); 2135 if ($size <= 0) { 2136 tlwarn("Creation of backup container of $pkg failed.\n"); 2137 return 1; # backup failed? abort 2138 } 2139 foreach my $pkg_part (@pkg_parts) { 2140 if ($media eq 'local_compressed') { 2141 copy("$repo/$pkg_part.tar.xz", "$temp"); 2142 } else { # net 2143 TeXLive::TLUtils::download_file("$repo/$pkg_part.tar.xz", "$temp/$pkg_part.tar.xz"); 2144 } 2145 # now we should have the file present 2146 if (!-r "$temp/$pkg_part.tar.xz") { 2147 tlwarn("Couldn't get $pkg_part.tar.xz, that is bad\n"); 2148 return 1; # abort 2149 } 2150 # unpack xz archive 2151 my $sysret = system("$::progs{'xzdec'} < \"$temp/$pkg_part.tar.xz\" > \"$temp/$pkg_part.tar\""); 2152 if ($sysret) { 2153 tlwarn("Couldn't unpack $pkg_part.tar.xz\n"); 2154 return 1; # unpack failed? abort 2155 } 2156 unlink("$temp/$pkg_part.tar.xz"); # we don't need that archive anymore 2157 } 2158 } 2159 2160 # prepare updater script 2161 my $respawn_cmd = "cmd.exe /e:on/v:off/d/c"; 2162 $respawn_cmd = "start /wait $respawn_cmd" if ($::gui_mode); 2163 my $gui_pause = ($::gui_mode ? "pause" : "rem"); 2164 my $upd_log = ($::opt_verbosity ? "STDERR" : '"%~dp0update-self.log"'); 2165 my $std_handles_redir = ($::opt_verbosity ? "1^>^&2" : "2^>$upd_log 1^>^&2"); 2166 my $pkg_log = ($packagelogfile ? "\"$packagelogfile\"" : "nul"); 2167 my $post_update_msg = "You may now close this window."; 2168 my $rerun_tlmgr = "rem"; 2169 if ($restart_tlmgr) { 2170 $post_update_msg = "About to restart tlmgr to complete update ..."; 2171 # quote all arguments for tlmgr restart in case of spaces 2172 $rerun_tlmgr = join (" ", map ("\"$_\"", @::SAVEDARGV) ); 2173 $rerun_tlmgr = "if not errorlevel 1 tlmgr.bat $rerun_tlmgr"; 2174 } 2175 my $batch_script = <<"EOF"; 2176:: This file is part of an automated update process of 2177:: infrastructure files and should not be run standalone. 2178:: For more details about the update process see comments 2179:: in tlmgr.pl (subroutine write_w32_updater). 2180 2181 if [%1]==[:doit] goto :doit 2182 if not exist "%~dp0tar.exe" goto :notar 2183 $respawn_cmd call "%~f0" :doit $std_handles_redir 2184 $rerun_tlmgr 2185 goto :eof 2186 2187:notar 2188 echo %~nx0: cannot run without "%~dp0tar.exe" 2189 findstr "^::" <"%~f0" 2190 exit /b 1 2191 2192:doit 2193 set prompt=TL\$G 2194 title TeX Live Manager $TeXLive::TLConfig::ReleaseYear Update 2195 set PERL5LIB=$root/tlpkg/tlperl/lib 2196 >con echo DO NOT CLOSE THIS WINDOW! 2197 >con echo TeX Live infrastructure update in progress ... 2198 >con echo Detailed command logging to $upd_log 2199 chdir /d "%~dp0.." 2200 if not errorlevel 1 goto :update 2201 >con echo Could not change working directory to "%~dp0.." 2202 >con echo Aborting infrastructure update, no changes have been made. 2203 >con $gui_pause 2204 exit /b 1 2205 2206:update 2207 for %%I in (@upd_tar) do ( 2208 temp\\tar.exe -xmf temp\\%%I 2209 if errorlevel 1 goto :rollback 2210 ) 2211 tlpkg\\tlperl\\bin\\perl.exe .\\texmf-dist\\scripts\\texlive\\tlmgr.pl _include_tlpobj @upd_tlpobj 2212 if errorlevel 1 goto :rollback 2213 >>$pkg_log echo [%date% %time%] self update: @upd_info 2214 >con echo self update: @upd_info 2215 del "%~dp0*.tar" "%~dp0tar.exe" 2216 >con echo Infrastructure update finished successfully. 2217 >con echo $post_update_msg 2218 >con $gui_pause 2219 exit /b 0 2220 2221:rollback 2222 >>$pkg_log echo [%date% %time%] failed self update: @upd_info 2223 >con echo failed self update: @upd_info 2224 >con echo Rolling back to previous version ... 2225 for %%I in (@rst_tar) do ( 2226 temp\\tar.exe -xmf temp\\%%I 2227 if errorlevel 1 goto :panic 2228 ) 2229 tlpkg\\tlperl\\bin\\perl.exe .\\texmf-dist\\scripts\\texlive\\tlmgr.pl _include_tlpobj @rst_tlpobj 2230 if errorlevel 1 goto :panic 2231 >>$pkg_log echo [%date% %time%] self restore: @rst_info 2232 >con echo self restore: @rst_info 2233 >con echo Infrastructure update failed. Previous version has been restored. 2234 >con $gui_pause 2235 exit /b 1 2236 2237:panic 2238 >>$pkg_log echo [%date% %time%] failed self restore: @rst_info 2239 >con echo failed self restore: @rst_info 2240 >con echo FATAL ERROR: 2241 >con echo Infrastructure update failed and backup recovery failed too. 2242 >con echo To repair your TeX Live installation download and run: 2243 >con echo $TeXLive::TLConfig::TeXLiveURL/update-tlmgr-latest.exe 2244 >con $gui_pause 2245 exit /b 666 2246EOF 2247 2248 ddebug("\n:: UPDATER BATCH SCRIPT ::\n$batch_script\n:: END OF FILE ::\n"); 2249 if ($opts{"dry-run"}) { 2250 my $upd_info = "self update: @upd_info"; 2251 $upd_info =~ s/\^//g; 2252 info($upd_info); 2253 } else { 2254 copy("$root/tlpkg/installer/tar.exe", "$temp"); 2255 # make sure copied tar is working 2256 if (system("\"$temp/tar.exe\" --version >nul")) { 2257 tlwarn("Could not copy tar.exe, that is bad.\n"); 2258 return 1; # abort 2259 } 2260 open UPDATER, ">$temp/updater-w32" or die "Cannot create updater script: $!"; 2261 print UPDATER $batch_script; 2262 close UPDATER; 2263 } 2264 return 0; 2265} 2266 2267 2268# UPDATE 2269 2270# compute the list of auto-install, auto-remove, forcibly-removed 2271# packages from the list of packages to be installed 2272# the list of packages passed in is already expanded 2273sub auto_remove_install_force_packages { 2274 my @todo = @_; 2275 my %removals_full; 2276 my %forcermpkgs_full; 2277 my %newpkgs_full; 2278 my %new_pkgs_due_forcerm_coll; 2279 # check for new/removed/forcibly removed packages. 2280 # we start from the list of installed collections in the local tlpdb 2281 # which are also present in the remote database 2282 # and expand this list once with expand_dependencies in the local tlpdb 2283 # and once in the tlmedia tlpdb. Then we compare the lists 2284 # let A = set of local expansions 2285 # B = set of remote expansions 2286 # then we should(?) have 2287 # B \ A set of new packages 2288 # A \ B set of packages removed on the server 2289 # A \cup B set of packages which should be checked for forcible removal 2290 # 2291 my @all_schmscolls = (); 2292 for my $p ($localtlpdb->schemes) { 2293 push (@all_schmscolls, $p) if defined($remotetlpdb->get_package($p)); 2294 } 2295 for my $p ($localtlpdb->collections) { 2296 push (@all_schmscolls, $p) if defined($remotetlpdb->get_package($p)); 2297 } 2298 my @localexpansion_full = 2299 $localtlpdb->expand_dependencies($localtlpdb, @all_schmscolls); 2300 my @remoteexpansion_full = 2301 $remotetlpdb->expand_dependencies($localtlpdb, @all_schmscolls); 2302 2303 # compute new/remove/forcerm based on the full expansions 2304 for my $p (@remoteexpansion_full) { 2305 $newpkgs_full{$p} = 1; 2306 } 2307 for my $p (@localexpansion_full) { 2308 delete($newpkgs_full{$p}); 2309 $removals_full{$p} = 1; 2310 } 2311 for my $p (@remoteexpansion_full) { 2312 delete($removals_full{$p}); 2313 } 2314 # in a first round we check only for forcibly removed collections 2315 # this is necessary to NOT declare a package that is contained 2316 # in a forcibly removed collections as auto-install since it appears 2317 # in the @remoteexpansion_full, but not in @localexpansion_full. 2318 for my $p (@localexpansion_full) { 2319 # intersection, don't check A\B and B\A 2320 next if $newpkgs_full{$p}; 2321 next if $removals_full{$p}; 2322 my $remotetlp = $remotetlpdb->get_package($p); 2323 if (!defined($remotetlp)) { 2324 tlwarn("Strange, $p mentioned but not found anywhere!\n"); 2325 next; 2326 } 2327 next if ($remotetlp->category ne "Collection"); 2328 my $tlp = $localtlpdb->get_package($p); 2329 if (!defined($tlp)) { 2330 if ($opts{"reinstall-forcibly-removed"}) { 2331 $newpkgs_full{$p} = 1; 2332 } else { 2333 $forcermpkgs_full{$p} = 1; 2334 } 2335 } 2336 } 2337 # now we have in %forcermpkgs_full only collections that have been 2338 # forcibly removed. Again, expand those against the remote tlpdb 2339 # and remove the expanded packages from the list of localexpansion. 2340 my @pkgs_from_forcerm_colls = 2341 $remotetlpdb->expand_dependencies($localtlpdb, keys %forcermpkgs_full); 2342 # 2343 # the package in @pkgs_from_forcerm_colls would be auto-installed, so 2344 # check for that: 2345 for my $p (keys %newpkgs_full) { 2346 if (member($p, @pkgs_from_forcerm_colls)) { 2347 delete $newpkgs_full{$p}; 2348 $new_pkgs_due_forcerm_coll{$p} = 1; 2349 } 2350 } 2351 # 2352 # now create the final list of forcerm packages by checking against 2353 # all packages 2354 for my $p (@localexpansion_full) { 2355 # intersection, don't check A\B and B\A 2356 next if $newpkgs_full{$p}; 2357 next if $removals_full{$p}; 2358 my $tlp = $localtlpdb->get_package($p); 2359 if (!defined($tlp)) { 2360 if ($opts{"reinstall-forcibly-removed"}) { 2361 $newpkgs_full{$p} = 1; 2362 } else { 2363 $forcermpkgs_full{$p} = 1; 2364 } 2365 } 2366 } 2367 # 2368 # for some packages (texworks, psview, ...) we only have w32 packages 2369 # in the repository, but it is possible that alternative repositories 2370 # ship binaries for some platforms (like texworks for linux on tlcontrib) 2371 # currently updating from tlnet will remove these alternative .ARCH 2372 # packages because they are not listed anywhere locally, so they 2373 # are considered as disappearing. 2374 # We remove here packages PKG.ARCH if the main package PKG is found 2375 # here and is *not* disappearing, from the removal hash 2376 for my $p (keys %removals_full) { 2377 if ($p =~ m/^([^.]*)\./) { 2378 my $mpkg = $1; 2379 if (!defined($removals_full{$mpkg})) { 2380 delete($removals_full{$p}); 2381 } 2382 } 2383 } 2384 # 2385 # now take only the subset of packages that is in @todo 2386 # note that @todo is already expanded in action_updated according 2387 # to the --no-depends and --no-depends-at-all options 2388 # 2389 my %removals; 2390 my %forcermpkgs; 2391 my %newpkgs; 2392 for my $p (@todo) { 2393 $removals{$p} = 1 if defined($removals_full{$p}); 2394 $forcermpkgs{$p} = 1 if defined($forcermpkgs_full{$p}); 2395 $newpkgs{$p} = 1 if defined($newpkgs_full{$p}); 2396 } 2397 debug ("$prg: new pkgs: " . join("\n\t",keys %newpkgs) . "\n"); 2398 debug ("$prg: deleted : " . join("\n\t",keys %removals) . "\n"); 2399 debug ("$prg: forced : " . join("\n\t",keys %forcermpkgs) . "\n"); 2400 2401 return (\%removals, \%newpkgs, \%forcermpkgs, \%new_pkgs_due_forcerm_coll); 2402} 2403 2404# tlmgr update foo 2405# if foo is of type Package|Documentation it will update only foo 2406# and the respective .ARCH dependencies 2407# if foo is of type Collection|Scheme it will update itself AND 2408# will check all depending packs of type NOT(COllection|Scheme) 2409# for necessary updates 2410# 2411# tlmgr update --no-depends foo 2412# as above, but will not check for depends of Collections/Schemes 2413# but it will still update .ARCH deps 2414# 2415# tlmgr update --no-depends-at-all foo 2416# will absolutely only update foo not even taking .ARCH into account 2417# 2418# TLPDB->install_package INSTALLS ONLY ONE PACKAGE, no deps whatsoever 2419# anymore. That has all to be done by hand. 2420# 2421sub machine_line { 2422 my ($flag1) = @_; 2423 my $ret = 0; 2424 if ($flag1 eq "-ret") { 2425 $ret = 1; 2426 shift; 2427 } 2428 my ($pkg, $flag, $lrev, $rrev, $size, $runtime, $esttot, $tag, $lcv, $rcv) = @_; 2429 $lrev ||= "-"; 2430 $rrev ||= "-"; 2431 $flag ||= "?"; 2432 $size ||= "-"; 2433 $runtime ||= "-"; 2434 $esttot ||= "-"; 2435 $tag ||= "-"; 2436 $lcv ||= "-"; 2437 $rcv ||= "-"; 2438 my $str = join("\t", $pkg, $flag, $lrev, $rrev, $size, $runtime, $esttot, $tag, $lcv, $rcv); 2439 $str .= "\n"; 2440 return($str) if $ret; 2441 print $str; 2442} 2443 2444sub upd_info { 2445 my ($pkg, $kb, $lrev, $mrev, $txt) = @_; 2446 my $flen = 25; 2447 my $kbstr = ($kb >= 0 ? " [${kb}k]" : ""); 2448 my $kbstrlen = length($kbstr); 2449 my $pkglen = length($pkg); 2450 my $is = sprintf("%-9s ", "$txt:"); 2451 if ($pkglen + $kbstrlen > $flen) { 2452 $is .= "$pkg$kbstr: "; 2453 } else { 2454 $is .= sprintf ('%*2$s', $pkg, -($flen-$kbstrlen)); 2455 $is .= "$kbstr: "; 2456 } 2457 $is .= sprintf("local: %8s, source: %8s", 2458 $lrev, $mrev); 2459 info("$is\n"); 2460} 2461 2462sub action_update { 2463 my $ret = $F_OK; 2464 2465 init_local_db(1); 2466 $opts{"no-depends"} = 1 if $opts{"no-depends-at-all"}; 2467 2468 # make a quick check on command line arguments to avoid loading 2469 # the remote db uselessly. 2470 # we require: 2471 # if no --list is given: either --self or --all or <pkgs> 2472 # if --list is given: nothing 2473 # other options just change the behaviour 2474 if (!($opts{"list"} || @ARGV || $opts{"all"} || $opts{"self"})) { 2475 tlwarn("tlmgr update: specify --list, --all, --self, or a list of package names.\n"); 2476 return ($F_ERROR); 2477 } 2478 2479 init_tlmedia_or_die(); 2480 info("$prg update: dry run, no changes will be made\n") if $opts{"dry-run"}; 2481 2482 my @excluded_pkgs = (); 2483 if ($opts{"exclude"}) { 2484 @excluded_pkgs = @{$opts{"exclude"}}; 2485 } 2486 2487 if (!$opts{"list"}) { 2488 return ($F_ERROR) if !check_on_writable(); 2489 } 2490 2491 # check for updates to tlmgr and die unless either --force or --list or --self 2492 # is given 2493 my @critical; 2494 if (!$opts{"usermode"}) { 2495 @critical = check_for_critical_updates($localtlpdb, $remotetlpdb); 2496 } 2497 my $dry_run_cont = $opts{"dry-run"} && ($opts{"dry-run"} < 0); 2498 if ( !$dry_run_cont && !$opts{"self"} && @critical) { 2499 critical_updates_warning(); 2500 if ($opts{"force"}) { 2501 tlwarn("$prg: Continuing due to --force.\n"); 2502 } elsif ($opts{"list"}) { 2503 # do not warn here 2504 } else { 2505 return($F_ERROR); 2506 } 2507 } 2508 2509 my $autobackup = 0; 2510 # check for the tlpdb option autobackup, and if present and true (!= 0) 2511 # assume we are doing backups 2512 if (!$opts{"backup"}) { 2513 $autobackup = $localtlpdb->option("autobackup"); 2514 if ($autobackup) { 2515 # check the format, we currently allow only natural numbers, and -1 2516 if ($autobackup eq "-1") { 2517 debug ("Automatic backups activated, keeping all backups.\n"); 2518 $opts{"backup"} = 1; 2519 } elsif ($autobackup eq "0") { 2520 debug ("Automatic backups disabled.\n"); 2521 } elsif ($autobackup =~ m/^[0-9]+$/) { 2522 debug ("Automatic backups activated, keeping $autobackup backups.\n"); 2523 $opts{"backup"} = 1; 2524 } else { 2525 tlwarn ("Option autobackup can only be an integer >= -1.\n"); 2526 tlwarn ("Disabling auto backups.\n"); 2527 $localtlpdb->option("autobackup", 0); 2528 $autobackup = 0; 2529 $ret |= $F_WARNING; 2530 } 2531 } 2532 } 2533 2534 # cmd line --backup, we check for --backupdir, and if that is not given 2535 # we try to get the default from the tlpdb. If that doesn't work, exit. 2536 if ($opts{"backup"}) { 2537 my ($a, $b) = check_backupdir_selection(); 2538 if ($a & $F_ERROR) { 2539 # in all these cases we want to terminate in the non-gui mode 2540 tlwarn($b); 2541 return ($F_ERROR); 2542 } 2543 } 2544 2545 # finally, if we have --backupdir, but no --backup, just enable it 2546 $opts{"backup"} = 1 if $opts{"backupdir"}; 2547 2548 info("$prg: saving backups to $opts{'backupdir'}\n") 2549 if $opts{"backup"} && !$::machinereadable; 2550 2551 # these two variables are used throughout this function 2552 my $root = $localtlpdb->root; 2553 my $temp = "$root/temp"; 2554 2555 # remove old _BACKUP packages that have piled up in temp 2556 # they can be recognized by their name starting with __BACKUP_ 2557 for my $f (<$temp/__BACKUP_*>) { 2558 unlink($f) unless $opts{"dry-run"}; 2559 } 2560 2561 2562 my @todo; 2563 if ($opts{"list"}) { 2564 if ($opts{"all"}) { 2565 @todo = $localtlpdb->list_packages; 2566 } elsif ($opts{"self"}) { 2567 @todo = @critical; 2568 } else { 2569 if (@ARGV) { 2570 @todo = @ARGV; 2571 } else { 2572 @todo = $localtlpdb->list_packages; 2573 } 2574 } 2575 } elsif ($opts{"self"} && @critical) { 2576 @todo = @critical; 2577 } elsif ($opts{"all"}) { 2578 @todo = $localtlpdb->list_packages; 2579 } else { 2580 @todo = @ARGV; 2581 } 2582 # don't do anything if we have been invoked in a strange way 2583 if (!@todo) { 2584 if ($opts{"self"}) { 2585 info("$prg: no updates for tlmgr present.\n"); 2586 } else { 2587 tlwarn("tlmgr update: please specify a list of packages, --all, or --self.\n"); 2588 return ($F_ERROR); 2589 } 2590 } 2591 2592 if (!($opts{"self"} && @critical) || ($opts{"self"} && $opts{"list"})) { 2593 # update all .ARCH dependencies, too, unless $opts{"no-depends-at-all"}: 2594 @todo = $remotetlpdb->expand_dependencies("-only-arch", $localtlpdb, @todo) 2595 unless $opts{"no-depends-at-all"}; 2596 # 2597 # update general deps unless $opts{"no-depends"}: 2598 @todo = $remotetlpdb->expand_dependencies("-no-collections",$localtlpdb,@todo) 2599 unless $opts{"no-depends"}; 2600 # 2601 # filter out critical packages 2602 @todo = grep (!m/$CriticalPackagesRegexp/, @todo) 2603 unless $opts{"list"}; 2604 } 2605 2606 my ($remref, $newref, $forref, $new_due_to_forcerm_coll_ref) = 2607 auto_remove_install_force_packages(@todo); 2608 my %removals = %$remref; 2609 my %forcermpkgs = %$forref; 2610 my %newpkgs = %$newref; 2611 my %new_due_to_forcerm_coll = %$new_due_to_forcerm_coll_ref; 2612 2613 # check that the --exclude options do not conflict with the 2614 # options --no-auto-remove, --no-auto-install, --reinstall-forcibly-removed 2615 my @option_conflict_lines = (); 2616 my $in_conflict = 0; 2617 if (!$opts{"no-auto-remove"} && $config{"auto-remove"}) { 2618 for my $pkg (keys %removals) { 2619 for my $ep (@excluded_pkgs) { 2620 if ($pkg eq $ep || $pkg =~ m/^$ep\./) { 2621 push @option_conflict_lines, "$pkg: excluded but scheduled for auto-removal\n"; 2622 $in_conflict = 1; 2623 last; # of the --exclude for loop 2624 } 2625 } 2626 } 2627 } 2628 if (!$opts{"no-auto-install"}) { 2629 for my $pkg (keys %newpkgs) { 2630 for my $ep (@excluded_pkgs) { 2631 if ($pkg eq $ep || $pkg =~ m/^$ep\./) { 2632 push @option_conflict_lines, "$pkg: excluded but scheduled for auto-install\n"; 2633 $in_conflict = 1; 2634 last; # of the --exclude for loop 2635 } 2636 } 2637 } 2638 } 2639 if ($opts{"reinstall-forcibly-removed"}) { 2640 for my $pkg (keys %forcermpkgs) { 2641 for my $ep (@excluded_pkgs) { 2642 if ($pkg eq $ep || $pkg =~ m/^$ep\./) { 2643 push @option_conflict_lines, "$pkg: excluded but scheduled for reinstall\n"; 2644 $in_conflict = 1; 2645 last; # of the --exclude for loop 2646 } 2647 } 2648 } 2649 } 2650 if ($in_conflict) { 2651 tlwarn("Conflicts have been found:\n"); 2652 for (@option_conflict_lines) { tlwarn(" $_"); } 2653 tlwarn("Please resolve these conflicts!\n"); 2654 return ($F_ERROR); 2655 } 2656 2657 # 2658 # we first collect the list of packages to be actually updated or installed 2659 my %updated; 2660 my @new; 2661 my @addlines; 2662 2663 TODO: foreach my $pkg (sort @todo) { 2664 next if ($pkg =~ m/^00texlive/); 2665 for my $ep (@excluded_pkgs) { 2666 if ($pkg eq $ep || $pkg =~ m/^$ep\./) { 2667 info("Skipping excluded package $pkg\n"); 2668 next TODO; 2669 } 2670 } 2671 my $tlp = $localtlpdb->get_package($pkg); 2672 if (!defined($tlp)) { 2673 # if the user has forcibly removed (say) bin-makeindex, then the 2674 # loop above has no way to add bin-makeindex.ARCH into the 2675 # %forcermpkgs hash, but the .ARCH will still be in the dependency 2676 # expansion. So try both with and without the .ARCH extension. 2677 (my $pkg_noarch = $pkg) =~ s/\.[^.]*$//; 2678 my $forcerm_coll = $forcermpkgs{$pkg} || $forcermpkgs{$pkg_noarch}; 2679 2680 # similarly for new packages. If latexmk is new, latexmk.ARCH 2681 # will be in the dependency expansion, and we want it. 2682 my $newpkg_coll = $newpkgs{$pkg} || $newpkgs{$pkg_noarch}; 2683 if ($forcerm_coll) { 2684 if ($::machinereadable) { 2685 # TODO should we add a revision number 2686 push @addlines, 2687 # $pkg, $flag, $lrev, $rrev, $size, $runtime, $esttot, $tag, $lcv, $rcv 2688 machine_line("-ret", $pkg, $FLAG_FORCIBLE_REMOVED); 2689 } else { 2690 info("skipping forcibly removed package $pkg\n"); 2691 } 2692 next; 2693 } elsif ($newpkg_coll) { 2694 # do nothing here, it will be reported below. 2695 } elsif (defined($removals{$pkg})) { 2696 # skipping this package, it has been removed due to server removal 2697 # and has already been removed 2698 next; 2699 } elsif (defined($new_due_to_forcerm_coll{$pkg})) { 2700 debug("$prg: $pkg seems to be contained in a forcibly removed" . 2701 " collection, not auto-installing it!\n"); 2702 next; 2703 } else { 2704 tlwarn("\n$prg: $pkg mentioned, but neither new nor forcibly removed\n"); 2705 next; 2706 } 2707 # install new packages 2708 my $mediatlp = $remotetlpdb->get_package($pkg); 2709 if (!defined($mediatlp)) { 2710 tlwarn("\nShould not happen: $pkg not found in $location\n"); 2711 $ret |= $F_WARNING; 2712 next; 2713 } 2714 my $mediarev = $mediatlp->revision; 2715 push @new, $pkg; 2716 next; 2717 } 2718 my $rev = $tlp->revision; 2719 my $lctanvers = $tlp->cataloguedata->{'version'}; 2720 my $mediatlp; 2721 my $maxtag; 2722 if ($remotetlpdb->is_virtual) { 2723 ($maxtag, undef, $mediatlp, undef) = 2724 $remotetlpdb->virtual_candidate($pkg); 2725 } else { 2726 $mediatlp = $remotetlpdb->get_package($pkg); 2727 } 2728 if (!defined($mediatlp)) { 2729 debug("$pkg cannot be found in $location\n"); 2730 next; 2731 } 2732 my $rctanvers = $mediatlp->cataloguedata->{'version'}; 2733 my $mediarev = $mediatlp->revision; 2734 my $mediarevstr = $mediarev; 2735 my @addargs = (); 2736 if ($remotetlpdb->is_virtual) { 2737 push @addargs, $maxtag; 2738 $mediarevstr .= "\@$maxtag"; 2739 } else { 2740 push @addargs, undef; 2741 } 2742 push @addargs, $lctanvers, $rctanvers; 2743 if ($rev < $mediarev) { 2744 $updated{$pkg} = 0; # will be changed to one on successful update 2745 } elsif ($rev > $mediarev) { 2746 if ($::machinereadable) { 2747 # $pkg, $flag, $lrev, $rrev, $size, $runtime, $esttot, $tag, $lcv, $rcv 2748 push @addlines, 2749 machine_line("-ret", $pkg, $FLAG_REVERSED_UPDATE, $rev, $mediarev, "-", "-", "-", @addargs); 2750 } else { 2751 if ($opts{"list"}) { 2752 # not issueing anything if we keep a package 2753 upd_info($pkg, -1, $rev, $mediarevstr, "keep"); 2754 } 2755 } 2756 } 2757 } 2758 my @updated = sort keys %updated; 2759 for my $i (sort @new) { 2760 debug("$i new package\n"); 2761 } 2762 for my $i (@updated) { 2763 debug("$i upd package\n"); 2764 } 2765 2766 # number calculation 2767 # without w32 special packages, those are dealt with in the updater batch 2768 # script 2769 my $totalnr = $#updated + 1; 2770 my @alltodo = @updated; 2771 my $nrupdated = 0; 2772 my $currnr = 1; 2773 2774 # we have to remove all the stuff before we install other packages 2775 # to support moving of files from one package to another. 2776 # remove the packages that have disappeared: 2777 # we add that only to the list of total packages do be worked on 2778 # when --all is given, because we remove packages only on --all 2779 if (!$opts{"no-auto-remove"} && $config{"auto-remove"}) { 2780 my @foo = keys %removals; 2781 $totalnr += $#foo + 1; 2782 } 2783 if (!$opts{"no-auto-install"}) { 2784 $totalnr += $#new + 1; 2785 push @alltodo, @new; 2786 } 2787 2788 # sizes_of_packages returns the sizes of *all* packages if nothing 2789 # is passed over, so if @new and @updated both are empty we will 2790 # get something wrong back, namely the total size of all packages 2791 # the third argument is undef to compute *all* platforms 2792 my %sizes; 2793 if (@alltodo) { 2794 %sizes = %{$remotetlpdb->sizes_of_packages( 2795 $localtlpdb->option("install_srcfiles"), 2796 $localtlpdb->option("install_docfiles"), undef, @alltodo)}; 2797 } else { 2798 $sizes{'__TOTAL__'} = 0; 2799 } 2800 2801 print "total-bytes\t$sizes{'__TOTAL__'}\n" if $::machinereadable; 2802 print "end-of-header\n" if $::machinereadable; 2803 2804 # print deferred machine-readable lines after the header 2805 for (@addlines) { print; } 2806 2807 # 2808 # compute the list of moved files from %removals, @new, @updated 2809 # 2810 my %do_warn_on_move; 2811 { 2812 # keep all these vars local to this block 2813 my @removals = keys %removals; 2814 my %old_files_to_pkgs; 2815 my %new_files_to_pkgs; 2816 # first save for each file in the currently installed packages 2817 # to be updated the packages it is contained it (might be more!) 2818 # 2819 # TODO WHY WHY is there the next so that all the file move checks 2820 # are actually disabled?!?!?! 2821 for my $p (@updated, @removals) { 2822 my $pkg = $localtlpdb->get_package($p); 2823 tlwarn("Should not happen: $p not found in local tlpdb\n") if (!$pkg); 2824 next; 2825 for my $f ($pkg->all_files) { 2826 push @{$old_files_to_pkgs{$f}}, $p; 2827 } 2828 } 2829 for my $p (@updated, @new) { 2830 my $pkg = $remotetlpdb->get_package($p); 2831 tlwarn("Should not happen: $p not found in $location\n") if (!$pkg); 2832 next; 2833 for my $f ($pkg->all_files) { 2834 if ($pkg->relocated) { 2835 $f =~ s:^$RelocPrefix/:$RelocTree/:; 2836 } 2837 push @{$new_files_to_pkgs{$f}}, $p; 2838 } 2839 } 2840 # 2841 # the idea of supressing warnings is simply that if a file is present 2842 # in more than one package either in the beginning or after a full 2843 # update then this should give a warning. In all other cases 2844 # the warning should be supressed. 2845 for my $f (keys %old_files_to_pkgs) { 2846 my @a = @{$old_files_to_pkgs{$f}}; 2847 $do_warn_on_move{$f} = 1 if ($#a > 0) 2848 } 2849 for my $f (keys %new_files_to_pkgs) { 2850 my @a = @{$new_files_to_pkgs{$f}}; 2851 $do_warn_on_move{$f} = 1 if ($#a > 0) 2852 } 2853 } 2854 2855 # parameters for field width 2856 my $totalnrdigits = length("$totalnr"); 2857 2858 # 2859 # ORDER OF PACKAGE ACTIONS 2860 # 1. removals 2861 # 2. updates 2862 # 3. auto-install 2863 # that way if a file has been moved from one to another package it 2864 # removing the old version after the new package has been installed 2865 # will not give a warning about files being included somewhere else 2866 # 2867 2868 # 2869 # REMOVALS 2870 # 2871 for my $p (keys %removals) { 2872 if ($opts{"no-auto-remove"} || !$config{"auto-remove"}) { 2873 info("not removing $p due to -no-auto-remove or config file option (removed on server)\n"); 2874 } else { 2875 &ddebug("removing package $p\n"); 2876 my $pkg = $localtlpdb->get_package($p); 2877 if (! $pkg) { 2878 # This happened when a collection was removed by the user, 2879 # and then renamed on the server, e.g., collection-langarab -> 2880 # collection-langarabic; Luecking report 20 July 2009. 2881 &ddebug(" get_package($p) failed, ignoring"); 2882 next; 2883 } 2884 my $rev = $pkg->revision; 2885 my $lctanvers = $pkg->cataloguedata->{'version'}; 2886 if ($opts{"list"}) { 2887 if ($::machinereadable) { 2888 # $pkg, $flag, $lrev, $rrev, $size, $runtime, $esttot, $tag, $lcv, $rcv 2889 machine_line($p, $FLAG_REMOVE, $rev, "-", "-", "-", "-", "-", $lctanvers); 2890 } else { 2891 upd_info($p, -1, $rev, "<absent>", "autorm"); 2892 } 2893 $currnr++; 2894 } else { 2895 # new we are sure that: 2896 # - $opts{"no-auto-remove"} is *not* set 2897 # - $opts{"list"} is *not* set 2898 # we have to check in addition that 2899 # - $opts{"dry-run"} is not set 2900 if ($::machinereadable) { 2901 # $pkg, $flag, $lrev, $rrev, $size, $runtime, $esttot, $tag, $lcv, $rcv 2902 machine_line($p, $FLAG_REMOVE, $rev, "-", "-", "-", "-", "-", $lctanvers); 2903 } else { 2904 info("[" . sprintf ('%*2$s', $currnr, $totalnrdigits) . 2905 "/$totalnr] auto-remove: $p ... "); 2906 } 2907 if (!$opts{"dry-run"}) { 2908 # older tlmgr forgot to clear the relocated bit when saving a tlpobj 2909 # into the local tlpdb, although the paths were rewritten. 2910 # We have to clear this bit otherwise the make_container calls below 2911 # for creating the backup will create some rubbish! 2912 # Same as further down in the update part! 2913 if ($pkg->relocated) { 2914 debug("$prg: warn, relocated bit set for $p, but that is wrong!\n"); 2915 $pkg->relocated(0); 2916 } 2917 if ($opts{"backup"}) { 2918 $pkg->make_container("xz", $root, 2919 $opts{"backupdir"}, 2920 "${p}.r" . $pkg->revision, 2921 $pkg->relocated); 2922 if ($autobackup) { 2923 # in case we do auto backups we remove older backups 2924 clear_old_backups($p, $opts{"backupdir"}, $autobackup); 2925 } 2926 } 2927 $localtlpdb->remove_package($p); 2928 logpackage("remove: $p"); 2929 } 2930 info("done\n") unless $::machinereadable; 2931 $currnr++; 2932 } 2933 } 2934 } 2935 2936 2937 my $starttime = time(); 2938 my $donesize = 0; 2939 my $totalsize = $sizes{'__TOTAL__'}; 2940 2941 2942 # 2943 # UPDATES AND NEW PACKAGES 2944 # 2945 # order: 2946 # - update normal packages 2947 # - install new normal packages 2948 # - update collections 2949 # - install new collections 2950 # - update schemes 2951 # - install new schemes (? will not happen?) 2952 # 2953 # this makes sure that only if all depending packages are installed 2954 # the collection is updated, which in turn makes sure that 2955 # if the installation of a new package does break it will not be 2956 # counted as forcibly removed later on. 2957 # 2958 my @inst_packs; 2959 my @inst_colls; 2960 my @inst_schemes; 2961 for my $pkg (@updated) { 2962 # we do name checking here, not to load all tlpobj again and again 2963 if ($pkg =~ m/^scheme-/) { 2964 push @inst_schemes, $pkg; 2965 } elsif ($pkg =~ m/^collection-/) { 2966 push @inst_colls, $pkg; 2967 } else { 2968 push @inst_packs, $pkg; 2969 } 2970 } 2971 @inst_packs = sort packagecmp @inst_packs; 2972 2973 my @new_packs; 2974 my @new_colls; 2975 my @new_schemes; 2976 for my $pkg (sort @new) { 2977 # we do name checking here, not to load all tlpobj again and again 2978 if ($pkg =~ m/^scheme-/) { 2979 push @new_schemes, $pkg; 2980 } elsif ($pkg =~ m/^collection-/) { 2981 push @new_colls, $pkg; 2982 } else { 2983 push @new_packs, $pkg; 2984 } 2985 } 2986 @new_packs = sort packagecmp @new_packs; 2987 my %is_new; 2988 for my $pkg (@new_packs, @new_colls, @new_schemes) { 2989 $is_new{$pkg} = 1; 2990 } 2991 2992 # 2993 # TODO idea 2994 # currently this big loop contains a long if then for new packages 2995 # and updated package. That *could* be merged into one so that 2996 # some things like the logging has not been written two times. 2997 # OTOH, the control flow in the "new package" part is much simpler 2998 # and following it after the change would make it much harder 2999 # 3000 foreach my $pkg (@inst_packs, @new_packs, @inst_colls, @new_colls, @inst_schemes, @new_schemes) { 3001 3002 if (!$is_new{$pkg}) { 3003 # skip this loop if infra update on w32 3004 next if ($pkg =~ m/^00texlive/); 3005 my $tlp = $localtlpdb->get_package($pkg); 3006 # we checked already that this package is present! 3007 # but our checks seem to be wrong, no idea why 3008 # ahhh, it seems that it can happen due to a stupid incident, a bug 3009 # on the server: 3010 # - remove a package from a collection 3011 # - at the same time increase its version number 3012 # then what happens is: 3013 # - first the package is removed (auto-remove!) 3014 # - then it is tried to be updated here, which is not working! 3015 # report that and ask for report 3016 if (!defined($tlp)) { 3017 tlwarn("$prg: inconsistency on the server:\n"); 3018 tlwarn("$prg: tlp for package $pkg cannot be found, please report.\n"); 3019 $ret |= $F_WARNING; 3020 next; 3021 } 3022 my $unwind_package; 3023 my $remove_unwind_container = 0; 3024 my $rev = $tlp->revision; 3025 my $lctanvers = $tlp->cataloguedata->{'version'}; 3026 my $mediatlp; 3027 my $maxtag; 3028 if ($remotetlpdb->is_virtual) { 3029 ($maxtag, undef, $mediatlp, undef) = 3030 $remotetlpdb->virtual_candidate($pkg); 3031 } else { 3032 $mediatlp = $remotetlpdb->get_package($pkg); 3033 } 3034 if (!defined($mediatlp)) { 3035 debug("$pkg cannot be found in $location\n"); 3036 next; 3037 } 3038 my $rctanvers = $mediatlp->cataloguedata->{'version'}; 3039 my $mediarev = $mediatlp->revision; 3040 my $mediarevstr = $mediarev; 3041 my @addargs = (); 3042 if ($remotetlpdb->is_virtual) { 3043 push @addargs, $maxtag; 3044 $mediarevstr .= "\@$maxtag"; 3045 } else { 3046 push @addargs, undef; 3047 } 3048 push @addargs, $lctanvers, $rctanvers; 3049 $nrupdated++; 3050 if ($opts{"list"}) { 3051 if ($::machinereadable) { 3052 # $pkg, $flag, $lrev, $rrev, $size, $runtime, $esttot, $tag, $lcv, $rcv 3053 machine_line($pkg, $FLAG_UPDATE, $rev, $mediarev, $sizes{$pkg}, "-", "-", @addargs); 3054 } else { 3055 my $kb = int($sizes{$pkg} / 1024) + 1; 3056 upd_info($pkg, $kb, $rev, $mediarevstr, "update"); 3057 if ($remotetlpdb->is_virtual) { 3058 my @cand = $remotetlpdb->candidates($pkg); 3059 shift @cand; # remove the top element 3060 if (@cand) { 3061 print "\tother candidates: "; 3062 for my $a (@cand) { 3063 my ($t,$r) = split(/\//, $a, 2); 3064 print $r . '@' . $t . " "; 3065 } 3066 print "\n"; 3067 } 3068 } 3069 } 3070 $updated{$pkg} = 1; 3071 next; 3072 } elsif (win32() && ($pkg =~ m/$CriticalPackagesRegexp/)) { 3073 # we pretend that the update happened 3074 # in order to calculate file changes properly 3075 $updated{$pkg} = 1; 3076 next; 3077 } 3078 3079 # older tlmgr forgot to clear the relocated bit when saving a tlpobj 3080 # into the local tlpdb, although the paths were rewritten. 3081 # We have to clear this bit otherwise the make_container calls below 3082 # for creating an unwind container will create some rubbish 3083 # TODO for user mode we should NOT clear this bit! 3084 if ($tlp->relocated) { 3085 debug("$prg: warn, relocated bit set for $pkg, but that is wrong!\n"); 3086 $tlp->relocated(0); 3087 } 3088 3089 if ($opts{"backup"} && !$opts{"dry-run"}) { 3090 $tlp->make_container("xz", $root, 3091 $opts{"backupdir"}, "${pkg}.r" . $tlp->revision, 3092 $tlp->relocated); 3093 $unwind_package = 3094 "$opts{'backupdir'}/${pkg}.r" . $tlp->revision . ".tar.xz"; 3095 3096 if ($autobackup) { 3097 # in case we do auto backups we remove older backups 3098 clear_old_backups($pkg, $opts{"backupdir"}, $autobackup); 3099 } 3100 } 3101 3102 my ($estrem, $esttot); 3103 if (!$opts{"list"}) { 3104 ($estrem, $esttot) = TeXLive::TLUtils::time_estimate($totalsize, 3105 $donesize, $starttime); 3106 } 3107 3108 if ($::machinereadable) { 3109 machine_line($pkg, $FLAG_UPDATE, $rev, $mediarev, $sizes{$pkg}, $estrem, $esttot, @addargs); 3110 } else { 3111 my $kb = int ($sizes{$pkg} / 1024) + 1; 3112 info("[" . sprintf ('%*2$s', $currnr, $totalnrdigits) . 3113 "/$totalnr, $estrem/$esttot] update: $pkg [${kb}k] ($rev -> $mediarevstr)"); 3114 } 3115 $donesize += $sizes{$pkg}; 3116 $currnr++; 3117 3118 if ($opts{"dry-run"}) { 3119 info("\n") unless $::machinereadable; 3120 $updated{$pkg} = 1; 3121 next; 3122 } else { 3123 info(" ... ") unless $::machinereadable; # more to come 3124 } 3125 3126 if (!$unwind_package) { 3127 # no backup was made, so let us create a temporary .tar file 3128 # of the package 3129 my $tlp = $localtlpdb->get_package($pkg); 3130 my ($s, $m, $fullname) = $tlp->make_container("tar", $root, $temp, 3131 "__BACKUP_${pkg}.r" . $tlp->revision, 3132 $tlp->relocated); 3133 if ($s <= 0) { 3134 tlwarn("\n$prg: Creation of backup container of $pkg failed.\n"); 3135 tlwarn("Continuing to update other packages, please retry...\n"); 3136 $ret |= $F_WARNING; 3137 # we should try to update other packages at least 3138 next; 3139 } 3140 $remove_unwind_container = 1; 3141 $unwind_package = "$fullname"; 3142 } 3143 # first remove the package, then reinstall it 3144 # this way we get rid of useless files 3145 # force the deinstallation since we will reinstall it 3146 # 3147 # the remove_package should also remove empty dirs in case 3148 # a dir is changed into a file 3149 if ($pkg =~ m/$CriticalPackagesRegexp/) { 3150 debug("Not removing critical package $pkg\n"); 3151 } else { 3152 $localtlpdb->remove_package($pkg, 3153 "remove-warn-files" => \%do_warn_on_move); 3154 } 3155 if ($remotetlpdb->install_package($pkg, $localtlpdb)) { 3156 # installation succeeded because we got a reference 3157 logpackage("update: $pkg ($rev -> $mediarevstr)"); 3158 unlink($unwind_package) if $remove_unwind_container; 3159 # remember successful update 3160 $updated{$pkg} = 1; 3161 # 3162 # if we updated a .ARCH package we have to announce the postactions 3163 # of the parent package so that formats are rebuild 3164 if ($pkg =~ m/^([^.]*)\./) { 3165 my $parent = $1; 3166 if (!TeXLive::TLUtils::member($parent, @inst_packs, @new_packs, @inst_colls, @new_colls, @inst_schemes, @new_schemes)) { 3167 # ok, nothing happens with the parent package, so we have to 3168 # find it and execute the postactions 3169 my $parentobj = $localtlpdb->get_package($parent); 3170 if (!defined($parentobj)) { 3171 # well, in this case we might have hit a package that only 3172 # has .ARCH package, like psv.win32, so do nothing 3173 debug("$prg: .ARCH package without parent, not announcing postaction\n"); 3174 } else { 3175 debug("$prg: announcing parent execute action for $pkg\n"); 3176 TeXLive::TLUtils::announce_execute_actions("enable", $parentobj); 3177 } 3178 } 3179 } 3180 } else { 3181 # install_package returned a scalar, so error. 3182 # now in fact we should do some cleanup, removing files and 3183 # dirs from the new package before re-installing the old one. 3184 # TODO 3185 logpackage("failed update: $pkg ($rev -> $mediarevstr)"); 3186 tlwarn("\n\nInstallation of new version of $pkg did fail, trying to unwind.\n"); 3187 if (win32()) { 3188 # w32 is notorious for not releasing a file immediately 3189 # we experienced permission denied errors 3190 my $newname = $unwind_package; 3191 $newname =~ s/__BACKUP/___BACKUP/; 3192 copy ("-f", $unwind_package, $newname); 3193 # try to remove the file if has been created by us 3194 unlink($unwind_package) if $remove_unwind_container; 3195 # and make sure that the temporary file is removed in any case 3196 $remove_unwind_container = 1; 3197 $unwind_package = $newname; 3198 } 3199 my $instret = TeXLive::TLPDB->_install_package("$unwind_package", 0, 3200 [], $localtlpdb); 3201 if ($instret) { 3202 # now we have to include the tlpobj 3203 my $tlpobj = TeXLive::TLPOBJ->new; 3204 $tlpobj->from_file($root . "/tlpkg/tlpobj/$pkg.tlpobj"); 3205 $localtlpdb->add_tlpobj($tlpobj); 3206 $localtlpdb->save; 3207 logpackage("restore: $pkg ($rev)"); 3208 $ret |= $F_WARNING; 3209 tlwarn("Restoring old package state succeeded.\n"); 3210 } else { 3211 logpackage("failed restore: $pkg ($rev)"); 3212 tlwarn("Restoring of old package did NOT succeed.\n"); 3213 tlwarn("Most likely repair: run tlmgr install $pkg and hope.\n"); 3214 # TODO_ERRORCHECKING 3215 # should we return F_ERROR here??? If we would do this, then 3216 # no postactions at all would run? Maybe better only to give 3217 # a warning 3218 $ret |= $F_WARNING; 3219 } 3220 unlink($unwind_package) if $remove_unwind_container; 3221 } 3222 info("done\n") unless $::machinereadable; 3223 } else { # $is_new{$pkg} is true!!! 3224 # 3225 # NEW PACKAGES 3226 # 3227 if ($opts{"no-auto-install"}) { 3228 info("not auto-installing $pkg due to -no-auto-install (new on server)\n") 3229 unless $::machinereadable; 3230 } else { 3231 # install new packages 3232 my $mediatlp; 3233 my $maxtag; 3234 if ($remotetlpdb->is_virtual) { 3235 ($maxtag, undef, $mediatlp, undef) = 3236 $remotetlpdb->virtual_candidate($pkg); 3237 } else { 3238 $mediatlp = $remotetlpdb->get_package($pkg); 3239 } 3240 if (!defined($mediatlp)) { 3241 tlwarn("\nShould not happen: $pkg not found in $location\n"); 3242 $ret |= $F_WARNING; 3243 next; 3244 } 3245 my $mediarev = $mediatlp->revision; 3246 my $mediarevstr = $mediarev; 3247 my @addargs; 3248 if ($remotetlpdb->is_virtual) { 3249 $mediarevstr .= "\@$maxtag"; 3250 push @addargs, $maxtag; 3251 } 3252 my ($estrem, $esttot); 3253 if (!$opts{"list"}) { 3254 ($estrem, $esttot) = TeXLive::TLUtils::time_estimate($totalsize, 3255 $donesize, $starttime); 3256 } 3257 if ($::machinereadable) { 3258 my @maargs = ($pkg, $FLAG_AUTOINSTALL, "-", $mediatlp->revision, $sizes{$pkg}); 3259 if (!$opts{"list"}) { 3260 push @maargs, $estrem, $esttot; 3261 } else { 3262 push @maargs, undef, undef; 3263 } 3264 machine_line(@maargs, @addargs); 3265 } else { 3266 my $kb = int($sizes{$pkg} / 1024) + 1; 3267 if ($opts{"list"}) { 3268 upd_info($pkg, $kb, "<absent>", $mediarevstr, "autoinst"); 3269 } else { 3270 info("[" . sprintf ('%*2$s', $currnr, $totalnrdigits) . 3271 "/$totalnr, $estrem/$esttot] auto-install: $pkg ($mediarevstr) [${kb}k] ... "); 3272 } 3273 } 3274 $currnr++; 3275 $donesize += $sizes{$pkg}; 3276 next if ($opts{"dry-run"} || $opts{"list"}); 3277 if ($remotetlpdb->install_package($pkg, $localtlpdb)) { 3278 # installation succeeded because we got a reference 3279 logpackage("auto-install new: $pkg ($mediarevstr)"); 3280 $nrupdated++; 3281 info("done\n") unless $::machinereadable; 3282 } else { 3283 tlwarn("$prg: couldn't install new package $pkg\n"); 3284 } 3285 } 3286 } 3287 } 3288 3289 # 3290 # special check for depending format updates: 3291 # if one of latex or tex has been updated, we rebuild the formats 3292 # defined in packages *depending* on these packages. 3293 if (!$opts{"list"}) { 3294 TeXLive::TLUtils::announce_execute_actions("latex-updated") if ($updated{"latex"}); 3295 TeXLive::TLUtils::announce_execute_actions("tex-updated") if ($updated{"tex"}); 3296 } 3297 3298 print "end-of-updates\n" if $::machinereadable; 3299 3300 # 3301 # check that if updates to the critical packages are present all of 3302 # them have been successfully updated 3303 my $infra_update_done = 1; 3304 my @infra_files_to_be_removed; 3305 if ($opts{"list"}) { 3306 $infra_update_done = 0; 3307 } else { 3308 for my $pkg (@critical) { 3309 next unless (defined($updated{$pkg})); 3310 $infra_update_done &&= $updated{$pkg}; 3311 my $oldtlp; 3312 my $newtlp; 3313 if ($updated{$pkg}) { 3314 $oldtlp = $localtlpdb->get_package($pkg); 3315 $newtlp = $remotetlpdb->get_package($pkg); 3316 } else { 3317 # update failed but we could introduce new files, that 3318 # should be removed now as a part of restoring backup 3319 $oldtlp = $remotetlpdb->get_package($pkg); 3320 $newtlp = $localtlpdb->get_package($pkg); 3321 } 3322 die ("That shouldn't happen: $pkg not found in tlpdb") if !defined($newtlp); 3323 die ("That shouldn't happen: $pkg not found in tlpdb") if !defined($oldtlp); 3324 my @old_infra_files = $oldtlp->all_files; 3325 my @new_infra_files = $newtlp->all_files; 3326 my %del_files; 3327 @del_files{@old_infra_files} = (); 3328 delete @del_files{@new_infra_files}; 3329 for my $k (keys %del_files) { 3330 my @found_pkgs = $localtlpdb->find_file($k); 3331 if ($#found_pkgs >= 0) { 3332 my $bad_file = 1; 3333 if (win32()) { 3334 # on w32 the packages have not been removed already, 3335 # so we check that the only package listed in @found_pkgs 3336 # is the one we are working on ($pkg) 3337 if ($#found_pkgs == 0 && $found_pkgs[0] =~ m/^$pkg:/) { 3338 # only one package has been returned and it 3339 # matches the current package followed by a colon 3340 # remember the TLPDB->find_file returns 3341 # $pkg:$file 3342 # in this case we can ignore it 3343 $bad_file = 0; 3344 } 3345 } 3346 if ($bad_file) { 3347 tlwarn("$prg: The file $k has disappeared from the critical" . 3348 "package $pkg but is still present in @found_pkgs\n"); 3349 $ret |= $F_WARNING; 3350 } else { 3351 push @infra_files_to_be_removed, $k; 3352 } 3353 } else { 3354 push @infra_files_to_be_removed, $k; 3355 } 3356 } 3357 } 3358 3359 if (!win32()) { 3360 for my $f (@infra_files_to_be_removed) { 3361 # TODO actually unlink the stuff 3362 #unlink("$Master/$f"); 3363 debug("removing disappearing file $f\n"); 3364 } 3365 } 3366 } # end of if ($opts{"list"}) ... else part 3367 3368 # check if any additional updates are asked for 3369 my $other_updates_asked_for = 0; 3370 if ($opts{"all"}) { 3371 $other_updates_asked_for = 1; 3372 } else { 3373 foreach my $p (@ARGV) { 3374 if ($p !~ m/$CriticalPackagesRegexp/) { 3375 $other_updates_asked_for = 1; 3376 last; 3377 } 3378 } 3379 } 3380 3381 my $restart_tlmgr = 0; 3382 if ($opts{"self"} && @critical && 3383 $infra_update_done && $other_updates_asked_for) { 3384 # weed out the --self argument from the saved arguments 3385 @::SAVEDARGV = grep (!m/^-?-self$/, @::SAVEDARGV); 3386 $restart_tlmgr = 1; 3387 } 3388 3389 # infra update and tlmgr restart on w32 is done by the updater batch script 3390 if (win32() && !$opts{"list"} && @critical) { 3391 info("$prg: Preparing TeX Live infrastructure update...\n"); 3392 for my $f (@infra_files_to_be_removed) { 3393 debug("file scheduled for removal $f\n"); 3394 } 3395 my $ret = write_w32_updater($restart_tlmgr, 3396 \@infra_files_to_be_removed, @critical); 3397 if ($ret) { 3398 tlwarn ("$prg: Aborting infrastructure update.\n"); 3399 $ret |= $F_ERROR; 3400 $restart_tlmgr = 0 if ($opts{"dry-run"}); 3401 } 3402 } 3403 3404 # only when we are not dry-running we restart the program 3405 if (!win32() && $restart_tlmgr && !$opts{"dry-run"} && !$opts{"list"}) { 3406 info ("Restarting tlmgr to complete update ...\n"); 3407 debug("restarting tlmgr @::SAVEDARGV\n"); 3408 exec("tlmgr", @::SAVEDARGV); 3409 # we need warn here, otherwise perl gives warnings! 3410 warn ("$prg: cannot restart tlmgr, please retry update\n"); 3411 return ($F_ERROR); 3412 } 3413 3414 # for --dry-run we cannot restart tlmgr (no way to fake successful 3415 # infra update) instead we call action_update() again and signal this 3416 # by $opts{"dry-run"} = -1 3417 if ($opts{"dry-run"} && !$opts{"list"} && $restart_tlmgr) { 3418 $opts{"self"} = 0; 3419 $opts{"dry-run"} = -1; 3420 $localtlpdb = undef; 3421 $remotetlpdb = undef; 3422 info ("Restarting tlmgr to complete update ...\n"); 3423 $ret |= action_update(); 3424 return ($ret); 3425 } 3426 3427 # if a real update from default disk location didn't find anything, 3428 # warn if nothing is updated. 3429 if (!(@new || @updated)) { 3430 info("$prg: no updates available\n"); 3431 if ($remotetlpdb->media ne "NET" 3432 && $remotetlpdb->media ne "virtual" 3433 && !$opts{"dry-run"} 3434 && !$opts{"repository"} 3435 && !$ENV{"TEXLIVE_INSTALL_ENV_NOCHECK"} 3436 ) { 3437 tlwarn(<<END_DISK_WARN); 3438$prg: Your installation is set up to look on the disk for updates. 3439To install from the Internet for this one time only, run: 3440 tlmgr -repository $TeXLiveURL ACTION ARG... 3441where ACTION is install, update, etc.; see tlmgr -help if needed. 3442 3443To change the default for all future updates, run: 3444 tlmgr option repository $TeXLiveURL 3445END_DISK_WARN 3446 } 3447 } 3448 return ($ret); 3449} 3450 3451 3452# INSTALL 3453# 3454# tlmgr install foo bar baz 3455# will create the closure under dependencies of {foo,bar,baz}, i.e. all 3456# dependencies recursively down to the last package, and install all 3457# the packages that are necessary 3458# 3459# tlmgr install --no-depends foo bar baz 3460# will *only* install these three packages (if they are not already installed 3461# but it will STILL INSTALL foo.ARCH if they are necessary. 3462# 3463# tlmgr install --no-depends-at-all foo bar baz 3464# will absolutely only install these three packages, and will not even 3465# take .ARCH deps into account 3466# 3467# tlmgr install --reinstall ... 3468# behaves exactely like without --reinstall BUT the following two 3469# differences: 3470# . dependencies are not expanded from collection to collection, so 3471# if you reinstall a collection then all its dependencies of type 3472# Package will be reinstalled, too, but not the dependencies on 3473# other collection, because that would force the full reinstallation 3474# of the whole installation 3475# . it does not care for whether a package seems to be installed or 3476# not (that is the --reinstall) 3477# 3478# TLPDB->install_package does ONLY INSTALL ONE PACKAGE, no deps whatsoever 3479# anymore! That has all to be done by the caller. 3480# 3481sub action_install { 3482 init_local_db(1); 3483 my $ret = $F_OK; 3484 return ($F_ERROR) if !check_on_writable(); 3485 3486 # installation from a .tar.xz 3487 if ($opts{"file"}) { 3488 if ($localtlpdb->install_package_files(@ARGV)) { 3489 return ($ret); 3490 } else { 3491 return ($F_ERROR); 3492 } 3493 } 3494 3495 # if we are still here, we are installing from some repository 3496 # initialize the TLPDB from $location 3497 $opts{"no-depends"} = 1 if $opts{"no-depends-at-all"}; 3498 init_tlmedia_or_die(); 3499 3500 # check for updates to tlmgr itself, and die unless --force is given 3501 if (!$opts{"usermode"}) { 3502 if (check_for_critical_updates( $localtlpdb, $remotetlpdb)) { 3503 critical_updates_warning(); 3504 if ($opts{"force"}) { 3505 tlwarn("Continuing due to --force\n"); 3506 } else { 3507 if ($::gui_mode) { 3508 # return here and don't do any updates 3509 return ($F_ERROR); 3510 } else { 3511 die "$prg: Terminating; please see warning above!\n"; 3512 } 3513 } 3514 } 3515 } 3516 3517 $opts{"no-depends"} = 1 if $opts{"no-depends-at-all"}; 3518 info("$prg install: dry run, no changes will be made\n") if $opts{"dry-run"}; 3519 3520 my @packs = @ARGV; 3521 # first expand the .ARCH dependencies unless $opts{"no-depends-at-all"} 3522 @packs = $remotetlpdb->expand_dependencies("-only-arch", $localtlpdb, @ARGV) 3523 unless $opts{"no-depends-at-all"}; 3524 # 3525 # if no-depends, we're done; else get rest of deps. 3526 unless ($opts{"no-depends"}) { 3527 if ($opts{"reinstall"} || $opts{"usermode"}) { 3528 # if reinstall or usermode, omit collection->collection deps 3529 @packs = $remotetlpdb->expand_dependencies("-no-collections", 3530 $localtlpdb, @packs); 3531 } else { 3532 @packs = $remotetlpdb->expand_dependencies($localtlpdb, @packs); 3533 } 3534 } 3535 # 3536 # expand dependencies returns a list pkg@tag in case of a virtual 3537 # remote db. 3538 my %packs; 3539 for my $p (@packs) { 3540 my ($pp, $aa) = split('@', $p); 3541 $packs{$pp} = (defined($aa) ? $aa : 0); 3542 } 3543 # 3544 # installation order of packages: 3545 # first all normal packages, then collections, then schemes 3546 # isn't already installed, but the collection already updated, it will 3547 # be reported as forcibly removed. 3548 my @inst_packs; 3549 my @inst_colls; 3550 my @inst_schemes; 3551 for my $pkg (sort keys %packs) { 3552 # we do name checking here, not to load all tlpobj again and again 3553 if ($pkg =~ m/^scheme-/) { 3554 push @inst_schemes, $pkg; 3555 } elsif ($pkg =~ m/^collection-/) { 3556 push @inst_colls, $pkg; 3557 } else { 3558 push @inst_packs, $pkg; 3559 } 3560 } 3561 @inst_packs = sort packagecmp @inst_packs; 3562 3563 my $starttime = time(); 3564 # count packages 3565 my $totalnr = 0; 3566 my %revs; 3567 my @todo; 3568 for my $pkg (@inst_packs, @inst_colls, @inst_schemes) { 3569 my $pkgrev = 0; 3570 # if the package name is asked from a specific repository, use 3571 # that one, otherwise leave the decision to $remotetlpdb by not 3572 # giving a final argument 3573 my $mediatlp = $remotetlpdb->get_package($pkg, 3574 ($packs{$pkg} ? $packs{$pkg} : undef)); 3575 if (!defined($mediatlp)) { 3576 tlwarn("$prg install: package $pkg not present in repository.\n"); 3577 $ret |= $F_WARNING; 3578 next; 3579 } 3580 if (defined($localtlpdb->get_package($pkg))) { 3581 if ($opts{"reinstall"}) { 3582 $totalnr++; 3583 $revs{$pkg} = $mediatlp->revision; 3584 push @todo, $pkg; 3585 } else { 3586 # debug msg that we have this one. 3587 debug("already installed: $pkg\n"); 3588 # if explicitly requested by user (not a dep), tell them. 3589 info("$prg install: package already present: $pkg\n") 3590 if grep { $_ eq $pkg } @ARGV; 3591 } 3592 } else { 3593 $totalnr++; 3594 $revs{$pkg} = $mediatlp->revision; 3595 push (@todo, $pkg); 3596 } 3597 } 3598 # return if there is nothing to install! 3599 return ($ret) if (!@todo); 3600 3601 my $orig_do_src = $localtlpdb->option("install_srcfiles"); 3602 my $orig_do_doc = $localtlpdb->option("install_docfiles"); 3603 if (!$opts{"dry-run"}) { 3604 $localtlpdb->option("install_srcfiles", 1) if $opts{'with-src'}; 3605 $localtlpdb->option("install_docfiles", 1) if $opts{'with-doc'}; 3606 } 3607 3608 my $currnr = 1; 3609 # undef here is a ref to array of platforms, if undef all are used 3610 my %sizes = %{$remotetlpdb->sizes_of_packages( 3611 $localtlpdb->option("install_srcfiles"), 3612 $localtlpdb->option("install_docfiles"), undef, @todo)}; 3613 defined($sizes{'__TOTAL__'}) || ($sizes{'__TOTAL__'} = 0); 3614 my $totalsize = $sizes{'__TOTAL__'}; 3615 my $donesize = 0; 3616 3617 print "total-bytes\t$sizes{'__TOTAL__'}\n" if $::machinereadable; 3618 print "end-of-header\n" if $::machinereadable; 3619 3620 foreach my $pkg (@todo) { 3621 my $flag = $FLAG_INSTALL; 3622 my $re = ""; 3623 my $tlp = $remotetlpdb->get_package($pkg); 3624 my $rctanvers = $tlp->cataloguedata->{'version'}; 3625 if (!defined($tlp)) { 3626 info("Unknown package $pkg\n"); 3627 next; 3628 } 3629 if (!$tlp->relocated && $opts{"usermode"}) { 3630 info("Package $pkg is not relocatable, cannot install it in user mode!\n"); 3631 next; 3632 } 3633 my $lctanvers; 3634 if (defined($localtlpdb->get_package($pkg))) { 3635 my $lctanvers = $localtlpdb->get_package($pkg)->cataloguedata->{'version'}; 3636 if ($opts{"reinstall"}) { 3637 $re = "re"; 3638 $flag = $FLAG_REINSTALL; 3639 } else { 3640 debug("already installed (but didn't we say that already?): $pkg\n"); 3641 next; 3642 } 3643 } 3644 my ($estrem, $esttot) = TeXLive::TLUtils::time_estimate($totalsize, 3645 $donesize, $starttime); 3646 my $kb = int($sizes{$pkg} / 1024) + 1; 3647 my @addargs = (); 3648 my $tagstr = ""; 3649 if ($remotetlpdb->is_virtual) { 3650 if ($packs{$pkg} ne "0") { 3651 push @addargs, $packs{$pkg}; 3652 $tagstr = " \@" . $packs{$pkg}; 3653 } else { 3654 my ($maxtag,undef,undef,undef) = $remotetlpdb->virtual_candidate($pkg); 3655 push @addargs, $maxtag; 3656 $tagstr = " \@" . $maxtag; 3657 } 3658 } 3659 push @addargs, $lctanvers, $rctanvers; 3660 if ($::machinereadable) { 3661 machine_line($pkg, $flag, "-", $revs{$pkg}, $sizes{$pkg}, $estrem, $esttot, @addargs); 3662 } else { 3663 info("[$currnr/$totalnr, $estrem/$esttot] ${re}install: $pkg$tagstr [${kb}k]\n"); 3664 } 3665 if (!$opts{"dry-run"}) { 3666 $remotetlpdb->install_package($pkg, $localtlpdb, 3667 ($packs{$pkg} ? $packs{$pkg} : undef) ); 3668 logpackage("${re}install: $pkg$tagstr"); 3669 } 3670 $donesize += $sizes{$pkg}; 3671 $currnr++; 3672 } 3673 print "end-of-updates\n" if $::machinereadable; 3674 3675 3676 if ($opts{"dry-run"}) { 3677 # stop here, don't do any postinstall actions 3678 return($ret | $F_NOPOSTACTION); 3679 } else { 3680 # reset option if --with-src argument was given 3681 $localtlpdb->option("install_srcfiles", $orig_do_src) if $opts{'with-src'}; 3682 $localtlpdb->option("install_docfiles", $orig_do_doc) if $opts{'with-doc'}; 3683 $localtlpdb->save if ($opts{'with-src'} || $opts{'with-doc'}); 3684 } 3685 return ($ret); 3686} 3687 3688sub show_list_of_packages { 3689 init_local_db(); 3690 # make sure that the @ARGV hash is not changed in case we switch to 3691 # show mode 3692 my ($what) = @_; 3693 $what = "" if !$what; 3694 my $tlm; 3695 if ($opts{"only-installed"}) { 3696 $tlm = $localtlpdb; 3697 } else { 3698 init_tlmedia_or_die(); 3699 $tlm = $remotetlpdb; 3700 } 3701 my @whattolist; 3702 if ($what =~ m/^collections/i) { 3703 @whattolist = $tlm->collections; 3704 } elsif ($what =~ m/^schemes/i) { 3705 @whattolist = $tlm->schemes; 3706 } else { 3707 if ($tlm->is_virtual) { 3708 @whattolist = $tlm->list_packages("-all"); 3709 } else { 3710 @whattolist = $tlm->list_packages; 3711 } 3712 } 3713 foreach (@whattolist) { 3714 next if ($_ =~ m/^00texlive/); 3715 if (defined($localtlpdb->get_package($_))) { 3716 print "i "; 3717 } else { 3718 print " "; 3719 } 3720 my $tlp = $tlm->get_package($_); 3721 if (!$tlp) { 3722 if ($remotetlpdb->is_virtual) { 3723 # we might have the case that a package is present in a 3724 # subsidiary repository, but not pinned, so it will 3725 # not be found by ->get_package 3726 # In this case we list all repositories shipping it, 3727 # but warn that it is not pinned and thus not reachable. 3728 my @cand = $remotetlpdb->candidates($_); 3729 if (@cand) { 3730 my $first = shift @cand; 3731 if (defined($first)) { 3732 tlwarn("strange, we have a first candidate but no tlp: $_\n"); 3733 next; 3734 } 3735 # already shifted away the first element 3736 if ($#cand >= 0) { 3737 print "$_: --- no installable candidate found, \n"; 3738 print " but present in subsidiary repositories without a pin.\n"; 3739 print " This package is not reachable without pinning.\n"; 3740 print " Repositories containing this package:\n"; 3741 for my $a (@cand) { 3742 my ($t,$r) = split(/\//, $a, 2); 3743 my $tlp = $remotetlpdb->get_package($_, $t); 3744 my $foo = $tlp->shortdesc; 3745 print " $t: ", defined($foo) ? $foo : "(shortdesc missing)" , "\n"; 3746 } 3747 next; 3748 } else { 3749 tlwarn("strange, package listed but no residual candidates: $_\n"); 3750 next; 3751 } 3752 } else { 3753 tlwarn("strange, package listed but no candidates: $_\n"); 3754 next; 3755 } 3756 } else { 3757 tlwarn("strange, package cannot be found in remote tlpdb: $_\n"); 3758 next; 3759 } 3760 } 3761 my $foo = $tlp->shortdesc; 3762 print "$_: ", defined($foo) ? $foo : "(shortdesc missing)" , "\n"; 3763 } 3764 return; 3765} 3766 3767# PINNING 3768# 3769# this action manages the pinning file 3770# of course it can be edited by hand, but we want to make this 3771# easier for people to use 3772# tlmgr pinning show 3773# tlmgr pinning check 3774# tlmgr pinning add <repo> <pkgglob> [<pkgglob> ...] 3775# tlmgr pinning remove <repo> <pkgglob> [<pkgglob> ...] 3776# tlmgr pinning remove <repo> --all 3777sub action_pinning { 3778 my $what = shift @ARGV; 3779 $what || ($what = 'show'); 3780 init_local_db(); 3781 init_tlmedia_or_die(); 3782 if (!$remotetlpdb->is_virtual) { 3783 tlwarn("$prg: only one repository configured, " 3784 . "pinning actions not supported.\n"); 3785 return; 3786 } 3787 my $pinref = $remotetlpdb->virtual_pindata(); 3788 my $pf = $remotetlpdb->virtual_pinning(); 3789 3790 if ($what =~ m/^show$/i) { 3791 my @pins = @$pinref; 3792 if (!@pins) { 3793 tlwarn("$prg: no pinning data present.\n"); 3794 return 0; 3795 } 3796 info("$prg: this pinning data is defined:\n"); 3797 for my $p (@pins) { 3798 info(" ", $p->{'repo'}, ":", $p->{'glob'}, "\n"); 3799 } 3800 return 1; 3801 3802 } elsif ($what =~ m/^check$/i) { 3803 tlwarn("$prg: not implemented yet, sorry!\n"); 3804 return 0; 3805 3806 } elsif ($what =~ m/^add$/i) { 3807 # we need at least two more arguments 3808 if (@ARGV < 2) { 3809 tlwarn("$prg: need at least two arguments to pinning add\n"); 3810 return; 3811 } 3812 my $repo = shift @ARGV; 3813 my @new = (); 3814 my @ov = $pf->value($repo); 3815 for my $n (@ARGV) { 3816 if (member($n, @ov)) { 3817 info("$prg: already pinned to $repo: $n\n"); 3818 } else { 3819 push (@ov, $n); 3820 push (@new, $n); 3821 } 3822 } 3823 $pf->value($repo, @ov); 3824 $remotetlpdb->virtual_update_pins(); 3825 $pf->save; 3826 info("$prg: new pinning data for $repo: @new\n") if @new; 3827 return 1; 3828 3829 } elsif ($what =~ m/^remove$/i) { 3830 my $repo = shift @ARGV; 3831 if (!defined($repo)) { 3832 tlwarn("$prg: missing repository argument to pinning remove\n"); 3833 return 0; 3834 } 3835 if ($opts{'all'}) { 3836 if (@ARGV) { 3837 tlwarn("$prg: additional argument(s) not allowed with --all: @ARGV\n"); 3838 return 0; 3839 } 3840 $pf->delete_key($repo); 3841 $remotetlpdb->virtual_update_pins(); 3842 $pf->save; 3843 info("$prg: all pinning data removed for repository $repo\n"); 3844 return 1; 3845 } 3846 # complicated case, we want to remove only one setting 3847 my @ov = $pf->value($repo); 3848 my @nv; 3849 for my $pf (@ov) { 3850 push (@nv, $pf) if (!member($pf, @ARGV)); 3851 } 3852 if ($#ov == $#nv) { 3853 info("$prg: no changes in pinning data for $repo\n"); 3854 return 1; 3855 } 3856 if (@nv) { 3857 $pf->value($repo, @nv); 3858 } else { 3859 $pf->delete_key($repo); 3860 } 3861 $remotetlpdb->virtual_update_pins(); 3862 $pf->save; 3863 info("$prg: removed pinning data for repository $repo: @ARGV\n"); 3864 return 1; 3865 3866 } else { 3867 tlwarn("$prg: unknown argument for pinning action: $what\n"); 3868 return 0; 3869 } 3870 # $pin{'repo'} = $repo; 3871 # $pin{'glob'} = $glob; 3872 # $pin{'re'} = $re; 3873 # $pin{'line'} = $line; # for debug/warning purpose 3874 return 0; 3875} 3876 3877# REPOSITORY 3878# 3879# this action manages the list of repositories 3880# tlmgr repository list -> lists repositories 3881# tlmgr repository list path|tag -> lists content of repo path|tag 3882# tlmgr repository add path [tag] -> add repository with optional tag 3883# tlmgr repository remove [path|tag] -> removes repository or tag 3884# tlmgr repository set path[#tag] [path[#tag] ...] -> sets the list 3885# 3886 3887sub array_to_repository { 3888 my %r = @_; 3889 my @ret; 3890 my @k = keys %r; 3891 if ($#k == 0) { 3892 # only one repo, don't write any tag 3893 return $r{$k[0]}; 3894 } 3895 for my $k (keys %r) { 3896 my $v = $r{$k}; 3897 if ($k ne $v) { 3898 $v = "$v#$k"; 3899 } 3900 # encode spaces and % in the path and tags 3901 $v =~ s/%/%25/g; 3902 $v =~ s/ /%20/g; 3903 push @ret, $v; 3904 } 3905 return "@ret"; 3906} 3907sub repository_to_array { 3908 my $r = shift; 3909 my %r; 3910 my @repos = split ' ', $r; 3911 if ($#repos == 0) { 3912 # only one repo, this is the main one! 3913 $r{'main'} = $repos[0]; 3914 return %r; 3915 } 3916 for my $rr (@repos) { 3917 my $tag; 3918 my $url; 3919 # decode spaces and % in reverse order 3920 $rr =~ s/%20/ /g; 3921 $rr =~ s/%25/%/g; 3922 $tag = $url = $rr; 3923 if ($rr =~ m/^([^#]+)#(.*)$/) { 3924 $tag = $2; 3925 $url = $1; 3926 } 3927 $r{$tag} = $url; 3928 } 3929 return %r; 3930} 3931sub merge_sub_packages { 3932 my %pkgs; 3933 for my $p (@_) { 3934 if ($p =~ m/^(.*)\.([^.]*)$/) { 3935 my $n = $1; 3936 my $a = $2; 3937 if ($p eq "texlive.infra") { 3938 push @{$pkgs{$p}}, "all"; 3939 } else { 3940 push @{$pkgs{$n}}, $a; 3941 } 3942 } else { 3943 push @{$pkgs{$p}}, "all"; 3944 } 3945 } 3946 return %pkgs; 3947} 3948sub action_repository { 3949 init_local_db(); 3950 my $what = shift @ARGV; 3951 $what = "list" if !defined($what); 3952 my %repos = repository_to_array($localtlpdb->option("location")); 3953 if ($what =~ m/^list$/i) { 3954 if (@ARGV) { 3955 # list what is in a repository 3956 for my $repo (@ARGV) { 3957 my $loc = $repo; 3958 if (defined($repos{$repo})) { 3959 $loc = $repos{$repo}; 3960 } 3961 my ($tlpdb, $errormsg) = setup_one_remotetlpdb($loc); 3962 if (!defined($tlpdb)) { 3963 tlwarn("cannot get TLPDB from location $loc\n\n"); 3964 } else { 3965 print "Packages at $loc:\n"; 3966 my %pkgs = merge_sub_packages($tlpdb->list_packages); 3967 for my $p (sort keys %pkgs) { 3968 next if ($p =~ m/00texlive/); 3969 print " $p"; 3970 if (!$opts{'with-platforms'}) { 3971 print "\n"; 3972 } else { 3973 my @a = @{$pkgs{$p}}; 3974 if ($#a == 0) { 3975 if ($a[0] eq "all") { 3976 # no further information necessary 3977 print "\n"; 3978 } else { 3979 print ".$a[0]\n"; 3980 } 3981 } else { 3982 print " (@{$pkgs{$p}})\n"; 3983 } 3984 } 3985 } 3986 } 3987 } 3988 } else { 3989 print "List of repositories (with tags if set):\n"; 3990 for my $k (keys %repos) { 3991 my $v = $repos{$k}; 3992 print "\t$v"; 3993 if ($k ne $v) { 3994 print " ($k)"; 3995 } 3996 print "\n"; 3997 } 3998 } 3999 return ($F_OK); 4000 } 4001 if ($what eq "add") { 4002 my $p = shift @ARGV; 4003 if (!defined($p)) { 4004 tlwarn("$prg: no repository given (to add)\n"); 4005 return ($F_ERROR); 4006 } 4007 # check if it is either url or absolute path 4008 if (($p !~ m!^(http|ftp)://!i) && 4009 !File::Spec->file_name_is_absolute($p)) { 4010 tlwarn("$prg: neither http/ftp URL nor absolute path, no action: $p\n"); 4011 return ($F_ERROR); 4012 } 4013 my $t = shift @ARGV; 4014 $t = $p if (!defined($t)); 4015 if (defined($repos{$t})) { 4016 tlwarn("$prg: repository or its tag already defined, no action: $p\n"); 4017 return ($F_ERROR); 4018 } 4019 # TODO more checks needed? 4020 # if there was till now only *one* repository and that without 4021 # a tag, we give that one the "main" tag which is necessary 4022 # for proper operation! 4023 my @tags = keys %repos; 4024 if ($#tags == 0) { 4025 # we have only one repository, check if it has the main tag 4026 my $maintag = $tags[0]; 4027 if ($maintag ne 'main') { 4028 $repos{'main'} = $repos{$maintag}; 4029 delete $repos{$maintag}; 4030 } 4031 } 4032 $repos{$t} = $p; 4033 $localtlpdb->option("location", array_to_repository(%repos)); 4034 $localtlpdb->save; 4035 if ($t eq $p) { 4036 print "$prg: added repository: $p\n"; 4037 } else { 4038 print "$prg: added repository with tag $t: $p\n"; 4039 } 4040 return ($F_OK); 4041 } 4042 if ($what eq "remove") { 4043 my $p = shift @ARGV; 4044 if (!defined($p)) { 4045 tlwarn("$prg: no repository given (to remove)\n"); 4046 return ($F_ERROR); 4047 } 4048 my $found = 0; 4049 for my $k (keys %repos) { 4050 if ($k eq $p || $repos{$k} eq $p) { 4051 $found = 1; 4052 delete $repos{$k}; 4053 } 4054 } 4055 if (!$found) { 4056 tlwarn("$prg: repository not defined, cannot remove: $p\n"); 4057 return ($F_ERROR); 4058 } else { 4059 $localtlpdb->option("location", array_to_repository(%repos)); 4060 $localtlpdb->save; 4061 print "$prg: removed repository: $p\n"; 4062 return ($F_OK); 4063 } 4064 # no reached 4065 return ($F_OK); 4066 } 4067 if ($what eq "set") { 4068 # TODO TODO 4069 # we have to make sure that there is ONE main repository!!! 4070 %repos = repository_to_array("@ARGV"); 4071 $localtlpdb->option("location", array_to_repository(%repos)); 4072 $localtlpdb->save; 4073 return ($F_OK); 4074 } 4075 # we are still here, unknown command to repository 4076 tlwarn("$prg: unknown subaction for tlmgr repository: $what\n"); 4077 return ($F_ERROR); 4078} 4079 4080sub action_candidates { 4081 my $what = shift @ARGV; 4082 if (!defined($what)) { 4083 tlwarn("$prg: candidates needs a package name as argument\n"); 4084 return ($F_ERROR); 4085 } 4086 init_local_db(); 4087 init_tlmedia_or_die(); 4088 my @cand = $remotetlpdb->candidates($what); 4089 if (@cand) { 4090 my $first = shift @cand; 4091 if (defined($first)) { 4092 my ($t,$r) = split(/\//, $first, 2); 4093 print "Install candidate for $what from $t ($r)\n"; 4094 } else { 4095 print "No install candidate for $what found.\n"; 4096 } 4097 # already shifted away the first element 4098 if ($#cand >= 0) { 4099 print "Other repositories providing this package:\n"; 4100 for my $a (@cand) { 4101 my ($t,$r) = split(/\//, $a, 2); 4102 print "$t ($r)\n"; 4103 } 4104 } 4105 } else { 4106 print "Package $what not found.\n"; 4107 return ($F_WARNING); 4108 } 4109 return ($F_OK);; 4110} 4111 4112# OPTION 4113# 4114sub action_option { 4115 my $what = shift @ARGV; 4116 $what = "show" unless defined($what); 4117 init_local_db(); 4118 my $ret = $F_OK; 4119 if ($what =~ m/^show$/i) { 4120 for my $o (keys %{$localtlpdb->options}) { 4121 # ignore some things which are w32 specific 4122 next if ($o eq "desktop_integration" && !win32()); 4123 next if ($o eq "file_assocs" && !win32()); 4124 next if ($o eq "w32_multi_user" && !win32()); 4125 if (win32()) { 4126 next if ($o =~ m/^sys_/); 4127 } 4128 if (defined $TLPDBOptions{$o}) { 4129 if ($::machinereadable) { 4130 print "$TLPDBOptions{$o}->[2]\t", $localtlpdb->option($o), "\n"; 4131 } else { 4132 info("$TLPDBOptions{$o}->[3] ($TLPDBOptions{$o}->[2]): " . 4133 $localtlpdb->option($o) . "\n"); 4134 } 4135 } else { 4136 tlwarn ("$prg: option $o not supported\n"); 4137 $ret |= $F_WARNING; 4138 } 4139 } 4140 } elsif ($what =~ m/^showall$/i) { 4141 my %loc = %{$localtlpdb->options}; 4142 for my $o (sort keys %TLPDBOptions) { 4143 if ($::machinereadable) { 4144 print "$TLPDBOptions{$o}->[2]\t", 4145 (defined($loc{$o}) ? $loc{$o} : "(not set)"), "\n"; 4146 } else { 4147 info("$TLPDBOptions{$o}->[3] ($TLPDBOptions{$o}->[2]): " . 4148 (defined($loc{$o}) ? $loc{$o} : "(not set)") . "\n"); 4149 } 4150 } 4151 } else { 4152 if ($what eq "location" || $what eq "repo") { 4153 # silently rewrite location|repo -> repository 4154 $what = "repository"; 4155 } 4156 my $found = 0; 4157 for my $opt (keys %TLPDBOptions) { 4158 if ($what eq $TLPDBOptions{$opt}->[2]) { 4159 $found = 1; 4160 # the option argument matches the name 4161 my $val = shift @ARGV; 4162 if (defined($val)) { 4163 return ($F_ERROR) if !check_on_writable(); 4164 # set new value 4165 # here we have to care for some special cases 4166 if ($what eq $TLPDBOptions{"location"}->[2]) { 4167 # support "ctan" on the cmd line 4168 if ($val =~ m/^ctan$/i) { 4169 $val = "$TeXLive::TLConfig::TeXLiveURL"; 4170 } 4171 info("$prg: setting default package repository to $val\n"); 4172 $localtlpdb->option($opt, $val); 4173 } elsif ($what eq $TLPDBOptions{"backupdir"}->[2]) { 4174 info("$prg: setting option $what to $val.\n"); 4175 if (! -d $val) { 4176 info("$prg: the directory $val does not exists, it has to be created\n"); 4177 info("$prg: before backups can be done automatically.\n"); 4178 } 4179 $localtlpdb->option($opt, $val); 4180 } elsif ($what eq $TLPDBOptions{"w32_multi_user"}->[2]) { 4181 # when running w32 do not allow that a non-admin users sets 4182 # this from false to true 4183 my $do_it = 0; 4184 if (win32()) { 4185 if (admin()) { 4186 $do_it = 1; 4187 } else { 4188 if ($val) { 4189 # non admin and tries to set to true, warn 4190 tlwarn("$prg: non-admin user cannot set $TLPDBOptions{'w32_multi_user'}->[2] option to true\n"); 4191 } else { 4192 $do_it = 1; 4193 } 4194 } 4195 } else { 4196 $do_it = 1; 4197 } 4198 if ($do_it) { 4199 if ($val) { 4200 info("$prg: setting option $what to 1.\n"); 4201 $localtlpdb->option($opt, 1); 4202 } else { 4203 info("$prg: setting option $what to 0.\n"); 4204 $localtlpdb->option($opt, 0); 4205 } 4206 } 4207 } else { 4208 # default case, switch for different types 4209 if ($TLPDBOptions{$opt}->[0] eq "b") { 4210 if ($val) { 4211 info("$prg: setting option $what to 1.\n"); 4212 $localtlpdb->option($opt, 1); 4213 } else { 4214 info("$prg: setting option $what to 0.\n"); 4215 $localtlpdb->option($opt, 0); 4216 } 4217 } elsif ($TLPDBOptions{$opt}->[0] eq "p") { 4218 info("$prg: setting option $what to $val.\n"); 4219 $localtlpdb->option($opt, $val); 4220 } elsif ($TLPDBOptions{$opt}->[0] eq "u") { 4221 info("$prg: setting option $what to $val.\n"); 4222 $localtlpdb->option($opt, $val); 4223 } elsif ($TLPDBOptions{$opt}->[0] =~ m/^n(:((-)?\d+)?..((-)?\d+)?)?$/) { 4224 my $isgood = 1; 4225 my $n = int($val); 4226 my $low; 4227 my $up; 4228 if (defined($1)) { 4229 # range given 4230 if (defined($2)) { 4231 # lower border 4232 if ($2 > $n) { 4233 tlwarn("value $n for $what out of range ($TLPDBOptions{$opt}->[0])\n"); 4234 $isgood = 0; 4235 } 4236 } 4237 if (defined($4)) { 4238 # upper border 4239 if ($4 < $n) { 4240 tlwarn("value $n for $what out of range ($TLPDBOptions{$opt}->[0])\n"); 4241 $isgood = 0; 4242 } 4243 } 4244 } 4245 if ($isgood) { 4246 info("$prg: setting option $what to $n.\n"); 4247 $localtlpdb->option($opt, $n); 4248 } 4249 } else { 4250 tlwarn ("Unknown type of option $opt: $TLPDBOptions{$opt}->[0]\n"); 4251 return ($F_ERROR); 4252 } 4253 } 4254 $localtlpdb->save; 4255 # now also save the TLPOBJ of 00texlive.installation 4256 my $tlpo = $localtlpdb->get_package("00texlive.installation"); 4257 if ($tlpo) { 4258 if (open(TOFD, ">$::maintree/tlpkg/tlpobj/00texlive.installation.tlpobj")) { 4259 $tlpo->writeout(\*TOFD); 4260 close(TOFD); 4261 } else { 4262 tlwarn("Cannot save 00texlive.installation to $::maintree/tlpkg/tlpobj/00texlive.installation.tlpobj\n"); 4263 $ret |= $F_WARNING; 4264 } 4265 } 4266 } else { 4267 # show current value 4268 if ($::machinereadable) { 4269 print "$TLPDBOptions{$opt}->[2]\t", $localtlpdb->option($opt), "\n"; 4270 } else { 4271 info ("$TLPDBOptions{$opt}->[3] ($TLPDBOptions{$opt}->[2]): " . 4272 $localtlpdb->option($opt) . "\n"); 4273 } 4274 } 4275 last; 4276 } 4277 } 4278 if (!$found) { 4279 tlwarn("$prg: option $what not supported!\n"); 4280 return ($F_ERROR); 4281 } 4282 } 4283 return ($ret); 4284} 4285 4286 4287# ARCH 4288# 4289sub action_platform { 4290 my @extra_w32_packs = qw/tlperl.win32 tlgs.win32 tlpsv.win32 4291 collection-wintools 4292 dviout.win32 wintools.win32/; 4293 if ($^O=~/^MSWin(32|64)$/i) { 4294 warn("action `platform' not supported on Windows\n"); 4295 return(); 4296 } 4297 if ($opts{"usermode"}) { 4298 tlwarn("action `platform' not supported in usermode\n"); 4299 exit 1; 4300 } 4301 my $what = shift @ARGV; 4302 init_local_db(1); 4303 info("$prg platform: dry run, no changes will be made\n") if $opts{"dry-run"}; 4304 $what || ($what = "list"); 4305 if ($what =~ m/^list$/i) { 4306 # list the available platforms 4307 # initialize the TLPDB from $location 4308 init_tlmedia_or_die(); 4309 my @already_installed_arch = $localtlpdb->available_architectures; 4310 print "Available platforms:\n"; 4311 foreach my $a ($remotetlpdb->available_architectures) { 4312 if (member($a,@already_installed_arch)) { 4313 print "(i) $a\n"; 4314 } else { 4315 print " $a\n"; 4316 } 4317 } 4318 print "Already installed platforms are marked with (i)\n"; 4319 print "You can add new platforms with: tlmgr platform add ARCH1 ARCH2...\n"; 4320 return ($F_OK | $F_NOPOSTACTION); 4321 } elsif ($what =~ m/^add$/i) { 4322 return if !check_on_writable(); 4323 init_tlmedia_or_die(); 4324 my @already_installed_arch = $localtlpdb->available_architectures; 4325 my @available_arch = $remotetlpdb->available_architectures; 4326 my @todoarchs; 4327 foreach my $a (@ARGV) { 4328 if (TeXLive::TLUtils::member($a, @already_installed_arch)) { 4329 print "Platform $a is already installed\n"; 4330 next; 4331 } 4332 if (!TeXLive::TLUtils::member($a, @available_arch)) { 4333 print "Platform $a not available, use 'tlmgr platform list'!\n"; 4334 next; 4335 } 4336 push @todoarchs, $a; 4337 } 4338 foreach my $pkg ($localtlpdb->list_packages) { 4339 next if ($pkg =~ m/^00texlive/); 4340 my $tlp = $localtlpdb->get_package($pkg); 4341 foreach my $dep ($tlp->depends) { 4342 if ($dep =~ m/^(.*)\.ARCH$/) { 4343 # we have to install something 4344 foreach my $a (@todoarchs) { 4345 if ($remotetlpdb->get_package("$pkg.$a")) { 4346 info("install: $pkg.$a\n"); 4347 $remotetlpdb->install_package("$pkg.$a", $localtlpdb) 4348 if (!$opts{"dry-run"}); 4349 } 4350 } 4351 } 4352 } 4353 } 4354 if (TeXLive::TLUtils::member('win32', @todoarchs)) { 4355 # install the necessary w32 stuff 4356 for my $p (@extra_w32_packs) { 4357 info("install: $p\n"); 4358 $remotetlpdb->install_package($p, $localtlpdb) if (!$opts{"dry-run"}); 4359 } 4360 } 4361 # update the option("available_architectures") list of installed archs 4362 if (!$opts{"dry-run"}) { 4363 my @larchs = $localtlpdb->setting("available_architectures"); 4364 push @larchs, @todoarchs; 4365 $localtlpdb->setting("available_architectures",@larchs); 4366 $localtlpdb->save; 4367 } 4368 } elsif ($what =~ m/^remove$/i) { 4369 return if !check_on_writable(); 4370 my @already_installed_arch = $localtlpdb->available_architectures; 4371 my @todoarchs; 4372 my $currentarch = $localtlpdb->platform(); 4373 foreach my $a (@ARGV) { 4374 if (!TeXLive::TLUtils::member($a, @already_installed_arch)) { 4375 print "Platform $a not installed, use 'tlmgr platform list'!\n"; 4376 next; 4377 } 4378 if ($currentarch eq $a) { 4379 info("You are running on platform $a, you cannot remove that one!\n"); 4380 next; 4381 } 4382 push @todoarchs, $a; 4383 } 4384 foreach my $pkg ($localtlpdb->list_packages) { 4385 next if ($pkg =~ m/^00texlive/); 4386 my $tlp = $localtlpdb->get_package($pkg); 4387 if (!$tlp) { 4388 # that is a package foobar.$a that has already been remove but 4389 # is still in the list above, so ignore that 4390 next; 4391 } 4392 foreach my $dep ($tlp->depends) { 4393 if ($dep =~ m/^(.*)\.ARCH$/) { 4394 # we have to install something 4395 foreach my $a (@todoarchs) { 4396 if ($localtlpdb->get_package("$pkg.$a")) { 4397 info("remove: $pkg.$a\n"); 4398 $localtlpdb->remove_package("$pkg.$a") if (!$opts{"dry-run"}); 4399 } 4400 } 4401 } 4402 } 4403 } 4404 if (TeXLive::TLUtils::member('win32', @todoarchs)) { 4405 for my $p (@extra_w32_packs) { 4406 info("remove: $p\n"); 4407 $localtlpdb->remove_package($p) if (!$opts{"dry-run"}); 4408 } 4409 } 4410 if (!$opts{"dry-run"}) { 4411 # try to remove bin/$a dirs 4412 for my $a (@todoarchs) { 4413 if (!rmdir("$Master/bin/$a")) { 4414 tlwarn("binary directory $Master/bin/$a not empty after removal of $a.\n"); 4415 } 4416 } 4417 # update the option("available_architectures") list of installed archs 4418 my @larchs = $localtlpdb->setting("available_architectures"); 4419 my @newarchs; 4420 for my $a (@larchs) { 4421 push @newarchs, $a if !member($a, @todoarchs); 4422 } 4423 $localtlpdb->setting("available_architectures",@newarchs); 4424 $localtlpdb->save; 4425 } 4426 } elsif ($what =~ m/^set$/i) { 4427 return if !check_on_writable(); 4428 my $arg = shift @ARGV; 4429 die "Missing argument to platform set" unless defined($arg); 4430 my @already_installed_arch = $localtlpdb->available_architectures; 4431 if ($arg =~ m/^auto$/i) { 4432 info("Setting platform detection to auto mode.\n"); 4433 $localtlpdb->setting('-clear', 'platform'); 4434 $localtlpdb->save; 4435 } else { 4436 if (!TeXLive::TLUtils::member($arg, @already_installed_arch)) { 4437 tlwarn("cannot set platform to a not installed one.\n"); 4438 return; 4439 } 4440 $localtlpdb->setting('platform', $arg); 4441 $localtlpdb->save; 4442 } 4443 } else { 4444 die "Unknown option for platform: $what"; 4445 } 4446} 4447 4448 4449# GENERATE 4450# 4451sub action_generate { 4452 if ($opts{"usermode"}) { 4453 tlwarn("action `generate' not supported in usermode!\n"); 4454 return $F_ERROR; 4455 } 4456 my $what = shift @ARGV; 4457 init_local_db(); 4458 4459 # we create fmtutil.cnf, language.dat, language.def in TEXMFSYSVAR and 4460 # updmap.cfg in TEXMFDIST. The reason is that we are now using an 4461 # implementation of updmap that supports multiple updmap files. 4462 # Local adaptions should not be made there, but only in TEXMFLOCAL 4463 # or TEXMF(SYS)CONFIG updmap.cfg 4464 # 4465 chomp (my $TEXMFSYSVAR = `kpsewhich -var-value=TEXMFSYSVAR`); 4466 chomp (my $TEXMFSYSCONFIG = `kpsewhich -var-value=TEXMFSYSCONFIG`); 4467 chomp (my $TEXMFLOCAL = `kpsewhich -var-value=TEXMFLOCAL`); 4468 chomp (my $TEXMFDIST = `kpsewhich -var-value=TEXMFDIST`); 4469 4470 # we do generate all config files, treat $opts{"dest"} as pattern 4471 # and make it append the respective extensions 4472 my $append_extension = (($opts{"dest"} && ($what eq "language")) ? 1 : 0); 4473 4474 if ($what =~ m/^language(\.dat|\.def|\.dat\.lua)?$/i) { 4475 # 4476 # if --rebuild-sys is given *and* --dest we warn that this might not 4477 # work if the destination is not the default one 4478 if ($opts{"rebuild-sys"} && $opts{"dest"}) { 4479 tlwarn("tlmgr generate $what: warning: both --rebuild-sys and --dest\n", 4480 "given; the call to fmtutil-sys can fail if the given\n", 4481 "destination is different from the default.\n"); 4482 } 4483 # 4484 # we have to set TEXMFVAR, TEXMFCONFIG in the environment so that 4485 # searching for language.(dat/def) does search in the right place 4486 if ($what =~ m/^language(\.dat\.lua)?$/i) { 4487 my $dest = $opts{"dest"} || 4488 "$TEXMFSYSVAR/tex/generic/config/language.dat.lua"; 4489 $dest .= ".dat.lua" if $append_extension; 4490 my $localcfg = $opts{"localcfg"} || 4491 "$TEXMFLOCAL/tex/generic/config/language-local.dat.lua"; 4492 debug("$prg: writing language.dat.lua data to $dest\n"); 4493 TeXLive::TLUtils::create_language_lua($localtlpdb, $dest, $localcfg); 4494 if ($opts{"rebuild-sys"}) { 4495 do_cmd_and_check 4496 ("fmtutil-sys $common_fmtutil_args --byhyphen \"$dest\""); 4497 } else { 4498 info("To make the newly-generated language.dat.lua take effect," 4499 . " run fmtutil-sys --byhyphen $dest.\n"); 4500 } 4501 } 4502 if ($what =~ m/^language(\.dat)?$/i) { 4503 my $dest = $opts{"dest"} || 4504 "$TEXMFSYSVAR/tex/generic/config/language.dat"; 4505 $dest .= ".dat" if $append_extension; 4506 my $localcfg = $opts{"localcfg"} || 4507 "$TEXMFLOCAL/tex/generic/config/language-local.dat"; 4508 debug ("$prg: writing language.dat data to $dest\n"); 4509 TeXLive::TLUtils::create_language_dat($localtlpdb, $dest, $localcfg); 4510 if ($opts{"rebuild-sys"}) { 4511 do_cmd_and_check 4512 ("fmtutil-sys $common_fmtutil_args --byhyphen \"$dest\""); 4513 } else { 4514 info("To make the newly-generated language.dat take effect," 4515 . " run fmtutil-sys --byhyphen $dest.\n"); 4516 } 4517 } 4518 if ($what =~ m/^language(\.def)?$/i) { 4519 my $dest = $opts{"dest"} || 4520 "$TEXMFSYSVAR/tex/generic/config/language.def"; 4521 $dest .= ".def" if $append_extension; 4522 my $localcfg = $opts{"localcfg"} || 4523 "$TEXMFLOCAL/tex/generic/config/language-local.def"; 4524 debug("$prg: writing language.def data to $dest\n"); 4525 TeXLive::TLUtils::create_language_def($localtlpdb, $dest, $localcfg); 4526 if ($opts{"rebuild-sys"}) { 4527 do_cmd_and_check 4528 ("fmtutil-sys $common_fmtutil_args --byhyphen \"$dest\""); 4529 } else { 4530 info("To make the newly-generated language.def take effect," 4531 . " run fmtutil-sys --byhyphen $dest.\n"); 4532 } 4533 } 4534 4535 } elsif ($what =~ m/^fmtutil$/i) { 4536 tlwarn("$prg: generate fmtutil is no longer needed or supported.\n"); 4537 tlwarn("$prg: Please read the documentation of the `fmtutil' program.\n"); 4538 tlwarn("$prg: Goodbye.\n"); 4539 return $F_ERROR; 4540 4541 } elsif ($what =~ m/^_fmtutil$/i) { 4542 my $dest = $opts{"dest"} || "$TEXMFDIST/web2c/fmtutil.cnf"; 4543 debug("$prg: writing new fmtutil.cnf to $dest\n"); 4544 TeXLive::TLUtils::create_fmtutil($localtlpdb, $dest); 4545 4546 if ($opts{"rebuild-sys"}) { 4547 do_cmd_and_check("fmtutil-sys $common_fmtutil_args --all"); 4548 } else { 4549 info("To make the newly-generated fmtutil.cnf take effect," 4550 . " run fmtutil-sys --all.\n"); 4551 } 4552 4553 } elsif ($what =~ m/^updmap$/i) { 4554 tlwarn("$prg: generate updmap is no longer needed or supported.\n"); 4555 tlwarn("$prg: Please read the documentation of the `updmap' program.\n"); 4556 tlwarn("$prg: Goodbye.\n"); 4557 return $F_ERROR; 4558 4559 } elsif ($what =~ m/^_updmap$/i) { 4560 my $dest = $opts{"dest"} || "$TEXMFDIST/web2c/updmap.cfg"; 4561 debug("$prg: writing new updmap.cfg to $dest\n"); 4562 TeXLive::TLUtils::create_updmap($localtlpdb, $dest); 4563 4564 if ($opts{"rebuild-sys"}) { 4565 do_cmd_and_check("updmap-sys"); 4566 } else { 4567 info("To make the newly-generated updmap.cfg take effect," 4568 . " run updmap-sys.\n"); 4569 } 4570 4571 } else { 4572 tlwarn("$prg: Unknown option for generate: $what; try --help if you need it.\n"); 4573 return $F_ERROR; 4574 } 4575 4576 return $F_OK; 4577} 4578 4579 4580# GUI 4581# 4582sub action_gui { 4583 eval { require Tk; }; 4584 if ($@) { 4585 # that didn't work out, give some usefull error message and stop 4586 my $tkmissing = 0; 4587 if ($@ =~ /^Can\'t locate Tk\.pm/) { 4588 $tkmissing = 1; 4589 } 4590 if ($tkmissing) { 4591 if ($^O=~/^MSWin(32|64)$/i) { 4592 # that should not happen, we are shipping Tk!! 4593 require Win32; 4594 my $msg = "Cannot load Tk, that should not happen as we ship it!\nHow did you start tlmgrgui??\n(Error message: $@)\n"; 4595 Win32::MsgBox($msg, 1|Win32::MB_ICONSTOP(), "Warning"); 4596 } else { 4597 printf STDERR " 4598$prg: Cannot load Tk, thus the GUI cannot be started! 4599The Perl/Tk module is not shipped with the TeX Live installation. 4600You have to install it to get the tlmgr GUI working. 4601(INC = @INC) 4602 4603See http://tug.org/texlive/distro.html#perltk for more details. 4604Goodbye. 4605"; 4606 } 4607 } else { 4608 printf STDERR "$prg: unexpected problem loading Tk: $@\n"; 4609 } 4610 exit 1; 4611 } 4612 4613 # now check that we can actually create a top level window, 4614 # on darwin the X server might not be started, or on unix we are working 4615 # on a console, or whatever. 4616 eval { my $foo = Tk::MainWindow->new; $foo->destroy; }; 4617 if ($@) { 4618 printf STDERR "perl/Tk unusable, cannot create main windows. 4619That could be a consequence of not having X Windows installed or started! 4620Error message from creating MainWindow: 4621 $@ 4622"; 4623 exit 1; 4624 } 4625 4626 # be sure that sub actions do *not* finish 4627 $::gui_mode = 1; 4628 # also unset the $opts{"gui"} to make recursive calls to action_* not starting 4629 # another GUI instance (or better trying to ...) 4630 $opts{"gui"} = 0; 4631 4632 require("tlmgrgui.pl"); 4633 # should not be reached 4634 exit(1); 4635} 4636 4637 4638# UNINSTALL 4639# 4640sub action_uninstall { 4641 if (win32()) { 4642 printf STDERR "Please use \"Add/Remove Programs\" from the Control Panel to removing TeX Live!\n"; 4643 return ($F_ERROR); 4644 } 4645 return if !check_on_writable(); 4646 my $force = defined($opts{"force"}) ? $opts{"force"} : 0; 4647 if (!$force) { 4648 print("If you answer yes here the whole TeX Live installation will be removed!\n"); 4649 print "Remove TeX Live (y/N): "; 4650 my $yesno = <STDIN>; 4651 if ($yesno !~ m/^y(es)?$/i) { 4652 print "Ok, cancelling the removal!\n"; 4653 return ($F_OK | $F_NOPOSTACTION); 4654 } 4655 } 4656 print ("Ok, removing the whole installation:\n"); 4657 init_local_db(); 4658 TeXLive::TLUtils::remove_symlinks($localtlpdb->root, 4659 $localtlpdb->platform(), 4660 $localtlpdb->option("sys_bin"), 4661 $localtlpdb->option("sys_man"), 4662 $localtlpdb->option("sys_info")); 4663 # now do remove the rest 4664 system("rm", "-rf", "$Master/texmf-dist"); 4665 system("rm", "-rf", "$Master/texmf-doc"); 4666 system("rm", "-rf", "$Master/texmf-var"); 4667 system("rm", "-rf", "$Master/tlpkg"); 4668 system("rm", "-rf", "$Master/bin"); 4669 system("rm", "-rf", "$Master/tlpkg/readme-html.dir"); 4670 system("rm", "-rf", "$Master/tlpkg/readme-txt.dir"); 4671 for my $f (qw/doc.html index.html LICENSE.CTAN LICENSE.TL README 4672 README.usergroups release-texlive.txt texmf.cnf/) { 4673 system("rm", "-f", "$Master/tlpkg/$f"); 4674 } 4675 if (-d "$Master/tlpkg/temp") { 4676 system("rmdir", "--ignore-fail-on-non-empty", "$Master/tlpkg/temp"); 4677 } 4678 unlink("$Master/tlpkg/install-tl.log"); 4679 # should we do that???? 4680 # system("rm", "-rf", "$Master/texmf-config"); 4681 # system("rmdir", "--ignore-fail-on-non-empty", "$Master"); 4682} 4683 4684 4685# RECREATE-TLPDB 4686# 4687sub action_recreate_tlpdb { 4688 return if !check_on_writable(); 4689 my $tlpdb = TeXLive::TLPDB->new; 4690 $tlpdb->root($Master); 4691 my $inst = TeXLive::TLPOBJ->new; 4692 $inst->name("00texlive.installation"); 4693 $inst->category("TLCore"); 4694 my @deps; 4695 # options are done further down with $tlpdb->reset_options() 4696 #for my $k (keys %TeXLive::TLConfig::TLPDBOptions) { 4697 # push @deps, "opt_$k:" . $TeXLive::TLConfig::TLPDBOptions{k}->[1]; 4698 #} 4699 # find list of available archs 4700 my @archs; 4701 opendir (DIR, "$Master/bin") || die "opendir($Master/bin) failed: $!"; 4702 my @dirents = readdir (DIR); 4703 closedir (DIR) || warn "closedir($Master/bin) failed: $!"; 4704 for my $dirent (@dirents) { 4705 next if $dirent eq "."; 4706 next if $dirent eq ".."; 4707 next unless -d "$Master/bin/$dirent"; 4708 if (-r "$Master/bin/$dirent/kpsewhich" || -r "$Master/bin/$dirent/kpsewhich.exe") { 4709 push @archs, $dirent; 4710 debug("Skipping directory $Master/bin/$dirent, no kpsewhich there\n"); 4711 } 4712 } 4713 push @deps, "setting_available_architectures:" . join(" ",@archs); 4714 # we have to find out the default arch 4715 # if there is only one dir in $Master/bin then we are settled, 4716 # otherwise we expect the user to pass a correct arch string 4717 if (!TeXLive::TLUtils::member(TeXLive::TLUtils::platform(), @archs)) { 4718 # hmm that is bad, the platform as detected is not in the list 4719 # of installed platforms, so the option --arch has to be given 4720 # if only one is installed use that one 4721 if ($#archs == 0) { 4722 # only one arch available, fine, use it as default 4723 push @deps, "setting_platform:$archs[0]"; 4724 } else { 4725 if (defined($opts{"platform"})) { 4726 if (member($opts{"platform"}, @archs)) { 4727 push @deps, "setting_platform:" . $opts{"platform"}; 4728 } else { 4729 tlwarn("The platform you passed in with --platform is not present in $Master/bin\n"); 4730 tlwarn("Please specify one of the available ones: @archs\n"); 4731 exit(1); 4732 } 4733 } else { 4734 tlwarn("More than one platform available: @archs\n"); 4735 tlwarn("Please pass one as the default you are running on with --platform=...\n"); 4736 exit(1); 4737 } 4738 } 4739 } 4740 $inst->depends(@deps); 4741 # now we have all the stuff for 00texlive.installation done 4742 $tlpdb->add_tlpobj($inst); 4743 # reset the options to default values 4744 $tlpdb->add_default_options(); 4745 # check for location == _MASTER_ 4746 if ($tlpdb->option("location") eq "__MASTER__") { 4747 $tlpdb->option("location", $TeXLive::TLConfig::TeXLiveURL); 4748 } 4749 # add the other stuff in $Master/tlpkg/tlpobj/*.tlpobj 4750 # we can ignore *.{source,doc}.tlpobj because they are already 4751 # included in the *.tlpobj parent one at install time 4752 # (TODO: we should actually REMOVE the *.{source,doc}.tlpobj files 4753 # at package install time) 4754 opendir (DIR, "$Master/tlpkg/tlpobj") or die "opendir($Master/tlpkg/tlpobj) failed: $!"; 4755 my @tlps = readdir(DIR); 4756 closedir (DIR) || warn "closedir($Master/tlpkg/tlpobj) failed: $!"; 4757 for my $t (@tlps) { 4758 next if -d $t; # also does . and .. 4759 next if ($t !~ m/\.tlpobj$/i); 4760 # ignore .source and .doc tlpobjs 4761 next if ($t =~ m/\.(source|doc)\.tlpobj$/i); 4762 my $tlp = TeXLive::TLPOBJ->new; 4763 $tlp->from_file("$Master/tlpkg/tlpobj/$t"); 4764 $tlpdb->add_tlpobj($tlp); 4765 } 4766 # writeout the re-created tlpdb to stdout 4767 $tlpdb->writeout; 4768 return; 4769} 4770 4771# CHECK 4772# 4773sub init_tltree { 4774 my ($svn) = @_; 4775 4776 # if we are on W32, die (no find). 4777 my $arch = $localtlpdb->platform(); 4778 if ($arch eq "win32") { 4779 tldie("$prg: sorry, cannot check this on Windows.\n"); 4780 } 4781 4782 my $Master = $localtlpdb->root; 4783 my $tltree = TeXLive::TLTREE->new ("svnroot" => $Master); 4784 if ($svn) { 4785 debug("Initializine TLTREE from svn\n"); 4786 $tltree->init_from_svn; 4787 } else { 4788 debug("Initializine TLTREE from find\n"); 4789 $tltree->init_from_files; 4790 } 4791 return($tltree); 4792} 4793 4794sub action_check { 4795 my $svn = defined($opts{"use-svn"}) ? $opts{"use-svn"} : 0; 4796 my $what = shift @ARGV; 4797 $what || ($what = "all"); 4798 init_local_db(); 4799 my $ret = 0; 4800 if ($what =~ m/^all/i) { 4801 my $tltree = init_tltree($svn); 4802 print "Running check files:\n"; 4803 $ret |= check_files($tltree); 4804 print "Running check depends:\n"; 4805 $ret |= check_depends(); 4806 print "Running check executes:\n"; 4807 $ret |= check_executes(); 4808 print "Running check runfiles:\n"; 4809 $ret |= check_runfiles(); 4810 } elsif ($what =~ m/^files/i) { 4811 my $tltree = init_tltree($svn); 4812 $ret |= check_files($tltree); 4813 } elsif ($what =~ m/^collections/i) { 4814 tlwarn("the \"collections\" check is replaced by the \"depends\" check.\n"); 4815 $ret |= check_depends(); 4816 } elsif ($what =~ m/^depends/i) { 4817 $ret |= check_depends(); 4818 } elsif ($what =~ m/^runfiles/i) { 4819 $ret |= check_runfiles(); 4820 } elsif ($what =~ m/^executes/i) { 4821 $ret |= check_executes(); 4822 } else { 4823 print "No idea how to check that: $what\n"; 4824 } 4825 if ($ret) { 4826 return ($F_ERROR); 4827 } else { 4828 return ($F_OK); 4829 } 4830} 4831 4832# check file coverage in both direction. 4833# 4834sub check_files { 4835 my $tltree = shift; 4836 my $ret = 0; 4837 my %filetopacks; 4838 my $Master = $localtlpdb->root; 4839 debug("Collecting all files of all packages\n"); 4840 for my $p ($localtlpdb->list_packages()) { 4841 # ignore files in the installer 4842 next if ($p eq "00texlive.installer"); 4843 my $tlp = $localtlpdb->get_package($p); 4844 my @files = $tlp->all_files; 4845 if ($tlp->relocated) { 4846 for (@files) { s:^$RelocPrefix/:$RelocTree/:; } 4847 } 4848 for my $f (@files) { 4849 push @{$filetopacks{$f}}, $p; 4850 } 4851 } 4852 my @multiple = (); 4853 my @missing = (); 4854 debug("Checking for occurrences and existence of all files\n"); 4855 for (keys %filetopacks) { 4856 push @missing, $_ if (! -r "$Master/$_"); 4857 my @foo = @{$filetopacks{$_}}; 4858 if ($#foo < 0) { 4859 warn "that shouldn't happen: $_\n"; 4860 } elsif ($#foo > 0) { 4861 push @multiple, $_; 4862 } 4863 } 4864 if ($#multiple >= 0) { 4865 $ret = 1; 4866 print "\f Multiple included files (relative to $Master):\n"; 4867 for (sort @multiple) { 4868 my @foo = @{$filetopacks{$_}}; 4869 print " $_ (@foo)\n"; 4870 } 4871 print "\n"; 4872 } 4873 if ($#missing >= 0) { 4874 $ret = 1; 4875 print "\f Files mentioned in tlpdb but missing (relative to $Master):\n"; 4876 for my $m (@missing) { 4877 print "\t$m\n"; 4878 } 4879 print "\n"; 4880 } 4881 4882 # check that all files in the trees are covered, along with 4883 # 00texlive.image, q.v. The ones here are not included in the 4884 # archival source/ tarball; 4885 my @IgnorePatterns = qw! 4886 source/ 4887 texmf-dist/ls-R$ texmf-doc/ls-R$ 4888 tlpkg/archive tlpkg/backups tlpkg/installer 4889 tlpkg/texlive.tlpdb tlpkg/tlpobj tlpkg/texlive.profile 4890 texmf-config/ texmf-var/ 4891 texmf.cnf texmfcnf.lua install-tl.log 4892 !; 4893 my %tltreefiles = %{$tltree->{'_allfiles'}}; 4894 my @tlpdbfiles = keys %filetopacks; 4895 my @nohit; 4896 for my $f (keys %tltreefiles) { 4897 # if it is mentioned in the tlpdb or is ignored it is considered 4898 # as covered, thus, otherwise we push it onto the nothit list 4899 if (!defined($filetopacks{$f})) { 4900 my $ignored = 0; 4901 for my $p (@IgnorePatterns) { 4902 if ($f =~ m/^$p/) { 4903 $ignored = 1; 4904 last; 4905 } 4906 } 4907 if (!$ignored) { 4908 push @nohit, $f; 4909 } 4910 } 4911 } 4912 if (@nohit) { 4913 $ret = 1; 4914 print "\f Files present but not covered (relative to $Master):\n"; 4915 for my $f (sort @nohit) { 4916 print " $f\n"; 4917 } 4918 print "\n"; 4919 } 4920 return($ret); 4921} 4922 4923# Check for runtime files with the same name but different contents. 4924# 4925sub check_runfiles { 4926 my $Master = $localtlpdb->root; 4927 4928 # build a list of all runtime files associated to 'normal' packages 4929 (my $non_normal = `ls "$Master/bin"`) =~ s/\n/\$|/g; # binaries 4930 $non_normal .= '^0+texlive|^bin-|^collection-|^scheme-|^texlive-|^texworks'; 4931 $non_normal .= '|^pgf$'; # has lots of intentionally duplicated .lua 4932 my @runtime_files = (); 4933 # 4934 foreach my $tlpn ($localtlpdb->list_packages) { 4935 next if ($tlpn =~ /$non_normal/); 4936 # 4937 my $tlp = $localtlpdb->get_package($tlpn); 4938 my @files = $tlp->runfiles; 4939 if ($tlp->relocated) { 4940 for (@files) { 4941 s!^$TeXLive::TLConfig::RelocPrefix/!$TeXLive::TLConfig::RelocTree/!; 4942 } 4943 } 4944 # special case for koma-script where doc/src files are in runfiles section 4945 if ($tlpn eq "koma-script") { 4946 @files = grep {!m;^texmf-dist/source/latex/koma-script/;} @files; 4947 @files = grep {!m;^texmf-dist/doc/latex/koma-script/;} @files; 4948 } 4949 push @runtime_files, @files; 4950 } 4951 4952 # build the duplicates list. 4953 my @duplicates = (""); # just to use $duplicates[-1] freely 4954 my $prev = ""; 4955 foreach my $f (sort map { TeXLive::TLUtils::basename($_) } @runtime_files) { 4956 push (@duplicates, $f) if (($f eq $prev) and not ($f eq $duplicates[-1])); 4957 $prev = $f; 4958 } 4959 shift @duplicates; # get rid of the fake 1st value 4960 4961 # check if duplicates are different files. 4962 foreach my $f (@duplicates) { 4963 # assume tex4ht, xdy, afm stuff is ok, and don't worry about 4964 # Changes, README et al. Other per-format versions. 4965 next if $f =~ /\.(afm|cfg|dll|exe|4hf|htf|xdy)$/; 4966 next if $f 4967 =~ /^((czech|slovak)\.sty 4968 |Changes 4969 |Makefile 4970 |README 4971 |cid2code\.txt 4972 |etex\.src 4973 |kinsoku\.tex 4974 |language\.dat 4975 |language\.def 4976 |local\.mf 4977 |m-tex4ht\.tex 4978 |metatex\.tex 4979 |.*-noEmbed\.map 4980 |ps2mfbas\.mf 4981 |pstricks\.con 4982 |sample\.bib 4983 |tex4ht\.env 4984 |test\.mf 4985 |texutil\.rb 4986 |tlmgrgui\.pl 4987 )$/x; 4988 # 4989 my @copies = grep (/\/$f$/, @runtime_files); 4990 # map files can be duplicated between (but not within) formats. 4991 if ($f =~ /\.map$/) { 4992 my $need_check = 0; 4993 my $prev_dir = ""; 4994 my @cop = @copies; # don't break the outside list 4995 map { s#^texmf-dist/fonts/map/(.*?)/.*#$1# } @cop; 4996 foreach my $dir (sort @cop ) { 4997 last if ($need_check = ($dir eq $prev_dir)); 4998 $prev_dir = $dir; 4999 } 5000 next unless $need_check; 5001 } 5002 # if all copies are identical, ok, else, complain 5003 my $diff = 0; 5004 for (my $i = 1; $i < scalar(@copies); $i++) { 5005 if ($diff = tlcmp("$Master/$copies[$i-1]", "$Master/$copies[$i]")) { 5006 print "# $f\ndiff $Master/$copies[$i-1] $Master/$copies[$i]\n"; 5007 last; 5008 } 5009 } 5010 print join ("\n", @copies), "\n" if ($diff and (scalar(@copies) > 2)); 5011 } 5012} 5013 5014# check executes 5015# 5016sub check_executes { 5017 my $Master = $localtlpdb->root; 5018 my (%maps,%langcodes,%fmtlines); 5019 for my $pkg ($localtlpdb->list_packages) { 5020 for my $e ($localtlpdb->get_package($pkg)->executes) { 5021 if ($e =~ m/add(Mixed|Kanji)?Map\s+(.*)$/) { 5022 my $foo = $2; 5023 chomp($foo); 5024 if ($foo !~ m/\@kanjiEmbed@/) { 5025 push @{$maps{$foo}}, $pkg; 5026 } 5027 } elsif ($e =~ m/AddFormat\s+(.*)$/) { 5028 my $foo = $1; 5029 chomp($foo); 5030 push @{$fmtlines{$foo}}, $pkg; 5031 } elsif ($e =~ m/AddHyphen\s+.*\s+file=(\S+)(\s*$|\s+.*)/) { 5032 my $foo = $1; 5033 chomp($foo); 5034 push @{$langcodes{$foo}}, $pkg; 5035 } else { 5036 warn "$pkg: unmatched execute: $e\n"; 5037 } 5038 } 5039 } 5040 my %badmaps; 5041 foreach my $mf (keys %maps) { 5042 my @pkgsfound = @{$maps{$mf}}; 5043 if ($#pkgsfound > 0) { 5044 tlwarn ("map file $mf is referenced in the executes of @pkgsfound\n"); 5045 } else { 5046 # less then 1 occurrences is not possible, so we have only one 5047 # package that contains the reference to that map file 5048 my $pkgfoundexecute = $pkgsfound[0]; 5049 my @found = $localtlpdb->find_file($mf); 5050 if ($#found < 0) { 5051 $badmaps{$mf} = $maps{$mf}; 5052 } elsif ($#found > 0) { 5053 # we want to check for multiple inclusions 5054 my %mapfn; 5055 foreach my $foo (@found) { 5056 $foo =~ m/^(.*):(.*)$/; 5057 push @{$mapfn{$2}}, $1; 5058 } 5059 foreach my $k (keys %mapfn) { 5060 my @bla = @{$mapfn{$k}}; 5061 if ($#bla > 0) { 5062 tlwarn ("map file $mf occurs multiple times (in pkgs: @bla)!\n"); 5063 } 5064 } 5065 } else { 5066 # only one occurrence found, we check that the map is also contained 5067 # in the right package! 5068 my ($pkgcontained) = ( $found[0] =~ m/^(.*):.*$/ ); 5069 if ($pkgcontained ne $pkgfoundexecute) { 5070 tlwarn("map file $mf: execute in $pkgfoundexecute, map file in $pkgcontained\n"); 5071 } 5072 } 5073 } 5074 } 5075 if (keys %badmaps) { 5076 tlwarn("$prg: mentioned map file not present in any package:\n"); 5077 foreach my $mf (keys %badmaps) { 5078 print "\t$mf (execute in @{$badmaps{$mf}})\n"; 5079 } 5080 } 5081 my %badhyphcodes; 5082 my %problemhyphen; 5083 foreach my $lc (keys %langcodes) { 5084 next if ($lc eq "zerohyph.tex"); 5085 my @found = $localtlpdb->find_file("texmf-dist/tex/generic/hyph-utf8/loadhyph/$lc"); 5086 if ($#found < 0) { 5087 # try again this time search all packages 5088 my @found = $localtlpdb->find_file("$lc"); 5089 if ($#found < 0) { 5090 $badhyphcodes{$lc} = $langcodes{$lc}; 5091 } else { 5092 $problemhyphen{$lc} = [ @found ]; 5093 } 5094 } 5095 } 5096 if (keys %badhyphcodes) { 5097 print "\f mentioned hyphen loaders without file:\n"; 5098 foreach my $mf (keys %badhyphcodes) { 5099 print "\t$mf (execute in @{$badhyphcodes{$mf}})\n"; 5100 } 5101 } 5102 # disable the echoing of problematic hyphens 5103 #if (keys %problemhyphen) { 5104 # print "hyphen files with possible problematic location:\n"; 5105 # foreach my $mf (keys %problemhyphen) { 5106 # print "\t$mf (@{$problemhyphen{$mf}})\n"; 5107 # } 5108 #} 5109 # 5110 # what should be checked for the executes? we could check 5111 # - the existence of the engine in bin/i386-linux or all $arch 5112 # - the existence of the format name link/bat 5113 # - parse the options parameter and check for the inifile 5114 # - rework the format definition that we have inifile=pdflatex.ini 5115 # isn't the * unnecessary? 5116 my %missingbins; 5117 my %missingengines; 5118 my %missinginis; 5119 for (keys %fmtlines) { 5120 my %r = TeXLive::TLUtils::parse_AddFormat_line("$_"); 5121 if (defined($r{"error"})) { 5122 die "$r{'error'}, parsing $_, package(s) @{$fmtlines{$_}}"; 5123 } 5124 my $opt = $r{"options"}; 5125 my $engine = $r{"engine"}; 5126 my $name = $r{"name"}; 5127 my $mode = $r{"mode"}; 5128 # special case for cont-en ... 5129 next if ($name eq "cont-en"); 5130 # we check that the name exist in bin/$arch 5131 my @archs_to_check = $localtlpdb->available_architectures; 5132 if ($engine eq "luajittex") { 5133 # luajittex is special since it is not available on all architectures 5134 # due to inherent reasons (machine code) 5135 # We do not want to have error messages here, so we do the following: 5136 # * if tlpkg/tlpsrc/luatex.tlpsrc is available, then load it 5137 # and filter away those archs that are excluded with f/!... 5138 # * if tlpkg/tlpsrc/luatex.tlpsrc is *not* available (user installation) 5139 # we just ignore it completely. 5140 my $tlpsrc_file = $localtlpdb->root . "/tlpkg/tlpsrc/luatex.tlpsrc"; 5141 if (-r $tlpsrc_file) { 5142 require TeXLive::TLPSRC; 5143 my $tlpsrc = new TeXLive::TLPSRC; 5144 $tlpsrc->from_file($tlpsrc_file); 5145 my @binpats = $tlpsrc->binpatterns; 5146 my @negarchs; 5147 for my $p (@binpats) { 5148 if ($p =~ m%^(\w+)/(!?[-_a-z0-9,]+)\s+(.*)$%) { 5149 my $pt = $1; 5150 my $aa = $2; 5151 my $pr = $3; 5152 if ($pr =~ m!/luajittex$!) { 5153 # bingo, get the negative patterns 5154 if ($aa =~ m/^!(.*)$/) { 5155 @negarchs = split(/,/,$1); 5156 } 5157 } 5158 } 5159 } 5160 my %foo; 5161 for my $a (@archs_to_check) { 5162 $foo{$a} = 1; 5163 } 5164 for my $a (@negarchs) { 5165 delete $foo{$a} if defined($foo{$a}); 5166 } 5167 @archs_to_check = keys %foo; 5168 } else { 5169 @archs_to_check = (); 5170 } 5171 } 5172 for my $a (@archs_to_check) { 5173 my $f = "$Master/bin/$a/$name"; 5174 if (!check_file($a, $f)) { 5175 push @{$missingbins{$_}}, "bin/$a/$name" if $mode; 5176 } 5177 if (!check_file($a, "$Master/bin/$a/$engine")) { 5178 push @{$missingengines{$_}}, "bin/$a/$engine" if $mode; 5179 } 5180 } 5181 # check for the existence of the .ini file 5182 # by using the last word in the options value 5183 my $inifile = $opt; 5184 # $inifile now contains "bla bla bla *file.ini" 5185 # strip initial and trailing " 5186 $inifile =~ s/^"(.*)"$/$1/; 5187 # remove everything before the last space 5188 $inifile =~ s/^.* ([^ ]*)$/$1/; 5189 # remove the optional leading * 5190 $inifile =~ s/^\*//; 5191 my @found = $localtlpdb->find_file("$inifile"); 5192 if ($#found < 0) { 5193 $missinginis{$_} = "$inifile"; 5194 } 5195 } 5196 if (keys %missinginis) { 5197 print "\f mentioned ini files that cannot be found:\n"; 5198 for my $i (keys %missinginis) { 5199 print "\t $missinginis{$i} (execute: $i)\n"; 5200 } 5201 } 5202 if (keys %missingengines) { 5203 print "\f mentioned engine files that cannot be found:\n"; 5204 for my $i (keys %missingengines) { 5205 print "\t @{$missingengines{$i}}\n"; 5206 } 5207 } 5208 if (keys %missingbins) { 5209 print "\f mentioned bin files that cannot be found:\n"; 5210 for my $i (keys %missingbins) { 5211 print "\t @{$missingbins{$i}}\n"; 5212 } 5213 } 5214} 5215 5216sub check_file { 5217 my ($a, $f) = @_; 5218 if (-r $f) { 5219 return 1; 5220 } else { 5221 # not -r, so check for the extensions .bat and .exe on windoze-ish. 5222 if ($a =~ /win[0-9]|.*-cygwin/) { 5223 if (-r "$f.exe" || -r "$f.bat") { 5224 return 1; 5225 } 5226 } 5227 return 0; 5228 } 5229} 5230 5231# check depends 5232# 5233sub check_depends { 5234 my $ret = 0; 5235 my $Master = $localtlpdb->root; 5236 my %presentpkg; 5237 for my $pkg ($localtlpdb->list_packages) { 5238 $presentpkg{$pkg} = 1; 5239 } 5240 # list of collections. 5241 my @colls = $localtlpdb->collections; 5242 my @coll_deps 5243 = $localtlpdb->expand_dependencies("-no-collections", $localtlpdb, @colls); 5244 my %coll_deps; 5245 @coll_deps{@coll_deps} = (); # initialize hash with keys from list 5246 5247 my (%wrong_dep, @no_dep); 5248 for my $pkg ($localtlpdb->list_packages) { 5249 # do not check any package starting with 00texlive. 5250 next if $pkg =~ m/^00texlive/; 5251 5252 # For each package, check that it is a dependency of some collection. 5253 if (! exists $coll_deps{$pkg}) { 5254 # Except that schemes and our ugly Windows packages are ok. 5255 push (@no_dep, $pkg) unless $pkg =~/^scheme-|\.win32$/; 5256 } 5257 5258 # For each dependency, check that we have a package. 5259 for my $d ($localtlpdb->get_package($pkg)->depends) { 5260 next if ($d =~ m/\.ARCH$/); 5261 if (!defined($presentpkg{$d})) { 5262 push (@{$wrong_dep{$d}}, $pkg); 5263 } 5264 } 5265 } 5266 5267 # check whether packages are included more than one time in a collection 5268 my %pkg2mother; 5269 for my $c (@colls) { 5270 for my $p ($localtlpdb->get_package($c)->depends) { 5271 next if ($p =~ /^collection-/); 5272 push @{$pkg2mother{$p}}, $c; 5273 } 5274 } 5275 my @double_inc_pkgs; 5276 for my $k (keys %pkg2mother) { 5277 if (@{$pkg2mother{$k}} > 1) { 5278 push @double_inc_pkgs, $k; 5279 } 5280 } 5281 5282 if (keys %wrong_dep) { 5283 $ret++; 5284 print "\f DEPENDS WITHOUT PACKAGES:\n"; 5285 for my $d (keys %wrong_dep) { 5286 print "$d in: @{$wrong_dep{$d}}\n"; 5287 } 5288 } 5289 5290 if (@no_dep) { 5291 $ret++; 5292 print "\f PACKAGES NOT IN ANY COLLECTION: @no_dep\n"; 5293 } 5294 5295 if (@double_inc_pkgs) { 5296 $ret++; 5297 print "\f PACKAGES IN MORE THAN ONE COLLECTION: @double_inc_pkgs\n"; 5298 } 5299 5300 return $ret; 5301} 5302 5303# POSTACTION 5304# explictly run the various post actions, e.g., 5305# on a client system or overriding global settings. 5306# 5307# tlmgr postaction [--w32mode=user|admin] [--fileassocmode=1|2] [--all] 5308# [install|remove] [shortcut|fileassoc|script] [<pkg>...] 5309 5310sub action_postaction { 5311 my $how = shift @ARGV; 5312 if (!defined($how) || ($how !~ m/^(install|remove)$/i)) { 5313 tlwarn("action postaction needs at least two arguments, first being either 'install' or 'remove'\n"); 5314 return; 5315 } 5316 my $type = shift @ARGV; 5317 my $badtype = 0; 5318 if (!defined($type)) { 5319 $badtype = 1; 5320 } elsif ($type !~ m/^(shortcut|fileassoc|script)$/i) { 5321 $badtype = 1; 5322 } 5323 if ($badtype) { 5324 tlwarn("action postaction needs as second argument one from 'shortcut', 'fileassoc', 'script'\n"); 5325 return; 5326 } 5327 if (win32()) { 5328 if ($opts{"w32mode"}) { 5329 if ($opts{"w32mode"} eq "user") { 5330 if (TeXLive::TLWinGoo::admin()) { 5331 debug("Switching to user mode on user request\n"); 5332 TeXLive::TLWinGoo::non_admin(); 5333 } 5334 # in user mode we also switch TEXMFSYSVAR to TEXMFVAR since 5335 # xetex.pl, but maybe others are writing to TEXMFSYSVAR 5336 chomp($ENV{"TEXMFSYSVAR"} = `kpsewhich -var-value TEXMFVAR`); 5337 } elsif ($opts{"w32mode"} eq "admin") { 5338 if (!TeXLive::TLWinGoo::admin()) { 5339 tlwarn("You don't have the permissions for --w32mode=admin\n"); 5340 return; 5341 } 5342 } else { 5343 tlwarn("action postaction --w32mode can only be 'admin' or 'user'\n"); 5344 return; 5345 } 5346 } 5347 } 5348 my @todo; 5349 if ($opts{"all"}) { 5350 init_local_db(); 5351 @todo = $localtlpdb->list_packages; 5352 } else { 5353 if ($#ARGV < 0) { 5354 tlwarn("action postaction: need either --all or a list of packages\n"); 5355 return; 5356 } 5357 init_local_db(); 5358 @todo = @ARGV; 5359 @todo = $localtlpdb->expand_dependencies("-only-arch", $localtlpdb, @todo); 5360 } 5361 if ($type =~ m/^shortcut$/i) { 5362 if (!win32()) { 5363 tlwarn("action postaction shortcut only works on windows.\n"); 5364 return; 5365 } 5366 for my $p (@todo) { 5367 my $tlp = $localtlpdb->get_package($p); 5368 if (!defined($tlp)) { 5369 tlwarn("$p is not installed, ignoring it.\n"); 5370 } else { 5371 # run all shortcut actions, desktop and menu integration 5372 TeXLive::TLUtils::do_postaction($how, $tlp, 0, 1, 1, 0); 5373 } 5374 } 5375 } elsif ($type =~ m/^fileassoc$/i) { 5376 if (!win32()) { 5377 tlwarn("action postaction fileassoc only works on windows.\n"); 5378 return; 5379 } 5380 my $fa = $localtlpdb->option("file_assocs"); 5381 if ($opts{"fileassocmode"}) { 5382 if ($opts{"fileassocmode"} < 1 || $opts{"fileassocmode"} > 2) { 5383 tlwarn("action postaction: value of --fileassocmode can only be 1 or 2\n"); 5384 return; 5385 } 5386 $fa = $opts{"fileassocmode"}; 5387 } 5388 for my $p (@todo) { 5389 my $tlp = $localtlpdb->get_package($p); 5390 if (!defined($tlp)) { 5391 tlwarn("$p is not installed, ignoring it.\n"); 5392 } else { 5393 TeXLive::TLUtils::do_postaction($how, $tlp, $fa, 0, 0, 0); 5394 } 5395 } 5396 } elsif ($type =~ m/^script$/i) { 5397 for my $p (@todo) { 5398 my $tlp = $localtlpdb->get_package($p); 5399 if (!defined($tlp)) { 5400 tlwarn("$p is not installed, ignoring it.\n"); 5401 } else { 5402 TeXLive::TLUtils::do_postaction($how, $tlp, 0, 0, 0, 1); 5403 } 5404 } 5405 } else { 5406 tlwarn("action postaction needs one of 'shortcut', 'fileassoc', 'script'\n"); 5407 return; 5408 } 5409} 5410 5411# INIT USER TREE 5412# sets up the user tree for tlmgr in user mode 5413sub action_init_usertree { 5414 # init_local_db but do not die if localtlpdb is not found! 5415 init_local_db(2); 5416 my $tlpdb = TeXLive::TLPDB->new; 5417 my $usertree; 5418 if ($opts{"usertree"}) { 5419 $usertree = $opts{"usertree"}; 5420 } else { 5421 chomp($usertree = `kpsewhich -var-value TEXMFHOME`); 5422 } 5423 if (-r "$usertree/$InfraLocation/$DatabaseName") { 5424 tldie("$prg: user mode database already set up in\n$prg: $usertree/$InfraLocation/$DatabaseName\n$prg: not overwriting it.\n"); 5425 } 5426 $tlpdb->root($usertree); 5427 # copy values from main installation over 5428 my $maininsttlp; 5429 my $inst; 5430 if (defined($localtlpdb)) { 5431 $maininsttlp = $localtlpdb->get_package("00texlive.installation"); 5432 $inst = $maininsttlp->copy; 5433 } else { 5434 $inst = TeXLive::TLPOBJ->new; 5435 $inst->name("00texlive.installation"); 5436 $inst->category("TLCore"); 5437 } 5438 $tlpdb->add_tlpobj($inst); 5439 # remove all available architectures 5440 $tlpdb->setting( "available_architectures", ""); 5441 $tlpdb->option( "location", $TeXLive::TLConfig::TeXLiveURL); 5442 # specify that we are in user mode 5443 $tlpdb->setting( "usertree", 1 ); 5444 $tlpdb->save; 5445 # 5446 # we need to create web2c dir for TLMedia to succeed setting up 5447 # and for tlmgr.log file 5448 mkdir ("$usertree/web2c"); 5449 mkdir ("$usertree/tlpkg/tlpobj"); 5450} 5451 5452# CONF 5453# tries to mimic texconfig conf but can also set values for both tlmgr 5454# and texmf conf files. 5455# 5456sub action_conf { 5457 my $arg = shift @ARGV; 5458 if (!defined($arg)) { 5459 texconfig_conf_mimic(); 5460 return; 5461 } 5462 if ($arg eq "tlmgr" || $arg eq "texmf" || $arg eq "updmap") { 5463 my ($fn,$cf); 5464 if ($opts{'conffile'}) { 5465 $fn = $opts{'conffile'} ; 5466 } 5467 if ($arg eq "tlmgr") { 5468 chomp (my $TEXMFCONFIG = `kpsewhich -var-value=TEXMFCONFIG`); 5469 $fn || ( $fn = "$TEXMFCONFIG/tlmgr/config" ) ; 5470 $cf = TeXLive::TLConfFile->new($fn, "#", "="); 5471 } elsif ($arg eq "texmf") { 5472 $fn || ( $fn = "$Master/tlpkg/texmf.cnf" ) ; 5473 $cf = TeXLive::TLConfFile->new($fn, "[%#]", "="); 5474 } elsif ($arg eq "updmap") { 5475 $fn || ( chomp ($fn = `kpsewhich updmap.cfg`) ) ; 5476 $cf = TeXLive::TLConfFile->new($fn, '(#|(Mixed)?Map)', ' '); 5477 } else { 5478 die "Should not happen, conf arg=$arg"; 5479 } 5480 my ($key,$val) = @ARGV; 5481 if (!defined($key)) { 5482 # show all settings 5483 if ($cf) { 5484 info("$arg configuration values (from $fn):\n"); 5485 for my $k ($cf->keys) { 5486 info("$k = " . $cf->value($k) . "\n"); 5487 } 5488 } else { 5489 info("$arg config file $fn not present\n"); 5490 } 5491 } else { 5492 if (!defined($val)) { 5493 if (defined($opts{'delete'})) { 5494 if (defined($cf->value($key))) { 5495 info("removing setting $arg $key value: " . $cf->value($key) . "from $fn\n"); 5496 $cf->delete_key($key); 5497 } else { 5498 info("$arg $key not defined, cannot remove ($fn)\n"); 5499 } 5500 } else { 5501 if (defined($cf->value($key))) { 5502 info("$arg $key value: " . $cf->value($key) . " ($fn)\n"); 5503 } else { 5504 info("$key not defined in $arg config file ($fn)\n"); 5505 if ($arg eq "texmf") { 5506 # not in user-specific file, show anything kpsewhich gives us. 5507 chomp (my $defval = `kpsewhich -var-value $key`); 5508 if ($? != 0) { 5509 info("$arg $key default value is unknown"); 5510 } else { 5511 info("$arg $key default value: $defval"); 5512 } 5513 info(" (kpsewhich -var-value)\n"); 5514 } 5515 } 5516 } 5517 } else { 5518 if (defined($opts{'delete'})) { 5519 warning("$arg --delete and value for key $key given, don't know what to do!\n"); 5520 } else { 5521 info("setting $arg $key to $val (in $fn)\n"); 5522 $cf->value($key, $val); 5523 } 5524 } 5525 } 5526 if ($cf->is_changed) { 5527 $cf->save; 5528 } 5529 } else { 5530 warn "$prg: unknown conf arg: $arg (try tlmgr or texmf or updmap)\n"; 5531 } 5532} 5533 5534# output various values in same form as texconfig conf. 5535sub texconfig_conf_mimic { 5536 my $PATH = $ENV{'PATH'}; 5537 info("=========================== version information ==========================\n"); 5538 info(give_version()); 5539 info("==================== executables found by searching PATH =================\n"); 5540 info("PATH: $PATH\n"); 5541 for my $cmd (qw/kpsewhich updmap fmtutil tlmgr tex pdftex mktexpk 5542 dvips dvipdfmx/) { 5543 info("$cmd: " . TeXLive::TLUtils::which($cmd) . "\n"); 5544 } 5545 info("=========================== active config files ==========================\n"); 5546 for my $m (qw/texmf.cnf updmap.cfg/) { 5547 for my $f (`kpsewhich -all $m`) { 5548 info("$m: $f"); 5549 } 5550 } 5551 for my $m (qw/fmtutil.cnf config.ps mktex.cnf pdftexconfig.tex/) { 5552 info("$m: " . `kpsewhich $m`); 5553 } 5554 5555 #tlwarn("missing finding of XDvi, config!\n"); 5556 5557 info("============================= font map files =============================\n"); 5558 for my $m (qw/psfonts.map pdftex.map ps2pk.map kanjix.map/) { 5559 info("$m: " . `kpsewhich $m`); 5560 } 5561 5562 info("=========================== kpathsea variables ===========================\n"); 5563 for my $v (qw/TEXMFMAIN TEXMFDIST TEXMFLOCAL TEXMFSYSVAR TEXMFSYSCONFIG TEXMFVAR TEXMFCONFIG TEXMFHOME VARTEXFONTS TEXMF SYSTEXMF TEXMFDBS WEB2C TEXPSHEADERS TEXCONFIG ENCFONTS TEXFONTMAPS/) { 5564 info("$v=" . `kpsewhich -var-value=$v`); 5565 } 5566 5567 info("==== kpathsea variables from environment only (ok if no output here) ====\n"); 5568 my @envVars = qw/ 5569 AFMFONTS BIBINPUTS BSTINPUTS CMAPFONTS CWEBINPUTS ENCFONTS GFFONTS 5570 GLYPHFONTS INDEXSTYLE LIGFONTS MFBASES MFINPUTS MFPOOL MFTINPUTS 5571 MISCFONTS MPINPUTS MPMEMS MPPOOL MPSUPPORT OCPINPUTS OFMFONTS 5572 OPENTYPEFONTS OPLFONTS OTPINPUTS OVFFONTS OVPFONTS PDFTEXCONFIG PKFONTS 5573 PSHEADERS SFDFONTS T1FONTS T1INPUTS T42FONTS TEXBIB TEXCONFIG TEXDOCS 5574 TEXFONTMAPS TEXFONTS TEXFORMATS TEXINDEXSTYLE TEXINPUTS TEXMFCNF 5575 TEXMFDBS TEXMFINI TEXMFSCRIPTS TEXPICTS TEXPKS TEXPOOL TEXPSHEADERS 5576 TEXSOURCES TFMFONTS TRFONTS TTFONTS VFFONTS WEB2C WEBINPUTS 5577 /; 5578 for my $v (@envVars) { 5579 if (defined($ENV{$v})) { 5580 info("$v=$ENV{$v}\n"); 5581 } 5582 } 5583} 5584 5585 5586# Subroutines galore. 5587# 5588# set global $location variable. 5589# 5590# argument $should_i_die specifies what is requried 5591# to suceed during initialization. 5592# 5593# undef or false: TLPDB needs to be found and initialized, but 5594# support programs need not be found 5595# 1 : TLPDB initialized and support programs must work 5596# 2 : not even TLPDB needs to be found 5597# if we cannot read tlpdb, die if arg SHOULD_I_DIE is true. 5598# 5599# if an argument is given and is true init_local_db will die if 5600# setting up of programs failed. 5601# 5602sub init_local_db { 5603 my ($should_i_die) = @_; 5604 defined($should_i_die) or ($should_i_die = 0); 5605 # if the localtlpdb is already defined do simply return here already 5606 # to make sure that the settings in the local tlpdb do not overwrite 5607 # stuff changed via the GUI 5608 return if defined $localtlpdb; 5609 $localtlpdb = TeXLive::TLPDB->new ( root => $::maintree ); 5610 if (!defined($localtlpdb)) { 5611 if ($should_i_die == 2) { 5612 return undef; 5613 } else { 5614 die("cannot setup TLPDB in $::maintree"); 5615 } 5616 } 5617 # setup the programs, for w32 we need the shipped wget/xz etc, so we 5618 # pass the location of these files to setup_programs. 5619 if (!setup_programs("$Master/tlpkg/installer", $localtlpdb->platform)) { 5620 tlwarn("Couldn't set up the necessary programs.\nInstallation of packages is not supported.\nPlease report to texlive\@tug.org.\n"); 5621 if (defined($should_i_die) && $should_i_die) { 5622 return ($F_ERROR); 5623 } else { 5624 tlwarn("Continuing anyway ...\n"); 5625 return ($F_WARNING); 5626 } 5627 } 5628 # let cmd line options override the settings in localtlpdb 5629 my $loc = norm_tlpdb_path($localtlpdb->option("location")); 5630 if (defined($loc)) { 5631 $location = $loc; 5632 } 5633 if (defined($opts{"location"})) { 5634 $location = $opts{"location"}; 5635 } 5636 if (!defined($location)) { 5637 die("$prg: No installation source found: neither in texlive.tlpdb nor on command line.\n$prg: Please specify one!"); 5638 } 5639 if ($location =~ m/^ctan$/i) { 5640 $location = "$TeXLive::TLConfig::TeXLiveURL"; 5641 } 5642 # we normalize the path only if it is 5643 # - a url starting with neither http or ftp 5644 # - if we are on Windows, it does not start with Drive:[\/] 5645 if (! ( $location =~ m!^(http|ftp)://!i || 5646 (win32() && (!(-e $location) || ($location =~ m!^.:[\\/]!) ) ) ) ) { 5647 # seems to be a local path, try to normalize it 5648 my $testloc = abs_path($location); 5649 # however, if we were given a url, that will get "normalized" to the 5650 # empty string, it not being a path. Restore the original value if so. 5651 $location = $testloc if $testloc; 5652 } 5653} 5654 5655 5656# initialize the global $remotetlpdb object, or die. 5657# uses the global $location. 5658# 5659sub init_tlmedia_or_die { 5660 my ($ret, $err) = init_tlmedia(); 5661 if (!$ret) { 5662 tldie("$prg: $err\n"); 5663 } 5664} 5665 5666sub init_tlmedia 5667{ 5668 # first check if $location contains multiple locations 5669 # in this case we go to virtual mode 5670 #my %repos = repository_to_array($localtlpdb->option("location")); 5671 my %repos = repository_to_array($location); 5672 my @tags = keys %repos; 5673 # if we have only one repo, but this one contains a name tag #.... 5674 # then we remove it and save the local tlpdb 5675 if ($#tags == 0 && ($location =~ m/#/)) { 5676 $location = $repos{$tags[0]}; 5677 $localtlpdb->option("location", $location); 5678 $localtlpdb->save; 5679 %repos = repository_to_array($location); 5680 } 5681 # check if we are only one tag/repo 5682 if ($#tags == 0) { 5683 # go to normal mode 5684 return _init_tlmedia(); 5685 } 5686 # we are still here, so we have more tags 5687 5688 # check that there is a main repository 5689 if (!TeXLive::TLUtils::member('main', @tags)) { 5690 return(0, "Cannot find main repository, you have to tag one as main!"); 5691 } 5692 5693 # TODO TODO 5694 # - abstract the set up of a single media tlpdb 5695 # - make clear how to check for a already loaded remotetlpdb 5696 $remotetlpdb = TeXLive::TLPDB->new(); 5697 $remotetlpdb->make_virtual; 5698 5699 my $locstr = $repos{'main'}; 5700 my ($tlmdb, $errormsg) = setup_one_remotetlpdb($locstr); 5701 if (!defined($tlmdb)) { 5702 return (0, $errormsg); 5703 } 5704 $remotetlpdb->virtual_add_tlpdb($tlmdb, "main"); 5705 for my $t (@tags) { 5706 if ($t ne 'main') { 5707 my ($tlmdb, $errormsg) = setup_one_remotetlpdb($repos{$t}); 5708 if (!defined($tlmdb)) { 5709 return(0, $errormsg); 5710 } 5711 $remotetlpdb->virtual_add_tlpdb($tlmdb, $t); 5712 $locstr .= " $repos{$t}"; 5713 } 5714 } 5715 5716 # now check/setup pinning 5717 if (!$opts{"pin-file"}) { 5718 # check for pinning file in TEXMFLOCAL/tlpkg/pinning.txt 5719 chomp (my $TEXMFLOCAL = `kpsewhich -var-value=TEXMFLOCAL`); 5720 debug("trying to load pinning file $TEXMFLOCAL/tlpkg/pinning.txt\n"); 5721 # since we use TLConfFile it does not matter if the file 5722 # is not existing, it will be treated properly in TLConfFile 5723 $opts{"pin-file"} = "$TEXMFLOCAL/tlpkg/pinning.txt"; 5724 } 5725 $pinfile = TeXLive::TLConfFile->new($opts{"pin-file"}, "#", ":", 'multiple'); 5726 $remotetlpdb->virtual_pinning($pinfile); 5727 # this "location-url" line should not be changed since GUI programs 5728 # depend on it: 5729 print "location-url\t$locstr\n" if $::machinereadable; 5730 info("$prg: package repositories:\n"); 5731 info("\tmain = " . $repos{'main'} . "\n"); 5732 for my $t (@tags) { 5733 if ($t ne 'main') { 5734 info("\t$t = " . $repos{$t} . "\n"); 5735 } 5736 } 5737 return 1; 5738} 5739 5740 5741 5742 5743sub _init_tlmedia 5744{ 5745 5746 # if we are already initialized to the same location, nothing 5747 # needs to be done. 5748 # if we are initialized to a virtual tlpdb, then we have to 5749 # do in any case an initialization 5750 if (defined($remotetlpdb) && !$remotetlpdb->is_virtual && 5751 ($remotetlpdb->root eq $location)) { 5752 # nothing to be done 5753 return 1; 5754 } 5755 5756 # choose a mirror if we are asked. 5757 if ($location =~ m/^ctan$/i) { 5758 $location = give_ctan_mirror(); 5759 } elsif ($location =~ m,^$TeXLiveServerURL,) { 5760 my $mirrorbase = TeXLive::TLUtils::give_ctan_mirror_base(); 5761 $location =~ s,^$TeXLiveServerURL,$mirrorbase,; 5762 } 5763 5764 my $errormsg; 5765 ($remotetlpdb, $errormsg) = setup_one_remotetlpdb($location); 5766 if (!defined($remotetlpdb)) { 5767 return(0, $errormsg); 5768 } 5769 5770 5771 # this "location-url" line should not be changed since GUI programs 5772 # depend on it: 5773 print "location-url\t$location\n" if $::machinereadable; 5774 info("$prg: package repository $location\n"); 5775 return 1; 5776} 5777 5778sub setup_one_remotetlpdb 5779{ 5780 my $location = shift; 5781 my $remotetlpdb; 5782 5783 # TODO 5784 # check if that is already loaded!!! 5785 5786 # choose a mirror if we are asked. 5787 if ($location =~ m/^ctan$/i) { 5788 $location = give_ctan_mirror(); 5789 } elsif ($location =~ m,^$TeXLiveServerURL,) { 5790 my $mirrorbase = TeXLive::TLUtils::give_ctan_mirror_base(); 5791 $location =~ s,^$TeXLiveServerURL,$mirrorbase,; 5792 } 5793 5794 # if we talk about a net location try to download the hash of the tlpdb 5795 # - if that is possible, check for the locally saved file and if the hash 5796 # agrees load the local copy if present instead of the remote one, 5797 # if the hashes disagree, load the remote tlpdb 5798 # - if that does not work assume we are offline or target not reachable, 5799 # so warn the user and use saved, but note that installation will 5800 # not work 5801 5802 my $local_copy_tlpdb_used = 0; 5803 if ($location =~ m;^(http|ftp)://;) { 5804 # first check that the saved tlpdb is present at all 5805 my $loc_digest = Digest::MD5::md5_hex($location); 5806 my $loc_copy_of_remote_tlpdb = 5807 "$Master/$InfraLocation/texlive.tlpdb.$loc_digest"; 5808 ddebug("loc_digest = $loc_digest\n"); 5809 ddebug("loc_copy = $loc_copy_of_remote_tlpdb\n"); 5810 if (-r $loc_copy_of_remote_tlpdb) { 5811 ddebug("loc copy found!\n"); 5812 # we found the tlpdb matching the current location 5813 # check for the remote hash 5814 my $path = "$location/$InfraLocation/$DatabaseName.md5"; 5815 ddebug("remote path of digest = $path\n"); 5816 my $fh = TeXLive::TLUtils::download_file($path, "|"); 5817 my $rem_digest; 5818 if (read ($fh, $rem_digest, 32) != 32) { 5819 info(<<END_NO_INTERNET); 5820Unable to download the remote TeX Live database, 5821but found a local copy so using that. 5822 5823You may want to try specifying an explicit or different CTAN mirror; 5824see the information and examples for the -repository option at 5825http://tug.org/texlive/doc/install-tl.html 5826(or in the output of install-tl --help). 5827 5828END_NO_INTERNET 5829 # above text duplicated in install-tl 5830 5831 $remotetlpdb = TeXLive::TLPDB->new(root => $location, 5832 tlpdbfile => $loc_copy_of_remote_tlpdb); 5833 $local_copy_tlpdb_used = 1; 5834 } else { 5835 ddebug("found remote digest: $rem_digest\n"); 5836 my $rem_copy_digest = TeXLive::TLUtils::tlmd5($loc_copy_of_remote_tlpdb); 5837 ddebug("rem_copy_digest = $rem_copy_digest\n"); 5838 if ($rem_copy_digest eq $rem_digest) { 5839 debug("md5 of local copy identical with remote hash\n"); 5840 $remotetlpdb = TeXLive::TLPDB->new(root => $location, 5841 tlpdbfile => $loc_copy_of_remote_tlpdb); 5842 $local_copy_tlpdb_used = 1; 5843 } 5844 } 5845 } 5846 } 5847 if (!$local_copy_tlpdb_used) { 5848 $remotetlpdb = TeXLive::TLPDB->new(root => $location); 5849 } 5850 if (!defined($remotetlpdb)) { 5851 return(undef, $loadmediasrcerror . $location); 5852 } 5853 # we allow a range of years to be specified by the remote tlpdb 5854 # for which it might work. 5855 # the lower limit is TLPDB->config_minrelease 5856 # the upper limit is TLPDB->config_release 5857 # if the later is not present only the year in config_release is accepted 5858 # checks are done on the first 4 digits only 5859 # Why only the first four places: some optional network distributions 5860 # might use 5861 # release/2009-foobar 5862 # If it should work for 2009 and 2010, please use 5863 # minrelease/2009-foobar 5864 # release/2010-foobar 5865 my $texlive_release = $remotetlpdb->config_release; 5866 my $texlive_minrelease = $remotetlpdb->config_minrelease; 5867 my $rroot = $remotetlpdb->root; 5868 if (!defined($texlive_release)) { 5869 return(undef, "The installation repository ($rroot) does not specify a " 5870 . "release year for which it was prepared, goodbye."); 5871 } 5872 # still here, so we have $texlive_release defined 5873 my $texlive_release_year = $texlive_release; 5874 $texlive_release_year =~ s/^(....).*$/$1/; 5875 if ($texlive_release_year !~ m/^[1-9][0-9][0-9][0-9]$/) { 5876 return(undef, "The installation repository ($rroot) does not specify a " 5877 . "valid release year, goodbye: $texlive_release"); 5878 } 5879 # so $texlive_release_year is numeric, good 5880 if (defined($texlive_minrelease)) { 5881 # we specify a range of years! 5882 my $texlive_minrelease_year = $texlive_minrelease; 5883 $texlive_minrelease_year =~ s/^(....).*$/$1/; 5884 if ($texlive_minrelease_year !~ m/^[1-9][0-9][0-9][0-9]$/) { 5885 return(undef, "The installation repository ($rroot) does not specify a " 5886 . "valid minimal release year, goodbye: $texlive_minrelease"); 5887 } 5888 # ok, all numeric and fine, check for range 5889 if ($TeXLive::TLConfig::ReleaseYear < $texlive_minrelease_year 5890 || $TeXLive::TLConfig::ReleaseYear > $texlive_release_year) { 5891 return (undef, "The TeX Live versions supported by the repository 5892$rroot 5893 ($texlive_minrelease_year--$texlive_release_year) 5894do not include the version of the local installation 5895 ($TeXLive::TLConfig::ReleaseYear)."); 5896 } 5897 } else { 5898 # $texlive_minrelease not defined, so only one year is valid 5899 if ($texlive_release_year != $TeXLive::TLConfig::ReleaseYear) { 5900 return(undef, "The TeX Live versions of the local installation 5901and the repository are not compatible: 5902 local: $TeXLive::TLConfig::ReleaseYear 5903 repository: $texlive_release_year ($rroot) 5904(Perhaps you need to use a different CTAN mirror? Just a guess.)"); 5905 } 5906 } 5907 5908 # check for being frozen 5909 if ($remotetlpdb->option("frozen")) { 5910 my $frozen_msg = <<FROZEN; 5911TeX Live $TeXLive::TLConfig::ReleaseYear is frozen forever and will no 5912longer be updated. This happens in preparation for a new release. 5913 5914If you're interested in helping to pretest the new release (when 5915pretests are available), please read http://tug.org/texlive/pretest.html. 5916Otherwise, just wait, and the new release will be ready in due time. 5917FROZEN 5918 # don't die here, we want to allow updates even if tlnet is frozen! 5919 tlwarn($frozen_msg); 5920 } 5921 5922 # save remote database if it is a net location 5923 # make sure that the writeout of the tlpdb is done in UNIX mode 5924 # since otherwise the sha256 will change. 5925 if (!$local_copy_tlpdb_used && $location =~ m;^(http|ftp)://;) { 5926 my $loc_digest = Digest::MD5::md5_hex($location); 5927 my $loc_copy_of_remote_tlpdb = 5928 "$Master/$InfraLocation/texlive.tlpdb.$loc_digest"; 5929 my $tlfh; 5930 if (!open($tlfh, ">:unix", $loc_copy_of_remote_tlpdb)) { 5931 # that should be only a debug statement, since a user without 5932 # write permission might have done a tlmgr search --global or 5933 # similar 5934 &debug("Cannot save remote TeX Live database to $loc_copy_of_remote_tlpdb: $!\n"); 5935 } else { 5936 &debug("writing out tlpdb to $loc_copy_of_remote_tlpdb\n"); 5937 $remotetlpdb->writeout($tlfh); 5938 close($tlfh); 5939 } 5940 } 5941 5942 return($remotetlpdb); 5943} 5944 5945 5946 5947# finish handles the -pause option (wait for input from stdin), 5948# and then exits unless the global $::gui_mode is set, in which case we 5949# merely return. 5950# 5951sub finish { 5952 my ($ret) = @_; 5953 5954 if ($ret > 0) { 5955 print "$prg: exiting unsuccessfully (status $ret).\n"; 5956 } 5957 5958 if ($::gui_mode) { 5959 return $ret; 5960 } else { 5961 exit($ret); 5962 } 5963} 5964 5965 5966# tlmgr config file handling. These config files are located in 5967# TEXMFCONFIG/tlmgr/config, thus specific for each user. 5968# 5969# format: 5970# key=value 5971# 5972sub load_config_file { 5973 # 5974 # first set default values 5975 # the default for gui-expertmode is 1 since that is what we 5976 # have shipped till now 5977 $config{"gui-expertmode"} = 1; 5978 # 5979 # by default we remove packages 5980 $config{"auto-remove"} = 1; 5981 5982 chomp (my $TEXMFCONFIG = `kpsewhich -var-value=TEXMFCONFIG`); 5983 my $fn = "$TEXMFCONFIG/tlmgr/config"; 5984 $tlmgr_config_file = TeXLive::TLConfFile->new($fn, "#", "="); 5985 5986 # switched names for this one after initial release. 5987 if ($tlmgr_config_file->key_present("gui_expertmode")) { 5988 $tlmgr_config_file->rename_key("gui_expertmode", "gui-expertmode"); 5989 } 5990 5991 for my $key ($tlmgr_config_file->keys) { 5992 my $val = $tlmgr_config_file->value($key); 5993 if ($key eq "gui-expertmode") { 5994 if ($val eq "0") { 5995 $config{"gui-expertmode"} = 0; 5996 } elsif ($val eq "1") { 5997 $config{"gui-expertmode"} = 1; 5998 } else { 5999 tlwarn("$fn: Unknown value for gui-expertmode: $val\n"); 6000 } 6001 6002 } elsif ($key eq "persistent-downloads") { 6003 if (($val eq "0") || ($val eq "1")) { 6004 $config{'persistent-downloads'} = $val; 6005 } else { 6006 tlwarn("$fn: Unknown value for persistent-downloads: $val\n"); 6007 } 6008 6009 } elsif ($key eq "gui-lang") { 6010 $config{'gui-lang'} = $val; 6011 6012 } elsif ($key eq "auto-remove") { 6013 if ($val eq "0") { 6014 $config{"auto-remove"} = 0; 6015 } elsif ($val eq "1") { 6016 $config{"auto-remove"} = 1; 6017 } else { 6018 tlwarn("$fn: Unknown value for auto-remove: $val\n"); 6019 } 6020 6021 } else { 6022 tlwarn("$fn: Unknown tlmgr configuration variable: $key\n"); 6023 } 6024 } 6025} 6026 6027sub write_config_file { 6028 if (!defined($tlmgr_config_file)) { 6029 chomp (my $TEXMFCONFIG = `kpsewhich -var-value=TEXMFCONFIG`); 6030 my $dn = "$TEXMFCONFIG/tlmgr"; 6031 my $fn = "$dn/config"; 6032 # create a new one 6033 $tlmgr_config_file = TeXLive::TLConfFile->new($fn, "#", "="); 6034 } 6035 for my $k (keys %config) { 6036 # it doesn't hurt to save all config settings as we check in TLConfFile 6037 # if the value has actually changed 6038 $tlmgr_config_file->value($k, $config{$k}); 6039 } 6040 # make sure that deleted config entries are carried over 6041 for my $k ($tlmgr_config_file->keys) { 6042 if (not(defined($config{$k}))) { 6043 $tlmgr_config_file->delete_key($k); 6044 } 6045 } 6046 if ($tlmgr_config_file->is_changed) { 6047 $tlmgr_config_file->save; 6048 } 6049} 6050 6051# if the packagelog variable is set then write to PACKAGELOG filehandle 6052# 6053sub logpackage 6054{ 6055 if ($packagelogfile) { 6056 $packagelogged++; 6057 my $tim = localtime(); 6058 print PACKAGELOG "[$tim] @_\n"; 6059 } 6060} 6061 6062# resolve relative paths from tlpdb wrt tlroot 6063sub norm_tlpdb_path 6064{ 6065 my ($path) = @_; 6066 return if (!defined($path)); 6067 $path =~ s!\\!/!; 6068 # just return if absolute path 6069 return $path if ($path =~ m!^/|:!); 6070 init_local_db() unless defined($localtlpdb); 6071 return $localtlpdb->root . "/$path"; 6072} 6073 6074# clear the backup dir for $pkg and keep only $autobackup packages 6075# mind that with $autobackup == 0 all packages are cleared 6076sub clear_old_backups 6077{ 6078 my ($pkg, $backupdir, $autobackup, $dry) = @_; 6079 6080 my $dryrun = 0; 6081 $dryrun = 1 if ($dry); 6082 # keep arbitrary many backups 6083 return if ($autobackup == -1); 6084 6085 opendir (DIR, $backupdir) || die "opendir($backupdir) failed: $!"; 6086 my @dirents = readdir (DIR); 6087 closedir (DIR) || warn "closedir($backupdir) failed: $!"; 6088 my @backups; 6089 for my $dirent (@dirents) { 6090 next if (-d $dirent); 6091 next if ($dirent !~ m/^$pkg\.r([0-9]+)\.tar\.xz$/); 6092 push @backups, $1; 6093 } 6094 my $i = 1; 6095 for my $e (reverse sort {$a <=> $b} @backups) { 6096 if ($i > $autobackup) { 6097 log ("Removing backup $backupdir/$pkg.r$e.tar.xz\n"); 6098 unlink("$backupdir/$pkg.r$e.tar.xz") unless $dryrun; 6099 } 6100 $i++; 6101 } 6102} 6103 6104# check for updates to tlcritical packages 6105# 6106sub check_for_critical_updates 6107{ 6108 my ($localtlpdb, $mediatlpdb) = @_; 6109 6110 my $criticalupdate = 0; 6111 my @critical = $localtlpdb->expand_dependencies("-no-collections", 6112 $localtlpdb, @CriticalPackagesList); 6113 my @critical_upd; 6114 for my $pkg (sort @critical) { 6115 my $tlp = $localtlpdb->get_package($pkg); 6116 if (!defined($tlp)) { 6117 # that should not happen, we expanded in the localtlpdb so why 6118 # should it not be present, any anyway, those are so fundamental 6119 # so they have to be there 6120 tlwarn("\nFundamental package $pkg not present, uh oh, goodbye"); 6121 die "Should not happen, $pkg not found"; 6122 } 6123 my $localrev = $tlp->revision; 6124 my $mtlp = $mediatlpdb->get_package($pkg); 6125 if (!defined($mtlp)) { 6126 debug("Very surprising, $pkg is not present in the remote tlpdb.\n"); 6127 next; 6128 } 6129 my $remoterev = $mtlp->revision; 6130 push (@critical_upd, $pkg) if ($remoterev > $localrev); 6131 } 6132 return(@critical_upd); 6133} 6134 6135sub critical_updates_warning { 6136 tlwarn("=" x 79, "\n"); 6137 tlwarn("tlmgr itself needs to be updated.\n"); 6138 tlwarn("Please do this via either\n"); 6139 tlwarn(" tlmgr update --self\n"); 6140 tlwarn("or by getting the latest updater for Unix-ish systems:\n"); 6141 tlwarn(" $TeXLiveURL/update-tlmgr-latest.sh\n"); 6142 tlwarn("and/or Windows systems:\n"); 6143 tlwarn(" $TeXLiveURL/update-tlmgr-latest.exe\n"); 6144 tlwarn("Then continue with other updates as usual.\n"); 6145 tlwarn("=" x 79, "\n"); 6146} 6147 6148# 6149# our compare function for package sorting, which makes sure that 6150# packages with .ARCH names are sorted *before* the main packages 6151sub packagecmp { 6152 my $aa = $a; 6153 my $bb = $b; 6154 # remove the part after the . if at all present 6155 $aa =~ s/\..*$//; 6156 $bb =~ s/\..*$//; 6157 if ($aa lt $bb) { 6158 return -1; 6159 } elsif ($aa gt $bb) { 6160 return 1; 6161 } else { 6162 # the parts before the . are the same 6163 # sort the .something *before* the ones without 6164 if ($a eq $aa && $b eq $bb) { 6165 return 0; 6166 } elsif ($a eq $aa) { 6167 # so $a = foobar 6168 # and $b = foobar.something 6169 # this is the special case where we want to invert the order 6170 return 1; 6171 } elsif ($b eq $bb) { 6172 # so $a = foobar.something 6173 # and $b = foobar 6174 return -1; 6175 } else { 6176 return ($a cmp $b); 6177 } 6178 } 6179} 6180 6181sub check_on_writable { 6182 return 1 if $opts{"usermode"}; 6183 if (!TeXLive::TLUtils::dir_writable("$Master/tlpkg")) { 6184 tlwarn("You don't have permission to change the installation in any way,\n"); 6185 tlwarn("specifically, the directory $Master/tlpkg/ is not writable.\n"); 6186 tlwarn("Please run this program as administrator, or contact your local admin.\n"); 6187 if ($opts{"dry-run"}) { 6188 tlwarn("Continuing due to --dry-run\n"); 6189 return 1; 6190 } else { 6191 return 0; 6192 } 6193 } 6194 return 1; 6195} 6196 61971; 6198__END__ 6199 6200=head1 NAME 6201 6202tlmgr - the TeX Live Manager 6203 6204=head1 SYNOPSIS 6205 6206tlmgr [I<option>]... I<action> [I<option>]... [I<operand>]... 6207 6208=head1 DESCRIPTION 6209 6210B<tlmgr> manages an existing TeX Live installation, both packages and 6211configuration options. For information on initially downloading and 6212installing TeX Live, see L<http://tug.org/texlive/acquire.html>. 6213 6214The most up-to-date version of this documentation (updated nightly from 6215the development sources) is available at 6216L<http://tug.org/texlive/tlmgr.html>, along with procedures for updating 6217C<tlmgr> itself and information about test versions. 6218 6219TeX Live is organized into a few top-level I<schemes>, each of which is 6220specified as a different set of I<collections> and I<packages>, where a 6221collection is a set of packages, and a package is what contains actual 6222files. Schemes typically contain a mix of collections and packages, but 6223each package is included in exactly one collection, no more and no less. 6224A TeX Live installation can be customized and managed at any level. 6225 6226See L<http://tug.org/texlive/doc> for all the TeX Live documentation 6227available. 6228 6229=head1 EXAMPLES 6230 6231After successfully installing TeX Live, here are a few common operations 6232with C<tlmgr>: 6233 6234=over 4 6235 6236=item C<tlmgr option repository http://mirror.ctan.org/systems/texlive/tlnet> 6237 6238Tell C<tlmgr> to use a nearby CTAN mirror for future updates; useful if 6239you installed TeX Live from the DVD image and want continuing updates. 6240 6241=item C<tlmgr update --list> 6242 6243Report what would be updated without actually updating anything. 6244 6245=item C<tlmgr update --all> 6246 6247Make your local TeX installation correspond to what is in the package 6248repository (typically useful when updating from CTAN). 6249 6250=item C<tlmgr info> I<what> 6251 6252Display detailed information about a package I<what>, such as the installation 6253status and description, of searches for I<what> in all packages. 6254 6255=back 6256 6257For all the capabilities and details of C<tlmgr>, please read the 6258following voluminous information. 6259 6260=head1 OPTIONS 6261 6262The following options to C<tlmgr> are global options, not specific to 6263any action. All options, whether global or action-specific, can be 6264given anywhere on the command line, and in any order. The first 6265non-option argument will be the main action. In all cases, 6266C<-->I<option> and C<->I<option> are equivalent, and an C<=> is optional 6267between an option name and its value. 6268 6269=over 4 6270 6271=item B<--repository> I<url|path> 6272 6273Specifies the package repository from which packages should be installed 6274or updated, overriding the default package repository found in the 6275installation's TeX Live Package Database (a.k.a. the TLPDB, defined 6276entirely in the file C<tlpkg/texlive.tlpdb>). The documentation for 6277C<install-tl> has more details about this 6278(L<http://tug.org/texlive/doc/install-tl.html>). 6279 6280C<--repository> changes the repository location only for the current 6281run; to make a permanent change, use C<option repository> (see the 6282L</option> action). 6283 6284For backward compatibility and convenience, C<--location> and C<--repo> 6285are accepted as aliases for this option. 6286 6287 6288=item B<--gui> [I<action>] 6289 6290C<tlmgr> has a graphical interface as well as the command line 6291interface. You can give this option, C<--gui>, together with an action 6292to be brought directly into the respective screen of the GUI. For 6293example, running 6294 6295 tlmgr --gui update 6296 6297starts you directly at the update screen. If no action is given, the 6298GUI will be started at the main screen. 6299 6300=for comment Keep language list in sync with install-tl. 6301 6302=item B<--gui-lang> I<llcode> 6303 6304By default, the GUI tries to deduce your language from the environment 6305(on Windows via the registry, on Unix via C<LC_MESSAGES>). If that fails 6306you can select a different language by giving this option with a 6307language code (based on ISO 639-1). Currently supported (but not 6308necessarily completely translated) are: English (en, default), Czech 6309(cs), German (de), French (fr), Italian (it), Japanese (ja), Dutch (nl), 6310Polish (pl), Brazilian Portuguese (pt_BR), Russian (ru), Slovak (sk), 6311Slovenian (sl), Serbian (sr), Ukrainian (uk), Vietnamese (vi), 6312simplified Chinese (zh_CN), and traditional Chinese (zh_TW). 6313 6314=item B<--debug-translation> 6315 6316In GUI mode, this switch tells C<tlmgr> to report any untranslated (or 6317missing) messages to standard error. This can help translators to see 6318what remains to be done. 6319 6320=item B<--machine-readable> 6321 6322Instead of the normal output intended for human consumption, write (to 6323standard output) a fixed format more suitable for machine parsing. See 6324the L</MACHINE-READABLE OUTPUT> section below. 6325 6326=item B<--no-execute-actions> 6327 6328Suppress the execution of the execute actions as defined in the tlpsrc 6329files. Documented only for completeness, as this is only useful in 6330debugging. 6331 6332=item B<--package-logfile> I<file> 6333 6334C<tlmgr> logs all package actions (install, remove, update, failed 6335updates, failed restores) to a separate log file, by default 6336C<TEXMFSYSVAR/web2c/tlmgr.log>. This option allows you to specific a 6337different file for the log. 6338 6339=item B<--pause> 6340 6341This option makes C<tlmgr> wait for user input before exiting. Useful on 6342Windows to avoid disappearing command windows. 6343 6344=item B<--persistent-downloads> 6345 6346=item B<--no-persistent-downloads> 6347 6348For network-based installations, this option (on by default) makes 6349C<tlmgr> try to set up a persistent connection (using the C<LWP> Perl 6350module). The idea is to open and reuse only one connection per session 6351between your computer and the server, instead of initiating a new 6352download for each package. 6353 6354If this is not possible, C<tlmgr> will fall back to using C<wget>. To 6355disable these persistent connections, use C<--no-persistent-downloads>. 6356 6357=item B<--pin-file> 6358 6359Change the pinning file location from C<TEXMFLOCAL/tlpkg/pinning.txt> 6360(see L</Pinning> below). Documented only for completeness, as this is 6361only useful in debugging. 6362 6363=item B<--usermode> 6364 6365Activates user mode for this run of C<tlmgr>; see L<USER MODE> below. 6366 6367=item B<--usertree> I<dir> 6368 6369Uses I<dir> for the tree in user mode; see L<USER MODE> below. 6370 6371=back 6372 6373The standard options for TeX Live programs are also accepted: 6374C<--help/-h/-?>, C<--version>, C<-q> (no informational messages), C<-v> 6375(debugging messages, can be repeated). For the details about these, see 6376the C<TeXLive::TLUtils> documentation. 6377 6378The C<--version> option shows version information about the TeX Live 6379release and about the C<tlmgr> script itself. If C<-v> is also given, 6380revision number for the loaded TeX Live Perl modules are shown, too. 6381 6382 6383=head1 ACTIONS 6384 6385=head2 help 6386 6387Display this help information and exit (same as C<--help>, and on the 6388web at L<http://tug.org/texlive/doc/tlmgr.html>). Sometimes the 6389C<perldoc> and/or C<PAGER> programs on the system have problems, 6390resulting in control characters being literally output. This can't 6391always be detected, but you can set the C<NOPERLDOC> environment 6392variable and C<perldoc> will not be used. 6393 6394=head2 version 6395 6396Gives version information (same as C<--version>). 6397 6398If C<-v> has been given the revisions of the used modules are reported, too. 6399 6400=head2 backup [--clean[=I<N>]] [--backupdir I<dir>] [--all | I<pkg>]... 6401 6402If the C<--clean> option is not specified, this action makes a backup of 6403the given packages, or all packages given C<--all>. These backups are 6404saved to the value of the C<--backupdir> option, if that is an existing and 6405writable directory. If C<--backupdir> is not given, the C<backupdir> 6406option setting in the TLPDB is used, if present. If both are missing, 6407no backups are made. 6408 6409If the C<--clean> option is specified, backups are pruned (removed) 6410instead of saved. The optional integer value I<N> may be specified to 6411set the number of backups that will be retained when cleaning. If C<N> 6412is not given, the value of the C<autobackup> option is used. If both are 6413missing, an error is issued. For more details of backup pruning, see 6414the C<option> action. 6415 6416Options: 6417 6418=over 4 6419 6420=item B<--backupdir> I<directory> 6421 6422Overrides the C<backupdir> option setting in the TLPDB. 6423The I<directory> argument is required and must specify an existing, 6424writable directory where backups are to be placed. 6425 6426=item B<--all> 6427 6428If C<--clean> is not specified, make a backup of all packages in the TeX 6429Live installation; this will take quite a lot of space and time. If 6430C<--clean> is specified, all packages are pruned. 6431 6432=item B<--clean>[=I<N>] 6433 6434Instead of making backups, prune the backup directory of old backups, as 6435explained above. The optional integer argument I<N> overrides the 6436C<autobackup> option set in the TLPDB. You must use C<--all> or a list 6437of packages together with this option, as desired. 6438 6439=item B<--dry-run> 6440 6441Nothing is actually backed up or removed; instead, the actions to be 6442performed are written to the terminal. 6443 6444=back 6445 6446 6447=head2 candidates I<pkg> 6448 6449=over 4 6450 6451=item B<candidates I<pkg>> 6452 6453Shows the available candidate repositories for package I<pkg>. 6454See L</MULTIPLE REPOSITORIES> below. 6455 6456 6457=back 6458 6459=head2 check [I<option>]... [files|depends|executes|runfiles|all] 6460 6461Executes one (or all) check(s) on the consistency of the installation. 6462 6463=over 4 6464 6465=item B<files> 6466 6467Checks that all files listed in the local TLPDB (C<texlive.tlpdb>) are 6468actually present, and lists those missing. 6469 6470=item B<depends> 6471 6472Lists those packages which occur as dependencies in an installed collections, 6473but are themselves not installed, and those packages that are not 6474contained in any collection. 6475 6476If you call C<tlmgr check collections> this test will be carried out 6477instead since former versions for C<tlmgr> called it that way. 6478 6479=item B<executes> 6480 6481Check that the files referred to by C<execute> directives in the TeX 6482Live Database are present. 6483 6484=item B<runfiles> 6485 6486List those filenames that are occurring more than one time in the runfiles. 6487 6488=back 6489 6490Options: 6491 6492=over 4 6493 6494=item B<--use-svn> 6495 6496Use the output of C<svn status> instead of listing the files; for 6497checking the TL development repository. 6498 6499=back 6500 6501 6502=head2 conf [texmf|tlmgr|updmap [--conffile I<file>] [--delete] [I<key> [I<value>]]] 6503 6504With only C<conf>, show general configuration information for TeX Live, 6505including active configuration files, path settings, and more. This is 6506like the C<texconfig conf> call, but works on all supported platforms. 6507 6508With either C<conf texmf>, C<conf tlmgr>, or C<conf updmap> given in 6509addition, shows all key/value pairs (i.e., all settings) as saved in 6510C<ROOT/texmf.cnf>, the tlmgr configuration file (see below), or the 6511first found (via kpsewhich) C<updmap.cfg> file, respectively. 6512 6513If I<key> is given in addition, shows the value of only that I<key> in 6514the respective file. If option I<--delete> is also given, the 6515configuration file -- it is removed, not just commented out! 6516 6517If I<value> is given in addition, I<key> is set to I<value> in the 6518respective file. I<No error checking is done!> 6519 6520In all cases the file used can be explicitly specified via the option 6521C<--conffile I<file>>, in case one wants to operate on a different file. 6522 6523Practical application: if the execution of (some or all) system commands 6524via C<\write18> was left enabled during installation, you can disable 6525it afterwards: 6526 6527 tlmgr conf texmf shell_escape 0 6528 6529A more complicated example: the C<TEXMFHOME> tree (see the main TeX Live 6530guide, L<http://tug.org/texlive/doc.html>) can be set to multiple 6531directories, but they must be enclosed in braces and separated by 6532commas, so quoting the value to the shell is a good idea. Thus: 6533 6534 tlmgr conf texmf TEXMFHOME "{~/texmf,~/texmfbis}" 6535 6536Warning: The general facility is here, but tinkering with settings in 6537this way is very strongly discouraged. Again, no error checking on 6538either keys or values is done, so any sort of breakage is possible. 6539 6540 6541=head2 dump-tlpdb [--local|--remote] 6542 6543Dump complete local or remote TLPDB to standard output, as-is. The 6544output is analogous to the C<--machine-readable> output; see 6545L<MACHINE-READABLE OUTPUT> section. 6546 6547Options: 6548 6549=over 4 6550 6551=item B<--local> 6552 6553Dump the local tlpdb. 6554 6555=item B<--remote> 6556 6557Dump the remote tlpdb. 6558 6559=back 6560 6561Exactly one of C<--local> and C<--remote> must be given. 6562 6563In either case, the first line of the output specifies the repository 6564location, in this format: 6565 6566 "location-url" "\t" location 6567 6568where C<location-url> is the literal field name, followed by a tab, and 6569I<location> is the file or url to the repository. 6570 6571Line endings may be either LF or CRLF depending on the current platform. 6572 6573 6574=head2 generate [I<option>]... I<what> 6575 6576=over 4 6577 6578=item B<generate language> 6579 6580=item B<generate language.dat> 6581 6582=item B<generate language.def> 6583 6584=item B<generate language.dat.lua> 6585 6586=back 6587 6588The C<generate> action overwrites any manual changes made in the 6589respective files: it recreates them from scratch based on the 6590information of the installed packages, plus local adaptions. 6591The TeX Live installer and C<tlmgr> routinely call C<generate> for 6592all of these files. 6593 6594For managing your own fonts, please read the C<updmap --help> 6595information and/or L<http://tug.org/fonts/fontinstall.html>. 6596 6597For managing your own formats, please read the C<fmtutil --help> 6598information. 6599 6600In more detail: C<generate> remakes any of the configuration files 6601C<language.dat>, C<language.def>, and C<language.dat.lua> 6602from the information present in the local TLPDB, plus 6603locally-maintained files. 6604 6605The locally-maintained files are C<language-local.dat>, 6606C<language-local.def>, or C<language-local.dat.lua>, 6607searched for in C<TEXMFLOCAL> in the respective 6608directories. If local additions are present, the final file is made by 6609starting with the main file, omitting any entries that the local file 6610specifies to be disabled, and finally appending the local file. 6611 6612(Historical note: The formerly supported C<updmap-local.cfg> and 6613C<fmtutil-local.cnf> are no longer read, since C<updmap> and C<fmtutil> 6614now reads and supports multiple configuration files. Thus, 6615local additions can and should be put into an C<updmap.cfg> of C<fmtutil.cnf> 6616file in C<TEXMFLOCAL>. The C<generate updmap> and C<generate fmtutil> actions 6617no longer exist.) 6618 6619Local files specify entries to be disabled with a comment line, namely 6620one of these: 6621 6622 %!NAME 6623 --!NAME 6624 6625where C<language.dat> and C<language.def> use C<%>, 6626and C<language.dat.lua> use C<-->. In all cases, the I<name> is 6627the respective format name or hyphenation pattern identifier. 6628Examples: 6629 6630 %!german 6631 --!usenglishmax 6632 6633(Of course, you're not likely to actually want to disable those 6634particular items. They're just examples.) 6635 6636After such a disabling line, the local file can include another entry 6637for the same item, if a different definition is desired. In general, 6638except for the special disabling lines, the local files follow the same 6639syntax as the master files. 6640 6641The form C<generate language> recreates all three files C<language.dat>, 6642C<language.def>, and C<language.dat.lua>, while the forms with an 6643extension recreates only that given language file. 6644 6645Options: 6646 6647=over 4 6648 6649=item B<--dest> I<output_file> 6650 6651specifies the output file (defaults to the respective location in 6652C<TEXMFSYSVAR>). If C<--dest> is given to C<generate language>, it 6653serves as a basename onto which C<.dat> will be appended for the name of 6654the C<language.dat> output file, C<.def> will be appended to the value 6655for the name of the C<language.def> output file, and C<.dat.lua> to the 6656name of the C<language.dat.lua> file. (This is just to avoid 6657overwriting; if you want a specific name for each output file, we 6658recommend invoking C<tlmgr> twice.) 6659 6660=item B<--localcfg> I<local_conf_file> 6661 6662specifies the (optional) local additions (defaults to the respective 6663location in C<TEXMFLOCAL>). 6664 6665=item B<--rebuild-sys> 6666 6667tells tlmgr to run necessary programs after config files have been 6668regenerated. These are: 6669C<fmtutil-sys --all> after C<generate fmtutil>, 6670C<fmtutil-sys --byhyphen .../language.dat> after C<generate language.dat>, 6671and 6672C<fmtutil-sys --byhyphen .../language.def> after C<generate language.def>. 6673 6674These subsequent calls cause the newly-generated files to actually take 6675effect. This is not done by default since those calls are lengthy 6676processes and one might want to made several related changes in 6677succession before invoking these programs. 6678 6679=back 6680 6681The respective locations are as follows: 6682 6683 tex/generic/config/language.dat (and language-local.dat); 6684 tex/generic/config/language.def (and language-local.def); 6685 tex/generic/config/language.dat.lua (and language-local.dat.lua); 6686 6687 6688=head2 gui 6689 6690Start the graphical user interface. See B<GUI> below. 6691 6692 6693=head2 info [I<option>...] [collections|schemes|I<pkg>...] 6694 6695With no argument, lists all packages available at the package 6696repository, prefixing those already installed with C<i>. 6697 6698With the single word C<collections> or C<schemes> as the argument, lists 6699the request type instead of all packages. 6700 6701With any other arguments, display information about I<pkg>: the name, 6702category, short and long description, installation status, and TeX Live 6703revision number. If I<pkg> is not locally installed, searches in the 6704remote installation source. 6705 6706If I<pkg> is not found locally or remotely, the search action is used 6707and lists matching packages and files. 6708 6709It also displays information taken from the TeX Catalogue, namely the 6710package version, date, and license. Consider these, especially the 6711package version, as approximations only, due to timing skew of the 6712updates of the different pieces. By contrast, the C<revision> value 6713comes directly from TL and is reliable. 6714 6715The former actions C<show> and C<list> are merged into this action, 6716but are still supported for backward compatibility. 6717 6718Options: 6719 6720=over 4 6721 6722=item B<--list> 6723 6724If the option C<--list> is given with a package, the list of contained 6725files is also shown, including those for platform-specific dependencies. 6726When given with schemes and collections, C<--list> outputs their 6727dependencies in a similar way. 6728 6729=item B<--only-installed> 6730 6731If this options is given, the installation source will 6732not be used; only locally installed packages, collections, or schemes 6733are listed. 6734(Does not work for listing of packages for now) 6735 6736=back 6737 6738 6739=head2 init-usertree 6740 6741Sets up a texmf tree for so-called user mode management, either the 6742default user tree (C<TEXMFHOME>), or one specified on the command line 6743with C<--usertree>. See L<USER MODE> below. 6744 6745 6746=head2 install [I<option>]... I<pkg>... 6747 6748Install each I<pkg> given on the command line, if it is not already 6749installed. (It does not touch existing packages; see the C<update> 6750action for how to get the latest version of a package.) 6751 6752By default this also installs all packages on which the given I<pkg>s are 6753dependent. Options: 6754 6755=over 4 6756 6757=item B<--dry-run> 6758 6759Nothing is actually installed; instead, the actions to be performed are 6760written to the terminal. 6761 6762=item B<--file> 6763 6764Instead of fetching a package from the installation repository, use 6765the package files given on the command line. These files must 6766be standard TeX Live package files (with contained tlpobj file). 6767 6768=item B<--force> 6769 6770If updates to C<tlmgr> itself (or other parts of the basic 6771infrastructure) are present, C<tlmgr> will bail out and not perform the 6772installation unless this option is given. Not recommended. 6773 6774=item B<--no-depends> 6775 6776Do not install dependencies. (By default, installing a package ensures 6777that all dependencies of this package are fulfilled.) 6778 6779=item B<--no-depends-at-all> 6780 6781Normally, when you install a package which ships binary files the 6782respective binary package will also be installed. That is, for a 6783package C<foo>, the package C<foo.i386-linux> will also be installed on 6784an C<i386-linux> system. This option suppresses this behavior, and also 6785implies C<--no-depends>. Don't use it unless you are sure of what you 6786are doing. 6787 6788=item B<--reinstall> 6789 6790Reinstall a package (including dependencies for collections) even if it 6791already seems to be installed (i.e, is present in the TLPDB). This is 6792useful to recover from accidental removal of files in the hierarchy. 6793 6794When re-installing, only dependencies on normal packages are followed 6795(i.e., not those of category Scheme or Collection). 6796 6797=item B<--with-doc> 6798 6799=item B<--with-src> 6800 6801While not recommended, the C<install-tl> program provides an option to 6802omit installation of all documentation and/or source files. (By 6803default, everything is installed.) After such an installation, you may 6804find that you want the documentation or source files for a given package 6805after all. You can get them by using these options in conjunction with 6806C<--reinstall>, as in (using the C<fontspec> package as the example): 6807 6808 tlmgr install --reinstall --with-doc --with-src fontspec 6809 6810=back 6811 6812 6813=head2 option 6814 6815=over 4 6816 6817=item B<option [show]> 6818 6819=item B<option showall> 6820 6821=item B<option I<key> [I<value>]> 6822 6823=back 6824 6825The first form shows the global TeX Live settings currently saved in the 6826TLPDB with a short description and the C<key> used for changing it in 6827parentheses. 6828 6829The second form is similar, but also shows options which can be defined 6830but are not currently set to any value. 6831 6832In the third form, if I<value> is not given, the setting for I<key> is 6833displayed. If I<value> is present, I<key> is set to I<value>. 6834 6835Possible values for I<key> are (run C<tlmgr option showall> for 6836the definitive list): 6837 6838 repository (default package repository), 6839 formats (create formats at installation time), 6840 postcode (run postinst code blobs) 6841 docfiles (install documentation files), 6842 srcfiles (install source files), 6843 backupdir (default directory for backups), 6844 autobackup (number of backups to keep). 6845 sys_bin (directory to which executables are linked by the path action) 6846 sys_man (directory to which man pages are linked by the path action) 6847 sys_info (directory to which Info files are linked by the path action) 6848 desktop_integration (Windows-only: create Start menu shortcuts) 6849 fileassocs (Windows-only: change file associations) 6850 multiuser (Windows-only: install for all users) 6851 6852One common use of C<option> is to permanently change the installation to 6853get further updates from the Internet, after originally installing from 6854DVD. To do this, you can run 6855 6856 tlmgr option repository http://mirror.ctan.org/systems/texlive/tlnet 6857 6858The C<install-tl> documentation has more information about the possible 6859values for C<repository>. (For backward compatibility, C<location> can 6860be used as alternative name for C<repository>.) 6861 6862If C<formats> is set (this is the default), then formats are regenerated 6863when either the engine or the format files have changed. Disable this 6864only when you know what you are doing. 6865 6866The C<postcode> option controls execution of per-package 6867postinstallation action code. It is set by default, and again disabling 6868is not likely to be of interest except perhaps to developers. 6869 6870The C<docfiles> and C<srcfiles> options control the installation of 6871their respective files of a package. By default both are enabled (1). 6872This can be disabled (set to 0) if disk space is (very) limited. 6873 6874The options C<autobackup> and C<backupdir> determine the defaults for 6875the actions C<update>, C<backup> and C<restore>. These three actions 6876need a directory in which to read or write the backups. If 6877C<--backupdir> is not specified on the command line, the C<backupdir> 6878option value is used (if set). 6879 6880The C<autobackup> option (de)activates automatic generation of backups. 6881Its value is an integer. If the C<autobackup> value is C<-1>, no 6882backups are removed. If C<autobackup> is 0 or more, it specifies the 6883number of backups to keep. Thus, backups are disabled if the value is 68840. In the C<--clean> mode of the C<backup> action this option also 6885specifies the number to be kept. 6886 6887To setup C<autobackup> to C<-1> on the command line, use: 6888 6889 tlmgr option -- autobackup -1 6890 6891The C<--> avoids having the C<-1> treated as an option. (C<--> stops 6892parsing for options at the point where it appears; this is a general 6893feature across most Unix programs.) 6894 6895The C<sys_bin>, C<sys_man>, and C<sys_info> options are used on 6896Unix-like systems to control the generation of links for executables, 6897info files and man pages. See the C<path> action for details. 6898 6899The last three options control behaviour on Windows installations. If 6900C<desktop_integration> is set, then some packages will install items in 6901a sub-folder of the Start menu for C<tlmgr gui>, documentation, etc. If 6902C<fileassocs> is set, Windows file associations are made (see also the 6903C<postaction> action). Finally, if C<multiuser> is set, then adaptions 6904to the registry and the menus are done for all users on the system 6905instead of only the current user. All three options are on by default. 6906 6907 6908=head2 paper 6909 6910=over 4 6911 6912=item B<paper [a4|letter]> 6913 6914=item B<S<[xdvi|pdftex|dvips|dvipdfmx|context|psutils] paper [I<papersize>|--list]>> 6915 6916=back 6917 6918With no arguments (C<tlmgr paper>), shows the default paper size setting 6919for all known programs. 6920 6921With one argument (e.g., C<tlmgr paper a4>), sets the default for all 6922known programs to that paper size. 6923 6924With a program given as the first argument and no paper size specified 6925(e.g., C<tlmgr dvips paper>), shows the default paper size for that 6926program. 6927 6928With a program given as the first argument and a paper size as the last 6929argument (e.g., C<tlmgr dvips paper a4>), set the default for that 6930program to that paper size. 6931 6932With a program given as the first argument and C<--list> given as the 6933last argument (e.g., C<tlmgr dvips paper --list>), shows all valid paper 6934sizes for that program. The first size shown is the default. 6935 6936Incidentally, this syntax of having a specific program name before the 6937C<paper> keyword is unusual. It is inherited from the longstanding 6938C<texconfig> script, which supports other configuration settings for 6939some programs, notably C<dvips>. C<tlmgr> does not support those extra 6940settings. 6941 6942 6943=head2 path [--w32mode=user|admin] [add|remove] 6944 6945On Unix, merely adds or removes symlinks for binaries, man pages, and 6946info pages in the system directories specified by the respective options 6947(see the L</option> description above). Does not change any 6948initialization files, either system or personal. 6949 6950On Windows, the registry part where the binary directory is added or 6951removed is determined in the following way: 6952 6953If the user has admin rights, and the option C<--w32mode> is not given, 6954the setting I<w32_multi_user> determines the location (i.e., if it is 6955on then the system path, otherwise the user path is changed). 6956 6957If the user has admin rights, and the option C<--w32mode> is given, this 6958option determines the path to be adjusted. 6959 6960If the user does not have admin rights, and the option C<--w32mode> 6961is not given, and the setting I<w32_multi_user> is off, the user path 6962is changed, while if the setting I<w32_multi_user> is on, a warning is 6963issued that the caller does not have enough privileges. 6964 6965If the user does not have admin rights, and the option C<--w32mode> 6966is given, it must be B<user> and the user path will be adjusted. If a 6967user without admin rights uses the option C<--w32mode admin> a warning 6968is issued that the caller does not have enough privileges. 6969 6970 6971=head2 pinning 6972 6973The C<pinning> action manages the pinning file, see L</Pinning> below. 6974 6975=over 4 6976 6977=item C<pinning show> 6978 6979Shows the current pinning data. 6980 6981=item C<pinning add> I<repo> I<pkgglob>... 6982 6983Pins the packages matching the I<pkgglob>(s) to the repository 6984I<repo>. 6985 6986=item C<pinning remove> I<repo> I<pkgglob>... 6987 6988Any packages recorded in the pinning file matching the <pkgglob>s for 6989the given repository I<repo> are removed. 6990 6991=item C<pinning remove I<repo> --all> 6992 6993Remove all pinning data for repository I<repo>. 6994 6995=back 6996 6997=head2 platform list|add|remove I<platform>... 6998 6999=head2 platform set I<platform> 7000 7001=head2 platform set auto 7002 7003C<platform list> lists the TeX Live names of all the platforms 7004(a.k.a. architectures), (C<i386-linux>, ...) available at the package 7005repository. 7006 7007C<platform add> I<platform>... adds the executables for each given platform 7008I<platform> to the installation from the repository. 7009 7010C<platform remove> I<platform>... removes the executables for each given 7011platform I<platform> from the installation, but keeps the currently 7012running platform in any case. 7013 7014C<platform set> I<platform> switches TeX Live to always use the given 7015platform instead of auto detection. 7016 7017C<platform set auto> switches TeX Live to auto detection mode for platform. 7018 7019Platform detection is needed to select the proper C<xz>, C<xzdec> and 7020C<wget> binaries that are shipped with TeX Live. 7021 7022C<arch> is a synonym for C<platform>. 7023 7024Options: 7025 7026=over 4 7027 7028=item B<--dry-run> 7029 7030Nothing is actually installed; instead, the actions to be performed are 7031written to the terminal. 7032 7033=back 7034 7035 7036=cut 7037 7038# keep the following on *ONE* line otherwise Losedows perldoc does 7039# not show it!!!! 7040 7041=pod 7042 7043=head2 postaction [--w32mode=user|admin] [--fileassocmode=1|2] [--all] [install|remove] [shortcut|fileassoc|script] [I<pkg>]... 7044 7045Carry out the postaction C<shortcut>, C<fileassoc>, or C<script> given 7046as the second required argument in install or remove mode (which is the 7047first required argument), for either the packages given on the command 7048line, or for all if C<--all> is given. 7049 7050If the option C<--w32mode> is given the value C<user>, all actions will 7051only be carried out in the user-accessible parts of the 7052registry/filesystem, while the value C<admin> selects the system-wide 7053parts of the registry for the file associations. If you do not have 7054enough permissions, using C<--w32mode=admin> will not succeed. 7055 7056C<--fileassocmode> specifies the action for file associations. If it is 7057set to 1 (the default), only new associations are added; if it is set to 70582, all associations are set to the TeX Live programs. (See also 7059C<option fileassocs>.) 7060 7061 7062=head2 print-platform 7063 7064Print the TeX Live identifier for the detected platform 7065(hardware/operating system) combination to standard output, and exit. 7066C<--print-arch> is a synonym. 7067 7068 7069=head2 remove [I<option>]... I<pkg>... 7070 7071Remove each I<pkg> specified. Removing a collection removes all package 7072dependencies (unless C<--no-depends> is specified), but not any 7073collection dependencies of that collection. However, when removing a 7074package, dependencies are never removed. Options: 7075 7076=over 4 7077 7078=item B<--no-depends> 7079 7080Do not remove dependent packages. 7081 7082=item B<--no-depends-at-all> 7083 7084See above under B<install> (and beware). 7085 7086=item B<--force> 7087 7088By default, removal of a package or collection that is a dependency of 7089another collection or scheme is not allowed. With this option, the 7090package will be removed unconditionally. Use with care. 7091 7092A package that has been removed using the C<--force> option because it 7093is still listed in an installed collection or scheme will not be 7094updated, and will be mentioned as B<forcibly removed> in the output of 7095B<tlmgr update --list>. 7096 7097=item B<--dry-run> 7098 7099Nothing is actually removed; instead, the actions to be performed are 7100written to the terminal. 7101 7102=back 7103 7104 7105=head2 repository 7106 7107=over 4 7108 7109=item B<repository list> 7110 7111=item B<repository list I<path|tag>> 7112 7113=item B<repository add I<path> [I<tag>]> 7114 7115=item B<repository remove I<path|tag>> 7116 7117=item B<repository set I<path>[#I<tag>] [I<path>[#I<tag>] ...]> 7118 7119This action manages the list of repositories. See L</MULTIPLE 7120REPOSITORIES> below for detailed explanations. 7121 7122The first form (C<list>) lists all configured repositories and the 7123respective tags if set. If a path, url, or tag is given after the 7124C<list> keyword, it is interpreted as source from where to 7125initialize a TeX Live Database and lists the contained packages. 7126This can also be an up-to-now not used repository, both locally 7127and remote. If one pass in addition C<--with-platforms>, for each 7128package the available platforms (if any) are listed, too. 7129 7130The third form (C<add>) adds a repository 7131(optionally attaching a tag) to the list of repositories. The forth 7132form (C<remove>) removes a repository, either by full path/url, or by 7133tag. The last form (C<set>) sets the list of repositories to the items 7134given on the command line, not keeping previous settings 7135 7136In all cases, one of the repositories must be tagged as C<main>; 7137otherwise, all operations will fail! 7138 7139=back 7140 7141 7142=head2 restore [--backupdir I<dir>] [--all | I<pkg> [I<rev>]] 7143 7144Restore a package from a previously-made backup. 7145 7146If C<--all> is given, try to restore the latest revision of all 7147package backups found in the backup directory. 7148 7149Otherwise, if neither I<pkg> nor I<rev> are given, list the available 7150backup revisions for all packages. With I<pkg> given but no I<rev>, 7151list all available backup revisions of I<pkg>. 7152 7153When listing available packages tlmgr shows the revision, and in 7154parenthesis the creation time if available (in format yyyy-mm-dd hh:mm). 7155 7156If (and only if) both I<pkg> and a valid revision number I<rev> are 7157specified, try to restore the package from the specified backup. 7158 7159Options: 7160 7161=over 4 7162 7163=item B<--all> 7164 7165Try to restore the latest revision of all package backups found in the 7166backup directory. Additional non-option arguments (like I<pkg>) are not 7167allowed. 7168 7169=item B<--backupdir> I<directory> 7170 7171Specify the directory where the backups are to be found. If not given it 7172will be taken from the configuration setting in the TLPDB. 7173 7174=item B<--dry-run> 7175 7176Nothing is actually restored; instead, the actions to be performed are 7177written to the terminal. 7178 7179=item B<--force> 7180 7181Don't ask questions. 7182 7183=back 7184 7185 7186=head2 search [I<option>...] I<what> 7187 7188=head3 search [I<option>...] --file I<what> 7189 7190=head3 search [I<option>...] --all I<what> 7191 7192By default, search the names, short descriptions, and long descriptions 7193of all locally installed packages for the argument I<what>, interpreted 7194as a (Perl) regular expression. 7195 7196Options: 7197 7198=over 4 7199 7200=item B<--file> 7201 7202List all filenames containing I<what>. 7203 7204=item B<--all> 7205 7206Search everything: package names, descriptions and filenames. 7207 7208=item B<--global> 7209 7210Search the TeX Live Database of the installation medium, instead of the 7211local installation. 7212 7213=item B<--word> 7214 7215Restrict the search of package names and descriptions (but not 7216filenames) to match only full words. For example, searching for 7217C<table> with this option will not output packages containing the word 7218C<tables> (unless they also contain the word C<table> on its own). 7219 7220=back 7221 7222 7223=head2 uninstall 7224 7225Uninstalls the entire TeX Live installation. Options: 7226 7227=over 4 7228 7229=item B<--force> 7230 7231Do not ask for confirmation, remove immediately. 7232 7233=back 7234 7235 7236=head2 update [I<option>]... [I<pkg>]... 7237 7238Updates the packages given as arguments to the latest version available 7239at the installation source. Either C<--all> or at least one I<pkg> name 7240must be specified. Options: 7241 7242=over 4 7243 7244=item B<--all> 7245 7246Update all installed packages except for C<tlmgr> itself. Thus, if 7247updates to C<tlmgr> itself are present, this will simply give an error, 7248unless also the option C<--force> or C<--self> is given. (See below.) 7249 7250In addition to updating the installed packages, during the update of a 7251collection the local installation is (by default) synchronized to the 7252status of the collection on the server, for both additions and removals. 7253 7254This means that if a package has been removed on the server (and thus 7255has also been removed from the respective collection), C<tlmgr> will 7256remove the package in the local installation. This is called 7257``auto-remove'' and is announced as such when using the option 7258C<--list>. This auto-removal can be suppressed using the option 7259C<--no-auto-remove> (not recommended, see option description). 7260 7261Analogously, if a package has been added to a collection on the server 7262that is also installed locally, it will be added to the local 7263installation. This is called ``auto-install'' and is announced as such 7264when using the option C<--list>. This auto-installation can be 7265suppressed using the option C<--no-auto-install>. 7266 7267An exception to the collection dependency checks (including the 7268auto-installation of packages just mentioned) are those that have been 7269``forcibly removed'' by you, that is, you called C<tlmgr remove --force> 7270on them. (See the C<remove> action documentation.) To reinstall any 7271such forcibly removed packages use C<--reinstall-forcibly-removed>. 7272 7273If you want to exclude some packages from the current update run (e.g., 7274due to a slow link), see the C<--exclude> option below. 7275 7276=item B<--self> 7277 7278Update C<tlmgr> itself (that is, the infrastructure packages) if updates 7279to it are present. On Windows this includes updates to the private Perl 7280interpreter shipped inside TeX Live. 7281 7282If this option is given together with either C<--all> or a list of 7283packages, then C<tlmgr> will be updated first and, if this update 7284succeeds, the new version will be restarted to complete the rest of the 7285updates. 7286 7287In short: 7288 7289 tlmgr update --self # update infrastructure only 7290 tlmgr update --self --all # update infrastructure and all packages 7291 tlmgr update --force --all # update all packages but *not* infrastructure 7292 # ... this last at your own risk, not recommended! 7293 7294=item B<--dry-run> 7295 7296Nothing is actually installed; instead, the actions to be performed are 7297written to the terminal. This is a more detailed report than C<--list>. 7298 7299=item B<--list> [I<pkg>] 7300 7301Concisely list the packages which would be updated, newly installed, or 7302removed, without actually changing anything. 7303If C<--all> is also given, all available updates are listed. 7304If C<--self> is given, but not C<--all>, only updates to the 7305critical packages (tlmgr, texlive infrastructure, perl on Windows, etc.) 7306are listed. 7307If neither C<--all> nor C<--self> is given, and in addition no I<pkg> is 7308given, then C<--all> is assumed (thus, C<tlmgr update --list> is the 7309same as C<tlmgr update --list --all>). 7310If neither C<--all> nor C<--self> is given, but specific package names are 7311given, those packages are checked for updates. 7312 7313=item B<--exclude> I<pkg> 7314 7315Exclude I<pkg> from the update process. If this option is given more 7316than once, its arguments accumulate. 7317 7318An argument I<pkg> excludes both the package I<pkg> itself and all 7319its related platform-specific packages I<pkg.ARCH>. For example, 7320 7321 tlmgr update --all --exclude a2ping 7322 7323will not update C<a2ping>, C<a2ping.i386-linux>, or 7324any other C<a2ping.>I<ARCH> package. 7325 7326If this option specifies a package that would otherwise be a candidate 7327for auto-installation, auto-removal, or reinstallation of a forcibly 7328removed package, C<tlmgr> quits with an error message. Excludes are not 7329supported in these circumstances. 7330 7331=item B<--no-auto-remove> [I<pkg>]... 7332 7333By default, C<tlmgr> tries to remove packages which have disappeared on 7334the server, as described above under C<--all>. This option prevents 7335such removals, either for all packages (with C<--all>), or for just the 7336given I<pkg> names. This can lead to an inconsistent TeX installation, 7337since packages are not infrequently renamed or replaced by their 7338authors. Therefore this is not recommend. 7339 7340=item B<--no-auto-install> [I<pkg>]... 7341 7342Under normal circumstances C<tlmgr> will install packages which are new 7343on the server, as described above under C<--all>. This option prevents 7344any such automatic installation, either for all packages (with 7345C<--all>), or the given I<pkg> names. 7346 7347Furthermore, after the C<tlmgr> run using this has finished, the 7348packages that would have been auto-installed I<will be considered as 7349forcibly removed>. So, if C<foobar> is the only new package on the 7350server, then 7351 7352 tlmgr update --all --no-auto-install 7353 7354is equivalent to 7355 7356 tlmgr update --all 7357 tlmgr remove --force foobar 7358 7359=item B<--reinstall-forcibly-removed> 7360 7361Under normal circumstances C<tlmgr> will not install packages that have 7362been forcibly removed by the user; that is, removed with C<remove 7363--force>, or whose installation was prohibited by C<--no-auto-install> 7364during an earlier update. 7365 7366This option makes C<tlmgr> ignore the forcible removals and re-install 7367all such packages. This can be used to completely synchronize an 7368installation with the server's idea of what is available: 7369 7370 tlmgr update --reinstall-forcibly-removed --all 7371 7372=item B<--backup> and B<--backupdir> I<directory> 7373 7374These two options control the creation of backups of packages I<before> 7375updating; that is, backup of packages as currently installed. If 7376neither of these options are given, no backup package will be saved. If 7377C<--backupdir> is given and specifies a writable directory then a backup 7378will be made in that location. If only C<--backup> is given, then a 7379backup will be made to the directory previously set via the C<option> 7380action (see below). If both are given then a backup will be made to the 7381specified I<directory>. 7382 7383You can set options via the C<option> action to automatically create 7384backups for all packages, and/or keep only a certain number of 7385backups. Please see the C<option> action for details. 7386 7387C<tlmgr> always makes a temporary backup when updating packages, in case 7388of download or other failure during an update. In contrast, the purpose 7389of this C<--backup> option is to allow you to save a persistent backup 7390in case the actual I<content> of the update causes problems, e.g., 7391introduces an incompatibility. 7392 7393The C<restore> action explains how to restore from a backup. 7394 7395=item B<--no-depends> 7396 7397If you call for updating a package normally all depending packages 7398will also be checked for updates and updated if necessary. This switch 7399suppresses this behavior. 7400 7401=item B<--no-depends-at-all> 7402 7403See above under B<install> (and beware). 7404 7405=item B<--force> 7406 7407Force update of normal packages, without updating C<tlmgr> itself 7408(unless the C<--self> option is also given). Not recommended. 7409 7410Also, C<update --list> is still performed regardless of this option. 7411 7412=back 7413 7414If the package on the server is older than the package already installed 7415(e.g., if the selected mirror is out of date), C<tlmgr> does not 7416downgrade. Also, packages for uninstalled platforms are not installed. 7417 7418C<tlmgr> saves a copy of the C<texlive.tlpdb> file used for an update 7419with a suffix representing the repository url, as in 7420C<tlpkg/texlive.tlpdb.>I<long-hash-string>. These can be useful for 7421fallback information, but if you don't like them accumulating (e.g., 7422on each run C<mirror.ctan.org> might resolve to a new host, resulting in 7423a different hash), it's harmless to delete them. 7424 7425=head1 USER MODE 7426 7427C<tlmgr> provides a restricted way, called ``user mode'', to manage 7428arbitrary texmf trees in the same way as the main installation. For 7429example, this allows people without write permissions on the 7430installation location to update/install packages into a tree of their 7431own. 7432 7433C<tlmgr> is switched into user mode with the command line option 7434C<--usermode>. It does not switch automatically, nor is there any 7435configuration file setting for it. Thus, this option has to be 7436explicitly given every time user mode is to be activated. 7437 7438This mode of C<tlmgr> works on a user tree, by default the value of the 7439C<TEXMFHOME> variable. This can be overridden with the command line 7440option C<--usertree>. In the following when we speak of the user tree 7441we mean either C<TEXMFHOME> or the one given on the command line. 7442 7443Not all actions are allowed in user mode; C<tlmgr> will warn you and not 7444carry out any problematic actions. Currently not supported (and 7445probably will never be) is the C<platform> action. The C<gui> action is 7446currently not supported, but may be in a future release. 7447 7448Some C<tlmgr> actions don't need any write permissions and thus work the 7449same in user mode and normal mode. Currently these are: C<check>, 7450C<help>, C<list>, C<print-platform>, C<search>, C<show>, C<version>. 7451 7452On the other hand, most of the actions dealing with package management 7453do need write permissions, and thus behave differently in user mode, as 7454described below: C<install>, C<update>, C<remove>, C<option>, C<paper>, 7455C<generate>, C<backup>, C<restore>, C<uninstall>, C<symlinks>. 7456 7457Before using C<tlmgr> in user mode, you have to set up the user tree 7458with the C<init-usertree> action. This creates I<usertree>C</web2c> and 7459I<usertree>C</tlpkg/tlpobj>, and a minimal 7460I<usertree>C</tlpkg/texlive.tlpdb>. At that point, you can tell 7461C<tlmgr> to do the (supported) actions by adding the C<--usermode> 7462command line option. 7463 7464In user mode the file I<usertree>C</tlpkg/texlive.tlpdb> contains only 7465the packages that have been installed into the user tree using C<tlmgr>, 7466plus additional options from the ``virtual'' package 7467C<00texlive.installation> (similar to the main installation's 7468C<texlive.tlpdb>). 7469 7470All actions on packages in user mode can only be carried out on packages 7471that are known as C<relocatable>. This excludes all packages containing 7472executables and a few other core packages. Of the 2500 or so packages 7473currently in TeX Live the vast majority are relocatable and can be 7474installed into a user tree. 7475 7476Description of changes of actions in user mode: 7477 7478=head2 User mode install 7479 7480In user mode, the C<install> action checks that the package and all 7481dependencies are all either relocated or already installed in the system 7482installation. If this is the case, it unpacks all containers to be 7483installed into the user tree (to repeat, that's either C<TEXMFHOME> or 7484the value of C<--usertree>) and add the respective packages to the user 7485tree's C<texlive.tlpdb> (creating it if need be). 7486 7487Currently installing a collection in user mode installs all dependent 7488packages, but in contrast to normal mode, does I<not> install dependent 7489collections. For example, in normal mode C<tlmgr install 7490collection-context> would install C<collection-basic> and other 7491collections, while in user mode, I<only> the packages mentioned in 7492C<collection-context> are installed. 7493 7494=head2 User mode backup, restore, remove, update 7495 7496In user mode, these actions check that all packages to be acted on are 7497installed in the user tree before proceeding; otherwise, they behave 7498just as in normal mode. 7499 7500=head2 User mode generate, option, paper 7501 7502In user mode, these actions operate only on the user tree's 7503configuration files and/or C<texlive.tlpdb>. 7504creates configuration files in user tree 7505 7506 7507=head1 CONFIGURATION FILE FOR TLMGR 7508 7509A small subset of the command line options can be set in a config file 7510for C<tlmgr> which resides in C<TEXMFCONFIG/tlmgr/config>. By default, the 7511config file is in C<~/.texliveYYYY/texmf-config/tlmgr/config> (replacing 7512C<YYYY> with the year of your TeX Live installation). This is I<not> 7513C<TEXMFSYSVAR>, so that the file is specific to a single user. 7514 7515In this file, empty lines and lines starting with # are ignored. All 7516other lines must look like 7517 7518 key = value 7519 7520where the allowed keys are C<gui-expertmode> (value 0 or 1), 7521C<persistent-downloads> (value 0 or 1), C<auto-remove> (value 0 or 1), 7522and C<gui-lang> (value like in the command line option). 7523 7524C<persistent-downloads>, C<gui-lang>, and C<auto-remove> correspond to 7525the respective command line options of the same name. C<gui-expertmode> 7526switches between the full GUI and a simplified GUI with only the 7527important and mostly used settings. 7528 7529 7530=head1 MULTIPLE REPOSITORIES 7531 7532The main TeX Live repository contains a vast array of packages. 7533Nevertheless, additional local repositories can be useful to provide 7534locally-installed resources, such as proprietary fonts and house styles. 7535Also, alternative package repositories distribute packages that cannot 7536or should not be included in TeX Live, for whatever reason. 7537 7538The simplest and most reliable method is to temporarily set the 7539installation source to any repository (with the C<-repository> or 7540C<option repository> command line options), and perform your operations. 7541 7542When you are using multiple repositories over a sustained time, however, 7543explicitly switching between them becomes inconvenient. Thus, it's 7544possible to tell C<tlmgr> about additional repositories you want to use. 7545The basic command is C<tlmgr repository add>. The rest of this section 7546explains further. 7547 7548When using multiple repositories, one of them has to be set as the main 7549repository, which distributes most of the installed packages. When you 7550switch from a single repository installation to a multiple repository 7551installation, the previous sole repository will be set as the main 7552repository. 7553 7554By default, even if multiple repositories are configured, packages are 7555I<still> I<only> installed from the main repository. Thus, simply 7556adding a second repository does not actually enable installation of 7557anything from there. You also have to specify which packages should be 7558taken from the new repository, by specifying so-called ``pinning'' 7559rules, described next. 7560 7561=head2 Pinning 7562 7563When a package C<foo> is pinned to a repository, a package C<foo> in any 7564other repository, even if it has a higher revision number, will not be 7565considered an installable candidate. 7566 7567As mentioned above, by default everything is pinned to the main 7568repository. Let's now go through an example of setting up a second 7569repository and enabling updates of a package from it. 7570 7571First, check that we have support for multiple repositories, and have 7572only one enabled (as is the case by default): 7573 7574 $ tlmgr repository list 7575 List of repositories (with tags if set): 7576 /var/www/norbert/tlnet 7577 7578Ok. Let's add the C<tlcontrib> repository (this is a real 7579repository, hosted at L<http://tlcontrib.metatex.org>, maintained by 7580Taco Hoekwater et al.), with the tag C<tlcontrib>: 7581 7582 $ tlmgr repository add http://tlcontrib.metatex.org/2012 tlcontrib 7583 7584Check the repository list again: 7585 7586 $ tlmgr repository list 7587 List of repositories (with tags if set): 7588 http://tlcontrib.metatex.org/2012 (tlcontrib) 7589 /var/www/norbert/tlnet (main) 7590 7591Now we specify a pinning entry to get the package C<context> from 7592C<tlcontrib>: 7593 7594 $ tlmgr pinning add tlcontrib context 7595 7596Check that we can find C<context>: 7597 7598 $ tlmgr show context 7599 tlmgr: package repositories: 7600 ... 7601 package: context 7602 repository: tlcontrib/26867 7603 ... 7604 7605- install C<context>: 7606 7607 $ tlmgr install context 7608 tlmgr: package repositories: 7609 ... 7610 [1/1, ??:??/??:??] install: context @tlcontrib [ 7611 7612In the output here you can see that the C<context> package has been 7613installed from the C<tlcontrib> repository (C<@tlcontrib>). 7614 7615Finally, C<tlmgr pinning> also supports removing certain or all packages 7616from a given repository: 7617 7618 $ tlmgr pinning remove tlcontrib context # remove just context 7619 $ tlmgr pinning remove tlcontrib --all # take nothing from tlcontrib 7620 7621A summary of the C<tlmgr pinning> actions is given above. 7622 7623 7624=head1 GUI FOR TLMGR 7625 7626The graphical user interface for C<tlmgr> needs Perl/Tk to be installed. 7627For Windows the necessary modules are shipped within TeX Live, for all 7628other (i.e., Unix-based) systems Perl/Tk (as well as Perl of course) has 7629to be installed. L<http://tug.org/texlive/distro.html#perltk> has a 7630list of invocations for some distros. 7631 7632When started with C<tlmgr gui> the graphical user interface will be 7633shown. The main window contains a menu bar, the main display, and a 7634status area where messages normally shown on the console are displayed. 7635 7636Within the main display there are three main parts: the C<Display 7637configuration> area, the list of packages, and the action buttons. 7638 7639Also, at the top right the currently loaded repository is shown; this 7640also acts as a button and when clicked will try to load the default 7641repository. To load a different repository, see the C<tlmgr> menu item. 7642 7643Finally, the status area at the bottom of the window gives additional 7644information about what is going on. 7645 7646 7647=head2 Main display 7648 7649=head3 Display configuration area 7650 7651The first part of the main display allows you to specify (filter) which 7652packages are shown. By default, all are shown. Changes here are 7653reflected right away. 7654 7655=over 4 7656 7657=item Status 7658 7659Select whether to show all packages (the default), only those installed, 7660only those I<not> installed, or only those with update available. 7661 7662=item Category 7663 7664Select which categories are shown: packages, collections, and/or 7665schemes. These are briefly explained in the L</DESCRIPTION> section 7666above. 7667 7668=item Match 7669 7670Select packages matching for a specific pattern. By default, this 7671searches both descriptions and filenames. You can also select a subset 7672for searching. 7673 7674=item Selection 7675 7676Select packages to those selected, those not selected, or all. Here, 7677``selected'' means that the checkbox in the beginning of the line of a 7678package is ticked. 7679 7680=item Display configuration buttons 7681 7682To the right there are three buttons: select all packages, select none 7683(a.k.a. deselect all), and reset all these filters to the defaults, 7684i.e., show all available. 7685 7686=back 7687 7688=head3 Package list area 7689 7690The second are of the main display lists all installed packages. If a 7691repository is loaded, those that are available but not installed are 7692also listed. 7693 7694Double clicking on a package line pops up an informational window with 7695further details: the long description, included files, etc. 7696 7697Each line of the package list consists of the following items: 7698 7699=over 4 7700 7701=item a checkbox 7702 7703Used to select particular packages; some of the action buttons (see 7704below) work only on the selected packages. 7705 7706=item package name 7707 7708The name (identifier) of the package as given in the database. 7709 7710=item local revision (and version) 7711 7712If the package is installed the TeX Live revision number for the 7713installed package will be shown. If there is a catalogue version given 7714in the database for this package, it will be shown in parentheses. 7715However, the catalogue version, unlike the TL revision, is not 7716guaranteed to reflect what is actually installed. 7717 7718=item remote revision (and version) 7719 7720If a repository has been loaded the revision of the package in the 7721repository (if present) is shown. As with the local column, if a 7722catalogue version is provided it will be displayed. And also as with 7723the local column, the catalogue version may be stale. 7724 7725=item short description 7726 7727The short description of the package. 7728 7729=back 7730 7731=head3 Main display action buttons 7732 7733Below the list of packages are several buttons: 7734 7735=over 4 7736 7737=item Update all installed 7738 7739This calls C<tlmgr update --all>, i.e., tries to update all available 7740packages. Below this button is a toggle to allow reinstallation of 7741previously removed packages as part of this action. 7742 7743The other four buttons only work on the selected packages, i.e., those 7744where the checkbox at the beginning of the package line is ticked. 7745 7746=item Update 7747 7748Update only the selected packages. 7749 7750=item Install 7751 7752Install the selected packages; acts like C<tlmgr install>, i.e., also 7753installs dependencies. Thus, installing a collection installs all its 7754constituent packages. 7755 7756=item Remove 7757 7758Removes the selected packages; acts like C<tlmgr remove>, i.e., it will 7759also remove dependencies of collections (but not dependencies of normal 7760packages). 7761 7762=item Backup 7763 7764Makes a backup of the selected packages; acts like C<tlmgr backup>. This 7765action needs the option C<backupdir> set (see C<Options -> General>). 7766 7767=back 7768 7769 7770=head2 Menu bar 7771 7772The following entries can be found in the menu bar: 7773 7774=over 4 7775 7776=item C<tlmgr> menu 7777 7778The items here load various repositories: the default as specified in 7779the TeX Live database, the default network repository, the repository 7780specified on the command line (if any), and an arbitrarily 7781manually-entered one. Also has the so-necessary C<quit> operation. 7782 7783=item C<Options menu> 7784 7785Provides access to several groups of options: C<Paper> (configuration of 7786default paper sizes), C<Platforms> (only on Unix, configuration of the 7787supported/installed platforms), C<GUI Language> (select language used in 7788the GUI interface), and C<General> (everything else). 7789 7790Several toggles are also here. The first is C<Expert options>, which is 7791set by default. If you turn this off, the next time you start the GUI a 7792simplified screen will be shown that display only the most important 7793functionality. This setting is saved in the configuration file of 7794C<tlmgr>; see L<CONFIGURATION FILE FOR TLMGR> for details. 7795 7796The other toggles are all off by default: for debugging output, to 7797disable the automatic installation of new packages, and to disable the 7798automatic removal of packages deleted from the server. Playing with the 7799choices of what is or isn't installed may lead to an inconsistent TeX Live 7800installation; e.g., when a package is renamed. 7801 7802=item C<Actions menu> 7803 7804Provides access to several actions: update the filename database (aka 7805C<ls-R>, C<mktexlsr>, C<texhash>), rebuild all formats (C<fmtutil-sys 7806--all>), update the font map database (C<updmap-sys>), restore from a backup 7807of a package, and use of symbolic links in system directories (not on 7808Windows). 7809 7810The final action is to remove the entire TeX Live installation (also not 7811on Windows). 7812 7813=item C<Help menu> 7814 7815Provides access to the TeX Live manual (also on the web at 7816L<http://tug.org/texlive/doc.html>) and the usual ``About'' box. 7817 7818=back 7819 7820 7821=head1 MACHINE-READABLE OUTPUT 7822 7823With the C<--machine-readable> option, C<tlmgr> writes to stdout in the 7824fixed line-oriented format described here, and the usual informational 7825messages for human consumption are written to stderr (normally they are 7826written to stdout). The idea is that a program can get all the 7827information it needs by reading stdout. 7828 7829Currently this option only applies to the 7830L<update|/update [I<option>]... [I<pkg>]...>, 7831L<install|/install [I<option>]... I<pkg>...>, and 7832L</option> actions. 7833 7834 7835=head2 Machine-readable C<update> and C<install> output 7836 7837The output format is as follows: 7838 7839 fieldname "\t" value 7840 ... 7841 "end-of-header" 7842 pkgname status localrev serverrev size runtime esttot 7843 ... 7844 "end-of-updates" 7845 other output from post actions, not in machine readable form 7846 7847The header section currently has two fields: C<location-url> (the 7848repository source from which updates are being drawn), and 7849C<total-bytes> (the total number of bytes to be downloaded). 7850 7851The I<localrev> and I<serverrev> fields for each package are the 7852revision numbers in the local installation and server repository, 7853respectively. The I<size> field is the number of bytes to be 7854downloaded, i.e., the size of the compressed tar file for a network 7855installation, not the unpacked size. The runtime and esttot fields 7856are only present for updated and auto-install packages, and contain 7857the currently passed time since start of installation/updates 7858and the estimated total time. 7859 7860Line endings may be either LF or CRLF depending on the current platform. 7861 7862=over 4 7863 7864=item C<location-url> I<location> 7865 7866The I<location> may be a url (including C<file:///foo/bar/...>), or a 7867directory name (C</foo/bar>). It is the package repository from which 7868the new package information was drawn. 7869 7870=item C<total-bytes> I<count> 7871 7872The I<count> is simply a decimal number, the sum of the sizes of all the 7873packages that need updating or installing (which are listed subsequently). 7874 7875=back 7876 7877Then comes a line with only the literal string C<end-of-header>. 7878 7879Each following line until a line with literal string C<end-of-updates> 7880reports on one package. The fields on 7881each line are separated by a tab. Here are the fields. 7882 7883=over 4 7884 7885=item I<pkgname> 7886 7887The TeX Live package identifier, with a possible platform suffix for 7888executables. For instance, C<pdftex> and C<pdftex.i386-linux> are given 7889as two separate packages, one on each line. 7890 7891=item I<status> 7892 7893The status of the package update. One character, as follows: 7894 7895=over 8 7896 7897=item C<d> 7898 7899The package was removed on the server. 7900 7901=item C<f> 7902 7903The package was removed in the local installation, even though a 7904collection depended on it. (E.g., the user ran C<tlmgr remove 7905--force>.) 7906 7907=item C<u> 7908 7909Normal update is needed. 7910 7911=item C<r> 7912 7913Reversed non-update: the locally-installed version is newer than the 7914version on the server. 7915 7916=item C<a> 7917 7918Automatically-determined need for installation, the package is new on 7919the server and is (most probably) part of an installed collection. 7920 7921=item C<i> 7922 7923Package will be installed and isn't present in the local installation 7924(action install). 7925 7926=item C<I> 7927 7928Package is already present but will be reinstalled (action install). 7929 7930=back 7931 7932=item I<localrev> 7933 7934The revision number of the installed package, or C<-> if it is not 7935present locally. 7936 7937=item I<serverrev> 7938 7939The revision number of the package on the server, or C<-> if it is not 7940present on the server. 7941 7942=item I<size> 7943 7944The size in bytes of the package on the server. The sum of all the 7945package sizes is given in the C<total-bytes> header field mentioned above. 7946 7947=item I<runtime> 7948 7949The run time since start of installations or updates. 7950 7951=item I<esttot> 7952 7953The estimated total time. 7954 7955=back 7956 7957=head2 Machine-readable C<option> output 7958 7959The output format is as follows: 7960 7961 key "\t" value 7962 7963If a value is not saved in the database the string C<(not set)> is shown. 7964 7965If you are developing a program that uses this output, and find that 7966changes would be helpful, do not hesitate to write the mailing list. 7967 7968 7969=head1 AUTHORS AND COPYRIGHT 7970 7971This script and its documentation were written for the TeX Live 7972distribution (L<http://tug.org/texlive>) and both are licensed under the 7973GNU General Public License Version 2 or later. 7974 7975=cut 7976 7977# to remake HTML version: pod2html --cachedir=/tmp tlmgr.pl >/foo/tlmgr.html. 7978 7979### Local Variables: 7980### perl-indent-level: 2 7981### tab-width: 2 7982### indent-tabs-mode: nil 7983### End: 7984# vim:set tabstop=2 expandtab: # 7985