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