///////////////////////////////////////////////////////////////////
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();
+ }
+
///////////////////////////////////////////////////////////////////
//
// CLASS NAME : PatternExpander
private:
PatternMap _patternMap;
};
- /////////////////////////////////////////////////////////////////
} // namespace
///////////////////////////////////////////////////////////////////
- IMPL_PTR_TYPE(Pattern);
///////////////////////////////////////////////////////////////////
- //
- // 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 ); }
- /** */
+ {
+ // bsc#900769: If visibility is a string(solvable ident) the pattern
+ // is visible IFF ident is available in the pool.
+ IdString ident( lookupStrAttribute( sat::SolvAttr::isvisible ) );
+ return( ident.empty() ? lookupBoolAttribute( sat::SolvAttr::isvisible )
+ : ! ResPool::instance().byIdent( ident ).empty() );
+ }
+
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 ); }
std::string Pattern::order() const
{ return lookupStrAttribute( sat::SolvAttr::order ); }
+ bool Pattern::isAutoPattern() const
+ { return bool(autoCapability( provides() )); }
+
+ sat::Solvable Pattern::autoPackage() const
+ {
+ 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();
+ }
+
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
{
+ // 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( requires() );
+ 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::depends() const
+ Pattern::Contents Pattern::depends( bool includeSuggests_r ) const
{
- // load requires, recommends, suggests
+ // 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 )
{
- Capabilities c( requires() );
- caps.insert( c.begin(),c.end() );
- c = recommends();
- caps.insert( c.begin(),c.end() );
- c = suggests();
- caps.insert( c.begin(),c.end() );
+ 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 );
make_filter_end( filter::byKind<Package>(), prv ) );
}
- Pattern::Contents Pattern::contents() const
+ Pattern::Contents Pattern::contents( bool includeSuggests_r ) const
{
PatternExpander expander;
if ( ! expander.doExpand( this ) )
Contents result;
for_( it, expander.begin(), expander.end() )
{
- Contents c( (*it)->depends() );
+ Contents c( (*it)->depends( includeSuggests_r ) );
result.get().insert( c.begin(), c.end() );
}
return result;
}
+ ///////////////////////////////////////////////////////////////////
+ namespace
+ {
+ // Get packages referenced by depKeeper dependency.
+ inline void dependsSetDoCollect( sat::Solvable depKeeper_r, Dep dep_r, Pattern::Contents & set_r )
+ {
+ CapabilitySet caps;
+ addCaps( caps, depKeeper_r, dep_r );
+ sat::WhatProvides prv( caps );
+ for ( ui::Selectable::Ptr sel : prv.selectable() )
+ {
+ const PoolItem & pi( sel->theObj() );
+ if ( pi.isKind<Package>() )
+ set_r.insert( pi );
+ }
+ }
+
+ // Get packages referenced by depKeeper.
+ inline void dependsSet( sat::Solvable depKeeper_r, Pattern::ContentsSet & collect_r )
+ {
+ dependsSetDoCollect( depKeeper_r, Dep::REQUIRES, collect_r.req );
+ dependsSetDoCollect( depKeeper_r, Dep::RECOMMENDS, collect_r.rec ),
+ dependsSetDoCollect( depKeeper_r, Dep::SUGGESTS, collect_r.sug );
+ }
+
+ // Whether this is a patterns depkeeper.
+ inline bool isPatternsPackage( sat::Solvable depKeeper_r )
+ {
+ static const Capability indicator( "pattern()" );
+ return depKeeper_r.provides().matches( indicator );
+ }
+ } // namespace
+ ///////////////////////////////////////////////////////////////////
+ void Pattern::contentsSet( ContentsSet & collect_r, bool recursively_r ) const
+ {
+ sat::Solvable depKeeper( autoPackage() ); // (my required) patterns-package
+ if ( ! depKeeper )
+ return;
+
+ // step 2 data
+ std::set<sat::Solvable> recTodo; // recommended patterns-packages to process
+ std::set<sat::Solvable> allDone; // patterns-packages already expanded
+ {
+ // step 1: Expand requirements, remember recommends....
+ // step 1 data (scoped to step1)
+ std::set<sat::Solvable> reqTodo; // required patterns-packages to process
+
+ collect_r.req.insert( depKeeper );// collect the depKeeper
+ reqTodo.insert( depKeeper ); // and expand it...
+
+ while ( ! reqTodo.empty() )
+ {
+ // pop one patterns-package from todo
+ depKeeper = ( *reqTodo.begin() );
+ reqTodo.erase( reqTodo.begin() );
+ allDone.insert( depKeeper );
+
+ // collects stats
+ ContentsSet result;
+ dependsSet( depKeeper, result );
+
+ // evaluate result....
+ for ( sat::Solvable solv : result.req ) // remember unprocessed required patterns-packages...
+ {
+ if ( collect_r.req.insert( solv ) && recursively_r && isPatternsPackage( solv ) )
+ reqTodo.insert( solv );
+ }
+ for ( sat::Solvable solv : result.rec ) // remember unprocessed recommended patterns-packages...
+ {
+ if ( collect_r.rec.insert( solv ) && recursively_r && isPatternsPackage( solv ) )
+ recTodo.insert( solv );
+ }
+ for ( sat::Solvable solv : result.sug ) // NOTE: We don't expand suggested patterns!
+ {
+ collect_r.sug.insert( solv );
+ }
+ }
+ }
+ // step 2: All requirements are expanded, now check remaining recommends....
+ while ( ! recTodo.empty() )
+ {
+ // pop one patterns-package from todo
+ depKeeper = ( *recTodo.begin() );
+ recTodo.erase( recTodo.begin() );
+ if ( ! allDone.insert( depKeeper ).second )
+ continue; // allready expanded (in requires)
+
+ // collects stats
+ ContentsSet result;
+ dependsSet( depKeeper, result );
+
+ // evaluate result....
+ for ( sat::Solvable solv : result.req ) // remember unprocessed required patterns-packages...
+ {
+ // NOTE: Requirements of recommended patterns count as 'recommended'
+ if ( collect_r.rec.insert( solv ) && recursively_r && isPatternsPackage( solv ) )
+ recTodo.insert( solv );
+ }
+ for ( sat::Solvable solv : result.rec ) // remember unprocessed recommended patterns-packages...
+ {
+ if ( collect_r.rec.insert( solv ) && recursively_r && isPatternsPackage( solv ) )
+ recTodo.insert( solv );
+ }
+ for ( sat::Solvable solv : result.sug ) // NOTE: We don't expand suggested patterns!
+ {
+ collect_r.sug.insert( solv );
+ }
+ }
+ }
+
+
/////////////////////////////////////////////////////////////////
} // namespace zypp
///////////////////////////////////////////////////////////////////