/-*/
#include "zypp/solver/detail/InstallOrder.h"
-#include "zypp/base/Logger.h"
+#include "zypp/base/LogTools.h"
#include "zypp/base/Iterator.h"
#include "zypp/base/Algorithm.h"
+#include "zypp/solver/detail/SATResolver.h"
+
#include "zypp/ResFilters.h"
#include "zypp/ResStatus.h"
+#include "zypp/NameKindProxy.h"
+#include "zypp/sat/Pool.h"
+#include <zypp/sat/WhatObsoletes.h>
/////////////////////////////////////////////////////////////////////////
namespace zypp
//-----------------------------------------------------------------------------
-const void
+void
InstallOrder::printAdj (std::ostream& os, bool reversed) const
{
const Graph& g = (reversed ? _rgraph : _graph);
for (Nodes::iterator it = _nodes.begin(); it != _nodes.end(); ++it)
{
if (it->second.order == 0
- && it->second.item) // the default Nodes constructor leaves this empty
+ && it->second.item) // the default Nodes constructor leaves this empty
{
- DBG << "InstallOrder::computeNextSet found " << ITEMNAME(it->second.item) << endl;
+ XXX << "InstallOrder::computeNextSet found " << ITEMNAME(it->second.item) << endl;
newlist.push_back(it->second.item);
}
// decrease order of every adjacent node
void
-InstallOrder::setInstalled(PoolItem_Ref item )
+InstallOrder::setInstalled(PoolItem item )
{
_dirty = true;
PoolItemList adj = _rgraph[item];
- DBG << "InstallOrder::setInstalled " << ITEMNAME(item) << endl;
+ XXX << "InstallOrder::setInstalled " << ITEMNAME(item) << endl;
// order will be < 0
_nodes[item].order--;
info.order--;
if (info.order < 0)
{
- DBG << "order of node " << (*it) << " is < 0" << endl;
+ WAR << "order of node " << (*it) << " is < 0" << endl;
}
}
}
//-----------------------------------------------------------------------------
bool
-InstallOrder::doesProvide( const Capability requirement, PoolItem_Ref item ) const
+InstallOrder::doesProvide( const Capability requirement, PoolItem item ) const
{
- CapSet::const_iterator pend = item->dep( Dep::PROVIDES ).end();
- for( CapSet::const_iterator pit = item->dep( Dep::PROVIDES ).begin(); pit != pend; ++pit) {
+ Capabilities::const_iterator pend = item->dep( Dep::PROVIDES ).end();
+ for( Capabilities::const_iterator pit = item->dep( Dep::PROVIDES ).begin(); pit != pend; ++pit) {
if( pit->matches( requirement ) == CapMatch::yes ) {
return item;
}
}
- return PoolItem_Ref();
+ return PoolItem();
}
-PoolItem_Ref
+PoolItem
InstallOrder::findProviderInSet( const Capability requirement, const PoolItemSet & candidates ) const
{
for( PoolItemSet::const_iterator citer = candidates.begin(); citer != candidates.end(); citer++) {
}
}
- return PoolItem_Ref();
+ return PoolItem();
}
-struct CollectProviders : public resfilter::OnCapMatchCallbackFunctor
-{
- const PoolItem_Ref requestor;
- PoolItemList result;
- const PoolItemSet & limitto; // limit search to members of this set
-
- CollectProviders (const PoolItem_Ref pi, const PoolItemSet & limit)
- : requestor (pi)
- , limitto (limit)
- { }
-
-
- bool operator()( PoolItem_Ref provider, const Capability & match )
- {
- // item provides cap which matches a requirement from info->requestor
- // this function gets _all_ providers and filter out those which are
- // either installed or in our toinstall input list
- //
-XXX << "info(" << provider <<")"<< endl;
- if ((provider.resolvable() != requestor.resolvable()) // resolvable could provide its own requirement
- && (limitto.find( provider ) != limitto.end())) // limit to members of 'limitto' set
- {
- XXX << "tovisit " << ITEMNAME(provider) << endl;
- result.push_back (provider);
- }
-
- return true;
- }
-
-};
-
//-----------------------------------------------------------------------------
void
-InstallOrder::rdfsvisit (const PoolItem_Ref item)
+InstallOrder::rdfsvisit (const PoolItem item)
{
typedef list<Capability> CapList;
CapList requires;
- DBG << "InstallOrder::rdfsvisit, visiting " << ITEMNAME(item) << endl;
+ XXX << "InstallOrder::rdfsvisit, visiting " << ITEMNAME(item) << endl;
NodeInfo& nodeinfo = _nodes[item];
nodeinfo.begintime = _rdfstime;
_rdfstime++;
+ // items prereq
+ CapabilitySet prq( item->dep(Dep::PREREQUIRES).begin(), item->dep(Dep::PREREQUIRES).end() );
+ // any obsoleted items prereq (in case they are reqired for uninstall scripts)
+ sat::WhatObsoletes obs( item );
+ for_( it, obs.begin(), obs.end() )
+ {
+ Capabilities p( it->prerequires() );
+ prq.insert( p.begin(), p.end() );
+ }
// put prerequires first and requires last on list to ensure
// that prerequires are processed first
-
- for (CapSet::const_iterator it = item->dep (Dep::PREREQUIRES).begin(); it != item->dep (Dep::PREREQUIRES).end(); ++it)
+ for (CapabilitySet::const_iterator it = prq.begin(); it != prq.end(); ++it)
{
- const Capability cap = *it;
- requires.push_back(cap);
+ requires.push_back(*it);
}
- for (CapSet::const_iterator it = item->dep (Dep::REQUIRES).begin(); it != item->dep (Dep::REQUIRES).end(); ++it)
- {
- const Capability cap = *it;
- requires.push_back(cap);
- }
+ // Product requirements are ignored to assert Product gets installed
+ // as early as possible. Some stuff depends on it (e.g. registration).
+ if ( ! isKind<Product>( item.resolvable() ) )
+ {
+ for (Capabilities::const_iterator it = item->dep (Dep::REQUIRES).begin(); it != item->dep (Dep::REQUIRES).end(); ++it)
+ {
+ requires.push_back(*it);
+ }
+ }
for (CapList::const_iterator iter = requires.begin(); iter != requires.end(); ++iter)
{
+ bool goBack = false;
const Capability requirement = *iter;
+ PoolItemList providers;
+
XXX << "check requirement " << requirement << " of " << ITEMNAME(item) << endl;
+ SATResolver satResolver(_pool, sat::Pool::instance().get());
PoolItemList tovisit;
+ sat::WhatProvides possibleProviders(requirement);
-#if 0
- // _world->foreachProvidingResItem (requirement, collect_providers, &info);
- Dep dep (Dep::PROVIDES);
- invokeOnEach( _pool.byCapabilityIndexBegin( requirement.index(), dep ),
- _pool.byCapabilityIndexEnd( requirement.index(), dep ),
- resfilter::callOnCapMatchIn( dep, requirement, functor::functorRef<bool,PoolItem,Capability>(info) ) );
-#endif
-#if 1
// first, look in _installed
-
- CollectProviders info ( item, _installed );
-
- ResPool::const_indexiterator pend = _pool.providesend( requirement.index() );
- for (ResPool::const_indexiterator it = _pool.providesbegin( requirement.index() ); it != pend; ++it) {
- if (it->second.second->arch() == Arch_src)
- continue;
- if (it->second.first.matches (requirement) == CapMatch::yes) {
- if (!info( it->second.second, it->second.first))
- break;
- }
- }
-
- // if not found in _iustalled, look in _toinstall
-
- if (info.result.empty()) {
- CollectProviders info1 ( item, _toinstall );
-
- ResPool::const_indexiterator pend = _pool.providesend( requirement.index() );
- for (ResPool::const_indexiterator it = _pool.providesbegin( requirement.index() ); it != pend; ++it) {
- if (it->second.second->arch() == Arch_src)
- continue;
- if (it->second.first.matches (requirement) == CapMatch::yes) {
- if (!info1( it->second.second, it->second.first))
- break;
- }
- }
- tovisit = info1.result;
- }
-#endif
-#if 0
- // item could provide its own requirement
- if( doesProvide( requirement, item ) ) {
- XXX << "self-provides " << endl;
-// tovisit.push_back(node);
+ for_( iter, possibleProviders.begin(), possibleProviders.end() ) {
+ PoolItem provider = ResPool::instance().find( *iter );
+ if ( provider == item )
+ {
+ goBack = true;
+ break;
+ }
+ if (_installed.find( provider ) != _installed.end()) // and is not installed
+ {
+ XXX << "tovisit " << ITEMNAME(provider) << endl;
+ providers.push_back (provider);
+ }
+ }
+
+ if ( goBack )
+ continue;
+
+ // if not found in _installed, look in _toinstall
+
+ if (providers.empty()) {
+ for_( iter, possibleProviders.begin(), possibleProviders.end() ) {
+ PoolItem provider = ResPool::instance().find( *iter );
+ if ((provider.resolvable() != item.resolvable()) // resolvable could provide its own requirement
+ && (_toinstall.find( provider ) != _toinstall.end())) // and is not to be installed
+ {
+ XXX << "tovisit " << ITEMNAME(provider) << endl;
+ tovisit.push_back (provider);
+ }
+ }
}
- else {
- PoolItem_Ref provider = findProviderInSet( requirement, _installed );
- if (!provider)
- {
- provider = findProviderInSet( requirement, _toinstall );
- if (provider) {
- XXX << "provided by " << ITEMNAME(provider) << endl;
- tovisit.push_back( provider );
- }
- }
- }
-#endif
for (PoolItemList::iterator it = tovisit.begin(); it != tovisit.end(); ++it)
{
- const PoolItem_Ref must_visit = *it;
+ const PoolItem must_visit = *it;
if (_nodes[must_visit].visited == false)
{
nodeinfo.order++;
{
if (must_visit != item)
{
- ERR << "*************************************************************" << endl;
- ERR << "** dependency loop: " << ITEMNAME(item) << " -> " << ITEMNAME(must_visit) << endl;
- ERR << "*************************************************************" << endl;
+ // log only the 1st occurrence.
+ std::string lstr( ITEMNAME(item) );
+ lstr += " -> ";
+ lstr += ITEMNAME(must_visit);
+ if ( _logset.insert( lstr ).second )
+ {
+ WAR << "** dependency loop: " << lstr << endl;
+ }
}
}
else
_nodes[item].endtime = _rdfstime;
_rdfstime++;
- DBG << ITEMNAME(item) << " done" << endl;
+ XXX << ITEMNAME(item) << " done" << endl;
}
_topsorted.clear();
_numrun++;
- DBG << "run #" << _numrun << endl;
+ XXX << "run #" << _numrun << endl;
// initialize all nodes
for (PoolItemSet::iterator it = _toinstall.begin(); it != _toinstall.end(); ++it)
{
- PoolItem_Ref item = *it;
+ PoolItem item = *it;
_nodes[item] = NodeInfo (item);
_rgraph[item] = PoolItemList();
_graph[item] = PoolItemList();
// visit all nodes
for (PoolItemSet::iterator it = _toinstall.begin(); it != _toinstall.end(); ++it)
{
- const PoolItem_Ref item = *it;
+ const PoolItem item = *it;
if (_nodes[item].visited == false)
{
- DBG << "start recursion on " << ITEMNAME(item) << endl;
+ XXX << "start recursion on " << ITEMNAME(item) << endl;
rdfsvisit (item);
}
}