From f1f6627d5cee583bf3902e2d407d81b2eb0436aa Mon Sep 17 00:00:00 2001 From: Michael Andres Date: Fri, 4 Dec 2009 13:53:22 +0100 Subject: [PATCH] Provide setPickStatus implementation --- zypp/ui/Selectable.cc | 4 +- zypp/ui/Selectable.h | 4 +- zypp/ui/SelectableImpl.cc | 221 ++++++++++++++++++++++++++++++++++++++++------ zypp/ui/SelectableImpl.h | 4 +- 4 files changed, 200 insertions(+), 33 deletions(-) diff --git a/zypp/ui/Selectable.cc b/zypp/ui/Selectable.cc index 94ec2d9..bcb86a9 100644 --- a/zypp/ui/Selectable.cc +++ b/zypp/ui/Selectable.cc @@ -64,7 +64,7 @@ namespace zypp 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 @@ -154,7 +154,7 @@ namespace zypp bool Selectable::multiversionInstall() const { return _pimpl->multiversionInstall(); } - bool Selectable::setPickStatus( const PoolItem & pi_r, const Status state_r, ResStatus::TransactByValue causer_r ) + bool Selectable::setPickStatus( const PoolItem & pi_r, Status state_r, ResStatus::TransactByValue causer_r ) { return _pimpl->setPickStatus( pi_r, state_r, causer_r ); } Status Selectable::pickStatus( const PoolItem & pi_r ) const diff --git a/zypp/ui/Selectable.h b/zypp/ui/Selectable.h index 62ef05f..b439780 100644 --- a/zypp/ui/Selectable.h +++ b/zypp/ui/Selectable.h @@ -309,7 +309,7 @@ namespace zypp bool multiversionInstall() const; /** */ - bool setPickStatus( const PoolItem & pi_r, const Status state_r, ResStatus::TransactByValue causer_r = ResStatus::USER ); + bool setPickStatus( const PoolItem & pi_r, Status state_r, ResStatus::TransactByValue causer_r = ResStatus::USER ); /** Compute the \ref ui::Status for an individual PoolItem. * This just takes into account the item and any identical @@ -448,7 +448,7 @@ namespace zypp * 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 --git a/zypp/ui/SelectableImpl.cc b/zypp/ui/SelectableImpl.cc index 5ecbfe5..29c129b 100644 --- a/zypp/ui/SelectableImpl.cc +++ b/zypp/ui/SelectableImpl.cc @@ -23,6 +23,102 @@ namespace zypp 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 + 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::vector _backup; + }; + /////////////////////////////////////////////////////////////////// // // CLASS NAME : StatusHelper @@ -68,7 +164,7 @@ namespace zypp ResStatus & inststatus( backup( inst.status() ) ); if ( ! inststatus.setTransact( false, causer ) ) return restore(); if ( ! inststatus.setLock ( false, causer ) ) return restore(); - if ( ! cand->installOnly() ) + if ( ! cand->multiversionInstall() ) { // This is what the solver most probabely will do. // If we are wrong the solver will correct it. But @@ -177,29 +273,8 @@ namespace zypp 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::vector _backup; + bool restore() { return backup.restore(); } + StatusBackup backup; }; /////////////////////////////////////////////////////////////////// @@ -242,7 +317,7 @@ namespace zypp 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 ); @@ -324,9 +399,101 @@ namespace zypp } /////////////////////////////////////////////////////////////////// - - bool Selectable::Impl::setPickStatus( const PoolItem & pi_r, const Status state_r, ResStatus::TransactByValue 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 i; + std::vector a; + + for_( it, installedBegin(), installedEnd() ) + if ( identical( *it, pi_r ) ) + i.push_back( *it ); + for_( it, availableBegin(), availableEnd() ) + if ( identical( *it, pi_r ) ) + i.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(); + + 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; } diff --git a/zypp/ui/SelectableImpl.h b/zypp/ui/SelectableImpl.h index 3f437b5..9fc2e75 100644 --- a/zypp/ui/SelectableImpl.h +++ b/zypp/ui/SelectableImpl.h @@ -91,7 +91,7 @@ namespace zypp 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 @@ -285,7 +285,7 @@ namespace zypp bool multiversionInstall() const { return theObj().satSolvable().multiversionInstall(); } - bool setPickStatus( const PoolItem & pi_r, const Status state_r, ResStatus::TransactByValue causer_r ); + bool setPickStatus( const PoolItem & pi_r, Status state_r, ResStatus::TransactByValue causer_r ); Status pickStatus( const PoolItem & pi_r ) const; -- 2.7.4