![](https://seccdn.libravatar.org/avatar/1a5a039cbdb74b7bb361ba2e9d30cb91.jpg?s=120&d=mm&r=g)
Author: mlandres Date: Thu Aug 14 21:58:30 2008 New Revision: 10866 URL: http://svn.opensuse.org/viewcvs/zypp?rev=10866&view=rev Log: Fix Selectable implementation to honour causer. Modified: trunk/libzypp/VERSION.cmake trunk/libzypp/zypp/ResStatus.h trunk/libzypp/zypp/ui/SelectableImpl.cc Modified: trunk/libzypp/VERSION.cmake URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/VERSION.cmake?rev=10866&r1=10865&r2=10866&view=diff ============================================================================== --- trunk/libzypp/VERSION.cmake (original) +++ trunk/libzypp/VERSION.cmake Thu Aug 14 21:58:30 2008 @@ -61,7 +61,7 @@ SET(LIBZYPP_MAJOR "5") SET(LIBZYPP_COMPATMINOR "5") SET(LIBZYPP_MINOR "5") -SET(LIBZYPP_PATCH "1") +SET(LIBZYPP_PATCH "2") # # LAST RELEASED: 5.5.1 (5) # (The number in parenthesis is LIBZYPP_COMPATMINOR) Modified: trunk/libzypp/zypp/ResStatus.h URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/ResStatus.h?rev=10866&r1=10865&r2=10866&view=diff ============================================================================== --- trunk/libzypp/zypp/ResStatus.h (original) +++ trunk/libzypp/zypp/ResStatus.h Thu Aug 14 21:58:30 2008 @@ -22,6 +22,7 @@ namespace resstatus { class UserLockQueryManip; + class StatusBackup; } /////////////////////////////////////////////////////////////////// @@ -669,6 +670,7 @@ { return _bitfield.value<_Field>() < val_r; } private: + friend class resstatus::StatusBackup; BitFieldType _bitfield; }; /////////////////////////////////////////////////////////////////// @@ -684,7 +686,32 @@ inline bool operator!=( const ResStatus & lhs, const ResStatus & rhs ) { return ! (lhs == rhs); } - ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + + namespace resstatus + { + class StatusBackup + { + public: + StatusBackup() + : _status( 0 ) + {} + + StatusBackup( ResStatus & status_r ) + : _status( &status_r ) + , _bitfield( _status->_bitfield ) + {} + + void replay() + { if ( _status ) _status->_bitfield = _bitfield; } + + private: + ResStatus * _status; + ResStatus::BitFieldType _bitfield; + }; + } + + ///////////////////////////////////////////////////////////////// } // namespace zypp /////////////////////////////////////////////////////////////////// #endif // ZYPP_RESSTATUS_H Modified: trunk/libzypp/zypp/ui/SelectableImpl.cc URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/ui/SelectableImpl.cc?rev=10866&r1=10865&r2=10866&view=diff ============================================================================== --- trunk/libzypp/zypp/ui/SelectableImpl.cc (original) +++ trunk/libzypp/zypp/ui/SelectableImpl.cc Thu Aug 14 21:58:30 2008 @@ -35,6 +35,7 @@ : _impl( impl ) , inst( impl.installedObj() ) , cand( impl.candidateObj() ) + , causer( causer_r ) {} typedef Selectable::Impl::available_const_iterator available_const_iterator; @@ -57,103 +58,148 @@ bool hasBoth() const { return inst && cand; } - // - // ResStatus manip - // - void resetTransactingCandidates() const + /** \name Topevel methods must restore status on failure. */ + //@{ + bool setInstall() { - for ( available_const_iterator it = _impl.availableBegin(); - it != _impl.availableEnd(); ++it ) - { - (*it).status().setTransact( false, ResStatus::USER ); + 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() ) + { + // 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 ); + } } + if ( ! unlockCandidates() ) return restore(); + ResStatus & candstatus( backup( cand.status() ) ); + if ( ! candstatus.setTransact( true, causer ) ) return restore(); + return true; + } + return false; } - void unlockCandidates() const + + bool setDelete() { - for ( available_const_iterator it = _impl.availableBegin(); - it != _impl.availableEnd(); ++it ) - { - (*it).status().setTransact( false, ResStatus::USER ); - (*it).status().setLock( false, ResStatus::USER ); - } + 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(); + return true; + } + return false; } - void lockCandidates() const + + bool unset() { - for ( available_const_iterator it = _impl.availableBegin(); - it != _impl.availableEnd(); ++it ) - { - (*it).status().setTransact( false, ResStatus::USER ); - (*it).status().setLock( true, ResStatus::USER ); - } + if ( inst ) + { + ResStatus & inststatus( backup( inst.status() ) ); + if ( ! inststatus.setTransact( false, causer ) ) return restore(); + if ( ! inststatus.setLock( false, causer ) ) return restore(); + } + if ( ! unlockCandidates() ) return restore(); + return true; } - bool setInstall() const + bool setProtected() { - if ( cand ) - { - if ( inst ) { - inst.status().setTransact( false, ResStatus::USER ); - inst.status().setLock ( false, ResStatus::USER ); - if ( ! cand->installOnly() ) - { - // 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. - inst.status().setTransact( true, ResStatus::SOLVER ); - } - } - unlockCandidates(); - return cand.status().setTransact( true, ResStatus::USER ); - } - return false; + if ( causer != ResStatus::USER ) // by user only + return false; + + if ( inst ) { + resetTransactingCandidates(); + inst.status().setTransact( false, causer ); + return inst.status().setLock( true, causer ); + } else + return false; } - bool setDelete() const + bool setTaboo() { - if ( inst ) - { - resetTransactingCandidates(); - inst.status().setLock( false, ResStatus::USER ); - return inst.status().setTransact( true, ResStatus::USER ); - } - return false; + if ( causer != ResStatus::USER ) // by user only + return false; + + if ( cand ) { + lockCandidates(); + return true; + } else + return false; } + //@} - bool unset() const + private: + /** \name Helper methods backup status but do not replay. */ + //@{ + bool resetTransactingCandidates() { - if ( inst ) { - inst.status().setTransact( false, ResStatus::USER ); - inst.status().setLock( false, ResStatus::USER ); - } - unlockCandidates(); - return true; + for_( it, _impl.availableBegin(), _impl.availableEnd() ) + { + ResStatus & status( backup( (*it).status() ) ); + if ( ! status.setTransact( false, causer ) ) return false; + } + return true; } - - bool setProtected() const + bool unlockCandidates() { - if ( inst ) { - resetTransactingCandidates(); - inst.status().setTransact( false, ResStatus::USER ); - return inst.status().setLock( true, ResStatus::USER ); - } else - return false; + for_( it, _impl.availableBegin(), _impl.availableEnd() ) + { + ResStatus & status( backup( (*it).status() ) ); + if ( ! status.setTransact( false, causer ) ) return false; + if ( ! status.setLock( false, causer ) ) return false; + } + return true; } + bool lockCandidates() + { + for_( it, _impl.availableBegin(), _impl.availableEnd() ) + { + ResStatus & status( backup( (*it).status() ) ); + if ( ! status.setTransact( false, causer ) ) return false; + if ( ! status.setLock( true, causer ) ) return false; + } + return true; + } + //@} - bool setTaboo() const + private: + const Selectable::Impl & _impl; + PoolItem inst; + PoolItem cand; + ResStatus::TransactByValue causer; + + private: + // No backup replay needed if causer is user, + // because actions should always succeed. + + ResStatus & backup( ResStatus & status_r ) { - if ( cand ) { - lockCandidates(); - return true; - } else - return false; + 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(); + } - public: - const Selectable::Impl & _impl; - PoolItem inst; - PoolItem cand; + std::vector<resstatus::StatusBackup> _backup; }; /////////////////////////////////////////////////////////////////// -- To unsubscribe, e-mail: zypp-commit+unsubscribe@opensuse.org For additional commands, e-mail: zypp-commit+help@opensuse.org