Imported Upstream version 15.0.0
[platform/upstream/libzypp.git] / zypp / sat / Solvable.cc
index 886979c..bd700ae 100644 (file)
@@ -16,6 +16,7 @@
 #include "zypp/base/Exception.h"
 #include "zypp/base/Functional.h"
 #include "zypp/base/Collector.h"
+#include "zypp/base/Xml.h"
 
 #include "zypp/sat/detail/PoolImpl.h"
 #include "zypp/sat/Solvable.h"
@@ -35,64 +36,57 @@ namespace zypp
   namespace sat
   { /////////////////////////////////////////////////////////////////
 
-    Solvable::SplitIdent::SplitIdent( IdString ident_r )
-    : _ident( ident_r )
+    namespace
     {
-      if ( ! ident_r )
-        return;
-
-      const char * ident = ident_r.c_str();
-      const char * sep = ::strchr( ident, ':' );
-
-      // no ':' in package names (hopefully)
-      if ( ! sep )
+      void _doSplit( IdString & _ident, ResKind & _kind, IdString & _name )
       {
-        _kind = ResKind::package;
-        _name = ident_r;
-        return;
+        if ( ! _ident )
+          return;
+
+       ResKind explicitKind = ResKind::explicitBuiltin( _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;
+         else 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;
       }
+    }
 
-      // save name
-      _name = IdString( sep+1 );
-      // quick check for well known kinds
-      if ( sep-ident >= 4 )
-      {
-        switch ( ident[3] )
-        {
-#define OUTS(K,S) if ( !::strncmp( ident, ResKind::K.c_str(), S ) ) _kind = ResKind::K
-          //             ----v
-          case 'c': OUTS( patch, 5 );       return; break;
-          case 'd': OUTS( product, 7 );     return; break;
-          case 'k': OUTS( package, 7 );     return; break;
-          case 'p': OUTS( srcpackage, 10 ); return; break;
-          case 't': OUTS( pattern, 7 );     return; break;
-#undef OUTS
-        }
-      }
+    Solvable::SplitIdent::SplitIdent( IdString ident_r )
+    : _ident( ident_r )
+    { _doSplit( _ident, _kind, _name ); }
 
-      // an unknown kind
-      _kind = ResKind( std::string( ident, sep-ident ) );
-    }
+    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 )
-    : _kind( kind_r )
-    , _name( name_r )
-    {
-      if ( kind_r == ResKind::package || kind_r == ResKind::srcpackage )
-        _ident = _name;
-      else
-        _ident = IdString( str::form( "%s:%s", kind_r.c_str(), name_r.c_str() ) );
-    }
+    : _ident( name_r )
+    , _kind( kind_r )
+    { _doSplit( _ident, _kind, _name ); }
 
     Solvable::SplitIdent::SplitIdent( ResKind kind_r, const C_Str & name_r )
-    : _kind( kind_r )
-    , _name( name_r )
-    {
-      if ( kind_r == ResKind::package || kind_r == ResKind::srcpackage )
-        _ident = _name;
-      else
-        _ident = IdString( str::form( "%s:%s", kind_r.c_str(), name_r.c_str() ) );
-    }
+    : _ident( name_r )
+    , _kind( kind_r )
+    { _doSplit( _ident, _kind, _name ); }
 
     /////////////////////////////////////////////////////////////////
 
@@ -136,6 +130,11 @@ namespace zypp
       return myPool().isSystemRepo( _solvable->repo );
     }
 
+    bool Solvable::onSystemByUser() const
+    {
+      return isSystem() && myPool().isOnSystemByUser( ident() );
+    }
+
     IdString Solvable::ident() const
     {
       NO_SOLVABLE_RETURN( IdString() );
@@ -159,12 +158,16 @@ 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();
    }
 
-    unsigned Solvable::lookupNumAttribute( const SolvAttr & attr ) const
+    unsigned long long Solvable::lookupNumAttribute( const SolvAttr & attr ) const
     {
       NO_SOLVABLE_RETURN( 0 );
       return ::solvable_lookup_num( _solvable, attr.id(), 0 );
@@ -193,48 +196,77 @@ namespace zypp
       {
         case REPOKEY_TYPE_MD5:    return CheckSum::md5( s );
         case REPOKEY_TYPE_SHA1:   return CheckSum::sha1( s );
+        case REPOKEY_TYPE_SHA224: return CheckSum::sha224( s );
         case REPOKEY_TYPE_SHA256: return CheckSum::sha256( s );
+        case REPOKEY_TYPE_SHA384: return CheckSum::sha384( s );
+        case REPOKEY_TYPE_SHA512: return CheckSum::sha512( s );
       }
       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
       unsigned medianr;
-      char * file = ::solvable_get_location( _solvable, &medianr );
+      const char * file = ::solvable_lookup_location( _solvable, &medianr );
       if ( ! file )
         return OnMediaLocation();
+      if ( ! medianr )
+       medianr = 1;
 
       OnMediaLocation ret;
 
       Pathname path;
-#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(?).
-      // (ma@) Just a quick'n'dirty solution as we wan't
-      // to get rid of susetags.
-      static const sat::SolvAttr susetagsDatadir( "susetags:datadir" );
       switch ( repository().info().type().toEnum() )
       {
         case repo::RepoType::NONE_e:
-          if ( sat::LookupAttr( susetagsDatadir, repository() ).empty() )
-            break;
-          // else set type and fall through
-          repository().info().setProbedType( repo::RepoType::YAST2_e );
+        {
+          path = lookupDatadirIn( repository() );
+          if ( ! path.empty() )
+            repository().info().setProbedType( repo::RepoType::YAST2_e );
+        }
+        break;
+
         case repo::RepoType::YAST2_e:
-          path = "suse";
-          break;
+        {
+          path = lookupDatadirIn( repository() );
+          if ( path.empty() )
+            path = "suse";
+        }
+        break;
+
         default:
           break;
       }
       ret.setLocation    ( path/file, medianr );
-      ret.setDownloadSize( ByteCount( lookupNumAttribute( SolvAttr::downloadsize ), ByteCount::K ) );
+      ret.setDownloadSize( ByteCount( lookupNumAttribute( SolvAttr::downloadsize ) ) );
       ret.setChecksum    ( lookupCheckSumAttribute( SolvAttr::checksum ) );
       // Not needed/available for solvables?
-      //ret.setOpenSize    ( ByteCount( lookupNumAttribute( SolvAttr::opensize ), ByteCount::K ) );
+      //ret.setOpenSize    ( ByteCount( lookupNumAttribute( SolvAttr::opensize ) ) );
       //ret.setOpenChecksum( lookupCheckSumAttribute( SolvAttr::openchecksum ) );
       return ret;
     }
@@ -251,30 +283,18 @@ namespace zypp
           break;
       }
 
+      // either explicitly prefixed...
       const char * ident = IdString( _solvable->name ).c_str();
-      const char * sep = ::strchr( ident, ':' );
+      ResKind knownKind( ResKind::explicitBuiltin( ident ) );
+      if ( knownKind )
+       return knownKind;
 
-      // no ':' in package names (hopefully)
+      // ...or no ':' in package names (hopefully)...
+      const char * sep = ::strchr( ident, ':' );
       if ( ! sep )
-        return ResKind::package;
+       return ResKind::package;
 
-      // quick check for well known kinds
-      if ( sep-ident >= 4 )
-      {
-        switch ( ident[3] )
-        {
-#define OUTS(K,S) if ( !::strncmp( ident, ResKind::K.c_str(), S ) ) return 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
-        }
-      }
-
-      // an unknown kind
+      // ...or something unknown.
       return ResKind( std::string( ident, sep-ident ) );
     }
 
@@ -333,12 +353,9 @@ namespace zypp
       //return ArchId( _solvable->arch );
     }
 
-    bool Solvable::installOnly() const
+    bool Solvable::multiversionInstall() const
     {
-       std::set<IdString> multiversion = ZConfig::instance().multiversion();
-       if (multiversion.find(ident()) != multiversion.end())
-             return true;
-       return false;
+      return myPool().isMultiversion( ident() );
     }
 
     IdString Solvable::vendor() const
@@ -417,6 +434,65 @@ 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() );
+    }
+
+    std::string Solvable::asUserString() const\
+    {
+      NO_SOLVABLE_RETURN( (_id == detail::systemSolvableId ? "systemSolvable" : "noSolvable") );
+      return str::form( "%s-%s.%s(%s)",
+                        IdString( _solvable->name ).c_str(),
+                        IdString( _solvable->evr ).c_str(),
+                        IdString( _solvable->arch ).c_str(),
+                        repository().asUserString().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
     { /////////////////////////////////////////////////////////////////
@@ -564,6 +640,18 @@ namespace zypp
       return str;
     }
 
+    std::ostream & dumpAsXmlOn( std::ostream & str, const Solvable & obj )
+    {
+      xmlout::Node guard( str, "solvable" );
+
+      dumpAsXmlOn( *guard, obj.kind() );
+      *xmlout::Node( *guard, "name" ) << obj.name();
+      dumpAsXmlOn( *guard, obj.edition() );
+      dumpAsXmlOn( *guard, obj.arch() );
+      dumpAsXmlOn( *guard, obj.repository() );
+      return str;
+    }
+
     /////////////////////////////////////////////////////////////////
   } // namespace sat
   ///////////////////////////////////////////////////////////////////