ref: refs/heads/master
commit f1f6627d5cee583bf3902e2d407d81b2eb0436aa
Author: Michael Andres
Date: Fri Dec 4 13:53:22 2009 +0100
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 <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
@@ -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::vectorresstatus::StatusBackup _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<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 ) )
+ 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;
--
To unsubscribe, e-mail: zypp-commit+unsubscribe@opensuse.org
For additional commands, e-mail: zypp-commit+help@opensuse.org