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