libzypp  17.7.0
PoolQuery.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
13 #include <sstream>
14 
15 #include "zypp/base/Gettext.h"
16 #include "zypp/base/LogTools.h"
17 #include "zypp/base/Algorithm.h"
18 #include "zypp/base/String.h"
20 #include "zypp/RelCompare.h"
21 
22 #include "zypp/sat/Pool.h"
23 #include "zypp/sat/Solvable.h"
24 #include "zypp/base/StrMatcher.h"
25 
26 #include "zypp/PoolQuery.h"
27 
28 #undef ZYPP_BASE_LOGGER_LOGGROUP
29 #define ZYPP_BASE_LOGGER_LOGGROUP "PoolQuery"
30 
31 using namespace std;
32 using namespace zypp::sat;
33 
35 namespace zypp
36 {
37 
39  namespace
40  {
41 
43  // some Helpers and Predicates
45 
46  bool isDependencyAttribute( sat::SolvAttr attr_r )
47  {
48  static sat::SolvAttr deps[] = {
49  SolvAttr::provides,
50  SolvAttr::requires,
51  SolvAttr::recommends,
52  SolvAttr::obsoletes,
53  SolvAttr::conflicts,
54  SolvAttr::suggests,
55  SolvAttr::supplements,
56  SolvAttr::enhances,
57  };
58  for_( it, arrayBegin(deps), arrayEnd(deps) )
59  if ( *it == attr_r )
60  return true;
61  return false;
62  }
63 
68  struct EditionRangePredicate
69  {
70  EditionRangePredicate( const Rel & op, const Edition & edition )
71  : _range( op, edition )
72  , _arch( Arch_empty )
73  {}
74  EditionRangePredicate( const Rel & op, const Edition & edition, const Arch & arch )
75  : _range( op, edition )
76  , _arch( arch )
77  {}
78 
79  bool operator()( sat::LookupAttr::iterator iter_r )
80  {
81  if ( !_arch.empty() && iter_r.inSolvable().arch() != _arch )
82  return false;
83 
84  CapDetail cap( iter_r.id() );
85  if ( ! cap.isSimple() )
86  return false;
87  if ( cap.isNamed() ) // no range to match
88  return true;
89  return overlaps( Edition::MatchRange( cap.op(), cap.ed() ), _range );
90  }
91 
92  std::string serialize() const
93  {
94  std::string ret( "EditionRange" );
95  str::appendEscaped( ret, _range.op.asString() );
96  str::appendEscaped( ret, _range.value.asString() );
97  str::appendEscaped( ret, _arch.asString() );
98  return ret;
99  }
100 
101  Edition::MatchRange _range;
102  Arch _arch;
103  };
104 
106  struct SolvableRangePredicate
107  {
108  SolvableRangePredicate( const Rel & op, const Edition & edition )
109  : _range( op, edition )
110  , _arch( Arch_empty )
111  {}
112 
113  SolvableRangePredicate( const Rel & op, const Edition & edition, const Arch & arch )
114  : _range( op, edition )
115  , _arch( arch )
116  {}
117 
118  bool operator()( sat::LookupAttr::iterator iter_r )
119  {
120  if ( !_arch.empty() && iter_r.inSolvable().arch() != _arch )
121  return false;
122  return overlaps( Edition::MatchRange( Rel::EQ, iter_r.inSolvable().edition() ), _range );
123  }
124 
125  std::string serialize() const
126  {
127  std::string ret( "SolvableRange" );
128  str::appendEscaped( ret, _range.op.asString() );
129  str::appendEscaped( ret, _range.value.asString() );
130  str::appendEscaped( ret, _arch.asString() );
131  return ret;
132  }
133 
134  Edition::MatchRange _range;
135  Arch _arch;
136  };
137 
142  struct CapabilityMatchPredicate
143  {
144  CapabilityMatchPredicate( Capability cap_r )
145  : _cap( cap_r )
146  {}
147 
148  bool operator()( sat::LookupAttr::iterator iter_r ) const
149  {
150  return _cap.matches( iter_r.asType<Capability>() ) == CapMatch::yes;
151  }
152 
153  std::string serialize() const
154  {
155  std::string ret( "CapabilityMatch" );
156  str::appendEscaped( ret, _cap.asString() );
157  return ret;
158  }
159 
160  Capability _cap;
161  };
162 
164  //
166 
191  struct AttrMatchData
192  {
193  typedef function<bool(sat::LookupAttr::iterator)> Predicate;
194 
195  static bool always( sat::LookupAttr::iterator ) { return true; }
196  static bool never( sat::LookupAttr::iterator ) { return false; }
197 
198  AttrMatchData()
199  {}
200 
201  AttrMatchData( sat::SolvAttr attr_r )
202  : attr( attr_r )
203  {}
204 
205  AttrMatchData( sat::SolvAttr attr_r, const StrMatcher & strMatcher_r )
206  : attr( attr_r )
207  , strMatcher( strMatcher_r )
208  {}
209 
210  AttrMatchData( sat::SolvAttr attr_r, const StrMatcher & strMatcher_r,
211  const Predicate & predicate_r, const std::string & predicateStr_r )
212  : attr( attr_r )
213  , strMatcher( strMatcher_r )
214  , predicate( predicate_r )
215  , predicateStr( predicateStr_r )
216  {}
217 
223  template<class TPredicate>
224  void addPredicate( const TPredicate & predicate_r )
225  {
226  predicate = predicate_r;
227  predicateStr = predicate_r.serialize();
228  }
229 
235  std::string serialize() const
236  {
237  std::string ret( "AttrMatchData" );
238  str::appendEscaped( ret, attr.asString() );
239  str::appendEscaped( ret, strMatcher.searchstring() );
240  str::appendEscaped( ret, serializeMode( strMatcher.flags().mode() ) );
242  return ret;
243  }
244 
248  static AttrMatchData deserialize( const std::string & str_r )
249  {
250  std::vector<std::string> words;
251  str::splitEscaped( str_r, std::back_inserter(words) );
252  if ( words.empty() || words[0] != "AttrMatchData" )
253  ZYPP_THROW( Exception( str::Str() << "Expecting AttrMatchData: " << str_r ) );
254  if ( words.size() != 5 )
255  ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) );
256 
257  AttrMatchData ret;
258  ret.attr = sat::SolvAttr( words[1] );
259  ret.strMatcher = StrMatcher( words[2] );
260  if ( Match::Mode mode = deserializeMode( words[3] ) )
261  ret.strMatcher.setFlags( mode );
262  ret.predicateStr = words[4];
263 
264  // now the predicate
265  words.clear();
266  str::splitEscaped( ret.predicateStr, std::back_inserter(words) );
267  if ( ! words.empty() )
268  {
269  if ( words[0] == "EditionRange" )
270  {
271  switch( words.size() )
272  {
273  case 3:
274  ret.predicate = EditionRangePredicate( Rel(words[1]), Edition(words[2]) );
275  break;
276  case 4:
277  ret.predicate = EditionRangePredicate( Rel(words[1]), Edition(words[2]), Arch(words[3]) );
278  break;
279  default:
280  ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) );
281  break;
282  }
283  }
284  else if ( words[0] == "SolvableRange" )
285  {
286  switch( words.size() )
287  {
288  case 3:
289  ret.predicate = SolvableRangePredicate( Rel(words[1]), Edition(words[2]) );
290  break;
291  case 4:
292  ret.predicate = SolvableRangePredicate( Rel(words[1]), Edition(words[2]), Arch(words[3]) );
293  break;
294  default:
295  ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) );
296  break;
297  }
298  }
299  else if ( words[0] == "CapabilityMatch" )
300  {
301  if ( words.size() != 2 )
302  ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) );
303  ret.predicate = CapabilityMatchPredicate( Capability(words[1]) );
304  }
305  else
306  ZYPP_THROW( Exception( str::Str() << "Unknown predicate: " << str_r ) );
307  }
308  return ret;
309  }
310 
311  sat::SolvAttr attr;
312  StrMatcher strMatcher;
313  Predicate predicate;
314  std::string predicateStr;
315  ResKind kindPredicate = ResKind::nokind; // holds the 'kind' part if SolvAttr:name looks for an explicit 'kind:name'
316 
317  private:
319  static std::string serializeMode( Match::Mode mode_r )
320  {
321  // Legacy code used "[C|X]" to differ just between OTHER (need to (C)ompile) and
322  // using the default search mode. As we now allow to specify a SEARCHMODE we
323  // need to serialize it:
324  switch ( mode_r )
325  {
326 #define OUTS(M,S) case Match::M: return #S; break
327  // (C)ompile
328  OUTS( OTHER, C );
329  // well known modes:
330  OUTS( STRING, T );
331  OUTS( STRINGSTART, S );
332  OUTS( STRINGEND, E );
333  OUTS( SUBSTRING, B );
334  OUTS( GLOB, G );
335  OUTS( REGEX, R );
336 #undef OUTS
337  // everything else use default
338  case Match::NOTHING:
339  break;
340  }
341  return "X";
342  }
343 
345  static Match::Mode deserializeMode( const std::string & str_r )
346  {
347  switch ( str_r[0] )
348  {
349 #define OUTS(M,C) case *#C: return Match::M; break
350  // (C)ompile
351  OUTS( OTHER, C );
352  // well known modes:
353  OUTS( STRING, T );
354  OUTS( STRINGSTART, S );
355  OUTS( STRINGEND, E );
356  OUTS( SUBSTRING, B );
357  OUTS( GLOB, G );
358  OUTS( REGEX, R );
359 #undef OUTS
360  // everything else use default
361  default:
362  break;
363  }
364  return Match::NOTHING;
365  }
366  };
367 
369  inline std::ostream & operator<<( std::ostream & str, const AttrMatchData & obj )
370  {
371  str << obj.attr << ": " << obj.strMatcher;
372  if ( obj.kindPredicate )
373  str << " +(" << obj.kindPredicate << ")";
374  if ( obj.predicate )
375  str << " +(" << obj.predicateStr << ")";
376  return str;
377  }
378 
380  inline bool operator==( const AttrMatchData & lhs, const AttrMatchData & rhs )
381  {
382  return ( lhs.attr == rhs.attr
383  && lhs.strMatcher == rhs.strMatcher
384  && lhs.predicateStr == rhs.predicateStr );
385  }
386 
388  inline bool operator!=( const AttrMatchData & lhs, const AttrMatchData & rhs )
389  { return !( lhs == rhs ); }
390 
392  inline bool operator<( const AttrMatchData & lhs, const AttrMatchData & rhs )
393  {
394  if ( lhs.attr != rhs.attr )
395  return ( lhs.attr < rhs.attr );
396  if ( lhs.strMatcher != rhs.strMatcher )
397  return ( lhs.strMatcher < rhs.strMatcher );
398  if ( lhs.predicateStr != rhs.predicateStr )
399  return ( lhs.predicateStr < rhs.predicateStr );
400  return false;
401  }
402 
403  typedef std::list<AttrMatchData> AttrMatchList;
404 
405 
406  }
407  // namespace
409 
411  //
412  // CLASS NAME : PoolQuery::Impl
413  //
416  {
417  public:
419  : _flags( Match::SUBSTRING | Match::NOCASE | Match::SKIP_KIND )
420  , _match_word(false)
421  , _require_all(false)
422  , _status_flags(ALL)
423  {}
424 
426  {}
427 
428  public:
430  string asString() const;
431 
439  std::set<AttrMatchData> _uncompiledPredicated;
440 
445 
448 
453 
456 
460 
461  public:
462 
463  bool operator<( const PoolQuery::Impl & rhs ) const
464  {
465 #define OUTS(A) if ( A != rhs.A ) return A < rhs.A;
466  OUTS( _strings );
467  OUTS( _attrs );
468  OUTS( _uncompiledPredicated );
469  OUTS( _flags.get() );
470  OUTS( _match_word );
471  OUTS( _require_all );
472  OUTS( _status_flags );
473  OUTS( _edition );
474  OUTS( _op.inSwitch() );
475  OUTS( _repos );
476  OUTS( _kinds );
477 #undef OUTS
478  return false;
479  }
480 
481  bool operator==( const PoolQuery::Impl & rhs ) const
482  {
483  if ( _flags == rhs._flags
484  // bnc#792901: while libzypp uses exact match mode for a single
485  // package name lock, zypper always uses glob. :(
486  // We unify those two forms to enable zypper to remove zypp locks
487  // without need to actually evaluate the query (which would require
488  // repos to be loaded).
489  || ( ( ( _flags.isModeString() && rhs._flags.isModeGlob() )
490  || ( _flags.isModeGlob() && rhs._flags.isModeString() ) )
491  && _strings.empty()
492  && _attrs.size() == 1
493  && _attrs.begin()->first == sat::SolvAttr::name ) )
494  {
495  return ( _strings == rhs._strings
496  && _attrs == rhs._attrs
497  && _uncompiledPredicated == rhs._uncompiledPredicated
498  && _match_word == rhs._match_word
499  && _require_all == rhs._require_all
500  && _status_flags == rhs._status_flags
501  && _edition == rhs._edition
502  && _op == rhs._op
503  && _repos == rhs._repos
504  && _kinds == rhs._kinds );
505  }
506  return false;
507  }
508 
509  bool operator!=( const PoolQuery::Impl & rhs ) const
510  { return ! operator==( rhs ); }
511 
512  public:
517  void compile() const;
518 
520  mutable AttrMatchList _attrMatchList;
521 
522  private:
524  string createRegex( const StrContainer & container, const Match & flags ) const;
525 
526  private:
527  friend Impl * rwcowClone<Impl>( const Impl * rhs );
529  Impl * clone() const
530  { return new Impl( *this ); }
531  };
532 
534 
535  struct MyInserter
536  {
537  MyInserter(PoolQuery::StrContainer & cont) : _cont(cont) {}
538 
539  bool operator()(const string & str)
540  {
541  _cont.insert(str);
542  return true;
543  }
544 
546  };
547 
548 
549  struct EmptyFilter
550  {
551  bool operator()(const string & str)
552  {
553  return !str.empty();
554  }
555  };
556 
557  void PoolQuery::Impl::compile() const
558  {
559  _attrMatchList.clear();
560 
561  Match cflags( _flags );
562  if ( cflags.mode() == Match::OTHER ) // this will never succeed...
564 
566  string rcstrings;
567 
568 
569  // 'different' - will have to iterate through all and match by ourselves (slow)
570  // 'same' - will pass the compiled string to dataiterator_init
571  // 'one-attr' - will pass it to dataiterator_init
572  // 'one-non-regex-str' - will pass to dataiterator_init, set flag to SEARCH_STRING or SEARCH_SUBSTRING
573 
574  // // NO ATTRIBUTE
575  // else
576  // for all _strings
577  // create regex; store in rcstrings; if more strings flag regex;
578  if (_attrs.empty())
579  {
580  ; // A default 'query-all' will be added after all sources are processed.
581  }
582 
583  // // ONE ATTRIBUTE
584  // else if _attrs is not empty but it contains just one attr
585  // for all _strings and _attr[key] strings
586  // create regex; flag 'one-attr'; if more strings flag regex;
587  else if (_attrs.size() == 1)
588  {
589  StrContainer joined;
590  invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
591  invokeOnEach(_attrs.begin()->second.begin(), _attrs.begin()->second.end(), EmptyFilter(), MyInserter(joined));
592  rcstrings = createRegex(joined, cflags);
593  if (joined.size() > 1) // switch to regex for multiple strings
594  cflags.setModeRegex();
595  _attrMatchList.push_back( AttrMatchData( _attrs.begin()->first,
596  StrMatcher( rcstrings, cflags ) ) );
597  }
598 
599  // // MULTIPLE ATTRIBUTES
600  else
601  {
602  // check whether there are any per-attribute strings
603  bool attrvals_empty = true;
604  for (AttrRawStrMap::const_iterator ai = _attrs.begin(); ai != _attrs.end(); ++ai)
605  if (!ai->second.empty())
606  for(StrContainer::const_iterator it = ai->second.begin();
607  it != ai->second.end(); it++)
608  if (!it->empty())
609  {
610  attrvals_empty = false;
611  goto attremptycheckend;
612  }
613 attremptycheckend:
614 
615  // chceck whether the per-attribute strings are all the same
616  bool attrvals_thesame = true;
617  AttrRawStrMap::const_iterator ai = _attrs.begin();
618  const StrContainer & set1 = ai->second;
619  ++ai;
620  for (; ai != _attrs.end(); ++ai)
621  {
622  StrContainer result;
623  set_difference(
624  set1.begin(), set1.end(),
625  ai->second.begin(), ai->second.end(),
626  inserter(result, result.begin())/*, ltstr()*/);
627  if (!result.empty())
628  {
629  attrvals_thesame = false;
630  break;
631  }
632  }
633 
634  // // THE SAME STRINGS FOR DIFFERENT ATTRS
635  // else if _attrs is not empty but it does not contain strings
636  // for each key in _attrs take all _strings
637  // create regex; store in rcstrings; flag 'same'; if more strings flag regex;
638  if (attrvals_empty || attrvals_thesame)
639  {
640  StrContainer joined;
641  if (attrvals_empty)
642  {
643  invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
644  rcstrings = createRegex(joined, cflags);
645  }
646  else
647  {
648  invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
649  invokeOnEach(_attrs.begin()->second.begin(), _attrs.begin()->second.end(), EmptyFilter(), MyInserter(joined));
650  rcstrings = createRegex(joined, cflags);
651  }
652  if (joined.size() > 1) // switch to regex for multiple strings
653  cflags.setModeRegex();
654  // May use the same StrMatcher for all
655  StrMatcher matcher( rcstrings, cflags );
656  for_( ai, _attrs.begin(), _attrs.end() )
657  {
658  _attrMatchList.push_back( AttrMatchData( ai->first, matcher ) );
659  }
660  }
661 
662  // // DIFFERENT STRINGS FOR DIFFERENT ATTRS
663  // if _attrs is not empty and it contains non-empty vectors with non-empty strings
664  // for each key in _attrs take all _strings + all _attrs[key] strings
665  // create regex; flag 'different'; if more strings flag regex;
666  else
667  {
668  for_(ai, _attrs.begin(), _attrs.end())
669  {
670  StrContainer joined;
671  invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
672  invokeOnEach(ai->second.begin(), ai->second.end(), EmptyFilter(), MyInserter(joined));
673  string s = createRegex(joined, cflags);
674  if (joined.size() > 1) // switch to regex for multiple strings
675  cflags.setModeRegex();
676  _attrMatchList.push_back( AttrMatchData( ai->first,
677  StrMatcher( s, cflags ) ) );
678  }
679  }
680  }
681 
682  // Now handle any predicated queries
683  if ( ! _uncompiledPredicated.empty() )
684  {
685  StrContainer global;
686  invokeOnEach( _strings.begin(), _strings.end(), EmptyFilter(), MyInserter(global) );
687  for_( it, _uncompiledPredicated.begin(), _uncompiledPredicated.end() )
688  {
689  if ( it->strMatcher.flags().mode() == Match::OTHER )
690  {
691  // need to compile:
692  StrContainer joined( global );
693  const std::string & mstr( it->strMatcher.searchstring() );
694  if ( ! mstr.empty() )
695  joined.insert( mstr );
696 
697  cflags = _flags;
698  rcstrings = createRegex( joined, cflags );
699  if ( joined.size() > 1 ) // switch to regex for multiple strings
700  cflags.setModeRegex();
701 
702  // copy and exchange the StrMatcher
703  AttrMatchData nattr( *it );
704  nattr.strMatcher = StrMatcher( rcstrings, cflags ),
705  _attrMatchList.push_back( std::move(nattr) );
706  }
707  else
708  {
709  // copy matcher
710  _attrMatchList.push_back( *it );
711  }
712  }
713  }
714 
715  // If no attributes defined at all, then add 'query all'
716  if ( _attrMatchList.empty() )
717  {
718  cflags = _flags;
719  rcstrings = createRegex( _strings, cflags );
720  if ( _strings.size() > 1 ) // switch to regex for multiple strings
721  cflags.setModeRegex();
722  _attrMatchList.push_back( AttrMatchData( sat::SolvAttr::allAttr,
723  StrMatcher( rcstrings, cflags ) ) );
724  }
725 
726  // Finally check here, whether all involved regex compile.
727  for_( it, _attrMatchList.begin(), _attrMatchList.end() )
728  {
729  it->strMatcher.compile(); // throws on error
730  }
731  //DBG << asString() << endl;
732  }
733 
734 
738  static string wildcards2regex(const string & str)
739  {
740  string regexed = str;
741 
742  string r_all(".*"); // regex equivalent of '*'
743  string r_one("."); // regex equivalent of '?'
744  string::size_type pos;
745 
746  // replace all "*" in input with ".*"
747  for (pos = 0; (pos = regexed.find("*", pos)) != std::string::npos; pos+=2)
748  regexed = regexed.replace(pos, 1, r_all);
749 
750  // replace all "?" in input with "."
751  for (pos = 0; (pos = regexed.find('?', pos)) != std::string::npos; ++pos)
752  regexed = regexed.replace(pos, 1, r_one);
753 
754  return regexed;
755  }
756 
757  string PoolQuery::Impl::createRegex( const StrContainer & container, const Match & flags ) const
758  {
760 #define WB (_match_word ? string("\\b") : string())
761  string rstr;
762 
763  if (container.empty())
764  return rstr;
765 
766  if (container.size() == 1)
767  {
768  return WB + *container.begin() + WB;
769  }
770 
771  // multiple strings
772 
773  bool use_wildcards = flags.isModeGlob();
774  StrContainer::const_iterator it = container.begin();
775  string tmp;
776 
777  if (use_wildcards)
778  tmp = wildcards2regex(*it);
779  else
780  tmp = *it;
781 
782  if (_require_all)
783  {
784  if ( ! flags.isModeString() ) // not match exact
785  tmp += ".*" + WB + tmp;
786  rstr = "(?=" + tmp + ")";
787  }
788  else
789  {
790  if ( flags.isModeString() || flags.isModeGlob() )
791  rstr = "^";
792  rstr += WB + "(" + tmp;
793  }
794 
795  ++it;
796 
797  for (; it != container.end(); ++it)
798  {
799  if (use_wildcards)
800  tmp = wildcards2regex(*it);
801  else
802  tmp = *it;
803 
804  if (_require_all)
805  {
806  if ( ! flags.isModeString() ) // not match exact
807  tmp += ".*" + WB + tmp;
808  rstr += "(?=" + tmp + ")";
809  }
810  else
811  {
812  rstr += "|" + tmp;
813  }
814  }
815 
816  if (_require_all)
817  {
818  if ( ! flags.isModeString() ) // not match exact
819  rstr += WB + ".*";
820  }
821  else
822  {
823  rstr += ")" + WB;
824  if ( flags.isModeString() || flags.isModeGlob() )
825  rstr += "$";
826  }
827 
828  return rstr;
829 #undef WB
830  }
831 
833  {
834  ostringstream o;
835 
836  o << "kinds: ";
837  if ( _kinds.empty() )
838  o << "ALL";
839  else
840  {
841  for(Kinds::const_iterator it = _kinds.begin();
842  it != _kinds.end(); ++it)
843  o << *it << " ";
844  }
845  o << endl;
846 
847  o << "repos: ";
848  if ( _repos.empty() )
849  o << "ALL";
850  else
851  {
852  for(StrContainer::const_iterator it = _repos.begin();
853  it != _repos.end(); ++it)
854  o << *it << " ";
855  }
856  o << endl;
857 
858  o << "version: "<< _op << " " << _edition.asString() << endl;
859  o << "status: " << ( _status_flags ? ( _status_flags == INSTALLED_ONLY ? "INSTALLED_ONLY" : "UNINSTALLED_ONLY" )
860  : "ALL" ) << endl;
861 
862  o << "string match flags: " << Match(_flags) << endl;
863 
864  // raw
865  o << "strings: ";
866  for(StrContainer::const_iterator it = _strings.begin();
867  it != _strings.end(); ++it)
868  o << *it << " ";
869  o << endl;
870 
871  o << "attributes: " << endl;
872  for(AttrRawStrMap::const_iterator ai = _attrs.begin(); ai != _attrs.end(); ++ai)
873  {
874  o << "* " << ai->first << ": ";
875  for(StrContainer::const_iterator vi = ai->second.begin();
876  vi != ai->second.end(); ++vi)
877  o << *vi << " ";
878  o << endl;
879  }
880 
881  o << "predicated: " << endl;
882  for_( it, _uncompiledPredicated.begin(), _uncompiledPredicated.end() )
883  {
884  o << "* " << *it << endl;
885  }
886 
887  // compiled
888  o << "last attribute matcher compiled: " << endl;
889  if ( _attrMatchList.empty() )
890  {
891  o << "not yet compiled" << endl;
892  }
893  else
894  {
895  for_( it, _attrMatchList.begin(), _attrMatchList.end() )
896  {
897  o << "* " << *it << endl;
898  }
899  }
900  return o.str();
901  }
902 
904 
906  //
907  // CLASS NAME : PoolQuery
908  //
910 
911  PoolQuery::PoolQuery()
912  : _pimpl(new Impl())
913  {}
914 
916  {}
917 
918  void PoolQuery::addRepo(const std::string &repoalias)
919  {
920  if (repoalias.empty())
921  {
922  WAR << "ignoring an empty repository alias" << endl;
923  return;
924  }
925  _pimpl->_repos.insert(repoalias);
926  }
927 
928  void PoolQuery::addKind(const ResKind & kind)
929  { _pimpl->_kinds.insert(kind); }
930 
931  void PoolQuery::addString(const string & value)
932  { _pimpl->_strings.insert(value); }
933 
934  void PoolQuery::addAttribute(const sat::SolvAttr & attr, const std::string & value)
935  { _pimpl->_attrs[attr].insert(value); }
936 
937  void PoolQuery::addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition )
938  {
939  // Default Match::OTHER indicates need to compile, i.e. to merge name into the global search string and mode.
940  return addDependency( attr, name, op, edition, Arch_empty, Match::OTHER );
941  }
942 
943  void PoolQuery::addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition, const Arch & arch )
944  {
945  // Default Match::OTHER indicates need to compile, i.e. to merge name into the global search string and mode.
946  return addDependency( attr, name, op, edition, arch, Match::OTHER );
947  }
948 
949  void PoolQuery::addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition, const Arch & arch, Match::Mode mode )
950  {
951  if ( op == Rel::NONE ) // will never match.
952  return;
953 
954  // SolvAttr::name with explicit 'kind:name' will overwrite the default _kinds
955  ResKind explicitKind;
956  if ( attr == sat::SolvAttr::name )
957  explicitKind = ResKind::explicitBuiltin( name );
958 
959  // Legacy: Match::OTHER and no additional constraints on edition/arch/kind
960  // require addAttribute, otherwise de-serialisation breaks (serialized
961  // and de-serialized query could be !=).
962  // From the results POV we could also use the predicated case below.
963  if ( op == Rel::ANY && arch.empty() && !explicitKind && mode == Match::OTHER )
964  {
965  addAttribute( attr, name );
966  return;
967  }
968 
969  // Match::OTHER indicates need to compile
970  // (merge global search strings into name).
971  AttrMatchData attrMatchData( attr );
972  if ( !explicitKind )
973  attrMatchData.strMatcher = StrMatcher( name, mode );
974  else
975  {
976  // ResKind::explicitBuiltin call above asserts the presence of the ':' in name
977  attrMatchData.strMatcher = StrMatcher( strchr( name.c_str(), ':')+1, mode );
978  attrMatchData.kindPredicate = explicitKind;
979  }
980 
981  if ( isDependencyAttribute( attr ) )
982  attrMatchData.addPredicate( EditionRangePredicate( op, edition, arch ) );
983  else
984  attrMatchData.addPredicate( SolvableRangePredicate( op, edition, arch ) );
985 
986  _pimpl->_uncompiledPredicated.insert( attrMatchData );
987  }
988 
990  {
991  CapDetail cap( cap_r );
992  if ( ! cap.isSimple() ) // will never match.
993  return;
994 
995  // Matches STRING per default. (won't get compiled!)
996  AttrMatchData attrMatchData( attr, StrMatcher( cap.name().asString() ) );
997 
998  if ( isDependencyAttribute( attr ) )
999  attrMatchData.addPredicate( CapabilityMatchPredicate( cap_r ) );
1000  else
1001  attrMatchData.addPredicate( SolvableRangePredicate( cap.op(), cap.ed() ) );
1002 
1003  _pimpl->_uncompiledPredicated.insert( attrMatchData );
1004  }
1005 
1006  void PoolQuery::setEdition(const Edition & edition, const Rel & op)
1007  {
1008  _pimpl->_edition = edition;
1009  _pimpl->_op = op;
1010  }
1011 
1017  {
1018  _pimpl->_match_word = true;
1020  }
1021 
1023  { return _pimpl->_flags; }
1024  void PoolQuery::setFlags( const Match & flags )
1025  { _pimpl->_flags = flags; }
1026 
1027 
1033  { _pimpl->_status_flags = flags; }
1034 
1035 
1036  void PoolQuery::setRequireAll(bool require_all)
1037  { _pimpl->_require_all = require_all; }
1038 
1039 
1040  const PoolQuery::StrContainer &
1042  { return _pimpl->_strings; }
1043 
1044  const PoolQuery::AttrRawStrMap &
1046  { return _pimpl->_attrs; }
1047 
1048  const PoolQuery::StrContainer &
1050  {
1051  static const PoolQuery::StrContainer nocontainer;
1052  AttrRawStrMap::const_iterator it = _pimpl->_attrs.find(attr);
1053  return it != _pimpl->_attrs.end() ? it->second : nocontainer;
1054  }
1055 
1057  { return _pimpl->_edition; }
1059  { return _pimpl->_op; }
1060 
1061 
1062  const PoolQuery::Kinds &
1064  { return _pimpl->_kinds; }
1065 
1066  const PoolQuery::StrContainer &
1068  { return _pimpl->_repos; }
1069 
1070 
1072  { return !_pimpl->_flags.test( Match::NOCASE ); }
1073  void PoolQuery::setCaseSensitive( bool value )
1074  { _pimpl->_flags.turn( Match::NOCASE, !value ); }
1075 
1077  { return _pimpl->_flags.test( Match::FILES ); }
1079  { _pimpl->_flags.turn( Match::FILES, value ); }
1080 
1081  bool PoolQuery::matchExact() const { return _pimpl->_flags.isModeString(); }
1083  bool PoolQuery::matchGlob() const { return _pimpl->_flags.isModeGlob(); }
1084  bool PoolQuery::matchRegex() const { return _pimpl->_flags.isModeRegex(); }
1085 
1087  { return _pimpl->_match_word; }
1088 
1090  { return _pimpl->_require_all; }
1091 
1093  { return _pimpl->_status_flags; }
1094 
1095  bool PoolQuery::empty() const
1096  {
1097  try { return begin() == end(); }
1098  catch (const Exception & ex) {}
1099  return true;
1100  }
1101 
1103  {
1104  try
1105  {
1106  size_type count = 0;
1107  for_( it, begin(), end() )
1108  ++count;
1109  return count;
1110  }
1111  catch (const Exception & ex) {}
1112  return 0;
1113  }
1114 
1116  { invokeOnEach( begin(), end(), fnc); }
1117 
1118 
1120  //
1121  // CLASS NAME : PoolQuery::Attr
1122  //
1127  struct PoolQueryAttr : public IdStringType<PoolQueryAttr>
1128  {
1129  private:
1132  public:
1133 
1134  //noAttr
1136 
1137  explicit PoolQueryAttr( const char* cstr_r )
1138  : _str( cstr_r )
1139  {}
1140 
1141  explicit PoolQueryAttr( const std::string & str_r )
1142  : _str( str_r )
1143  {}
1144 
1145  // unknown atributes
1146  static const PoolQueryAttr noAttr;
1147 
1148  // PoolQuery's own attributes
1149  static const PoolQueryAttr repoAttr;
1150  static const PoolQueryAttr kindAttr;
1158  };
1159 
1161 
1162  const PoolQueryAttr PoolQueryAttr::repoAttr( "repo" );
1163  const PoolQueryAttr PoolQueryAttr::kindAttr( "type" );
1164  const PoolQueryAttr PoolQueryAttr::stringAttr( "query_string" );
1165  const PoolQueryAttr PoolQueryAttr::stringTypeAttr("match_type");
1166  const PoolQueryAttr PoolQueryAttr::requireAllAttr("require_all");
1167  const PoolQueryAttr PoolQueryAttr::caseSensitiveAttr("case_sensitive");
1168  const PoolQueryAttr PoolQueryAttr::installStatusAttr("install_status");
1169  const PoolQueryAttr PoolQueryAttr::editionAttr("version");
1170  const PoolQueryAttr PoolQueryAttr::complexAttr("complex");
1171 
1172  class StringTypeAttr : public IdStringType<PoolQueryAttr>
1173  {
1176 
1177  public:
1179  explicit StringTypeAttr( const char* cstr_r )
1180  : _str( cstr_r ){}
1181  explicit StringTypeAttr( const std::string & str_r )
1182  : _str( str_r ){}
1183 
1184  static const StringTypeAttr noAttr;
1185 
1189  static const StringTypeAttr globAttr;
1190  static const StringTypeAttr wordAttr;
1191  };
1192 
1194 
1196  const StringTypeAttr StringTypeAttr::substringAttr("substring");
1200 
1202 
1203 
1204  //\TODO maybe ctor with stream can be usefull
1205  //\TODO let it throw, let it throw, let it throw.
1206  bool PoolQuery::recover( istream &str, char delim )
1207  {
1208  bool finded_something = false; //indicates some atributes is finded
1209  string s;
1210  do {
1211  if ( str.eof() )
1212  break;
1213 
1214  getline( str, s, delim );
1215 
1216  if ((!s.empty()) && s[0]=='#') //comment
1217  {
1218  continue;
1219  }
1220 
1221  string::size_type pos = s.find(':');
1222  if (s.empty() || pos == s.npos) // some garbage on line... act like blank line
1223  {
1224  if (finded_something) //is first blank line after record?
1225  {
1226  break;
1227  }
1228  else
1229  {
1230  continue;
1231  }
1232  }
1233 
1234  finded_something = true;
1235 
1236  string attrName(str::trim(string(s,0,pos))); // trimmed name of atribute
1237  string attrValue(str::trim(string(s,pos+1,s.npos))); //trimmed value
1238 
1239  PoolQueryAttr attribute( attrName );
1240 
1242  {
1243  addRepo( attrValue );
1244  }
1245  /* some backwards compatibility */
1246  else if ( attribute==PoolQueryAttr::kindAttr || attribute=="kind" )
1247  {
1248  addKind( ResKind(attrValue) );
1249  }
1251  || attribute=="global_string")
1252  {
1253  addString( attrValue );
1254  }
1256  || attribute=="string_type" )
1257  {
1258  StringTypeAttr s(attrValue);
1259  if( s == StringTypeAttr::regexAttr )
1260  {
1261  setMatchRegex();
1262  }
1263  else if ( s == StringTypeAttr::globAttr )
1264  {
1265  setMatchGlob();
1266  }
1267  else if ( s == StringTypeAttr::exactAttr )
1268  {
1269  setMatchExact();
1270  }
1271  else if ( s == StringTypeAttr::substringAttr )
1272  {
1274  }
1275  else if ( s == StringTypeAttr::wordAttr )
1276  {
1277  setMatchWord();
1278  }
1279  else if ( s == StringTypeAttr::noAttr )
1280  {
1281  WAR << "unknown string type " << attrValue << endl;
1282  }
1283  else
1284  {
1285  WAR << "forget recover some attribute defined as String type attribute: " << attrValue << endl;
1286  }
1287  }
1289  {
1290  if ( str::strToTrue(attrValue) )
1291  {
1292  setRequireAll(true);
1293  }
1294  else if ( !str::strToFalse(attrValue) )
1295  {
1296  setRequireAll(false);
1297  }
1298  else
1299  {
1300  WAR << "unknown boolean value " << attrValue << endl;
1301  }
1302  }
1304  {
1305  if ( str::strToTrue(attrValue) )
1306  {
1307  setCaseSensitive(true);
1308  }
1309  else if ( !str::strToFalse(attrValue) )
1310  {
1311  setCaseSensitive(false);
1312  }
1313  else
1314  {
1315  WAR << "unknown boolean value " << attrValue << endl;
1316  }
1317  }
1319  {
1320  if( attrValue == "all" )
1321  {
1323  }
1324  else if( attrValue == "installed" )
1325  {
1326  setInstalledOnly();
1327  }
1328  else if( attrValue == "not-installed" )
1329  {
1331  }
1332  else
1333  {
1334  WAR << "Unknown value for install status " << attrValue << endl;
1335  }
1336  }
1338  {
1339  string::size_type pos;
1340  Rel rel("==");
1341  if (attrValue.find_first_of("=<>!") == 0)
1342  {
1343  pos = attrValue.find_last_of("=<>");
1344  rel = Rel(attrValue.substr(0, pos+1));
1345  attrValue = str::trim(attrValue.substr(pos+1, attrValue.npos));
1346  }
1347 
1348  setEdition(Edition(attrValue), rel);
1349  }
1350  else if ( attribute == PoolQueryAttr::complexAttr )
1351  {
1352  try
1353  {
1355  }
1356  catch ( const Exception & err )
1357  {
1358  WAR << "Unparsable value for complex: " << err.asUserHistory() << endl;
1359 
1360  }
1361  }
1362  else if ( attribute==PoolQueryAttr::noAttr )
1363  {
1364  WAR << "empty attribute name" << endl;
1365  }
1366  else
1367  {
1368  string s = attrName;
1369  str::replaceAll( s,"_",":" );
1370  SolvAttr a(s);
1371  if ( a == SolvAttr::name || isDependencyAttribute( a ) )
1372  {
1373  Capability c( attrValue );
1374  CapDetail d( c );
1375  if ( d.isVersioned() )
1376  addDependency( a, d.name().asString(), d.op(), d.ed() );
1377  else
1378  addDependency( a, attrValue );
1379  }
1380  else
1381  addAttribute( a, attrValue );
1382  }
1383 
1384  } while ( true );
1385 
1386  return finded_something;
1387  }
1388 
1389  void PoolQuery::serialize( ostream &str, char delim ) const
1390  {
1391  //separating delim
1392  str << delim;
1393  //iterate thrue all settings and write it
1394  static const zypp::PoolQuery q; //not save default options, so create default query example
1395 
1396  for_( it, repos().begin(), repos().end() )
1397  {
1398  str << "repo: " << *it << delim ;
1399  }
1400 
1401  for_( it, kinds().begin(), kinds().end() )
1402  {
1403  str << PoolQueryAttr::kindAttr.asString() << ": "
1404  << it->idStr() << delim ;
1405  }
1406 
1407  if (editionRel() != Rel::ANY && edition() != Edition::noedition)
1408  str << PoolQueryAttr::editionAttr.asString() << ": " << editionRel() << " " << edition() << delim;
1409 
1410  if (matchMode()!=q.matchMode())
1411  {
1412  switch( matchMode() )
1413  {
1414  case Match::STRING:
1415  str << PoolQueryAttr::stringTypeAttr.asString() << ": exact" << delim;
1416  break;
1417  case Match::SUBSTRING:
1419  << ": substring" << delim;
1420  break;
1421  case Match::GLOB:
1422  str << PoolQueryAttr::stringTypeAttr.asString() << ": glob" << delim;
1423  break;
1424  case Match::REGEX:
1425  str << PoolQueryAttr::stringTypeAttr.asString() << ": regex" << delim;
1426  break;
1427  default:
1428  WAR << "unknown match type " << matchMode() << endl;
1429  }
1430  }
1431 
1432  if( caseSensitive() != q.caseSensitive() )
1433  {
1434  str << "case_sensitive: ";
1435  if (caseSensitive())
1436  {
1437  str << "on" << delim;
1438  }
1439  else
1440  {
1441  str << "off" << delim;
1442  }
1443  }
1444 
1445  if( requireAll() != q.requireAll() )
1446  {
1447  str << "require_all: ";
1448  if (requireAll())
1449  {
1450  str << "on" << delim;
1451  }
1452  else
1453  {
1454  str << "off" << delim;
1455  }
1456  }
1457 
1458  if( statusFilterFlags() != q.statusFilterFlags() )
1459  {
1460  switch( statusFilterFlags() )
1461  {
1462  case ALL:
1463  str << "install_status: all" << delim;
1464  break;
1465  case INSTALLED_ONLY:
1466  str << "install_status: installed" << delim;
1467  break;
1468  case UNINSTALLED_ONLY:
1469  str << "install_status: not-installed" << delim;
1470  break;
1471  }
1472  }
1473 
1474  for_( it, strings().begin(), strings().end() )
1475  {
1476  str << PoolQueryAttr::stringAttr.asString()<< ": " << *it << delim;
1477  }
1478 
1479  for_( it, attributes().begin(), attributes().end() )
1480  {
1481  string s = it->first.asString();
1482  str::replaceAll(s,":","_");
1483  for_( it2,it->second.begin(),it->second.end() )
1484  {
1485  str << s <<": "<< *it2 << delim;
1486  }
1487  }
1488 
1490  {
1491  str << "complex: "<< it->serialize() << delim;
1492  }
1493 
1494  //separating delim - protection
1495  str << delim;
1496  }
1497 
1498  string PoolQuery::asString() const
1499  { return _pimpl->asString(); }
1500 
1501  ostream & operator<<( ostream & str, const PoolQuery & obj )
1502  { return str << obj.asString(); }
1503 
1504  std::ostream & dumpOn( std::ostream & str, const PoolQuery & obj )
1505  { return dumpRange( str << obj, obj.begin(), obj.end() ); }
1506 
1507  bool PoolQuery::operator==( const PoolQuery & rhs ) const
1508  { return *_pimpl == *rhs._pimpl; }
1509 
1510  bool PoolQuery::operator<( const PoolQuery & rhs ) const
1511  { return *_pimpl < *rhs._pimpl; }
1512 
1514  namespace detail
1515  {
1516 
1518  //
1519  // CLASS NAME : PoolQueryMatcher
1520  //
1538  {
1539  public:
1541 
1542  public:
1543  const base_iterator & end() const
1544  {
1545  static base_iterator _end;
1546  return _end;
1547  }
1548 
1549  bool advance( base_iterator & base_r ) const
1550  {
1551  if ( base_r == end() )
1552  base_r = startNewQyery(); // first candidate
1553  else
1554  {
1555  base_r.nextSkipSolvable(); // assert we don't visit this Solvable again
1556  ++base_r; // advance to next candidate
1557  }
1558 
1559  while ( base_r != end() )
1560  {
1561  if ( isAMatch( base_r ) )
1562  return true;
1563  // No match: try next
1564  ++base_r;
1565  }
1566  return false;
1567  }
1568 
1572  void matchDetail( const base_iterator & base_r, std::vector<base_iterator> & return_r ) const
1573  {
1574  if ( base_r == end() )
1575  return;
1576 
1577  sat::Solvable inSolvable( base_r.inSolvable() );
1578 
1579  if ( _attrMatchList.size() == 1 )
1580  {
1581  // base_r is already on the 1st matching attribute!
1582  // String matching is done by the base iterator. We must check the predicate here.
1583  // Let's see if there are more matches for this solvable:
1584  base_iterator base( base_r );
1585  base.stayInThisSolvable(); // avoid discarding matches we found far away from here.
1586  return_r.push_back( base );
1587 
1588  const AttrMatchData::Predicate & predicate( _attrMatchList.front().predicate );
1589  for ( ++base; base.inSolvable() == inSolvable; ++base ) // safe even if base == end()
1590  {
1591  if ( ! predicate || predicate( base ) )
1592  return_r.push_back( base );
1593  }
1594  }
1595  else
1596  {
1597  // Here: search all attributes ;(
1598  for_( mi, _attrMatchList.begin(), _attrMatchList.end() )
1599  {
1600  const AttrMatchData & matchData( *mi );
1601  sat::LookupAttr q( matchData.attr, inSolvable );
1602  if ( matchData.strMatcher ) // an empty searchstring matches always
1603  q.setStrMatcher( matchData.strMatcher );
1604 
1605  if ( ! q.empty() ) // there are matches.
1606  {
1607  // now check any predicate:
1608  const AttrMatchData::Predicate & predicate( matchData.predicate );
1609  for_( it, q.begin(), q.end() )
1610  {
1611  if ( ! predicate || predicate( it ) )
1612  return_r.push_back( it );
1613  }
1614  }
1615  }
1616  }
1617  }
1618 
1619  public:
1623  PoolQueryMatcher( const shared_ptr<const PoolQuery::Impl> & query_r )
1624  {
1625  query_r->compile();
1626 
1627  // Repo restriction:
1628  sat::Pool satpool( sat::Pool::instance() );
1629 
1630  for_( it, query_r->_repos.begin(), query_r->_repos.end() )
1631  {
1632  Repository r( satpool.reposFind( *it ) );
1633  if ( r )
1634  _repos.insert( r );
1635  else
1636  _neverMatchRepo = true;
1637  }
1638  // _neverMatchRepo: we just need to catch the case that no repo
1639  // matched, so we'd interpret the empty list as 'take from all'
1640  if ( _neverMatchRepo && ! _repos.empty() )
1641  _neverMatchRepo = false;
1642 
1643  // Kind restriction:
1644  _kinds = query_r->_kinds;
1645  // Edition restriction:
1646  _op = query_r->_op;
1647  _edition = query_r->_edition;
1648  // Status restriction:
1649  _status_flags = query_r->_status_flags;
1650  // StrMatcher
1651  _attrMatchList = query_r->_attrMatchList;
1652  }
1653 
1655  {}
1656 
1657  private:
1660  {
1661  sat::LookupAttr q;
1662 
1663  if ( _neverMatchRepo )
1664  return q.end();
1665 
1666  // Repo restriction:
1667  if ( _repos.size() == 1 )
1668  q.setRepo( *_repos.begin() );
1669  // else: handled in isAMatch.
1670 
1671  // Attribute restriction:
1672  if ( _attrMatchList.size() == 1 ) // all (SolvAttr::allAttr) or 1 attr
1673  {
1674  const AttrMatchData & matchData( _attrMatchList.front() );
1675  q.setAttr( matchData.attr );
1676  if ( matchData.strMatcher ) // empty searchstring matches always
1677  q.setStrMatcher( matchData.strMatcher );
1678  }
1679  else // more than 1 attr (but not all)
1680  {
1681  // no restriction, it's all handled in isAMatch.
1683  }
1684 
1685  return q.begin();
1686  }
1687 
1688 
1699  bool isAMatch( base_iterator & base_r ) const
1700  {
1702  Repository inRepo( base_r.inRepo() );
1703  // Status restriction:
1704  if ( _status_flags
1705  && ( (_status_flags == PoolQuery::INSTALLED_ONLY) != inRepo.isSystemRepo() ) )
1706  {
1707  base_r.nextSkipRepo();
1708  return false;
1709  }
1710  // Repo restriction:
1711  if ( _repos.size() > 1 && _repos.find( inRepo ) == _repos.end() )
1712  {
1713  base_r.nextSkipRepo();
1714  return false;
1715  }
1717  sat::Solvable inSolvable( base_r.inSolvable() );
1718  // Edition restriction:
1719  if ( _op != Rel::ANY && !compareByRel( _op, inSolvable.edition(), _edition, Edition::Match() ) )
1720  {
1721  base_r.nextSkipSolvable();
1722  return false;
1723  }
1724 
1725  // Kind restriction:
1726  // Delay the decision to nextSkipSolvable and return false, as there may be
1727  // some explicit kind:name predicate which overrules the global kinds.
1728  bool globalKindOk =( _kinds.empty() || inSolvable.isKind( _kinds.begin(), _kinds.end() ) );
1729 
1731  // string and predicate matching:
1732 
1733  if ( _attrMatchList.size() == 1 )
1734  {
1735  // String matching was done by the base iterator.
1736  // Now check any predicate:
1737  const AttrMatchData & matchData( _attrMatchList.front() );
1738 
1739  if ( matchData.kindPredicate )
1740  {
1741  if ( matchData.kindPredicate != inSolvable.kind() )
1742  {
1743  base_r.nextSkipSolvable(); // this matchData will never match in this solvable
1744  return false;
1745  }
1746  }
1747  else if ( !globalKindOk )
1748  return false; // only matching kindPredicate could overwrite this
1749 
1750  if ( !matchData.predicate || matchData.predicate( base_r ) )
1751  return true;
1752 
1753  return false; // no skip as there may be more occurrences in this solvable of this attr.
1754  }
1755 
1756  // Here: search all attributes ;(
1757  for_( mi, _attrMatchList.begin(), _attrMatchList.end() )
1758  {
1759  const AttrMatchData & matchData( *mi );
1760 
1761  if ( matchData.kindPredicate )
1762  {
1763  if ( matchData.kindPredicate != inSolvable.kind() )
1764  continue; // this matchData does not apply
1765  }
1766  else if ( !globalKindOk )
1767  continue; // only matching kindPredicate could overwrite this
1768 
1769  sat::LookupAttr q( matchData.attr, inSolvable );
1770  if ( matchData.strMatcher ) // an empty searchstring matches always
1771  q.setStrMatcher( matchData.strMatcher );
1772 
1773  if ( ! q.empty() ) // there are matches.
1774  {
1775  // now check any predicate:
1776  const AttrMatchData::Predicate & predicate( matchData.predicate );
1777  if ( predicate )
1778  {
1779  for_( it, q.begin(), q.end() )
1780  {
1781  if ( predicate( it ) )
1782  return true;
1783  }
1784  }
1785  else
1786  return true;
1787  }
1788  }
1789  base_r.nextSkipSolvable();
1790  return false;
1791  }
1792 
1793  private:
1795  std::set<Repository> _repos;
1798  std::set<ResKind> _kinds;
1805  AttrMatchList _attrMatchList;
1806  };
1808 
1810  {
1811  // matcher restarts if at end! It is called from the ctor
1812  // to get the 1st match. But if the end is reached, it should
1813  // be deleted, otherwise we'd start over again.
1814  if ( !_matcher )
1815  return; // at end
1816  if ( _matches )
1817  _matches.reset(); // invalidate old matches
1818  if ( ! _matcher->advance( base_reference() ) )
1819  _matcher.reset();
1820  }
1821 
1823  {
1824  if ( _matches )
1825  return *_matches;
1826 
1827  if ( !_matcher )
1828  {
1829  // at end of query:
1830  static const Matches _none;
1831  return _none;
1832  }
1833 
1834  _matches.reset( new Matches );
1835  _matcher->matchDetail( base_reference(), *_matches );
1836  return *_matches;
1837  }
1838 
1839  std::ostream & dumpOn( std::ostream & str, const PoolQueryIterator & obj )
1840  {
1841  str << *obj;
1842  if ( ! obj.matchesEmpty() )
1843  {
1844  for_( it, obj.matchesBegin(), obj.matchesEnd() )
1845  {
1846  str << endl << " " << it->inSolvAttr() << "\t" << it->asString();
1847  }
1848  }
1849  return str;
1850  }
1851 
1853  } //namespace detail
1855 
1857  {
1858  return shared_ptr<detail::PoolQueryMatcher>( new detail::PoolQueryMatcher( _pimpl.getPtr() ) );
1859  }
1860 
1862 } // namespace zypp
1864 
int _status_flags
Installed status filter flags.
Definition: PoolQuery.cc:1803
Interface to gettext.
static const PoolQueryAttr installStatusAttr
Definition: PoolQuery.cc:1155
bool matchExact() const
Definition: PoolQuery.cc:1081
Rel _op
Operator for edition condition.
Definition: PoolQuery.cc:452
A Solvable object within the sat Pool.
Definition: Solvable.h:53
void setUninstalledOnly()
Return only packages from repos other than .
Definition: PoolQuery.cc:1030
bool isVersioned() const
Definition: Capability.h:337
StatusFilter
Installed status filter setters.
Definition: PoolQuery.h:169
Arch _arch
Definition: PoolQuery.cc:102
static const StringTypeAttr substringAttr
Definition: PoolQuery.cc:1187
const AttrRawStrMap & attributes() const
Map (map<SolvAttr, StrContainer>) of attribute values added via addAttribute(), addDep in string form...
Definition: PoolQuery.cc:1045
bool compareByRel(Rel op, const Tp &lhs, const Tp &rhs, TCompare compare)
Comparison of two elements using relational operator op.
Definition: RelCompare.h:108
void addAttribute(const sat::SolvAttr &attr, const std::string &value="")
Filter by the value of the specified attr attribute.
Definition: PoolQuery.cc:934
void setAttr(SolvAttr attr_r)
Set the SolvAttr to search.
Definition: LookupAttr.cc:199
unsigned splitEscaped(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \, bool withEmpty=false)
Split line_r into words with respect to escape delimeters.
Definition: String.h:561
std::set< ResKind > Kinds
Definition: PoolQuery.h:93
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
String matching option flags as used e.g.
Definition: StrMatcher.h:32
static const SolvAttr allAttr
Value to request searching all Attributes (0).
Definition: SolvAttr.h:46
Edition ed() const
Definition: Capability.h:347
std::set< ResKind > _kinds
Resolvable kinds to include.
Definition: PoolQuery.cc:1798
Helper providing more detailed information about a Capability.
Definition: Capability.h:298
PoolQuery::StrContainer & _cont
Definition: PoolQuery.cc:545
std::ostream & dumpOn(std::ostream &str, const PoolQueryIterator &obj)
Definition: PoolQuery.cc:1839
Architecture.
Definition: Arch.h:36
static const StringTypeAttr noAttr
Definition: PoolQuery.cc:1184
static ResKind explicitBuiltin(const char *str_r)
Return the builtin kind if str_r explicitly prefixed.
Definition: ResKind.cc:46
PoolQuery iterator as returned by PoolQuery::begin.
Definition: PoolQuery.h:521
void setFlags(const Match &flags)
Free function to set libsolv repo search flags.
Definition: PoolQuery.cc:1024
String matching (STRING|SUBSTRING|GLOB|REGEX).
Definition: StrMatcher.h:297
Relational operators.
Definition: Rel.h:43
bool empty() const
Test for an empty Arch (this is Arch_epmty, not Arch_noarch ).
Definition: Arch.h:63
static const PoolQueryAttr caseSensitiveAttr
Definition: PoolQuery.cc:1154
void execute(ProcessResolvable fnc)
Executes the query with the current settings.
Definition: PoolQuery.cc:1115
void addString(const std::string &value)
Add a global query string.
Definition: PoolQuery.cc:931
Lightweight attribute value lookup.
Definition: LookupAttr.h:107
Rel _op
Edition filter.
Definition: PoolQuery.cc:1800
const StrContainer & strings() const
Search strings added via addString()
Definition: PoolQuery.cc:1041
constPtrType getPtr() const
Definition: PtrTypes.h:349
Regular Expression.
Definition: StrMatcher.h:48
sat::SolvAttr attr
Definition: PoolQuery.cc:311
bool operator()(const string &str)
Definition: PoolQuery.cc:539
Match::Mode matchMode() const
Returns string matching mode as enum.
Definition: PoolQuery.h:430
std::ostream & dumpRange(std::ostream &str, TIterator begin, TIterator end, const std::string &intro="{", const std::string &pfx="\ ", const std::string &sep="\ ", const std::string &sfx="\, const std::string &extro="}")
Print range defined by iterators (multiline style).
Definition: LogTools.h:91
const Matches & matches() const
Definition: PoolQuery.cc:1822
void setMatchGlob()
Set to match globs.
Definition: PoolQuery.cc:1015
void setMatchRegex()
Set to use the query strings as regexes.
Definition: PoolQuery.cc:1014
const Arch Arch_empty(IdString::Empty)
String related utilities and Regular expression matching.
bool operator<(const PoolQuery &b) const
Definition: PoolQuery.cc:1510
PoolQueryMatcher(const shared_ptr< const PoolQuery::Impl > &query_r)
Ctor stores the PoolQuery settings.
Definition: PoolQuery.cc:1623
Definition: Arch.h:344
void addDependency(const sat::SolvAttr &attr, const std::string &name, const Rel &op, const Edition &edition)
Query "name|global op edition".
Definition: PoolQuery.cc:937
Capability _cap
Definition: PoolQuery.cc:160
void setModeGlob()
Set the mode GLOB.
Definition: StrMatcher.h:198
Access to the sat-pools string space.
Definition: IdString.h:41
void setCaseSensitive(bool value=true)
Turn case sentitivity on or off (unsets or sets SEARCH_NOCASE flag).
Definition: PoolQuery.cc:1073
Match _flags
Sat solver search flags.
Definition: PoolQuery.cc:442
Rel op() const
Definition: Capability.h:346
void addKind(const ResKind &kind)
Filter by selectable kind.
Definition: PoolQuery.cc:928
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:27
Edition represents [epoch:]version[-release]
Definition: Edition.h:60
Store PoolQuery settings and assist PoolQueryIterator.
Definition: PoolQuery.cc:1537
static const Rel ANY
Definition: Rel.h:56
Edition _edition
Edition condition operand.
Definition: PoolQuery.cc:450
bool operator==(const SetRelation::Enum &lhs, const SetCompare &rhs)
Mode mode() const
Return the mode part.
Definition: StrMatcher.cc:52
void setModeSubstring()
Set the mode SUBSTRING.
Definition: StrMatcher.h:195
const Kinds & kinds() const
Definition: PoolQuery.cc:1063
string asString() const
String representation.
Definition: PoolQuery.cc:832
Base class for creating IdString based types.
Definition: IdStringType.h:86
PoolQueryAttr(const std::string &str_r)
Definition: PoolQuery.cc:1141
size_type size() const
Number of solvables in the query result.
Definition: PoolQuery.cc:1102
Unknown match mode.
Definition: StrMatcher.h:257
std::string & replaceAll(std::string &str_r, const std::string &from_r, const std::string &to_r)
Replace all occurrences of from_r with to_r in str_r (inplace).
Definition: String.cc:328
static const PoolQueryAttr noAttr
Definition: PoolQuery.cc:1146
bool overlaps(Rel lhs, Rel rhs, int cmp)
Compute Range overlaps.
Definition: Range.cc:30
static const PoolQueryAttr repoAttr
Definition: PoolQuery.cc:1149
bool operator==(const PoolQuery &b) const
Definition: PoolQuery.cc:1507
void serialize(std::ostream &str, char delim='\n') const
Writes a machine-readable string representation of the query to stream.
Definition: PoolQuery.cc:1389
bool operator!=(const PoolQuery::Impl &rhs) const
Definition: PoolQuery.cc:509
const StrContainer & attribute(const sat::SolvAttr &attr) const
Definition: PoolQuery.cc:1049
std::vector< sat::LookupAttr::iterator > Matches
Definition: PoolQuery.h:529
AttrMatchList _attrMatchList
StrMatcher per attribtue.
Definition: PoolQuery.cc:1805
iterator end() const
Iterator behind the end of query results.
Definition: LookupAttr.cc:239
void turn(const Match &rhs, bool onoff)
Depending on the value of onoff, set or unset flags.
Definition: StrMatcher.h:127
Edition::MatchRange _range
Definition: PoolQuery.cc:101
bool caseSensitive() const
returns true if search is case sensitive
Definition: PoolQuery.cc:1071
std::string getline(std::istream &str)
Read one line from stream.
Definition: IOStream.cc:33
unsigned int size_type
Definition: PoolQuery.h:98
StringTypeAttr(const char *cstr_r)
Definition: PoolQuery.cc:1179
static Pool instance()
Singleton ctor.
Definition: Pool.h:53
Solvable attribute keys.
Definition: SolvAttr.h:40
bool filesMatchFullPath() const
Whether searching in filelists looks at the full path or just at the basenames.
Definition: PoolQuery.cc:1076
std::set< std::string > StrContainer
Definition: PoolQuery.h:94
std::string asString() const
Definition: IdStringType.h:106
void setRepo(Repository repo_r, Location=SOLV_ATTR)
Set search in one Repository.
Definition: LookupAttr.cc:219
void setStatusFilterFlags(StatusFilter flags)
Set status filter directly.
Definition: PoolQuery.cc:1032
std::ostream & operator<<(std::ostream &str, const Exception &obj)
Definition: Exception.cc:147
match functor.
Definition: Edition.h:160
std::string trim(const std::string &s, const Trim trim_r)
Definition: String.cc:221
const StrContainer & repos() const
Definition: PoolQuery.cc:1067
void addRepo(const std::string &repoalias)
Filter by repo.
Definition: PoolQuery.cc:918
static string wildcards2regex(const string &str)
Converts &#39;*&#39; and &#39;?&#39; wildcards within str into their regex equivalents.
Definition: PoolQuery.cc:738
void setModeRegex()
Set the mode REGEX.
Definition: StrMatcher.h:201
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Definition: Exception.cc:91
#define OUTS(M, S)
void setMatchWord()
Set to match words (uses regex)
Definition: PoolQuery.cc:1016
const_iterator begin() const
Query result accessers.
Definition: PoolQuery.cc:1856
#define WAR
Definition: Logger.h:65
void stayInThisSolvable()
Stop after all matches in the current Solvable are processed.
Definition: LookupAttr.cc:369
Match substring.
Definition: StrMatcher.h:46
void setStrMatcher(const StrMatcher &matcher_r)
Set the pattern to match.
Definition: LookupAttr.cc:205
MyInserter(PoolQuery::StrContainer &cont)
Definition: PoolQuery.cc:537
base_iterator startNewQyery() const
Initialize a new base query.
Definition: PoolQuery.cc:1659
sat::LookupAttr::iterator base_iterator
Definition: PoolQuery.cc:1540
void nextSkipSolvable()
On the next call to operator++ advance to the next Solvable.
Definition: LookupAttr.cc:363
const Rel editionRel() const
Definition: PoolQuery.cc:1058
static const SolvAttr name
Definition: SolvAttr.h:52
std::ostream & dumpOn(std::ostream &str, const Capability &obj)
Definition: Capability.cc:444
StringTypeAttr(const std::string &str_r)
Definition: PoolQuery.cc:1181
bool strToFalse(const C_Str &str)
Return false if str is 0, false, no, off.
Definition: String.cc:80
Kinds _kinds
Kinds to search.
Definition: PoolQuery.cc:458
for_use_in_switch inSwitch() const
Enumarator provided for use in switch statement.
Definition: Rel.h:141
void setInstalledOnly()
Return only repo packages.
Definition: PoolQuery.cc:1028
static const StringTypeAttr exactAttr
Definition: PoolQuery.cc:1186
bool recover(std::istream &str, char delim='\n')
Reads from stream query.
Definition: PoolQuery.cc:1206
Mode
Mode flags (mutual exclusive).
Definition: StrMatcher.h:40
const base_iterator & end() const
Definition: PoolQuery.cc:1543
void matchDetail(const base_iterator &base_r, std::vector< base_iterator > &return_r) const
Provide all matching attributes within this solvable.
Definition: PoolQuery.cc:1572
bool advance(base_iterator &base_r) const
Definition: PoolQuery.cc:1549
const_iterator end() const
An iterator pointing to the end of the query result.
Definition: PoolQuery.h:626
static const PoolQueryAttr stringTypeAttr
Definition: PoolQuery.cc:1152
static const StringTypeAttr wordAttr
Definition: PoolQuery.cc:1190
SolvableIdType size_type
Definition: PoolMember.h:126
std::ostream & operator<<(std::ostream &str, const zypp::shared_ptr< void > &obj)
Definition: PtrTypes.h:134
Libsolv interface
const Edition edition() const
Definition: PoolQuery.cc:1056
bool operator<(const PoolQuery::Impl &rhs) const
Definition: PoolQuery.cc:463
bool operator!=(const SetRelation::Enum &lhs, const SetCompare &rhs)
void setMatchSubstring()
Set to substring (the default).
Definition: PoolQuery.cc:1012
represents all atributes in PoolQuery except SolvAtributes, which are used as is (not needed extend a...
Definition: PoolQuery.cc:1127
for_use_in_switch _op
The operator.
Definition: Rel.h:154
#define arrayEnd(A)
Definition: Easy.h:42
#define arrayBegin(A)
Simple C-array iterator.
Definition: Easy.h:40
bool strToTrue(const C_Str &str)
Parsing boolean from string.
Definition: String.cc:63
std::set< Repository > _repos
Repositories include in the search.
Definition: PoolQuery.cc:1795
std::string predicateStr
Definition: PoolQuery.cc:314
static const PoolQueryAttr stringAttr
Definition: PoolQuery.cc:1151
bool deserialize(const std::string &str_r, DownloadMode &result_r)
Definition: DownloadMode.cc:23
std::map< sat::SolvAttr, StrContainer > AttrRawStrMap
Definition: PoolQuery.h:95
std::set< AttrMatchData > _uncompiledPredicated
Uncompiled attributes with predicate.
Definition: PoolQuery.cc:439
Repository reposFind(const std::string &alias_r) const
Find a Repository named alias_r.
Definition: Pool.cc:142
void setModeString()
Set the mode STRING.
Definition: StrMatcher.h:186
static const Match NOCASE
If set, match case insensitive.
Definition: StrMatcher.h:59
Meta-data query API.
Definition: PoolQuery.h:90
bool matchWord() const
Definition: PoolQuery.cc:1086
Base class for Exception.
Definition: Exception.h:145
int get() const
Return the integer representation.
Definition: StrMatcher.h:150
Solvable inSolvable() const
The current Solvable.
Definition: LookupAttr.cc:354
static const PoolQueryAttr complexAttr
Definition: PoolQuery.cc:1157
bool isModeGlob() const
Whether this has mode GLOB.
Definition: StrMatcher.h:176
void setEdition(const Edition &edition, const Rel &op=Rel::EQ)
Set version condition.
Definition: PoolQuery.cc:1006
void setMatchExact()
Set to match exact string instead of substring.
Definition: PoolQuery.cc:1013
A sat capability.
Definition: Capability.h:59
Excat matching.
Definition: StrMatcher.h:43
#define WB
Predicate predicate
Definition: PoolQuery.cc:313
shared_ptr< PoolQueryMatcher > _matcher
Definition: PoolQuery.h:610
StatusFilter statusFilterFlags() const
Definition: PoolQuery.cc:1092
void nextSkipRepo()
On the next call to operator++ advance to the next Repository.
Definition: LookupAttr.cc:366
bool matchSubstring() const
Definition: PoolQuery.cc:1082
StrContainer _repos
Repos to search.
Definition: PoolQuery.cc:455
Global sat-pool.
Definition: Pool.h:44
bool operator()(const string &str)
Definition: PoolQuery.cc:551
bool empty() const
Whether the result is empty.
Definition: PoolQuery.cc:1095
shared_ptr< Matches > _matches
Definition: PoolQuery.h:611
DefaultIntegral< bool, false > _neverMatchRepo
Definition: PoolQuery.cc:1796
static const PoolQueryAttr requireAllAttr
Definition: PoolQuery.cc:1153
Match flags() const
Free function to get libsolv repo search flags.
Definition: PoolQuery.cc:1022
static const PoolQueryAttr editionAttr
Definition: PoolQuery.cc:1156
bool isModeRegex() const
Whether this has mode REGEX.
Definition: StrMatcher.h:179
void setFilesMatchFullPath(bool value=true)
If set (default), look at the full path when searching in filelists.
Definition: PoolQuery.cc:1078
std::string asString() const
Conversion to std::string
Definition: IdString.h:91
bool test(const Match &rhs) const
Test whether all of the rhs bits are set (same mode if rhs has one).
Definition: StrMatcher.h:101
RW_pointer< Impl > _pimpl
Pointer to implementation.
Definition: PoolQuery.h:491
AttrMatchList _attrMatchList
StrMatcher per attribtue.
Definition: PoolQuery.cc:520
StatusFilter _status_flags
Sat solver status flags.
Definition: PoolQuery.cc:447
Impl * clone() const
clone for RWCOW_pointer
Definition: PoolQuery.cc:529
PoolQueryAttr(const char *cstr_r)
Definition: PoolQuery.cc:1137
bool isAMatch(base_iterator &base_r) const
Check whether we are on a match.
Definition: PoolQuery.cc:1699
int invokeOnEach(TIterator begin_r, TIterator end_r, TFilter filter_r, TFunction fnc_r)
Iterate through [begin_r,end_r) and invoke fnc_r on each item that passes filter_r.
Definition: Algorithm.h:30
bool operator<(const StrMatcher &lhs, const StrMatcher &rhs)
Definition: StrMatcher.cc:335
std::string asString() const
Return a human-readable description of the query.
Definition: PoolQuery.cc:1498
Resolvable kinds.
Definition: ResKind.h:32
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
static const PoolQueryAttr kindAttr
Definition: PoolQuery.cc:1150
function< bool(const sat::Solvable &)> ProcessResolvable
Definition: PoolQuery.h:101
Repository inRepo() const
The current Repository.
Definition: LookupAttr.cc:351
IdString name() const
Definition: Capability.h:345
bool matchGlob() const
Definition: PoolQuery.cc:1083
static const Match FILES
LookupAttr: match full path when matching in filelists, otherwise just the basenames.
Definition: StrMatcher.h:75
bool isSimple() const
Definition: Capability.h:338
bool requireAll() const
Whether all values added via addString() or addAttribute() are required to match the values of the re...
Definition: PoolQuery.cc:1089
StrContainer _strings
Raw search strings.
Definition: PoolQuery.cc:435
bool isModeString() const
Whether this has mode STRING.
Definition: StrMatcher.h:164
StrMatcher strMatcher
Definition: PoolQuery.cc:312
void appendEscaped(std::string &str_r, const C_Str &next_r, const char sep_r=' ')
Escape next_r and append it to str_r using separator sep_r.
Definition: String.h:888
ResKind kindPredicate
Definition: PoolQuery.cc:315
bool empty() const
Whether the query is empty.
Definition: LookupAttr.cc:242
bool matchRegex() const
Definition: PoolQuery.cc:1084
static const StringTypeAttr globAttr
Definition: PoolQuery.cc:1189
iterator begin() const
Iterator to the begin of query results.
Definition: LookupAttr.cc:236
AttrRawStrMap _attrs
Raw attributes.
Definition: PoolQuery.cc:437
static const Edition noedition
Value representing noedition ("") This is in fact a valid Edition.
Definition: Edition.h:73
Something else.
Definition: StrMatcher.h:49
bool operator==(const PoolQuery::Impl &rhs) const
Definition: PoolQuery.cc:481
static const StringTypeAttr regexAttr
Definition: PoolQuery.cc:1188
void setRequireAll(bool require_all=true)
Require that all of the values set by addString or addAttribute match the values of respective attrib...
Definition: PoolQuery.cc:1036
bool isModeSubstring() const
Whether this has mode SUBSTRING.
Definition: StrMatcher.h:173
static const Rel NONE
Definition: Rel.h:57