From 12bdae7779a82ecf0d9aceb1f7ec03a4c5f98dc1 Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Tue, 28 Jul 2009 13:12:01 +0000 Subject: keep track of sources for obsoleted/removed levels Patch by Anssi Hannula, fixes bug #50666 removed/obsoleted levels are set in set_rejected() when a package is rejected (i.e. removed) or a rejection reason is added. They keep track on whether the package is removed and/or obsoleted. When the package has both flags and one of the rejection reasons is removed by _remove_rejected_from(), appropriate flags do not get removed. The case I encountered: the package is set for removal when a package it depends on fails upgrade due to unsatisfied dependency and has to be removed (backtrack_selected => resolve_rejected, causing removed=1), and the package is then promoted (causing obsoleted=1). However, the promotion fails due to the same unsatisfied dependency and backtrack_selected => disable_selected_and_unrequested_dependencies => disable_selected => _remove_all_rejected_from => _remove_rejected_from gets called. This removes the latter rejection reason, but leaves flags, including the now wrong obsoleted=1. Thus the package is not explicitely removed as an obsoletion is assumed, therefore failing the transaction. --- URPM.pm | 3 ++- URPM/Resolve.pm | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/URPM.pm b/URPM.pm index dc10a0f..d1d4a13 100644 --- a/URPM.pm +++ b/URPM.pm @@ -834,7 +834,8 @@ B: { id => { } } B: { fullname => { - size => int, removed => bool, obsoleted => bool, + size => int, removed => { fullname|"asked" => undef }, + obsoleted => { fullname|"asked" => undef }, backtrack => { # those info are only used to display why package is unselected promote => [ name ], keep => [ fullname ], unsatisfied => [ id|property ], diff --git a/URPM/Resolve.pm b/URPM/Resolve.pm index d12aa91..801929b 100644 --- a/URPM/Resolve.pm +++ b/URPM/Resolve.pm @@ -682,6 +682,14 @@ sub _remove_rejected_from { my ($state, $fullname, $from_fullname) = @_; my $rv = $state->{rejected}{$fullname} or return; + + foreach (qw(removed obsoleted)) { + if (exists $rv->{$_} && exists $rv->{$_}{$from_fullname}) { + delete $rv->{$_}{$from_fullname}; + delete $rv->{$_} if !%{$rv->{$_}}; + } + } + exists $rv->{closure}{$from_fullname} or return; delete $rv->{closure}{$from_fullname}; if (%{$rv->{closure}}) { @@ -756,8 +764,13 @@ sub set_rejected { #- set removed and obsoleted level. foreach (qw(removed obsoleted)) { - $rdep->{$_} && (! exists $rv->{$_} || $rdep->{$_} <= $rv->{$_}) - and $rv->{$_} = $rdep->{$_}; + if ($rdep->{$_}) { + if ($rdep->{from}) { + $rv->{$_}{scalar $rdep->{from}->fullname} = undef; + } else { + $rv->{$_}{asked} = undef; + } + } } $newly_rejected; -- cgit v1.2.1