Index: tlpkg/TeXLive/TLConfig.pm =================================================================== --- tlpkg/TeXLive/TLConfig.pm (revision 14577) +++ tlpkg/TeXLive/TLConfig.pm (working copy) @@ -183,7 +183,8 @@ our %TLPDBSettings = ( "platform" => [ "s", "Main platform for this computer" ], - "available_architectures" => [ "l", "All available/installed architectures" ] + "available_architectures" => [ "l", "All available/installed architectures" ], + "usertree" => [ "b", "This tree acts as user tree" ] ); our $WindowsMainMenuName = "TeX Live $ReleaseYear"; Index: tlpkg/TeXLive/TLPOBJ.pm =================================================================== --- tlpkg/TeXLive/TLPOBJ.pm (revision 14577) +++ tlpkg/TeXLive/TLPOBJ.pm (working copy) @@ -459,6 +459,21 @@ sub cancel_reloc_prefix { my $self = shift; my @docfiles = $self->docfiles; + for (@docfiles) { s:^$RelocPrefix/::; } + $self->docfiles(@docfiles); + my @runfiles = $self->runfiles; + for (@runfiles) { s:^$RelocPrefix/::; } + $self->runfiles(@runfiles); + my @srcfiles = $self->srcfiles; + for (@srcfiles) { s:^$RelocPrefix/::; } + $self->srcfiles(@srcfiles); + # if there are bin files they have definitely NOT the + # texmf-dist prefix, so we cannot cancel it anyway +} + +sub replace_reloc_prefix { + my $self = shift; + my @docfiles = $self->docfiles; for (@docfiles) { s:^$RelocPrefix/:$RelocTree/:; } $self->docfiles(@docfiles); my @runfiles = $self->runfiles; Index: tlpkg/TeXLive/TLMedia.pm =================================================================== --- tlpkg/TeXLive/TLMedia.pm (revision 14577) +++ tlpkg/TeXLive/TLMedia.pm (working copy) @@ -60,6 +60,8 @@ } if (-d "$location/texmf/web2c") { $media = 'DVD'; + } elsif (-d "$location/web2c") { + $media = 'DVD'; } elsif (-d "$location/$Archive") { $media = 'CD'; } else { @@ -247,8 +249,12 @@ } # if a package is relocatable we have to cancel the reloc prefix # before we save it to the local tlpdb - if ($tlpobj->relocated) { - $tlpobj->cancel_reloc_prefix; + if ($reloc) { + if ($totlpdb->setting("usertree")) { + $tlpobj->cancel_reloc_prefix; + } else { + $tlpobj->replace_reloc_prefix; + } } # we have to write out the tlpobj file since it is contained in the # archives (.tar.xz) but at DVD install time we don't have them @@ -317,7 +323,11 @@ } elsif ($what =~ m,\.tar(\.xz)?$,) { my $type = defined($1) ? "xz" : "tar"; - $target .= "/$TeXLive::TLConfig::RelocTree" if $reloc; + if ($reloc) { + if (!$totlpdb->setting("usertree")) { + $target .= "/$TeXLive::TLConfig::RelocTree" if $reloc; + } + } # this is the case when we install from CD or the NET, or a backup # @@ -400,6 +410,7 @@ my ($self, $pkg, $nopostinstall) = @_; my $localtlpdb = $self->tlpdb; my $tlp = $localtlpdb->get_package($pkg); + my $usertree = $localtlpdb->setting("usertree"); if (!defined($tlp)) { tlwarn ("$pkg: package not present, cannot remove\n"); } else { @@ -425,9 +436,12 @@ # in user mode we just remove the prefix, in normal mode we # replace it with texmf-dist # since we don't have user mode + if ($tlp->relocated) { for (@files) { - s:^$RelocPrefix/:$RelocTree/:; + if (!$usertree) { + s:^$RelocPrefix/:$RelocTree/:; + } } } # Index: tlpkg/TeXLive/TLUtils.pm =================================================================== --- tlpkg/TeXLive/TLUtils.pm (revision 14577) +++ tlpkg/TeXLive/TLUtils.pm (working copy) @@ -1198,7 +1198,7 @@ # if a package is relocatable we have to cancel the reloc prefix # before we save it to the local tlpdb if ($tlpobj->relocated) { - $tlpobj->cancel_reloc_prefix; + $tlpobj->replace_reloc_prefix; } $totlpdb->add_tlpobj($tlpobj); # we have to write out the tlpobj file since it is contained in the Index: texmf/scripts/texlive/tlmgr.pl =================================================================== --- texmf/scripts/texlive/tlmgr.pl (revision 14581) +++ texmf/scripts/texlive/tlmgr.pl (working copy) @@ -122,6 +122,8 @@ "machine-readable" => 1, "package-logfiles" => "=s", "pause" => 1, + "usermode" => 1, + "usertree" => "=s", "version" => 1, "help|h|?" => 1); @@ -285,13 +287,30 @@ pod2usage(-msg => $msg, -exitstatus => 1, -verbose => 1, @noperldoc); } + # + # the main tree we will be working on + $::maintree = $Master; + if ($opts{"usermode"}) { + # we could also try to detect that we don't have write permissions + # and switch to user mode automatically + if (defined($opts{"usertree"})) { + $::maintree = $opts{"usertree"}; + } else { + chomp($::maintree = `kpsewhich -var-value TEXMFHOME`); + } + } + # besides doing normal logging if -logfile is specified, we try to log # package related actions (install, remove, update) to # the package-log file TEXMFSYSVAR/web2c/tlmgr.log $packagelogged = 0; # how many msgs we logged chomp (my $texmfsysvar = `kpsewhich -var-value=TEXMFSYSVAR`); $packagelogfile = $opts{"package-logfile"}; - $packagelogfile ||= "$texmfsysvar/web2c/tlmgr.log"; + if ($opts{"usermode"}) { + $packagelogfile ||= "$::maintree/web2c/tlmgr.log"; + } else { + $packagelogfile ||= "$texmfsysvar/web2c/tlmgr.log"; + } # # Try to open the packagelog file, but do NOT die when that does not work if (!open(PACKAGELOG, ">>$packagelogfile")) { @@ -427,6 +446,9 @@ } elsif ($action =~ m/^show$/i) { action_show(); finish(0); + } elsif ($action =~ m/^init-usertree$/i) { + action_init_usertree(); + finish(0); } elsif ($action =~ m/^remove$/i) { action_remove(); } elsif ($action =~ /^paper$/) { @@ -480,6 +502,8 @@ # sub handle_execute_actions { + my $sysmode = ($opts{"usermode"} ? "" : "-sys"); + my $errors = 0; if ($::files_changed) { @@ -512,14 +536,14 @@ } } for my $m (keys %do_disable) { - $errors += do_cmd_and_check("updmap-sys --nomkmap --nohash --disable $m"); + $errors += do_cmd_and_check("updmap$sysmode --nomkmap --nohash --disable $m"); } for my $m (keys %do_enable) { - my $str = "updmap-sys --nomkmap --nohash --enable " . + my $str = "updmap$sysmode --nomkmap --nohash --enable " . $::execute_actions{'enable'}{'maps'}{$m} . "=$m"; $errors += do_cmd_and_check($str); } - $errors += do_cmd_and_check("updmap-sys") if $run_full; + $errors += do_cmd_and_check("updmap$sysmode") if $run_full; } @@ -561,7 +585,7 @@ if ($opt_fmt && !$::regenerate_all_formats) { for my $f (keys %do_enable) { log ("(re)creating format dump $f\n"); - $errors += do_cmd_and_check("fmtutil-sys --byfmt $f"); + $errors += do_cmd_and_check("fmtutil$sysmode --byfmt $f"); $done_formats{$f} = 1; } @@ -576,7 +600,7 @@ for my $e (@upen) { if ($def{'engine'} eq $e) { log ("updating format $def{'name'} (engine $e updated)\n"); - $errors += do_cmd_and_check("fmtutil-sys --byfmt $def{'name'}"); + $errors += do_cmd_and_check("fmtutil$sysmode --byfmt $def{'name'}"); $done_formats{$def{'name'}} = 1; } } @@ -618,7 +642,7 @@ $lang = "$TEXMFSYSVAR/tex/generic/config/$lang"; } if ($localtlpdb->option("create_formats") && !$::regenerate_all_formats) { - $errors += do_cmd_and_check("fmtutil-sys --byhyphen $lang"); + $errors += do_cmd_and_check("fmtutil$sysmode --byhyphen $lang"); } } } @@ -627,7 +651,7 @@ # if ($::regenerate_all_formats) { info("Regenerating all formats, this may take some time ..."); - $errors += do_cmd_and_check("fmtutil-sys --all"); + $errors += do_cmd_and_check("fmtutil$sysmode --all"); info("done\n"); $::regenerate_all_formats = 0; } @@ -799,8 +823,13 @@ action_gui("config") if $opts{"gui"}; init_local_db(); - chomp(my $texmfsysconfig = `kpsewhich -var-value=TEXMFSYSCONFIG`); - $ENV{"TEXMFCONFIG"} = $texmfsysconfig; + my $texmfconfig; + if ($opts{"usermode"}) { + chomp($texmfconfig = `kpsewhich -var-value=TEXMFCONFIG`); + } else { + chomp($texmfconfig = `kpsewhich -var-value=TEXMFSYSCONFIG`); + } + $ENV{"TEXMFCONFIG"} = $texmfconfig; my $action = shift @ARGV; if ($action =~ m/^paper$/i) { # generic paper @@ -812,14 +841,14 @@ "as in: tlmgr pdftex paper --list\n"); } elsif (!defined($newpaper)) { # tlmgr paper => show all current sizes. - TeXLive::TLPaper::paper_all($texmfsysconfig,undef); + TeXLive::TLPaper::paper_all($texmfconfig,undef); } elsif ($newpaper !~ /^(a4|letter)$/) { # tlmgr paper junk => complain. $newpaper = "the empty string" if !defined($newpaper); tlwarn("tlmgr: expected `a4' or `letter' after paper, not $newpaper\n"); } else { # tlmgr paper {a4|letter} => do it. - TeXLive::TLPaper::paper_all($texmfsysconfig,$newpaper); + TeXLive::TLPaper::paper_all($texmfconfig,$newpaper); } } else { # program-specific paper @@ -833,7 +862,7 @@ # the do_paper progs check for the argument --list, so if given # restore it to the cmd line. unshift(@ARGV, "--list") if $opts{"list"}; - TeXLive::TLPaper::do_paper($prog,$texmfsysconfig,@ARGV); + TeXLive::TLPaper::do_paper($prog,$texmfconfig,@ARGV); } } @@ -874,13 +903,14 @@ # include arbitrary package in the list of collections, but # only collectons: @colls = grep {m;^collection-;} @colls; - print "Package: ", $tlp->name, "\n"; - print "Category: ", $tlp->category, "\n"; - print "ShortDesc: ", $tlp->shortdesc, "\n" if ($tlp->shortdesc); - print "LongDesc: ", $tlp->longdesc, "\n" if ($tlp->longdesc); - print "Installed: ", ($installed ? "Yes" : "No"), "\n"; - print "Revision: ", $tlp->revision, "\n" if ($installed); - print "Collection: ", @colls, "\n" if (@colls); + print "Package: ", $tlp->name, "\n"; + print "Category: ", $tlp->category, "\n"; + print "ShortDesc: ", $tlp->shortdesc, "\n" if ($tlp->shortdesc); + print "LongDesc: ", $tlp->longdesc, "\n" if ($tlp->longdesc); + print "Installed: ", ($installed ? "Yes" : "No"), "\n"; + print "Revision: ", $tlp->revision, "\n" if ($installed); + print "Relocatable: ", ($tlp->relocated ? "Yes" : "No"), "\n"; + print "Collection: ", @colls, "\n" if (@colls); if ($opts{"list"}) { if ($tlp->category eq "Collection" || $tlp->category eq "Scheme") { # in the case of collections of schemes we list the deps @@ -944,6 +974,10 @@ # SYMLINKS # sub action_path { + if ($opts{"usermode"}) { + tlwarn("action `path' not supported in usermode!\n"); + exit 1; + } my $what = shift @ARGV; if (!defined($what) || ($what !~ m/^(add|remove)$/i)) { tlwarn("action path needs one argument, either add or remove\n"); @@ -1424,7 +1458,10 @@ # check for updates to tlmgr and die unless either --force or --list or --self # is given - my @critical = check_for_critical_updates($localtlpdb, $tlmediatlpdb); + my @critical; + if (!$opts{"usermode"}) { + @critical = check_for_critical_updates($localtlpdb, $tlmediatlpdb); + } my $dry_run_cont = $opts{"dry-run"} && ($opts{"dry-run"} < 0); if ( !$dry_run_cont && !$opts{"self"} && @critical) { critical_updates_warning(); @@ -2060,16 +2097,18 @@ init_tlmedia(); # check for updates to tlmgr itself, and die unless --force is given - if (check_for_critical_updates( $localtlpdb, $tlmediatlpdb)) { - critical_updates_warning(); - if ($opts{"force"}) { - tlwarn("Continuing due to --force\n"); - } else { - if ($::gui_mode) { - # return here and don't do any updates - return; + if (!$opts{"usermode"}) { + if (check_for_critical_updates( $localtlpdb, $tlmediatlpdb)) { + critical_updates_warning(); + if ($opts{"force"}) { + tlwarn("Continuing due to --force\n"); } else { - die "tlmgr: Not continuing, please see warning above!\n"; + if ($::gui_mode) { + # return here and don't do any updates + return; + } else { + die "tlmgr: Not continuing, please see warning above!\n"; + } } } } @@ -2106,6 +2145,15 @@ } } foreach my $pkg (@inst_packs, @inst_colls, @inst_schemes) { + my $tlp = $tlmediasrc->tlpdb->get_package($pkg); + if (!defined($tlp)) { + info("Unknown package $pkg\n"); + next; + } + if (!$tlp->relocated && $opts{"usermode"}) { + info("Package $pkg is not relocatable, cannot install it in user mode!\n"); + next; + } my $re = ""; if (defined($localtlpdb->get_package($pkg))) { if ($opts{"reinstall"}) { @@ -2321,6 +2369,10 @@ if ($^O=~/^MSWin(32|64)$/i) { warn("action `arch' not supported on Windows\n"); } + if ($opts{"usermode"}) { + tlwarn("action `arch' not supported in usermode\n"); + exit 1; + } if ($opts{"gui"}) { action_gui("arch"); } @@ -2402,6 +2454,10 @@ # GENERATE # sub action_generate { + if ($opts{"usermode"}) { + tlwarn("action `generate' not supported in usermode!\n"); + exit 1; + } my $dest = defined($opts{"dest"}) ? $opts{"dest"} : ""; my $localconf = defined($opts{"localcfg"}) ? $opts{"localcfg"} : ""; my $what = shift @ARGV; @@ -3209,6 +3265,34 @@ # +# action init_user_tree +# sets up TEXMFHOME or --usertree argument for user mode tlmgr +# by creating a minimal tlpdb +# +sub action_init_usertree { + init_local_db(); + my $tlpdb = TeXLive::TLPDB->new; + my $usertree; + if ($opts{"usertree"}) { + $usertree = $opts{"usertree"}; + } else { + chomp($usertree = `kpsewhich -var-value TEXMFHOME`); + } + $tlpdb->root($usertree); + my $inst = TeXLive::TLPOBJ->new; + $inst->name("00texlive.installation"); + $inst->category("TLCore"); + my @deps; + push @deps, "opt_location:$location"; + push @deps, "setting_available_architectures:"; + push @deps, "setting_usertree:1"; + $inst->depends(@deps); + $tlpdb->add_tlpobj($inst); + $tlpdb->save; +} + + +# # action conf # tries to mimick texconfig conf but probably will add some more things # @@ -3272,10 +3356,10 @@ # stuff changed via the GUI return if defined $localtlmedia; return if defined $localtlpdb; - $localtlmedia = TeXLive::TLMedia->new ( $Master ); - die("cannot setup TLMedia in $Master") unless (defined($localtlmedia)); + $localtlmedia = TeXLive::TLMedia->new ( $::maintree ); + die("cannot setup TLMedia in $::maintree") unless (defined($localtlmedia)); $localtlpdb = $localtlmedia->tlpdb; - die("cannot find tlpdb in $Master") unless (defined($localtlpdb)); + die("cannot find tlpdb in $::maintree") unless (defined($localtlpdb)); # setup the programs, for w32 we need the shipped wget/xz etc, so we # pass the location of these files to setup_programs. if (!setup_programs("$Master/tlpkg/installer", $localtlmedia->platform)) {