* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA.
*/
+#include <sstream>
#include "zypp/solver/detail/Helper.h"
-
-#include "zypp/CapSet.h"
+#include "zypp/Capabilities.h"
#include "zypp/base/Logger.h"
#include "zypp/base/String.h"
#include "zypp/base/Gettext.h"
-
+#include "zypp/VendorAttr.h"
#include "zypp/base/Algorithm.h"
#include "zypp/ResPool.h"
#include "zypp/ResFilters.h"
-#include "zypp/CapFilters.h"
+#include "zypp/RepoInfo.h"
using namespace std;
}
-class LookForInstalled : public resfilter::OnCapMatchCallbackFunctor, public resfilter::PoolItemFilterFunctor
+class LookFor : public resfilter::PoolItemFilterFunctor
{
public:
- PoolItem_Ref installed;
+ PoolItem item;
- bool operator()( PoolItem_Ref provider )
+ bool operator()( PoolItem provider )
{
- installed = provider;
+ item = provider;
return false; // stop here, we found it
}
};
// just find installed item with same kind/name as item
-PoolItem_Ref
-Helper::findInstalledByNameAndKind (const ResPool & pool, const string & name, const Resolvable::Kind & kind)
+template<class _Iter>
+static PoolItem findInstalledByNameAndKind ( _Iter begin, _Iter end, const string & name, const Resolvable::Kind & kind)
{
- LookForInstalled info;
-#if 0
- invokeOnEach( pool.byNameBegin( name ),
- pool.byNameEnd( name ),
- functor::chain (resfilter::ByInstalled (), // ByInstalled
- resfilter::ByKind( kind ) ), // equal kind
+ LookFor info;
+
+ invokeOnEach(begin, end,
+ resfilter::ByInstalled (), // ByInstalled
functor::functorRef<bool,PoolItem> (info) );
-#endif
- ResPool::const_nameiterator pend = pool.nameend(name);
- for (ResPool::const_nameiterator it = pool.namebegin(name); it != pend; ++it) {
- PoolItem item = it->second;
- if (item.status().isInstalled()
- && item->kind() == kind) {
- if (!info( it->second ))
- break;
- }
- }
- _DEBUG("Helper::findInstalledByNameAndKind (" << name << ", " << kind << ") => " << info.installed);
- return info.installed;
+ _XDEBUG("Helper::findInstalledByNameAndKind (" << name << ", " << kind << ") => " << info.item);
+ return info.item;
+
}
+PoolItem Helper::findInstalledByNameAndKind (const ResPool & pool, const string & name, const Resolvable::Kind & kind)
+{ return detail::findInstalledByNameAndKind( pool.byIdentBegin( kind, name ), pool.byIdentEnd( kind, name ), name, kind ); }
-// just find installed item with same kind/name as item
-// does *NOT* check edition
+PoolItem Helper::findInstalledItem (const ResPool & pool, PoolItem item)
+{ return findInstalledByNameAndKind(pool, item->name(), item->kind() ); }
+
+PoolItem Helper::findInstalledItem( const std::vector<PoolItem> & pool, PoolItem item )
+{ return detail::findInstalledByNameAndKind( pool.begin(), pool.end(), item->name(), item->kind() ); }
-PoolItem_Ref
-Helper::findInstalledItem (const ResPool & pool, PoolItem_Ref item)
+
+// just find uninstalled item with same kind/name as item
+
+PoolItem
+Helper::findUninstalledByNameAndKind (const ResPool & pool, const string & name, const Resolvable::Kind & kind)
{
- return findInstalledByNameAndKind (pool, item->name(), item->kind() );
+ LookFor info;
+
+ invokeOnEach( pool.byIdentBegin( kind, name ),
+ pool.byIdentEnd( kind, name ),
+ resfilter::ByUninstalled(), // ByUninstalled
+ functor::functorRef<bool,PoolItem> (info) );
+
+ _XDEBUG("Helper::findUninstalledByNameAndKind (" << name << ", " << kind << ") => " << info.item);
+ return info.item;
}
+
//----------------------------------------------------------------------------
-class LookForUpdate : public resfilter::OnCapMatchCallbackFunctor, public resfilter::PoolItemFilterFunctor
+class LookForUpdate : public resfilter::PoolItemFilterFunctor
{
public:
- PoolItem_Ref uninstalled;
+ PoolItem uninstalled;
+ PoolItem installed;
- bool operator()( PoolItem_Ref provider )
+ bool operator()( PoolItem provider )
{
- uninstalled = provider;
- return false; // stop here, we found it
+ // is valid
+ if ( ! provider.resolvable() )
+ {
+ WAR << "Warning: '" << provider << "' not valid" << endl;
+ return true;
+ }
+
+ if ( installed.resolvable() )
+ {
+ if ( !VendorAttr::instance().equivalent( installed, provider ) )
+ {
+ MIL << "Discarding '" << provider << "' from vendor '"
+ << provider->vendor() << "' different to uninstalled '"
+ << installed->vendor() << "' vendor." << endl;
+ return true;
+ }
+ }
+
+ if ((!uninstalled // none yet
+ || (uninstalled->edition().compare( provider->edition() ) < 0) // or a better edition
+ || (uninstalled->arch().compare( provider->arch() ) < 0) ) // or a better architecture
+ && !provider.status().isLocked() ) // is not locked
+ {
+ uninstalled = provider; // store
+ }
+ return true;
}
};
-// just find installed item with same kind/name as item
+// just find best (according to edition) uninstalled item with same kind/name as item
// *DOES* check edition
-PoolItem_Ref
-Helper::findUpdateItem (const ResPool & pool, PoolItem_Ref item)
+template<class _Iter>
+static PoolItem findUpdateItem( _Iter begin, _Iter end, PoolItem item )
{
LookForUpdate info;
-#warning FIXME, should not report locked update candidates.
-#if 0
- invokeOnEach( pool.byNameBegin( item->name() ),
- pool.byNameEnd( item->name() ),
- functor::chain (functor::chain (resfilter::ByUninstalled (), // ByUninstalled
- resfilter::ByKind( item->kind() ) ), // equal kind
- resfilter::byEdition<CompareByGT<Edition> >( item->edition() )),
+ info.installed = item;
+
+ invokeOnEach( begin, end,
+ functor::chain (resfilter::ByUninstalled (), // ByUninstalled
+ resfilter::byEdition<CompareByGT<Edition> >( item->edition() )), // only look at better editions
functor::functorRef<bool,PoolItem> (info) );
-#endif
- ResPool::const_nameiterator pend = pool.nameend(item->name());
- for (ResPool::const_nameiterator it = pool.namebegin(item->name()); it != pend; ++it) {
- PoolItem pos = it->second;
- if (pos.status().isUninstalled()
- && pos->kind() == item->kind()
- && item->edition().compare(pos->edition()) < 0)
- {
- if (!info( pos ))
- break;
- }
- }
- _DEBUG("Helper::findUpdateItem(" << item << ") => " << info.uninstalled);
+ _XDEBUG("Helper::findUpdateItem(" << item << ") => " << info.uninstalled);
return info.uninstalled;
}
+PoolItem Helper::findUpdateItem (const ResPool & pool, PoolItem item)
+{ return detail::findUpdateItem( pool.byIdentBegin( item ), pool.byIdentEnd( item ), item ); }
+
+PoolItem Helper::findUpdateItem (const std::vector<PoolItem> & pool, PoolItem item)
+{ return detail::findUpdateItem( pool.begin(), pool.end(), item ); }
+
//----------------------------------------------------------------------------
-class LookForReinstall : public resfilter::OnCapMatchCallbackFunctor, public resfilter::PoolItemFilterFunctor
+class LookForReinstall : public resfilter::PoolItemFilterFunctor
{
public:
- PoolItem_Ref uninstalled;
+ PoolItem uninstalled;
- bool operator()( PoolItem_Ref provider )
+ bool operator()( PoolItem provider )
{
- uninstalled = provider;
- return false; // stop here, we found it
+ if (provider.status().isLocked()) {
+ return true; // search next
+ } else {
+ uninstalled = provider;
+ return false; // stop here, we found it
+ }
}
};
-PoolItem_Ref
-Helper::findReinstallItem (const ResPool & pool, PoolItem_Ref item)
+PoolItem
+Helper::findReinstallItem (const ResPool & pool, PoolItem item)
{
LookForReinstall info;
-#warning FIXME, should not report locked update candidates.
-#if 0
- invokeOnEach( pool.byNameBegin( item->name() ),
- pool.byNameEnd( item->name() ),
- functor::chain (functor::chain (resfilter::ByUninstalled (), // ByUninstalled
- resfilter::ByKind( item->kind() ) ), // equal kind
+
+ invokeOnEach( pool.byIdentBegin( item ),
+ pool.byIdentEnd( item ),
+ functor::chain (resfilter::ByUninstalled (), // ByUninstalled
resfilter::byEdition<CompareByEQ<Edition> >( item->edition() )),
functor::functorRef<bool,PoolItem> (info) );
-#endif
- ResPool::const_nameiterator pend = pool.nameend(item->name());
- for (ResPool::const_nameiterator it = pool.namebegin(item->name()); it != pend; ++it) {
- PoolItem pos = it->second;
- if (pos.status().isUninstalled()
- && pos->kind() == item->kind()
- && item->edition().compare(pos->edition()) == 0)
- {
- if (!info( pos ))
- break;
- }
- }
- _DEBUG("Helper::findReinstallItem(" << item << ") => " << info.uninstalled);
+ _XDEBUG("Helper::findReinstallItem(" << item << ") => " << info.uninstalled);
return info.uninstalled;
}
+//----------------------------------------------------------------------------
+
+class CheckIfBest : public resfilter::PoolItemFilterFunctor
+{
+ public:
+ PoolItem _item;
+ bool is_best;
+
+ CheckIfBest( PoolItem item )
+ : _item( item )
+ , is_best( true ) // assume we already have the best
+ {}
+
+ // check if provider is better. If yes, end the search.
+
+ bool operator()( PoolItem provider )
+ {
+ int archcmp = _item->arch().compare( provider->arch() );
+ if (((archcmp < 0) // provider has a better architecture
+ || ((archcmp == 0)
+ && (_item->edition().compare( provider->edition() ) < 0))) // or a better edition
+ && !provider.status().isLocked()) // and is not locked
+ {
+ is_best = false;
+ return false;
+ }
+ return true;
+ }
+};
+
+
+// check if the given item is the best one of the pool
+
+bool
+Helper::isBestUninstalledItem (const ResPool & pool, PoolItem item)
+{
+ CheckIfBest info( item );
+
+ invokeOnEach( pool.byIdentBegin( item ),
+ pool.byIdentEnd( item ),
+ resfilter::ByUninstalled(), // ByUninstalled
+ functor::functorRef<bool,PoolItem>( info ) );
+
+ _XDEBUG("Helper::isBestUninstalledItem(" << item << ") => " << info.is_best);
+ return info.is_best;
+}
+
+std::string
+Helper::itemToString (PoolItem item, bool shortVersion)
+{
+ ostringstream os;
+ if (!item) return "";
+
+ if (item->kind() != ResKind::package)
+ os << item->kind() << ':';
+ os << item->name();
+ if (!shortVersion) {
+ os << '-' << item->edition();
+ if (item->arch() != "") {
+ os << '.' << item->arch();
+ }
+
+ string alias = item->repoInfo().alias();
+ if (!alias.empty()
+ && alias != "@System")
+ {
+ os << '[' << alias << ']';
+ }
+ }
+ return os.str();
+}
+
+std::string
+Helper::capToString (const Capability & capability)
+{
+ ostringstream os;
+ os << capability.asString();
+ return os.str();
+}
+
+
///////////////////////////////////////////////////////////////////
};// namespace detail
/////////////////////////////////////////////////////////////////////