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"
30 ///////////////////////////////////////////////////////////////////
32 { /////////////////////////////////////////////////////////////////
33 ///////////////////////////////////////////////////////////////////
35 { /////////////////////////////////////////////////////////////////
37 /** backward skip whitespace starting at pos_r */
38 inline std::string::size_type backskipWs( const std::string & str_r, std::string::size_type pos_r )
40 for ( ; pos_r != std::string::npos; --pos_r )
42 char ch = str_r[pos_r];
43 if ( ch != ' ' && ch != '\t' )
49 /** backward skip non-whitespace starting at pos_r */
50 inline std::string::size_type backskipNWs( const std::string & str_r, std::string::size_type pos_r )
52 for ( ; pos_r != std::string::npos; --pos_r )
54 char ch = str_r[pos_r];
55 if ( ch == ' ' || ch == '\t' )
61 /** Split any 'op edition' from str_r */
62 void splitOpEdition( std::string & str_r, Rel & op_r, Edition & ed_r )
66 std::string::size_type ch( str_r.size()-1 );
68 // check whether the one but last word is a valid Rel:
69 if ( (ch = backskipWs( str_r, ch )) != std::string::npos )
71 std::string::size_type ee( ch );
72 if ( (ch = backskipNWs( str_r, ch )) != std::string::npos )
74 std::string::size_type eb( ch );
75 if ( (ch = backskipWs( str_r, ch )) != std::string::npos )
77 std::string::size_type oe( ch );
78 ch = backskipNWs( str_r, ch ); // now before 'op'? begin
79 if ( op_r.parseFrom( str_r.substr( ch+1, oe-ch ) ) )
82 ed_r = Edition( str_r.substr( eb+1, ee-eb ) );
83 if ( ch != std::string::npos ) // 'op' is not at str_r begin, so skip WS
84 ch = backskipWs( str_r, ch );
91 // HERE: Didn't find 'name op edition'
92 // As a convenience we check for an embeded 'op' (not surounded by WS).
93 // But just '[<=>]=?|!=' and not inside '()'.
94 ch = str_r.find_last_of( "<=>)" );
95 if ( ch != std::string::npos && str_r[ch] != ')' )
97 std::string::size_type oe( ch );
100 ch = str_r.find_first_not_of( " \t", oe+1 );
101 if ( ch != std::string::npos )
102 ed_r = Edition( str_r.substr( ch ) );
106 if ( str_r[oe] != '=' ) // '[<>]'
108 op_r = ( str_r[oe] == '<' ) ? Rel::LT : Rel::GT;
112 if ( ch != std::string::npos )
116 case '<': --ch; op_r = Rel::LE; break;
117 case '>': --ch; op_r = Rel::GE; break;
118 case '!': --ch; op_r = Rel::NE; break;
119 case '=': --ch; // fall through
120 default: op_r = Rel::EQ; break;
126 if ( ch != std::string::npos ) // 'op' is not at str_r begin, so skip WS
127 ch = backskipWs( str_r, ch );
131 // HERE: It's a plain 'name'
134 /** Build \ref Capability from data. No parsing required.
136 sat::detail::IdType relFromStr( ::_Pool * pool_r,
138 const std::string & name_r,
140 const Edition & ed_r,
141 const ResKind & kind_r )
143 // First build the name, non-packages prefixed by kind
144 sat::detail::IdType nid( sat::detail::noId );
145 if ( ! kind_r || kind_r == ResKind::package )
147 nid = IdString( name_r ).id();
149 else if ( kind_r == ResKind::srcpackage )
151 // map 'kind srcpackage' to 'arch src', the pseudo architecture
153 nid = IdString( name_r ).id();
154 nid = ::rel2id( pool_r, nid, IdString(ARCH_SRC).id(), REL_ARCH, /*create*/true );
158 nid = IdString( str::form( "%s:%s",
160 name_r.c_str() ) ).id();
164 // Extend name by architecture, if provided and not a srcpackage
165 if ( ! arch_r.empty() && kind_r != ResKind::srcpackage )
167 nid = ::rel2id( pool_r, nid, arch_r.id(), REL_ARCH, /*create*/true );
170 // Extend 'op edition', if provided
171 if ( op_r != Rel::ANY && ed_r != Edition::noedition )
173 nid = ::rel2id( pool_r, nid, ed_r.id(), op_r.bits(), /*create*/true );
179 /** Build \ref Capability from data, just parsing name for '[.arch]' and detect
180 * 'kind srcpackage' (will be mapped to arch \c src).
182 sat::detail::IdType relFromStr( ::_Pool * pool_r,
183 const std::string & name_r, Rel op_r, const Edition & ed_r,
184 const ResKind & kind_r )
186 static const Arch srcArch( IdString(ARCH_SRC).asString() );
187 static const std::string srcKindPrefix( ResKind::srcpackage.asString() + ':' );
189 // check for an embedded 'srcpackage:foo' to be mapped to 'foo' and 'ResKind::srcpackage'.
190 if ( kind_r.empty() && str::hasPrefix( name_r, srcKindPrefix ) )
192 return relFromStr( pool_r, Arch_empty, name_r.substr( srcKindPrefix.size() ), op_r, ed_r, ResKind::srcpackage );
195 Arch arch( Arch_empty );
196 std::string name( name_r );
198 std::string::size_type asep( name_r.rfind( "." ) );
199 if ( asep != std::string::npos )
201 Arch ext( name_r.substr( asep+1 ) );
202 if ( ext.isBuiltIn() || ext == srcArch )
209 return relFromStr( pool_r, arch, name, op_r, ed_r, kind_r );
212 /** Full parse from string, unless Capability::PARSED.
214 sat::detail::IdType relFromStr( ::_Pool * pool_r,
215 const Arch & arch_r, // parse from name if empty
216 const std::string & str_r, const ResKind & kind_r,
217 Capability::CtorFlag flag_r )
219 std::string name( str_r );
222 if ( flag_r == Capability::UNPARSED )
224 splitOpEdition( name, op, ed );
227 if ( arch_r.empty() )
228 return relFromStr( pool_r, name, op, ed, kind_r ); // parses for name[.arch]
230 return relFromStr( pool_r, arch_r, name, op, ed, kind_r );
233 /////////////////////////////////////////////////////////////////
235 ///////////////////////////////////////////////////////////////////
237 const Capability Capability::Null( STRID_NULL );
238 const Capability Capability::Empty( STRID_EMPTY );
240 /////////////////////////////////////////////////////////////////
242 Capability::Capability( const char * str_r, const ResKind & prefix_r, CtorFlag flag_r )
243 : _id( relFromStr( myPool().getPool(), Arch_empty, str_r, prefix_r, flag_r ) )
246 Capability::Capability( const std::string & str_r, const ResKind & prefix_r, CtorFlag flag_r )
247 : _id( relFromStr( myPool().getPool(), Arch_empty, str_r.c_str(), prefix_r, flag_r ) )
250 Capability::Capability( const Arch & arch_r, const char * str_r, const ResKind & prefix_r, CtorFlag flag_r )
251 : _id( relFromStr( myPool().getPool(), arch_r, str_r, prefix_r, flag_r ) )
254 Capability::Capability( const Arch & arch_r, const std::string & str_r, const ResKind & prefix_r, CtorFlag flag_r )
255 : _id( relFromStr( myPool().getPool(), arch_r, str_r.c_str(), prefix_r, flag_r ) )
258 Capability::Capability( const char * str_r, CtorFlag flag_r, const ResKind & prefix_r )
259 : _id( relFromStr( myPool().getPool(), Arch_empty, str_r, prefix_r, flag_r ) )
262 Capability::Capability( const std::string & str_r, CtorFlag flag_r, const ResKind & prefix_r )
263 : _id( relFromStr( myPool().getPool(), Arch_empty, str_r, prefix_r, flag_r ) )
266 Capability::Capability( const Arch & arch_r, const char * str_r, CtorFlag flag_r, const ResKind & prefix_r )
267 : _id( relFromStr( myPool().getPool(), arch_r, str_r, prefix_r, flag_r ) )
270 Capability::Capability( const Arch & arch_r, const std::string & str_r, CtorFlag flag_r, const ResKind & prefix_r )
271 : _id( relFromStr( myPool().getPool(), arch_r, str_r, prefix_r, flag_r ) )
274 ///////////////////////////////////////////////////////////////////
275 // Ctor from <name[.arch] op edition>.
276 ///////////////////////////////////////////////////////////////////
278 Capability::Capability( const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r )
279 : _id( relFromStr( myPool().getPool(), name_r, Rel(op_r), Edition(ed_r), prefix_r ) )
281 Capability::Capability( const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r )
282 : _id( relFromStr( myPool().getPool(), name_r, op_r, Edition(ed_r), prefix_r ) )
284 Capability::Capability( const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r )
285 : _id( relFromStr( myPool().getPool(), name_r, op_r, ed_r, prefix_r ) )
288 ///////////////////////////////////////////////////////////////////
289 // Ctor from <arch name op edition>.
290 ///////////////////////////////////////////////////////////////////
292 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 )
293 : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, Rel(op_r), Edition(ed_r), prefix_r ) )
295 Capability::Capability( const std::string & 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(arch_r), name_r, op_r, Edition(ed_r), prefix_r ) )
298 Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r )
299 : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, op_r, ed_r, prefix_r ) )
301 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 )
302 : _id( relFromStr( myPool().getPool(), arch_r, name_r, Rel(op_r), Edition(ed_r), prefix_r ) )
304 Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r )
305 : _id( relFromStr( myPool().getPool(), arch_r, name_r, op_r, Edition(ed_r), prefix_r ) )
307 Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r )
308 : _id( relFromStr( myPool().getPool(), arch_r, name_r, op_r, ed_r, prefix_r ) )
311 const char * Capability::c_str() const
312 { return( _id ? ::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::optimize|str::regex::nosubs );
374 return str::regex_match( name_r, what, filenameRegex );
377 Capability Capability::guessPackageSpec( const std::string & str_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 if ( detail.isNamed() && ::strrchr( detail.name().c_str(), '-' ) && sat::WhatProvides( cap ).empty() )
386 Arch origArch( detail.arch() ); // to support a trailing .arch
388 std::string guess( detail.name().asString() );
389 std::string::size_type pos( guess.rfind( '-' ) );
392 Capability guesscap( origArch, guess );
393 detail = guesscap.detail();
395 if ( ! sat::WhatProvides( Capability(detail.name().id()) ).empty() )
398 // try the one but last '-'
402 if ( (pos = guess.rfind( '-', pos-1 )) != std::string::npos )
406 guesscap = Capability( origArch, guess );
407 detail = guesscap.detail();
409 if ( ! sat::WhatProvides( Capability(detail.name().id()) ).empty() )
417 /******************************************************************
419 ** FUNCTION NAME : operator<<
420 ** FUNCTION TYPE : std::ostream &
422 std::ostream & operator<<( std::ostream & str, const Capability & obj )
424 return str << obj.detail();
427 std::ostream & dumpOn( std::ostream & str, const Capability & obj )
429 return str << obj.detail();
432 ///////////////////////////////////////////////////////////////////
434 // CLASS NAME : CapDetail
436 ///////////////////////////////////////////////////////////////////
438 void CapDetail::_init()
440 // : _kind( NOCAP ), _lhs( id_r ), _rhs( 0 ), _flag( 0 ), _archIfSimple( 0 )
442 if ( _lhs == sat::detail::emptyId || _lhs == sat::detail::noId )
445 if ( ! ISRELDEP(_lhs) )
447 // this is name without arch!
452 ::Reldep * rd = GETRELDEP( myPool().getPool(), _lhs );
457 if ( Rel::isRel( _flag ) )
460 // Check for name.arch...
461 if ( ! ISRELDEP(_lhs) )
462 return; // this is name without arch!
463 rd = GETRELDEP( myPool().getPool(), _lhs );
464 if ( rd->flags != CAP_ARCH )
465 return; // this is not name.arch
466 // This is name.arch:
468 _archIfSimple = rd->evr;
470 else if ( rd->flags == CAP_ARCH )
473 // This is name.arch:
475 _archIfSimple = rd->evr;
482 // map back satsolvers pseudo arch 'src' to kind srcpackage
483 if ( _archIfSimple == ARCH_SRC )
485 _lhs = IdString( (ResKind::srcpackage.asString() + ":" + IdString(_lhs).c_str()).c_str() ).id();
490 /******************************************************************
492 ** FUNCTION NAME : operator<<
493 ** FUNCTION TYPE : std::ostream &
495 std::ostream & operator<<( std::ostream & str, const CapDetail & obj )
497 static const char archsep = '.';
498 switch ( obj.kind() )
500 case CapDetail::NOCAP:
501 return str << "<NoCap>";
503 case CapDetail::NAMED:
506 str << archsep << obj.arch();
509 case CapDetail::VERSIONED:
512 str << archsep << obj.arch();
513 return str << " " << obj.op() << " " << obj.ed();
515 case CapDetail::EXPRESSION:
516 switch ( obj.capRel() )
518 case CapDetail::REL_NONE:
519 case CapDetail::CAP_AND:
520 case CapDetail::CAP_OR:
521 case CapDetail::CAP_WITH:
522 case CapDetail::CAP_ARCH:
523 return str << obj.lhs().detail() << " " << obj.capRel() << " " << obj.rhs().detail();
525 case CapDetail::CAP_NAMESPACE:
526 return str << obj.lhs().detail() << "(" << obj.rhs().detail() << ")";
530 return str << "<UnknownCap>";
533 std::ostream & operator<<( std::ostream & str, CapDetail::Kind obj )
537 case CapDetail::NOCAP: return str << "NoCap"; break;
538 case CapDetail::NAMED: return str << "NamedCap"; break;
539 case CapDetail::VERSIONED: return str << "VersionedCap"; break;
540 case CapDetail::EXPRESSION: return str << "CapExpression"; break;
542 return str << "UnknownCap";
545 std::ostream & operator<<( std::ostream & str, CapDetail::CapRel obj )
549 case CapDetail::REL_NONE: return str << "NoCapRel"; break;
550 case CapDetail::CAP_AND: return str << "&"; break; // AND
551 case CapDetail::CAP_OR: return str << "|"; break; // OR
552 case CapDetail::CAP_WITH: return str << "+"; break; // WITH
553 case CapDetail::CAP_NAMESPACE: return str << "NAMESPACE"; break;
554 case CapDetail::CAP_ARCH: return str << "ARCH"; break;
556 return str << "UnknownCapRel";
559 /////////////////////////////////////////////////////////////////
561 ///////////////////////////////////////////////////////////////////