Support RepoInfo content keywords (FATE#316287)
authorMichael Andres <ma@suse.de>
Fri, 11 Jul 2014 11:42:29 +0000 (13:42 +0200)
committerMichael Andres <ma@suse.de>
Fri, 11 Jul 2014 11:42:29 +0000 (13:42 +0200)
zypp/RepoInfo.cc
zypp/RepoInfo.h

index d22f721..6c31914 100644 (file)
 #include "zypp/ExternalProgram.h"
 #include "zypp/media/MediaAccess.h"
 
+#include "zypp/base/IOStream.h"
+#include "zypp/base/InputStream.h"
+#include "zypp/parser/xml/Reader.h"
+
 using std::endl;
 using zypp::xml::escape;
 
@@ -97,6 +101,56 @@ namespace zypp
     bool baseurl2dump() const
     { return !emptybaseurls && !_baseUrls.empty(); }
 
+
+    void addContent( const std::string & keyword_r )
+    { _keywords.insert( keyword_r ); }
+
+    bool hasContent( const std::string & keyword_r ) const
+    {
+      if ( _keywords.empty() && ! metadatapath.empty() )
+      {
+       // HACK directly check master index file until RepoManager offers
+       // some content probing ans zypepr uses it.
+       /////////////////////////////////////////////////////////////////
+       MIL << "Empty keywords...." << metadatapath << endl;
+       Pathname master;
+       if ( PathInfo( (master=metadatapath/"/repodata/repomd.xml") ).isFile() )
+       {
+         //MIL << "GO repomd.." << endl;
+         xml::Reader reader( master );
+         while ( reader.seekToNode( 2, "content" ) )
+         {
+           _keywords.insert( reader.nodeText().asString() );
+           reader.seekToEndNode( 2, "content" );
+         }
+         _keywords.insert( "" );       // valid content in _keywords even if empty
+       }
+       else if ( PathInfo( (master=metadatapath/"/content") ).isFile() )
+       {
+         //MIL << "GO content.." << endl;
+         iostr::forEachLine( InputStream( master ),
+                            [this]( int num_r, std::string line_r )->bool
+                            {
+                              if ( str::startsWith( line_r, "REPOKEYWORDS" ) )
+                             {
+                               std::vector<std::string> words;
+                               if ( str::split( line_r, std::back_inserter(words) ) > 1
+                                 && words[0].length() == 12 /*"REPOKEYWORDS"*/ )
+                               {
+                                 this->_keywords.insert( ++words.begin(), words.end() );
+                               }
+                               return true; // mult. occurrances are ok.
+                             }
+                             return( ! str::startsWith( line_r, "META " ) );   // no need to parse into META section.
+                           } );
+         _keywords.insert( "" );
+       }
+       /////////////////////////////////////////////////////////////////
+      }
+      return( _keywords.find( keyword_r ) != _keywords.end() );
+
+    }
+
   public:
     TriBool gpgcheck;
     TriBool keeppackages;
@@ -114,6 +168,7 @@ namespace zypp
   private:
     Url mirrorlist_url;
     mutable std::set<Url> _baseUrls;
+    mutable std::set<std::string> _keywords;
 
     friend Impl * rwcowClone<Impl>( const Impl * rhs );
     /** clone for RWCOW_pointer */
@@ -272,6 +327,13 @@ namespace zypp
   bool RepoInfo::baseUrlSet() const
   { return _pimpl->baseurl2dump(); }
 
+
+  void RepoInfo::addContent( const std::string & keyword_r )
+  { _pimpl->addContent( keyword_r ); }
+
+  bool RepoInfo::hasContent( const std::string & keyword_r ) const
+  { return _pimpl->hasContent( keyword_r ); }
+
   ///////////////////////////////////////////////////////////////////
 
   bool RepoInfo::hasLicense() const
index 47b111f..3b87086 100644 (file)
@@ -302,6 +302,40 @@ namespace zypp
        */
       void setTargetDistribution(const std::string & targetDistribution);
 
+      /** Add content keywords */
+      void addContent( const std::string & keyword_r );
+      /** \overload add keywords from container */
+      template <class _Iterator>
+      void addContentFrom( _Iterator begin_r, _Iterator end_r )
+      { for_( it, begin_r, end_r ) addContent( *it ); }
+      /** \overload  */
+      template <class _Container>
+      void addContentFrom( const _Container & container_r )
+      { addContentFrom( container_r.begin(), container_r.end() ); }
+
+      /** Check for content keywords.
+       * Checking for an empty string returns whether content kewords are
+       * known at all. They may be missing due to missing metadata in disabled
+       * repos.
+       */
+      bool hasContent( const std::string & keyword_r = std::string() ) const;
+      /** \overload check for \b all keywords being present */
+      template <class _Iterator>
+      bool hasContentAll( _Iterator begin_r, _Iterator end_r ) const
+      { for_( it, begin_r, end_r ) if ( ! hasContent( *it ) ) return false; return true; }
+      /** \overload  */
+      template <class _Container>
+      bool hasContentAll( const _Container & container_r ) const
+      { return hasContentAll( container_r.begin(), container_r.end() ); }
+      /** \overload check for \b any keyword being present */
+      template <class _Iterator>
+      bool hasContentAny( _Iterator begin_r, _Iterator end_r ) const
+      { for_( it, begin_r, end_r ) if ( hasContent( *it ) ) return true; return false; }
+      /** \overload  */
+      template <class _Container>
+      bool hasContentAny( const _Container & container_r ) const
+      { return hasContentAny( container_r.begin(), container_r.end() ); }
+
     public:
       /** \name Repository license
       */