diff options
Diffstat (limited to 'Master/tlpkg/archive/applied.auto-backup-feature.patch')
-rw-r--r-- | Master/tlpkg/archive/applied.auto-backup-feature.patch | 414 |
1 files changed, 414 insertions, 0 deletions
diff --git a/Master/tlpkg/archive/applied.auto-backup-feature.patch b/Master/tlpkg/archive/applied.auto-backup-feature.patch new file mode 100644 index 00000000000..aa01f1d1381 --- /dev/null +++ b/Master/tlpkg/archive/applied.auto-backup-feature.patch @@ -0,0 +1,414 @@ +Implement automatic backups +Current status: + tlmgr option backupdir ..... +sets the defalt backup dir. Now tlmgr update can take another argument + tlmgr update --backup .... +which creates backups in the default backupdir as specified in the TLPDB. + +Furthermore, if the tlpdb opion autobackup is set to a integer >= -1 the +following happens (all of them need the option backupdir set to an +existing directory) + tlmgr option autobackup -1 + always make backups, keep infinitely many + tlmgr option autobackup 0 + disable automatic backups + tlmgr option autobackup N + for N > 0 keep N backups + + +So if you want to set up automatic backups, do: + mkdir /var/cache/texlive-backups + tlmgr option backupdir /var/cache/texlive-backups/ + tlmgr option autobackup 5 + + +Cleaning mode: + tlmgr backup --clean[=ARG] [--backupdir=dir] [--all] [packs] + +if NO --clean is given, a backup is made. + +if --clean is given without any argument, then the value of "autobackup" +in the tlpdb is used (should we change the name?) + +if --clean=ARG is given it must be either -1, 0, 1, ... with the following +meaning: + -1: do nothing, keep all backups (not very useful, but ... + N>=0 keep only N backups (that means for N == 0 all backups + will be removed) + +If --backupdir is NOT given we will try to initialize it from TLPDB +option "backupdir". + + +TODO: +. testing on windows +. documentation in POD format +. testing with .doc/.src args, and with .ARCH packages, no idea + what is going on there + +--- + +Index: texmf/scripts/texlive/tlmgr.pl +=================================================================== +--- texmf/scripts/texlive/tlmgr.pl (revision 11087) ++++ texmf/scripts/texlive/tlmgr.pl (working copy) +@@ -34,6 +34,16 @@ + # - always do backups, let the user clean them up manually + # Possibly, an operation like 'tlmgr clean' for cleaning old backup could + # be great. ++# format for the options: ++# option backupdir ++# option autobackup/TIME ++# where TIME = natural number N -> keep N backups per package ++# or = 0 -> don't do auto backups ++# or = -1 (= +\infty) keep backup indefinitely ++# or = Nd | Nw | Nm -> keeping backups younger then ++# Nd N days ++# Nw N weeks ++# Nm N months + # - ordering or collections removal (see below for details) + # - (?) removal does not remove created format files from TEXMFSYSVAR + # - after install/update show the number of bytes transfered +@@ -112,7 +122,7 @@ + "gui-lang=s" => \$opt_gui_lang, + "package-logfile=s" => \$opt_packagelogfile, + "version" => \$opt_version, +- "pause" => \$opt_pause, ++ "pause" => \$opt_pause, + "h|help|?" => \$opt_help) or pod2usage(2); + + my $action = shift; +@@ -731,14 +741,90 @@ + my $opt_dry = 0; + my $opt_all = 0; + my $opt_backupdir; ++ # --clean argument ++ # can be either -1 ... don't clean ++ # 0 ... remove all backups ++ # N ... keep only N backups ++ # that parallels the value of autoclean in the configuration ++ # we have to be careful, because if simply --clean is given, we should ++ # check for the value saved in the tlpdb, and if that is not present ++ # do nothing. But Getopt::Long with clean:i leaves 0 in $opt_clean if ++ # it is present. So ++ # !defined($opt_clean) -> no --clean given ++ # $opt_clean = "" -> --clean without argument given, check tlpdb ++ # $opt_clean = -1, 0, N -> --clean=N given, check argument ++ # ++ my $opt_clean; + Getopt::Long::Configure(@getopt_configure_subopts); + GetOptions("all" => \$opt_all, + "backupdir=s" => \$opt_backupdir, ++ "clean:s" => \$opt_clean, ++ "n|dry-run" => \$opt_dry, + ) or pod2usage(2); ++ my $clean_mode = 0; ++ $clean_mode = 1 if defined($opt_clean); ++ if ($clean_mode) { ++ if ($opt_clean eq "") { ++ # we need to check the tlpdb ++ $opt_clean = $localtlpdb->option("autobackup"); ++ if (!$opt_clean) { ++ tlwarn ("--clean given without an argument, but no default clean\n"); ++ tlwarn ("mode specified in the tlpdb, terminating.\n"); ++ exit 1; ++ } ++ } ++ # now $opt_clean is something, but maybe not a number, check for ++ # validity ++ if ($opt_clean =~ m/^(-1|[0-9]+)$/) { ++ # get rid of leading zeros etc etc ++ $opt_clean = $opt_clean + 0; ++ } else { ++ tlwarn ("clean mode as specified on the command line or as given by default\n"); ++ tlwarn ("must be an integer larger or equal than -1, terminating.\n"); ++ exit 1; ++ } ++ } ++ # check the backup dir argument ++ my $die_backupdir = 0; ++ if ($opt_backupdir) { ++ my $ob = abs_path($opt_backupdir); ++ $ob && ($opt_backupdir = $ob); ++ if (! -d $opt_backupdir) { ++ tlwarn ("backupdir argument $opt_backupdir is not a directory.\n"); ++ if ($clean_mode) { ++ tlwarn ("Cannot clean a non existing directory, terminating.\n"); ++ } else { ++ tlwarn ("Don't know where to save backups, terminating.\n"); ++ } ++ exit 1; ++ } ++ } else { ++ # no argument, check for presence in TLPDB ++ $opt_backupdir = $localtlpdb->option("backupdir"); ++ if (!$opt_backupdir) { ++ if ($clean_mode) { ++ tlwarn ("Cannot clean an unknown directory, terminating.\n"); ++ } else { ++ tlwarn ("Don't know where to save backups, terminating.\n"); ++ } ++ exit 1; ++ } ++ # we are stil here, there is something set in tlpdb ++ my $ob = abs_path($opt_backupdir); ++ $ob && ($opt_backupdir = $ob); ++ if (! -d $opt_backupdir) { ++ tlwarn ("backupdir as set in tlpdb $opt_backupdir is not a directory.\n"); ++ if ($clean_mode) { ++ tlwarn ("Cannot clean a non existing directory, terminating.\n"); ++ } else { ++ tlwarn ("Don't know where to save backups, terminating.\n"); ++ } ++ exit 1; ++ } ++ } ++ + my %ret; + my @todo; +- die ("tlmgr backup needs an obligatory argument --backupdir") +- unless (defined($opt_backupdir)); + if ($opt_all) { + @todo = $localtlpdb->list_packages; + } else { +@@ -748,13 +834,16 @@ + printf "tlmgr backup takes either a list of packages or --all\n"; + } + foreach my $pkg (@todo) { +- $opt_backupdir = abs_path($opt_backupdir); +- if (! -d $opt_backupdir) { +- printf STDERR "backupdir argument must be an existing directory!\n"; ++ if ($clean_mode) { ++ clear_old_backups ($pkg, $opt_backupdir, $opt_clean, $opt_dry); + } else { + my $tlp = $localtlpdb->get_package($pkg); +- $tlp->make_container("lzma", $localtlpdb->root, +- $opt_backupdir, "${pkg}.r" . $tlp->revision); ++ info("saving current status of $pkg to $opt_backupdir${pkg}.r" . ++ $tlp->revision . ".\n"); ++ if (!$opt_dry) { ++ $tlp->make_container("lzma", $localtlpdb->root, ++ $opt_backupdir, "${pkg}.r" . $tlp->revision); ++ } + } + } + return(\%ret); +@@ -928,6 +1017,7 @@ + my $opt_list = 0; + my $opt_noremove = 0; + my $opt_backupdir; ++ my $opt_backup = 0; + Getopt::Long::Configure(@getopt_configure_subopts); + GetOptions("no-depends" => \$opt_nodepends, + "no-depends-at-all" => \$opt_reallynodepends, +@@ -935,6 +1025,7 @@ + "list" => \$opt_list, + "no-remove" => \$opt_noremove, + "backupdir=s" => \$opt_backupdir, ++ "backup" => \$opt_backup, + "n|dry-run" => \$opt_dry) or pod2usage(2); + $opt_nodepends = 1 if $opt_reallynodepends; + my $nrupdated = 0; +@@ -944,6 +1035,70 @@ + my $mediatlpdb = $tlmediasrc->tlpdb; + info("update: dry run, no changes will be made\n") if $opt_dry; + ++ # do backup dir checking now so that we don't run into troubles ++ # later, and exit if that doesn't work ++ if ($opt_backupdir) { ++ $opt_backupdir = abs_path($opt_backupdir); ++ if (! -d $opt_backupdir) { ++ tlwarn("Argument for --backupdir must be an existing directory. Terminating.\n"); ++ exit 1; ++ } ++ } ++ ++ my $autobackup = 0; ++ # check for the tlpdb option autobackup, and if present and true (!= 0) ++ # assume we are doing backups ++ if (!$opt_backup) { ++ $autobackup = $localtlpdb->option("autobackup"); ++ if ($autobackup) { ++ # check the format, we currently allow only natural numbers, and -1 ++ if ($autobackup eq "-1") { ++ debug ("Automatic backups activated, keeping \\infty backups.\n"); ++ $opt_backup = 1; ++ } elsif ($autobackup eq "0") { ++ debug ("Automatic backups disabled.\n"); ++ } elsif ($autobackup =~ m/^[0-9]+$/) { ++ debug ("Automatic backups activated, keeping $autobackup backups.\n"); ++ $opt_backup = 1; ++ } else { ++ tlwarn ("Option autobackup can only be an integer >= -1.\n"); ++ tlwarn ("Disabling auto backups.\n"); ++ $localtlpdb->option("autobackup", 0); ++ $autobackup = 0; ++ } ++ } ++ } ++ ++ # cmd line --backup, we check for --backupdir, and if that is not given ++ # we try to get the default from the tlpdb. If that doesn't work, exit. ++ if ($opt_backup) { ++ my $diebackupdir = 0; ++ if (!$opt_backupdir) { ++ $opt_backupdir = $localtlpdb->option("backupdir"); ++ if ($opt_backupdir) { ++ # check again: ++ $opt_backupdir = abs_path($opt_backupdir); ++ $diebackupdir = 1 if (! -d $opt_backupdir); ++ } else { ++ # not set in the tlpdb, and not set on cmd line, but asked for ++ # --backup ++ $diebackupdir = 1; ++ } ++ } ++ # no else branch necessary, we already checked that --backupdir if ++ # given is ok, see above ++ if ($diebackupdir) { ++ tlwarn("You have asked for backups, but the backup directory as specified\n"); ++ tlwarn("in the local TLPDB or the cmd line does not exists, exiting.\n"); ++ exit 1; ++ } ++ } ++ ++ # finally, if we have --backupdir, but no --backup, just enable it ++ $opt_backup = 1 if $opt_backupdir; ++ ++ debug("Doing backups to $opt_backupdir\n") if $opt_backup; ++ + # these two variables are used throughout this function + my $root = $localtlpdb->root; + my $temp = "$root/temp"; +@@ -1122,19 +1277,18 @@ + if ($opt_list) { + info("$pkg: local: $rev, source: $mediarev\n"); + } else { +- # first remove the package, then reinstall it +- # this way we get rid of useless files +- # force the deinstallation since we will reinstall it +- if ($opt_backupdir && !$opt_dry) { +- $opt_backupdir = abs_path($opt_backupdir); +- if (! -d $opt_backupdir) { +- tlwarn("backupdir argument must be an existing directory!\n"); +- } else { +- $tlp->make_container("lzma", $root, +- $opt_backupdir, "${pkg}.r" . $tlp->revision); +- $unwind_package = "$opt_backupdir/${pkg}.r" . $tlp->revision . ".tar.lzma"; ++ if ($opt_backup && !$opt_dry) { ++ $tlp->make_container("lzma", $root, ++ $opt_backupdir, "${pkg}.r" . $tlp->revision); ++ $unwind_package = ++ "$opt_backupdir/${pkg}.r" . $tlp->revision . ".tar.lzma"; ++ ++ if ($autobackup) { ++ # in case we do auto backups we remove older backups ++ clear_old_backups($pkg, $opt_backupdir, $autobackup); + } + } ++ + if (win32() && ($pkg =~ m/$WinSpecialUpdatePackagesRegexp/)) { + add_w32_updater($mediatlp, $opt_dry); + } else { +@@ -1161,6 +1315,10 @@ + $remove_unwind_container = 1; + $unwind_package = "$fullname"; + } ++ # first remove the package, then reinstall it ++ # this way we get rid of useless files ++ # force the deinstallation since we will reinstall it ++ # + # the remove_package should also remove empty dirs in case + # a dir is changed into a file + merge_into(\%ret, &remove_package($pkg, $localtlpdb, 1)); +@@ -1176,7 +1334,7 @@ + # dirs from the new package before re-installing the old one. + # TODO + logpackage("failed update: $pkg ($rev -> $mediarev)"); +- tlwarn("\n\nInstallation of new version of $pkg did fail, trying to unwind!\n"); ++ tlwarn("\n\nInstallation of new version of $pkg did fail, trying to unwind.\n"); + if (win32()) { + # w32 is notorious for not releasing a file immediately + # we experienced permission denied errors +@@ -1402,7 +1560,15 @@ + print "Install documentation files: ", ($localtlpdb->option_install_docfiles ? "yes": "no"), "\n"; + print "Install source files: ", ($localtlpdb->option_install_srcfiles ? "yes": "no"), "\n"; + } else { +- warn "Setting other options currently not supported, please edit texlive.tlpdb!"; ++ my $val = shift @ARGV; ++ if (defined($val)) { ++ print "Setting option $what to $val.\n"; ++ $localtlpdb->option($what,$val); ++ $localtlpdb->save; ++ } else { ++ print "Option $what = ", $localtlpdb->option($what), "\n";; ++ } ++ #warn "Setting other options currently not supported, please edit texlive.tlpdb!"; + } + return; + } +@@ -1961,6 +2127,37 @@ + } + + ++# clear the backup dir for $pkg and keep only $autobackup packages ++# mind that with $autobackup == 0 all packages are cleared ++sub clear_old_backups ++{ ++ my ($pkg, $opt_backupdir, $autobackup, $opt_dry) = @_; ++ ++ my $dryrun = 0; ++ $dryrun = 1 if ($opt_dry); ++ # keep arbitrary many backups ++ return if ($autobackup == -1); ++ ++ opendir (DIR, $opt_backupdir) || die "opendir($opt_backupdir) failed: $!"; ++ my @dirents = readdir (DIR); ++ closedir (DIR) || warn "closedir($opt_backupdir) failed: $!"; ++ my @backups; ++ for my $dirent (@dirents) { ++ next if (-d $dirent); ++ next if ($dirent !~ m/^$pkg\.r([0-9]+)\.tar\.lzma$/); ++ push @backups, $1; ++ } ++ my $i = 1; ++ for my $e (reverse sort {$a <=> $b} @backups) { ++ if ($i > $autobackup) { ++ info ("Removing backup $opt_backupdir/$pkg.r$e.tar.lzma\n"); ++ unlink("$opt_backupdir/$pkg.r$e.tar.lzma") unless $dryrun; ++ } ++ $i++; ++ } ++} ++ ++ + # + # return all the directories from which all content will be removed + # +Index: tlpkg/TeXLive/TLPDB.pm +=================================================================== +--- tlpkg/TeXLive/TLPDB.pm (revision 11087) ++++ tlpkg/TeXLive/TLPDB.pm (working copy) +@@ -49,6 +49,7 @@ + $tlpdb->config_container_format; + $tlpdb->config_release; + $tlpdb->config_revision; ++ $tlpdb->option($key, [$value]); + + TeXLive::TLPDB->listdir([$dir]); + $tlpdb->generate_listfiles([$destdir]); +@@ -955,6 +956,14 @@ + return; + } + ++sub option { ++ my $self = shift; ++ my $key = shift; ++ if (@_) { $self->_set_option_value($key, shift); } ++ return $self->_option_value($key); ++} ++# TODO the above function should be used in the functions below as ++# far as possible ... + sub option_available_architectures { + my $self = shift; + if (@_) { $self->_set_option_value("available_architectures","@_"); } |