libzypp 17.37.17
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
47 bool isDependencyAttribute( const sat::SolvAttr& attr_r )
48 {
49 static sat::SolvAttr deps[] = {
58 };
59 for_( it, arrayBegin(deps), arrayEnd(deps) )
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
102 Edition::MatchRange _range;
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
135 Edition::MatchRange _range;
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
161 Capability _cap;
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
206 AttrMatchData( sat::SolvAttr attr_r, StrMatcher strMatcher_r )
207 : attr(std::move( attr_r ))
208 , strMatcher(std::move( strMatcher_r ))
209 {}
210
211 AttrMatchData( sat::SolvAttr attr_r, StrMatcher strMatcher_r,
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 ))
216 , predicateStr(std::move( predicateStr_r ))
217 {}
218
224 template<class TPredicate>
225 void addPredicate( const TPredicate & predicate_r )
226 {
227 predicate = predicate_r;
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
312 sat::SolvAttr attr;
313 StrMatcher strMatcher;
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 )
421 , _match_word(false)
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
438
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:
531 StrMatcher joinedStrMatcher( const StrContainer & container_r, const Match & flags_r ) const;
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 {
591 StrContainer joined;
592 invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
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;
627 set_difference(
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;
642 if (attrvals_empty || attrvals_thesame)
643 {
644 StrContainer joined;
645 if (attrvals_empty)
646 {
647 invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
648 }
649 else
650 {
651 invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
652 invokeOnEach(_attrs.begin()->second.begin(), _attrs.begin()->second.end(), EmptyFilter(), MyInserter(joined));
653 }
654
655 // May use the same StrMatcher for all
656 StrMatcher matcher( joinedStrMatcher( joined, _flags ) );
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 {
671 StrContainer joined;
672 invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
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 {
683 StrContainer global;
684 invokeOnEach( _strings.begin(), _strings.end(), EmptyFilter(), MyInserter(global) );
686 {
687 if ( it->strMatcher.flags().mode() == Match::OTHER )
688 {
689 // need to compile:
690 StrContainer joined( global );
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
742 StrMatcher PoolQuery::Impl::joinedStrMatcher( const StrContainer & container_r, const Match & flags_r ) const
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)
753 Match retflags( flags_r );
754 retflags.setModeRegex();
755 str::Str ret;
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;
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
860 : _pimpl(new Impl())
861 {}
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
877 { _pimpl->_kinds.insert(kind); }
878
879 void PoolQuery::setComment(const std::string & comment) const
880 { _pimpl->_comment = comment; }
881
882 void PoolQuery::addString(const std::string & value)
883 { _pimpl->_strings.insert(value); }
884
885 void PoolQuery::addAttribute(const sat::SolvAttr & attr, const std::string & value)
886 { _pimpl->_attrs[attr].insert(value); }
887
888 void PoolQuery::addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition )
889 {
890 // Default Match::OTHER indicates need to compile, i.e. to merge name into the global search string and mode.
891 return addDependency( attr, name, op, edition, Arch_empty, Match::OTHER );
892 }
893
894 void PoolQuery::addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition, const Arch & arch )
895 {
896 // Default Match::OTHER indicates need to compile, i.e. to merge name into the global search string and mode.
897 return addDependency( attr, name, op, edition, arch, Match::OTHER );
898 }
899
900 void PoolQuery::addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition, const Arch & arch, Match::Mode mode )
901 {
902 if ( op == Rel::NONE ) // will never match.
903 return;
904
905 // SolvAttr::name with explicit 'kind:name' will overwrite the default _kinds
906 ResKind explicitKind;
907 if ( attr == sat::SolvAttr::name )
908 explicitKind = ResKind::explicitBuiltin( name );
909
910 // Legacy: Match::OTHER and no additional constraints on edition/arch/kind
911 // require addAttribute, otherwise de-serialisation breaks (serialized
912 // and de-serialized query could be !=).
913 // From the results POV we could also use the predicated case below.
914 if ( op == Rel::ANY && arch.empty() && !explicitKind && mode == Match::OTHER )
915 {
916 addAttribute( attr, name );
917 return;
918 }
919
920 // Match::OTHER indicates need to compile
921 // (merge global search strings into name).
922 AttrMatchData attrMatchData( attr );
923 if ( !explicitKind )
924 attrMatchData.strMatcher = StrMatcher( name, mode );
925 else
926 {
927 // ResKind::explicitBuiltin call above asserts the presence of the ':' in name
928 attrMatchData.strMatcher = StrMatcher( strchr( name.c_str(), ':')+1, mode );
929 attrMatchData.kindPredicate = explicitKind;
930 }
931
932 if ( isDependencyAttribute( attr ) )
933 attrMatchData.addPredicate( EditionRangePredicate( op, edition, arch ) );
934 else
935 attrMatchData.addPredicate( SolvableRangePredicate( op, edition, arch ) );
936
937 _pimpl->_uncompiledPredicated.insert( attrMatchData );
938 }
939
941 {
942 CapDetail cap( cap_r );
943 if ( ! cap.isSimple() ) // will never match.
944 return;
945
946 // Matches STRING per default. (won't get compiled!)
947 AttrMatchData attrMatchData( attr, StrMatcher( cap.name().asString() ) );
948
949 if ( isDependencyAttribute( attr ) )
950 attrMatchData.addPredicate( CapabilityMatchPredicate( cap_r ) );
951 else
952 attrMatchData.addPredicate( SolvableRangePredicate( cap.op(), cap.ed() ) );
953
954 _pimpl->_uncompiledPredicated.insert( attrMatchData );
955 }
956
957 void PoolQuery::setEdition(const Edition & edition, const Rel & op)
958 {
959 _pimpl->_edition = edition;
960 _pimpl->_op = op;
961 }
962
963 void PoolQuery::setMatchSubstring() { _pimpl->_flags.setModeSubstring(); _pimpl->_match_word = false; }
964 void PoolQuery::setMatchExact() { _pimpl->_flags.setModeString(); _pimpl->_match_word = false; }
965 void PoolQuery::setMatchRegex() { _pimpl->_flags.setModeRegex(); _pimpl->_match_word = false; }
966 void PoolQuery::setMatchGlob() { _pimpl->_flags.setModeGlob(); _pimpl->_match_word = false; }
967 void PoolQuery::setMatchWord() { _pimpl->_flags.setModeSubstring(); _pimpl->_match_word = true; }
968
970 { return _pimpl->_flags; }
972 { _pimpl->_flags = flags; }
973
974
976 { _pimpl->_status_flags = INSTALLED_ONLY; }
978 { _pimpl->_status_flags = UNINSTALLED_ONLY; }
981
982
985 { return _pimpl->_strings; }
986
989 { return _pimpl->_attrs; }
990
993 {
994 static const PoolQuery::StrContainer nocontainer;
995 AttrRawStrMap::const_iterator it = _pimpl->_attrs.find(attr);
996 return it != _pimpl->_attrs.end() ? it->second : nocontainer;
997 }
998
1000 { return _pimpl->_edition; }
1002 { return _pimpl->_op; }
1003
1004
1005 const PoolQuery::Kinds &
1007 { return _pimpl->_kinds; }
1008
1011 { return _pimpl->_repos; }
1012
1013 const std::string &
1015 { return _pimpl->_comment; }
1016
1018 { return !_pimpl->_flags.test( Match::NOCASE ); }
1020 { _pimpl->_flags.turn( Match::NOCASE, !value ); }
1021
1023 { return _pimpl->_flags.test( Match::FILES ); }
1025 { _pimpl->_flags.turn( Match::FILES, value ); }
1026
1027 bool PoolQuery::matchExact() const { return _pimpl->_flags.isModeString(); }
1028 bool PoolQuery::matchSubstring() const { return _pimpl->_flags.isModeSubstring() && !_pimpl->_match_word; }
1029 bool PoolQuery::matchGlob() const { return _pimpl->_flags.isModeGlob(); }
1030 bool PoolQuery::matchRegex() const { return _pimpl->_flags.isModeRegex(); }
1031 bool PoolQuery::matchWord() const { return _pimpl->_flags.isModeSubstring() && _pimpl->_match_word; }
1032
1034 { return _pimpl->_status_flags; }
1035
1036 bool PoolQuery::empty() const
1037 {
1038 try { return begin() == end(); }
1039 catch (const Exception & ex) {}
1040 return true;
1041 }
1042
1044 {
1045 try
1046 {
1047 size_type count = 0;
1048 for_( it, begin(), end() )
1049 ++count;
1050 return count;
1051 }
1052 catch (const Exception & ex) {}
1053 return 0;
1054 }
1055
1057 { invokeOnEach( begin(), end(), std::move(fnc)); }
1058
1059
1060 /*DEPRECATED LEGACY:*/void PoolQuery::setRequireAll( bool ) {}
1061 /*DEPRECATED LEGACY:*/bool PoolQuery::requireAll() const { return false; }
1062
1064 //
1065 // CLASS NAME : PoolQuery::Attr
1066 //
1071 struct PoolQueryAttr : public IdStringType<PoolQueryAttr>
1072 {
1073 private:
1074 friend class IdStringType<PoolQueryAttr>;
1076 public:
1077
1078 //noAttr
1080
1081 explicit PoolQueryAttr( const char* cstr_r )
1082 : _str( cstr_r )
1083 {}
1084
1085 explicit PoolQueryAttr( const std::string & str_r )
1086 : _str( str_r )
1087 {}
1088
1089 // unknown atributes
1090 static const PoolQueryAttr noAttr;
1091
1092 // PoolQuery's own attributes
1098 static const PoolQueryAttr requireAllAttr; // LEAGACY: attribute was defined but never implemented.
1103 };
1104
1106
1107 const PoolQueryAttr PoolQueryAttr::repoAttr( "repo" );
1108 const PoolQueryAttr PoolQueryAttr::kindAttr( "type" );
1109 const PoolQueryAttr PoolQueryAttr::commentAttr( "comment" );
1110 const PoolQueryAttr PoolQueryAttr::stringAttr( "query_string" );
1111 const PoolQueryAttr PoolQueryAttr::stringTypeAttr("match_type");
1112 const PoolQueryAttr PoolQueryAttr::requireAllAttr("require_all"); // LEAGACY: attribute was defined but never implemented.
1113 const PoolQueryAttr PoolQueryAttr::caseSensitiveAttr("case_sensitive");
1114 const PoolQueryAttr PoolQueryAttr::installStatusAttr("install_status");
1117
1118 class StringTypeAttr : public IdStringType<PoolQueryAttr>
1119 {
1120 friend class IdStringType<StringTypeAttr>;
1122
1123 public:
1125 explicit StringTypeAttr( const char* cstr_r )
1126 : _str( cstr_r ){}
1127 explicit StringTypeAttr( const std::string & str_r )
1128 : _str( str_r ){}
1129
1131
1137 };
1138
1140
1146
1148
1149
1150 //\TODO maybe ctor with stream can be useful
1151 //\TODO let it throw, let it throw, let it throw.
1152 bool PoolQuery::recover( std::istream &str, char delim )
1153 {
1154 bool finded_something = false; //indicates some atributes is finded
1155 std::string s;
1156 do {
1157 if ( str.eof() )
1158 break;
1159
1160 getline( str, s, delim );
1161
1162 if ((!s.empty()) && s[0]=='#') //comment
1163 {
1164 continue;
1165 }
1166
1167 std::string::size_type pos = s.find(':');
1168 if (s.empty() || pos == s.npos) // some garbage on line... act like blank line
1169 {
1170 if (finded_something) //is first blank line after record?
1171 {
1172 break;
1173 }
1174 else
1175 {
1176 continue;
1177 }
1178 }
1179
1180 finded_something = true;
1181
1182 std::string attrName(str::trim(std::string(s,0,pos))); // trimmed name of atribute
1183 std::string attrValue(str::trim(std::string(s,pos+1,s.npos))); //trimmed value
1184
1185 PoolQueryAttr attribute( attrName );
1186
1188 {
1189 addRepo( attrValue );
1190 }
1191 /* some backwards compatibility */
1192 else if ( attribute==PoolQueryAttr::kindAttr || attribute=="kind" )
1193 {
1194 addKind( ResKind(attrValue) );
1195 }
1197 {
1198 setComment( attrValue );
1199 }
1201 || attribute=="global_string")
1202 {
1203 addString( attrValue );
1204 }
1206 || attribute=="string_type" )
1207 {
1208 StringTypeAttr s(attrValue);
1209 if( s == StringTypeAttr::regexAttr )
1210 {
1211 setMatchRegex();
1212 }
1213 else if ( s == StringTypeAttr::globAttr )
1214 {
1215 setMatchGlob();
1216 }
1217 else if ( s == StringTypeAttr::exactAttr )
1218 {
1219 setMatchExact();
1220 }
1221 else if ( s == StringTypeAttr::substringAttr )
1222 {
1224 }
1225 else if ( s == StringTypeAttr::wordAttr )
1226 {
1227 setMatchWord();
1228 }
1229 else if ( s == StringTypeAttr::noAttr )
1230 {
1231 WAR << "unknown string type " << attrValue << endl;
1232 }
1233 else
1234 {
1235 WAR << "forget recover some attribute defined as String type attribute: " << attrValue << endl;
1236 }
1237 }
1239 {
1240 // LEAGACY: attribute was defined but never implemented.
1241 // Actually it should not occur outside our testcases.
1242 }
1244 {
1245 if ( str::strToTrue(attrValue) )
1246 {
1247 setCaseSensitive(true);
1248 }
1249 else if ( !str::strToFalse(attrValue) )
1250 {
1251 setCaseSensitive(false);
1252 }
1253 else
1254 {
1255 WAR << "unknown boolean value " << attrValue << endl;
1256 }
1257 }
1259 {
1260 if( attrValue == "all" )
1261 {
1263 }
1264 else if( attrValue == "installed" )
1265 {
1267 }
1268 else if( attrValue == "not-installed" )
1269 {
1271 }
1272 else
1273 {
1274 WAR << "Unknown value for install status " << attrValue << endl;
1275 }
1276 }
1278 {
1279 std::string::size_type pos = 0;
1280 Rel rel("==");
1281 if (attrValue.find_first_of("=<>!") == 0)
1282 {
1283 pos = attrValue.find_last_of("=<>");
1284 rel = Rel(attrValue.substr(0, pos+1));
1285 attrValue = str::trim(attrValue.substr(pos+1, attrValue.npos));
1286 }
1287
1288 setEdition(Edition(attrValue), rel);
1289 }
1291 {
1292 try
1293 {
1294 _pimpl->_uncompiledPredicated.insert( AttrMatchData::deserialize( attrValue ) );
1295 }
1296 catch ( const Exception & err )
1297 {
1298 WAR << "Unparsable value for complex: " << err.asUserHistory() << endl;
1299
1300 }
1301 }
1302 else if ( attribute==PoolQueryAttr::noAttr )
1303 {
1304 WAR << "empty attribute name" << endl;
1305 }
1306 else
1307 {
1308 std::string s = attrName;
1309 str::replaceAll( s,"_",":" );
1310 SolvAttr a(s);
1311 if ( a == SolvAttr::name || isDependencyAttribute( a ) )
1312 {
1313 Capability c( attrValue );
1314 CapDetail d( c );
1315 if ( d.isVersioned() )
1316 addDependency( a, d.name().asString(), d.op(), d.ed() );
1317 else
1318 addDependency( a, attrValue );
1319 }
1320 else
1321 addAttribute( a, attrValue );
1322 }
1323
1324 } while ( true );
1325
1326 // OLD STYLE VERSIONED LOCKS:
1327 // solvable_name: kernel
1328 // version: > 1
1329 //
1330 // NEW STYLE VERSIONED LOCKS:
1331 // complex: AttrMatchData solvable:name kernel C SolvableRange\ >\ 1\ \"\"
1332 // or
1333 // solvable_name: kernel > 1
1334 //
1335 // Semantically equivalent as locks, but due to the different syntax
1336 // the complex lock is wrongly handled by zypper.
1337 //
1338 // bsc#1112911: Unfortunately all styles are found in real-life locks-files.
1339 // libzypp will try to make sure, when parsing the locks-file, that complex
1340 // locks are rewritten into to OLD STYLE queries zypper can handle.
1341 if ( !_pimpl->_attrs.count(SolvAttr::name) && _pimpl->_uncompiledPredicated.size() == 1 )
1342 {
1343 // No OLD STYLE lock for SolvAttr::name and exactly one complex lock...
1344 const AttrMatchData & attrmatch { *_pimpl->_uncompiledPredicated.begin() };
1345 if ( attrmatch.attr == SolvAttr::name && attrmatch.strMatcher.flags().mode() == Match::OTHER )
1346 {
1347 // ...for SolvAttr::name and following the global search flags.
1348 // A candidate for a rewrite?
1349
1350 std::vector<std::string> words;
1351 str::splitEscaped( attrmatch.predicateStr, std::back_inserter(words) );
1352 if ( words.size() < 4 || words[3].empty() )
1353 {
1354 // We have _NO_ arch rule in the complex predicate, so we can simplify it.
1355 //
1356 // NOTE: AFAIK it's not possible to create (or have created) a complex lock
1357 // with arch rule with zypper means. Nevertheless, in case such a rule made it
1358 // into a locks file, it's better to have a strange looking 'zypper locks' list
1359 // than to lock the wrong packages.
1360 // (and remember that you can't use "addAttribute( SolvAttr::arch, ... )" because
1361 // attributes are `OR`ed)
1362
1363 // kind
1364 if ( attrmatch.kindPredicate )
1365 {
1366 _pimpl->_kinds.clear(); // an explicit kind overwrites any global one
1367 addKind( attrmatch.kindPredicate );
1368 }
1369
1370 // name
1371 addAttribute( SolvAttr::name, attrmatch.strMatcher.searchstring() );
1372
1373 // edition
1374 std::vector<std::string> words;
1375 str::splitEscaped( attrmatch.predicateStr, std::back_inserter(words) );
1376 if ( ! words.empty() )
1377 {
1378 if ( words[0] == "EditionRange" || words[0] == "SolvableRange" )
1379 {
1380 setEdition( Edition(words[2]), Rel(words[1]) );
1381 }
1382 }
1383
1384 // finally remove the complex lock
1385 _pimpl->_uncompiledPredicated.clear();
1386 }
1387 }
1388 }
1389
1390 return finded_something;
1391 }
1392
1393 void PoolQuery::serialize( std::ostream &str, char delim ) const
1394 {
1395 //separating delim
1396 str << delim;
1397 //iterate thrue all settings and write it
1398 static const zypp::PoolQuery q; //not save default options, so create default query example
1399
1400 for_( it, repos().begin(), repos().end() )
1401 {
1402 str << "repo: " << *it << delim ;
1403 }
1404
1405 for_( it, kinds().begin(), kinds().end() )
1406 {
1407 str << PoolQueryAttr::kindAttr.asString() << ": "
1408 << it->idStr() << delim ;
1409 }
1410
1412 str << PoolQueryAttr::editionAttr.asString() << ": " << editionRel() << " " << edition() << delim;
1413
1414 if (matchMode()!=q.matchMode())
1415 {
1416 switch( matchMode() )
1417 {
1418 case Match::STRING:
1419 str << PoolQueryAttr::stringTypeAttr.asString() << ": exact" << delim;
1420 break;
1421 case Match::SUBSTRING:
1423 << ": substring" << delim;
1424 break;
1425 case Match::GLOB:
1426 str << PoolQueryAttr::stringTypeAttr.asString() << ": glob" << delim;
1427 break;
1428 case Match::REGEX:
1429 str << PoolQueryAttr::stringTypeAttr.asString() << ": regex" << delim;
1430 break;
1431 default:
1432 WAR << "unknown match type " << matchMode() << endl;
1433 }
1434 }
1435
1436 if( caseSensitive() != q.caseSensitive() )
1437 {
1438 str << "case_sensitive: ";
1439 if (caseSensitive())
1440 {
1441 str << "on" << delim;
1442 }
1443 else
1444 {
1445 str << "off" << delim;
1446 }
1447 }
1448
1450 {
1451 switch( statusFilterFlags() )
1452 {
1453 case ALL:
1454 str << "install_status: all" << delim;
1455 break;
1456 case INSTALLED_ONLY:
1457 str << "install_status: installed" << delim;
1458 break;
1459 case UNINSTALLED_ONLY:
1460 str << "install_status: not-installed" << delim;
1461 break;
1462 }
1463 }
1464
1465 for_( it, strings().begin(), strings().end() )
1466 {
1467 str << PoolQueryAttr::stringAttr.asString()<< ": " << *it << delim;
1468 }
1469
1470 for_( it, attributes().begin(), attributes().end() )
1471 {
1472 std::string s = it->first.asString();
1473 str::replaceAll(s,":","_");
1474 for_( it2,it->second.begin(),it->second.end() )
1475 {
1476 str << s <<": "<< *it2 << delim;
1477 }
1478 }
1479
1480 for_( it, _pimpl->_uncompiledPredicated.begin(), _pimpl->_uncompiledPredicated.end() )
1481 {
1482 str << "complex: "<< it->serialize() << delim;
1483 }
1484
1485 if ( const std::string & c { comment() }; not c.empty() )
1486 str << PoolQueryAttr::commentAttr.asString() << ": " << c << delim ;
1487
1488 //separating delim - protection
1489 str << delim;
1490 }
1491
1492 std::string PoolQuery::asString() const
1493 { return _pimpl->asString(); }
1494
1495 std::ostream & operator<<( std::ostream & str, const PoolQuery & obj )
1496 { return str << obj.asString(); }
1497
1498 std::ostream & dumpOn( std::ostream & str, const PoolQuery & obj )
1499 { return dumpRange( str << obj, obj.begin(), obj.end() ); }
1500
1501 bool PoolQuery::operator==( const PoolQuery & rhs ) const
1502 { return *_pimpl == *rhs._pimpl; }
1503
1504 bool PoolQuery::operator<( const PoolQuery & rhs ) const
1505 { return *_pimpl < *rhs._pimpl; }
1506
1508 namespace detail
1509 {
1510
1512 //
1513 // CLASS NAME : PoolQueryMatcher
1514 //
1532 {
1533 public:
1535
1536 public:
1537 const base_iterator & end() const
1538 {
1539 static base_iterator _end;
1540 return _end;
1541 }
1542
1543 bool advance( base_iterator & base_r ) const
1544 {
1545 if ( base_r == end() )
1546 base_r = startNewQyery(); // first candidate
1547 else
1548 {
1549 base_r.nextSkipSolvable(); // assert we don't visit this Solvable again
1550 ++base_r; // advance to next candidate
1551 }
1552
1553 while ( base_r != end() )
1554 {
1555 if ( isAMatch( base_r ) )
1556 return true;
1557 // No match: try next
1558 ++base_r;
1559 }
1560 return false;
1561 }
1562
1566 void matchDetail( const base_iterator & base_r, std::vector<base_iterator> & return_r ) const
1567 {
1568 if ( base_r == end() )
1569 return;
1570
1571 sat::Solvable inSolvable( base_r.inSolvable() );
1572
1573 if ( _attrMatchList.size() == 1 )
1574 {
1575 // base_r is already on the 1st matching attribute!
1576 // String matching is done by the base iterator. We must check the predicate here.
1577 // Let's see if there are more matches for this solvable:
1578 base_iterator base( base_r );
1579 base.stayInThisSolvable(); // avoid discarding matches we found far away from here.
1580 return_r.push_back( base );
1581
1582 const AttrMatchData::Predicate & predicate( _attrMatchList.front().predicate );
1583 for ( ++base; base.inSolvable() == inSolvable; ++base ) // safe even if base == end()
1584 {
1585 if ( ! predicate || predicate( base ) )
1586 return_r.push_back( base );
1587 }
1588 }
1589 else
1590 {
1591 // Here: search all attributes ;(
1592 for_( mi, _attrMatchList.begin(), _attrMatchList.end() )
1593 {
1594 const AttrMatchData & matchData( *mi );
1595 sat::LookupAttr q( matchData.attr, inSolvable );
1596 if ( matchData.strMatcher ) // an empty searchstring matches always
1597 q.setStrMatcher( matchData.strMatcher );
1598
1599 if ( ! q.empty() ) // there are matches.
1600 {
1601 // now check any predicate:
1602 const AttrMatchData::Predicate & predicate( matchData.predicate );
1603 for_( it, q.begin(), q.end() )
1604 {
1605 if ( ! predicate || predicate( it ) )
1606 return_r.push_back( it );
1607 }
1608 }
1609 }
1610 }
1611 }
1612
1613 public:
1618
1623 {
1624 query_r->compile();
1625
1626 // Repo restriction:
1627 sat::Pool satpool( sat::Pool::instance() );
1628
1629 for_( it, query_r->_repos.begin(), query_r->_repos.end() )
1630 {
1631 Repository r( satpool.reposFind( *it ) );
1632 if ( r )
1633 _repos.insert( r );
1634 else
1635 _neverMatchRepo = true;
1636 }
1637 // _neverMatchRepo: we just need to catch the case that no repo
1638 // matched, so we'd interpret the empty list as 'take from all'
1639 if ( _neverMatchRepo && ! _repos.empty() )
1640 _neverMatchRepo = false;
1641
1642 // Kind restriction:
1643 _kinds = query_r->_kinds;
1644 // Edition restriction:
1645 _op = query_r->_op;
1646 _edition = query_r->_edition;
1647 // Status restriction:
1648 _status_flags = query_r->_status_flags;
1649 // StrMatcher
1650 _attrMatchList = query_r->_attrMatchList;
1651 }
1652
1655
1656 private:
1659 {
1661
1662 if ( _neverMatchRepo )
1663 return q.end();
1664
1665 // Repo restriction:
1666 if ( _repos.size() == 1 )
1667 q.setRepo( *_repos.begin() );
1668 // else: handled in isAMatch.
1669
1670 // Attribute restriction:
1671 if ( _attrMatchList.size() == 1 ) // all (SolvAttr::allAttr) or 1 attr
1672 {
1673 const AttrMatchData & matchData( _attrMatchList.front() );
1674 q.setAttr( matchData.attr );
1675 if ( matchData.strMatcher ) // empty searchstring matches always
1676 q.setStrMatcher( matchData.strMatcher );
1677 }
1678 else // more than 1 attr (but not all)
1679 {
1680 // no restriction, it's all handled in isAMatch.
1682 }
1683
1684 return q.begin();
1685 }
1686
1687
1698 bool isAMatch( base_iterator & base_r ) const
1699 {
1701 Repository inRepo( base_r.inRepo() );
1702 // Status restriction:
1703 if ( _status_flags
1704 && ( (_status_flags == PoolQuery::INSTALLED_ONLY) != inRepo.isSystemRepo() ) )
1705 {
1706 base_r.nextSkipRepo();
1707 return false;
1708 }
1709 // Repo restriction:
1710 if ( _repos.size() > 1 && _repos.find( inRepo ) == _repos.end() )
1711 {
1712 base_r.nextSkipRepo();
1713 return false;
1714 }
1716 sat::Solvable inSolvable( base_r.inSolvable() );
1717 // Edition restriction:
1718 if ( _op != Rel::ANY && !compareByRel( _op, inSolvable.edition(), _edition, Edition::Match() ) )
1719 {
1720 base_r.nextSkipSolvable();
1721 return false;
1722 }
1723
1724 // Kind restriction:
1725 // Delay the decision to nextSkipSolvable and return false, as there may be
1726 // some explicit kind:name predicate which overrules the global kinds.
1727 bool globalKindOk =( _kinds.empty() || inSolvable.isKind( _kinds.begin(), _kinds.end() ) );
1728
1730 // string and predicate matching:
1731
1732 if ( _attrMatchList.size() == 1 )
1733 {
1734 // String matching was done by the base iterator.
1735 // Now check any predicate:
1736 const AttrMatchData & matchData( _attrMatchList.front() );
1737
1738 if ( matchData.kindPredicate )
1739 {
1740 if ( matchData.kindPredicate != inSolvable.kind() )
1741 {
1742 base_r.nextSkipSolvable(); // this matchData will never match in this solvable
1743 return false;
1744 }
1745 }
1746 else if ( !globalKindOk )
1747 return false; // only matching kindPredicate could overwrite this
1748
1749 if ( !matchData.predicate || matchData.predicate( base_r ) )
1750 return true;
1751
1752 return false; // no skip as there may be more occurrences in this solvable of this attr.
1753 }
1754
1755 // Here: search all attributes ;(
1756 for_( mi, _attrMatchList.begin(), _attrMatchList.end() )
1757 {
1758 const AttrMatchData & matchData( *mi );
1759
1760 if ( matchData.kindPredicate )
1761 {
1762 if ( matchData.kindPredicate != inSolvable.kind() )
1763 continue; // this matchData does not apply
1764 }
1765 else if ( !globalKindOk )
1766 continue; // only matching kindPredicate could overwrite this
1767
1768 sat::LookupAttr q( matchData.attr, inSolvable );
1769 if ( matchData.strMatcher ) // an empty searchstring matches always
1770 q.setStrMatcher( matchData.strMatcher );
1771
1772 if ( ! q.empty() ) // there are matches.
1773 {
1774 // now check any predicate:
1775 const AttrMatchData::Predicate & predicate( matchData.predicate );
1776 if ( predicate )
1777 {
1778 for_( it, q.begin(), q.end() )
1779 {
1780 if ( predicate( it ) )
1781 return true;
1782 }
1783 }
1784 else
1785 return true;
1786 }
1787 }
1788 base_r.nextSkipSolvable();
1789 return false;
1790 }
1791
1792 private:
1794 std::set<Repository> _repos;
1797 std::set<ResKind> _kinds;
1804 AttrMatchList _attrMatchList;
1805 };
1806
1807
1809 {
1810 // matcher restarts if at end! It is called from the ctor
1811 // to get the 1st match. But if the end is reached, it should
1812 // be deleted, otherwise we'd start over again.
1813 if ( !_matcher )
1814 return; // at end
1815 if ( _matches )
1816 _matches.reset(); // invalidate old matches
1817 if ( ! _matcher->advance( base_reference() ) )
1818 _matcher.reset();
1819 }
1820
1822 {
1823 if ( _matches )
1824 return *_matches;
1825
1826 if ( !_matcher )
1827 {
1828 // at end of query:
1829 static const Matches _none;
1830 return _none;
1831 }
1832
1833 _matches.reset( new Matches );
1834 _matcher->matchDetail( base_reference(), *_matches );
1835 return *_matches;
1836 }
1837
1838 std::ostream & dumpOn( std::ostream & str, const PoolQueryIterator & obj )
1839 {
1840 str << *obj;
1841 if ( ! obj.matchesEmpty() )
1842 {
1843 for_( it, obj.matchesBegin(), obj.matchesEnd() )
1844 {
1845 str << endl << " " << it->inSolvAttr() << "\t" << it->asString();
1846 }
1847 }
1848 return str;
1849 }
1850
1852 } //namespace detail
1853
1854
1859
1861} // namespace zypp
1863
#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
bool operator()(const zypp::Arch &lhs, const zypp::Arch &rhs) const
Default order for std::container based Arch::compare.
Definition Arch.h:370
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:52
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
Range< Edition, Match > MatchRange
Edition Range based on Match.
Definition Edition.h:169
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:153
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Definition Exception.cc:140
Access to the sat-pools string space.
Definition IdString.h:44
std::string asString() const
Conversion to std::string
Definition IdString.h:99
String matching option flags as used e.g.
Definition StrMatcher.h:33
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
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
friend Impl * rwcowClone(const Impl *rhs)
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:969
void addString(const std::string &value)
Add a global query string.
Definition PoolQuery.cc:882
const Rel editionRel() const
bool matchSubstring() const
const StrContainer & repos() const
void setMatchExact()
Set to match exact string instead of substring.
Definition PoolQuery.cc:964
void setMatchWord()
Set substring to match words.
Definition PoolQuery.cc:967
void setMatchRegex()
Set to use the query strings as regexes.
Definition PoolQuery.cc:965
void setFlags(const Match &flags)
Free function to set libsolv repo search flags.
Definition PoolQuery.cc:971
RW_pointer< Impl > _pimpl
Pointer to implementation.
Definition PoolQuery.h:489
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:979
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
unsigned int size_type
Definition PoolQuery.h:98
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:885
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:425
void setInstalledOnly()
Return only @System repo packages.
Definition PoolQuery.cc:975
const Edition edition() const
Definition PoolQuery.cc:999
const_iterator end() const
An iterator pointing to the end of the query result.
Definition PoolQuery.h:621
StatusFilter statusFilterFlags() const
const StrContainer & strings() const
Search strings added via addString()
Definition PoolQuery.cc:984
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:988
void addDependency(const sat::SolvAttr &attr, const std::string &name, const Rel &op, const Edition &edition)
Query "name|global op edition".
Definition PoolQuery.cc:888
StatusFilter
Installed status filter setters.
Definition PoolQuery.h:174
void setEdition(const Edition &edition, const Rel &op=Rel::EQ)
Set version condition.
Definition PoolQuery.cc:957
const StrContainer & attribute(const sat::SolvAttr &attr) const
Definition PoolQuery.cc:992
void setMatchSubstring()
Set to substring (the default).
Definition PoolQuery.cc:963
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:977
void setMatchGlob()
Set to match globs.
Definition PoolQuery.cc:966
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:523
const Matches & matches() const
matches_iterator matchesEnd() const
End of matches.
Definition PoolQuery.h:590
bool matchesEmpty() const
False unless this is the end iterator.
Definition PoolQuery.h:584
shared_ptr< Matches > _matches
Definition PoolQuery.h:606
matches_iterator matchesBegin() const
Begin of matches.
Definition PoolQuery.h:588
shared_ptr< PoolQueryMatcher > _matcher
Definition PoolQuery.h:605
std::vector< sat::LookupAttr::iterator > Matches
Definition PoolQuery.h:524
PoolQueryIterator()
Default ctor is also end.
Definition PoolQuery.h:530
Store PoolQuery settings and assist PoolQueryIterator.
PoolQueryMatcher(PoolQueryMatcher &&)=default
sat::LookupAttr::iterator base_iterator
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
detail::IdType id() const
Definition LookupAttr.h:523
Tp asType() const
Templated return type.
Definition LookupAttr.h:535
void nextSkipSolvable()
On the next call to operator++ advance to the next Solvable.
Solvable inSolvable() const
The current Solvable.
void nextSkipRepo()
On the next call to operator++ advance to the next Repository.
Repository inRepo() const
The current Repository.
Lightweight attribute value lookup.
Definition LookupAttr.h:110
iterator end() const
Iterator behind the end of query results.
bool empty() const
Whether the query is empty.
void setStrMatcher(const StrMatcher &matcher_r)
Set the pattern to match.
void setAttr(SolvAttr attr_r)
Set the SolvAttr to search.
void setRepo(Repository repo_r, Location=SOLV_ATTR)
Set search in one Repository.
iterator begin() const
Iterator to the begin of query results.
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 dep_requires
Definition SolvAttr.h:82
static const SolvAttr name
Definition SolvAttr.h:52
static const SolvAttr dep_enhances
Definition SolvAttr.h:86
static const SolvAttr dep_obsoletes
Definition SolvAttr.h:80
static const SolvAttr dep_suggests
Definition SolvAttr.h:84
static const SolvAttr dep_provides
Definition SolvAttr.h:79
static const SolvAttr dep_conflicts
Definition SolvAttr.h:81
static const SolvAttr allAttr
Value to request searching all Attributes (0).
Definition SolvAttr.h:46
static const SolvAttr dep_recommends
Definition SolvAttr.h:83
static const SolvAttr dep_supplements
Definition SolvAttr.h:85
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
Arch arch() const
The architecture.
Definition Solvable.cc:344
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
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:333
bool strToTrue(const C_Str &str)
Parsing boolean from string.
Definition String.cc:66
std::string rxEscapeGlob(std::string str_r)
Escape GLOB str_r for use in a regex (not anchored by "^" or "$").
Definition String.cc:423
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:992
std::string rxEscapeStr(std::string str_r)
Escape plain STRING str_r for use in a regex (not anchored by "^" or "$").
Definition String.cc:418
bool strToFalse(const C_Str &str)
Return false if str is 0, false, no, off, never.
Definition String.cc:84
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:665
std::string trim(const std::string &s, const Trim trim_r)
Definition String.cc:226
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)
const ResKind ResTraits< Package >::kind(ResKind::package)
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
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:213
#define arrayBegin(A)
Simple C-array iterator.
Definition Easy.h:36
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:27
#define arrayEnd(A)
Definition Easy.h:38
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
#define WAR
Definition Logger.h:101
Interface to gettext.