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