aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristophe Fergeau <cfergeau@mandriva.com>2009-08-10 14:37:04 +0000
committerChristophe Fergeau <cfergeau@mandriva.com>2009-08-10 14:37:04 +0000
commit307fdff9e12f783b01d0275d92c22b4cf7dd020f (patch)
treede8a85ccaf674b8ab7845bd76f80727c9a84e405
parent2aa62ffc953968bbc0911ad1fdb7eb54f86fc06b (diff)
downloadperl-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--NEWS2
-rw-r--r--URPM/Resolve.pm21
2 files changed, 13 insertions, 10 deletions
diff --git a/NEWS b/NEWS
index 50a827b..2bafaa6 100644
--- a/NEWS
+++ b/NEWS
@@ -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);