00001
00002
00003
00004
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
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 );
00080 if ( op_r.parseFrom( str_r.substr( ch+1, oe-ch ) ) )
00081 {
00082
00083 ed_r = Edition( str_r.substr( eb+1, ee-eb ) );
00084 if ( ch != std::string::npos )
00085 ch = backskipWs( str_r, ch );
00086 str_r.erase( ch+1 );
00087 return;
00088 }
00089 }
00090 }
00091 }
00092
00093
00094
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
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
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;
00121 default: op_r = Rel::EQ; break;
00122 }
00123 }
00124 }
00125
00126
00127 if ( ch != std::string::npos )
00128 ch = backskipWs( str_r, ch );
00129 str_r.erase( ch+1 );
00130 return;
00131 }
00132
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
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
00151
00152 nid = ::rel2id( pool_r, nid, IdString(ARCH_SRC).id(), REL_ARCH, true );
00153 }
00154
00155
00156 if ( ! arch_r.empty() && kind_r != ResKind::srcpackage )
00157 {
00158 nid = ::rel2id( pool_r, nid, arch_r.id(), REL_ARCH, true );
00159 }
00160
00161
00162 if ( op_r != Rel::ANY && ed_r != Edition::noedition )
00163 {
00164 nid = ::rel2id( pool_r, nid, ed_r.id(), op_r.bits(), 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
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,
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 );
00220
00221 return relFromStr( pool_r, arch_r, name, op, ed, kind_r );
00222 }
00223
00225 }
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
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
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 ? ::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 );
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;
00332 break;
00333 case CapDetail::EXPRESSION:
00334 return CapMatch::irrelevant;
00335 break;
00336 case CapDetail::NAMED:
00337 case CapDetail::VERSIONED:
00338 break;
00339 }
00340
00341 if ( l.name() != r.name() )
00342 return CapMatch::no;
00343
00344
00345 if ( l.arch() != r.arch()
00346 && ! ( l.arch().empty() || r.arch().empty() ) )
00347 return CapMatch::no;
00348
00349
00350 if ( l.isNamed() || r.isNamed() )
00351 return CapMatch::yes;
00352
00353
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
00374
00375 if ( detail.isNamed() && ::strrchr( detail.name().c_str(), '-' ) && sat::WhatProvides( cap ).empty() )
00376 {
00377 Arch origArch( detail.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
00388 if ( pool.byIdentBegin( detail.name() ) != pool.byIdentEnd( detail.name() ) )
00389 {
00390 rewrote_r = true;
00391 return guesscap;
00392 }
00393
00394
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
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
00428
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
00443
00445
00446 void CapDetail::_init()
00447 {
00448
00449
00450 if ( _lhs == sat::detail::emptyId || _lhs == sat::detail::noId )
00451 return;
00452
00453 if ( ! ISRELDEP(_lhs) )
00454 {
00455
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
00469 if ( ! ISRELDEP(_lhs) )
00470 return;
00471 rd = GETRELDEP( myPool().getPool(), _lhs );
00472 if ( rd->flags != CAP_ARCH )
00473 return;
00474
00475 _lhs = rd->name;
00476 _archIfSimple = rd->evr;
00477 }
00478 else if ( rd->flags == CAP_ARCH )
00479 {
00480 _kind = NAMED;
00481
00482 _lhs = rd->name;
00483 _archIfSimple = rd->evr;
00484 }
00485 else
00486 {
00487 _kind = EXPRESSION;
00488 return;
00489 }
00490
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
00501
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;
00559 case CapDetail::CAP_OR: return str << "|"; break;
00560 case CapDetail::CAP_WITH: return str << "+"; break;
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 }