libzypp
10.5.0
|
00001 /*---------------------------------------------------------------------\ 00002 | ____ _ __ __ ___ | 00003 | |__ / \ / / . \ . \ | 00004 | / / \ V /| _/ _/ | 00005 | / /__ | | | | | | | 00006 | /_____||_| |_| |_| | 00007 | | 00008 \---------------------------------------------------------------------*/ 00012 #include <iostream> 00013 #include "zypp/base/Logger.h" 00014 00015 #include "zypp/base/String.h" 00016 #include "zypp/base/Regex.h" 00017 #include "zypp/base/Gettext.h" 00018 #include "zypp/base/Exception.h" 00019 00020 #include "zypp/Arch.h" 00021 #include "zypp/Rel.h" 00022 #include "zypp/Edition.h" 00023 #include "zypp/Capability.h" 00024 00025 #include "zypp/sat/detail/PoolImpl.h" 00026 #include "zypp/sat/Pool.h" 00027 #include "zypp/ResPool.h" 00028 00029 using std::endl; 00030 00032 namespace zypp 00033 { 00034 00035 namespace 00036 { 00037 00039 inline std::string::size_type backskipWs( const std::string & str_r, std::string::size_type pos_r ) 00040 { 00041 for ( ; pos_r != std::string::npos; --pos_r ) 00042 { 00043 char ch = str_r[pos_r]; 00044 if ( ch != ' ' && ch != '\t' ) 00045 break; 00046 } 00047 return pos_r; 00048 } 00049 00051 inline std::string::size_type backskipNWs( const std::string & str_r, std::string::size_type pos_r ) 00052 { 00053 for ( ; pos_r != std::string::npos; --pos_r ) 00054 { 00055 char ch = str_r[pos_r]; 00056 if ( ch == ' ' || ch == '\t' ) 00057 break; 00058 } 00059 return pos_r; 00060 } 00061 00063 void splitOpEdition( std::string & str_r, Rel & op_r, Edition & ed_r ) 00064 { 00065 if ( str_r.empty() ) 00066 return; 00067 std::string::size_type ch( str_r.size()-1 ); 00068 00069 // check whether the one but last word is a valid Rel: 00070 if ( (ch = backskipWs( str_r, ch )) != std::string::npos ) 00071 { 00072 std::string::size_type ee( ch ); 00073 if ( (ch = backskipNWs( str_r, ch )) != std::string::npos ) 00074 { 00075 std::string::size_type eb( ch ); 00076 if ( (ch = backskipWs( str_r, ch )) != std::string::npos ) 00077 { 00078 std::string::size_type oe( ch ); 00079 ch = backskipNWs( str_r, ch ); // now before 'op'? begin 00080 if ( op_r.parseFrom( str_r.substr( ch+1, oe-ch ) ) ) 00081 { 00082 // found a legal 'op' 00083 ed_r = Edition( str_r.substr( eb+1, ee-eb ) ); 00084 if ( ch != std::string::npos ) // 'op' is not at str_r begin, so skip WS 00085 ch = backskipWs( str_r, ch ); 00086 str_r.erase( ch+1 ); 00087 return; 00088 } 00089 } 00090 } 00091 } 00092 // HERE: Didn't find 'name op edition' 00093 // As a convenience we check for an embeded 'op' (not surounded by WS). 00094 // But just '[<=>]=?|!=' and not inside '()'. 00095 ch = str_r.find_last_of( "<=>)" ); 00096 if ( ch != std::string::npos && str_r[ch] != ')' ) 00097 { 00098 std::string::size_type oe( ch ); 00099 00100 // do edition first: 00101 ch = str_r.find_first_not_of( " \t", oe+1 ); 00102 if ( ch != std::string::npos ) 00103 ed_r = Edition( str_r.substr( ch ) ); 00104 00105 // now finish op: 00106 ch = oe-1; 00107 if ( str_r[oe] != '=' ) // '[<>]' 00108 { 00109 op_r = ( str_r[oe] == '<' ) ? Rel::LT : Rel::GT; 00110 } 00111 else 00112 { // '?=' 00113 if ( ch != std::string::npos ) 00114 { 00115 switch ( str_r[ch] ) 00116 { 00117 case '<': --ch; op_r = Rel::LE; break; 00118 case '>': --ch; op_r = Rel::GE; break; 00119 case '!': --ch; op_r = Rel::NE; break; 00120 case '=': --ch; // fall through 00121 default: op_r = Rel::EQ; break; 00122 } 00123 } 00124 } 00125 00126 // finally name: 00127 if ( ch != std::string::npos ) // 'op' is not at str_r begin, so skip WS 00128 ch = backskipWs( str_r, ch ); 00129 str_r.erase( ch+1 ); 00130 return; 00131 } 00132 // HERE: It's a plain 'name' 00133 } 00134 00137 sat::detail::IdType relFromStr( ::_Pool * pool_r, 00138 const Arch & arch_r, 00139 const std::string & name_r, 00140 Rel op_r, 00141 const Edition & ed_r, 00142 const ResKind & kind_r ) 00143 { 00144 // First build the name, non-packages prefixed by kind 00145 sat::Solvable::SplitIdent split( kind_r, name_r ); 00146 sat::detail::IdType nid( split.ident().id() ); 00147 00148 if ( split.kind() == ResKind::srcpackage ) 00149 { 00150 // map 'kind srcpackage' to 'arch src', the pseudo architecture 00151 // libsolv uses. 00152 nid = ::pool_rel2id( pool_r, nid, IdString(ARCH_SRC).id(), REL_ARCH, /*create*/true ); 00153 } 00154 00155 // Extend name by architecture, if provided and not a srcpackage 00156 if ( ! arch_r.empty() && kind_r != ResKind::srcpackage ) 00157 { 00158 nid = ::pool_rel2id( pool_r, nid, arch_r.id(), REL_ARCH, /*create*/true ); 00159 } 00160 00161 // Extend 'op edition', if provided 00162 if ( op_r != Rel::ANY && ed_r != Edition::noedition ) 00163 { 00164 nid = ::pool_rel2id( pool_r, nid, ed_r.id(), op_r.bits(), /*create*/true ); 00165 } 00166 00167 return nid; 00168 } 00169 00173 sat::detail::IdType relFromStr( ::_Pool * pool_r, 00174 const std::string & name_r, Rel op_r, const Edition & ed_r, 00175 const ResKind & kind_r ) 00176 { 00177 static const Arch srcArch( IdString(ARCH_SRC).asString() ); 00178 static const std::string srcKindPrefix( ResKind::srcpackage.asString() + ':' ); 00179 00180 // check for an embedded 'srcpackage:foo' to be mapped to 'foo' and 'ResKind::srcpackage'. 00181 if ( kind_r.empty() && str::hasPrefix( name_r, srcKindPrefix ) ) 00182 { 00183 return relFromStr( pool_r, Arch_empty, name_r.substr( srcKindPrefix.size() ), op_r, ed_r, ResKind::srcpackage ); 00184 } 00185 00186 Arch arch( Arch_empty ); 00187 std::string name( name_r ); 00188 00189 std::string::size_type asep( name_r.rfind( "." ) ); 00190 if ( asep != std::string::npos ) 00191 { 00192 Arch ext( name_r.substr( asep+1 ) ); 00193 if ( ext.isBuiltIn() || ext == srcArch ) 00194 { 00195 arch = ext; 00196 name.erase( asep ); 00197 } 00198 } 00199 00200 return relFromStr( pool_r, arch, name, op_r, ed_r, kind_r ); 00201 } 00202 00205 sat::detail::IdType relFromStr( ::_Pool * pool_r, 00206 const Arch & arch_r, // parse from name if empty 00207 const std::string & str_r, const ResKind & kind_r, 00208 Capability::CtorFlag flag_r ) 00209 { 00210 std::string name( str_r ); 00211 Rel op; 00212 Edition ed; 00213 if ( flag_r == Capability::UNPARSED ) 00214 { 00215 splitOpEdition( name, op, ed ); 00216 } 00217 00218 if ( arch_r.empty() ) 00219 return relFromStr( pool_r, name, op, ed, kind_r ); // parses for name[.arch] 00220 // else 00221 return relFromStr( pool_r, arch_r, name, op, ed, kind_r ); 00222 } 00223 00225 } // namespace 00227 00228 const Capability Capability::Null( STRID_NULL ); 00229 const Capability Capability::Empty( STRID_EMPTY ); 00230 00232 00233 Capability::Capability( const char * str_r, const ResKind & prefix_r, CtorFlag flag_r ) 00234 : _id( relFromStr( myPool().getPool(), Arch_empty, str_r, prefix_r, flag_r ) ) 00235 {} 00236 00237 Capability::Capability( const std::string & str_r, const ResKind & prefix_r, CtorFlag flag_r ) 00238 : _id( relFromStr( myPool().getPool(), Arch_empty, str_r.c_str(), prefix_r, flag_r ) ) 00239 {} 00240 00241 Capability::Capability( const Arch & arch_r, const char * str_r, const ResKind & prefix_r, CtorFlag flag_r ) 00242 : _id( relFromStr( myPool().getPool(), arch_r, str_r, prefix_r, flag_r ) ) 00243 {} 00244 00245 Capability::Capability( const Arch & arch_r, const std::string & str_r, const ResKind & prefix_r, CtorFlag flag_r ) 00246 : _id( relFromStr( myPool().getPool(), arch_r, str_r.c_str(), prefix_r, flag_r ) ) 00247 {} 00248 00249 Capability::Capability( const char * str_r, CtorFlag flag_r, const ResKind & prefix_r ) 00250 : _id( relFromStr( myPool().getPool(), Arch_empty, str_r, prefix_r, flag_r ) ) 00251 {} 00252 00253 Capability::Capability( const std::string & str_r, CtorFlag flag_r, const ResKind & prefix_r ) 00254 : _id( relFromStr( myPool().getPool(), Arch_empty, str_r, prefix_r, flag_r ) ) 00255 {} 00256 00257 Capability::Capability( const Arch & arch_r, const char * str_r, CtorFlag flag_r, const ResKind & prefix_r ) 00258 : _id( relFromStr( myPool().getPool(), arch_r, str_r, prefix_r, flag_r ) ) 00259 {} 00260 00261 Capability::Capability( const Arch & arch_r, const std::string & str_r, CtorFlag flag_r, const ResKind & prefix_r ) 00262 : _id( relFromStr( myPool().getPool(), arch_r, str_r, prefix_r, flag_r ) ) 00263 {} 00264 00266 // Ctor from <name[.arch] op edition>. 00268 00269 Capability::Capability( const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r ) 00270 : _id( relFromStr( myPool().getPool(), name_r, Rel(op_r), Edition(ed_r), prefix_r ) ) 00271 {} 00272 Capability::Capability( const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r ) 00273 : _id( relFromStr( myPool().getPool(), name_r, op_r, Edition(ed_r), prefix_r ) ) 00274 {} 00275 Capability::Capability( const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r ) 00276 : _id( relFromStr( myPool().getPool(), name_r, op_r, ed_r, prefix_r ) ) 00277 {} 00278 00280 // Ctor from <arch name op edition>. 00282 00283 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 ) 00284 : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, Rel(op_r), Edition(ed_r), prefix_r ) ) 00285 {} 00286 Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r ) 00287 : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, op_r, Edition(ed_r), prefix_r ) ) 00288 {} 00289 Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r ) 00290 : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, op_r, ed_r, prefix_r ) ) 00291 {} 00292 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 ) 00293 : _id( relFromStr( myPool().getPool(), arch_r, name_r, Rel(op_r), Edition(ed_r), prefix_r ) ) 00294 {} 00295 Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r ) 00296 : _id( relFromStr( myPool().getPool(), arch_r, name_r, op_r, Edition(ed_r), prefix_r ) ) 00297 {} 00298 Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r ) 00299 : _id( relFromStr( myPool().getPool(), arch_r, name_r, op_r, ed_r, prefix_r ) ) 00300 {} 00301 00302 const char * Capability::c_str() const 00303 { return( _id ? ::pool_dep2str( myPool().getPool(), _id ) : "" ); } 00304 00305 CapMatch Capability::_doMatch( sat::detail::IdType lhs, sat::detail::IdType rhs ) 00306 { 00307 #warning MIGRATE TO SAT 00308 #warning TESTCASE 00309 if ( lhs == rhs ) 00310 return CapMatch::yes; 00311 00312 CapDetail l( lhs ); 00313 CapDetail r( rhs ); 00314 00315 switch ( l.kind() ) 00316 { 00317 case CapDetail::NOCAP: 00318 return( r.kind() == CapDetail::NOCAP ); // NOCAP matches NOCAP only 00319 break; 00320 case CapDetail::EXPRESSION: 00321 return CapMatch::irrelevant; 00322 break; 00323 case CapDetail::NAMED: 00324 case CapDetail::VERSIONED: 00325 break; 00326 } 00327 00328 switch ( r.kind() ) 00329 { 00330 case CapDetail::NOCAP: 00331 return CapMatch::no; // match case handled above 00332 break; 00333 case CapDetail::EXPRESSION: 00334 return CapMatch::irrelevant; 00335 break; 00336 case CapDetail::NAMED: 00337 case CapDetail::VERSIONED: 00338 break; 00339 } 00340 // comparing two simple caps: 00341 if ( l.name() != r.name() ) 00342 return CapMatch::no; 00343 00344 // if both are arch restricted they must match 00345 if ( l.arch() != r.arch() 00346 && ! ( l.arch().empty() || r.arch().empty() ) ) 00347 return CapMatch::no; 00348 00349 // isNamed matches ANY edition: 00350 if ( l.isNamed() || r.isNamed() ) 00351 return CapMatch::yes; 00352 00353 // both are versioned: 00354 return overlaps( Edition::MatchRange( l.op(), l.ed() ), 00355 Edition::MatchRange( r.op(), r.ed() ) ); 00356 } 00357 00358 bool Capability::isInterestingFileSpec( const char * name_r ) 00359 { 00360 static str::smatch what; 00361 static const str::regex filenameRegex( 00362 "/(s?bin|lib(64)?|etc)/|^/usr/(games/|share/(dict/words|magic\\.mime)$)|^/opt/gnome/games/", 00363 str::regex::optimize|str::regex::nosubs ); 00364 00365 return str::regex_match( name_r, what, filenameRegex ); 00366 } 00367 00368 Capability Capability::guessPackageSpec( const std::string & str_r, bool & rewrote_r ) 00369 { 00370 Capability cap( str_r ); 00371 CapDetail detail( cap.detail() ); 00372 00373 // str_r might be the form "libzypp-1.2.3-4.5(.arch)' 00374 // correctly parsed as name capability by the ctor. 00375 if ( detail.isNamed() && ::strrchr( detail.name().c_str(), '-' ) && sat::WhatProvides( cap ).empty() ) 00376 { 00377 Arch origArch( detail.arch() ); // to support a trailing .arch 00378 00379 std::string guess( detail.name().asString() ); 00380 std::string::size_type pos( guess.rfind( '-' ) ); 00381 guess[pos] = '='; 00382 00383 Capability guesscap( origArch, guess ); 00384 detail = guesscap.detail(); 00385 00386 ResPool pool( ResPool::instance() ); 00387 // require name part matching a pool items name (not just provides!) 00388 if ( pool.byIdentBegin( detail.name() ) != pool.byIdentEnd( detail.name() ) ) 00389 { 00390 rewrote_r = true; 00391 return guesscap; 00392 } 00393 00394 // try the one but last '-' 00395 if ( pos ) 00396 { 00397 guess[pos] = '-'; 00398 if ( (pos = guess.rfind( '-', pos-1 )) != std::string::npos ) 00399 { 00400 guess[pos] = '='; 00401 00402 guesscap = Capability( origArch, guess ); 00403 detail = guesscap.detail(); 00404 00405 // require name part matching a pool items name (not just provides!) 00406 if ( pool.byIdentBegin( detail.name() ) != pool.byIdentEnd( detail.name() ) ) 00407 { 00408 rewrote_r = true; 00409 return guesscap; 00410 } 00411 } 00412 } 00413 } 00414 00415 rewrote_r = false; 00416 return cap; 00417 } 00418 00419 Capability Capability::guessPackageSpec( const std::string & str_r ) 00420 { 00421 bool dummy; 00422 return guessPackageSpec( str_r, dummy ); 00423 } 00424 00425 /****************************************************************** 00426 ** 00427 ** FUNCTION NAME : operator<< 00428 ** FUNCTION TYPE : std::ostream & 00429 */ 00430 std::ostream & operator<<( std::ostream & str, const Capability & obj ) 00431 { 00432 return str << obj.detail(); 00433 } 00434 00435 std::ostream & dumpOn( std::ostream & str, const Capability & obj ) 00436 { 00437 return str << obj.detail(); 00438 } 00439 00441 // 00442 // CLASS NAME : CapDetail 00443 // 00445 00446 void CapDetail::_init() 00447 { 00448 // : _kind( NOCAP ), _lhs( id_r ), _rhs( 0 ), _flag( 0 ), _archIfSimple( 0 ) 00449 00450 if ( _lhs == sat::detail::emptyId || _lhs == sat::detail::noId ) 00451 return; // NOCAP 00452 00453 if ( ! ISRELDEP(_lhs) ) 00454 { 00455 // this is name without arch! 00456 _kind = NAMED; 00457 return; 00458 } 00459 00460 ::Reldep * rd = GETRELDEP( myPool().getPool(), _lhs ); 00461 _lhs = rd->name; 00462 _rhs = rd->evr; 00463 _flag = rd->flags; 00464 00465 if ( Rel::isRel( _flag ) ) 00466 { 00467 _kind = VERSIONED; 00468 // Check for name.arch... 00469 if ( ! ISRELDEP(_lhs) ) 00470 return; // this is name without arch! 00471 rd = GETRELDEP( myPool().getPool(), _lhs ); 00472 if ( rd->flags != CAP_ARCH ) 00473 return; // this is not name.arch 00474 // This is name.arch: 00475 _lhs = rd->name; 00476 _archIfSimple = rd->evr; 00477 } 00478 else if ( rd->flags == CAP_ARCH ) 00479 { 00480 _kind = NAMED; 00481 // This is name.arch: 00482 _lhs = rd->name; 00483 _archIfSimple = rd->evr; 00484 } 00485 else 00486 { 00487 _kind = EXPRESSION; 00488 return; 00489 } 00490 // map back libsolvs pseudo arch 'src' to kind srcpackage 00491 if ( _archIfSimple == ARCH_SRC ) 00492 { 00493 _lhs = IdString( (ResKind::srcpackage.asString() + ":" + IdString(_lhs).c_str()).c_str() ).id(); 00494 _archIfSimple = 0; 00495 } 00496 } 00497 00498 /****************************************************************** 00499 ** 00500 ** FUNCTION NAME : operator<< 00501 ** FUNCTION TYPE : std::ostream & 00502 */ 00503 std::ostream & operator<<( std::ostream & str, const CapDetail & obj ) 00504 { 00505 static const char archsep = '.'; 00506 switch ( obj.kind() ) 00507 { 00508 case CapDetail::NOCAP: 00509 return str << "<NoCap>"; 00510 break; 00511 case CapDetail::NAMED: 00512 str << obj.name(); 00513 if ( obj.hasArch() ) 00514 str << archsep << obj.arch(); 00515 return str; 00516 break; 00517 case CapDetail::VERSIONED: 00518 str << obj.name(); 00519 if ( obj.hasArch() ) 00520 str << archsep << obj.arch(); 00521 return str << " " << obj.op() << " " << obj.ed(); 00522 break; 00523 case CapDetail::EXPRESSION: 00524 switch ( obj.capRel() ) 00525 { 00526 case CapDetail::REL_NONE: 00527 case CapDetail::CAP_AND: 00528 case CapDetail::CAP_OR: 00529 case CapDetail::CAP_WITH: 00530 case CapDetail::CAP_ARCH: 00531 return str << obj.lhs().detail() << " " << obj.capRel() << " " << obj.rhs().detail(); 00532 break; 00533 case CapDetail::CAP_NAMESPACE: 00534 return str << obj.lhs().detail() << "(" << obj.rhs().detail() << ")"; 00535 } 00536 break; 00537 } 00538 return str << "<UnknownCap>"; 00539 } 00540 00541 std::ostream & operator<<( std::ostream & str, CapDetail::Kind obj ) 00542 { 00543 switch ( obj ) 00544 { 00545 case CapDetail::NOCAP: return str << "NoCap"; break; 00546 case CapDetail::NAMED: return str << "NamedCap"; break; 00547 case CapDetail::VERSIONED: return str << "VersionedCap"; break; 00548 case CapDetail::EXPRESSION: return str << "CapExpression"; break; 00549 } 00550 return str << "UnknownCap"; 00551 } 00552 00553 std::ostream & operator<<( std::ostream & str, CapDetail::CapRel obj ) 00554 { 00555 switch ( obj ) 00556 { 00557 case CapDetail::REL_NONE: return str << "NoCapRel"; break; 00558 case CapDetail::CAP_AND: return str << "&"; break; // AND 00559 case CapDetail::CAP_OR: return str << "|"; break; // OR 00560 case CapDetail::CAP_WITH: return str << "+"; break; // WITH 00561 case CapDetail::CAP_NAMESPACE: return str << "NAMESPACE"; break; 00562 case CapDetail::CAP_ARCH: return str << "ARCH"; break; 00563 } 00564 return str << "UnknownCapRel"; 00565 } 00566 00568 } // namespace zypp