From b411fe74f8464acd468e120a04f1cf7ac90e37a0 Mon Sep 17 00:00:00 2001 From: Jan Kupec Date: Sun, 5 Oct 2008 10:35:12 +0000 Subject: [PATCH] - fixed problems related to incorrect selection of, or check for update candidate (bnc #422141) --- src/install.cc | 88 ++++++++++++++------------------------------------------ src/update.cc | 91 ++++++++++++++++++++++++++++++++-------------------------- src/update.h | 11 +++++++ 3 files changed, 83 insertions(+), 107 deletions(-) diff --git a/src/install.cc b/src/install.cc index 5a6a79d..5f23950 100755 --- a/src/install.cc +++ b/src/install.cc @@ -8,13 +8,17 @@ #include "utils/misc.h" #include "install.h" - +#include "update.h" +#include using namespace std; using namespace zypp; using namespace boost; extern ZYpp::Ptr God; +/** Use ui::Selectable::theObj() or candidateObj() */ +#define USE_THE_ONE 0 + // TODO edition, arch ? static void mark_for_install(Zypper & zypper, const ResObject::Kind &kind, @@ -47,32 +51,36 @@ static void mark_for_install(Zypper & zypper, ui::Selectable::Ptr s = *q.selectableBegin(); +#if USE_THE_ONE + PoolItem candidate = s->candidateObj(); +#else + PoolItem candidate = findUpdateItem(God->pool(), s->installedObj()); + if (!candidate) + candidate = s->installedObj(); +#endif + if (s->installedObj() && - s->installedObj().resolvable()->edition() == s->candidateObj().resolvable()->edition() && - s->installedObj().resolvable()->arch() == s->candidateObj().resolvable()->arch() && + s->installedObj().resolvable()->edition() == candidate.resolvable()->edition() && + s->installedObj().resolvable()->arch() == candidate.resolvable()->arch() && ( ! copts.count("force") ) ) { // if it is broken install anyway, even if it is installed - if ( s->candidateObj().isBroken() ) - { - s->candidateObj().status().setTransact( true, zypp::ResStatus::USER ); - } + if (candidate.isBroken()) + candidate.status().setTransact(true, zypp::ResStatus::USER); else - { zypper.out().info(boost::str(format( // translators: e.g. skipping package 'zypper' (the newest version already installed) _("skipping %s '%s' (the newest version already installed)")) % kind_to_string_localized(kind,1) % name)); - } } - else { - + else + { //! \todo don't use setToBeInstalled for this purpose but higher level solver API - bool result = s->candidateObj().status().setToBeInstalled( zypp::ResStatus::USER ); - if (!result) + if (!candidate.status().setToBeInstalled(zypp::ResStatus::USER)) { + cout << "no" << endl; // this is because the resolvable is installed and we are forcing. - s->candidateObj().status().setTransact( true, zypp::ResStatus::USER ); + candidate.status().setTransact(true, zypp::ResStatus::USER); if (!copts.count("force")) { zypper.out().error(boost::str( @@ -235,58 +243,6 @@ install_remove_preprocess_args(const Zypper::ArgList & args, DBG << endl; } -#define USE_THE_ONE 0 - -#if not USE_THE_ONE - -// ---------------------------------------------------------------------------- - -class LookForUpdate : public zypp::resfilter::PoolItemFilterFunctor -{ -public: - PoolItem best; - - bool operator()( PoolItem provider ) - { - if (!provider.status().isLocked() // is not locked (taboo) - && (!best // first match - // or a better edition than so-far-found - || best->edition().compare( provider->edition() ) < 0)) - { - best = provider; - } - return true; - } -}; - -// ---------------------------------------------------------------------------- - -// Find best (according to edition) uninstalled item -// with same kind/name/arch as item. -// Similar to zypp::solver::detail::Helper::findUpdateItem -// but allows changing the vendor -static -PoolItem -findUpdateItem( const ResPool & pool, PoolItem item ) -{ - LookForUpdate info; - - invokeOnEach( pool.byIdentBegin(item->kind(), item->name()), - pool.byIdentEnd(item->kind(), item->name()), - // get uninstalled, equal kind and arch, better edition - functor::chain ( - functor::chain ( - resfilter::ByUninstalled (), - resfilter::byArch >( item->arch() ) ), - resfilter::byEdition >( item->edition() )), - functor::functorRef(info)); - - XXX << "findArchUpdateItem(" << item << ") => " << info.best; - return info.best; -} - -#endif - // ---------------------------------------------------------------------------- static void diff --git a/src/update.cc b/src/update.cc index ff69dcf..14f98f2 100755 --- a/src/update.cc +++ b/src/update.cc @@ -202,51 +202,47 @@ static void list_patch_updates(Zypper & zypper) // ---------------------------------------------------------------------------- -// collect items, select best edition -// this is used to find best available or installed. -// The name of the class is a bit misleading though ... - -class LookForArchUpdate : public zypp::resfilter::PoolItemFilterFunctor +/* + * Collect items, select the best edition. + * This is used to find the best available or installed pool item from a set. + */ +class SaveBetterEdition : public zypp::resfilter::PoolItemFilterFunctor { public: PoolItem best; - bool operator()( PoolItem provider ) + bool operator()(PoolItem provider) + { + if (!provider.status().isLocked() // is not locked (taboo) + && (!best // first match + // or a better edition than so-far-found + || best->edition().compare(provider->edition()) < 0)) { - if (!provider.status().isLocked() // is not locked (taboo) - && (!best // first match - // or a better edition than candidate - || best->edition().compare( provider->edition() ) < 0)) - { - best = provider; // store - } - return true; // keep going + best = provider; } + return true; + } }; // ---------------------------------------------------------------------------- -// Find best (according to edition) uninstalled item -// with same kind/name/arch as item. -// Similar to zypp::solver::detail::Helper::findUpdateItem -// but that allows changing the arch (#222140). -static +// does not allow changing the arch (#222140). PoolItem -findArchUpdateItem( const ResPool & pool, PoolItem item ) +findUpdateItem( const ResPool & pool, PoolItem item ) { - LookForArchUpdate info; + SaveBetterEdition info; - invokeOnEach( pool.byIdentBegin( item->kind(), item->name() ), - pool.byIdentEnd( item->kind(), item->name() ), + invokeOnEach( pool.byIdentBegin(item->kind(), item->name()), + pool.byIdentEnd(item->kind(), item->name()), // get uninstalled, equal kind and arch, better edition - functor::chain ( - functor::chain ( - resfilter::ByUninstalled (), - resfilter::byArch >( item->arch() ) ), - resfilter::byEdition >( item->edition() )), - functor::functorRef (info) ); - - _XDEBUG("findArchUpdateItem(" << item << ") => " << info.best); + functor::chain( + functor::chain( + resfilter::ByUninstalled(), + resfilter::byArch >(item->arch())), + resfilter::byEdition >(item->edition())), + functor::functorRef(info)); + + XXX << "findUpdateItem(" << item << ") => " << info.best; return info.best; } @@ -283,8 +279,8 @@ find_updates( const ResKind & kind, Candidates & candidates ) { if (it->status().isUninstalled()) continue; - // (actually similar to ProvideProcess?) - PoolItem candidate = findArchUpdateItem( pool, *it ); + + PoolItem candidate = findUpdateItem( pool, *it ); if (!candidate.resolvable()) continue; @@ -451,23 +447,24 @@ mark_item_install (const PoolItem & pi) // best-effort update // ---------------------------------------------------------------------------- -// find installed item matching passed one -// use LookForArchUpdate as callback handler in order to cope with -// multiple installed resolvables of the same name. -// LookForArchUpdate will return the one with the highest edition. - +/* + * Find installed item matching passed one. + * Use SaveBetterEdition as callback handler in order to cope with + * multiple installed resolvables of the same name. + * SaveBetterEdition will return the one with the highest edition. + */ static PoolItem findInstalledItem( PoolItem item ) { const zypp::ResPool& pool = God->pool(); - LookForArchUpdate info; + SaveBetterEdition info; invokeOnEach( pool.byIdentBegin( item->kind(), item->name() ), pool.byIdentEnd( item->kind(), item->name() ), resfilter::ByInstalled (), functor::functorRef (info) ); - _XDEBUG("findInstalledItem(" << item << ") => " << info.best); + XXX << "findInstalledItem(" << item << ") => " << info.best; return info.best; } @@ -684,7 +681,19 @@ void mark_updates(Zypper & zypper, const ResKindSet & kinds, bool skip_interacti for_(solvit, q.selectableBegin(), q.selectableEnd()) { ui::Selectable::Ptr s = *solvit; - PoolItem theone = s->theObj(); +#if USE_THE_ONE + PoolItem theone = s.theObj(); +#else + PoolItem theone; + + if (s->installedEmpty()) + theone = *s->availableBegin(); + else + theone = findUpdateItem(God->pool(), *s->installedBegin()); + if (!theone) + theone = *s->installedBegin(); +#endif + if (equalNVRA(*s->installedObj().resolvable(), *theone.resolvable())) { DBG << "the One (" << theone << ") is installed, skipping." << endl; diff --git a/src/update.h b/src/update.h index 3d2fb22..0537e76 100755 --- a/src/update.h +++ b/src/update.h @@ -1,3 +1,5 @@ +#include "zypp/PoolItem.h" + #include "Zypper.h" #include "utils/misc.h" @@ -34,3 +36,12 @@ void mark_updates(Zypper & zypper, const ResKindSet & kinds, bool skip_interactive, bool best_effort); + +/** + * Find best (according to edition) uninstalled item + * with same kind/name/arch as \a item. + * + * Similar to zypp::solver::detail::Helper::findUpdateItem() + * but allows changing the vendor and does not allow chaning arch. + */ +zypp::PoolItem findUpdateItem(const zypp::ResPool & pool, zypp::PoolItem item); -- 2.7.4