diff options
author | Christophe Fergeau <cfergeau@mandriva.com> | 2009-08-10 14:37:04 +0000 |
---|---|---|
committer | Christophe Fergeau <cfergeau@mandriva.com> | 2009-08-10 14:37:04 +0000 |
commit | 307fdff9e12f783b01d0275d92c22b4cf7dd020f (patch) | |
tree | de8a85ccaf674b8ab7845bd76f80727c9a84e405 | |
parent | 2aa62ffc953968bbc0911ad1fdb7eb54f86fc06b (diff) | |
download | perl-URPM-307fdff9e12f783b01d0275d92c22b4cf7dd020f.tar perl-URPM-307fdff9e12f783b01d0275d92c22b4cf7dd020f.tar.gz perl-URPM-307fdff9e12f783b01d0275d92c22b4cf7dd020f.tar.bz2 perl-URPM-307fdff9e12f783b01d0275d92c22b4cf7dd020f.tar.xz perl-URPM-307fdff9e12f783b01d0275d92c22b4cf7dd020f.zip |
use set_rejected_and_compute_diff_provides for package removal
Patch by Anssi Hannula, fixes bug #52667
k1-1 provides k, but not k1-2
l-1 and l-2 requires k
m-1 requires k but not m-2
n requires m
User has l-1, m-1, n-1, k1-1.
There is only one upgrade path:
k1-1 -> k1-2
m-1 -> m-2
removal of l-1
When transaction is created with all of them (e.g. what --auto-select does
first), the path is resolved correctly.
However, when the upgrade is triggered with the upgrade of k1, and l is in RPM
db before n, resolving proceeds as follows:
1. k1 selected and old version rejected
2. l is promoted
3. m is promoted
4. l-2 is therefore selected
5. no packages are found for k (as k1-1 was rejected in step 1)
6. backtrack_selected calls resolve_rejected to reject the chain
7. rejection process rejects l, m, n
8. m-2 is selected because of step 3
End result: n is wrongly removed.
Therefore, when using --auto-select (with --split-length 1 --split-level 1 in
this small case, to force splitting) to trigger the upgrade, the early resolve
is done correctly, but the first splitted transaction ("rpms sorted by
dependencies" has k1 and m separately, so split is tried) tries to remove n and
URPM fallbacks to single big transaction.
In reverse, when using "urpmi k1" to trigger the upgrade, urpmi asks user
confirmation for n removal, but the transaction is created with both k1 and m
("rpms sorted by dependencies" has k1+m, so they are put in same transaction),
thus triggering the correct behaviour and n is not really removed after all,
even if user agreed to it.
Attached patch fixes this by switching backtrack_selected() to use
set_rejected_and_compute_diff_provides() for package removal instead of
resolve_rejected_(). The code already contained a comment indicating that
diff_provides code should be applied.
The patch introduces no regression in the urpmi and perl-URPM testsuites.
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | URPM/Resolve.pm | 21 |
2 files changed, 13 insertions, 10 deletions
@@ -1,3 +1,5 @@ +- backtrack_selected: use set_rejected_and_compute_diff_provides for package + removal (Anssi Hannula) - obey options (keep, nodeps) when unselecting current package in the case that was added in 3.31 (Anssi Hannula) diff --git a/URPM/Resolve.pm b/URPM/Resolve.pm index 1079ad8..4f8a9e1 100644 --- a/URPM/Resolve.pm +++ b/URPM/Resolve.pm @@ -384,7 +384,7 @@ sub _score_for_locales { #- side-effects: $properties, $choices #- + those of backtrack_selected ($state->{backtrack}, $state->{rejected}, $state->{selected}, $state->{whatrequires}, flag_requested, flag_required) sub _choose_required { - my ($urpm, $db, $state, $dep, $properties, $choices, %options) = @_; + my ($urpm, $db, $state, $dep, $properties, $choices, $diff_provides, %options) = @_; #- take the best choice possible. my ($chosen, $prefered) = find_required_package($urpm, $db, $state, $dep->{required}); @@ -399,7 +399,7 @@ sub _choose_required { #- one to choose; else take the first one available. if (!@$chosen) { $urpm->{debug_URPM}("no packages match " . _dep_to_name($urpm, $dep) . " (it is either in skip.list or already rejected)") if $urpm->{debug_URPM}; - unshift @$properties, backtrack_selected($urpm, $db, $state, $dep, %options); + unshift @$properties, backtrack_selected($urpm, $db, $state, $dep, $diff_provides, %options); return; #- backtrack code choose to continue with same package or completely new strategy. } elsif (@$chosen > 1) { if (@$properties) { @@ -554,10 +554,10 @@ sub with_any_unsatisfied_requires { #- side-effects: $state->{backtrack}, $state->{selected} #- + those of disable_selected_and_unrequested_dependencies ($state->{whatrequires}, flag_requested, flag_required) #- + those of _set_rejected_from ($state->{rejected}) -#- + those of resolve_rejected_ ($state->{rejected}) +#- + those of set_rejected_and_compute_diff_provides ($state->{rejected}, $diff_provides_h) #- + those of _add_rejected_backtrack ($state->{rejected}) sub backtrack_selected { - my ($urpm, $db, $state, $dep, %options) = @_; + my ($urpm, $db, $state, $dep, $diff_provides, %options) = @_; if (defined $dep->{required}) { #- avoid deadlock here... @@ -638,12 +638,13 @@ sub backtrack_selected { #- the backtrack need to examine diff_provides promotion on $n. with_db_unsatisfied_requires($urpm, $db, $state, $dep->{promote}, sub { my ($p, @unsatisfied) = @_; - #- typically a redo of the diff_provides code should be applied... - resolve_rejected_($urpm, $db, $state, \@properties, { + my %diff_provides_h; + set_rejected_and_compute_diff_provides($urpm, $state, \%diff_provides_h, { rejected_pkg => $p, removed => 1, from => $dep->{psel}, why => { unsatisfied => \@unsatisfied } }); + push @$diff_provides, map { +{ name => $_, pkg => $dep->{psel} } } keys %diff_provides_h; }); } } @@ -954,7 +955,7 @@ sub resolve_requested__no_suggests_ { exists $state->{selected}{$dep->{from}->id} or next; } - my $pkg = _choose_required($urpm, $db, $state, $dep, \@properties, \@choices, %options) or next; + my $pkg = _choose_required($urpm, $db, $state, $dep, \@properties, \@choices, \@diff_provides, %options) or next; !$pkg || exists $state->{selected}{$pkg->id} and next; @@ -989,7 +990,7 @@ sub resolve_requested__no_suggests_ { _unselect_package_deprecated_by($urpm, $db, $state, \%diff_provides_h, $pkg); } - _handle_conflicts_with_selected($urpm, $db, $state, $pkg, $dep, \@properties, %options) or next; + _handle_conflicts_with_selected($urpm, $db, $state, $pkg, $dep, \@properties, \@diff_provides, %options) or next; #- all requires should be satisfied according to selected package, or installed packages. if (my @l = unsatisfied_requires($urpm, $db, $state, $pkg)) { @@ -1047,7 +1048,7 @@ sub resolve_requested__no_suggests_ { #- + those of disable_selected (flag_requested, flag_required, $state->{selected}, $state->{rejected}, $state->{whatrequires}) #- + those of backtrack_selected ($state->{backtrack}, $state->{rejected}, $state->{selected}, $state->{whatrequires}, flag_requested, flag_required) sub _handle_conflicts_with_selected { - my ($urpm, $db, $state, $pkg, $dep, $properties, %options) = @_; + my ($urpm, $db, $state, $pkg, $dep, $properties, $diff_provides, %options) = @_; foreach ($pkg->conflicts) { if (my ($n, $o, $v) = property2name_op_version($_)) { foreach my $p ($urpm->packages_providing($n)) { @@ -1057,7 +1058,7 @@ sub _handle_conflicts_with_selected { $urpm->{debug_URPM}($pkg->fullname . " conflicts with already selected package " . $p->fullname) if $urpm->{debug_URPM}; disable_selected($urpm, $db, $state, $pkg); _set_rejected_from($state, $pkg, $p); - unshift @$properties, backtrack_selected($urpm, $db, $state, $dep, %options); + unshift @$properties, backtrack_selected($urpm, $db, $state, $dep, $diff_provides, %options); return; } _set_rejected_from($state, $p, $pkg); |