Hello community, here is the log from the commit of package libzypp for openSUSE:Factory checked in at Mon Dec 7 15:04:48 CET 2009. -------- --- libzypp/libzypp.changes 2009-12-02 16:43:53.000000000 +0100 +++ /mounts/work_src_done/STABLE/libzypp/libzypp.changes 2009-12-04 18:03:39.000000000 +0100 @@ -1,0 +2,18 @@ +Fri Dec 4 17:19:58 CET 2009 - ma@suse.de + +- Improve multiversion status handling and installation. (fate #305311) +- version 6.27.0 (19) + +------------------------------------------------------------------- +Fri Dec 4 14:56:19 CET 2009 - jkupec@suse.cz + +- Don't allow an alias to start with '.' (bnc #473834) + +------------------------------------------------------------------- +Thu Dec 3 12:00:16 CET 2009 - ma@suse.de + +- PickList and status interface for handling packages which are + installable in multiple versions. (fate #305311) +- version 6.26.0 (19) + +------------------------------------------------------------------- calling whatdependson for head-i586 Old: ---- libzypp-6.25.0.tar.bz2 New: ---- libzypp-6.27.0.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libzypp.spec ++++++ --- /var/tmp/diff_new_pack.xekjpi/_old 2009-12-07 15:01:29.000000000 +0100 +++ /var/tmp/diff_new_pack.xekjpi/_new 2009-12-07 15:01:29.000000000 +0100 @@ -1,5 +1,5 @@ # -# spec file for package libzypp (Version 6.25.0) +# spec file for package libzypp (Version 6.27.0) # # Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. # @@ -24,7 +24,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-build AutoReqProv: on Summary: Package, Patch, Pattern, and Product Management -Version: 6.25.0 +Version: 6.27.0 Release: 1 Source: %{name}-%{version}.tar.bz2 Source1: %{name}-rpmlintrc ++++++ libzypp-6.25.0.tar.bz2 -> libzypp-6.27.0.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzypp-6.25.0/package/libzypp.changes new/libzypp-6.27.0/package/libzypp.changes --- old/libzypp-6.25.0/package/libzypp.changes 2009-12-02 14:20:21.000000000 +0100 +++ new/libzypp-6.27.0/package/libzypp.changes 2009-12-04 17:45:22.000000000 +0100 @@ -1,4 +1,22 @@ ------------------------------------------------------------------- +Fri Dec 4 17:19:58 CET 2009 - ma@suse.de + +- Improve multiversion status handling and installation. (fate #305311) +- version 6.27.0 (19) + +------------------------------------------------------------------- +Fri Dec 4 14:56:19 CET 2009 - jkupec@suse.cz + +- Don't allow an alias to start with '.' (bnc #473834) + +------------------------------------------------------------------- +Thu Dec 3 12:00:16 CET 2009 - ma@suse.de + +- PickList and status interface for handling packages which are + installable in multiple versions. (fate #305311) +- version 6.26.0 (19) + +------------------------------------------------------------------- Wed Dec 2 13:10:43 CET 2009 - ma@suse.de - Add Selectable::highestAvailableVersionObj. Returns the highest diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzypp-6.25.0/VERSION.cmake new/libzypp-6.27.0/VERSION.cmake --- old/libzypp-6.25.0/VERSION.cmake 2009-12-02 14:20:21.000000000 +0100 +++ new/libzypp-6.27.0/VERSION.cmake 2009-12-04 17:45:22.000000000 +0100 @@ -60,9 +60,9 @@ # SET(LIBZYPP_MAJOR "6") SET(LIBZYPP_COMPATMINOR "19") -SET(LIBZYPP_MINOR "25") +SET(LIBZYPP_MINOR "27") SET(LIBZYPP_PATCH "0") # -# LAST RELEASED: 6.25.0 (19) +# LAST RELEASED: 6.27.0 (19) # (The number in parenthesis is LIBZYPP_COMPATMINOR) #======= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzypp-6.25.0/zypp/PoolItem.h new/libzypp-6.27.0/zypp/PoolItem.h --- old/libzypp-6.25.0/zypp/PoolItem.h 2009-12-02 14:20:21.000000000 +0100 +++ new/libzypp-6.27.0/zypp/PoolItem.h 2009-12-04 17:45:22.000000000 +0100 @@ -187,7 +187,7 @@ /** \relates PoolItem Test for same content. */ inline bool identical( const PoolItem & lhs, const PoolItem & rhs ) - { return lhs.satSolvable().identical( rhs.satSolvable() ); } + { return lhs == rhs || lhs.satSolvable().identical( rhs.satSolvable() ); } /** \relates PoolItem Test for same content. */ inline bool identical( const PoolItem & lhs, sat::Solvable rhs ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzypp-6.25.0/zypp/repo/RepoException.cc new/libzypp-6.27.0/zypp/repo/RepoException.cc --- old/libzypp-6.25.0/zypp/repo/RepoException.cc 2009-12-02 14:20:21.000000000 +0100 +++ new/libzypp-6.27.0/zypp/repo/RepoException.cc 2009-12-04 17:45:22.000000000 +0100 @@ -64,6 +64,7 @@ DEF_CTORS( RepoNotCachedException, "Repository is not cached" ); DEF_CTORS( RepoNoUrlException, "Repository has no or invalid url defined." ); DEF_CTORS( RepoNoAliasException, "Repository has no alias defined." ); + DEF_CTORS( RepoInvalidAliasException, "Repository has an invalid alias." ); DEF_CTORS( RepoNotFoundException, "Repository not found." ); DEF_CTORS( RepoAlreadyExistsException, "Repository already exists." ); DEF_CTORS( RepoUnknownTypeException, "Repository type can't be determined." ); @@ -111,6 +112,7 @@ CLASS::CLASS( const ServiceInfo & service_r, const std::string & msg_r ) : ServiceException( service_r, msg_r ) {} DEF_CTORS( ServiceNoAliasException, "Service has no alias defined." ); + DEF_CTORS( ServiceInvalidAliasException, "Service has an invalid alias." ); DEF_CTORS( ServiceAlreadyExistsException, "Service already exists." ); DEF_CTORS( ServiceNoUrlException, "Service has no or invalid url defined." ); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzypp-6.25.0/zypp/repo/RepoException.h new/libzypp-6.27.0/zypp/repo/RepoException.h --- old/libzypp-6.25.0/zypp/repo/RepoException.h 2009-12-02 14:20:21.000000000 +0100 +++ new/libzypp-6.27.0/zypp/repo/RepoException.h 2009-12-04 17:45:22.000000000 +0100 @@ -98,6 +98,18 @@ }; /** + * Thrown when the repo alias is found to be invalid. + */ + class RepoInvalidAliasException : public RepoException + { + public: + RepoInvalidAliasException(); + RepoInvalidAliasException( const std::string & msg_r ); + RepoInvalidAliasException( const RepoInfo & info ); + RepoInvalidAliasException( const RepoInfo & info, const std::string & msg_r ); + }; + + /** * thrown when it was impossible to * match a repository */ @@ -194,6 +206,18 @@ ServiceNoAliasException( const ServiceInfo & service_r, const std::string & msg_r ); }; + /** + * Thrown when the repo alias is found to be invalid. + */ + class ServiceInvalidAliasException : public ServiceException + { + public: + ServiceInvalidAliasException(); + ServiceInvalidAliasException( const std::string & msg_r ); + ServiceInvalidAliasException( const ServiceInfo & info ); + ServiceInvalidAliasException( const ServiceInfo & info, const std::string & msg_r ); + }; + /** Service already exists and some unique attribute can't be duplicated. */ class ServiceAlreadyExistsException : public ServiceException diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzypp-6.25.0/zypp/RepoManager.cc new/libzypp-6.27.0/zypp/RepoManager.cc --- old/libzypp-6.25.0/zypp/RepoManager.cc 2009-12-02 14:20:21.000000000 +0100 +++ new/libzypp-6.27.0/zypp/RepoManager.cc 2009-12-04 17:45:22.000000000 +0100 @@ -285,12 +285,22 @@ { if ( info.alias().empty() ) ZYPP_THROW( RepoNoAliasException() ); + // bnc #473834. Maybe we can match the alias against a regex to define + // and check for valid aliases + if ( info.alias()[0] == '.') + ZYPP_THROW(RepoInvalidAliasException( + info, _("Repository alias cannot start with dot."))); } inline void assert_alias( const ServiceInfo & info ) { if ( info.alias().empty() ) ZYPP_THROW( ServiceNoAliasException() ); + // bnc #473834. Maybe we can match the alias against a regex to define + // and check for valid aliases + if ( info.alias()[0] == '.') + ZYPP_THROW(ServiceInvalidAliasException( + info, _("Service alias cannot start with dot."))); } //////////////////////////////////////////////////////////////////////////// diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzypp-6.25.0/zypp/sat/Solvable.cc new/libzypp-6.27.0/zypp/sat/Solvable.cc --- old/libzypp-6.25.0/zypp/sat/Solvable.cc 2009-12-02 14:20:21.000000000 +0100 +++ new/libzypp-6.27.0/zypp/sat/Solvable.cc 2009-12-04 17:45:22.000000000 +0100 @@ -503,7 +503,7 @@ { NO_SOLVABLE_RETURN( ! rhs.get() ); ::_Solvable * rhssolvable( rhs.get() ); - return rhssolvable && ::solvable_identical( _solvable, rhssolvable ); + return rhssolvable && ( _solvable == rhssolvable || ::solvable_identical( _solvable, rhssolvable ) ); } /////////////////////////////////////////////////////////////////// diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzypp-6.25.0/zypp/target/TargetImpl.cc new/libzypp-6.27.0/zypp/target/TargetImpl.cc --- old/libzypp-6.25.0/zypp/target/TargetImpl.cc 2009-12-02 14:20:21.000000000 +0100 +++ new/libzypp-6.27.0/zypp/target/TargetImpl.cc 2009-12-04 17:45:22.000000000 +0100 @@ -1239,7 +1239,7 @@ flags |= rpm::RPMINST_NODEPS; flags |= rpm::RPMINST_FORCE; // - if (p->installOnly()) flags |= rpm::RPMINST_NOUPGRADE; + if (p->multiversionInstall()) flags |= rpm::RPMINST_NOUPGRADE; if (policy_r.dryRun()) flags |= rpm::RPMINST_TEST; if (policy_r.rpmExcludeDocs()) flags |= rpm::RPMINST_EXCLUDEDOCS; if (policy_r.rpmNoSignature()) flags |= rpm::RPMINST_NOSIGNATURE; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzypp-6.25.0/zypp/ui/Selectable.cc new/libzypp-6.27.0/zypp/ui/Selectable.cc --- old/libzypp-6.25.0/zypp/ui/Selectable.cc 2009-12-02 14:20:21.000000000 +0100 +++ new/libzypp-6.27.0/zypp/ui/Selectable.cc 2009-12-04 17:45:22.000000000 +0100 @@ -64,7 +64,7 @@ Status Selectable::status() const { return _pimpl->status(); } - bool Selectable::setStatus( const Status state_r, ResStatus::TransactByValue causer_r ) + bool Selectable::setStatus( Status state_r, ResStatus::TransactByValue causer_r ) { return _pimpl->setStatus( state_r, causer_r ); } PoolItem Selectable::installedObj() const @@ -82,6 +82,9 @@ PoolItem Selectable::highestAvailableVersionObj() const { return _pimpl->highestAvailableVersionObj(); } + bool Selectable::identicalAvailable( const PoolItem & rhs ) const + { return _pimpl->identicalAvailable( rhs ); } + bool Selectable::identicalInstalled( const PoolItem & rhs ) const { return _pimpl->identicalInstalled( rhs ); } @@ -129,6 +132,19 @@ Selectable::installed_iterator Selectable::installedEnd() const { return _pimpl->installedEnd(); } + //////////////////////////////////////////////////////////////////////// + + bool Selectable::picklistEmpty() const + { return _pimpl->picklistEmpty(); } + + Selectable::picklist_size_type Selectable::picklistSize() const + { return _pimpl->picklistSize(); } + + Selectable::picklist_iterator Selectable::picklistBegin() const + { return _pimpl->picklistBegin(); } + + Selectable::picklist_iterator Selectable::picklistEnd() const + { return _pimpl->picklistEnd(); } //////////////////////////////////////////////////////////////////////// @@ -144,6 +160,12 @@ bool Selectable::pickDelete( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r ) { return _pimpl->pickDelete( pi_r, causer_r, yesno_r ); } + Status Selectable::pickStatus( const PoolItem & pi_r ) const + { return _pimpl->pickStatus( pi_r ); } + + bool Selectable::setPickStatus( const PoolItem & pi_r, Status state_r, ResStatus::TransactByValue causer_r ) + { return _pimpl->setPickStatus( pi_r, state_r, causer_r ); } + //////////////////////////////////////////////////////////////////////// bool Selectable::isUndetermined() const diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzypp-6.25.0/zypp/ui/Selectable.h new/libzypp-6.27.0/zypp/ui/Selectable.h --- old/libzypp-6.25.0/zypp/ui/Selectable.h 2009-12-02 14:20:21.000000000 +0100 +++ new/libzypp-6.27.0/zypp/ui/Selectable.h 2009-12-04 17:45:22.000000000 +0100 @@ -64,6 +64,9 @@ typedef SelectableTraits::installed_iterator installed_iterator; typedef SelectableTraits::installed_size_type installed_size_type; + typedef SelectableTraits::picklist_iterator picklist_iterator; + typedef SelectableTraits::picklist_size_type picklist_size_type; + public: /** \name Static ctor substitues picking the item from the pool. * \code @@ -147,8 +150,14 @@ */ PoolItem highestAvailableVersionObj() const; - /** \c True if \a rhs has the same content as an installed one. - * Basically the same name, edition, arch, vendor and buildtime. + /** \c True if \a rhs is installed and one with the same content is available. + * Basically the same name, edition, arch, vendor and buildtime. + * \see \ref sat::Solvable::identical + */ + bool identicalAvailable( const PoolItem & rhs ) const; + + /** \c True if \a rhs has the same content as an installed one. + * Basically the same name, edition, arch, vendor and buildtime. * \see \ref sat::Solvable::identical */ bool identicalInstalled( const PoolItem & rhs ) const; @@ -227,7 +236,7 @@ //////////////////////////////////////////////////////////////////////// - /** \name Insatlled objects iterators. + /** \name Installed objects iterators. * Ordered by install time. Latest first. */ //@{ @@ -239,6 +248,19 @@ //////////////////////////////////////////////////////////////////////// + /** \name picklist iterators. + * This is basically the available items list prepended by those + * installed items, that are nolonger \ref identicalAvailable. + */ + //@{ + bool picklistEmpty() const; + picklist_size_type picklistSize() const; + picklist_iterator picklistBegin() const; + picklist_iterator picklistEnd() const; + //} + + //////////////////////////////////////////////////////////////////////// + public: /** \name Query for objects within this Selectable. */ @@ -303,6 +325,34 @@ */ bool pickNoDelete( const PoolItem & pi_r, ResStatus::TransactByValue causer_r = ResStatus::USER ) { return pickDelete( pi_r, causer_r, false ); } + + /** Compute the \ref ui::Status for an individual PoolItem. + * This just takes into account the item and any identical + * installed (or available) one. + * \code + * Assume there are 3 identical 'foo-1.1 (vendor A)' items, + * one 'foo-2.1 (vendor A)' and one ''foo-1.1 (vendor B)': + * + * installed: . foo-1.1 (vendor A) -> S_KeepInstalled + * available: foo-2.1 (vendor A) (repo 1) -> S_NoInst + * . foo-1.1 (vendor A) (repo 1) -> S_KeepInstalled + * . foo-1.1 (vendor A) (repo 2) -> S_KeepInstalled + * foo-1.1 (vendor B) (repo 3) -> S_NoInst + * + * After 'foo-1.1 (vendor A) (repo 1)' was selected to be installed: + * + * installed: . foo-1.1 (vendor A) -> S_Update + * available: foo-2.1 (vendor A) (repo 1) -> S_NoInst + * I foo-1.1 (vendor A) (repo 1) -> S_Update + * . foo-1.1 (vendor A) (repo 2) -> S_KeepInstalled + * foo-1.1 (vendor B) (repo 3) -> S_NoInst + * \endcode + * \see \ref sat::Solvable::identical + */ + Status pickStatus( const PoolItem & pi_r ) const; + + /** Assign a new status to a specific item. */ + bool setPickStatus( const PoolItem & pi_r, Status state_r, ResStatus::TransactByValue causer_r = ResStatus::USER ); //@} /** \name Classification of available patches (pseudo installed items). @@ -416,7 +466,7 @@ * Try to set a new Status. * Returns \c false if the transitions is not allowed. */ - bool setStatus( const Status state_r, ResStatus::TransactByValue causer_r = ResStatus::USER ); + bool setStatus( Status state_r, ResStatus::TransactByValue causer_r = ResStatus::USER ); /** Return who caused the modification. */ ResStatus::TransactByValue modifiedBy() const; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzypp-6.25.0/zypp/ui/SelectableImpl.cc new/libzypp-6.27.0/zypp/ui/SelectableImpl.cc --- old/libzypp-6.25.0/zypp/ui/SelectableImpl.cc 2009-12-02 14:20:21.000000000 +0100 +++ new/libzypp-6.27.0/zypp/ui/SelectableImpl.cc 2009-12-04 17:45:22.000000000 +0100 @@ -23,11 +23,107 @@ namespace ui { ///////////////////////////////////////////////////////////////// + /** Simple ResStatus backup stack. + * \ref restore simply rewinds all remembered status. + */ + class StatusBackup + { + public: + typedef ResStatus::TransactByValue Causer; + + public: + /** Backup status. */ + ResStatus & backup( ResStatus & status_r ) + { + _backup.push_back( status_r ); + return status_r; + } + /** \overload */ + ResStatus & backup( const PoolItem & pi_r ) + { return backup( pi_r.status() ); } + + /** Backup status. */ + ResStatus & operator()( ResStatus & status_r ) + { return backup( status_r ); } + /** \overload */ + ResStatus & operator()( const PoolItem & pi_r ) + { return backup( pi_r.status() ); } + + /** Restore all status. */ + bool restore() + { + for_( rit, _backup.rbegin(), _backup.rend() ) + rit->replay(); + return false; // restore is done on error - return restore(); + } + + public: + /** lowlevel \c ResStatus::setTransact */ + bool setTransact( const PoolItem & pi_r, bool yesno_r, Causer causer_r ) + { return backup( pi_r ).setTransact( yesno_r, causer_r ); } + + /** lowlevel \c ResStatus::setLock */ + bool setLock( const PoolItem & pi_r, bool yesno_r, Causer causer_r ) + { return backup( pi_r ).setLock( yesno_r, causer_r ); } + + /** lowlevel \c ResStatus::setTransact(true). */ + bool setTransactTrue( const PoolItem & pi_r, Causer causer_r ) + { return setTransact( pi_r, true, causer_r ); } + + /** lowlevel \c ResStatus::setTransact(false). */ + bool setTransactFalse( const PoolItem & pi_r, Causer causer_r ) + { return setTransact( pi_r, false, causer_r ); } + + public: + /** highevel set transact (force unlock). */ + bool transact( const PoolItem & pi_r, Causer causer_r ) + { + ResStatus & status( backup( pi_r ) ); + if ( ! status.setLock( false, causer_r ) ) return false; + if ( ! status.setTransact( true, causer_r ) ) return false; + return true; + } + + /** highlevel set locked. */ + bool lock( const PoolItem & pi_r, Causer causer_r ) + { + ResStatus & status( backup( pi_r ) ); + if ( ! status.setTransact( false, causer_r ) ) return false; + if ( ! status.setLock( true, causer_r ) ) return false; + return true; + } + + /** highlevel unlock (also unsets transact). */ + bool unlock( const PoolItem & pi_r, Causer causer_r ) + { + ResStatus & status( backup( pi_r ) ); + if ( ! status.setTransact( false, causer_r ) ) return false; + if ( ! status.setLock( false, causer_r ) ) return false; + return true; + } + + /** Highlevel action. */ + typedef bool (StatusBackup::*Action)( const PoolItem &, Causer ); + + /** Highlevel action on range of items. */ + template <class _Iter> + bool forEach( _Iter begin_r, _Iter end_r, Action action_r, Causer causer_r ) + { + for_( it, begin_r, end_r ) + if ( ! (this->*action_r)( *it, causer_r ) ) + return false; + return true; + } + + private: + std::vectorresstatus::StatusBackup _backup; + }; + /////////////////////////////////////////////////////////////////// // // CLASS NAME : StatusHelper // - /** + /** \todo Unify status and pickStatus. */ struct StatusHelper { @@ -65,16 +161,19 @@ if ( cand ) { if ( inst ) { - ResStatus & inststatus( backup( inst.status() ) ); - if ( ! inststatus.setTransact( false, causer ) ) return restore(); - if ( ! inststatus.setLock ( false, causer ) ) return restore(); - if ( ! cand->installOnly() ) + for_( it, _impl.installedBegin(), _impl.installedEnd() ) { + ResStatus & inststatus( backup( it->status() ) ); + if ( ! inststatus.setTransact( false, causer ) ) return restore(); + if ( ! inststatus.setLock ( false, causer ) ) return restore(); + if ( ! cand->multiversionInstall() ) + { // This is what the solver most probabely will do. // If we are wrong the solver will correct it. But // this way we will get a better disk usage result, // even if no autosolving is on. - inststatus.setTransact( true, ResStatus::SOLVER ); + inststatus.setTransact( true, ResStatus::SOLVER ); + } } } if ( ! unlockCandidates() ) return restore(); @@ -90,9 +189,12 @@ if ( inst ) { if ( ! resetTransactingCandidates() ) return restore(); - ResStatus & inststatus( backup( inst.status() ) ); - if ( ! inststatus.setLock( false, causer ) ) return restore(); - if ( ! inststatus.setTransact( true, causer ) ) return restore(); + for_( it, _impl.installedBegin(), _impl.installedEnd() ) + { + ResStatus & inststatus( backup( it->status() ) ); + if ( ! inststatus.setLock( false, causer ) ) return restore(); + if ( ! inststatus.setTransact( true, causer ) ) return restore(); + } return true; } return false; @@ -102,9 +204,12 @@ { if ( inst ) { - ResStatus & inststatus( backup( inst.status() ) ); - if ( ! inststatus.setTransact( false, causer ) ) return restore(); - if ( ! inststatus.setLock( false, causer ) ) return restore(); + for_( it, _impl.installedBegin(), _impl.installedEnd() ) + { + ResStatus & inststatus( backup( it->status() ) ); + if ( ! inststatus.setTransact( false, causer ) ) return restore(); + if ( ! inststatus.setLock( false, causer ) ) return restore(); + } } if ( ! unlockCandidates() ) return restore(); return true; @@ -117,8 +222,12 @@ if ( inst ) { resetTransactingCandidates(); - inst.status().setTransact( false, causer ); - return inst.status().setLock( true, causer ); + for_( it, _impl.installedBegin(), _impl.installedEnd() ) + { + it->status().setTransact( false, causer ); + it->status().setLock( true, causer ); + } + return true; } else return false; } @@ -177,29 +286,8 @@ ResStatus::TransactByValue causer; private: - // No backup replay needed if causer is user, - // because actions should always succeed. - - ResStatus & backup( ResStatus & status_r ) - { - if ( causer != ResStatus::USER ) - _backup.push_back( status_r ); - return status_r; - } - - bool restore() - { - if ( causer != ResStatus::USER ) - { - for_( rit, _backup.rbegin(), _backup.rend() ) - { - rit->replay(); - } - } - return false; // restore is done on error - return restore(); - } - - std::vectorresstatus::StatusBackup _backup; + bool restore() { return backup.restore(); } + StatusBackup backup; }; /////////////////////////////////////////////////////////////////// @@ -242,7 +330,7 @@ return S_NoInst; } - bool Selectable::Impl::setStatus( const Status state_r, ResStatus::TransactByValue causer_r ) + bool Selectable::Impl::setStatus( Status state_r, ResStatus::TransactByValue causer_r ) { StatusHelper self( *this, causer_r ); @@ -323,22 +411,190 @@ return _candidate = newCandidate; } + /////////////////////////////////////////////////////////////////// + bool Selectable::Impl::pickInstall( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r ) { - if ( pi_r.satSolvable().ident() != ident() || pi_r.satSolvable().isSystem() ) - return false; // not my PoolItem or an installed one - - return pi_r.status().setTransact( yesno_r, causer_r ); + if ( identicalInstalled( pi_r ) ) + return setPickStatus( pi_r, ( yesno_r ? S_Update : S_KeepInstalled ), causer_r ); + return setPickStatus( pi_r, ( yesno_r ? S_Install : S_NoInst ), causer_r ); } bool Selectable::Impl::pickDelete( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r ) { - if ( pi_r.satSolvable().ident() != ident() || ! pi_r.satSolvable().isSystem() ) - return false; // not my PoolItem or not installed + return setPickStatus( pi_r, ( yesno_r ? S_Del : S_KeepInstalled ), causer_r ); + } + + bool Selectable::Impl::setPickStatus( const PoolItem & pi_r, Status state_r, ResStatus::TransactByValue causer_r ) + { + if ( pi_r.satSolvable().ident() != ident() ) + return false; // not my PoolItem + + if ( ! multiversionInstall() ) + return false; // We're not yet ready for this. + // TODO: Without multiversionInstall take care at most ONE available is set + // to install. Upon install ALL installed get deleted. Only upon deletetion + // one might pick individual versions (but more than one would be an error here). + + StatusBackup backup; + std::vector<PoolItem> i; + std::vector<PoolItem> a; + + for_( it, installedBegin(), installedEnd() ) + if ( identical( *it, pi_r ) ) + i.push_back( *it ); + for_( it, availableBegin(), availableEnd() ) + if ( identical( *it, pi_r ) ) + a.push_back( *it ); + + switch ( state_r ) + { + case S_Protected: + if ( causer_r == ResStatus::USER && ! i.empty() ) + { + if ( ! backup.forEach( i.begin(), i.end(), &StatusBackup::lock, causer_r ) ) return backup.restore(); + if ( ! backup.forEach( a.begin(), a.end(), &StatusBackup::setTransactFalse, causer_r ) ) return backup.restore(); + return true; + } + break; + + case S_Taboo: + if ( causer_r == ResStatus::USER && ! a.empty() ) + { + if ( ! backup.forEach( a.begin(), a.end(), &StatusBackup::lock, causer_r ) ) return backup.restore(); + return true; + } + break; + + case S_AutoDel: + case S_AutoInstall: + case S_AutoUpdate: + // Auto level is SOLVER level. UI may query, but not + // set at this level. + break; + + case S_Del: + if ( ! i.empty() ) + { + if ( ! backup.forEach( i.begin(), i.end(), &StatusBackup::transact, causer_r ) ) return backup.restore(); + if ( ! backup.forEach( a.begin(), a.end(), &StatusBackup::setTransactFalse, causer_r ) ) return backup.restore(); + return true; + } + break; + + case S_Install: + if ( i.empty() && ! a.empty() ) + { + // maybe unlock candidate only? + if ( ! backup.forEach( a.begin(), a.end(), &StatusBackup::unlock, causer_r ) ) return backup.restore(); + const PoolItem & cand( pi_r.status().isInstalled() ? *a.begin() : pi_r ); // status already backed up above + if ( ! cand.status().setTransact( true, causer_r ) ) return backup.restore(); + return true; + } + break; + + case S_Update: + if ( ! i.empty() && ! a.empty() ) + { + if ( ! backup.forEach( i.begin(), i.end(), &StatusBackup::unlock, causer_r ) ) return backup.restore(); + if ( ! backup.forEach( i.begin(), i.end(), &StatusBackup::setTransactTrue, ResStatus::SOLVER ) ) return backup.restore(); + // maybe unlock candidate only? + if ( ! backup.forEach( a.begin(), a.end(), &StatusBackup::unlock, causer_r ) ) return backup.restore(); + const PoolItem & cand( pi_r.status().isInstalled() ? *a.begin() : pi_r ); // status already backed up above + if ( ! cand.status().setTransact( true, causer_r ) ) return backup.restore(); + return true; + } + break; + + case S_KeepInstalled: + if ( ! i.empty() ) + { + if ( ! backup.forEach( i.begin(), i.end(), &StatusBackup::unlock, causer_r ) ) return backup.restore(); + if ( ! backup.forEach( a.begin(), a.end(), &StatusBackup::unlock, causer_r ) ) return backup.restore(); + return true; + } + break; + + case S_NoInst: + if ( i.empty() ) + { + if ( ! backup.forEach( a.begin(), a.end(), &StatusBackup::unlock, causer_r ) ) return backup.restore(); + return true; + } + break; + } + return false; + } + + Status Selectable::Impl::pickStatus( const PoolItem & pi_r ) const + { + if ( pi_r.satSolvable().ident() != ident() ) + return Status(-1); // not my PoolItem + + std::vector<PoolItem> i; + std::vector<PoolItem> a; + PoolItem ti; + PoolItem ta; + + for_( it, installedBegin(), installedEnd() ) + if ( identical( *it, pi_r ) ) + { + i.push_back( *it ); + if ( ! ti && it->status().transacts() ) + ti = *it; + } - return pi_r.status().setTransact( yesno_r, causer_r ); + for_( it, availableBegin(), availableEnd() ) + if ( identical( *it, pi_r ) ) + { + a.push_back( *it ); + if ( ! ta && it->status().transacts() ) + ta = *it; + } + + if ( ta ) + { + if ( ta.status().isByUser() ) + return( i.empty() ? S_Install : S_Update ); + else + return( i.empty() ? S_AutoInstall : S_AutoUpdate ); + } + + if ( ti ) + { + return( ti.status().isByUser() ? S_Del : S_AutoDel ); + } + + for_( it, i.begin(), i.end() ) + if ( it->status().isLocked() ) + return S_Protected; + + if ( i.empty() ) + { + bool allALocked = true; + for_( it, a.begin(), a.end() ) + if ( ! it->status().isLocked() ) + { + allALocked = false; + break; + } + if ( allALocked ) + return S_Taboo; + } + + // KEEP state: + if ( ! i.empty() ) + return S_KeepInstalled; + // Report pseudo installed items as installed, if they are satisfied. + if ( traits::isPseudoInstalled( kind() ) + && ( ta ? ta : *a.begin() ).status().isSatisfied() ) // no installed, so we must have candidate + return S_KeepInstalled; + + return S_NoInst; } + /////////////////////////////////////////////////////////////////// + ResStatus::TransactByValue Selectable::Impl::modifiedBy() const { PoolItem cand( candidateObj() ); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzypp-6.25.0/zypp/ui/SelectableImpl.h new/libzypp-6.27.0/zypp/ui/SelectableImpl.h --- old/libzypp-6.25.0/zypp/ui/SelectableImpl.h 2009-12-02 14:20:21.000000000 +0100 +++ new/libzypp-6.27.0/zypp/ui/SelectableImpl.h 2009-12-04 17:45:22.000000000 +0100 @@ -52,6 +52,8 @@ typedef SelectableTraits::installed_const_iterator installed_const_iterator; typedef SelectableTraits::installed_size_type installed_size_type; + typedef SelectableTraits::PickList PickList; + public: template <class _Iterator> Impl( const ResObject::Kind & kind_r, @@ -89,7 +91,7 @@ Status status() const; /** */ - bool setStatus( const Status state_r, ResStatus::TransactByValue causer_r ); + bool setStatus( Status state_r, ResStatus::TransactByValue causer_r ); /** Installed object (transacting ot highest version). */ PoolItem installedObj() const @@ -168,7 +170,7 @@ return _defaultCandidate; } - /** \copydoc Selectable::highestAvailableVersionObj() */ + /** \copydoc Selectable::highestAvailableVersionObj()const */ PoolItem highestAvailableVersionObj() const { PoolItem ret; @@ -180,9 +182,21 @@ return ret; } - /** \c True if \a rhs has the same content as an installed one. - * \see \ref sat::Solvable::identical - */ + /** \copydoc Selectable::identicalAvailable( const PoolItem & )const */ + bool identicalAvailable( const PoolItem & rhs ) const + { + if ( !availableEmpty() && rhs ) + { + for_( it, _availableItems.begin(), _availableItems.end() ) + { + if ( identical( *it, rhs ) ) + return true; + } + } + return false; + } + + /** \copydoc Selectable::identicalInstalled( const PoolItem & )const */ bool identicalInstalled( const PoolItem & rhs ) const { if ( !installedEmpty() && rhs ) @@ -235,6 +249,36 @@ //////////////////////////////////////////////////////////////////////// + const PickList & picklist() const + { + if ( ! _picklistPtr ) + { + _picklistPtr.reset( new PickList ); + // installed without identical avaialble first: + for_( it, _installedItems.begin(), _installedItems.end() ) + { + if ( ! identicalAvailable( *it ) ) + _picklistPtr->push_back( *it ); + } + _picklistPtr->insert( _picklistPtr->end(), availableBegin(), availableEnd() ); + } + return *_picklistPtr; + } + + bool picklistEmpty() const + { return picklist().empty(); } + + picklist_size_type picklistSize() const + { return picklist().size(); } + + picklist_iterator picklistBegin() const + { return picklist().begin(); } + + picklist_iterator picklistEnd() const + { return picklist().end(); } + + //////////////////////////////////////////////////////////////////////// + bool isUnmaintained() const { return availableEmpty(); } @@ -245,6 +289,10 @@ bool pickDelete( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r ); + Status pickStatus( const PoolItem & pi_r ) const; + + bool setPickStatus( const PoolItem & pi_r, Status state_r, ResStatus::TransactByValue causer_r ); + //////////////////////////////////////////////////////////////////////// bool isUndetermined() const @@ -356,9 +404,10 @@ AvailableItemSet _availableItems; //! Best among availabe with restpect to installed. PoolItem _defaultCandidate; - //! The object selected by setCandidateObj() method. PoolItem _candidate; + //! lazy initialized picklist + mutable scoped_ptr<PickList> _picklistPtr; }; /////////////////////////////////////////////////////////////////// @@ -419,6 +468,31 @@ } str << "} "; } + + if ( obj.picklistEmpty() ) + { + str << "(P 0) {}"; + } + else + { + PoolItem cand( obj.candidateObj() ); + PoolItem up( obj.updateCandidateObj() ); + str << "(P " << obj.picklistSize() << ") {" << endl; + for_( it, obj.picklistBegin(), obj.picklistEnd() ) + { + char t = ' '; + if ( *it == cand ) + { + t = *it == up ? 'C' : 'c'; + } + else if ( *it == up ) + { + t = 'u'; + } + str << " " << t << " " << *it << "\t" << obj.pickStatus( *it ) << endl; + } + str << "} "; + } return str; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzypp-6.25.0/zypp/ui/SelectableTraits.h new/libzypp-6.27.0/zypp/ui/SelectableTraits.h --- old/libzypp-6.25.0/zypp/ui/SelectableTraits.h 2009-12-02 14:20:21.000000000 +0100 +++ new/libzypp-6.27.0/zypp/ui/SelectableTraits.h 2009-12-04 17:45:22.000000000 +0100 @@ -13,6 +13,7 @@ #define ZYPP_UI_SELECTABLETRAITS_H #include <set> +#include <vector> #include "zypp/base/Iterator.h" #include "zypp/PoolItem.h" @@ -114,7 +115,10 @@ typedef AvailableItemSet::const_iterator installed_const_iterator; typedef AvailableItemSet::size_type installed_size_type; - }; + typedef std::vector<PoolItem> PickList; + typedef PickList::const_iterator picklist_iterator; + typedef PickList::size_type picklist_size_type; + }; /////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... -- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org