#include "zypp/base/Easy.h"
#include "zypp/base/LogTools.h"
#include "zypp/base/SerialNumber.h"
-#include "zypp/base/Deprecated.h"
+#include "zypp/APIConfig.h"
#include "zypp/pool/PoolTraits.h"
#include "zypp/ResPoolProxy.h"
+#include "zypp/PoolQueryResult.h"
#include "zypp/sat/Pool.h"
+#include "zypp/Product.h"
using std::endl;
///////////////////////////////////////////////////////////////////
namespace zypp
{ /////////////////////////////////////////////////////////////////
+
+ namespace resstatus
+ {
+ /** Manipulator for \ref ResStatus::UserLockQueryField.
+ * Field is not public available. It is intended to remember the
+ * initial lock status usually derived from /etc/zypp/locks. So
+ * we are able to detect changes we have to write back on commit.
+ */
+ struct UserLockQueryManip
+ {
+ /** Set lock and UserLockQuery bit according to \c yesno_r. */
+ static void setLock( ResStatus & status_r, bool yesno_r )
+ {
+ status_r.setLock( yesno_r, ResStatus::USER );
+ status_r.setUserLockQueryMatch( yesno_r );
+ }
+
+ /** Update lock and UserLockQuery bit IFF the item gained the bit. */
+ static void reapplyLock( ResStatus & status_r, bool yesno_r )
+ {
+ if ( yesno_r && ! status_r.isUserLockQueryMatch() )
+ {
+ status_r.setLock( yesno_r, ResStatus::USER );
+ status_r.setUserLockQueryMatch( yesno_r );
+ }
+ }
+
+ /** Test whether the lock status differs from the remembered UserLockQuery bit. */
+ static int diffLock( const ResStatus & status_r )
+ {
+ bool userLock( status_r.isUserLocked() );
+ if ( userLock == status_r.isUserLockQueryMatch() )
+ return 0;
+ return userLock ? 1 : -1;
+ }
+
+ };
+ }
+
+ namespace
+ {
+ inline PoolQuery makeTrivialQuery( IdString ident_r )
+ {
+ sat::Solvable::SplitIdent ident( ident_r );
+
+ PoolQuery q;
+ q.addAttribute( sat::SolvAttr::name, ident.name().asString() );
+ q.addKind( ident.kind() );
+ q.setMatchExact();
+ q.setCaseSensitive(true);
+ return q;
+ }
+
+ inline bool hardLockQueriesRemove( pool::PoolTraits::HardLockQueries & activeLocks_r, IdString ident_r )
+ {
+ unsigned s( activeLocks_r.size() );
+ activeLocks_r.remove( makeTrivialQuery( ident_r ) );
+ return( activeLocks_r.size() != s );
+ }
+
+ inline bool hardLockQueriesAdd( pool::PoolTraits::HardLockQueries & activeLocks_r, IdString ident_r )
+ {
+ PoolQuery q( makeTrivialQuery( ident_r ) );
+ for_( it, activeLocks_r.begin(), activeLocks_r.end() )
+ {
+ if ( *it == q )
+ return false;
+ }
+ activeLocks_r.push_back( q );
+ return true;
+ }
+ }
+
///////////////////////////////////////////////////////////////////
namespace pool
{ /////////////////////////////////////////////////////////////////
public:
/** \name Save and restore state. */
//@{
- void SaveState( const ResObject::Kind & kind_r );
+ void SaveState( const ResKind & kind_r );
- void RestoreState( const ResObject::Kind & kind_r );
+ void RestoreState( const ResKind & kind_r );
//@}
///////////////////////////////////////////////////////////////////
repository_iterator knownRepositoriesEnd() const
{ checkSerial(); return satpool().reposEnd(); }
+ Repository reposFind( const std::string & alias_r ) const
+ { checkSerial(); return satpool().reposFind( alias_r ); }
+
///////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////
public:
- bool hardLockAppliesTo( sat::Solvable solv_r ) const
- {
- return false;
- }
-
- public:
- typedef PoolTraits::AutoSoftLocks AutoSoftLocks;
- typedef PoolTraits::autoSoftLocks_iterator autoSoftLocks_iterator;
+ typedef PoolTraits::HardLockQueries HardLockQueries;
+ typedef PoolTraits::hardLockQueries_iterator hardLockQueries_iterator;
- const AutoSoftLocks & autoSoftLocks() const
- { return _autoSoftLocks; }
+ const HardLockQueries & hardLockQueries() const
+ { return _hardLockQueries; }
- bool autoSoftLockAppliesTo( sat::Solvable solv_r ) const
- { return( _autoSoftLocks.find( solv_r.ident() ) != _autoSoftLocks.end() ); }
+ void reapplyHardLocks() const
+ {
+ // It is assumed that reapplyHardLocks is called after new
+ // items were added to the pool, but the _hardLockQueries
+ // did not change since. Action is to be performed only on
+ // those items that gained the bit in the UserLockQueryField.
+ MIL << "Re-apply " << _hardLockQueries.size() << " HardLockQueries" << endl;
+ PoolQueryResult locked;
+ for_( it, _hardLockQueries.begin(), _hardLockQueries.end() )
+ {
+ locked += *it;
+ }
+ MIL << "HardLockQueries match " << locked.size() << " Solvables." << endl;
+ for_( it, begin(), end() )
+ {
+ resstatus::UserLockQueryManip::reapplyLock( it->status(), locked.contains( *it ) );
+ }
+ }
- void setAutoSoftLocks( const AutoSoftLocks & newLocks_r )
+ void setHardLockQueries( const HardLockQueries & newLocks_r )
{
- MIL << "Apply " << newLocks_r.size() << " AutoSoftLocks: " << newLocks_r << endl;
- _autoSoftLocks = newLocks_r;
+ MIL << "Apply " << newLocks_r.size() << " HardLockQueries" << endl;
+ _hardLockQueries = newLocks_r;
// now adjust the pool status
+ PoolQueryResult locked;
+ for_( it, _hardLockQueries.begin(), _hardLockQueries.end() )
+ {
+ locked += *it;
+ }
+ MIL << "HardLockQueries match " << locked.size() << " Solvables." << endl;
for_( it, begin(), end() )
{
- if ( ! it->status().isKept() )
- continue;
-
- if ( newLocks_r.find( it->satSolvable().ident() ) != newLocks_r.end() )
- it->status().setSoftLock( ResStatus::USER );
- else
- it->status().resetTransact( ResStatus::USER );
+ resstatus::UserLockQueryManip::setLock( it->status(), locked.contains( *it ) );
}
}
- void getActiveSoftLocks( AutoSoftLocks & activeLocks_r )
+ bool getHardLockQueries( HardLockQueries & activeLocks_r )
{
- activeLocks_r = _autoSoftLocks; // currentsoft-locks
- AutoSoftLocks todel; // + names to be deleted
- AutoSoftLocks toins; // - names to be installed
-
+ activeLocks_r = _hardLockQueries; // current queries
+ // Now diff to the pool collecting names only.
+ // Thus added and removed locks are not necessarily
+ // disjoint. Added locks win.
+ typedef std::unordered_set<IdString> IdentSet;
+ IdentSet addedLocks;
+ IdentSet removedLocks;
for_( it, begin(), end() )
{
- ResStatus & status( it->status() );
- if ( ! status.isByUser() )
- continue;
-
- switch ( status.getTransactValue() )
+ switch ( resstatus::UserLockQueryManip::diffLock( it->status() ) )
{
- case ResStatus::KEEP_STATE:
- activeLocks_r.insert( it->satSolvable().ident() );
- break;
- case ResStatus::LOCKED:
- // NOOP
+ case 0: // unchanged
break;
- case ResStatus::TRANSACT:
- (status.isInstalled() ? todel : toins).insert( it->satSolvable().ident() );
+ case 1:
+ addedLocks.insert( it->satSolvable().ident() );
break;
+ case -1:
+ removedLocks.insert( it->satSolvable().ident() );
+ break;
}
}
- for_( it, todel.begin(), todel.end() )
+ // now the bad part - adjust the queries
+ bool setChanged = false;
+ for_( it, removedLocks.begin(), removedLocks.end() )
{
- activeLocks_r.insert( *it );
+ if ( addedLocks.find( *it ) != addedLocks.end() )
+ continue; // Added locks win
+ if ( hardLockQueriesRemove( activeLocks_r, *it ) && ! setChanged )
+ setChanged = true;
}
- for_( it, toins.begin(), toins.end() )
+ for_( it, addedLocks.begin(), addedLocks.end() )
{
- activeLocks_r.erase( *it );
+ if ( hardLockQueriesAdd( activeLocks_r, *it ) && ! setChanged )
+ setChanged = true;
}
- }
+ return setChanged;
+ }
public:
const ContainerT & store() const
if ( _storeDirty )
{
sat::Pool pool( satpool() );
+ bool addedItems = false;
+ std::list<PoolItem> addedProducts;
- if ( pool.capacity() != _store.capacity() )
- {
- _store.resize( pool.capacity() );
- }
+ _store.resize( pool.capacity() );
if ( pool.capacity() )
{
{
// new PoolItem to add
pi = PoolItem::makePoolItem( s ); // the only way to create a new one!
- // and a few checks...
- if ( hardLockAppliesTo( s ) )
- {
- pi.status().setLock( true, ResStatus::USER );
- }
- else if ( autoSoftLockAppliesTo( s ) )
- {
- pi.status().setSoftLock( ResStatus::USER );
- }
+ // remember products for buddy processing (requires clean store)
+ if ( s.isKind( ResKind::product ) )
+ addedProducts.push_back( pi );
+ if ( !addedItems )
+ addedItems = true;
}
}
}
_storeDirty = false;
+
+ // Now, as the pool is adjusted, ....
+
+ // .... we check for product buddies.
+ if ( ! addedProducts.empty() )
+ {
+ for_( it, addedProducts.begin(), addedProducts.end() )
+ {
+ it->setBuddy( asKind<Product>(*it)->referencePackage() );
+ }
+ }
+
+ // .... we must reapply those query based hard locks.
+ if ( addedItems )
+ {
+ reapplyHardLocks();
+ }
}
return _store;
}
mutable shared_ptr<ResPoolProxy> _poolProxy;
private:
- /** Set of solvable idents that should be soft locked per default. */
- AutoSoftLocks _autoSoftLocks;
+ /** Set of queries that define hardlocks. */
+ HardLockQueries _hardLockQueries;
};
///////////////////////////////////////////////////////////////////