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