Use libsolv includes and adjust documentation
[platform/upstream/libzypp.git] / zypp / sat / Solvable.cc
index 4b341b8..a578d57 100644 (file)
 
 #include "zypp/sat/detail/PoolImpl.h"
 #include "zypp/sat/Solvable.h"
+#include "zypp/sat/Pool.h"
+#include "zypp/sat/LookupAttr.h"
+
 #include "zypp/Repository.h"
 #include "zypp/OnMediaLocation.h"
+#include "zypp/ZConfig.h"
 
 using std::endl;
 
@@ -31,6 +35,87 @@ namespace zypp
   namespace sat
   { /////////////////////////////////////////////////////////////////
 
+    namespace
+    {
+      void _doSplit( IdString & _ident, ResKind & _kind, IdString & _name )
+      {
+        if ( ! _ident )
+          return;
+
+       ResKind explicitKind = Solvable::SplitIdent::explicitKind( _ident.c_str() );
+       // NOTE: kind package and srcpackage do not have namespaced ident!
+       if ( ! explicitKind  )
+       {
+          _name = _ident;
+         // No kind defaults to package
+         if ( !_kind )
+           _kind = ResKind::package;
+         if ( ! ( _kind == ResKind::package || _kind == ResKind::srcpackage ) )
+           _ident = IdString( str::form( "%s:%s", _kind.c_str(), _ident.c_str() ) );
+       }
+       else
+       {
+         // strip kind spec from name
+         _name = IdString( ::strchr( _ident.c_str(), ':' )+1 );
+         _kind = explicitKind;
+         if ( _kind == ResKind::package || _kind == ResKind::srcpackage )
+           _ident = _name;
+       }
+       return;
+      }
+    }
+
+    Solvable::SplitIdent::SplitIdent( IdString ident_r )
+    : _ident( ident_r )
+    { _doSplit( _ident, _kind, _name ); }
+
+    Solvable::SplitIdent::SplitIdent( const char * ident_r )
+    : _ident( ident_r )
+    { _doSplit( _ident, _kind, _name ); }
+
+    Solvable::SplitIdent::SplitIdent( const std::string & ident_r )
+    : _ident( ident_r )
+    { _doSplit( _ident, _kind, _name ); }
+
+    Solvable::SplitIdent::SplitIdent( ResKind kind_r, IdString name_r )
+    : _ident( name_r )
+    , _kind( kind_r )
+    { _doSplit( _ident, _kind, _name ); }
+
+    Solvable::SplitIdent::SplitIdent( ResKind kind_r, const C_Str & name_r )
+    : _ident( name_r )
+    , _kind( kind_r )
+    { _doSplit( _ident, _kind, _name ); }
+
+    ResKind Solvable::SplitIdent::explicitKind( const char * ident_r )
+    {
+      if ( ! ident_r )
+       return ResKind();
+
+      const char * sep = ::strchr( ident_r, ':' );
+      if ( ! sep )
+       return ResKind();
+
+      ResKind ret;
+      if ( sep-ident_r >= 4 )
+      {
+       switch ( ident_r[3] )
+       {
+         #define OUTS(K,S) if ( !::strncmp( ident_r, ResKind::K.c_str(), S ) && ident_r[S] == ':' ) ret = ResKind::K
+         //             ----v
+         case 'c': OUTS( patch, 5 );       break;
+         case 'd': OUTS( product, 7 );     break;
+         case 'k': OUTS( package, 7 );     break;
+         case 'p': OUTS( srcpackage, 10 ); break;
+         case 't': OUTS( pattern, 7 );     break;
+         #undef OUTS
+       }
+      }
+      return ret;
+    }
+
+    /////////////////////////////////////////////////////////////////
+
     const Solvable Solvable::noSolvable;
 
     /////////////////////////////////////////////////////////////////
@@ -68,7 +153,12 @@ namespace zypp
     bool Solvable::isSystem() const
     {
       NO_SOLVABLE_RETURN( _id == detail::systemSolvableId );
-      return Repository( _solvable->repo ).isSystemRepo();
+      return myPool().isSystemRepo( _solvable->repo );
+    }
+
+    bool Solvable::onSystemByUser() const
+    {
+      return isSystem() && myPool().isOnSystemByUser( ident() );
     }
 
     IdString Solvable::ident() const
@@ -94,7 +184,11 @@ namespace zypp
       }
       else
       {
-        s = ::solvable_lookup_str_lang( _solvable, attr.id(), lang_r.code().c_str() );
+       for ( Locale l( lang_r ); l != Locale::noCode; l = l.fallback() )
+         if ( (s = ::solvable_lookup_str_lang( _solvable, attr.id(), l.code().c_str(), 0 )) )
+           return s;
+         // here: no matching locale, so use default
+         s = ::solvable_lookup_str_lang( _solvable, attr.id(), 0, 0 );
       }
       return s ? s : std::string();
    }
@@ -133,8 +227,30 @@ namespace zypp
       return CheckSum( std::string(), s ); // try to autodetect
     }
 
+    ///////////////////////////////////////////////////////////////////
+    namespace
+    {
+      inline Pathname lookupDatadirIn( Repository repor_r )
+      {
+        static const sat::SolvAttr susetagsDatadir( "susetags:datadir" );
+        Pathname ret;
+        // First look for repo attribute "susetags:datadir". If not found,
+        // look into the solvables as Code11 libsolv placed it there.
+        sat::LookupRepoAttr datadir( susetagsDatadir, repor_r );
+        if ( ! datadir.empty() )
+          ret = datadir.begin().asString();
+        else
+        {
+          sat::LookupAttr datadir( susetagsDatadir, repor_r );
+          if ( ! datadir.empty() )
+            ret = datadir.begin().asString();
+        }
+        return ret;
+      }
+    }
+    ///////////////////////////////////////////////////////////////////
+
     OnMediaLocation Solvable::lookupLocation() const
-    //std::string Solvable::lookupLocation( unsigned & medianr ) const
     {
       NO_SOLVABLE_RETURN( OnMediaLocation() );
       // medianumber and path
@@ -146,12 +262,26 @@ namespace zypp
       OnMediaLocation ret;
 
       Pathname path;
-      if ( repository().info().type().toEnum() == repo::RepoType::YAST2_e )
+      switch ( repository().info().type().toEnum() )
       {
-#warning STILL HARDCODED /suse PREFIX in location
-        // (ma@) loading a susetags repo search for a solvable with attribute
-        // susetags:datadir. this is the prefix. store it in RepoInfo(?).
-        path = "suse";
+        case repo::RepoType::NONE_e:
+        {
+          path = lookupDatadirIn( repository() );
+          if ( ! path.empty() )
+            repository().info().setProbedType( repo::RepoType::YAST2_e );
+        }
+        break;
+
+        case repo::RepoType::YAST2_e:
+        {
+          path = lookupDatadirIn( repository() );
+          if ( path.empty() )
+            path = "suse";
+        }
+        break;
+
+        default:
+          break;
       }
       ret.setLocation    ( path/file, medianr );
       ret.setDownloadSize( ByteCount( lookupNumAttribute( SolvAttr::downloadsize ), ByteCount::K ) );
@@ -190,11 +320,8 @@ namespace zypp
           //             ----v
           case 'c': OUTS( patch, 5 );       break;
           case 'd': OUTS( product, 7 );     break;
-          case 'i': OUTS( script, 6 );      break;
           case 'k': OUTS( package, 7 );     break;
-          case 'm': OUTS( atom, 4 );        break;
           case 'p': OUTS( srcpackage, 10 ); break;
-          case 's': OUTS( message, 7 );     break;
           case 't': OUTS( pattern, 7 );     break;
 #undef OUTS
         }
@@ -209,9 +336,12 @@ namespace zypp
       NO_SOLVABLE_RETURN( false );
 
       // detect srcpackages by 'arch'
-      if ( kind_r == ResKind::srcpackage )
+      switch ( _solvable->arch )
       {
-        return( _solvable->arch == ARCH_SRC || _solvable->arch == ARCH_NOSRC );
+        case ARCH_SRC:
+        case ARCH_NOSRC:
+          return( kind_r == ResKind::srcpackage );
+          break;
       }
 
       // no ':' in package names (hopefully)
@@ -256,6 +386,11 @@ namespace zypp
       //return ArchId( _solvable->arch );
     }
 
+    bool Solvable::multiversionInstall() const
+    {
+      return myPool().isMultiversion( ident() );
+    }
+
     IdString Solvable::vendor() const
     {
       NO_SOLVABLE_RETURN( IdString() );
@@ -272,7 +407,6 @@ namespace zypp
         case Dep::OBSOLETES_e:   return obsoletes();   break;
         case Dep::RECOMMENDS_e:  return recommends();  break;
         case Dep::SUGGESTS_e:    return suggests();    break;
-        case Dep::FRESHENS_e:    return freshens();    break;
         case Dep::ENHANCES_e:    return enhances();    break;
         case Dep::SUPPLEMENTS_e: return supplements(); break;
         case Dep::PREREQUIRES_e: return prerequires(); break;
@@ -314,11 +448,6 @@ namespace zypp
       NO_SOLVABLE_RETURN( Capabilities() );
       return _getCapabilities( _solvable->repo->idarraydata, _solvable->suggests );
     }
-    Capabilities Solvable::freshens() const
-    {
-      NO_SOLVABLE_RETURN( Capabilities() );
-      return _getCapabilities( _solvable->repo->idarraydata, _solvable->freshens );
-    }
     Capabilities Solvable::enhances() const
     {
       NO_SOLVABLE_RETURN( Capabilities() );
@@ -338,6 +467,55 @@ namespace zypp
                    : Capabilities();
     }
 
+    CapabilitySet Solvable::providesNamespace( const std::string & namespace_r ) const
+    {
+      NO_SOLVABLE_RETURN( CapabilitySet() );
+      CapabilitySet ret;
+      Capabilities caps( provides() );
+      for_( it, caps.begin(), caps.end() )
+      {
+        CapDetail caprep( it->detail() );
+        if ( str::hasPrefix( caprep.name().c_str(), namespace_r ) && *(caprep.name().c_str()+namespace_r.size()) == '(' )
+          ret.insert( *it );
+      }
+      return ret;
+   }
+
+    CapabilitySet Solvable::valuesOfNamespace( const std::string & namespace_r ) const
+    {
+      NO_SOLVABLE_RETURN( CapabilitySet() );
+      CapabilitySet ret;
+      Capabilities caps( provides() );
+      for_( it, caps.begin(), caps.end() )
+      {
+        CapDetail caprep( it->detail() );
+        if ( str::hasPrefix( caprep.name().c_str(), namespace_r ) && *(caprep.name().c_str()+namespace_r.size()) == '(' )
+        {
+          std::string value( caprep.name().c_str()+namespace_r.size()+1 );
+          value[value.size()-1] = '\0'; // erase the trailing ')'
+          ret.insert( Capability( value, caprep.op(), caprep.ed() ) );
+        }
+      }
+      return ret;
+    }
+
+
+    std::string Solvable::asString() const
+    {
+      NO_SOLVABLE_RETURN( (_id == detail::systemSolvableId ? "systemSolvable" : "noSolvable") );
+      return str::form( "%s-%s.%s",
+                        IdString( _solvable->name ).c_str(),
+                        IdString( _solvable->evr ).c_str(),
+                        IdString( _solvable->arch ).c_str() );
+    }
+
+    bool Solvable::identical( Solvable rhs ) const
+    {
+      NO_SOLVABLE_RETURN( ! rhs.get() );
+      ::_Solvable * rhssolvable( rhs.get() );
+      return rhssolvable && ( _solvable == rhssolvable || ::solvable_identical( _solvable, rhssolvable ) );
+    }
+
     ///////////////////////////////////////////////////////////////////
     namespace
     { /////////////////////////////////////////////////////////////////
@@ -355,16 +533,16 @@ namespace zypp
             case CapDetail::CAP_AND:
             case CapDetail::CAP_OR:
                 // expand
-            {
-              int res = invokeOnEachSupportedLocale( detail.lhs(), fnc_r );
-              if ( res < 0 )
-                return res; // negative on abort.
-              int res2 = invokeOnEachSupportedLocale( detail.rhs(), fnc_r );
-              if ( res2 < 0 )
-                return -res + res2; // negative on abort.
-              return res + res2;
-            }
-            break;
+              {
+                int res = invokeOnEachSupportedLocale( detail.lhs(), fnc_r );
+                if ( res < 0 )
+                  return res; // negative on abort.
+                int res2 = invokeOnEachSupportedLocale( detail.rhs(), fnc_r );
+                if ( res2 < 0 )
+                  return -res + res2; // negative on abort.
+                return res + res2;
+              }
+              break;
 
             case CapDetail::CAP_NAMESPACE:
               if ( detail.lhs().id() == NAMESPACE_LANGUAGE )
@@ -375,6 +553,7 @@ namespace zypp
 
             case CapDetail::REL_NONE:
             case CapDetail::CAP_WITH:
+            case CapDetail::CAP_ARCH:
               break; // unwanted
           }
         }
@@ -456,7 +635,7 @@ namespace zypp
       return str << "(" << obj.id() << ")"
           << ( obj.isKind( ResKind::srcpackage ) ? "srcpackage:" : "" ) << obj.ident()
           << '-' << obj.edition() << '.' << obj.arch() << "("
-          << obj.repository().name() << ")";
+          << obj.repository().alias() << ")";
     }
 
     /******************************************************************
@@ -477,7 +656,6 @@ namespace zypp
         OUTS(OBSOLETES);
         OUTS(RECOMMENDS);
         OUTS(SUGGESTS);
-        OUTS(FRESHENS);
         OUTS(ENHANCES);
         OUTS(SUPPLEMENTS);
 #undef OUTS