2eabbadf475c3d6d78cb718b3b86dfa16f34dce8
[platform/upstream/libzypp.git] / zypp / PoolQuery.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/PoolQuery.h
10  *
11 */
12 #ifndef ZYPP_POOLQUERY_H
13 #define ZYPP_POOLQUERY_H
14
15 #include <iosfwd>
16 #include <set>
17 #include <map>
18
19 #include "zypp/base/Regex.h"
20 #include "zypp/base/PtrTypes.h"
21 #include "zypp/base/Function.h"
22
23 #include "zypp/sat/SolvIterMixin.h"
24 #include "zypp/sat/LookupAttr.h"
25 #include "zypp/sat/AttrMatcher.h"
26 #include "zypp/sat/Pool.h"
27
28 ///////////////////////////////////////////////////////////////////
29 namespace zypp
30 { /////////////////////////////////////////////////////////////////
31
32   namespace detail
33   {
34     class PoolQueryIterator;
35   }
36
37   ///////////////////////////////////////////////////////////////////
38   //
39   //  CLASS NAME : PoolQuery
40   //
41   /**
42    * Meta-data query API. Returns solvables of specified kinds from specified
43    * repositories with attributes matching the specified search strings.
44    *
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).
50    *
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.
55    *
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.
61    *
62    * <code>
63    * PoolQuery q;
64    * q.addAttribute(sat::SolvAttr::name, "zypp*");
65    * q.addKind(ResKind::package);
66    * q.setMatchGlob();
67    *
68    * for (PoolQuery::Selectable_iterator it = q.selectableBegin();
69    *     it != q.selectableEnd(); ++it)
70    * {
71    *   ui::Selectable::constPtr s = *it;
72    *   // ...
73    * }
74    * </code>
75    *
76    * Performance considerations
77    *
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.
81    *
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.
85    *
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
89    */
90   class PoolQuery : public sat::SolvIterMixin<PoolQuery, detail::PoolQueryIterator>
91   {
92   public:
93     typedef std::set<ResKind>                               Kinds;
94     typedef std::set<std::string>                           StrContainer;
95     typedef std::map<sat::SolvAttr, StrContainer>           AttrRawStrMap;
96
97     typedef detail::PoolQueryIterator                       const_iterator;
98     typedef unsigned int                                    size_type;
99
100   public:
101     typedef function<bool( const sat::Solvable & )> ProcessResolvable;
102
103     PoolQuery();
104     ~PoolQuery();
105
106     /** Query result accessers. */
107     //@{
108     /**
109      * Compile the query and return an iterator to the result.
110      *
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
114      *         failed to compile.
115      *
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
119      */
120     const_iterator begin() const;
121
122     /** An iterator pointing to the end of the query result. */
123     const_iterator end() const;
124
125     /** Whether the result is empty. */
126     bool empty() const;
127
128     /** Number of solvables in the query result. */
129     size_type size() const;
130     //@}
131
132     /**
133      * Executes the query with the current settings.
134      * Results are yielded via the \a fnc callback.
135      */
136     void execute(ProcessResolvable fnc);
137
138     /**
139      * Filter by selectable kind.
140      *
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).
143      *
144      * Pass ResKind constants to this method, (e.g. ResKind::package).
145      */
146     void addKind(const ResKind & kind);
147
148     /**
149      * Filter by repo.
150      *
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).
153      */
154     void addRepo(const std::string &repoalias);
155
156     /** Installed status filter setters. */
157     //@{
158
159     /**
160      * Filter by status (installed uninstalled)
161      */
162     enum StatusFilter {
163       ALL = 0, // both install filter and uninstall filter bits are 0
164       INSTALLED_ONLY = 1,
165       UNINSTALLED_ONLY = 2
166     };
167
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 );
174
175     //@}
176
177     /**
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
180      * for all of them.
181      *
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.
187      */
188     void addString(const std::string & value);
189
190     /**
191      * Filter by the \a value of the specified \a attr attribute. This can
192      * be any of the available solvable attributes.
193      *
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()
199      * method.
200      *
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.
207      *
208      * \note Solvables of a kind not supporting the specified attribute will
209      * <b>not</b> be returned.
210      * \todo check the above
211      *
212      * \param attr Attribute identfier. Use sat::Solvattr::* constants
213      * \param value What to search for.
214      *
215      * \see sat::SolvAttr
216      */
217     void addAttribute( const sat::SolvAttr & attr, const std::string & value = "" );
218
219     /** \name Filter by dependencies matching a broken down capability <tt>name [op edition]</tt> and/or architecture.
220      *
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.
224      *
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.
229      *
230      * An optional \c arch argument will additionally require the matching
231      * solvable to be of this arch.
232      *
233      * \code
234      * {
235      *   setMatchGlob();
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
239      * }
240      * {
241      *   setMatchGlob();
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
246      * }
247      * \endcode
248      *
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).
252      *
253      * This is the list of valid dependency attributes:
254      * \code
255      *   SolvAttr::provides
256      *   SolvAttr::obsoletes
257      *   SolvAttr::conflicts
258      *   SolvAttr::requires
259      *   SolvAttr::recommends
260      *   SolvAttr::suggests
261      *   SolvAttr::supplements
262      *   SolvAttr::enhances
263      * \endcode
264      *
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.
269      *
270      * \code
271      *   // Find all packages providing "kernel > 2.0"
272      *   addDependency( sat::SolvAttr::provides, "kernel", Rel::GT, Edition("2.0") );
273      *
274      *   // // Find all packages named "kernel" and with edition "> 2.0"
275      *   addDependency( sat::SolvAttr::name, "kernel", Rel::GT, Edition("2.0") );
276      * \endcode
277      */
278     //@{
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 );
283
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 ); }
290
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 ); }
297
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 ); }
304
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 ); }
311
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 ); }
318
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.
322     */
323     void addDependency( const sat::SolvAttr & attr, Capability cap_r );
324     //@}
325
326     /**
327      * Set version condition. This will filter out solvables not matching
328      * <tt>solvableEdition \a op \a edition</tt>.
329      *
330      * \param edition Edition to look for.
331      * \param op      Found-wanted relation operator.
332      */
333     void setEdition(const Edition & edition, const Rel & op = Rel::EQ);
334
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>.
339      */
340     //@{
341     /**
342      * Turn case sentitivity on or off (unsets or sets \ref SEARCH_NOCASE flag).
343      * PoolQuery defaults to case insensitive search unless this method
344      * is used.
345      *
346      * \param value Whether to turn the case sensitivity on (default) or off.
347      */
348     void setCaseSensitive( bool value = true );
349
350     /**
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
354      */
355     void setFilesMatchFullPath( bool value = true );
356     /** \overload */
357     void setFilesMatchBasename( bool value = true )
358     { setFilesMatchFullPath( !value ); }
359
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. */
365     void setMatchGlob();
366     /** Set to use the query strings as regexes */
367     void setMatchRegex();
368     /** Set to match words (uses regex) */
369     void setMatchWord();
370     //void setLocale(const Locale & locale);
371     //@}
372
373     /**
374      * Require that all of the values set by addString or addAttribute
375      * match the values of respective attributes.
376      *
377      * \todo doesn't work yet, don't use this function
378      */
379     void setRequireAll( bool require_all = true );
380
381
382     /** \name getters */
383     //@{
384
385     /** Search strings added via addString() */
386     const StrContainer & strings() const;
387     /**
388      * Map (map<SolvAttr, StrContainer>) of attribute values added via
389      * addAttribute(), addDep in string form */
390     const AttrRawStrMap & attributes() const;
391
392     const StrContainer & attribute(const sat::SolvAttr & attr) const;
393
394     const Kinds & kinds() const;
395
396     const StrContainer & repos() const;
397
398     const Edition edition() const;
399     const Rel editionRel() const;
400
401     /**
402      * returns true if search is case sensitive
403      */
404     bool caseSensitive() const;
405
406     /** Whether searching in filelists looks at the full path or just at the basenames. */
407     bool filesMatchFullPath() const;
408     /** \overload */
409     bool filesMatchBasename() const
410     { return !filesMatchFullPath(); }
411
412     bool matchExact() const;
413     bool matchSubstring() const;
414     bool matchGlob() const;
415     bool matchRegex() const;
416     bool matchWord() const;
417
418     /** Returns string matching mode as enum.
419      * \see \ref Match::Mode
420      */
421     Match::Mode matchMode() const
422     { return flags().mode(); }
423
424     /**
425      * Whether all values added via addString() or addAttribute() are required
426      * to match the values of the respective attributes.
427      */
428     bool requireAll() const;
429
430     StatusFilter statusFilterFlags() const;
431     //@}
432
433     /**
434      * Reads from stream query. Attributes is sepated by delim. Query is
435      * separated by two delim.
436      *
437      * \param str input stream which contains query
438      * \param delim delimeter for attributes
439      * \return true if non-empty query is recovered
440      *
441      * \see readPoolQueriesFromFile
442      */
443     bool recover( std::istream &str, char delim = '\n' );
444
445     /**
446      * Writes a machine-readable string representation of the query to stream.
447      * Use \a delim as attribute delimiter.
448      *
449      * \param str output stream to write to
450      * \param delim delimiter for attributes
451      *
452      * \see writePoolQueriesToFile
453      */
454     void serialize( std::ostream &str, char delim = '\n' ) const;
455
456     /** Return a human-readable description of the query */
457     std::string asString() const;
458
459     bool operator==(const PoolQuery& b) const;
460     bool operator!=(const PoolQuery& b) const { return !(*this == b ); }
461
462     // low level API
463
464     /**
465      * Free function to get the satsolver repo search
466      * flags.
467      *
468      * \see \ref Match
469      */
470     Match flags() const;
471
472     /**
473      * Free function to set the satsolver repo search
474      * flags.
475      *
476      * \see \ref Match
477      */
478     void setFlags( const Match & flags );
479
480   public:
481     class Impl;
482   private:
483     /** Pointer to implementation */
484     RW_pointer<Impl> _pimpl;
485   };
486   ///////////////////////////////////////////////////////////////////
487
488   /** \relates PoolQuery Stream output. */
489   std::ostream & operator<<( std::ostream & str, const PoolQuery & obj );
490
491   /** \relates PoolQuery Detailed stream output. */
492   std::ostream & dumpOn( std::ostream & str, const PoolQuery & obj );
493
494   ///////////////////////////////////////////////////////////////////
495   namespace detail
496   { /////////////////////////////////////////////////////////////////
497
498   class PoolQueryMatcher;
499
500   ///////////////////////////////////////////////////////////////////
501   //
502   //  CLASS NAME : PoolQuery::PoolQueryIterator
503   //
504   /** \ref PoolQuery iterator as returned by \ref PoolQuery::begin.
505    *
506    * The \ref PoolQueryIterator visits sat::Solavables that do contain matches.
507    *
508    * But it also provides an iterator by itself, to allow a detailed inspection of
509    * the individual attribute matches within the current Solvable.
510    */
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
517   >
518   {
519       typedef std::vector<sat::LookupAttr::iterator> Matches;
520     public:
521       typedef Matches::size_type size_type;
522       typedef Matches::const_iterator matches_iterator;
523     public:
524       /** Default ctor is also \c end.*/
525       PoolQueryIterator()
526       {}
527
528       /** \Ref PoolQuery ctor. */
529       PoolQueryIterator( const shared_ptr<PoolQueryMatcher> & matcher_r )
530       : _matcher( matcher_r )
531       { increment(); }
532
533       /** \name Detailed inspection of attribute matches within the current Solvable.
534        *
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
539        * ended.
540        *
541        * \code
542        * // Setup query for "libzypp"  in name or requires:
543        * PoolQuery q;
544        * q.addString( "libzypp" );
545        * q.setMatchSubstring();
546        * q.setCaseSensitive( false );
547        * q.addAttribute( sat::SolvAttr::name );
548        * q.addDependency( sat::SolvAttr::requires );
549        *
550        * // Iterate the result:
551        * for_( solvIter, q.begin(), q.end() )
552        * {
553        *   sat::Solvable solvable( *solvIter );
554        *   cout << "Found matches in " << solvable << endl;
555        *   if ( verbose )
556        *     for_( attrIter, solvIter.matchesBegin(), solvIter.matchesEnd() )
557        *     {
558        *       sat::LookupAttr::iterator attr( *attrIter );
559        *       cout << "    " << attr.inSolvAttr() << "\t\"" << attr.asString() << "\"" << endl;
560        *     }
561        * }
562        *
563        *
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"
574        * ...
575        * \endcode
576        */
577       //@{
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(); }
586       //@}
587
588     private:
589       friend class boost::iterator_core_access;
590
591       sat::Solvable dereference() const
592       { return base_reference().inSolvable(); }
593
594       void increment();
595
596     private:
597       const Matches & matches() const;
598
599     private:
600       shared_ptr<PoolQueryMatcher> _matcher;
601       mutable shared_ptr<Matches>  _matches;
602   };
603   ///////////////////////////////////////////////////////////////////
604
605   /** \relates PoolQueryIterator Stream output. */
606   inline std::ostream & operator<<( std::ostream & str, const PoolQueryIterator & obj )
607   { return str << obj.base(); }
608
609   /** \relates PoolQueryIterator Detailed stream output. */
610   std::ostream & dumpOn( std::ostream & str, const PoolQueryIterator & obj );
611
612   ///////////////////////////////////////////////////////////////////
613   } //namespace detail
614   ///////////////////////////////////////////////////////////////////
615
616   inline detail::PoolQueryIterator PoolQuery::end() const
617   { return detail::PoolQueryIterator(); }
618
619   /////////////////////////////////////////////////////////////////
620 } // namespace zypp
621 ///////////////////////////////////////////////////////////////////
622
623 #endif // ZYPP_POOLQUERY_H