Imported Upstream version 14.45.0
[platform/upstream/libzypp.git] / zypp / Pattern.cc
index e6d3dd2..45562f0 100644 (file)
  *
 */
 #include <iostream>
+#include "zypp/base/LogTools.h"
 
+#include "zypp/ResPool.h"
 #include "zypp/Pattern.h"
+#include "zypp/Filter.h"
+
+using std::endl;
 
 ///////////////////////////////////////////////////////////////////
 namespace zypp
-{ /////////////////////////////////////////////////////////////////
+{
+  ///////////////////////////////////////////////////////////////////
+  namespace
+  {
+    inline Capability autoCapability( const Capabilities & provides_r )
+    {
+      static const Capability autopattern( "autopattern()" );
+      for ( const auto & cap : provides_r )
+       if ( cap.matches( autopattern ) == CapMatch::yes )
+         return cap;
+      return Capability();
+    }
 
-  IMPL_PTR_TYPE(Pattern);
+    ///////////////////////////////////////////////////////////////////
+    //
+    // CLASS NAME : PatternExpander
+    //
+    /** Recursively expand a Pattern.
+     *
+     * This means recursively expanding Patterns included by this or
+     * extending this. The result is a \c set of <tt>Pattern::constPtr</tt>
+     * accessible via iterator.
+     */
+    class PatternExpander
+    {
+      public:
+        typedef std::map<Pattern::constPtr, DefaultIntegral<bool, false> > PatternMap;
+        typedef PatternMap::size_type size_type;
+        typedef PatternMap::key_type  value_type;
+        typedef MapKVIteratorTraits<PatternMap>::Key_const_iterator const_iterator;
+
+      public:
+        PatternExpander()
+        {}
+
+        /** Recursively expand Pattern. */
+        size_type doExpand( Pattern::constPtr pat_r )
+        {
+          // INT << "+++ " << pat_r << " ++++++++++++++++++++++++++++++++++" << endl;
+          _patternMap.clear();
+          if ( pat_r )
+          {
+            _patternMap[pat_r];
+            Pattern::constPtr unprocessed( pat_r );
+            // MIL << _patternMap << endl;
+            do {
+              expandIncludes( unprocessed );
+              expandExtending( unprocessed );
+              _patternMap[unprocessed] = true;
+              // MIL << _patternMap << endl;
+            } while( (unprocessed = nextUnprocessed()) );
+          }
+          // SEC << "--- " << _patternMap.size() << " ----------------------------------" << endl;
+          return _patternMap.size();
+        }
+
+        const_iterator begin() const
+        { return make_map_key_begin( _patternMap ); }
+
+        const_iterator end() const
+        { return make_map_key_end( _patternMap ); }
+
+      private:
+        /** Get the next unprocessed Pattern in \c _patternMap. */
+        Pattern::constPtr nextUnprocessed() const
+        {
+          for_( it, _patternMap.begin(), _patternMap.end() )
+          {
+            if ( ! it->second )
+              return it->first;
+          }
+          return NULL;
+        }
+
+      private:
+        /** Store all included patterns in \c _patternMap. */
+        void expandIncludes( const Pattern::constPtr & pat_r )
+        {
+          Pattern::NameList c( pat_r->includes() );
+          for_( it, c.begin(), c.end() )
+          {
+            expandInclude( Capability( it->c_str()/*, *ResKind::pattern*/ ) );
+          }
+        }
 
+        /** Store Patterns matching an \c Includes capability in \c _patternMap. */
+        void expandInclude( const Capability & include_r )
+        {
+          sat::WhatProvides w( include_r );
+          for_( it, w.begin(), w.end() )
+          {
+            _patternMap[asKind<Pattern>(PoolItem(*it))];
+          }
+        }
+
+      private:
+        /** Store all patterns extending \c pat_r in \c _patternMap. */
+        void expandExtending( const Pattern::constPtr & pat_r )
+        {
+          ResPool pool( ResPool::instance() );
+          for_( it, pool.byKindBegin<Pattern>(), pool.byKindEnd<Pattern>() )
+          {
+            expandIfExtends( pat_r, *it );
+          }
+        }
+
+        /** Store \c extending_r if it extends \c pat_r. */
+        void expandIfExtends( const Pattern::constPtr & pat_r, const PoolItem & extending_r )
+        {
+          Pattern::constPtr extending( asKind<Pattern>(extending_r) );
+          Pattern::NameList c( extending->extends() );
+          for_( it, c.begin(), c.end() )
+          {
+            if ( providedBy( pat_r, Capability( it->c_str()/*, *ResKind::pattern*/ ) ) )
+            {
+              // an extends matches the Pattern
+              _patternMap[extending];
+              break;
+            }
+          }
+        }
+
+        /** Return true if Capability \c extends_r is provided by Pattern. */
+        bool providedBy( const Pattern::constPtr & pat_r, const Capability & extends_r )
+        {
+          if ( !pat_r )
+            return false;
+
+          sat::Solvable pat( pat_r->satSolvable() );
+          sat::WhatProvides w( extends_r );
+          for_( it, w.begin(), w.end() )
+          {
+            if ( pat == *it )
+              return true;
+          }
+          return false;
+        }
+
+      private:
+        PatternMap _patternMap;
+    };
+  } // namespace
   ///////////////////////////////////////////////////////////////////
-  //
-  //   METHOD NAME : Pattern::Pattern
-  //   METHOD TYPE : Ctor
-  //
+
+  ///////////////////////////////////////////////////////////////////
+  //   Pattern
+  ///////////////////////////////////////////////////////////////////
+
+  IMPL_PTR_TYPE(Pattern);
+
   Pattern::Pattern( const sat::Solvable & solvable_r )
   : ResObject( solvable_r )
   {}
 
-  ///////////////////////////////////////////////////////////////////
-  //
-  //   METHOD NAME : Pattern::~Pattern
-  //   METHOD TYPE : Dtor
-  //
   Pattern::~Pattern()
   {}
 
-  ///////////////////////////////////////////////////////////////////
-  //
-  //   Pattern interface forwarded to implementation
-  //
-  ///////////////////////////////////////////////////////////////////
-  /** */
   bool Pattern::isDefault() const
   { return lookupBoolAttribute( sat::SolvAttr::isdefault ); }
-  /** */
+
   bool Pattern::userVisible() const
   { return lookupBoolAttribute( sat::SolvAttr::isvisible ); }
-  /** */
-  std::string Pattern::category() const
-  { return lookupStrAttribute( sat::SolvAttr::category ); }
-  /** */
+
+  std::string Pattern::category( const Locale & lang_r ) const
+  { return lookupStrAttribute( sat::SolvAttr::category, lang_r ); }
+
   Pathname Pattern::icon() const
   { return lookupStrAttribute( sat::SolvAttr::icon ); }
-  /** */
+
   Pathname Pattern::script() const
   { return lookupStrAttribute( sat::SolvAttr::script ); }
 
-  Label Pattern::order() const
-  { return Label(); }
+  std::string Pattern::order() const
+  { return lookupStrAttribute( sat::SolvAttr::order ); }
 
-  std::set<std::string> Pattern::install_packages( const Locale & lang ) const
+  bool Pattern::isAutoPattern() const
+  { return bool(autoCapability( provides() )); }
+
+  sat::Solvable Pattern::autoPackage() const
   {
-#warning implement PATTERN::INSTALL_PACKAGES
-#if 0
--    static void copycaps( std::set<std::string> & out, const CapSet & in)
--    {
--      for (CapSet::const_iterator it = in.begin(); it != in.end(); ++it) {
--          if (isKind<capability::NamedCap>( *it )
--              && it->refers() == ResTraits<zypp::Package>::kind )
--          {
--              out.insert( it->index() );
--          }
--      }
--    }
--
--    std::set<std::string> PatternImplIf::install_packages( const Locale & lang) const
--    {
--      std::set<std::string> result;
--
--      copycaps( result, self()->dep( Dep::REQUIRES ) );
--      copycaps( result, self()->dep( Dep::RECOMMENDS) );
--      copycaps( result, self()->dep( Dep::SUGGESTS) );
--
--      return result;
--    }
--
--
-#endif
-  return std::set<std::string>();
+    Capability autocap( autoCapability( provides() ) );
+    if ( autocap )
+    {
+      Capability pkgCap( arch(), autocap.detail().ed().asString(), Rel::EQ, edition() );
+      for ( const auto & solv: sat::WhatProvides( pkgCap ) )
+       if ( solv.repository() == repository() )
+         return solv;
+    }
+    return sat::Solvable();
   }
 
-#warning implement PATTERN::INSTALL_PACKAGES
- const Capabilities & Pattern::includes() const
+  Pattern::NameList Pattern::includes() const
+  { return NameList( sat::SolvAttr::includes, satSolvable() ); }
+
+  Pattern::NameList Pattern::extends() const
+  { return NameList( sat::SolvAttr::extends, satSolvable() ); }
+
+  ///////////////////////////////////////////////////////////////////
+  namespace
+  {
+    inline void addCaps( CapabilitySet & caps_r, sat::Solvable solv_r, Dep dep_r )
+    {
+      Capabilities c( solv_r[dep_r] );
+      if ( ! c.empty() )
+      {
+       caps_r.insert( c.begin(),c.end() );
+      }
+    }
+  } //namespace
+  ///////////////////////////////////////////////////////////////////
+
+  Pattern::Contents Pattern::core() const
   {
-    static Capabilities _val;
-    return _val;
+    // Content dependencies are either associated with
+    // the autoPackage or the (oldstype) pattern itself.
+    // load requires
+    CapabilitySet caps;
+    addCaps( caps, *this, Dep::REQUIRES );
+
+    sat::Solvable depKeeper( autoPackage() );
+    if ( depKeeper )
+      addCaps( caps, depKeeper, Dep::REQUIRES );
+    // get items providing the requirements
+    sat::WhatProvides prv( caps );
+    // return packages only.
+    return Pattern::Contents( make_filter_begin( filter::byKind<Package>(), prv ),
+                              make_filter_end( filter::byKind<Package>(), prv ) );
   }
 
-  const Capabilities & Pattern::extends() const
+  Pattern::Contents Pattern::depends( bool includeSuggests_r ) const
   {
-    static Capabilities _val;
-    return _val;
+    // Content dependencies are either associated with
+    // the autoPackage or the (oldstype) pattern itself.
+    // load requires, recommends[, suggests]
+    CapabilitySet caps;
+    addCaps( caps, *this, Dep::REQUIRES );
+    addCaps( caps, *this, Dep::RECOMMENDS );
+    if ( includeSuggests_r )
+      addCaps( caps, *this, Dep::SUGGESTS );
+
+    sat::Solvable depKeeper( autoPackage() );
+    if ( depKeeper )
+    {
+      addCaps( caps, depKeeper, Dep::REQUIRES );
+      addCaps( caps, depKeeper, Dep::RECOMMENDS );
+      if ( includeSuggests_r )
+       addCaps( caps, depKeeper, Dep::SUGGESTS );
+    }
+    // get items providing the above
+    sat::WhatProvides prv( caps );
+    // return packages only.
+    return Pattern::Contents( make_filter_begin( filter::byKind<Package>(), prv ),
+                              make_filter_end( filter::byKind<Package>(), prv ) );
   }
 
+  Pattern::Contents Pattern::contents( bool includeSuggests_r ) const
+  {
+    PatternExpander expander;
+    if ( ! expander.doExpand( this ) )
+      return Contents(); // empty pattern set
+
+    Contents result;
+    for_( it, expander.begin(), expander.end() )
+    {
+      Contents c( (*it)->depends( includeSuggests_r ) );
+      result.get().insert( c.begin(), c.end() );
+    }
+    return result;
+  }
 
   /////////////////////////////////////////////////////////////////
 } // namespace zypp