1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/Pattern.cc
13 #include "zypp/base/LogTools.h"
15 #include "zypp/ResPool.h"
16 #include "zypp/Pattern.h"
17 #include "zypp/Filter.h"
21 ///////////////////////////////////////////////////////////////////
24 ///////////////////////////////////////////////////////////////////
27 inline Capability autoCapability( const Capabilities & provides_r )
29 static const Capability autopattern( "autopattern()" );
30 for ( const auto & cap : provides_r )
31 if ( cap.matches( autopattern ) == CapMatch::yes )
36 ///////////////////////////////////////////////////////////////////
38 // CLASS NAME : PatternExpander
40 /** Recursively expand a Pattern.
42 * This means recursively expanding Patterns included by this or
43 * extending this. The result is a \c set of <tt>Pattern::constPtr</tt>
44 * accessible via iterator.
49 typedef std::map<Pattern::constPtr, DefaultIntegral<bool, false> > PatternMap;
50 typedef PatternMap::size_type size_type;
51 typedef PatternMap::key_type value_type;
52 typedef MapKVIteratorTraits<PatternMap>::Key_const_iterator const_iterator;
58 /** Recursively expand Pattern. */
59 size_type doExpand( Pattern::constPtr pat_r )
61 // INT << "+++ " << pat_r << " ++++++++++++++++++++++++++++++++++" << endl;
66 Pattern::constPtr unprocessed( pat_r );
67 // MIL << _patternMap << endl;
69 expandIncludes( unprocessed );
70 expandExtending( unprocessed );
71 _patternMap[unprocessed] = true;
72 // MIL << _patternMap << endl;
73 } while( (unprocessed = nextUnprocessed()) );
75 // SEC << "--- " << _patternMap.size() << " ----------------------------------" << endl;
76 return _patternMap.size();
79 const_iterator begin() const
80 { return make_map_key_begin( _patternMap ); }
82 const_iterator end() const
83 { return make_map_key_end( _patternMap ); }
86 /** Get the next unprocessed Pattern in \c _patternMap. */
87 Pattern::constPtr nextUnprocessed() const
89 for_( it, _patternMap.begin(), _patternMap.end() )
98 /** Store all included patterns in \c _patternMap. */
99 void expandIncludes( const Pattern::constPtr & pat_r )
101 Pattern::NameList c( pat_r->includes() );
102 for_( it, c.begin(), c.end() )
104 expandInclude( Capability( it->c_str()/*, *ResKind::pattern*/ ) );
108 /** Store Patterns matching an \c Includes capability in \c _patternMap. */
109 void expandInclude( const Capability & include_r )
111 sat::WhatProvides w( include_r );
112 for_( it, w.begin(), w.end() )
114 _patternMap[asKind<Pattern>(PoolItem(*it))];
119 /** Store all patterns extending \c pat_r in \c _patternMap. */
120 void expandExtending( const Pattern::constPtr & pat_r )
122 ResPool pool( ResPool::instance() );
123 for_( it, pool.byKindBegin<Pattern>(), pool.byKindEnd<Pattern>() )
125 expandIfExtends( pat_r, *it );
129 /** Store \c extending_r if it extends \c pat_r. */
130 void expandIfExtends( const Pattern::constPtr & pat_r, const PoolItem & extending_r )
132 Pattern::constPtr extending( asKind<Pattern>(extending_r) );
133 Pattern::NameList c( extending->extends() );
134 for_( it, c.begin(), c.end() )
136 if ( providedBy( pat_r, Capability( it->c_str()/*, *ResKind::pattern*/ ) ) )
138 // an extends matches the Pattern
139 _patternMap[extending];
145 /** Return true if Capability \c extends_r is provided by Pattern. */
146 bool providedBy( const Pattern::constPtr & pat_r, const Capability & extends_r )
151 sat::Solvable pat( pat_r->satSolvable() );
152 sat::WhatProvides w( extends_r );
153 for_( it, w.begin(), w.end() )
162 PatternMap _patternMap;
165 ///////////////////////////////////////////////////////////////////
167 ///////////////////////////////////////////////////////////////////
169 ///////////////////////////////////////////////////////////////////
171 IMPL_PTR_TYPE(Pattern);
173 Pattern::Pattern( const sat::Solvable & solvable_r )
174 : ResObject( solvable_r )
180 bool Pattern::isDefault() const
181 { return lookupBoolAttribute( sat::SolvAttr::isdefault ); }
183 bool Pattern::userVisible() const
185 // bsc#900769: If visibility is a string(solvable ident) the pattern
186 // is visible IFF ident is available in the pool.
187 IdString ident( lookupStrAttribute( sat::SolvAttr::isvisible ) );
188 return( ident.empty() ? lookupBoolAttribute( sat::SolvAttr::isvisible )
189 : ! ResPool::instance().byIdent( ident ).empty() );
192 std::string Pattern::category( const Locale & lang_r ) const
193 { return lookupStrAttribute( sat::SolvAttr::category, lang_r ); }
195 Pathname Pattern::icon() const
196 { return lookupStrAttribute( sat::SolvAttr::icon ); }
198 Pathname Pattern::script() const
199 { return lookupStrAttribute( sat::SolvAttr::script ); }
201 std::string Pattern::order() const
202 { return lookupStrAttribute( sat::SolvAttr::order ); }
204 bool Pattern::isAutoPattern() const
205 { return bool(autoCapability( provides() )); }
207 sat::Solvable Pattern::autoPackage() const
209 Capability autocap( autoCapability( provides() ) );
212 Capability pkgCap( arch(), autocap.detail().ed().asString(), Rel::EQ, edition() );
213 for ( const auto & solv: sat::WhatProvides( pkgCap ) )
214 if ( solv.repository() == repository() )
217 return sat::Solvable();
220 Pattern::NameList Pattern::includes() const
221 { return NameList( sat::SolvAttr::includes, satSolvable() ); }
223 Pattern::NameList Pattern::extends() const
224 { return NameList( sat::SolvAttr::extends, satSolvable() ); }
226 ///////////////////////////////////////////////////////////////////
229 inline void addCaps( CapabilitySet & caps_r, sat::Solvable solv_r, Dep dep_r )
231 Capabilities c( solv_r[dep_r] );
234 caps_r.insert( c.begin(),c.end() );
238 ///////////////////////////////////////////////////////////////////
240 Pattern::Contents Pattern::core() const
242 // Content dependencies are either associated with
243 // the autoPackage or the (oldstype) pattern itself.
246 addCaps( caps, *this, Dep::REQUIRES );
248 sat::Solvable depKeeper( autoPackage() );
250 addCaps( caps, depKeeper, Dep::REQUIRES );
251 // get items providing the requirements
252 sat::WhatProvides prv( caps );
253 // return packages only.
254 return Pattern::Contents( make_filter_begin( filter::byKind<Package>(), prv ),
255 make_filter_end( filter::byKind<Package>(), prv ) );
258 Pattern::Contents Pattern::depends( bool includeSuggests_r ) const
260 // Content dependencies are either associated with
261 // the autoPackage or the (oldstype) pattern itself.
262 // load requires, recommends[, suggests]
264 addCaps( caps, *this, Dep::REQUIRES );
265 addCaps( caps, *this, Dep::RECOMMENDS );
266 if ( includeSuggests_r )
267 addCaps( caps, *this, Dep::SUGGESTS );
269 sat::Solvable depKeeper( autoPackage() );
272 addCaps( caps, depKeeper, Dep::REQUIRES );
273 addCaps( caps, depKeeper, Dep::RECOMMENDS );
274 if ( includeSuggests_r )
275 addCaps( caps, depKeeper, Dep::SUGGESTS );
277 // get items providing the above
278 sat::WhatProvides prv( caps );
279 // return packages only.
280 return Pattern::Contents( make_filter_begin( filter::byKind<Package>(), prv ),
281 make_filter_end( filter::byKind<Package>(), prv ) );
284 Pattern::Contents Pattern::contents( bool includeSuggests_r ) const
286 PatternExpander expander;
287 if ( ! expander.doExpand( this ) )
288 return Contents(); // empty pattern set
291 for_( it, expander.begin(), expander.end() )
293 Contents c( (*it)->depends( includeSuggests_r ) );
294 result.get().insert( c.begin(), c.end() );
299 ///////////////////////////////////////////////////////////////////
302 // Get packages referenced by depKeeper dependency.
303 inline void dependsSetDoCollect( sat::Solvable depKeeper_r, Dep dep_r, Pattern::Contents & set_r )
306 addCaps( caps, depKeeper_r, dep_r );
307 sat::WhatProvides prv( caps );
308 for ( ui::Selectable::Ptr sel : prv.selectable() )
310 const PoolItem & pi( sel->theObj() );
311 if ( pi.isKind<Package>() )
316 // Get packages referenced by depKeeper.
317 inline void dependsSet( sat::Solvable depKeeper_r, Pattern::ContentsSet & collect_r )
319 dependsSetDoCollect( depKeeper_r, Dep::REQUIRES, collect_r.req );
320 dependsSetDoCollect( depKeeper_r, Dep::RECOMMENDS, collect_r.rec ),
321 dependsSetDoCollect( depKeeper_r, Dep::SUGGESTS, collect_r.sug );
324 // Whether this is a patterns depkeeper.
325 inline bool isPatternsPackage( sat::Solvable depKeeper_r )
327 static const Capability indicator( "pattern()" );
328 return depKeeper_r.provides().matches( indicator );
331 ///////////////////////////////////////////////////////////////////
332 void Pattern::contentsSet( ContentsSet & collect_r, bool recursively_r ) const
334 sat::Solvable depKeeper( autoPackage() ); // (my required) patterns-package
339 std::set<sat::Solvable> recTodo; // recommended patterns-packages to process
340 std::set<sat::Solvable> allDone; // patterns-packages already expanded
342 // step 1: Expand requirements, remember recommends....
343 // step 1 data (scoped to step1)
344 std::set<sat::Solvable> reqTodo; // required patterns-packages to process
346 collect_r.req.insert( depKeeper );// collect the depKeeper
347 reqTodo.insert( depKeeper ); // and expand it...
349 while ( ! reqTodo.empty() )
351 // pop one patterns-package from todo
352 depKeeper = ( *reqTodo.begin() );
353 reqTodo.erase( reqTodo.begin() );
354 allDone.insert( depKeeper );
358 dependsSet( depKeeper, result );
360 // evaluate result....
361 for ( sat::Solvable solv : result.req ) // remember unprocessed required patterns-packages...
363 if ( collect_r.req.insert( solv ) && recursively_r && isPatternsPackage( solv ) )
364 reqTodo.insert( solv );
366 for ( sat::Solvable solv : result.rec ) // remember unprocessed recommended patterns-packages...
368 if ( collect_r.rec.insert( solv ) && recursively_r && isPatternsPackage( solv ) )
369 recTodo.insert( solv );
371 for ( sat::Solvable solv : result.sug ) // NOTE: We don't expand suggested patterns!
373 collect_r.sug.insert( solv );
377 // step 2: All requirements are expanded, now check remaining recommends....
378 while ( ! recTodo.empty() )
380 // pop one patterns-package from todo
381 depKeeper = ( *recTodo.begin() );
382 recTodo.erase( recTodo.begin() );
383 if ( ! allDone.insert( depKeeper ).second )
384 continue; // allready expanded (in requires)
388 dependsSet( depKeeper, result );
390 // evaluate result....
391 for ( sat::Solvable solv : result.req ) // remember unprocessed required patterns-packages...
393 // NOTE: Requirements of recommended patterns count as 'recommended'
394 if ( collect_r.rec.insert( solv ) && recursively_r && isPatternsPackage( solv ) )
395 recTodo.insert( solv );
397 for ( sat::Solvable solv : result.rec ) // remember unprocessed recommended patterns-packages...
399 if ( collect_r.rec.insert( solv ) && recursively_r && isPatternsPackage( solv ) )
400 recTodo.insert( solv );
402 for ( sat::Solvable solv : result.sug ) // NOTE: We don't expand suggested patterns!
404 collect_r.sug.insert( solv );
410 /////////////////////////////////////////////////////////////////
412 ///////////////////////////////////////////////////////////////////