Imported Upstream version 14.48.2
[platform/upstream/libzypp.git] / zypp / solver / detail / Helper.cc
index 9602e2a..37a20da 100644 (file)
  * 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;
 
@@ -57,14 +57,14 @@ operator<< (ostream & os, const PoolItemList & itemlist)
 }
 
 
-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
     }
 };
@@ -72,133 +72,227 @@ class LookForInstalled : public resfilter::OnCapMatchCallbackFunctor, public res
 
 // 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
     /////////////////////////////////////////////////////////////////////