1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/PoolQuery.h
12 #ifndef ZYPP_POOLQUERY_H
13 #define ZYPP_POOLQUERY_H
19 #include "zypp/base/Regex.h"
20 #include "zypp/base/PtrTypes.h"
21 #include "zypp/base/Function.h"
23 #include "zypp/sat/SolvIterMixin.h"
24 #include "zypp/sat/LookupAttr.h"
25 #include "zypp/sat/AttrMatcher.h"
26 #include "zypp/sat/Pool.h"
28 ///////////////////////////////////////////////////////////////////
30 { /////////////////////////////////////////////////////////////////
34 class PoolQueryIterator;
37 ///////////////////////////////////////////////////////////////////
39 // CLASS NAME : PoolQuery
42 * Meta-data query API. Returns solvables of specified kinds from specified
43 * repositories with attributes matching the specified search strings.
45 * The search strings can be specified via \ref addString() and
46 * \ref addAttribute() methods. String matching type can be set using the
47 * setMatch*() methods. Multiple search strings for a particular attribute
48 * will be combined into a regex (see \ref addString() and
49 * \ref addAttribute() for more details).
51 * The begin() and end() methods return a PoolQueryIterator returning
52 * \ref sat::Solvable objects which can easily be turned into \ref Resolvable
53 * objects. Additionally, thanx to the \ref sat::SolvIterMixin, a Selectable
54 * and PoolItem iterators are automatically available.
56 * \note You will sometimes face the problem, that when using the \ref PoolItem
57 * iterator you hit multiple version of the same package, while when using the
58 * \ref ui::Selectable iterator the information which of the available candidates
59 * actually matched got lost. In this case class \ref PoolItemBest may help you.
60 * Use it to pick the best version only.
64 * q.addAttribute(sat::SolvAttr::name, "zypp*");
65 * q.addKind(ResKind::package);
68 * for (PoolQuery::Selectable_iterator it = q.selectableBegin();
69 * it != q.selectableEnd(); ++it)
71 * ui::Selectable::constPtr s = *it;
76 * Performance considerations
78 * Results of simple queries like those using one string and/or one attribute
79 * and/or one repository are filtered by sat-solver's Dataiterator directly,
80 * and thus it is fast.
82 * Queries with multiple strings are implemented using regexes. Queries based
83 * on kinds, multiple repos, and multiple attributes are filtered inside
84 * the PoolQuery, so these tend to be slower.
86 * \see detail::PoolQueryIterator on how to inspect matches in detail.
87 * \see tests/zypp/PoolQuery_test.cc for more examples
88 * \see sat::SolvIterMixin
90 class PoolQuery : public sat::SolvIterMixin<PoolQuery, detail::PoolQueryIterator>
93 typedef std::set<ResKind> Kinds;
94 typedef std::set<std::string> StrContainer;
95 typedef std::map<sat::SolvAttr, StrContainer> AttrRawStrMap;
97 typedef detail::PoolQueryIterator const_iterator;
98 typedef unsigned int size_type;
101 typedef function<bool( const sat::Solvable & )> ProcessResolvable;
106 /** Query result accessers. */
109 * Compile the query and return an iterator to the result.
111 * \return An iterator (\ref detail::PoolQueryIterator) returning
112 * sat::Solvable objects pointing at the beginning of the query result.
113 * \throws sat::MatchInvalidRegexException if the query was about to use a regex which
116 * \note Note that PoolQuery is derived from \ref sat::SolvIterMixin which
117 * makes PoolItem and Selectable iterators automatically available.
118 * \see \ref sat::SolvIterMixin
120 const_iterator begin() const;
122 /** An iterator pointing to the end of the query result. */
123 const_iterator end() const;
125 /** Whether the result is empty. */
128 /** Number of solvables in the query result. */
129 size_type size() const;
133 * Executes the query with the current settings.
134 * Results are yielded via the \a fnc callback.
136 void execute(ProcessResolvable fnc);
139 * Filter by selectable kind.
141 * By default, all kinds will be returned. If addKind() is used,
142 * only the specified kinds will be returned (multiple kinds will be ORed).
144 * Pass ResKind constants to this method, (e.g. ResKind::package).
146 void addKind(const ResKind & kind);
151 * By default, all repos will be returned. If addRepo() is used,
152 * only the specified repo will be returned (multiple repos will be ORed).
154 void addRepo(const std::string &repoalias);
156 /** Installed status filter setters. */
160 * Filter by status (installed uninstalled)
163 ALL = 0, // both install filter and uninstall filter bits are 0
168 /** Return only @System repo packages */
169 void setInstalledOnly();
170 /** Return only packages from repos other than @System. */
171 void setUninstalledOnly();
172 /** Set status filter directly \see StatusFilter */
173 void setStatusFilterFlags( StatusFilter flags );
178 * Add a global query string. The string added via this method is applied
179 * to all query attributes as if addAttribute(..., \value) was called
182 * This method can be used multiple times in which case the query strings
183 * will be combined (together with strings added via addAttribute()) into
184 * a regex. Searched attribute value will match this regex if <b>any</b>
185 * of these strings will match the value. This can be changed by
186 * (not yet implemented) \ref setRequireAll() method.
188 void addString(const std::string & value);
191 * Filter by the \a value of the specified \a attr attribute. This can
192 * be any of the available solvable attributes.
194 * This method can be used multiple times with the same \a attr in which
195 * case the query strings will be combined (together with strings added
196 * via addString()) into a regex. Searched attribute value will match
197 * this regex if <b>any</b> of these strings will match the value.
198 * This can be changed by (not yet implemented) \ref setRequireAll()
201 * \note Though it is possible to use dependency attributes like
202 * \ref Solv::Attr::provides here, note that the query string is
203 * matched against a dependencies \c "name" part only. Any
204 * <tt>"op edition"</tt> part of a \ref Capability is \b not
205 * considered at all. \see \ref addDependency on how to query for
206 * capabilities including edition ranges.
208 * \note Solvables of a kind not supporting the specified attribute will
209 * <b>not</b> be returned.
210 * \todo check the above
212 * \param attr Attribute identfier. Use sat::Solvattr::* constants
213 * \param value What to search for.
217 void addAttribute( const sat::SolvAttr & attr, const std::string & value = "" );
219 /** \name Filter by dependencies matching a broken down capability <tt>name [op edition]</tt> and/or architecture.
221 * The capabilities \c name part may be defined as query string
222 * like with \ref addAttribute. Globing and regex are supported.
223 * Global query strings defined by \ref addString are considered.
225 * So without any <tt>op edition arch</tt> addDependency behaves the
226 * same as \ref addAttribute. If an edition range is given, matches
227 * are restricted accordingly. There are various overloads, so pick
228 * the one you like best.
230 * An optional \c arch argument will additionally require the matching
231 * solvable to be of this arch.
236 * setCaseSensitive( false );
237 * addDependency( sat::SolvAttr::provides, "kde*", Rel::EQ, Edition("2.0") );
238 * addDependency( sat::SolvAttr::provides, "kde*", Edition("2.0") ); // same as above
242 * setCaseSensitive( false );
243 * addString( "kde*" );
244 * addDependency( sat::SolvAttr::provides, Rel::EQ, Edition("2.0") );// same as above
245 * addDependency( sat::SolvAttr::provides, Edition("2.0") ); // same as above
249 * \note Thre's also a version of \ref addDependency provided, that takes a
250 * complete \ref Capability as argument. This always requires an exact match
251 * of the name part (as the resolver would do it).
253 * This is the list of valid dependency attributes:
256 * SolvAttr::obsoletes
257 * SolvAttr::conflicts
259 * SolvAttr::recommends
261 * SolvAttr::supplements
265 * \note <b>What happens if a non dependency attribute is passed?<\b>
266 * If an edition range is given, it is matched against the matching
267 * solvables edition instead. Without edition range it behaves the
268 * same as \ref addAttribute.
271 * // Find all packages providing "kernel > 2.0"
272 * addDependency( sat::SolvAttr::provides, "kernel", Rel::GT, Edition("2.0") );
274 * // // Find all packages named "kernel" and with edition "> 2.0"
275 * addDependency( sat::SolvAttr::name, "kernel", Rel::GT, Edition("2.0") );
279 /** Query <tt>"name|global op edition"</tt>. */
280 void addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition );
281 /** \overload also restricting architecture */
282 void addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition, const Arch & arch );
284 /** \overload Query <tt>"name|global == edition"</tt>. */
285 void addDependency( const sat::SolvAttr & attr, const std::string & name, const Edition & edition )
286 { addDependency( attr, name, Rel::EQ, edition ); }
287 /** \overload also restricting architecture */
288 void addDependency( const sat::SolvAttr & attr, const std::string & name, const Edition & edition, const Arch & arch )
289 { addDependency( attr, name, Rel::EQ, edition, arch ); }
291 /** \overload Query <tt>"name|global"</tt>. */
292 void addDependency( const sat::SolvAttr & attr, const std::string & name )
293 { addDependency( attr, name, Rel::ANY, Edition() ); }
294 /** \overload also restricting architecture */
295 void addDependency( const sat::SolvAttr & attr, const std::string & name, const Arch & arch )
296 { addDependency( attr, name, Rel::ANY, Edition(), arch ); }
298 /** \overload Query <tt>"global op edition"</tt>.*/
299 void addDependency( const sat::SolvAttr & attr, const Rel & op, const Edition & edition )
300 { addDependency( attr, std::string(), op, edition ); }
301 /** \overload also restricting architecture */
302 void addDependency( const sat::SolvAttr & attr, const Rel & op, const Edition & edition, const Arch & arch )
303 { addDependency( attr, std::string(), op, edition, arch ); }
305 /** \overload Query <tt>"global == edition"</tt>. */
306 void addDependency( const sat::SolvAttr & attr, const Edition & edition )
307 { addDependency( attr, std::string(), Rel::EQ, edition ); }
308 /** \overload also restricting architecture */
309 void addDependency( const sat::SolvAttr & attr, const Edition & edition, const Arch & arch )
310 { addDependency( attr, std::string(), Rel::EQ, edition, arch ); }
312 /** \overload Query <tt>"global"</tt>. */
313 void addDependency( const sat::SolvAttr & attr )
314 { addDependency( attr, std::string(), Rel::ANY, Edition() ); }
315 /** \overload also restricting architecture */
316 void addDependency( const sat::SolvAttr & attr, const Arch & arch )
317 { addDependency( attr, std::string(), Rel::ANY, Edition(), arch ); }
319 /** \overload Query taking a \ref Capability (always exact name match).
320 * \note If a non dependency attribute is passed, the \ref Capability
321 * will always be matched against the Solvables \c name and \c edition.
323 void addDependency( const sat::SolvAttr & attr, Capability cap_r );
327 * Set version condition. This will filter out solvables not matching
328 * <tt>solvableEdition \a op \a edition</tt>.
330 * \param edition Edition to look for.
331 * \param op Found-wanted relation operator.
333 void setEdition(const Edition & edition, const Rel & op = Rel::EQ);
335 /** \name Text Matching Options
336 * \note The implementation treats an empty search string as
337 * <it>"match always"</it>. So if you want to actually match
338 * an empty value, try <tt>( "^$", setMatchRegex )</tt>.
342 * Turn case sentitivity on or off (unsets or sets \ref SEARCH_NOCASE flag).
343 * PoolQuery defaults to case insensitive search unless this method
346 * \param value Whether to turn the case sensitivity on (default) or off.
348 void setCaseSensitive( bool value = true );
351 * If set (default), look at the full path when searching in filelists.
352 * Otherwise just match the the basenames.
353 * \see \ref Match::FILES
355 void setFilesMatchFullPath( bool value = true );
357 void setFilesMatchBasename( bool value = true )
358 { setFilesMatchFullPath( !value ); }
360 /** Set to match exact string instead of substring.*/
361 void setMatchExact();
362 /** Set to substring (the default). */
363 void setMatchSubstring();
364 /** Set to match globs. */
366 /** Set to use the query strings as regexes */
367 void setMatchRegex();
368 /** Set to match words (uses regex) */
370 //void setLocale(const Locale & locale);
374 * Require that all of the values set by addString or addAttribute
375 * match the values of respective attributes.
377 * \todo doesn't work yet, don't use this function
379 void setRequireAll( bool require_all = true );
385 /** Search strings added via addString() */
386 const StrContainer & strings() const;
388 * Map (map<SolvAttr, StrContainer>) of attribute values added via
389 * addAttribute(), addDep in string form */
390 const AttrRawStrMap & attributes() const;
392 const StrContainer & attribute(const sat::SolvAttr & attr) const;
394 const Kinds & kinds() const;
396 const StrContainer & repos() const;
398 const Edition edition() const;
399 const Rel editionRel() const;
402 * returns true if search is case sensitive
404 bool caseSensitive() const;
406 /** Whether searching in filelists looks at the full path or just at the basenames. */
407 bool filesMatchFullPath() const;
409 bool filesMatchBasename() const
410 { return !filesMatchFullPath(); }
412 bool matchExact() const;
413 bool matchSubstring() const;
414 bool matchGlob() const;
415 bool matchRegex() const;
416 bool matchWord() const;
418 /** Returns string matching mode as enum.
419 * \see \ref Match::Mode
421 Match::Mode matchMode() const
422 { return flags().mode(); }
425 * Whether all values added via addString() or addAttribute() are required
426 * to match the values of the respective attributes.
428 bool requireAll() const;
430 StatusFilter statusFilterFlags() const;
434 * Reads from stream query. Attributes is sepated by delim. Query is
435 * separated by two delim.
437 * \param str input stream which contains query
438 * \param delim delimeter for attributes
439 * \return true if non-empty query is recovered
441 * \see readPoolQueriesFromFile
443 bool recover( std::istream &str, char delim = '\n' );
446 * Writes a machine-readable string representation of the query to stream.
447 * Use \a delim as attribute delimiter.
449 * \param str output stream to write to
450 * \param delim delimiter for attributes
452 * \see writePoolQueriesToFile
454 void serialize( std::ostream &str, char delim = '\n' ) const;
456 /** Return a human-readable description of the query */
457 std::string asString() const;
459 bool operator==(const PoolQuery& b) const;
460 bool operator!=(const PoolQuery& b) const { return !(*this == b ); }
465 * Free function to get the satsolver repo search
473 * Free function to set the satsolver repo search
478 void setFlags( const Match & flags );
483 /** Pointer to implementation */
484 RW_pointer<Impl> _pimpl;
486 ///////////////////////////////////////////////////////////////////
488 /** \relates PoolQuery Stream output. */
489 std::ostream & operator<<( std::ostream & str, const PoolQuery & obj );
491 /** \relates PoolQuery Detailed stream output. */
492 std::ostream & dumpOn( std::ostream & str, const PoolQuery & obj );
494 ///////////////////////////////////////////////////////////////////
496 { /////////////////////////////////////////////////////////////////
498 class PoolQueryMatcher;
500 ///////////////////////////////////////////////////////////////////
502 // CLASS NAME : PoolQuery::PoolQueryIterator
504 /** \ref PoolQuery iterator as returned by \ref PoolQuery::begin.
506 * The \ref PoolQueryIterator visits sat::Solavables that do contain matches.
508 * But it also provides an iterator by itself, to allow a detailed inspection of
509 * the individual attribute matches within the current Solvable.
511 class PoolQueryIterator : public boost::iterator_adaptor<
512 PoolQueryIterator // Derived
513 , sat::LookupAttr::iterator // Base
514 , const sat::Solvable // Value
515 , boost::forward_traversal_tag // CategoryOrTraversal
516 , const sat::Solvable // Reference
519 typedef std::vector<sat::LookupAttr::iterator> Matches;
521 typedef Matches::size_type size_type;
522 typedef Matches::const_iterator matches_iterator;
524 /** Default ctor is also \c end.*/
528 /** \Ref PoolQuery ctor. */
529 PoolQueryIterator( const shared_ptr<PoolQueryMatcher> & matcher_r )
530 : _matcher( matcher_r )
533 /** \name Detailed inspection of attribute matches within the current Solvable.
535 * The \ref matches_iterator visits all attribute matches within the current Solvable,
536 * providing a \ref sat::LookupAttr::iterator pointing to attribute. While a
537 * \ref matches_iterator itself becomes invalid if the PoolQueryIterator is advanced,
538 * the \ref sat::LookupAttr::iterator it pointed to stays valid, even after the query
542 * // Setup query for "libzypp" in name or requires:
544 * q.addString( "libzypp" );
545 * q.setMatchSubstring();
546 * q.setCaseSensitive( false );
547 * q.addAttribute( sat::SolvAttr::name );
548 * q.addDependency( sat::SolvAttr::requires );
550 * // Iterate the result:
551 * for_( solvIter, q.begin(), q.end() )
553 * sat::Solvable solvable( *solvIter );
554 * cout << "Found matches in " << solvable << endl;
556 * for_( attrIter, solvIter.matchesBegin(), solvIter.matchesEnd() )
558 * sat::LookupAttr::iterator attr( *attrIter );
559 * cout << " " << attr.inSolvAttr() << "\t\"" << attr.asString() << "\"" << endl;
564 * Found matches in PackageKit-0.3.11-1.12.i586(@System)
565 * solvable:requires "libzypp.so.523"
566 * Found matches in libqdialogsolver1-1.2.6-1.1.2.i586(@System)
567 * solvable:requires "libzypp.so.523"
568 * solvable:requires "libzypp >= 5.25.3-0.1.2"
569 * Found matches in libzypp-5.30.3-0.1.1.i586(@System)
570 * solvable:name "libzypp"
571 * Found matches in libzypp-testsuite-tools-4.2.6-8.1.i586(@System)
572 * solvable:name "libzypp-testsuite-tools"
573 * solvable:requires "libzypp.so.523"
578 /** \c False unless this is the \c end iterator. */
579 bool matchesEmpty() const { return ! _matcher; }
580 /** Number of attribute matches. */
581 size_type matchesSize() const { return matches().size(); }
582 /** Begin of matches. */
583 matches_iterator matchesBegin() const { return matches().begin(); }
584 /** End of matches. */
585 matches_iterator matchesEnd() const { return matches().end(); }
589 friend class boost::iterator_core_access;
591 sat::Solvable dereference() const
592 { return base_reference().inSolvable(); }
597 const Matches & matches() const;
600 shared_ptr<PoolQueryMatcher> _matcher;
601 mutable shared_ptr<Matches> _matches;
603 ///////////////////////////////////////////////////////////////////
605 /** \relates PoolQueryIterator Stream output. */
606 inline std::ostream & operator<<( std::ostream & str, const PoolQueryIterator & obj )
607 { return str << obj.base(); }
609 /** \relates PoolQueryIterator Detailed stream output. */
610 std::ostream & dumpOn( std::ostream & str, const PoolQueryIterator & obj );
612 ///////////////////////////////////////////////////////////////////
614 ///////////////////////////////////////////////////////////////////
616 inline detail::PoolQueryIterator PoolQuery::end() const
617 { return detail::PoolQueryIterator(); }
619 /////////////////////////////////////////////////////////////////
621 ///////////////////////////////////////////////////////////////////
623 #endif // ZYPP_POOLQUERY_H