Imported Upstream version 14.45.0
[platform/upstream/libzypp.git] / zypp / sat / WhatObsoletes.cc
index 077e73d..52679fb 100644 (file)
@@ -12,6 +12,7 @@
 #include <iostream>
 
 #include "zypp/base/LogTools.h"
+#include "zypp/base/Tr1hash.h"
 #include "zypp/sat/WhatObsoletes.h"
 #include "zypp/sat/detail/PoolImpl.h"
 #include "zypp/PoolItem.h"
@@ -25,62 +26,123 @@ namespace zypp
   namespace sat
   { /////////////////////////////////////////////////////////////////
 
+    // Obsoletes may either match against provides, or names.
+    // Configuration depends on the behaviour of rpm.
+#ifdef _RPM_5
+    bool obsoleteUsesProvides = true;
+#else
+    bool obsoleteUsesProvides = false;
+#endif
+
     ///////////////////////////////////////////////////////////////////
     namespace
     { /////////////////////////////////////////////////////////////////
 
-      /** WhatObsoletes ctor helper collecting obsoleted installed items. */
-      shared_ptr<void> allocatedProviders( sat::Solvable item_r, const sat::detail::IdType *& first_r )
+      typedef std::tr1::unordered_set<detail::IdType> set_type;
+      typedef std::vector<sat::detail::IdType>        vector_type;
+
+      /////////////////////////////////////////////////////////////////
+    } // namespace
+    ///////////////////////////////////////////////////////////////////
+
+    WhatObsoletes::WhatObsoletes( Solvable item_r )
+    : _begin( 0 )
+    {
+      ctorAdd( item_r );
+      ctorDone();
+    }
+
+    WhatObsoletes::WhatObsoletes( const PoolItem & item_r )
+    : _begin( 0 )
+    {
+      ctorAdd( item_r );
+      ctorDone();
+    }
+
+    WhatObsoletes::WhatObsoletes( const ResObject::constPtr item_r )
+    : _begin( 0 )
+    {
+      if ( item_r )
       {
-        WhatProvides obsoleted( item_r.obsoletes() );
-        if ( obsoleted.empty() )
+        ctorAdd( item_r->satSolvable() );
+        ctorDone();
+      }
+    }
+
+    void WhatObsoletes::ctorAdd( const PoolItem & item_r )
+    { ctorAdd( item_r->satSolvable() ); }
+
+    void WhatObsoletes::ctorAdd( ResObject_constPtr item_r )
+    { if ( item_r ) ctorAdd( item_r->satSolvable() ); }
+
+
+    namespace
+    {
+      /** Add item to the set created on demand. */
+      inline void addToSet( Solvable item, set_type *& pdata, shared_ptr<void>& _private )
+      {
+        if ( ! pdata )
         {
-          return shared_ptr<void>();
+          _private.reset( (pdata = new set_type) );
         }
+        pdata->insert( item.id() );
+      }
+    }
+
+    void WhatObsoletes::ctorAdd( Solvable item_r )
+    {
+      if ( item_r.multiversionInstall() )
+        return; // multiversion (rpm -i) does not evaluate any obsoletes
 
-        // use allocated private data to store the result (incl. trailing NULL)
-        std::vector<sat::detail::IdType> * pdata = 0;
-        shared_ptr<void> ret;
+      if ( obsoleteUsesProvides )
+      {
+        WhatProvides obsoleted( item_r.obsoletes() );
+        if ( obsoleted.empty() )
+          return;
 
+        // use allocated private data to collect the results
+        set_type * pdata = ( _private ? reinterpret_cast<set_type*>( _private.get() ) : 0 );
         for_( it, obsoleted.begin(), obsoleted.end() )
         {
           if ( it->isSystem() )
-          {
-            if ( ! pdata )
-            {
-              ret.reset( (pdata = new std::vector<sat::detail::IdType>) );
-            }
-            pdata->push_back( it->id() );
-          }
+            addToSet( *it, pdata, _private );
         }
+      }
+      else // Obsoletes match names
+      {
+        Capabilities obsoletes( item_r.obsoletes() );
+        if ( obsoletes.empty() )
+          return;
 
-        if ( pdata )
+        // use allocated private data to collect the results
+        set_type * pdata = ( _private ? reinterpret_cast<set_type*>( _private.get() ) : 0 );
+        for_( it, obsoletes.begin(), obsoletes.end() )
         {
-          pdata->push_back( sat::detail::noId );
-          first_r = &pdata->front();
+          // For each obsoletes find providers, but with the same name
+          IdString ident( it->detail().name() );
+          WhatProvides obsoleted( *it );
+          for_( iit, obsoleted.begin(), obsoleted.end() )
+          {
+            if ( iit->isSystem() && iit->ident() == ident )
+              addToSet( *iit, pdata, _private );
+          }
         }
-        return ret;
       }
+    }
 
-      /////////////////////////////////////////////////////////////////
-    } // namespace
-    ///////////////////////////////////////////////////////////////////
-
-    WhatObsoletes::WhatObsoletes( Solvable item_r )
-    : _begin( 0 )
-    , _private( allocatedProviders( item_r, _begin ) )
-    {}
+    void WhatObsoletes::ctorDone()
+    {
+      if ( _private )
+      {
+        // copy set to vector and terminate _private
+        set_type * sdata = reinterpret_cast<set_type*>( _private.get() );
 
-    WhatObsoletes::WhatObsoletes( const PoolItem & item_r )
-    : _begin( 0 )
-    , _private( allocatedProviders( item_r.satSolvable(), _begin ) )
-    {}
+        vector_type * pdata = new vector_type( sdata->begin(), sdata->end() );
+        pdata->push_back( sat::detail::noId );
+        _begin = &pdata->front();
 
-    WhatObsoletes::WhatObsoletes( const ResObject::constPtr item_r )
-    : _begin( 0 )
-    {
-      if ( item_r )
-        _private = allocatedProviders( item_r->satSolvable(), _begin );
+        _private.reset( pdata );
+      }
     }
 
     WhatObsoletes::size_type WhatObsoletes::size() const