libzypp  17.38.7
Capability.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
14 
15 #include <zypp-core/base/String.h>
16 #include <zypp-core/base/Regex.h>
17 #include <zypp-core/base/Gettext.h>
19 
20 #include <zypp/Arch.h>
21 #include <zypp/Rel.h>
22 #include <zypp/Edition.h>
23 #include <zypp/Capability.h>
24 #include <zypp/ResPool.h>
25 #include <zypp/sat/Solvable.h>
26 
27 #include <zypp/ng/sat/stringpool.h>
28 
29 using std::endl;
30 
32 namespace zypp
33 {
34 
36 
37  namespace
38  {
39 
41  template <unsigned TLen = 5>
42  struct TempStrings
43  {
45  std::string & getNext()
46  { unsigned c = _next; _next = (_next+1) % TLen; _buf[c].clear(); return _buf[c]; }
47 
48  private:
49  unsigned _next = 0;
50  std::string _buf[TLen];
51  };
52 
54  inline std::string::size_type backskipWs( const std::string & str_r, std::string::size_type pos_r )
55  {
56  for ( ; pos_r != std::string::npos; --pos_r )
57  {
58  char ch = str_r[pos_r];
59  if ( ch != ' ' && ch != '\t' )
60  break;
61  }
62  return pos_r;
63  }
64 
66  inline std::string::size_type backskipNWs( const std::string & str_r, std::string::size_type pos_r )
67  {
68  for ( ; pos_r != std::string::npos; --pos_r )
69  {
70  char ch = str_r[pos_r];
71  if ( ch == ' ' || ch == '\t' )
72  break;
73  }
74  return pos_r;
75  }
76 
78  void splitOpEdition( std::string & str_r, Rel & op_r, Edition & ed_r )
79  {
80  if ( str_r.empty() )
81  return;
82  std::string::size_type ch( str_r.size()-1 );
83 
84  // check whether the one but last word is a valid Rel:
85  if ( (ch = backskipWs( str_r, ch )) != std::string::npos )
86  {
87  std::string::size_type ee( ch );
88  if ( (ch = backskipNWs( str_r, ch )) != std::string::npos )
89  {
90  std::string::size_type eb( ch );
91  if ( (ch = backskipWs( str_r, ch )) != std::string::npos )
92  {
93  std::string::size_type oe( ch );
94  ch = backskipNWs( str_r, ch ); // now before 'op'? begin
95  if ( op_r.parseFrom( str_r.substr( ch+1, oe-ch ) ) )
96  {
97  // found a legal 'op'
98  ed_r = Edition( str_r.substr( eb+1, ee-eb ) );
99  if ( ch != std::string::npos ) // 'op' is not at str_r begin, so skip WS
100  ch = backskipWs( str_r, ch );
101  str_r.erase( ch+1 );
102  return;
103  }
104  }
105  }
106  }
107  // HERE: Didn't find 'name op edition'
108  // As a convenience we check for an embeded 'op' (not surounded by WS).
109  // But just '[<=>]=?|!=' and not inside '()'.
110  ch = str_r.find_last_of( "<=>)" );
111  if ( ch != std::string::npos && str_r[ch] != ')' )
112  {
113  std::string::size_type oe( ch );
114 
115  // do edition first:
116  ch = str_r.find_first_not_of( " \t", oe+1 );
117  if ( ch != std::string::npos )
118  ed_r = Edition( str_r.substr( ch ) );
119 
120  // now finish op:
121  ch = oe-1;
122  if ( str_r[oe] != '=' ) // '[<>]'
123  {
124  op_r = ( str_r[oe] == '<' ) ? Rel::LT : Rel::GT;
125  }
126  else
127  { // '?='
128  if ( ch != std::string::npos )
129  {
130  switch ( str_r[ch] )
131  {
132  case '<': --ch; op_r = Rel::LE; break;
133  case '>': --ch; op_r = Rel::GE; break;
134  case '!': --ch; op_r = Rel::NE; break;
135  case '=': --ch; // fall through
136  default: op_r = Rel::EQ; break;
137  }
138  }
139  }
140 
141  // finally name:
142  if ( ch != std::string::npos ) // 'op' is not at str_r begin, so skip WS
143  ch = backskipWs( str_r, ch );
144  str_r.erase( ch+1 );
145  return;
146  }
147  // HERE: It's a plain 'name'
148  }
149 
152  sat::detail::IdType relFromStr( sat::detail::CPool * pool_r,
153  const Arch & arch_r,
154  const std::string & name_r,
155  Rel op_r,
156  const Edition & ed_r,
157  const ResKind & kind_r )
158  {
159  // First build the name, non-packages prefixed by kind
160  sat::Solvable::SplitIdent split( kind_r, name_r );
161  sat::detail::IdType nid( split.ident().id() );
162 
163  if ( split.kind() == ResKind::srcpackage )
164  {
165  // map 'kind srcpackage' to 'arch src', the pseudo architecture
166  // libsolv uses.
167  nid = ::pool_rel2id( pool_r, nid, IdString(ARCH_SRC).id(), REL_ARCH, /*create*/true );
168  }
169 
170  // Extend name by architecture, if provided and not a srcpackage
171  if ( ! arch_r.empty() && kind_r != ResKind::srcpackage )
172  {
173  nid = ::pool_rel2id( pool_r, nid, arch_r.id(), REL_ARCH, /*create*/true );
174  }
175 
176  // Extend 'op edition', if provided
177  if ( op_r != Rel::ANY && ed_r != Edition::noedition )
178  {
179  nid = ::pool_rel2id( pool_r, nid, ed_r.id(), op_r.bits(), /*create*/true );
180  }
181 
182  return nid;
183  }
184 
188  sat::detail::IdType relFromStr( sat::detail::CPool * pool_r,
189  const std::string & name_r, Rel op_r, const Edition & ed_r,
190  const ResKind & kind_r )
191  {
192  static const Arch srcArch( IdString(ARCH_SRC).asString() );
193  static const Arch nosrcArch( IdString(ARCH_NOSRC).asString() );
194  static const std::string srcKindPrefix( ResKind::srcpackage.asString() + ':' );
195 
196  // check for an embedded 'srcpackage:foo' to be mapped to 'foo' and 'ResKind::srcpackage'.
197  if ( kind_r.empty() && str::hasPrefix( name_r, srcKindPrefix ) )
198  {
199  return relFromStr( pool_r, Arch_empty, name_r.substr( srcKindPrefix.size() ), op_r, ed_r, ResKind::srcpackage );
200  }
201 
202  Arch arch( Arch_empty );
203  std::string name( name_r );
204 
205  std::string::size_type asep( name_r.rfind( '.' ) );
206  if ( asep != std::string::npos )
207  {
208  Arch ext( name_r.substr( asep+1 ) );
209  if ( ext.isBuiltIn() || ext == srcArch || ext == nosrcArch )
210  {
211  arch = ext;
212  name.erase( asep );
213  }
214  }
215 
216  return relFromStr( pool_r, arch, name, op_r, ed_r, kind_r );
217  }
218 
221  sat::detail::IdType relFromStr( sat::detail::CPool * pool_r,
222  const Arch & arch_r, // parse from name if empty
223  const std::string & str_r, const ResKind & kind_r,
224  Capability::CtorFlag flag_r )
225  {
226  std::string name( str_r );
227  Rel op;
228  Edition ed;
229  if ( flag_r == Capability::UNPARSED )
230  {
231  splitOpEdition( name, op, ed );
232  }
233 
234  if ( arch_r.empty() )
235  return relFromStr( pool_r, name, op, ed, kind_r ); // parses for name[.arch]
236  // else
237  return relFromStr( pool_r, arch_r, name, op, ed, kind_r );
238  }
239 
241  sat::detail::IdType richOrRelFromStr( sat::detail::CPool * pool_r, const std::string & str_r, const ResKind & prefix_r, Capability::CtorFlag flag_r )
242  {
243  if ( str_r[0] == '(' ) {
244  sat::detail::IdType res { StringPool::instance().parserpmrichdep( str_r.c_str() ) };
245  if ( res ) return res;
246  // else: no richdep, so fall back to the ordinary parser which in
247  // case of doubt turns the string into a NAMED cap.
248  }
249  return relFromStr( pool_r, Arch_empty, str_r, prefix_r, flag_r );
250  }
251 
253  } // namespace
255 
256  const Capability Capability::Null( STRID_NULL );
257  const Capability Capability::Empty( STRID_EMPTY );
258 
260 
261  Capability::Capability( const char * str_r, const ResKind & prefix_r, CtorFlag flag_r )
262  : _id( richOrRelFromStr( StringPool::instance().getPool(), str_r, prefix_r, flag_r ) )
263  {}
264 
265  Capability::Capability( const std::string & str_r, const ResKind & prefix_r, CtorFlag flag_r )
266  : _id( richOrRelFromStr( StringPool::instance().getPool(), str_r, prefix_r, flag_r ) )
267  {}
268 
269  Capability::Capability( const Arch & arch_r, const char * str_r, const ResKind & prefix_r, CtorFlag flag_r )
270  : _id( relFromStr( StringPool::instance().getPool(), arch_r, str_r, prefix_r, flag_r ) )
271  {}
272 
273  Capability::Capability( const Arch & arch_r, const std::string & str_r, const ResKind & prefix_r, CtorFlag flag_r )
274  : _id( relFromStr( StringPool::instance().getPool(), arch_r, str_r, prefix_r, flag_r ) )
275  {}
276 
277  Capability::Capability( const char * str_r, CtorFlag flag_r, const ResKind & prefix_r )
278  : _id( relFromStr( StringPool::instance().getPool(), Arch_empty, str_r, prefix_r, flag_r ) )
279  {}
280 
281  Capability::Capability( const std::string & str_r, CtorFlag flag_r, const ResKind & prefix_r )
282  : _id( relFromStr( StringPool::instance().getPool(), Arch_empty, str_r, prefix_r, flag_r ) )
283  {}
284 
285  Capability::Capability( const Arch & arch_r, const char * str_r, CtorFlag flag_r, const ResKind & prefix_r )
286  : _id( relFromStr( StringPool::instance().getPool(), arch_r, str_r, prefix_r, flag_r ) )
287  {}
288 
289  Capability::Capability( const Arch & arch_r, const std::string & str_r, CtorFlag flag_r, const ResKind & prefix_r )
290  : _id( relFromStr( StringPool::instance().getPool(), arch_r, str_r, prefix_r, flag_r ) )
291  {}
292 
294  // Ctor from <name[.arch] op edition>.
296 
297  Capability::Capability( const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r )
298  : _id( relFromStr( StringPool::instance().getPool(), name_r, Rel(op_r), Edition(ed_r), prefix_r ) )
299  {}
300  Capability::Capability( const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r )
301  : _id( relFromStr( StringPool::instance().getPool(), name_r, op_r, Edition(ed_r), prefix_r ) )
302  {}
303  Capability::Capability( const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r )
304  : _id( relFromStr( StringPool::instance().getPool(), name_r, op_r, ed_r, prefix_r ) )
305  {}
306 
308  // Ctor from <arch name op edition>.
310 
311  Capability::Capability( const std::string & arch_r, const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r )
312  : _id( relFromStr( StringPool::instance().getPool(), Arch(arch_r), name_r, Rel(op_r), Edition(ed_r), prefix_r ) )
313  {}
314  Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r )
315  : _id( relFromStr( StringPool::instance().getPool(), Arch(arch_r), name_r, op_r, Edition(ed_r), prefix_r ) )
316  {}
317  Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r )
318  : _id( relFromStr( StringPool::instance().getPool(), Arch(arch_r), name_r, op_r, ed_r, prefix_r ) )
319  {}
320  Capability::Capability( const Arch & arch_r, const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r )
321  : _id( relFromStr( StringPool::instance().getPool(), arch_r, name_r, Rel(op_r), Edition(ed_r), prefix_r ) )
322  {}
323  Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r )
324  : _id( relFromStr( StringPool::instance().getPool(), arch_r, name_r, op_r, Edition(ed_r), prefix_r ) )
325  {}
326  Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r )
327  : _id( relFromStr( StringPool::instance().getPool(), arch_r, name_r, op_r, ed_r, prefix_r ) )
328  {}
329 
331  // Ctor creating a namespace: capability.
333 
335  : _id( ::pool_rel2id(StringPool::instance().getPool(), asIdString(namespace_r).id(), (value_r.empty() ? STRID_NULL : value_r.id() ), CAP_NAMESPACE, /*create*/true ) )
336  {}
337 
339  // Ctor creating an expression
341 
342  Capability::Capability( Capability::CapRel rel_r, const Capability & lhs_r, const Capability & rhs_r )
343  : _id( ::pool_rel2id( StringPool::instance().getPool(), lhs_r.id(), rhs_r.id(), rel_r, /*create*/true ) )
344  {}
345 
347  // https://rpm-software-management.github.io/rpm/manual/boolean_dependencies.html
348  namespace
349  {
350  inline const char * opstr( int op_r )
351  {
352  switch ( op_r )
353  {
354  case REL_GT: return " > ";
355  case REL_EQ: return " = ";
356  case REL_LT: return " < ";
357  case REL_GT|REL_EQ: return " >= ";
358  case REL_LT|REL_EQ: return " <= ";
359  case REL_GT|REL_LT: return " != ";
360  case REL_GT|REL_LT|REL_EQ: return " <=> ";
361  case REL_AND: return " and ";
362  case REL_OR: return " or ";
363  case REL_COND: return " if ";
364  case REL_UNLESS: return " unless ";
365  case REL_ELSE: return " else ";
366  case REL_WITH: return " with ";
367  case REL_WITHOUT: return " without ";
368  }
369  return "UNKNOWNCAPREL";
370  }
371 
372  inline bool isBoolOp( int op_r )
373  {
374  switch ( op_r ) {
375  case REL_AND:
376  case REL_OR:
377  case REL_COND:
378  case REL_UNLESS:
379  case REL_ELSE:
380  case REL_WITH:
381  case REL_WITHOUT:
382  return true;
383  }
384  return false;
385  }
386 
387  inline bool needsBrace( int op_r, int parop_r )
388  {
389  return ( isBoolOp( parop_r ) || parop_r == 0 ) && isBoolOp( op_r )
390  && ( parop_r != op_r || op_r == REL_COND || op_r == REL_UNLESS || op_r == REL_ELSE )
391  && not ( ( parop_r == REL_COND || parop_r == REL_UNLESS ) && op_r == REL_ELSE );
392  }
393 
394  void cap2strHelper( std::string & outs_r, sat::detail::CPool * pool_r, sat::detail::IdType id_r, int parop_r )
395  {
396  if ( ISRELDEP(id_r) ) {
397  ::Reldep * rd = GETRELDEP( pool_r, id_r );
398  int op = rd->flags;
399 
400  if ( op == CapDetail::CAP_ARCH ) {
401  if ( rd->evr == ARCH_SRC || rd->evr == ARCH_NOSRC ) {
402  // map arch .{src,nosrc} to kind srcpackage
403  outs_r += ResKind::srcpackage.c_str();
404  outs_r += ":";
405  outs_r += IdString(rd->name).c_str();
406  return;
407  }
408  cap2strHelper( outs_r, pool_r, rd->name, op );
409  outs_r += ".";
410  cap2strHelper( outs_r, pool_r, rd->evr, op );
411  return;
412  }
413 
414  if ( op == CapDetail::CAP_NAMESPACE ) {
415  cap2strHelper( outs_r, pool_r, rd->name, op );
416  outs_r += "(";
417  cap2strHelper( outs_r, pool_r, rd->evr, op );
418  outs_r += ")";
419  return;
420  }
421 
422  if ( op == REL_FILECONFLICT )
423  {
424  cap2strHelper( outs_r, pool_r, rd->name, op );
425  return;
426  }
427 
428  if ( needsBrace( op, parop_r ) ) {
429  outs_r += "(";
430  cap2strHelper( outs_r, pool_r, rd->name, op );
431  outs_r += opstr( op );
432  cap2strHelper( outs_r, pool_r, rd->evr, op );
433  outs_r += ")";
434  return;
435  }
436 
437  cap2strHelper( outs_r, pool_r, rd->name, op );
438  outs_r += opstr( op );
439  cap2strHelper( outs_r, pool_r, rd->evr, op );
440  }
441  else
442  outs_r += IdString(id_r).c_str();
443  }
444  } // namespace
446 
447  const char * Capability::c_str() const
448  {
449  if ( not id() ) return "";
450  if ( not ISRELDEP(id()) ) return IdString(id()).c_str();
451 
452  static TempStrings<5> tempstrs; // Round Robin buffer to prolong the lifetime of the returned char*
453 
454  std::string & outs { tempstrs.getNext() };
455  cap2strHelper( outs, StringPool::instance().getPool(), id(), 0 );
456  return outs.c_str();
457  }
458 
460  {
461  if ( lhs == rhs )
462  return CapMatch::yes;
463 
464  CapDetail l( lhs );
465  CapDetail r( rhs );
466 
467  switch ( l.kind() )
468  {
469  case CapDetail::NOCAP:
470  return( r.kind() == CapDetail::NOCAP ); // NOCAP matches NOCAP only
471  break;
473  return CapMatch::irrelevant;
474  break;
475  case CapDetail::NAMED:
477  break;
478  }
479 
480  switch ( r.kind() )
481  {
482  case CapDetail::NOCAP:
483  return CapMatch::no; // match case handled above
484  break;
486  return CapMatch::irrelevant;
487  break;
488  case CapDetail::NAMED:
490  break;
491  }
492  // comparing two simple caps:
493  if ( l.name() != r.name() )
494  return CapMatch::no;
495 
496  // if both are arch restricted they must match
497  if ( l.arch() != r.arch()
498  && ! ( l.arch().empty() || r.arch().empty() ) )
499  return CapMatch::no;
500 
501  // isNamed matches ANY edition:
502  if ( l.isNamed() || r.isNamed() )
503  return CapMatch::yes;
504 
505  // both are versioned:
506  return overlaps( Edition::MatchRange( l.op(), l.ed() ),
507  Edition::MatchRange( r.op(), r.ed() ) );
508  }
509 
510  bool Capability::isInterestingFileSpec( const char * name_r )
511  {
512  static str::smatch what;
513  static const str::regex filenameRegex(
514  "/(s?bin|lib(64)?|etc)/|^/usr/(games/|share/(dict/words|magic\\.mime)$)|^/opt/gnome/games/",
516 
517  return str::regex_match( name_r, what, filenameRegex );
518  }
519 
520  Capability Capability::guessPackageSpec( const std::string & str_r, bool & rewrote_r )
521  {
522  Capability cap( str_r );
523  CapDetail detail( cap.detail() );
524 
525  // str_r might be the form "libzypp-1.2.3-4.5(.arch)'
526  // correctly parsed as name capability by the ctor.
527  // TODO: Think about allowing glob char in name - for now don't process
528  if ( detail.isNamed() && !::strpbrk( detail.name().c_str(), "*?[{" )
529  && ::strrchr( detail.name().c_str(), '-' ) && sat::WhatProvides( cap ).empty() )
530  {
531  Arch origArch( detail.arch() ); // to support a trailing .arch
532 
533  std::string guess( detail.name().asString() );
534  std::string::size_type pos( guess.rfind( '-' ) );
535  guess[pos] = '=';
536 
537  Capability guesscap( origArch, guess );
538  detail = guesscap.detail();
539 
540  ResPool pool( ResPool::instance() );
541  // require name part matching a pool items name (not just provides!)
542  if ( pool.byIdentBegin( detail.name() ) != pool.byIdentEnd( detail.name() ) )
543  {
544  rewrote_r = true;
545  return guesscap;
546  }
547 
548  // try the one but last '-'
549  if ( pos )
550  {
551  guess[pos] = '-';
552  if ( (pos = guess.rfind( '-', pos-1 )) != std::string::npos )
553  {
554  guess[pos] = '=';
555 
556  guesscap = Capability( origArch, guess );
557  detail = guesscap.detail();
558 
559  // require name part matching a pool items name (not just provides!)
560  if ( pool.byIdentBegin( detail.name() ) != pool.byIdentEnd( detail.name() ) )
561  {
562  rewrote_r = true;
563  return guesscap;
564  }
565  }
566  }
567  }
568 
569  rewrote_r = false;
570  return cap;
571  }
572 
573  Capability Capability::guessPackageSpec( const std::string & str_r )
574  {
575  bool dummy = false;
576  return guessPackageSpec( str_r, dummy );
577  }
578 
579  /******************************************************************
580  **
581  ** FUNCTION NAME : operator<<
582  ** FUNCTION TYPE : std::ostream &
583  */
584  std::ostream & operator<<( std::ostream & str, const Capability & obj )
585  {
586  return str << obj.c_str();
587  }
588 
589  std::ostream & dumpOn( std::ostream & str, const Capability & obj )
590  {
591  return str << ( obj ? ::pool_dep2str( StringPool::instance().getPool(), obj.id() ) : "" );
592  }
593 
594  std::ostream & operator<<( std::ostream & str, Capability::CapRel obj )
595  {
596  switch ( obj )
597  {
598  case Capability::CAP_AND: return str << "and"; break; // &
599  case Capability::CAP_OR: return str << "or"; break; // |
600  case Capability::CAP_COND: return str << "if"; break;
601  case Capability::CAP_UNLESS: return str << "unless"; break;
602  case Capability::CAP_ELSE: return str << "else"; break;
603  case Capability::CAP_WITH: return str << "with"; break; // +
604  case Capability::CAP_WITHOUT: return str << "without"; break; // -
605  case Capability::CAP_NAMESPACE: return str << "NAMESPACE"; break;
606  case Capability::CAP_ARCH: return str << "ARCH"; break;
607  }
608  return str << "UnknownCapRel("+str::numstring(obj)+")";
609  }
610 
611  std::ostream & dumpCap::dumpOn( std::ostream & str ) const
612  { return _dumpRec( str, _cap ); }
613  std::ostream & dumpCap::_dumpRec( std::ostream & str, Capability cap_r, std::string lvl_r ) const
614  {
615  std::optional<decltype(lvl_r.rbegin())> lastch; // lvl_r last char if not empty
616  if ( not lvl_r.empty() )
617  lastch = lvl_r.rbegin();
618  auto d = cap_r.detail();
619  if ( d.isExpression() ) {
620  static const char* ts = " +|+ ";
621  const char* t = lastch && **lastch == 'l' ? ts : ts+2;
622  if ( lastch ) **lastch = t[0];
623  _dumpRec( str, d.lhs(), lvl_r+" l" ) << endl;
624  if ( lastch ) **lastch = t[1];
625  str << lvl_r << "<" << d.capRel() << endl;
626  if ( lastch ) **lastch = t[2];
627  _dumpRec( str, d.rhs(), lvl_r+" r" );
628  } else {
629  if ( lastch ) **lastch = ' ';
630  str << lvl_r << '"' << d << '"';
631  }
632  return str;
633  }
634 
636  //
637  // CLASS NAME : CapDetail
638  //
640 
642  {
643  // : _kind( NOCAP ), _lhs( id_r ), _rhs( 0 ), _flag( 0 ), _archIfSimple( 0 )
644 
646  return; // NOCAP
647 
648  if ( ! ISRELDEP(_lhs) )
649  {
650  // this is name without arch!
651  _kind = NAMED;
652  return;
653  }
654 
655  ::Reldep * rd = GETRELDEP( StringPool::instance().getPool(), _lhs );
656  _lhs = rd->name;
657  _rhs = rd->evr;
658  _flag = rd->flags;
659 
660  if ( Rel::isRel( _flag ) )
661  {
662  _kind = VERSIONED;
663  // Check for name.arch...
664  if ( ! ISRELDEP(_lhs) )
665  return; // this is name without arch!
666  rd = GETRELDEP( StringPool::instance().getPool(), _lhs );
667  if ( rd->flags != CAP_ARCH )
668  return; // this is not name.arch
669  // This is name.arch:
670  _lhs = rd->name;
671  _archIfSimple = rd->evr;
672  }
673  else if ( rd->flags == CAP_ARCH )
674  {
675  _kind = NAMED;
676  // This is name.arch:
677  _lhs = rd->name;
678  _archIfSimple = rd->evr;
679  }
680  else
681  {
682  _kind = EXPRESSION;
683  return;
684  }
685  // map back libsolvs pseudo arch 'src' to kind srcpackage
686  if ( _archIfSimple == ARCH_SRC || _archIfSimple == ARCH_NOSRC )
687  {
688  _lhs = IdString( (ResKind::srcpackage.asString() + ":" + IdString(_lhs).c_str()).c_str() ).id();
689  _archIfSimple = 0;
690  }
691  }
692 
693  /******************************************************************
694  **
695  ** FUNCTION NAME : operator<<
696  ** FUNCTION TYPE : std::ostream &
697  */
698  std::ostream & operator<<( std::ostream & str, const CapDetail & obj )
699  {
700  static const char archsep = '.';
701  switch ( obj.kind() )
702  {
703  case CapDetail::NOCAP:
704  return str << "<NoCap>";
705  break;
706 
707  case CapDetail::NAMED:
708  str << obj.name();
709  if ( obj.hasArch() )
710  str << archsep << obj.arch();
711  return str;
712  break;
713 
715  str << obj.name();
716  if ( obj.hasArch() )
717  str << archsep << obj.arch();
718  return str << " " << obj.op() << " " << obj.ed();
719  break;
720 
722  {
723  std::string outs;
724  auto pool = StringPool::instance().getPool();
725  auto op = obj.capRel();
726  if ( obj.capRel() == CapDetail::CAP_NAMESPACE ) {
727  cap2strHelper( outs, pool, obj.lhs().id(), op );
728  outs += "(";
729  cap2strHelper( outs, pool, obj.rhs().id(), op );
730  outs += ")";
731  }
732  else {
733  outs += "(";
734  cap2strHelper( outs, pool, obj.lhs().id(), op );
735  outs += opstr( op );
736  cap2strHelper( outs, pool, obj.rhs().id(), op );
737  outs += ")";
738  }
739  return str << outs;
740  }
741  break;
742  }
743  return str << "<UnknownCap(" << obj.lhs() << " " << obj.capRel() << " " << obj.rhs() << ")>";
744  }
745 
746  std::ostream & operator<<( std::ostream & str, CapDetail::Kind obj )
747  {
748  switch ( obj )
749  {
750  case CapDetail::NOCAP: return str << "NoCap"; break;
751  case CapDetail::NAMED: return str << "NamedCap"; break;
752  case CapDetail::VERSIONED: return str << "VersionedCap"; break;
753  case CapDetail::EXPRESSION: return str << "CapExpression"; break;
754  }
755  return str << "UnknownCap";
756  }
757 
758  std::ostream & operator<<( std::ostream & str, CapDetail::CapRel obj )
759  {
760  if ( obj == CapDetail::REL_NONE )
761  return str << "NoCapRel";
762  return str << static_cast<Capability::CapRel>(obj);
763  }
764 
766 } // namespace zypp
static const Rel NE
Definition: Rel.h:53
static const Rel LT
Definition: Rel.h:54
CapRel capRel() const
Definition: Capability.h:427
static const Rel GT
Definition: Rel.h:56
Container of Solvable providing a Capability (read only).
Definition: WhatProvides.h:87
Capability lhs() const
Definition: Capability.h:426
std::ostream & dumpOn(std::ostream &str) const
Definition: Capability.cc:611
Regular expression.
Definition: Regex.h:94
Edition ed() const
Definition: Capability.h:421
bool empty() const
Whether the container is empty.
static CapMatch _doMatch(sat::detail::IdType lhs, sat::detail::IdType rhs)
Match two Capabilities.
Definition: Capability.cc:459
static Capability guessPackageSpec(const std::string &str_r)
Capability parser also guessing "libzypp-1.2.3-4.5.x86_64" formats.
Definition: Capability.cc:573
Helper providing more detailed information about a Capability.
Definition: Capability.h:365
std::string asString(const Patch::Category &obj)
relates: Patch::Category string representation.
Definition: Patch.cc:122
Architecture.
Definition: Arch.h:36
Relational operators.
Definition: Rel.h:45
static const CapMatch no
Definition: CapMatch.h:53
static const Rel EQ
Definition: Rel.h:52
IdType id() const
Expert backdoor.
Definition: IdString.h:144
detail::CPool * getPool() const
Explicit accessor for the raw sat-pool.
Definition: stringpool.h:60
bool isNamed() const
Definition: Capability.h:410
const Arch Arch_empty(IdString::Empty)
String related utilities and Regular expression matching.
static const Rel LE
Definition: Rel.h:55
CapRel
Enum values correspond with libsolv defines.
Definition: Capability.h:151
int IdType
Generic Id type.
Definition: PoolDefines.h:42
static const ResKind srcpackage
Definition: ResKind.h:44
Access to the sat-pools string space.
Definition: IdString.h:51
Rel op() const
Definition: Capability.h:420
Edition represents [epoch:]version[-release]
Definition: Edition.h:59
static const Rel ANY
Definition: Rel.h:58
static bool isInterestingFileSpec(const IdString &name_r)
Test for a filename that is likely being REQUIRED.
Definition: Capability.h:251
IdString arch() const
Definition: Capability.h:418
Support for substring addressing of matches is not required.
Definition: Regex.h:100
static StringPool & instance()
Access the global StringPool instance.
Definition: stringpool.cc:18
constexpr IdString asIdString(ResolverNamespace obj)
relates: ResolverNamespace The underlying libsolv ID
sat::detail::IdType id() const
Expert backdoor.
Definition: Capability.h:289
ResolverNamespace
The resolver&#39;s dependency namespaces.
static const CapMatch irrelevant
Definition: CapMatch.h:54
constexpr bool empty() const
Whether the string is empty.
Definition: IdString.h:99
unsigned split(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \, const Trim trim_r=NO_TRIM)
Split line_r into words.
Definition: String.h:602
Singleton manager for the underlying libsolv string pool.
Definition: stringpool.h:35
static const IdType emptyId(1)
static bool isRel(unsigned bits_r)
Test whether bits_r is a valid Rel (no extra bits set).
Definition: Rel.h:113
Capability _cap
Definition: Capability.h:341
std::string _buf[TLen]
Definition: Capability.cc:50
Used internally.
Definition: Capability.h:393
detail::IdType parserpmrichdep(const char *capstr_r)
libsolv capability parser
Definition: stringpool.h:64
Used internally.
Definition: Capability.h:164
static const Rel GE
Definition: Rel.h:57
std::ostream & dumpOn(std::ostream &str, const Capability &obj)
relates: Capability Detailed stream output
Definition: Capability.cc:589
const char * c_str() const
Conversion to const char *
Definition: IdString.cc:51
Tri state Capability match result.
Definition: CapMatch.h:38
static const Capability Null
No or Null Capability ( Id 0 ).
Definition: Capability.h:172
Kind kind() const
Definition: Capability.h:408
std::string numstring(char n, int w=0)
Definition: String.h:290
SolvableIdType size_type
Definition: poolconstants.h:59
Editions with v-r setparator highlighted.
Regular expression match result.
Definition: Regex.h:167
Global ResObject pool.
Definition: ResPool.h:61
sat::detail::IdType _lhs
Definition: Capability.h:435
sat::detail::IdType _archIfSimple
Definition: Capability.h:438
unsigned _next
Definition: Capability.cc:49
A sat capability.
Definition: Capability.h:62
unsigned _flag
Definition: Capability.h:437
::s_Pool CPool
Wrapped libsolv C data type exposed as backdoor.
Definition: PoolDefines.h:34
static const IdType noId(0)
static const Capability Empty
Empty Capability.
Definition: Capability.h:175
Capability()
Default ctor, Empty capability.
Definition: Capability.h:69
bool regex_match(const char *s, smatch &matches, const regex &regex) ZYPP_API
Regular expression matching.
Definition: Regex.cc:80
Not an expression.
Definition: Capability.h:381
sat::detail::IdType _rhs
Definition: Capability.h:436
byIdent_iterator byIdentEnd(const ByIdent &ident_r) const
Definition: ResPool.h:198
std::string asString() const
Conversion to std::string
Definition: IdString.h:110
CapRel
Enum values corresponding with libsolv defines.
Definition: Capability.h:379
std::ostream & operator<<(std::ostream &str, const Capabilities &obj)
relates: Capabilities Stream output
Definition: Capabilities.cc:65
static const CapMatch yes
Definition: CapMatch.h:52
bool overlaps(const Range< Tp, TCompare > &lhs, const Range< Tp, TCompare > &rhs)
Definition: Range.h:65
Capability rhs() const
Definition: Capability.h:428
CapDetail detail() const
Helper providing more detailed information about a Capability.
Definition: Capability.h:453
bool hasArch() const
Definition: Capability.h:417
Resolvable kinds.
Definition: ResKind.h:32
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
IdString name() const
Definition: Capability.h:419
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:1098
zypp::IdString IdString
Definition: idstring.h:16
const char * c_str() const
Definition: IdStringType.h:115
byIdent_iterator byIdentBegin(const ByIdent &ident_r) const
Definition: ResPool.h:167
static const Edition noedition
Value representing noedition ("") This is in fact a valid Edition.
Definition: Edition.h:72
const char * c_str() const
Conversion to const char *
Definition: Capability.cc:447
std::ostream & _dumpRec(std::ostream &str, Capability cap_r, std::string lvl_r="") const
Definition: Capability.cc:613
static ResPool instance()
Singleton ctor.
Definition: ResPool.cc:38