libzypp  17.1.1
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  // TODO: Actually the flag should be serialized too, but for PoolQuery
241  // it's by now sufficient to differ between mode OTHER and others,
242  // i.e. whether to compile or not compile.
243  str::appendEscaped( ret, strMatcher.flags().mode() == Match::OTHER ? "C" : "X" );
245  return ret;
246  }
247 
251  static AttrMatchData deserialize( const std::string & str_r )
252  {
253  std::vector<std::string> words;
254  str::splitEscaped( str_r, std::back_inserter(words) );
255  if ( words.empty() || words[0] != "AttrMatchData" )
256  ZYPP_THROW( Exception( str::Str() << "Expecting AttrMatchData: " << str_r ) );
257  if ( words.size() != 5 )
258  ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) );
259 
260  AttrMatchData ret;
261  ret.attr = sat::SolvAttr( words[1] );
262  ret.strMatcher = StrMatcher( words[2] );
263  if ( words[3] == "C" )
264  ret.strMatcher.setFlags( Match::OTHER );
265  ret.predicateStr = words[4];
266 
267  // now the predicate
268  words.clear();
269  str::splitEscaped( ret.predicateStr, std::back_inserter(words) );
270  if ( ! words.empty() )
271  {
272  if ( words[0] == "EditionRange" )
273  {
274  switch( words.size() )
275  {
276  case 3:
277  ret.predicate = EditionRangePredicate( Rel(words[1]), Edition(words[2]) );
278  break;
279  case 4:
280  ret.predicate = EditionRangePredicate( Rel(words[1]), Edition(words[2]), Arch(words[3]) );
281  break;
282  default:
283  ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) );
284  break;
285  }
286  }
287  else if ( words[0] == "SolvableRange" )
288  {
289  switch( words.size() )
290  {
291  case 3:
292  ret.predicate = SolvableRangePredicate( Rel(words[1]), Edition(words[2]) );
293  break;
294  case 4:
295  ret.predicate = SolvableRangePredicate( Rel(words[1]), Edition(words[2]), Arch(words[3]) );
296  break;
297  default:
298  ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) );
299  break;
300  }
301  }
302  else if ( words[0] == "CapabilityMatch" )
303  {
304  if ( words.size() != 2 )
305  ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) );
306  ret.predicate = CapabilityMatchPredicate( Capability(words[1]) );
307  }
308  else
309  ZYPP_THROW( Exception( str::Str() << "Unknown predicate: " << str_r ) );
310  }
311  return ret;
312  }
313 
314  sat::SolvAttr attr;
315  StrMatcher strMatcher;
316  Predicate predicate;
317  std::string predicateStr;
318  ResKind kindPredicate = ResKind::nokind; // holds the 'kind' part if SolvAttr:name looks for an explicit 'kind:name'
319  };
320 
322  inline std::ostream & operator<<( std::ostream & str, const AttrMatchData & obj )
323  {
324  str << obj.attr << ": " << obj.strMatcher;
325  if ( obj.kindPredicate )
326  str << " +(" << obj.kindPredicate << ")";
327  if ( obj.predicate )
328  str << " +(" << obj.predicateStr << ")";
329  return str;
330  }
331 
333  inline bool operator==( const AttrMatchData & lhs, const AttrMatchData & rhs )
334  {
335  return ( lhs.attr == rhs.attr
336  && lhs.strMatcher == rhs.strMatcher
337  && lhs.predicateStr == rhs.predicateStr );
338  }
339 
341  inline bool operator!=( const AttrMatchData & lhs, const AttrMatchData & rhs )
342  { return !( lhs == rhs ); }
343 
345  inline bool operator<( const AttrMatchData & lhs, const AttrMatchData & rhs )
346  {
347  if ( lhs.attr != rhs.attr )
348  return ( lhs.attr < rhs.attr );
349  if ( lhs.strMatcher != rhs.strMatcher )
350  return ( lhs.strMatcher < rhs.strMatcher );
351  if ( lhs.predicateStr != rhs.predicateStr )
352  return ( lhs.predicateStr < rhs.predicateStr );
353  return false;
354  }
355 
356  typedef std::list<AttrMatchData> AttrMatchList;
357 
358 
359  }
360  // namespace
362 
364  //
365  // CLASS NAME : PoolQuery::Impl
366  //
369  {
370  public:
372  : _flags( Match::SUBSTRING | Match::NOCASE | Match::SKIP_KIND )
373  , _match_word(false)
374  , _require_all(false)
375  , _status_flags(ALL)
376  {}
377 
379  {}
380 
381  public:
383  string asString() const;
384 
392  std::set<AttrMatchData> _uncompiledPredicated;
393 
398 
401 
406 
409 
413 
414  public:
415 
416  bool operator<( const PoolQuery::Impl & rhs ) const
417  {
418 #define OUTS(A) if ( A != rhs.A ) return A < rhs.A;
419  OUTS( _strings );
420  OUTS( _attrs );
421  OUTS( _uncompiledPredicated );
422  OUTS( _flags.get() );
423  OUTS( _match_word );
424  OUTS( _require_all );
425  OUTS( _status_flags );
426  OUTS( _edition );
427  OUTS( _op.inSwitch() );
428  OUTS( _repos );
429  OUTS( _kinds );
430 #undef OUTS
431  return false;
432  }
433 
434  bool operator==( const PoolQuery::Impl & rhs ) const
435  {
436  if ( _flags == rhs._flags
437  // bnc#792901: while libzypp uses exact match mode for a single
438  // package name lock, zypper always uses glob. :(
439  // We unify those two forms to enable zypper to remove zypp locks
440  // without need to actually evaluate the query (which would require
441  // repos to be loaded).
442  || ( ( ( _flags.isModeString() && rhs._flags.isModeGlob() )
443  || ( _flags.isModeGlob() && rhs._flags.isModeString() ) )
444  && _strings.empty()
445  && _attrs.size() == 1
446  && _attrs.begin()->first == sat::SolvAttr::name ) )
447  {
448  return ( _strings == rhs._strings
449  && _attrs == rhs._attrs
450  && _uncompiledPredicated == rhs._uncompiledPredicated
451  && _match_word == rhs._match_word
452  && _require_all == rhs._require_all
453  && _status_flags == rhs._status_flags
454  && _edition == rhs._edition
455  && _op == rhs._op
456  && _repos == rhs._repos
457  && _kinds == rhs._kinds );
458  }
459  return false;
460  }
461 
462  bool operator!=( const PoolQuery::Impl & rhs ) const
463  { return ! operator==( rhs ); }
464 
465  public:
470  void compile() const;
471 
473  mutable AttrMatchList _attrMatchList;
474 
475  private:
477  string createRegex( const StrContainer & container, const Match & flags ) const;
478 
479  private:
480  friend Impl * rwcowClone<Impl>( const Impl * rhs );
482  Impl * clone() const
483  { return new Impl( *this ); }
484  };
485 
487 
488  struct MyInserter
489  {
490  MyInserter(PoolQuery::StrContainer & cont) : _cont(cont) {}
491 
492  bool operator()(const string & str)
493  {
494  _cont.insert(str);
495  return true;
496  }
497 
499  };
500 
501 
502  struct EmptyFilter
503  {
504  bool operator()(const string & str)
505  {
506  return !str.empty();
507  }
508  };
509 
510  void PoolQuery::Impl::compile() const
511  {
512  _attrMatchList.clear();
513 
514  Match cflags( _flags );
515  if ( cflags.mode() == Match::OTHER ) // this will never succeed...
517 
519  string rcstrings;
520 
521 
522  // 'different' - will have to iterate through all and match by ourselves (slow)
523  // 'same' - will pass the compiled string to dataiterator_init
524  // 'one-attr' - will pass it to dataiterator_init
525  // 'one-non-regex-str' - will pass to dataiterator_init, set flag to SEARCH_STRING or SEARCH_SUBSTRING
526 
527  // // NO ATTRIBUTE
528  // else
529  // for all _strings
530  // create regex; store in rcstrings; if more strings flag regex;
531  if (_attrs.empty())
532  {
533  ; // A default 'query-all' will be added after all sources are processed.
534  }
535 
536  // // ONE ATTRIBUTE
537  // else if _attrs is not empty but it contains just one attr
538  // for all _strings and _attr[key] strings
539  // create regex; flag 'one-attr'; if more strings flag regex;
540  else if (_attrs.size() == 1)
541  {
542  StrContainer joined;
543  invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
544  invokeOnEach(_attrs.begin()->second.begin(), _attrs.begin()->second.end(), EmptyFilter(), MyInserter(joined));
545  rcstrings = createRegex(joined, cflags);
546  if (joined.size() > 1) // switch to regex for multiple strings
547  cflags.setModeRegex();
548  _attrMatchList.push_back( AttrMatchData( _attrs.begin()->first,
549  StrMatcher( rcstrings, cflags ) ) );
550  }
551 
552  // // MULTIPLE ATTRIBUTES
553  else
554  {
555  // check whether there are any per-attribute strings
556  bool attrvals_empty = true;
557  for (AttrRawStrMap::const_iterator ai = _attrs.begin(); ai != _attrs.end(); ++ai)
558  if (!ai->second.empty())
559  for(StrContainer::const_iterator it = ai->second.begin();
560  it != ai->second.end(); it++)
561  if (!it->empty())
562  {
563  attrvals_empty = false;
564  goto attremptycheckend;
565  }
566 attremptycheckend:
567 
568  // chceck whether the per-attribute strings are all the same
569  bool attrvals_thesame = true;
570  AttrRawStrMap::const_iterator ai = _attrs.begin();
571  const StrContainer & set1 = ai->second;
572  ++ai;
573  for (; ai != _attrs.end(); ++ai)
574  {
575  StrContainer result;
576  set_difference(
577  set1.begin(), set1.end(),
578  ai->second.begin(), ai->second.end(),
579  inserter(result, result.begin())/*, ltstr()*/);
580  if (!result.empty())
581  {
582  attrvals_thesame = false;
583  break;
584  }
585  }
586 
587  // // THE SAME STRINGS FOR DIFFERENT ATTRS
588  // else if _attrs is not empty but it does not contain strings
589  // for each key in _attrs take all _strings
590  // create regex; store in rcstrings; flag 'same'; if more strings flag regex;
591  if (attrvals_empty || attrvals_thesame)
592  {
593  StrContainer joined;
594  if (attrvals_empty)
595  {
596  invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
597  rcstrings = createRegex(joined, cflags);
598  }
599  else
600  {
601  invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
602  invokeOnEach(_attrs.begin()->second.begin(), _attrs.begin()->second.end(), EmptyFilter(), MyInserter(joined));
603  rcstrings = createRegex(joined, cflags);
604  }
605  if (joined.size() > 1) // switch to regex for multiple strings
606  cflags.setModeRegex();
607  // May use the same StrMatcher for all
608  StrMatcher matcher( rcstrings, cflags );
609  for_( ai, _attrs.begin(), _attrs.end() )
610  {
611  _attrMatchList.push_back( AttrMatchData( ai->first, matcher ) );
612  }
613  }
614 
615  // // DIFFERENT STRINGS FOR DIFFERENT ATTRS
616  // if _attrs is not empty and it contains non-empty vectors with non-empty strings
617  // for each key in _attrs take all _strings + all _attrs[key] strings
618  // create regex; flag 'different'; if more strings flag regex;
619  else
620  {
621  for_(ai, _attrs.begin(), _attrs.end())
622  {
623  StrContainer joined;
624  invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
625  invokeOnEach(ai->second.begin(), ai->second.end(), EmptyFilter(), MyInserter(joined));
626  string s = createRegex(joined, cflags);
627  if (joined.size() > 1) // switch to regex for multiple strings
628  cflags.setModeRegex();
629  _attrMatchList.push_back( AttrMatchData( ai->first,
630  StrMatcher( s, cflags ) ) );
631  }
632  }
633  }
634 
635  // Now handle any predicated queries
636  if ( ! _uncompiledPredicated.empty() )
637  {
638  StrContainer global;
639  invokeOnEach( _strings.begin(), _strings.end(), EmptyFilter(), MyInserter(global) );
640  for_( it, _uncompiledPredicated.begin(), _uncompiledPredicated.end() )
641  {
642  if ( it->strMatcher.flags().mode() == Match::OTHER )
643  {
644  // need to compile:
645  StrContainer joined( global );
646  const std::string & mstr( it->strMatcher.searchstring() );
647  if ( ! mstr.empty() )
648  joined.insert( mstr );
649 
650  cflags = _flags;
651  rcstrings = createRegex( joined, cflags );
652  if ( joined.size() > 1 ) // switch to regex for multiple strings
653  cflags.setModeRegex();
654 
655  // copy and exchange the StrMatcher
656  AttrMatchData nattr( *it );
657  nattr.strMatcher = StrMatcher( rcstrings, cflags ),
658  _attrMatchList.push_back( std::move(nattr) );
659  }
660  else
661  {
662  // copy matcher
663  _attrMatchList.push_back( *it );
664  }
665  }
666  }
667 
668  // If no attributes defined at all, then add 'query all'
669  if ( _attrMatchList.empty() )
670  {
671  cflags = _flags;
672  rcstrings = createRegex( _strings, cflags );
673  if ( _strings.size() > 1 ) // switch to regex for multiple strings
674  cflags.setModeRegex();
675  _attrMatchList.push_back( AttrMatchData( sat::SolvAttr::allAttr,
676  StrMatcher( rcstrings, cflags ) ) );
677  }
678 
679  // Finally check here, whether all involved regex compile.
680  for_( it, _attrMatchList.begin(), _attrMatchList.end() )
681  {
682  it->strMatcher.compile(); // throws on error
683  }
684  //DBG << asString() << endl;
685  }
686 
687 
691  static string wildcards2regex(const string & str)
692  {
693  string regexed = str;
694 
695  string r_all(".*"); // regex equivalent of '*'
696  string r_one("."); // regex equivalent of '?'
697  string::size_type pos;
698 
699  // replace all "*" in input with ".*"
700  for (pos = 0; (pos = regexed.find("*", pos)) != std::string::npos; pos+=2)
701  regexed = regexed.replace(pos, 1, r_all);
702 
703  // replace all "?" in input with "."
704  for (pos = 0; (pos = regexed.find('?', pos)) != std::string::npos; ++pos)
705  regexed = regexed.replace(pos, 1, r_one);
706 
707  return regexed;
708  }
709 
710  string PoolQuery::Impl::createRegex( const StrContainer & container, const Match & flags ) const
711  {
713 #define WB (_match_word ? string("\\b") : string())
714  string rstr;
715 
716  if (container.empty())
717  return rstr;
718 
719  if (container.size() == 1)
720  {
721  return WB + *container.begin() + WB;
722  }
723 
724  // multiple strings
725 
726  bool use_wildcards = flags.isModeGlob();
727  StrContainer::const_iterator it = container.begin();
728  string tmp;
729 
730  if (use_wildcards)
731  tmp = wildcards2regex(*it);
732  else
733  tmp = *it;
734 
735  if (_require_all)
736  {
737  if ( ! flags.isModeString() ) // not match exact
738  tmp += ".*" + WB + tmp;
739  rstr = "(?=" + tmp + ")";
740  }
741  else
742  {
743  if ( flags.isModeString() || flags.isModeGlob() )
744  rstr = "^";
745  rstr += WB + "(" + tmp;
746  }
747 
748  ++it;
749 
750  for (; it != container.end(); ++it)
751  {
752  if (use_wildcards)
753  tmp = wildcards2regex(*it);
754  else
755  tmp = *it;
756 
757  if (_require_all)
758  {
759  if ( ! flags.isModeString() ) // not match exact
760  tmp += ".*" + WB + tmp;
761  rstr += "(?=" + tmp + ")";
762  }
763  else
764  {
765  rstr += "|" + tmp;
766  }
767  }
768 
769  if (_require_all)
770  {
771  if ( ! flags.isModeString() ) // not match exact
772  rstr += WB + ".*";
773  }
774  else
775  {
776  rstr += ")" + WB;
777  if ( flags.isModeString() || flags.isModeGlob() )
778  rstr += "$";
779  }
780 
781  return rstr;
782 #undef WB
783  }
784 
786  {
787  ostringstream o;
788 
789  o << "kinds: ";
790  if ( _kinds.empty() )
791  o << "ALL";
792  else
793  {
794  for(Kinds::const_iterator it = _kinds.begin();
795  it != _kinds.end(); ++it)
796  o << *it << " ";
797  }
798  o << endl;
799 
800  o << "repos: ";
801  if ( _repos.empty() )
802  o << "ALL";
803  else
804  {
805  for(StrContainer::const_iterator it = _repos.begin();
806  it != _repos.end(); ++it)
807  o << *it << " ";
808  }
809  o << endl;
810 
811  o << "version: "<< _op << " " << _edition.asString() << endl;
812  o << "status: " << ( _status_flags ? ( _status_flags == INSTALLED_ONLY ? "INSTALLED_ONLY" : "UNINSTALLED_ONLY" )
813  : "ALL" ) << endl;
814 
815  o << "string match flags: " << Match(_flags) << endl;
816 
817  // raw
818  o << "strings: ";
819  for(StrContainer::const_iterator it = _strings.begin();
820  it != _strings.end(); ++it)
821  o << *it << " ";
822  o << endl;
823 
824  o << "attributes: " << endl;
825  for(AttrRawStrMap::const_iterator ai = _attrs.begin(); ai != _attrs.end(); ++ai)
826  {
827  o << "* " << ai->first << ": ";
828  for(StrContainer::const_iterator vi = ai->second.begin();
829  vi != ai->second.end(); ++vi)
830  o << *vi << " ";
831  o << endl;
832  }
833 
834  o << "predicated: " << endl;
835  for_( it, _uncompiledPredicated.begin(), _uncompiledPredicated.end() )
836  {
837  o << "* " << *it << endl;
838  }
839 
840  // compiled
841  o << "last attribute matcher compiled: " << endl;
842  if ( _attrMatchList.empty() )
843  {
844  o << "not yet compiled" << endl;
845  }
846  else
847  {
848  for_( it, _attrMatchList.begin(), _attrMatchList.end() )
849  {
850  o << "* " << *it << endl;
851  }
852  }
853  return o.str();
854  }
855 
857 
859  //
860  // CLASS NAME : PoolQuery
861  //
863 
864  PoolQuery::PoolQuery()
865  : _pimpl(new Impl())
866  {}
867 
869  {}
870 
871  void PoolQuery::addRepo(const std::string &repoalias)
872  {
873  if (repoalias.empty())
874  {
875  WAR << "ignoring an empty repository alias" << endl;
876  return;
877  }
878  _pimpl->_repos.insert(repoalias);
879  }
880 
881  void PoolQuery::addKind(const ResKind & kind)
882  { _pimpl->_kinds.insert(kind); }
883 
884  void PoolQuery::addString(const string & value)
885  { _pimpl->_strings.insert(value); }
886 
887  void PoolQuery::addAttribute(const sat::SolvAttr & attr, const std::string & value)
888  { _pimpl->_attrs[attr].insert(value); }
889 
890  void PoolQuery::addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition )
891  { return addDependency( attr, name, op, edition, Arch_empty ); }
892 
893  void PoolQuery::addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition, const Arch & arch )
894  {
895  // SolvAttr::name with explicit 'kind:name' will overwrite the default _kinds
896  ResKind explicitKind;
897  if ( attr == sat::SolvAttr::name ) explicitKind = ResKind::explicitBuiltin( name );
898 
899  switch ( op.inSwitch() )
900  {
901  case Rel::ANY_e: // no additional constraint on edition.
902  if ( arch.empty() && !explicitKind ) // no additional constraint on arch/kind
903  {
904  addAttribute( attr, name );
905  return;
906  }
907  break;
908 
909  case Rel::NONE_e: // will never match.
910  return;
911 
912  default: // go and add the predicated query (uncompiled)
913  break;
914  }
915 
916  // Match::OTHER indicates need to compile
917  // (merge global search strings into name).
918  AttrMatchData attrMatchData( attr );
919  if ( !explicitKind )
920  attrMatchData.strMatcher = StrMatcher( name, Match::OTHER );
921  else
922  {
923  // ResKind::explicitBuiltin call above asserts the presence of the ':' in name
924  attrMatchData.strMatcher = StrMatcher( strchr( name.c_str(), ':')+1, Match::OTHER );
925  attrMatchData.kindPredicate = explicitKind;
926  }
927 
928  if ( isDependencyAttribute( attr ) )
929  attrMatchData.addPredicate( EditionRangePredicate( op, edition, arch ) );
930  else
931  attrMatchData.addPredicate( SolvableRangePredicate( op, edition, arch ) );
932 
933  _pimpl->_uncompiledPredicated.insert( attrMatchData );
934  }
935 
937  {
938  CapDetail cap( cap_r );
939  if ( ! cap.isSimple() ) // will never match.
940  return;
941 
942  // Matches STRING per default. (won't get compiled!)
943  AttrMatchData attrMatchData( attr, StrMatcher( cap.name().asString() ) );
944 
945  if ( isDependencyAttribute( attr ) )
946  attrMatchData.addPredicate( CapabilityMatchPredicate( cap_r ) );
947  else
948  attrMatchData.addPredicate( SolvableRangePredicate( cap.op(), cap.ed() ) );
949 
950  _pimpl->_uncompiledPredicated.insert( attrMatchData );
951  }
952 
953  void PoolQuery::setEdition(const Edition & edition, const Rel & op)
954  {
956  _pimpl->_op = op;
957  }
958 
964  {
965  _pimpl->_match_word = true;
967  }
968 
970  { return _pimpl->_flags; }
972  { _pimpl->_flags = flags; }
973 
974 
980  { _pimpl->_status_flags = flags; }
981 
982 
983  void PoolQuery::setRequireAll(bool require_all)
984  { _pimpl->_require_all = require_all; }
985 
986 
989  { return _pimpl->_strings; }
990 
993  { return _pimpl->_attrs; }
994 
997  {
998  static const PoolQuery::StrContainer nocontainer;
999  AttrRawStrMap::const_iterator it = _pimpl->_attrs.find(attr);
1000  return it != _pimpl->_attrs.end() ? it->second : nocontainer;
1001  }
1002 
1004  { return _pimpl->_edition; }
1006  { return _pimpl->_op; }
1007 
1008 
1009  const PoolQuery::Kinds &
1011  { return _pimpl->_kinds; }
1012 
1013  const PoolQuery::StrContainer &
1015  { return _pimpl->_repos; }
1016 
1017 
1019  { return !_pimpl->_flags.test( Match::NOCASE ); }
1020  void PoolQuery::setCaseSensitive( bool value )
1021  { _pimpl->_flags.turn( Match::NOCASE, !value ); }
1022 
1024  { return _pimpl->_flags.test( Match::FILES ); }
1026  { _pimpl->_flags.turn( Match::FILES, value ); }
1027 
1028  bool PoolQuery::matchExact() const { return _pimpl->_flags.isModeString(); }
1030  bool PoolQuery::matchGlob() const { return _pimpl->_flags.isModeGlob(); }
1031  bool PoolQuery::matchRegex() const { return _pimpl->_flags.isModeRegex(); }
1032 
1034  { return _pimpl->_match_word; }
1035 
1037  { return _pimpl->_require_all; }
1038 
1040  { return _pimpl->_status_flags; }
1041 
1042  bool PoolQuery::empty() const
1043  {
1044  try { return begin() == end(); }
1045  catch (const Exception & ex) {}
1046  return true;
1047  }
1048 
1050  {
1051  try
1052  {
1053  size_type count = 0;
1054  for_( it, begin(), end() )
1055  ++count;
1056  return count;
1057  }
1058  catch (const Exception & ex) {}
1059  return 0;
1060  }
1061 
1063  { invokeOnEach( begin(), end(), fnc); }
1064 
1065 
1067  //
1068  // CLASS NAME : PoolQuery::Attr
1069  //
1074  struct PoolQueryAttr : public IdStringType<PoolQueryAttr>
1075  {
1076  private:
1079  public:
1080 
1081  //noAttr
1083 
1084  explicit PoolQueryAttr( const char* cstr_r )
1085  : _str( cstr_r )
1086  {}
1087 
1088  explicit PoolQueryAttr( const std::string & str_r )
1089  : _str( str_r )
1090  {}
1091 
1092  // unknown atributes
1093  static const PoolQueryAttr noAttr;
1094 
1095  // PoolQuery's own attributes
1096  static const PoolQueryAttr repoAttr;
1097  static const PoolQueryAttr kindAttr;
1105  };
1106 
1108 
1109  const PoolQueryAttr PoolQueryAttr::repoAttr( "repo" );
1110  const PoolQueryAttr PoolQueryAttr::kindAttr( "type" );
1111  const PoolQueryAttr PoolQueryAttr::stringAttr( "query_string" );
1112  const PoolQueryAttr PoolQueryAttr::stringTypeAttr("match_type");
1113  const PoolQueryAttr PoolQueryAttr::requireAllAttr("require_all");
1114  const PoolQueryAttr PoolQueryAttr::caseSensitiveAttr("case_sensitive");
1115  const PoolQueryAttr PoolQueryAttr::installStatusAttr("install_status");
1116  const PoolQueryAttr PoolQueryAttr::editionAttr("version");
1117  const PoolQueryAttr PoolQueryAttr::complexAttr("complex");
1118 
1119  class StringTypeAttr : public IdStringType<PoolQueryAttr>
1120  {
1123 
1124  public:
1126  explicit StringTypeAttr( const char* cstr_r )
1127  : _str( cstr_r ){}
1128  explicit StringTypeAttr( const std::string & str_r )
1129  : _str( str_r ){}
1130 
1131  static const StringTypeAttr noAttr;
1132 
1136  static const StringTypeAttr globAttr;
1137  static const StringTypeAttr wordAttr;
1138  };
1139 
1141 
1143  const StringTypeAttr StringTypeAttr::substringAttr("substring");
1147 
1149 
1150 
1151  //\TODO maybe ctor with stream can be usefull
1152  //\TODO let it throw, let it throw, let it throw.
1153  bool PoolQuery::recover( istream &str, char delim )
1154  {
1155  bool finded_something = false; //indicates some atributes is finded
1156  string s;
1157  do {
1158  if ( str.eof() )
1159  break;
1160 
1161  getline( str, s, delim );
1162 
1163  if ((!s.empty()) && s[0]=='#') //comment
1164  {
1165  continue;
1166  }
1167 
1168  string::size_type pos = s.find(':');
1169  if (s.empty() || pos == s.npos) // some garbage on line... act like blank line
1170  {
1171  if (finded_something) //is first blank line after record?
1172  {
1173  break;
1174  }
1175  else
1176  {
1177  continue;
1178  }
1179  }
1180 
1181  finded_something = true;
1182 
1183  string attrName(str::trim(string(s,0,pos))); // trimmed name of atribute
1184  string attrValue(str::trim(string(s,pos+1,s.npos))); //trimmed value
1185 
1186  PoolQueryAttr attribute( attrName );
1187 
1188  if ( attribute==PoolQueryAttr::repoAttr )
1189  {
1190  addRepo( attrValue );
1191  }
1192  /* some backwards compatibility */
1193  else if ( attribute==PoolQueryAttr::kindAttr || attribute=="kind" )
1194  {
1195  addKind( ResKind(attrValue) );
1196  }
1197  else if ( attribute==PoolQueryAttr::stringAttr
1198  || attribute=="global_string")
1199  {
1200  addString( attrValue );
1201  }
1202  else if ( attribute==PoolQueryAttr::stringTypeAttr
1203  || attribute=="string_type" )
1204  {
1205  StringTypeAttr s(attrValue);
1206  if( s == StringTypeAttr::regexAttr )
1207  {
1208  setMatchRegex();
1209  }
1210  else if ( s == StringTypeAttr::globAttr )
1211  {
1212  setMatchGlob();
1213  }
1214  else if ( s == StringTypeAttr::exactAttr )
1215  {
1216  setMatchExact();
1217  }
1218  else if ( s == StringTypeAttr::substringAttr )
1219  {
1221  }
1222  else if ( s == StringTypeAttr::wordAttr )
1223  {
1224  setMatchWord();
1225  }
1226  else if ( s == StringTypeAttr::noAttr )
1227  {
1228  WAR << "unknown string type " << attrValue << endl;
1229  }
1230  else
1231  {
1232  WAR << "forget recover some attribute defined as String type attribute: " << attrValue << endl;
1233  }
1234  }
1235  else if ( attribute==PoolQueryAttr::requireAllAttr )
1236  {
1237  if ( str::strToTrue(attrValue) )
1238  {
1239  setRequireAll(true);
1240  }
1241  else if ( !str::strToFalse(attrValue) )
1242  {
1243  setRequireAll(false);
1244  }
1245  else
1246  {
1247  WAR << "unknown boolean value " << attrValue << endl;
1248  }
1249  }
1250  else if ( attribute==PoolQueryAttr::caseSensitiveAttr )
1251  {
1252  if ( str::strToTrue(attrValue) )
1253  {
1254  setCaseSensitive(true);
1255  }
1256  else if ( !str::strToFalse(attrValue) )
1257  {
1258  setCaseSensitive(false);
1259  }
1260  else
1261  {
1262  WAR << "unknown boolean value " << attrValue << endl;
1263  }
1264  }
1265  else if ( attribute==PoolQueryAttr::installStatusAttr )
1266  {
1267  if( attrValue == "all" )
1268  {
1270  }
1271  else if( attrValue == "installed" )
1272  {
1273  setInstalledOnly();
1274  }
1275  else if( attrValue == "not-installed" )
1276  {
1278  }
1279  else
1280  {
1281  WAR << "Unknown value for install status " << attrValue << endl;
1282  }
1283  }
1284  else if ( attribute == PoolQueryAttr::editionAttr)
1285  {
1286  string::size_type pos;
1287  Rel rel("==");
1288  if (attrValue.find_first_of("=<>!") == 0)
1289  {
1290  pos = attrValue.find_last_of("=<>");
1291  rel = Rel(attrValue.substr(0, pos+1));
1292  attrValue = str::trim(attrValue.substr(pos+1, attrValue.npos));
1293  }
1294 
1295  setEdition(Edition(attrValue), rel);
1296  }
1297  else if ( attribute == PoolQueryAttr::complexAttr )
1298  {
1299  try
1300  {
1301  _pimpl->_uncompiledPredicated.insert( AttrMatchData::deserialize( attrValue ) );
1302  }
1303  catch ( const Exception & err )
1304  {
1305  WAR << "Unparsable value for complex: " << err.asUserHistory() << endl;
1306 
1307  }
1308  }
1309  else if ( attribute==PoolQueryAttr::noAttr )
1310  {
1311  WAR << "empty attribute name" << endl;
1312  }
1313  else
1314  {
1315  string s = attrName;
1316  str::replaceAll( s,"_",":" );
1317  SolvAttr a(s);
1318  if ( a == SolvAttr::name || isDependencyAttribute( a ) )
1319  {
1320  Capability c( attrValue );
1321  CapDetail d( c );
1322  if ( d.isVersioned() )
1323  addDependency( a, d.name().asString(), d.op(), d.ed() );
1324  else
1325  addDependency( a, attrValue );
1326  }
1327  else
1328  addAttribute( a, attrValue );
1329  }
1330 
1331  } while ( true );
1332 
1333  return finded_something;
1334  }
1335 
1336  void PoolQuery::serialize( ostream &str, char delim ) const
1337  {
1338  //separating delim
1339  str << delim;
1340  //iterate thrue all settings and write it
1341  static const zypp::PoolQuery q; //not save default options, so create default query example
1342 
1343  for_( it, repos().begin(), repos().end() )
1344  {
1345  str << "repo: " << *it << delim ;
1346  }
1347 
1348  for_( it, kinds().begin(), kinds().end() )
1349  {
1350  str << PoolQueryAttr::kindAttr.asString() << ": "
1351  << it->idStr() << delim ;
1352  }
1353 
1354  if (editionRel() != Rel::ANY && edition() != Edition::noedition)
1355  str << PoolQueryAttr::editionAttr.asString() << ": " << editionRel() << " " << edition() << delim;
1356 
1357  if (matchMode()!=q.matchMode())
1358  {
1359  switch( matchMode() )
1360  {
1361  case Match::STRING:
1362  str << PoolQueryAttr::stringTypeAttr.asString() << ": exact" << delim;
1363  break;
1364  case Match::SUBSTRING:
1366  << ": substring" << delim;
1367  break;
1368  case Match::GLOB:
1369  str << PoolQueryAttr::stringTypeAttr.asString() << ": glob" << delim;
1370  break;
1371  case Match::REGEX:
1372  str << PoolQueryAttr::stringTypeAttr.asString() << ": regex" << delim;
1373  break;
1374  default:
1375  WAR << "unknown match type " << matchMode() << endl;
1376  }
1377  }
1378 
1379  if( caseSensitive() != q.caseSensitive() )
1380  {
1381  str << "case_sensitive: ";
1382  if (caseSensitive())
1383  {
1384  str << "on" << delim;
1385  }
1386  else
1387  {
1388  str << "off" << delim;
1389  }
1390  }
1391 
1392  if( requireAll() != q.requireAll() )
1393  {
1394  str << "require_all: ";
1395  if (requireAll())
1396  {
1397  str << "on" << delim;
1398  }
1399  else
1400  {
1401  str << "off" << delim;
1402  }
1403  }
1404 
1405  if( statusFilterFlags() != q.statusFilterFlags() )
1406  {
1407  switch( statusFilterFlags() )
1408  {
1409  case ALL:
1410  str << "install_status: all" << delim;
1411  break;
1412  case INSTALLED_ONLY:
1413  str << "install_status: installed" << delim;
1414  break;
1415  case UNINSTALLED_ONLY:
1416  str << "install_status: not-installed" << delim;
1417  break;
1418  }
1419  }
1420 
1421  for_( it, strings().begin(), strings().end() )
1422  {
1423  str << PoolQueryAttr::stringAttr.asString()<< ": " << *it << delim;
1424  }
1425 
1426  for_( it, attributes().begin(), attributes().end() )
1427  {
1428  string s = it->first.asString();
1429  str::replaceAll(s,":","_");
1430  for_( it2,it->second.begin(),it->second.end() )
1431  {
1432  str << s <<": "<< *it2 << delim;
1433  }
1434  }
1435 
1436  for_( it, _pimpl->_uncompiledPredicated.begin(), _pimpl->_uncompiledPredicated.end() )
1437  {
1438  str << "complex: "<< it->serialize() << delim;
1439  }
1440 
1441  //separating delim - protection
1442  str << delim;
1443  }
1444 
1445  string PoolQuery::asString() const
1446  { return _pimpl->asString(); }
1447 
1448  ostream & operator<<( ostream & str, const PoolQuery & obj )
1449  { return str << obj.asString(); }
1450 
1451  std::ostream & dumpOn( std::ostream & str, const PoolQuery & obj )
1452  { return dumpRange( str << obj, obj.begin(), obj.end() ); }
1453 
1454  bool PoolQuery::operator==( const PoolQuery & rhs ) const
1455  { return *_pimpl == *rhs._pimpl; }
1456 
1457  bool PoolQuery::operator<( const PoolQuery & rhs ) const
1458  { return *_pimpl < *rhs._pimpl; }
1459 
1461  namespace detail
1462  {
1463 
1465  //
1466  // CLASS NAME : PoolQueryMatcher
1467  //
1485  {
1486  public:
1488 
1489  public:
1490  const base_iterator & end() const
1491  {
1492  static base_iterator _end;
1493  return _end;
1494  }
1495 
1496  bool advance( base_iterator & base_r ) const
1497  {
1498  if ( base_r == end() )
1499  base_r = startNewQyery(); // first candidate
1500  else
1501  {
1502  base_r.nextSkipSolvable(); // assert we don't visit this Solvable again
1503  ++base_r; // advance to next candidate
1504  }
1505 
1506  while ( base_r != end() )
1507  {
1508  if ( isAMatch( base_r ) )
1509  return true;
1510  // No match: try next
1511  ++base_r;
1512  }
1513  return false;
1514  }
1515 
1519  void matchDetail( const base_iterator & base_r, std::vector<base_iterator> & return_r ) const
1520  {
1521  if ( base_r == end() )
1522  return;
1523 
1524  sat::Solvable inSolvable( base_r.inSolvable() );
1525 
1526  if ( _attrMatchList.size() == 1 )
1527  {
1528  // base_r is already on the 1st matching attribute!
1529  // String matching is done by the base iterator. We must check the predicate here.
1530  // Let's see if there are more matches for this solvable:
1531  base_iterator base( base_r );
1532  base.stayInThisSolvable(); // avoid discarding matches we found far away from here.
1533  return_r.push_back( base );
1534 
1535  const AttrMatchData::Predicate & predicate( _attrMatchList.front().predicate );
1536  for ( ++base; base.inSolvable() == inSolvable; ++base ) // safe even if base == end()
1537  {
1538  if ( ! predicate || predicate( base ) )
1539  return_r.push_back( base );
1540  }
1541  }
1542  else
1543  {
1544  // Here: search all attributes ;(
1545  for_( mi, _attrMatchList.begin(), _attrMatchList.end() )
1546  {
1547  const AttrMatchData & matchData( *mi );
1548  sat::LookupAttr q( matchData.attr, inSolvable );
1549  if ( matchData.strMatcher ) // an empty searchstring matches always
1550  q.setStrMatcher( matchData.strMatcher );
1551 
1552  if ( ! q.empty() ) // there are matches.
1553  {
1554  // now check any predicate:
1555  const AttrMatchData::Predicate & predicate( matchData.predicate );
1556  for_( it, q.begin(), q.end() )
1557  {
1558  if ( ! predicate || predicate( it ) )
1559  return_r.push_back( it );
1560  }
1561  }
1562  }
1563  }
1564  }
1565 
1566  public:
1570  PoolQueryMatcher( const shared_ptr<const PoolQuery::Impl> & query_r )
1571  {
1572  query_r->compile();
1573 
1574  // Repo restriction:
1575  sat::Pool satpool( sat::Pool::instance() );
1576 
1577  for_( it, query_r->_repos.begin(), query_r->_repos.end() )
1578  {
1579  Repository r( satpool.reposFind( *it ) );
1580  if ( r )
1581  _repos.insert( r );
1582  else
1583  _neverMatchRepo = true;
1584  }
1585  // _neverMatchRepo: we just need to catch the case that no repo
1586  // matched, so we'd interpret the empty list as 'take from all'
1587  if ( _neverMatchRepo && ! _repos.empty() )
1588  _neverMatchRepo = false;
1589 
1590  // Kind restriction:
1591  _kinds = query_r->_kinds;
1592  // Edition restriction:
1593  _op = query_r->_op;
1594  _edition = query_r->_edition;
1595  // Status restriction:
1596  _status_flags = query_r->_status_flags;
1597  // StrMatcher
1598  _attrMatchList = query_r->_attrMatchList;
1599  }
1600 
1602  {}
1603 
1604  private:
1606  base_iterator startNewQyery() const
1607  {
1608  sat::LookupAttr q;
1609 
1610  if ( _neverMatchRepo )
1611  return q.end();
1612 
1613  // Repo restriction:
1614  if ( _repos.size() == 1 )
1615  q.setRepo( *_repos.begin() );
1616  // else: handled in isAMatch.
1617 
1618  // Attribute restriction:
1619  if ( _attrMatchList.size() == 1 ) // all (SolvAttr::allAttr) or 1 attr
1620  {
1621  const AttrMatchData & matchData( _attrMatchList.front() );
1622  q.setAttr( matchData.attr );
1623  if ( matchData.strMatcher ) // empty searchstring matches always
1624  q.setStrMatcher( matchData.strMatcher );
1625  }
1626  else // more than 1 attr (but not all)
1627  {
1628  // no restriction, it's all handled in isAMatch.
1630  }
1631 
1632  return q.begin();
1633  }
1634 
1635 
1646  bool isAMatch( base_iterator & base_r ) const
1647  {
1649  Repository inRepo( base_r.inRepo() );
1650  // Status restriction:
1651  if ( _status_flags
1652  && ( (_status_flags == PoolQuery::INSTALLED_ONLY) != inRepo.isSystemRepo() ) )
1653  {
1654  base_r.nextSkipRepo();
1655  return false;
1656  }
1657  // Repo restriction:
1658  if ( _repos.size() > 1 && _repos.find( inRepo ) == _repos.end() )
1659  {
1660  base_r.nextSkipRepo();
1661  return false;
1662  }
1664  sat::Solvable inSolvable( base_r.inSolvable() );
1665  // Edition restriction:
1666  if ( _op != Rel::ANY && !compareByRel( _op, inSolvable.edition(), _edition, Edition::Match() ) )
1667  {
1668  base_r.nextSkipSolvable();
1669  return false;
1670  }
1671 
1672  // Kind restriction:
1673  // Delay the decision to nextSkipSolvable and return false, as there may be
1674  // some explicit kind:name predicate which overrules the global kinds.
1675  bool globalKindOk =( _kinds.empty() || inSolvable.isKind( _kinds.begin(), _kinds.end() ) );
1676 
1678  // string and predicate matching:
1679 
1680  if ( _attrMatchList.size() == 1 )
1681  {
1682  // String matching was done by the base iterator.
1683  // Now check any predicate:
1684  const AttrMatchData & matchData( _attrMatchList.front() );
1685 
1686  if ( matchData.kindPredicate )
1687  {
1688  if ( matchData.kindPredicate != inSolvable.kind() )
1689  {
1690  base_r.nextSkipSolvable(); // this matchData will never match in this solvable
1691  return false;
1692  }
1693  }
1694  else if ( !globalKindOk )
1695  return false; // only matching kindPredicate could overwrite this
1696 
1697  if ( !matchData.predicate || matchData.predicate( base_r ) )
1698  return true;
1699 
1700  return false; // no skip as there may be more occurrences in this solvable of this attr.
1701  }
1702 
1703  // Here: search all attributes ;(
1704  for_( mi, _attrMatchList.begin(), _attrMatchList.end() )
1705  {
1706  const AttrMatchData & matchData( *mi );
1707 
1708  if ( matchData.kindPredicate )
1709  {
1710  if ( matchData.kindPredicate != inSolvable.kind() )
1711  continue; // this matchData does not apply
1712  }
1713  else if ( !globalKindOk )
1714  continue; // only matching kindPredicate could overwrite this
1715 
1716  sat::LookupAttr q( matchData.attr, inSolvable );
1717  if ( matchData.strMatcher ) // an empty searchstring matches always
1718  q.setStrMatcher( matchData.strMatcher );
1719 
1720  if ( ! q.empty() ) // there are matches.
1721  {
1722  // now check any predicate:
1723  const AttrMatchData::Predicate & predicate( matchData.predicate );
1724  if ( predicate )
1725  {
1726  for_( it, q.begin(), q.end() )
1727  {
1728  if ( predicate( it ) )
1729  return true;
1730  }
1731  }
1732  else
1733  return true;
1734  }
1735  }
1736  base_r.nextSkipSolvable();
1737  return false;
1738  }
1739 
1740  private:
1742  std::set<Repository> _repos;
1745  std::set<ResKind> _kinds;
1752  AttrMatchList _attrMatchList;
1753  };
1755 
1756  void PoolQueryIterator::increment()
1757  {
1758  // matcher restarts if at end! It is called from the ctor
1759  // to get the 1st match. But if the end is reached, it should
1760  // be deleted, otherwise we'd start over again.
1761  if ( !_matcher )
1762  return; // at end
1763  if ( _matches )
1764  _matches.reset(); // invalidate old matches
1765  if ( ! _matcher->advance( base_reference() ) )
1766  _matcher.reset();
1767  }
1768 
1769  const PoolQueryIterator::Matches & PoolQueryIterator::matches() const
1770  {
1771  if ( _matches )
1772  return *_matches;
1773 
1774  if ( !_matcher )
1775  {
1776  // at end of query:
1777  static const Matches _none;
1778  return _none;
1779  }
1780 
1781  _matches.reset( new Matches );
1782  _matcher->matchDetail( base_reference(), *_matches );
1783  return *_matches;
1784  }
1785 
1786  std::ostream & dumpOn( std::ostream & str, const PoolQueryIterator & obj )
1787  {
1788  str << *obj;
1789  if ( ! obj.matchesEmpty() )
1790  {
1791  for_( it, obj.matchesBegin(), obj.matchesEnd() )
1792  {
1793  str << endl << " " << it->inSolvAttr() << "\t" << it->asString();
1794  }
1795  }
1796  return str;
1797  }
1798 
1800  } //namespace detail
1802 
1804  {
1805  return shared_ptr<detail::PoolQueryMatcher>( new detail::PoolQueryMatcher( _pimpl.getPtr() ) );
1806  }
1807 
1809 } // namespace zypp
1811 
int _status_flags
Installed status filter flags.
Definition: PoolQuery.cc:1750
Interface to gettext.
static const PoolQueryAttr installStatusAttr
Definition: PoolQuery.cc:1102
bool matchExact() const
Definition: PoolQuery.cc:1028
Rel _op
Operator for edition condition.
Definition: PoolQuery.cc:405
A Solvable object within the sat Pool.
Definition: Solvable.h:53
void setUninstalledOnly()
Return only packages from repos other than .
Definition: PoolQuery.cc:977
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:1134
const AttrRawStrMap & attributes() const
Map (map<SolvAttr, StrContainer>) of attribute values added via addAttribute(), addDep in string form...
Definition: PoolQuery.cc:992
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:887
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:578
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:1745
Helper providing more detailed information about a Capability.
Definition: Capability.h:298
PoolQuery::StrContainer & _cont
Definition: PoolQuery.cc:498
Architecture.
Definition: Arch.h:36
static const StringTypeAttr noAttr
Definition: PoolQuery.cc:1131
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:519
void setFlags(const Match &flags)
Free function to set libsolv repo search flags.
Definition: PoolQuery.cc:971
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:1101
void execute(ProcessResolvable fnc)
Executes the query with the current settings.
Definition: PoolQuery.cc:1062
void addString(const std::string &value)
Add a global query string.
Definition: PoolQuery.cc:884
Lightweight attribute value lookup.
Definition: LookupAttr.h:107
Rel _op
Edition filter.
Definition: PoolQuery.cc:1747
const StrContainer & strings() const
Search strings added via addString()
Definition: PoolQuery.cc:988
constPtrType getPtr() const
Definition: PtrTypes.h:349
std::ostream & operator<<(std::ostream &str, const PoolQuery &obj)
Regular Expression.
Definition: StrMatcher.h:48
sat::SolvAttr attr
Definition: PoolQuery.cc:314
bool operator()(const string &str)
Definition: PoolQuery.cc:492
Match::Mode matchMode() const
Returns string matching mode as enum.
Definition: PoolQuery.h:428
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
void setMatchGlob()
Set to match globs.
Definition: PoolQuery.cc:962
void setMatchRegex()
Set to use the query strings as regexes.
Definition: PoolQuery.cc:961
const Arch Arch_empty(IdString::Empty)
String related utilities and Regular expression matching.
bool operator<(const PoolQuery &b) const
Definition: PoolQuery.cc:1457
PoolQueryMatcher(const shared_ptr< const PoolQuery::Impl > &query_r)
Ctor stores the PoolQuery settings.
Definition: PoolQuery.cc:1570
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:890
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:1020
Match _flags
Sat solver search flags.
Definition: PoolQuery.cc:395
Rel op() const
Definition: Capability.h:346
void addKind(const ResKind &kind)
Filter by selectable kind.
Definition: PoolQuery.cc:881
#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:1484
static const Rel ANY
Definition: Rel.h:56
Edition _edition
Edition condition operand.
Definition: PoolQuery.cc:403
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:1010
Base class for creating IdString based types.
Definition: IdStringType.h:86
#define OUTS(A)
PoolQueryAttr(const std::string &str_r)
Definition: PoolQuery.cc:1088
size_type size() const
Number of solvables in the query result.
Definition: PoolQuery.cc:1049
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:1093
bool overlaps(Rel lhs, Rel rhs, int cmp)
Compute Range overlaps.
Definition: Range.cc:30
static const PoolQueryAttr repoAttr
Definition: PoolQuery.cc:1096
bool operator==(const PoolQuery &b) const
Definition: PoolQuery.cc:1454
void serialize(std::ostream &str, char delim='\n') const
Writes a machine-readable string representation of the query to stream.
Definition: PoolQuery.cc:1336
bool operator!=(const PoolQuery::Impl &rhs) const
Definition: PoolQuery.cc:462
const StrContainer & attribute(const sat::SolvAttr &attr) const
Definition: PoolQuery.cc:996
std::vector< sat::LookupAttr::iterator > Matches
Definition: PoolQuery.h:527
AttrMatchList _attrMatchList
StrMatcher per attribtue.
Definition: PoolQuery.cc:1752
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:1018
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:1126
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:1023
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:979
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:1014
void addRepo(const std::string &repoalias)
Filter by repo.
Definition: PoolQuery.cc:871
static string wildcards2regex(const string &str)
Converts &#39;*&#39; and &#39;?&#39; wildcards within str into their regex equivalents.
Definition: PoolQuery.cc:691
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
void setMatchWord()
Set to match words (uses regex)
Definition: PoolQuery.cc:963
const_iterator begin() const
Query result accessers.
Definition: PoolQuery.cc:1803
#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
std::ostream & dumpOn(std::ostream &str, const PoolQuery &obj)
Definition: PoolQuery.cc:1451
void setStrMatcher(const StrMatcher &matcher_r)
Set the pattern to match.
Definition: LookupAttr.cc:205
MyInserter(PoolQuery::StrContainer &cont)
Definition: PoolQuery.cc:490
base_iterator startNewQyery() const
Initialize a new base query.
Definition: PoolQuery.cc:1606
sat::LookupAttr::iterator base_iterator
Definition: PoolQuery.cc:1487
void nextSkipSolvable()
On the next call to operator++ advance to the next Solvable.
Definition: LookupAttr.cc:363
const Rel editionRel() const
Definition: PoolQuery.cc:1005
static const SolvAttr name
Definition: SolvAttr.h:52
StringTypeAttr(const std::string &str_r)
Definition: PoolQuery.cc:1128
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:411
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:975
static const StringTypeAttr exactAttr
Definition: PoolQuery.cc:1133
bool recover(std::istream &str, char delim='\n')
Reads from stream query.
Definition: PoolQuery.cc:1153
const base_iterator & end() const
Definition: PoolQuery.cc:1490
void matchDetail(const base_iterator &base_r, std::vector< base_iterator > &return_r) const
Provide all matching attributes within this solvable.
Definition: PoolQuery.cc:1519
bool advance(base_iterator &base_r) const
Definition: PoolQuery.cc:1496
const_iterator end() const
An iterator pointing to the end of the query result.
Definition: PoolQuery.h:624
static const PoolQueryAttr stringTypeAttr
Definition: PoolQuery.cc:1099
static const StringTypeAttr wordAttr
Definition: PoolQuery.cc:1137
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:1003
bool operator<(const PoolQuery::Impl &rhs) const
Definition: PoolQuery.cc:416
bool operator!=(const SetRelation::Enum &lhs, const SetCompare &rhs)
void setMatchSubstring()
Set to substring (the default).
Definition: PoolQuery.cc:959
represents all atributes in PoolQuery except SolvAtributes, which are used as is (not needed extend a...
Definition: PoolQuery.cc:1074
#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:1742
std::string predicateStr
Definition: PoolQuery.cc:317
static const PoolQueryAttr stringAttr
Definition: PoolQuery.cc:1098
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:392
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:1033
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:1104
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:953
void setMatchExact()
Set to match exact string instead of substring.
Definition: PoolQuery.cc:960
A sat capability.
Definition: Capability.h:59
Excat matching.
Definition: StrMatcher.h:43
#define WB
Predicate predicate
Definition: PoolQuery.cc:316
StatusFilter statusFilterFlags() const
Definition: PoolQuery.cc:1039
void nextSkipRepo()
On the next call to operator++ advance to the next Repository.
Definition: LookupAttr.cc:366
bool matchSubstring() const
Definition: PoolQuery.cc:1029
StrContainer _repos
Repos to search.
Definition: PoolQuery.cc:408
Global sat-pool.
Definition: Pool.h:44
bool operator()(const string &str)
Definition: PoolQuery.cc:504
bool empty() const
Whether the result is empty.
Definition: PoolQuery.cc:1042
DefaultIntegral< bool, false > _neverMatchRepo
Definition: PoolQuery.cc:1743
static const PoolQueryAttr requireAllAttr
Definition: PoolQuery.cc:1100
Match flags() const
Free function to get libsolv repo search flags.
Definition: PoolQuery.cc:969
static const PoolQueryAttr editionAttr
Definition: PoolQuery.cc:1103
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:1025
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:489
AttrMatchList _attrMatchList
StrMatcher per attribtue.
Definition: PoolQuery.cc:473
StatusFilter _status_flags
Sat solver status flags.
Definition: PoolQuery.cc:400
Impl * clone() const
clone for RWCOW_pointer
Definition: PoolQuery.cc:482
PoolQueryAttr(const char *cstr_r)
Definition: PoolQuery.cc:1084
bool isAMatch(base_iterator &base_r) const
Check whether we are on a match.
Definition: PoolQuery.cc:1646
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:1445
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:1097
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:1030
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:1036
StrContainer _strings
Raw search strings.
Definition: PoolQuery.cc:388
bool isModeString() const
Whether this has mode STRING.
Definition: StrMatcher.h:164
StrMatcher strMatcher
Definition: PoolQuery.cc:315
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:905
ResKind kindPredicate
Definition: PoolQuery.cc:318
bool empty() const
Whether the query is empty.
Definition: LookupAttr.cc:242
bool matchRegex() const
Definition: PoolQuery.cc:1031
static const StringTypeAttr globAttr
Definition: PoolQuery.cc:1136
iterator begin() const
Iterator to the begin of query results.
Definition: LookupAttr.cc:236
AttrRawStrMap _attrs
Raw attributes.
Definition: PoolQuery.cc:390
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:434
static const StringTypeAttr regexAttr
Definition: PoolQuery.cc:1135
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:983
bool isModeSubstring() const
Whether this has mode SUBSTRING.
Definition: StrMatcher.h:173