1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/sat/Capability.cc
13 #include "zypp/base/Logger.h"
15 #include "zypp/base/String.h"
16 #include "zypp/base/Regex.h"
17 #include "zypp/base/Gettext.h"
18 #include "zypp/base/Exception.h"
20 #include "zypp/Arch.h"
22 #include "zypp/Edition.h"
23 #include "zypp/Capability.h"
25 #include "zypp/sat/detail/PoolImpl.h"
26 #include "zypp/sat/Pool.h"
27 #include "zypp/ResPool.h"
31 ///////////////////////////////////////////////////////////////////
33 { /////////////////////////////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////
36 { /////////////////////////////////////////////////////////////////
38 /** backward skip whitespace starting at pos_r */
39 inline std::string::size_type backskipWs( const std::string & str_r, std::string::size_type pos_r )
41 for ( ; pos_r != std::string::npos; --pos_r )
43 char ch = str_r[pos_r];
44 if ( ch != ' ' && ch != '\t' )
50 /** backward skip non-whitespace starting at pos_r */
51 inline std::string::size_type backskipNWs( const std::string & str_r, std::string::size_type pos_r )
53 for ( ; pos_r != std::string::npos; --pos_r )
55 char ch = str_r[pos_r];
56 if ( ch == ' ' || ch == '\t' )
62 /** Split any 'op edition' from str_r */
63 void splitOpEdition( std::string & str_r, Rel & op_r, Edition & ed_r )
67 std::string::size_type ch( str_r.size()-1 );
69 // check whether the one but last word is a valid Rel:
70 if ( (ch = backskipWs( str_r, ch )) != std::string::npos )
72 std::string::size_type ee( ch );
73 if ( (ch = backskipNWs( str_r, ch )) != std::string::npos )
75 std::string::size_type eb( ch );
76 if ( (ch = backskipWs( str_r, ch )) != std::string::npos )
78 std::string::size_type oe( ch );
79 ch = backskipNWs( str_r, ch ); // now before 'op'? begin
80 if ( op_r.parseFrom( str_r.substr( ch+1, oe-ch ) ) )
83 ed_r = Edition( str_r.substr( eb+1, ee-eb ) );
84 if ( ch != std::string::npos ) // 'op' is not at str_r begin, so skip WS
85 ch = backskipWs( str_r, ch );
92 // HERE: Didn't find 'name op edition'
93 // As a convenience we check for an embeded 'op' (not surounded by WS).
94 // But just '[<=>]=?|!=' and not inside '()'.
95 ch = str_r.find_last_of( "<=>)" );
96 if ( ch != std::string::npos && str_r[ch] != ')' )
98 std::string::size_type oe( ch );
101 ch = str_r.find_first_not_of( " \t", oe+1 );
102 if ( ch != std::string::npos )
103 ed_r = Edition( str_r.substr( ch ) );
107 if ( str_r[oe] != '=' ) // '[<>]'
109 op_r = ( str_r[oe] == '<' ) ? Rel::LT : Rel::GT;
113 if ( ch != std::string::npos )
117 case '<': --ch; op_r = Rel::LE; break;
118 case '>': --ch; op_r = Rel::GE; break;
119 case '!': --ch; op_r = Rel::NE; break;
120 case '=': --ch; // fall through
121 default: op_r = Rel::EQ; break;
127 if ( ch != std::string::npos ) // 'op' is not at str_r begin, so skip WS
128 ch = backskipWs( str_r, ch );
132 // HERE: It's a plain 'name'
135 /** Build \ref Capability from data. No parsing required.
137 sat::detail::IdType relFromStr( sat::detail::CPool * pool_r,
139 const std::string & name_r,
141 const Edition & ed_r,
142 const ResKind & kind_r )
144 // First build the name, non-packages prefixed by kind
145 sat::Solvable::SplitIdent split( kind_r, name_r );
146 sat::detail::IdType nid( split.ident().id() );
148 if ( split.kind() == ResKind::srcpackage )
150 // map 'kind srcpackage' to 'arch src', the pseudo architecture
152 nid = ::pool_rel2id( pool_r, nid, IdString(ARCH_SRC).id(), REL_ARCH, /*create*/true );
155 // Extend name by architecture, if provided and not a srcpackage
156 if ( ! arch_r.empty() && kind_r != ResKind::srcpackage )
158 nid = ::pool_rel2id( pool_r, nid, arch_r.id(), REL_ARCH, /*create*/true );
161 // Extend 'op edition', if provided
162 if ( op_r != Rel::ANY && ed_r != Edition::noedition )
164 nid = ::pool_rel2id( pool_r, nid, ed_r.id(), op_r.bits(), /*create*/true );
170 /** Build \ref Capability from data, just parsing name for '[.arch]' and detect
171 * 'kind srcpackage' (will be mapped to arch \c src).
173 sat::detail::IdType relFromStr( sat::detail::CPool * pool_r,
174 const std::string & name_r, Rel op_r, const Edition & ed_r,
175 const ResKind & kind_r )
177 static const Arch srcArch( IdString(ARCH_SRC).asString() );
178 static const std::string srcKindPrefix( ResKind::srcpackage.asString() + ':' );
180 // check for an embedded 'srcpackage:foo' to be mapped to 'foo' and 'ResKind::srcpackage'.
181 if ( kind_r.empty() && str::hasPrefix( name_r, srcKindPrefix ) )
183 return relFromStr( pool_r, Arch_empty, name_r.substr( srcKindPrefix.size() ), op_r, ed_r, ResKind::srcpackage );
186 Arch arch( Arch_empty );
187 std::string name( name_r );
189 std::string::size_type asep( name_r.rfind( "." ) );
190 if ( asep != std::string::npos )
192 Arch ext( name_r.substr( asep+1 ) );
193 if ( ext.isBuiltIn() || ext == srcArch )
200 return relFromStr( pool_r, arch, name, op_r, ed_r, kind_r );
203 /** Full parse from string, unless Capability::PARSED.
205 sat::detail::IdType relFromStr( sat::detail::CPool * pool_r,
206 const Arch & arch_r, // parse from name if empty
207 const std::string & str_r, const ResKind & kind_r,
208 Capability::CtorFlag flag_r )
210 std::string name( str_r );
213 if ( flag_r == Capability::UNPARSED )
215 splitOpEdition( name, op, ed );
218 if ( arch_r.empty() )
219 return relFromStr( pool_r, name, op, ed, kind_r ); // parses for name[.arch]
221 return relFromStr( pool_r, arch_r, name, op, ed, kind_r );
224 /////////////////////////////////////////////////////////////////
226 ///////////////////////////////////////////////////////////////////
228 const Capability Capability::Null( STRID_NULL );
229 const Capability Capability::Empty( STRID_EMPTY );
231 /////////////////////////////////////////////////////////////////
233 Capability::Capability( const char * str_r, const ResKind & prefix_r, CtorFlag flag_r )
234 : _id( relFromStr( myPool().getPool(), Arch_empty, str_r, prefix_r, flag_r ) )
237 Capability::Capability( const std::string & str_r, const ResKind & prefix_r, CtorFlag flag_r )
238 : _id( relFromStr( myPool().getPool(), Arch_empty, str_r.c_str(), prefix_r, flag_r ) )
241 Capability::Capability( const Arch & arch_r, const char * str_r, const ResKind & prefix_r, CtorFlag flag_r )
242 : _id( relFromStr( myPool().getPool(), arch_r, str_r, prefix_r, flag_r ) )
245 Capability::Capability( const Arch & arch_r, const std::string & str_r, const ResKind & prefix_r, CtorFlag flag_r )
246 : _id( relFromStr( myPool().getPool(), arch_r, str_r.c_str(), prefix_r, flag_r ) )
249 Capability::Capability( const char * str_r, CtorFlag flag_r, const ResKind & prefix_r )
250 : _id( relFromStr( myPool().getPool(), Arch_empty, str_r, prefix_r, flag_r ) )
253 Capability::Capability( const std::string & str_r, CtorFlag flag_r, const ResKind & prefix_r )
254 : _id( relFromStr( myPool().getPool(), Arch_empty, str_r, prefix_r, flag_r ) )
257 Capability::Capability( const Arch & arch_r, const char * str_r, CtorFlag flag_r, const ResKind & prefix_r )
258 : _id( relFromStr( myPool().getPool(), arch_r, str_r, prefix_r, flag_r ) )
261 Capability::Capability( const Arch & arch_r, const std::string & str_r, CtorFlag flag_r, const ResKind & prefix_r )
262 : _id( relFromStr( myPool().getPool(), arch_r, str_r, prefix_r, flag_r ) )
265 ///////////////////////////////////////////////////////////////////
266 // Ctor from <name[.arch] op edition>.
267 ///////////////////////////////////////////////////////////////////
269 Capability::Capability( const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r )
270 : _id( relFromStr( myPool().getPool(), name_r, Rel(op_r), Edition(ed_r), prefix_r ) )
272 Capability::Capability( const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r )
273 : _id( relFromStr( myPool().getPool(), name_r, op_r, Edition(ed_r), prefix_r ) )
275 Capability::Capability( const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r )
276 : _id( relFromStr( myPool().getPool(), name_r, op_r, ed_r, prefix_r ) )
279 ///////////////////////////////////////////////////////////////////
280 // Ctor from <arch name op edition>.
281 ///////////////////////////////////////////////////////////////////
283 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 )
284 : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, Rel(op_r), Edition(ed_r), prefix_r ) )
286 Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r )
287 : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, op_r, Edition(ed_r), prefix_r ) )
289 Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r )
290 : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, op_r, ed_r, prefix_r ) )
292 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 )
293 : _id( relFromStr( myPool().getPool(), arch_r, name_r, Rel(op_r), Edition(ed_r), prefix_r ) )
295 Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r )
296 : _id( relFromStr( myPool().getPool(), arch_r, name_r, op_r, Edition(ed_r), prefix_r ) )
298 Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r )
299 : _id( relFromStr( myPool().getPool(), arch_r, name_r, op_r, ed_r, prefix_r ) )
302 ///////////////////////////////////////////////////////////////////
303 // Ctor creating a namespace: capability.
304 ///////////////////////////////////////////////////////////////////
306 Capability::Capability( ResolverNamespace namespace_r, IdString value_r )
307 : _id( ::pool_rel2id( myPool().getPool(), asIdString(namespace_r).id(), (value_r.empty() ? STRID_NULL : value_r.id() ), REL_NAMESPACE, /*create*/true ) )
311 const char * Capability::c_str() const
312 { return( _id ? ::pool_dep2str( myPool().getPool(), _id ) : "" ); }
314 CapMatch Capability::_doMatch( sat::detail::IdType lhs, sat::detail::IdType rhs )
316 #warning MIGRATE TO SAT
319 return CapMatch::yes;
326 case CapDetail::NOCAP:
327 return( r.kind() == CapDetail::NOCAP ); // NOCAP matches NOCAP only
329 case CapDetail::EXPRESSION:
330 return CapMatch::irrelevant;
332 case CapDetail::NAMED:
333 case CapDetail::VERSIONED:
339 case CapDetail::NOCAP:
340 return CapMatch::no; // match case handled above
342 case CapDetail::EXPRESSION:
343 return CapMatch::irrelevant;
345 case CapDetail::NAMED:
346 case CapDetail::VERSIONED:
349 // comparing two simple caps:
350 if ( l.name() != r.name() )
353 // if both are arch restricted they must match
354 if ( l.arch() != r.arch()
355 && ! ( l.arch().empty() || r.arch().empty() ) )
358 // isNamed matches ANY edition:
359 if ( l.isNamed() || r.isNamed() )
360 return CapMatch::yes;
362 // both are versioned:
363 return overlaps( Edition::MatchRange( l.op(), l.ed() ),
364 Edition::MatchRange( r.op(), r.ed() ) );
367 bool Capability::isInterestingFileSpec( const char * name_r )
369 static str::smatch what;
370 static const str::regex filenameRegex(
371 "/(s?bin|lib(64)?|etc)/|^/usr/(games/|share/(dict/words|magic\\.mime)$)|^/opt/gnome/games/",
372 str::regex::nosubs );
374 return str::regex_match( name_r, what, filenameRegex );
377 Capability Capability::guessPackageSpec( const std::string & str_r, bool & rewrote_r )
379 Capability cap( str_r );
380 CapDetail detail( cap.detail() );
382 // str_r might be the form "libzypp-1.2.3-4.5(.arch)'
383 // correctly parsed as name capability by the ctor.
384 // TODO: Think about allowing glob char in name - for now don't process
385 if ( detail.isNamed() && !::strpbrk( detail.name().c_str(), "*?[{" )
386 && ::strrchr( detail.name().c_str(), '-' ) && sat::WhatProvides( cap ).empty() )
388 Arch origArch( detail.arch() ); // to support a trailing .arch
390 std::string guess( detail.name().asString() );
391 std::string::size_type pos( guess.rfind( '-' ) );
394 Capability guesscap( origArch, guess );
395 detail = guesscap.detail();
397 ResPool pool( ResPool::instance() );
398 // require name part matching a pool items name (not just provides!)
399 if ( pool.byIdentBegin( detail.name() ) != pool.byIdentEnd( detail.name() ) )
405 // try the one but last '-'
409 if ( (pos = guess.rfind( '-', pos-1 )) != std::string::npos )
413 guesscap = Capability( origArch, guess );
414 detail = guesscap.detail();
416 // require name part matching a pool items name (not just provides!)
417 if ( pool.byIdentBegin( detail.name() ) != pool.byIdentEnd( detail.name() ) )
430 Capability Capability::guessPackageSpec( const std::string & str_r )
433 return guessPackageSpec( str_r, dummy );
436 /******************************************************************
438 ** FUNCTION NAME : operator<<
439 ** FUNCTION TYPE : std::ostream &
441 std::ostream & operator<<( std::ostream & str, const Capability & obj )
443 return str << obj.detail();
446 std::ostream & dumpOn( std::ostream & str, const Capability & obj )
448 return str << obj.detail();
451 ///////////////////////////////////////////////////////////////////
453 // CLASS NAME : CapDetail
455 ///////////////////////////////////////////////////////////////////
457 void CapDetail::_init()
459 // : _kind( NOCAP ), _lhs( id_r ), _rhs( 0 ), _flag( 0 ), _archIfSimple( 0 )
461 if ( _lhs == sat::detail::emptyId || _lhs == sat::detail::noId )
464 if ( ! ISRELDEP(_lhs) )
466 // this is name without arch!
471 ::Reldep * rd = GETRELDEP( myPool().getPool(), _lhs );
476 if ( Rel::isRel( _flag ) )
479 // Check for name.arch...
480 if ( ! ISRELDEP(_lhs) )
481 return; // this is name without arch!
482 rd = GETRELDEP( myPool().getPool(), _lhs );
483 if ( rd->flags != CAP_ARCH )
484 return; // this is not name.arch
485 // This is name.arch:
487 _archIfSimple = rd->evr;
489 else if ( rd->flags == CAP_ARCH )
492 // This is name.arch:
494 _archIfSimple = rd->evr;
501 // map back libsolvs pseudo arch 'src' to kind srcpackage
502 if ( _archIfSimple == ARCH_SRC )
504 _lhs = IdString( (ResKind::srcpackage.asString() + ":" + IdString(_lhs).c_str()).c_str() ).id();
509 /******************************************************************
511 ** FUNCTION NAME : operator<<
512 ** FUNCTION TYPE : std::ostream &
514 std::ostream & operator<<( std::ostream & str, const CapDetail & obj )
516 static const char archsep = '.';
517 switch ( obj.kind() )
519 case CapDetail::NOCAP:
520 return str << "<NoCap>";
522 case CapDetail::NAMED:
525 str << archsep << obj.arch();
528 case CapDetail::VERSIONED:
531 str << archsep << obj.arch();
532 return str << " " << obj.op() << " " << obj.ed();
534 case CapDetail::EXPRESSION:
535 switch ( obj.capRel() )
537 case CapDetail::REL_NONE:
538 case CapDetail::CAP_AND:
539 case CapDetail::CAP_OR:
540 case CapDetail::CAP_WITH:
541 case CapDetail::CAP_ARCH:
542 return str << obj.lhs().detail() << " " << obj.capRel() << " " << obj.rhs().detail();
544 case CapDetail::CAP_NAMESPACE:
545 return str << obj.lhs().detail() << "(" << obj.rhs().detail() << ")";
549 return str << "<UnknownCap>";
552 std::ostream & operator<<( std::ostream & str, CapDetail::Kind obj )
556 case CapDetail::NOCAP: return str << "NoCap"; break;
557 case CapDetail::NAMED: return str << "NamedCap"; break;
558 case CapDetail::VERSIONED: return str << "VersionedCap"; break;
559 case CapDetail::EXPRESSION: return str << "CapExpression"; break;
561 return str << "UnknownCap";
564 std::ostream & operator<<( std::ostream & str, CapDetail::CapRel obj )
568 case CapDetail::REL_NONE: return str << "NoCapRel"; break;
569 case CapDetail::CAP_AND: return str << "&"; break; // AND
570 case CapDetail::CAP_OR: return str << "|"; break; // OR
571 case CapDetail::CAP_WITH: return str << "+"; break; // WITH
572 case CapDetail::CAP_NAMESPACE: return str << "NAMESPACE"; break;
573 case CapDetail::CAP_ARCH: return str << "ARCH"; break;
575 return str << "UnknownCapRel";
578 /////////////////////////////////////////////////////////////////
580 ///////////////////////////////////////////////////////////////////