libzypp  15.28.6
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  , _status_flags(ALL)
375  {}
376 
378  {}
379 
380  public:
382  string asString() const;
383 
391  std::set<AttrMatchData> _uncompiledPredicated;
392 
396 
399 
404 
407 
411 
412  public:
413 
414  bool operator<( const PoolQuery::Impl & rhs ) const
415  {
416 #define OUTS(A) if ( A != rhs.A ) return A < rhs.A;
417  OUTS( _strings );
418  OUTS( _attrs );
419  OUTS( _uncompiledPredicated );
420  OUTS( _flags.get() );
421  OUTS( _match_word );
422  OUTS( _status_flags );
423  OUTS( _edition );
424  OUTS( _op.inSwitch() );
425  OUTS( _repos );
426  OUTS( _kinds );
427 #undef OUTS
428  return false;
429  }
430 
431  bool operator==( const PoolQuery::Impl & rhs ) const
432  {
433  if ( _flags == rhs._flags
434  // bnc#792901: while libzypp uses exact match mode for a single
435  // package name lock, zypper always uses glob. :(
436  // We unify those two forms to enable zypper to remove zypp locks
437  // without need to actually evaluate the query (which would require
438  // repos to be loaded).
439  || ( ( ( _flags.isModeString() && rhs._flags.isModeGlob() )
440  || ( _flags.isModeGlob() && rhs._flags.isModeString() ) )
441  && _strings.empty()
442  && _attrs.size() == 1
443  && _attrs.begin()->first == sat::SolvAttr::name ) )
444  {
445  return ( _strings == rhs._strings
446  && _attrs == rhs._attrs
447  && _uncompiledPredicated == rhs._uncompiledPredicated
448  && _match_word == rhs._match_word
449  && _status_flags == rhs._status_flags
450  && _edition == rhs._edition
451  && _op == rhs._op
452  && _repos == rhs._repos
453  && _kinds == rhs._kinds );
454  }
455  return false;
456  }
457 
458  bool operator!=( const PoolQuery::Impl & rhs ) const
459  { return ! operator==( rhs ); }
460 
461  public:
466  void compile() const;
467 
469  mutable AttrMatchList _attrMatchList;
470 
471  private:
475  StrMatcher joinedStrMatcher( const StrContainer & container_r, const Match & flags_r ) const;
476 
477  private:
478  friend Impl * rwcowClone<Impl>( const Impl * rhs );
480  Impl * clone() const
481  { return new Impl( *this ); }
482  };
483 
485 
486  struct MyInserter
487  {
488  MyInserter(PoolQuery::StrContainer & cont) : _cont(cont) {}
489 
490  bool operator()(const string & str)
491  {
492  _cont.insert(str);
493  return true;
494  }
495 
497  };
498 
499 
500  struct EmptyFilter
501  {
502  bool operator()(const string & str)
503  {
504  return !str.empty();
505  }
506  };
507 
508  void PoolQuery::Impl::compile() const
509  {
510  _attrMatchList.clear();
511 
512  if ( _flags.mode() == Match::OTHER ) // this will never succeed...
514 
515  // 'different' - will have to iterate through all and match by ourselves (slow)
516  // 'same' - will pass the compiled string to dataiterator_init
517  // 'one-attr' - will pass it to dataiterator_init
518  // 'one-non-regex-str' - will pass to dataiterator_init, set flag to SEARCH_STRING or SEARCH_SUBSTRING
519 
520  // // NO ATTRIBUTE
521  // else
522  // for all _strings
523  // create regex; store in rcstrings; if more strings flag regex;
524  if (_attrs.empty())
525  {
526  ; // A default 'query-all' will be added after all sources are processed.
527  }
528 
529  // // ONE ATTRIBUTE
530  // else if _attrs is not empty but it contains just one attr
531  // for all _strings and _attr[key] strings
532  // create regex; flag 'one-attr'; if more strings flag regex;
533  else if (_attrs.size() == 1)
534  {
535  StrContainer joined;
536  invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
537  invokeOnEach(_attrs.begin()->second.begin(), _attrs.begin()->second.end(), EmptyFilter(), MyInserter(joined));
538 
539  _attrMatchList.push_back( AttrMatchData( _attrs.begin()->first, joinedStrMatcher( joined, _flags ) ) );
540  }
541 
542  // // MULTIPLE ATTRIBUTES
543  else
544  {
545  // check whether there are any per-attribute strings
546  bool attrvals_empty = true;
547  for_( ai, _attrs.begin(), _attrs.end() )
548  {
549  if ( ai->second.empty() )
550  continue;
551  for_( it, ai->second.begin(), ai->second.end() )
552  {
553  if ( !it->empty() )
554  {
555  attrvals_empty = false;
556  break;
557  }
558  }
559  if ( ! attrvals_empty )
560  break;
561  }
562 
563  // chceck whether the per-attribute strings are all the same
564  bool attrvals_thesame = true;
565  AttrRawStrMap::const_iterator ai = _attrs.begin();
566  const StrContainer & set1 = ai->second;
567  ++ai;
568  for (; ai != _attrs.end(); ++ai)
569  {
570  StrContainer result;
571  set_difference(
572  set1.begin(), set1.end(),
573  ai->second.begin(), ai->second.end(),
574  inserter(result, result.begin())/*, ltstr()*/);
575  if (!result.empty())
576  {
577  attrvals_thesame = false;
578  break;
579  }
580  }
581 
582  // // THE SAME STRINGS FOR DIFFERENT ATTRS
583  // else if _attrs is not empty but it does not contain strings
584  // for each key in _attrs take all _strings
585  // create regex; store in rcstrings; flag 'same'; if more strings flag regex;
586  if (attrvals_empty || attrvals_thesame)
587  {
588  StrContainer joined;
589  if (attrvals_empty)
590  {
591  invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
592  }
593  else
594  {
595  invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
596  invokeOnEach(_attrs.begin()->second.begin(), _attrs.begin()->second.end(), EmptyFilter(), MyInserter(joined));
597  }
598 
599  // May use the same StrMatcher for all
600  StrMatcher matcher( joinedStrMatcher( joined, _flags ) );
601  for_( ai, _attrs.begin(), _attrs.end() )
602  {
603  _attrMatchList.push_back( AttrMatchData( ai->first, matcher ) );
604  }
605  }
606 
607  // // DIFFERENT STRINGS FOR DIFFERENT ATTRS
608  // if _attrs is not empty and it contains non-empty vectors with non-empty strings
609  // for each key in _attrs take all _strings + all _attrs[key] strings
610  // create regex; flag 'different'; if more strings flag regex;
611  else
612  {
613  for_(ai, _attrs.begin(), _attrs.end())
614  {
615  StrContainer joined;
616  invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
617  invokeOnEach(ai->second.begin(), ai->second.end(), EmptyFilter(), MyInserter(joined));
618 
619  _attrMatchList.push_back( AttrMatchData( ai->first, joinedStrMatcher( joined, _flags ) ) );
620  }
621  }
622  }
623 
624  // Now handle any predicated queries
625  if ( ! _uncompiledPredicated.empty() )
626  {
627  StrContainer global;
628  invokeOnEach( _strings.begin(), _strings.end(), EmptyFilter(), MyInserter(global) );
629  for_( it, _uncompiledPredicated.begin(), _uncompiledPredicated.end() )
630  {
631  if ( it->strMatcher.flags().mode() == Match::OTHER )
632  {
633  // need to compile:
634  StrContainer joined( global );
635  const std::string & mstr( it->strMatcher.searchstring() );
636  if ( ! mstr.empty() )
637  joined.insert( mstr );
638 
639  // copy and exchange the StrMatcher
640  AttrMatchData nattr( *it );
641  nattr.strMatcher = joinedStrMatcher( joined, _flags );
642  _attrMatchList.push_back( std::move(nattr) );
643  }
644  else
645  {
646  // copy matcher
647  _attrMatchList.push_back( *it );
648  }
649  }
650  }
651 
652  // If no attributes defined at all, then add 'query all'
653  if ( _attrMatchList.empty() )
654  {
655  _attrMatchList.push_back( AttrMatchData( sat::SolvAttr::allAttr, joinedStrMatcher( _strings, _flags ) ) );
656  }
657 
658  // Finally check here, whether all involved regex compile.
659  for_( it, _attrMatchList.begin(), _attrMatchList.end() )
660  {
661  it->strMatcher.compile(); // throws on error
662  }
663  //DBG << asString() << endl;
664  }
665 
667  namespace
668  {
673  std::string rxEscape( std::string str_r, const Match & flags_r )
674  {
675  if ( str_r.empty() || flags_r.isModeRegex() )
676  return str_r;
677 
678  if ( flags_r.isModeGlob() )
679  return str::rxEscapeGlob( std::move(str_r) );
680 
681  return str::rxEscapeStr( std::move(str_r) );
682  }
683  } // namespace
685 
686  StrMatcher PoolQuery::Impl::joinedStrMatcher( const StrContainer & container_r, const Match & flags_r ) const
687  {
688  if ( container_r.empty() )
689  return StrMatcher( std::string(), flags_r );
690 
691  if ( container_r.size() == 1 && !_match_word ) // use RX to match words
692  return StrMatcher( *container_r.begin(), flags_r );
693 
694  // Convert to a regex.
695  // Note: Modes STRING and GLOB match whole strings (anchored ^ $)
696  // SUBSTRING and REGEX match substrings (match_word anchores SUBSTRING \b)
697  Match retflags( flags_r );
698  retflags.setModeRegex();
699  str::Str ret;
700 
701  if ( flags_r.isModeString() || flags_r.isModeGlob() )
702  ret << "^";
703  else if ( _match_word )
704  ret << "\\b";
705 
706  // (..|..|..)
707  char sep = '(';
708  for ( const::std::string & s : container_r )
709  {
710  ret << sep << rxEscape( s, flags_r );
711  if ( sep == '(' )
712  sep = '|';
713  }
714  ret << ')';
715 
716  if ( flags_r.isModeString() || flags_r.isModeGlob() )
717  ret << "$";
718  else if ( _match_word )
719  ret << "\\b";
720 
721  return StrMatcher( ret, retflags );
722  }
723 
725  {
726  ostringstream o;
727 
728  o << "kinds: ";
729  if ( _kinds.empty() )
730  o << "ALL";
731  else
732  {
733  for(Kinds::const_iterator it = _kinds.begin();
734  it != _kinds.end(); ++it)
735  o << *it << " ";
736  }
737  o << endl;
738 
739  o << "repos: ";
740  if ( _repos.empty() )
741  o << "ALL";
742  else
743  {
744  for(StrContainer::const_iterator it = _repos.begin();
745  it != _repos.end(); ++it)
746  o << *it << " ";
747  }
748  o << endl;
749 
750  o << "version: "<< _op << " " << _edition.asString() << endl;
751  o << "status: " << ( _status_flags ? ( _status_flags == INSTALLED_ONLY ? "INSTALLED_ONLY" : "UNINSTALLED_ONLY" )
752  : "ALL" ) << endl;
753 
754  o << "string match flags: " << Match(_flags) << endl;
755 
756  // raw
757  o << "strings: ";
758  for(StrContainer::const_iterator it = _strings.begin();
759  it != _strings.end(); ++it)
760  o << *it << " ";
761  o << endl;
762 
763  o << "attributes: " << endl;
764  for(AttrRawStrMap::const_iterator ai = _attrs.begin(); ai != _attrs.end(); ++ai)
765  {
766  o << "* " << ai->first << ": ";
767  for(StrContainer::const_iterator vi = ai->second.begin();
768  vi != ai->second.end(); ++vi)
769  o << *vi << " ";
770  o << endl;
771  }
772 
773  o << "predicated: " << endl;
774  for_( it, _uncompiledPredicated.begin(), _uncompiledPredicated.end() )
775  {
776  o << "* " << *it << endl;
777  }
778 
779  // compiled
780  o << "last attribute matcher compiled: " << endl;
781  if ( _attrMatchList.empty() )
782  {
783  o << "not yet compiled" << endl;
784  }
785  else
786  {
787  for_( it, _attrMatchList.begin(), _attrMatchList.end() )
788  {
789  o << "* " << *it << endl;
790  }
791  }
792  return o.str();
793  }
794 
796 
798  //
799  // CLASS NAME : PoolQuery
800  //
802 
803  PoolQuery::PoolQuery()
804  : _pimpl(new Impl())
805  {}
806 
808  {}
809 
810  void PoolQuery::addRepo(const std::string &repoalias)
811  {
812  if (repoalias.empty())
813  {
814  WAR << "ignoring an empty repository alias" << endl;
815  return;
816  }
817  _pimpl->_repos.insert(repoalias);
818  }
819 
820  void PoolQuery::addKind(const ResKind & kind)
821  { _pimpl->_kinds.insert(kind); }
822 
823  void PoolQuery::addString(const string & value)
824  { _pimpl->_strings.insert(value); }
825 
826  void PoolQuery::addAttribute(const sat::SolvAttr & attr, const std::string & value)
827  { _pimpl->_attrs[attr].insert(value); }
828 
829  void PoolQuery::addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition )
830  { return addDependency( attr, name, op, edition, Arch_empty ); }
831 
832  void PoolQuery::addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition, const Arch & arch )
833  {
834  // SolvAttr::name with explicit 'kind:name' will overwrite the default _kinds
835  ResKind explicitKind;
836  if ( attr == sat::SolvAttr::name ) explicitKind = ResKind::explicitBuiltin( name );
837 
838  switch ( op.inSwitch() )
839  {
840  case Rel::ANY_e: // no additional constraint on edition.
841  if ( arch.empty() && !explicitKind ) // no additional constraint on arch/kind
842  {
843  addAttribute( attr, name );
844  return;
845  }
846  break;
847 
848  case Rel::NONE_e: // will never match.
849  return;
850 
851  default: // go and add the predicated query (uncompiled)
852  break;
853  }
854 
855  // Match::OTHER indicates need to compile
856  // (merge global search strings into name).
857  AttrMatchData attrMatchData( attr );
858  if ( !explicitKind )
859  attrMatchData.strMatcher = StrMatcher( name, Match::OTHER );
860  else
861  {
862  // ResKind::explicitBuiltin call above asserts the presence of the ':' in name
863  attrMatchData.strMatcher = StrMatcher( strchr( name.c_str(), ':')+1, Match::OTHER );
864  attrMatchData.kindPredicate = explicitKind;
865  }
866 
867  if ( isDependencyAttribute( attr ) )
868  attrMatchData.addPredicate( EditionRangePredicate( op, edition, arch ) );
869  else
870  attrMatchData.addPredicate( SolvableRangePredicate( op, edition, arch ) );
871 
872  _pimpl->_uncompiledPredicated.insert( attrMatchData );
873  }
874 
876  {
877  CapDetail cap( cap_r );
878  if ( ! cap.isSimple() ) // will never match.
879  return;
880 
881  // Matches STRING per default. (won't get compiled!)
882  AttrMatchData attrMatchData( attr, StrMatcher( cap.name().asString() ) );
883 
884  if ( isDependencyAttribute( attr ) )
885  attrMatchData.addPredicate( CapabilityMatchPredicate( cap_r ) );
886  else
887  attrMatchData.addPredicate( SolvableRangePredicate( cap.op(), cap.ed() ) );
888 
889  _pimpl->_uncompiledPredicated.insert( attrMatchData );
890  }
891 
892  void PoolQuery::setEdition(const Edition & edition, const Rel & op)
893  {
895  _pimpl->_op = op;
896  }
897 
903 
905  { return _pimpl->_flags; }
906  void PoolQuery::setFlags( const Match & flags )
907  { _pimpl->_flags = flags; }
908 
909 
915  { _pimpl->_status_flags = flags; }
916 
917 
920  { return _pimpl->_strings; }
921 
924  { return _pimpl->_attrs; }
925 
928  {
929  static const PoolQuery::StrContainer nocontainer;
930  AttrRawStrMap::const_iterator it = _pimpl->_attrs.find(attr);
931  return it != _pimpl->_attrs.end() ? it->second : nocontainer;
932  }
933 
935  { return _pimpl->_edition; }
937  { return _pimpl->_op; }
938 
939 
940  const PoolQuery::Kinds &
942  { return _pimpl->_kinds; }
943 
946  { return _pimpl->_repos; }
947 
948 
950  { return !_pimpl->_flags.test( Match::NOCASE ); }
951  void PoolQuery::setCaseSensitive( bool value )
952  { _pimpl->_flags.turn( Match::NOCASE, !value ); }
953 
955  { return _pimpl->_flags.test( Match::FILES ); }
957  { _pimpl->_flags.turn( Match::FILES, value ); }
958 
959  bool PoolQuery::matchExact() const { return _pimpl->_flags.isModeString(); }
961  bool PoolQuery::matchGlob() const { return _pimpl->_flags.isModeGlob(); }
962  bool PoolQuery::matchRegex() const { return _pimpl->_flags.isModeRegex(); }
964 
966  { return _pimpl->_status_flags; }
967 
968  bool PoolQuery::empty() const
969  {
970  try { return begin() == end(); }
971  catch (const Exception & ex) {}
972  return true;
973  }
974 
976  {
977  try
978  {
979  size_type count = 0;
980  for_( it, begin(), end() )
981  ++count;
982  return count;
983  }
984  catch (const Exception & ex) {}
985  return 0;
986  }
987 
989  { invokeOnEach( begin(), end(), fnc); }
990 
991 
992  /*DEPRECATED LEGACY:*/void PoolQuery::setRequireAll( bool ) {}
993  /*DEPRECATED LEGACY:*/bool PoolQuery::requireAll() const { return false; }
994 
996  //
997  // CLASS NAME : PoolQuery::Attr
998  //
1003  struct PoolQueryAttr : public IdStringType<PoolQueryAttr>
1004  {
1005  private:
1008  public:
1009 
1010  //noAttr
1012 
1013  explicit PoolQueryAttr( const char* cstr_r )
1014  : _str( cstr_r )
1015  {}
1016 
1017  explicit PoolQueryAttr( const std::string & str_r )
1018  : _str( str_r )
1019  {}
1020 
1021  // unknown atributes
1022  static const PoolQueryAttr noAttr;
1023 
1024  // PoolQuery's own attributes
1025  static const PoolQueryAttr repoAttr;
1026  static const PoolQueryAttr kindAttr;
1029  static const PoolQueryAttr requireAllAttr; // LEAGACY: attribute was defined but never implemented.
1034  };
1035 
1037 
1038  const PoolQueryAttr PoolQueryAttr::repoAttr( "repo" );
1039  const PoolQueryAttr PoolQueryAttr::kindAttr( "type" );
1040  const PoolQueryAttr PoolQueryAttr::stringAttr( "query_string" );
1041  const PoolQueryAttr PoolQueryAttr::stringTypeAttr("match_type");
1042  const PoolQueryAttr PoolQueryAttr::requireAllAttr("require_all"); // LEAGACY: attribute was defined but never implemented.
1043  const PoolQueryAttr PoolQueryAttr::caseSensitiveAttr("case_sensitive");
1044  const PoolQueryAttr PoolQueryAttr::installStatusAttr("install_status");
1045  const PoolQueryAttr PoolQueryAttr::editionAttr("version");
1046  const PoolQueryAttr PoolQueryAttr::complexAttr("complex");
1047 
1048  class StringTypeAttr : public IdStringType<PoolQueryAttr>
1049  {
1052 
1053  public:
1055  explicit StringTypeAttr( const char* cstr_r )
1056  : _str( cstr_r ){}
1057  explicit StringTypeAttr( const std::string & str_r )
1058  : _str( str_r ){}
1059 
1060  static const StringTypeAttr noAttr;
1061 
1065  static const StringTypeAttr globAttr;
1066  static const StringTypeAttr wordAttr;
1067  };
1068 
1070 
1072  const StringTypeAttr StringTypeAttr::substringAttr("substring");
1076 
1078 
1079 
1080  //\TODO maybe ctor with stream can be usefull
1081  //\TODO let it throw, let it throw, let it throw.
1082  bool PoolQuery::recover( istream &str, char delim )
1083  {
1084  bool finded_something = false; //indicates some atributes is finded
1085  string s;
1086  do {
1087  if ( str.eof() )
1088  break;
1089 
1090  getline( str, s, delim );
1091 
1092  if ((!s.empty()) && s[0]=='#') //comment
1093  {
1094  continue;
1095  }
1096 
1097  string::size_type pos = s.find(':');
1098  if (s.empty() || pos == s.npos) // some garbage on line... act like blank line
1099  {
1100  if (finded_something) //is first blank line after record?
1101  {
1102  break;
1103  }
1104  else
1105  {
1106  continue;
1107  }
1108  }
1109 
1110  finded_something = true;
1111 
1112  string attrName(str::trim(string(s,0,pos))); // trimmed name of atribute
1113  string attrValue(str::trim(string(s,pos+1,s.npos))); //trimmed value
1114 
1115  PoolQueryAttr attribute( attrName );
1116 
1117  if ( attribute==PoolQueryAttr::repoAttr )
1118  {
1119  addRepo( attrValue );
1120  }
1121  /* some backwards compatibility */
1122  else if ( attribute==PoolQueryAttr::kindAttr || attribute=="kind" )
1123  {
1124  addKind( ResKind(attrValue) );
1125  }
1126  else if ( attribute==PoolQueryAttr::stringAttr
1127  || attribute=="global_string")
1128  {
1129  addString( attrValue );
1130  }
1131  else if ( attribute==PoolQueryAttr::stringTypeAttr
1132  || attribute=="string_type" )
1133  {
1134  StringTypeAttr s(attrValue);
1135  if( s == StringTypeAttr::regexAttr )
1136  {
1137  setMatchRegex();
1138  }
1139  else if ( s == StringTypeAttr::globAttr )
1140  {
1141  setMatchGlob();
1142  }
1143  else if ( s == StringTypeAttr::exactAttr )
1144  {
1145  setMatchExact();
1146  }
1147  else if ( s == StringTypeAttr::substringAttr )
1148  {
1150  }
1151  else if ( s == StringTypeAttr::wordAttr )
1152  {
1153  setMatchWord();
1154  }
1155  else if ( s == StringTypeAttr::noAttr )
1156  {
1157  WAR << "unknown string type " << attrValue << endl;
1158  }
1159  else
1160  {
1161  WAR << "forget recover some attribute defined as String type attribute: " << attrValue << endl;
1162  }
1163  }
1164  else if ( attribute==PoolQueryAttr::requireAllAttr )
1165  {
1166  // LEAGACY: attribute was defined but never implemented.
1167  // Actually it should not occur outside our testcases.
1168  }
1169  else if ( attribute==PoolQueryAttr::caseSensitiveAttr )
1170  {
1171  if ( str::strToTrue(attrValue) )
1172  {
1173  setCaseSensitive(true);
1174  }
1175  else if ( !str::strToFalse(attrValue) )
1176  {
1177  setCaseSensitive(false);
1178  }
1179  else
1180  {
1181  WAR << "unknown boolean value " << attrValue << endl;
1182  }
1183  }
1184  else if ( attribute==PoolQueryAttr::installStatusAttr )
1185  {
1186  if( attrValue == "all" )
1187  {
1189  }
1190  else if( attrValue == "installed" )
1191  {
1192  setInstalledOnly();
1193  }
1194  else if( attrValue == "not-installed" )
1195  {
1197  }
1198  else
1199  {
1200  WAR << "Unknown value for install status " << attrValue << endl;
1201  }
1202  }
1203  else if ( attribute == PoolQueryAttr::editionAttr)
1204  {
1205  string::size_type pos;
1206  Rel rel("==");
1207  if (attrValue.find_first_of("=<>!") == 0)
1208  {
1209  pos = attrValue.find_last_of("=<>");
1210  rel = Rel(attrValue.substr(0, pos+1));
1211  attrValue = str::trim(attrValue.substr(pos+1, attrValue.npos));
1212  }
1213 
1214  setEdition(Edition(attrValue), rel);
1215  }
1216  else if ( attribute == PoolQueryAttr::complexAttr )
1217  {
1218  try
1219  {
1221  }
1222  catch ( const Exception & err )
1223  {
1224  WAR << "Unparsable value for complex: " << err.asUserHistory() << endl;
1225 
1226  }
1227  }
1228  else if ( attribute==PoolQueryAttr::noAttr )
1229  {
1230  WAR << "empty attribute name" << endl;
1231  }
1232  else
1233  {
1234  string s = attrName;
1235  str::replaceAll( s,"_",":" );
1236  SolvAttr a(s);
1237  if ( a == SolvAttr::name || isDependencyAttribute( a ) )
1238  {
1239  Capability c( attrValue );
1240  CapDetail d( c );
1241  if ( d.isVersioned() )
1242  addDependency( a, d.name().asString(), d.op(), d.ed() );
1243  else
1244  addDependency( a, attrValue );
1245  }
1246  else
1247  addAttribute( a, attrValue );
1248  }
1249 
1250  } while ( true );
1251 
1252  // OLD STYLE VERSIONED LOCKS:
1253  // solvable_name: kernel
1254  // version: > 1
1255  //
1256  // NEW STYLE VERSIONED LOCKS:
1257  // complex: AttrMatchData solvable:name kernel C SolvableRange\ >\ 1\ \"\"
1258  // or
1259  // solvable_name: kernel > 1
1260  //
1261  // Semantically equivalent as locks, but due to the different syntax
1262  // the complex lock is wrongly handled by zypper.
1263  //
1264  // bsc#1112911: Unfortunately all styles are found in real-life locks-files.
1265  // libzypp will try to make sure, when parsing the locks-file, that complex
1266  // locks are rewritten into to OLD STYLE queries zypper can handle.
1267  if ( !_pimpl->_attrs.count(SolvAttr::name) && _pimpl->_uncompiledPredicated.size() == 1 )
1268  {
1269  // No OLD STYLE lock for SolvAttr::name and exactly one complex lock...
1270  const AttrMatchData & attrmatch { *_pimpl->_uncompiledPredicated.begin() };
1271  if ( attrmatch.attr == SolvAttr::name && attrmatch.strMatcher.flags().mode() == Match::OTHER )
1272  {
1273  // ...for SolvAttr::name and following the global search flags.
1274  // A candidate for a rewrite?
1275 
1276  std::vector<std::string> words;
1277  str::splitEscaped( attrmatch.predicateStr, std::back_inserter(words) );
1278  if ( words.size() < 4 || words[3].empty() )
1279  {
1280  // We have _NO_ arch rule in the complex predicate, so we can simplify it.
1281  //
1282  // NOTE: AFAIK it's not possible to create (or have created) a complex lock
1283  // with arch rule with zypper means. Nevertheless, in case such a rule made it
1284  // into a locks file, it's better to have a strange looking 'zypper locks' list
1285  // than to lock the wrong packages.
1286  // (and remember that you can't use "addAttribute( SolvAttr::arch, ... )" because
1287  // attributes are `OR`ed)
1288 
1289  // kind
1290  if ( attrmatch.kindPredicate )
1291  {
1292  _pimpl->_kinds.clear(); // an explicit kind overwrites any global one
1293  addKind( attrmatch.kindPredicate );
1294  }
1295 
1296  // name
1297  addAttribute( SolvAttr::name, attrmatch.strMatcher.searchstring() );
1298 
1299  // edition
1300  std::vector<std::string> words;
1301  str::splitEscaped( attrmatch.predicateStr, std::back_inserter(words) );
1302  if ( ! words.empty() )
1303  {
1304  if ( words[0] == "EditionRange" || words[0] == "SolvableRange" )
1305  {
1306  setEdition( Edition(words[2]), Rel(words[1]) );
1307  }
1308  }
1309 
1310  // finally remove the complex lock
1311  _pimpl->_uncompiledPredicated.clear();
1312  }
1313  }
1314  }
1315 
1316  return finded_something;
1317  }
1318 
1319  void PoolQuery::serialize( ostream &str, char delim ) const
1320  {
1321  //separating delim
1322  str << delim;
1323  //iterate thrue all settings and write it
1324  static const zypp::PoolQuery q; //not save default options, so create default query example
1325 
1326  for_( it, repos().begin(), repos().end() )
1327  {
1328  str << "repo: " << *it << delim ;
1329  }
1330 
1331  for_( it, kinds().begin(), kinds().end() )
1332  {
1333  str << PoolQueryAttr::kindAttr.asString() << ": "
1334  << it->idStr() << delim ;
1335  }
1336 
1337  if (editionRel() != Rel::ANY && edition() != Edition::noedition)
1338  str << PoolQueryAttr::editionAttr.asString() << ": " << editionRel() << " " << edition() << delim;
1339 
1340  if (matchMode()!=q.matchMode())
1341  {
1342  switch( matchMode() )
1343  {
1344  case Match::STRING:
1345  str << PoolQueryAttr::stringTypeAttr.asString() << ": exact" << delim;
1346  break;
1347  case Match::SUBSTRING:
1349  << ": substring" << delim;
1350  break;
1351  case Match::GLOB:
1352  str << PoolQueryAttr::stringTypeAttr.asString() << ": glob" << delim;
1353  break;
1354  case Match::REGEX:
1355  str << PoolQueryAttr::stringTypeAttr.asString() << ": regex" << delim;
1356  break;
1357  default:
1358  WAR << "unknown match type " << matchMode() << endl;
1359  }
1360  }
1361 
1362  if( caseSensitive() != q.caseSensitive() )
1363  {
1364  str << "case_sensitive: ";
1365  if (caseSensitive())
1366  {
1367  str << "on" << delim;
1368  }
1369  else
1370  {
1371  str << "off" << delim;
1372  }
1373  }
1374 
1375  if( statusFilterFlags() != q.statusFilterFlags() )
1376  {
1377  switch( statusFilterFlags() )
1378  {
1379  case ALL:
1380  str << "install_status: all" << delim;
1381  break;
1382  case INSTALLED_ONLY:
1383  str << "install_status: installed" << delim;
1384  break;
1385  case UNINSTALLED_ONLY:
1386  str << "install_status: not-installed" << delim;
1387  break;
1388  }
1389  }
1390 
1391  for_( it, strings().begin(), strings().end() )
1392  {
1393  str << PoolQueryAttr::stringAttr.asString()<< ": " << *it << delim;
1394  }
1395 
1396  for_( it, attributes().begin(), attributes().end() )
1397  {
1398  string s = it->first.asString();
1399  str::replaceAll(s,":","_");
1400  for_( it2,it->second.begin(),it->second.end() )
1401  {
1402  str << s <<": "<< *it2 << delim;
1403  }
1404  }
1405 
1407  {
1408  str << "complex: "<< it->serialize() << delim;
1409  }
1410 
1411  //separating delim - protection
1412  str << delim;
1413  }
1414 
1415  string PoolQuery::asString() const
1416  { return _pimpl->asString(); }
1417 
1418  ostream & operator<<( ostream & str, const PoolQuery & obj )
1419  { return str << obj.asString(); }
1420 
1421  std::ostream & dumpOn( std::ostream & str, const PoolQuery & obj )
1422  { return dumpRange( str << obj, obj.begin(), obj.end() ); }
1423 
1424  bool PoolQuery::operator==( const PoolQuery & rhs ) const
1425  { return *_pimpl == *rhs._pimpl; }
1426 
1427  bool PoolQuery::operator<( const PoolQuery & rhs ) const
1428  { return *_pimpl < *rhs._pimpl; }
1429 
1431  namespace detail
1432  {
1433 
1435  //
1436  // CLASS NAME : PoolQueryMatcher
1437  //
1455  {
1456  public:
1458 
1459  public:
1460  const base_iterator & end() const
1461  {
1462  static base_iterator _end;
1463  return _end;
1464  }
1465 
1466  bool advance( base_iterator & base_r ) const
1467  {
1468  if ( base_r == end() )
1469  base_r = startNewQyery(); // first candidate
1470  else
1471  {
1472  base_r.nextSkipSolvable(); // assert we don't visit this Solvable again
1473  ++base_r; // advance to next candidate
1474  }
1475 
1476  while ( base_r != end() )
1477  {
1478  if ( isAMatch( base_r ) )
1479  return true;
1480  // No match: try next
1481  ++base_r;
1482  }
1483  return false;
1484  }
1485 
1489  void matchDetail( const base_iterator & base_r, std::vector<base_iterator> & return_r ) const
1490  {
1491  if ( base_r == end() )
1492  return;
1493 
1494  sat::Solvable inSolvable( base_r.inSolvable() );
1495 
1496  if ( _attrMatchList.size() == 1 )
1497  {
1498  // base_r is already on the 1st matching attribute!
1499  // String matching is done by the base iterator. We must check the predicate here.
1500  // Let's see if there are more matches for this solvable:
1501  base_iterator base( base_r );
1502  base.stayInThisSolvable(); // avoid discarding matches we found far away from here.
1503  return_r.push_back( base );
1504 
1505  const AttrMatchData::Predicate & predicate( _attrMatchList.front().predicate );
1506  for ( ++base; base.inSolvable() == inSolvable; ++base ) // safe even if base == end()
1507  {
1508  if ( ! predicate || predicate( base ) )
1509  return_r.push_back( base );
1510  }
1511  }
1512  else
1513  {
1514  // Here: search all attributes ;(
1515  for_( mi, _attrMatchList.begin(), _attrMatchList.end() )
1516  {
1517  const AttrMatchData & matchData( *mi );
1518  sat::LookupAttr q( matchData.attr, inSolvable );
1519  if ( matchData.strMatcher ) // an empty searchstring matches always
1520  q.setStrMatcher( matchData.strMatcher );
1521 
1522  if ( ! q.empty() ) // there are matches.
1523  {
1524  // now check any predicate:
1525  const AttrMatchData::Predicate & predicate( matchData.predicate );
1526  for_( it, q.begin(), q.end() )
1527  {
1528  if ( ! predicate || predicate( it ) )
1529  return_r.push_back( it );
1530  }
1531  }
1532  }
1533  }
1534  }
1535 
1536  public:
1540  PoolQueryMatcher( const shared_ptr<const PoolQuery::Impl> & query_r )
1541  {
1542  query_r->compile();
1543 
1544  // Repo restriction:
1545  sat::Pool satpool( sat::Pool::instance() );
1546 
1547  for_( it, query_r->_repos.begin(), query_r->_repos.end() )
1548  {
1549  Repository r( satpool.reposFind( *it ) );
1550  if ( r )
1551  _repos.insert( r );
1552  else
1553  _neverMatchRepo = true;
1554  }
1555  // _neverMatchRepo: we just need to catch the case that no repo
1556  // matched, so we'd interpret the empty list as 'take from all'
1557  if ( _neverMatchRepo && ! _repos.empty() )
1558  _neverMatchRepo = false;
1559 
1560  // Kind restriction:
1561  _kinds = query_r->_kinds;
1562  // Edition restriction:
1563  _op = query_r->_op;
1564  _edition = query_r->_edition;
1565  // Status restriction:
1566  _status_flags = query_r->_status_flags;
1567  // StrMatcher
1568  _attrMatchList = query_r->_attrMatchList;
1569  }
1570 
1572  {}
1573 
1574  private:
1577  {
1578  sat::LookupAttr q;
1579 
1580  if ( _neverMatchRepo )
1581  return q.end();
1582 
1583  // Repo restriction:
1584  if ( _repos.size() == 1 )
1585  q.setRepo( *_repos.begin() );
1586  // else: handled in isAMatch.
1587 
1588  // Attribute restriction:
1589  if ( _attrMatchList.size() == 1 ) // all (SolvAttr::allAttr) or 1 attr
1590  {
1591  const AttrMatchData & matchData( _attrMatchList.front() );
1592  q.setAttr( matchData.attr );
1593  if ( matchData.strMatcher ) // empty searchstring matches always
1594  q.setStrMatcher( matchData.strMatcher );
1595  }
1596  else // more than 1 attr (but not all)
1597  {
1598  // no restriction, it's all handled in isAMatch.
1600  }
1601 
1602  return q.begin();
1603  }
1604 
1605 
1616  bool isAMatch( base_iterator & base_r ) const
1617  {
1619  Repository inRepo( base_r.inRepo() );
1620  // Status restriction:
1621  if ( _status_flags
1622  && ( (_status_flags == PoolQuery::INSTALLED_ONLY) != inRepo.isSystemRepo() ) )
1623  {
1624  base_r.nextSkipRepo();
1625  return false;
1626  }
1627  // Repo restriction:
1628  if ( _repos.size() > 1 && _repos.find( inRepo ) == _repos.end() )
1629  {
1630  base_r.nextSkipRepo();
1631  return false;
1632  }
1634  sat::Solvable inSolvable( base_r.inSolvable() );
1635  // Edition restriction:
1636  if ( _op != Rel::ANY && !compareByRel( _op, inSolvable.edition(), _edition, Edition::Match() ) )
1637  {
1638  base_r.nextSkipSolvable();
1639  return false;
1640  }
1641 
1642  // Kind restriction:
1643  // Delay the decision to nextSkipSolvable and return false, as there may be
1644  // some explicit kind:name predicate which overrules the global kinds.
1645  bool globalKindOk =( _kinds.empty() || inSolvable.isKind( _kinds.begin(), _kinds.end() ) );
1646 
1648  // string and predicate matching:
1649 
1650  if ( _attrMatchList.size() == 1 )
1651  {
1652  // String matching was done by the base iterator.
1653  // Now check any predicate:
1654  const AttrMatchData & matchData( _attrMatchList.front() );
1655 
1656  if ( matchData.kindPredicate )
1657  {
1658  if ( matchData.kindPredicate != inSolvable.kind() )
1659  {
1660  base_r.nextSkipSolvable(); // this matchData will never match in this solvable
1661  return false;
1662  }
1663  }
1664  else if ( !globalKindOk )
1665  return false; // only matching kindPredicate could overwrite this
1666 
1667  if ( !matchData.predicate || matchData.predicate( base_r ) )
1668  return true;
1669 
1670  return false; // no skip as there may be more occurrences in this solvable of this attr.
1671  }
1672 
1673  // Here: search all attributes ;(
1674  for_( mi, _attrMatchList.begin(), _attrMatchList.end() )
1675  {
1676  const AttrMatchData & matchData( *mi );
1677 
1678  if ( matchData.kindPredicate )
1679  {
1680  if ( matchData.kindPredicate != inSolvable.kind() )
1681  continue; // this matchData does not apply
1682  }
1683  else if ( !globalKindOk )
1684  continue; // only matching kindPredicate could overwrite this
1685 
1686  sat::LookupAttr q( matchData.attr, inSolvable );
1687  if ( matchData.strMatcher ) // an empty searchstring matches always
1688  q.setStrMatcher( matchData.strMatcher );
1689 
1690  if ( ! q.empty() ) // there are matches.
1691  {
1692  // now check any predicate:
1693  const AttrMatchData::Predicate & predicate( matchData.predicate );
1694  if ( predicate )
1695  {
1696  for_( it, q.begin(), q.end() )
1697  {
1698  if ( predicate( it ) )
1699  return true;
1700  }
1701  }
1702  else
1703  return true;
1704  }
1705  }
1706  base_r.nextSkipSolvable();
1707  return false;
1708  }
1709 
1710  private:
1712  std::set<Repository> _repos;
1715  std::set<ResKind> _kinds;
1722  AttrMatchList _attrMatchList;
1723  };
1725 
1727  {
1728  // matcher restarts if at end! It is called from the ctor
1729  // to get the 1st match. But if the end is reached, it should
1730  // be deleted, otherwise we'd start over again.
1731  if ( !_matcher )
1732  return; // at end
1733  if ( _matches )
1734  _matches.reset(); // invalidate old matches
1735  if ( ! _matcher->advance( base_reference() ) )
1736  _matcher.reset();
1737  }
1738 
1740  {
1741  if ( _matches )
1742  return *_matches;
1743 
1744  if ( !_matcher )
1745  {
1746  // at end of query:
1747  static const Matches _none;
1748  return _none;
1749  }
1750 
1751  _matches.reset( new Matches );
1752  _matcher->matchDetail( base_reference(), *_matches );
1753  return *_matches;
1754  }
1755 
1756  std::ostream & dumpOn( std::ostream & str, const PoolQueryIterator & obj )
1757  {
1758  str << *obj;
1759  if ( ! obj.matchesEmpty() )
1760  {
1761  for_( it, obj.matchesBegin(), obj.matchesEnd() )
1762  {
1763  str << endl << " " << it->inSolvAttr() << "\t" << it->asString();
1764  }
1765  }
1766  return str;
1767  }
1768 
1770  } //namespace detail
1772 
1774  {
1775  return shared_ptr<detail::PoolQueryMatcher>( new detail::PoolQueryMatcher( _pimpl.getPtr() ) );
1776  }
1777 
1779 } // namespace zypp
1781 
const Rel editionRel() const
Definition: PoolQuery.cc:936
unsigned splitEscaped(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \t", bool withEmpty=false)
Split line_r into words with respect to escape delimeters.
Definition: String.h:577
int _status_flags
Installed status filter flags.
Definition: PoolQuery.cc:1720
Interface to gettext.
static const PoolQueryAttr installStatusAttr
Definition: PoolQuery.cc:1031
Rel _op
Operator for edition condition.
Definition: PoolQuery.cc:403
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:904
A Solvable object within the sat Pool.
Definition: Solvable.h:53
void setUninstalledOnly()
Return only packages from repos other than .
Definition: PoolQuery.cc:912
StatusFilter
Installed status filter setters.
Definition: PoolQuery.h:162
Arch _arch
Definition: PoolQuery.cc:102
static const StringTypeAttr substringAttr
Definition: PoolQuery.cc:1063
bool compareByRel(Rel op, const Tp &lhs, const Tp &rhs, TCompare compare)
Comparison of two elements using relational operator op.
Definition: RelCompare.h:108
bool advance(base_iterator &base_r) const
Definition: PoolQuery.cc:1466
void addAttribute(const sat::SolvAttr &attr, const std::string &value="")
Filter by the value of the specified attr attribute.
Definition: PoolQuery.cc:826
void setAttr(SolvAttr attr_r)
Set the SolvAttr to search.
Definition: LookupAttr.cc:199
std::set< ResKind > Kinds
Definition: PoolQuery.h:93
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:321
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
std::set< ResKind > _kinds
Resolvable kinds to include.
Definition: PoolQuery.cc:1715
Helper providing more detailed information about a Capability.
Definition: Capability.h:298
PoolQuery::StrContainer & _cont
Definition: PoolQuery.cc:496
std::ostream & dumpOn(std::ostream &str, const PoolQueryIterator &obj)
Definition: PoolQuery.cc:1756
bool operator==(const PoolQuery::Impl &rhs) const
Definition: PoolQuery.cc:431
Architecture.
Definition: Arch.h:36
std::string rxEscapeStr(std::string str_r)
Escape plain STRING str_r for use in a regex (not anchored by "^" or "$").
Definition: String.cc:413
const StrContainer & strings() const
Search strings added via addString()
Definition: PoolQuery.cc:919
static const StringTypeAttr noAttr
Definition: PoolQuery.cc:1060
const StrContainer & attribute(const sat::SolvAttr &attr) const
Definition: PoolQuery.cc:927
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:500
void setFlags(const Match &flags)
Free function to set libsolv repo search flags.
Definition: PoolQuery.cc:906
String matching (STRING|SUBSTRING|GLOB|REGEX).
Definition: StrMatcher.h:297
Relational operators.
Definition: Rel.h:43
static const PoolQueryAttr caseSensitiveAttr
Definition: PoolQuery.cc:1030
bool requireAll() const ZYPP_DEPRECATED
Definition: PoolQuery.cc:993
void execute(ProcessResolvable fnc)
Executes the query with the current settings.
Definition: PoolQuery.cc:988
void addString(const std::string &value)
Add a global query string.
Definition: PoolQuery.cc:823
bool filesMatchFullPath() const
Whether searching in filelists looks at the full path or just at the basenames.
Definition: PoolQuery.cc:954
bool operator==(const PoolQuery &b) const
Definition: PoolQuery.cc:1424
Lightweight attribute value lookup.
Definition: LookupAttr.h:107
Rel _op
Edition filter.
Definition: PoolQuery.cc:1717
const Edition edition() const
Definition: PoolQuery.cc:934
Regular Expression.
Definition: StrMatcher.h:48
sat::SolvAttr attr
Definition: PoolQuery.cc:314
bool operator()(const string &str)
Definition: PoolQuery.cc:490
void setMatchGlob()
Set to match globs.
Definition: PoolQuery.cc:901
void setMatchRegex()
Set to use the query strings as regexes.
Definition: PoolQuery.cc:900
const Arch Arch_empty(IdString::Empty)
bool recover(std::istream &str, char delim= '\n')
Reads from stream query.
Definition: PoolQuery.cc:1082
const Matches & matches() const
Definition: PoolQuery.cc:1739
const std::string & asString(const std::string &t)
Global asString() that works with std::string too.
Definition: String.h:136
bool operator!=(const PoolQuery::Impl &rhs) const
Definition: PoolQuery.cc:458
PoolQueryMatcher(const shared_ptr< const PoolQuery::Impl > &query_r)
Ctor stores the PoolQuery settings.
Definition: PoolQuery.cc:1540
void addDependency(const sat::SolvAttr &attr, const std::string &name, const Rel &op, const Edition &edition)
Query "name|global op edition".
Definition: PoolQuery.cc:829
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:951
Match _flags
Sat solver search flags.
Definition: PoolQuery.cc:394
void addKind(const ResKind &kind)
Filter by selectable kind.
Definition: PoolQuery.cc:820
#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:1454
static const Rel ANY
Definition: Rel.h:56
Edition _edition
Edition condition operand.
Definition: PoolQuery.cc:401
bool caseSensitive() const
returns true if search is case sensitive
Definition: PoolQuery.cc:949
bool operator==(const SetRelation::Enum &lhs, const SetCompare &rhs)
void setModeSubstring()
Set the mode SUBSTRING.
Definition: StrMatcher.h:195
bool empty() const
Test for an empty Arch (this is Arch_epmty, not Arch_noarch ).
Definition: Arch.h:63
Base class for creating IdString based types.
Definition: IdStringType.h:86
#define OUTS(A)
PoolQueryAttr(const std::string &str_r)
Definition: PoolQuery.cc:1017
const StrContainer & repos() const
Definition: PoolQuery.cc:945
std::string asString() const
Conversion to std::string
Definition: IdString.h:91
constPtrType getPtr() const
Definition: PtrTypes.h:349
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:1022
bool overlaps(Rel lhs, Rel rhs, int cmp)
Compute Range overlaps.
Definition: Range.cc:30
static const PoolQueryAttr repoAttr
Definition: PoolQuery.cc:1025
std::vector< sat::LookupAttr::iterator > Matches
Definition: PoolQuery.h:508
AttrMatchList _attrMatchList
StrMatcher per attribtue.
Definition: PoolQuery.cc:1722
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
Match::Mode matchMode() const
Returns string matching mode as enum.
Definition: PoolQuery.h:409
std::string getline(std::istream &str)
Read one line from stream.
Definition: IOStream.cc:33
unsigned int size_type
Definition: PoolQuery.h:98
string asString() const
String representation.
Definition: PoolQuery.cc:724
StringTypeAttr(const char *cstr_r)
Definition: PoolQuery.cc:1055
static Pool instance()
Singleton ctor.
Definition: Pool.h:53
std::ostream & dumpRange(std::ostream &str, TIterator begin, TIterator end, const std::string &intro="{", const std::string &pfx="\n ", const std::string &sep="\n ", const std::string &sfx="\n", const std::string &extro="}")
Print range defined by iterators (multiline style).
Definition: LogTools.h:91
void setRequireAll(bool require_all=true) ZYPP_DEPRECATED
Definition: PoolQuery.cc:992
Solvable attribute keys.
Definition: SolvAttr.h:40
std::set< std::string > StrContainer
Definition: PoolQuery.h:94
iterator end() const
Iterator behind the end of query results.
Definition: LookupAttr.cc:239
bool isModeGlob() const
Whether this has mode GLOB.
Definition: StrMatcher.h:176
bool isVersioned() const
Definition: Capability.h:337
std::string rxEscapeGlob(std::string str_r)
Escape GLOB str_r for use in a regex (not anchored by "^" or "$").
Definition: String.cc:418
void setRepo(Repository repo_r, Location=SOLV_ATTR)
Set search in one Repository.
Definition: LookupAttr.cc:219
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition: String.h:210
void setStatusFilterFlags(StatusFilter flags)
Set status filter directly.
Definition: PoolQuery.cc:914
std::ostream & operator<<(std::ostream &str, const Exception &obj)
Definition: Exception.cc:120
match functor.
Definition: Edition.h:160
void matchDetail(const base_iterator &base_r, std::vector< base_iterator > &return_r) const
Provide all matching attributes within this solvable.
Definition: PoolQuery.cc:1489
std::string trim(const std::string &s, const Trim trim_r)
Definition: String.cc:221
std::string asString() const
Definition: IdStringType.h:106
bool matchWord() const
Definition: PoolQuery.cc:963
void addRepo(const std::string &repoalias)
Filter by repo.
Definition: PoolQuery.cc:810
const AttrRawStrMap & attributes() const
Map (map<SolvAttr, StrContainer>) of attribute values added via addAttribute(), addDep in string form...
Definition: PoolQuery.cc:923
void setModeRegex()
Set the mode REGEX.
Definition: StrMatcher.h:201
Solvable inSolvable() const
The current Solvable.
Definition: LookupAttr.cc:354
void setMatchWord()
Set substring to match words.
Definition: PoolQuery.cc:902
#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
Repository reposFind(const std::string &alias_r) const
Find a Repository named alias_r.
Definition: Pool.cc:142
bool isAMatch(base_iterator &base_r) const
Check whether we are on a match.
Definition: PoolQuery.cc:1616
void setStrMatcher(const StrMatcher &matcher_r)
Set the pattern to match.
Definition: LookupAttr.cc:205
MyInserter(PoolQuery::StrContainer &cont)
Definition: PoolQuery.cc:488
Match flags() const
Free function to get libsolv repo search flags.
Definition: PoolQuery.cc:904
sat::LookupAttr::iterator base_iterator
Definition: PoolQuery.cc:1457
bool matchExact() const
Definition: PoolQuery.cc:959
void nextSkipSolvable()
On the next call to operator++ advance to the next Solvable.
Definition: LookupAttr.cc:363
static const SolvAttr name
Definition: SolvAttr.h:52
std::ostream & dumpOn(std::ostream &str, const Capability &obj)
Definition: Capability.cc:446
StringTypeAttr(const std::string &str_r)
Definition: PoolQuery.cc:1057
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:409
void setInstalledOnly()
Return only repo packages.
Definition: PoolQuery.cc:910
static const StringTypeAttr exactAttr
Definition: PoolQuery.cc:1062
base_iterator startNewQyery() const
Initialize a new base query.
Definition: PoolQuery.cc:1576
static const PoolQueryAttr stringTypeAttr
Definition: PoolQuery.cc:1028
static const StringTypeAttr wordAttr
Definition: PoolQuery.cc:1066
SolvableIdType size_type
Definition: PoolMember.h:152
std::ostream & operator<<(std::ostream &str, const zypp::shared_ptr< void > &obj)
Definition: PtrTypes.h:134
bool empty() const
Whether the query is empty.
Definition: LookupAttr.cc:242
Repository inRepo() const
The current Repository.
Definition: LookupAttr.cc:351
bool operator!=(const SetRelation::Enum &lhs, const SetCompare &rhs)
bool matchGlob() const
Definition: PoolQuery.cc:961
void setMatchSubstring()
Set to substring (the default).
Definition: PoolQuery.cc:898
represents all atributes in PoolQuery except SolvAtributes, which are used as is (not needed extend a...
Definition: PoolQuery.cc:1003
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:1712
std::string predicateStr
Definition: PoolQuery.cc:317
bool isModeSubstring() const
Whether this has mode SUBSTRING.
Definition: StrMatcher.h:173
static const PoolQueryAttr stringAttr
Definition: PoolQuery.cc:1027
bool deserialize(const std::string &str_r, DownloadMode &result_r)
Definition: DownloadMode.cc:23
std::map< sat::SolvAttr, StrContainer > AttrRawStrMap
Definition: PoolQuery.h:95
bool matchSubstring() const
Definition: PoolQuery.cc:960
std::set< AttrMatchData > _uncompiledPredicated
Uncompiled attributes with predicate.
Definition: PoolQuery.cc:391
StatusFilter statusFilterFlags() const
Definition: PoolQuery.cc:965
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
Base class for Exception.
Definition: Exception.h:143
bool isModeRegex() const
Whether this has mode REGEX.
Definition: StrMatcher.h:179
const Kinds & kinds() const
Definition: PoolQuery.cc:941
bool empty() const
Whether the result is empty.
Definition: PoolQuery.cc:968
static const PoolQueryAttr complexAttr
Definition: PoolQuery.cc:1033
void setEdition(const Edition &edition, const Rel &op=Rel::EQ)
Set version condition.
Definition: PoolQuery.cc:892
void setMatchExact()
Set to match exact string instead of substring.
Definition: PoolQuery.cc:899
bool matchRegex() const
Definition: PoolQuery.cc:962
A sat capability.
Definition: Capability.h:59
Excat matching.
Definition: StrMatcher.h:43
Predicate predicate
Definition: PoolQuery.cc:316
shared_ptr< PoolQueryMatcher > _matcher
Definition: PoolQuery.h:589
void nextSkipRepo()
On the next call to operator++ advance to the next Repository.
Definition: LookupAttr.cc:366
bool isSimple() const
Definition: Capability.h:338
StrContainer _repos
Repos to search.
Definition: PoolQuery.cc:406
bool operator<(const PoolQuery::Impl &rhs) const
Definition: PoolQuery.cc:414
Global sat-pool.
Definition: Pool.h:44
bool operator()(const string &str)
Definition: PoolQuery.cc:502
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Definition: Exception.cc:75
Edition ed() const
Definition: Capability.h:347
size_type size() const
Number of solvables in the query result.
Definition: PoolQuery.cc:975
shared_ptr< Matches > _matches
Definition: PoolQuery.h:590
DefaultIntegral< bool, false > _neverMatchRepo
Definition: PoolQuery.cc:1713
static const PoolQueryAttr requireAllAttr
Definition: PoolQuery.cc:1029
void serialize(std::ostream &str, char delim= '\n') const
Writes a machine-readable string representation of the query to stream.
Definition: PoolQuery.cc:1319
static const PoolQueryAttr editionAttr
Definition: PoolQuery.cc:1032
for_use_in_switch inSwitch() const
Enumarator provided for use in switch statement.
Definition: Rel.h:141
void setFilesMatchFullPath(bool value=true)
If set (default), look at the full path when searching in filelists.
Definition: PoolQuery.cc:956
bool operator<(const PoolQuery &b) const
Definition: PoolQuery.cc:1427
RW_pointer< Impl > _pimpl
Pointer to implementation.
Definition: PoolQuery.h:470
AttrMatchList _attrMatchList
StrMatcher per attribtue.
Definition: PoolQuery.cc:469
const_iterator begin() const
Query result accessers.
Definition: PoolQuery.cc:1773
StatusFilter _status_flags
Sat solver status flags.
Definition: PoolQuery.cc:398
PoolQueryAttr(const char *cstr_r)
Definition: PoolQuery.cc:1013
Impl * clone() const
clone for RWCOW_pointer
Definition: PoolQuery.cc:480
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
const_iterator end() const
An iterator pointing to the end of the query result.
Definition: PoolQuery.h:605
bool operator<(const StrMatcher &lhs, const StrMatcher &rhs)
Definition: StrMatcher.cc:316
std::string asString() const
Return a human-readable description of the query.
Definition: PoolQuery.cc:1415
Resolvable kinds.
Definition: ResKind.h:32
static const PoolQueryAttr kindAttr
Definition: PoolQuery.cc:1026
function< bool(const sat::Solvable &)> ProcessResolvable
Definition: PoolQuery.h:101
Rel op() const
Definition: Capability.h:346
static const Match FILES
LookupAttr: match full path when matching in filelists, otherwise just the basenames.
Definition: StrMatcher.h:75
StrContainer _strings
Raw search strings.
Definition: PoolQuery.cc:387
StrMatcher strMatcher
Definition: PoolQuery.cc:315
IdString name() const
Definition: Capability.h:345
ResKind kindPredicate
Definition: PoolQuery.cc:318
static const StringTypeAttr globAttr
Definition: PoolQuery.cc:1065
AttrRawStrMap _attrs
Raw attributes.
Definition: PoolQuery.cc:389
static const Edition noedition
Value representing noedition ("") This is in fact a valid Edition.
Definition: Edition.h:73
Something else.
Definition: StrMatcher.h:49
const base_iterator & end() const
Definition: PoolQuery.cc:1460
iterator begin() const
Iterator to the begin of query results.
Definition: LookupAttr.cc:236
static const StringTypeAttr regexAttr
Definition: PoolQuery.cc:1064
bool isModeString() const
Whether this has mode STRING.
Definition: StrMatcher.h:164
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