From d6601e38e42dad86a071059489bacf9a8515b3d1 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Thu, 3 Sep 2009 00:05:07 +0000 Subject: changes to tlmgr update handling: - --list honors packages on the cmd line, and if nothing is given acts like --all - auto-install, auto-remove, reinstall-forcibly-removed only acts on the packages given on the cmd line - if a package is excluded and would be auto-installed, auto-removed, or reinstalled-after-being-forcibly-removed, tlmgr stops with a warning git-svn-id: svn://tug.org/texlive/trunk@15007 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf/scripts/texlive/tlmgr.pl | 203 ++++++++++++++++++++++------------ 1 file changed, 135 insertions(+), 68 deletions(-) (limited to 'Master/texmf') diff --git a/Master/texmf/scripts/texlive/tlmgr.pl b/Master/texmf/scripts/texlive/tlmgr.pl index ad2a3ac4d77..96b018bcbf3 100755 --- a/Master/texmf/scripts/texlive/tlmgr.pl +++ b/Master/texmf/scripts/texlive/tlmgr.pl @@ -1530,6 +1530,72 @@ EOF # UPDATE # + +# +# compute the list of auto-install, auto-remove, forcibly-removed +# packages from the list of packages to be installed +# the list of packages passed in is already expanded +sub auto_remove_install_force_packages { + my @todo = @_; + my %removals; + my %forcermpkgs; + my %newpkgs; + # check for new/removed/forcibly removed packages. + # we start from the list of installed collections in the local tlpdb + # which are also present in the remote database + # and expand this list once with expand_dependencies in the local tlpdb + # and once in the tlmedia tlpdb. Then we compare the lists + # let A = set of local expansions + # B = set of remote expansions + # then we should(?) have + # B \ A set of new packages + # A \ B set of packages removed on the server + # A \cup B set of packages which should be checked for forcible removal + # + my @schmscolls = (); + for my $p (@todo) { + my $localtlp = $localtlpdb->get_package($p); + if (defined($localtlp)) { + if ($localtlp->category =~ m/^$TeXLive::TLConfig::MetaCategoriesRegexp$/) { + push @schmscolls, $p if defined($tlmediatlpdb->get_package($p)); + } + } + } + my @localexpansion = + $localtlpdb->expand_dependencies($localtlpdb, @schmscolls); + my @remoteexpansion = + $tlmediatlpdb->expand_dependencies($localtlpdb, @schmscolls); + + for my $p (@remoteexpansion) { + $newpkgs{$p} = 1; + } + for my $p (@localexpansion) { + delete($newpkgs{$p}); + $removals{$p} = 1; + } + for my $p (@remoteexpansion) { + delete($removals{$p}); + } + for my $p (@localexpansion) { + # intersection, don't check A\B and B\A + next if $newpkgs{$p}; + next if $removals{$p}; + my $tlp = $localtlpdb->get_package($p); + if (!defined($tlp)) { + if ($opts{"reinstall-forcibly-removed"}) { + $newpkgs{$p} = 1; + } else { + $forcermpkgs{$p} = 1; + } + } + } + debug ("tlmgr: new pkgs: " . join("\n\t",keys %newpkgs) . "\n"); + debug ("tlmgr: deleted : " . join("\n\t",keys %removals) . "\n"); + debug ("tlmgr: forced : " . join("\n\t",keys %forcermpkgs) . "\n"); + + return (\%removals, \%newpkgs, \%forcermpkgs); +} + # tlmgr update foo # if foo is of type Package|Documentation it will update only foo # and the respective .ARCH dependencies @@ -1678,65 +1744,14 @@ sub action_update { unlink($f) unless $opts{"dry-run"}; } - my %removals; - my %forcermpkgs; - my %newpkgs; - # check for new/removed/forcibly removed packages. - # we start from the list of installed collections in the local tlpdb - # which are also present in the remote database - # and expand this list once with expand_dependencies in the local tlpdb - # and once in the tlmedia tlpdb. Then we compare the lists - # let A = set of local expansions - # B = set of remote expansions - # then we should(?) have - # B \ A set of new packages - # A \ B set of packages removed on the server - # A \cup B set of packages which should be checked for forcible removal - # - my @schmscolls = (); - for my $p ($localtlpdb->schemes) { - push @schmscolls, $p - if defined($tlmediatlpdb->get_package($p)); - } - for my $p ($localtlpdb->collections) { - push @schmscolls, $p - if defined($tlmediatlpdb->get_package($p)); - } - my @localexpansion = - $localtlpdb->expand_dependencies($localtlpdb, @schmscolls); - my @remoteexpansion = - $tlmediatlpdb->expand_dependencies($localtlpdb, @schmscolls); - - for my $p (@remoteexpansion) { - $newpkgs{$p} = 1; - } - for my $p (@localexpansion) { - delete($newpkgs{$p}); - $removals{$p} = 1; - } - for my $p (@remoteexpansion) { - delete($removals{$p}); - } - for my $p (@localexpansion) { - # intersection, don't check A\B and B\A - next if $newpkgs{$p}; - next if $removals{$p}; - my $tlp = $localtlpdb->get_package($p); - if (!defined($tlp)) { - if ($opts{"reinstall-forcibly-removed"}) { - $newpkgs{$p} = 1; - } else { - $forcermpkgs{$p} = 1; - } - } - } - debug ("tlmgr: new pkgs: " . join("\n\t",keys %newpkgs) . "\n"); - debug ("tlmgr: deleted : " . join("\n\t",keys %removals) . "\n"); - debug ("tlmgr: forced : " . join("\n\t",keys %forcermpkgs) . "\n"); my @todo; if ($opts{"list"}) { - @todo = $localtlpdb->list_packages; + if ($opts{"all"} || !@ARGV) { + @todo = $localtlpdb->list_packages; + } else { + @todo = @ARGV; + } } elsif ($opts{"self"} && @critical) { @todo = @critical; } elsif ($opts{"all"}) { @@ -1767,6 +1782,55 @@ sub action_update { unless $opts{"list"}; } + my ($remref, $newref, $forref) = auto_remove_install_force_packages(@todo); + my %removals = %$remref; + my %forcermpkgs = %$forref; + my %newpkgs = %$newref; + + # check that the --exclude options do not conflict with the + # options --no-auto-remove, --no-auto-install, --reinstall-forcibly-removed + my @option_conflict_lines = (); + my $in_conflict = 0; + if (!$opts{"no-auto-remove"}) { + for my $pkg (keys %removals) { + for my $ep (@excluded_pkgs) { + if ($pkg eq $ep || $pkg =~ m/^$ep\./) { + push @option_conflict_lines, "$pkg: excluded but scheduled for auto-removal\n"; + $in_conflict = 1; + last; # of the --exclude for loop + } + } + } + } + if (!$opts{"no-auto-install"}) { + for my $pkg (keys %newpkgs) { + for my $ep (@excluded_pkgs) { + if ($pkg eq $ep || $pkg =~ m/^$ep\./) { + push @option_conflict_lines, "$pkg: excluded but scheduled for auto-install\n"; + $in_conflict = 1; + last; # of the --exclude for loop + } + } + } + } + if ($opts{"reinstall-forcibly-removed"}) { + for my $pkg (keys %forcermpkgs) { + for my $ep (@excluded_pkgs) { + if ($pkg eq $ep || $pkg =~ m/^$ep\./) { + push @option_conflict_lines, "$pkg: excluded but scheduled for reinstall\n"; + $in_conflict = 1; + last; # of the --exclude for loop + } + } + } + } + if ($in_conflict) { + tlwarn("Conflicts have been found:\n"); + for (@option_conflict_lines) { tlwarn(" $_"); } + tlwarn("Please resolve these conflicts!\n"); + exit 1; + } + # # we first collect the list of packages to be actually updated or installed my %updated; @@ -1862,11 +1926,11 @@ sub action_update { # remove the packages that have disappeared: # we add that only to the list of total packages do be worked on # when --all is given, because we remove packages only on --all - if (!$opts{"no-auto-remove"} && $opts{"all"}) { + if (!$opts{"no-auto-remove"}) { my @foo = keys %removals; $totalnr += $#foo + 1; } - if (!$opts{"no-auto-install"} && ( $opts{"all"} || $opts{"list"} ) ) { + if (!$opts{"no-auto-install"}) { $totalnr += $#new + 1; push @alltodo, @new; } @@ -1916,15 +1980,12 @@ sub action_update { # - $opts{"list"} is *not* set # we have to check in addition that # - $opts{"dry-run"} is not set - # - and that we do --all updates, not single package updates - if ($opts{"all"}) { - info("[$currnr/$totalnr] auto-remove: $p\n"); - if (!$opts{"dry-run"}) { - $localtlmedia->remove_package($p); - logpackage("remove: $p"); - } - $currnr++; + info("[$currnr/$totalnr] auto-remove: $p\n"); + if (!$opts{"dry-run"}) { + $localtlmedia->remove_package($p); + logpackage("remove: $p"); } + $currnr++; } } } @@ -4225,7 +4286,9 @@ In brief: =item B<--list> Concisely list the packages which would be updated, newly installed, or -removed, without actually changing anything. +removed, without actually changing anything. If no package is given +acts like C<--list --all>, otherwise lists only updates to the packages +given as arguments (and its dependencies). =item B<--exclude I> @@ -4235,9 +4298,13 @@ C itself and all packages C. As an example giving tlmgr update --all --exclude a2ping -will not update C itself, but neither C or +will not update C itself, nor C or any other arch-package C. +Note that if a package is schedules for auto-installation, auto-removal, +or reinstallation of a forcibly removed, and at the same time +is excluded, tlmgr will warn you and stop. + =item B<--dry-run> Nothing is actually installed; instead, the actions to be performed are -- cgit v1.2.3