00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <string>
00014 #include <map>
00015 #include "zypp/base/Logger.h"
00016
00017 #include "zypp/ZYpp.h"
00018 #include "zypp/ZYppFactory.h"
00019
00020 #include "zypp/base/Algorithm.h"
00021 #include "zypp/base/Sysconfig.h"
00022 #include "zypp/detail/ResolvableImpl.h"
00023 #include "zypp/capability/CapabilityImpl.h"
00024 #include "zypp/capability/Capabilities.h"
00025
00026 using std::endl;
00027
00029 namespace zypp
00030 {
00031
00032 namespace
00033 {
00034 struct FilterUnwantedReq
00035 {
00036 bool operator()( const Capability & cap_r ) const
00037 {
00038 return cap_r.index().substr( 0, 7 ) == "rpmlib(";
00039 }
00040 };
00041
00042 void filterUnwantedReq( const CapSet & from, CapSet & to )
00043 {
00044 to.clear();
00045 std::remove_copy_if( from.begin(), from.end(),
00046 std::inserter( to, to.end() ),
00047 FilterUnwantedReq() );
00048 }
00049 }
00050
00051 namespace
00052 {
00053 struct FilterExtraDependency
00054 {
00055 Dependencies & deps;
00056 CapSet & languages;
00057
00058 FilterExtraDependency( Dependencies & d , CapSet & l)
00059 : deps( d ),
00060 languages( l )
00061 { }
00062
00063 bool operator()( const Capability & cap_r ) const
00064 {
00065 if ( isKind<capability::ModaliasCap>(cap_r) )
00066 {
00067
00068
00069
00070 capability::ModaliasCap::constPtr cap( capability::asKind<capability::ModaliasCap>(cap_r) );
00071 if ( cap ) {
00072 std::string pkgname( cap->pkgname() );
00073 if ( pkgname.empty() ) {
00074 pkgname = "kernel";
00075 }
00076 deps[Dep::SUPPLEMENTS].insert( CapFactory().parse( ResTraits<Package>::kind, pkgname ) );
00077 deps[Dep::FRESHENS].insert(cap_r);
00078 }
00079 return true;
00080 }
00081
00082 if ( isKind<capability::HalCap>(cap_r) )
00083 {
00084 deps[Dep::SUPPLEMENTS].insert( cap_r );
00085 return true;
00086 }
00087
00088 std::string capString = cap_r.index();
00089
00090 if (capString.substr( 0, 11 ) == "packageand(") {
00091
00092
00093
00094 if (capString[capString.size()-1] == ')') {
00095 CapFactory f;
00096 std::string andDep( capString, 11 );
00097 std::string::size_type pos = andDep.find( ":" );
00098 if (pos != std::string::npos) {
00099 deps[Dep::SUPPLEMENTS].insert( f.parse( ResTraits<Package>::kind, std::string( andDep, 0, pos ) ) );
00100 pos++;
00101 std::string depString( andDep, pos, andDep.size()-pos-1 );
00102 deps[Dep::FRESHENS].insert( f.parse( ResTraits<Package>::kind, depString ) );
00103 } else {
00104 ERR << "wrong dependency (missing \":\") : " << capString <<endl;
00105 }
00106 } else {
00107 ERR << "wrong dependency (missing \")\"): " << capString <<endl;
00108 }
00109 return true;
00110 }
00111
00112 if (capString.substr( 0, 7 ) != "locale(")
00113 return false;
00114
00115 CapFactory f;
00116
00117 std::string locales( capString, 7 );
00118 std::string::size_type pos = locales.find( ":" );
00119 if (pos != std::string::npos) {
00120 deps[Dep::SUPPLEMENTS].insert( f.parse( ResTraits<Package>::kind, std::string( locales, 0, pos ) ) );
00121 locales.erase( 0, pos+1 );
00122 }
00123 pos = 0;
00124 std::string::size_type next = pos;
00125 while (pos < locales.size()) {
00126 next = locales.find( ";", pos );
00127 if (next == std::string::npos)
00128 next = locales.size()-1;
00129
00130 std::string loc( locales, pos, next-pos );
00131 getZYpp()->availableLocale( Locale( loc ) );
00132 deps[Dep::FRESHENS].insert( f.parse( ResTraits<Language>::kind, loc ) );
00133 languages.insert( f.parse( ResTraits<Language>::kind, loc ) );
00134 pos = next + 1;
00135 }
00136 return true;
00137 }
00138 };
00139
00140 void filterExtraProvides( const Dependencies & from, Dependencies & to )
00141 {
00142
00143 CapSet provides;
00144 CapSet languages;
00145
00146 FilterExtraDependency flp( to, languages );
00147
00148 std::remove_copy_if( from[Dep::PROVIDES].begin(), from[Dep::PROVIDES].end(),
00149 std::inserter( provides, provides.end() ),
00150 flp );
00151 to[Dep::PROVIDES] = provides;
00152
00153
00154
00155
00156 if (languages.size() > 0
00157 && to[Dep::SUPPLEMENTS].size() == 0) {
00158 to[Dep::SUPPLEMENTS] = languages;
00159 }
00160 }
00161
00162 void filterExtraSupplements( const Dependencies & from, Dependencies & to )
00163 {
00164
00165 CapSet supplements;
00166 CapSet dummy;
00167 to[Dep::SUPPLEMENTS].clear();
00168
00169 FilterExtraDependency flp( to, dummy );
00170
00171 std::remove_copy_if( from[Dep::SUPPLEMENTS].begin(), from[Dep::SUPPLEMENTS].end(),
00172 std::inserter( supplements, supplements.end() ),
00173 flp );
00174 to[Dep::SUPPLEMENTS].insert(supplements.begin(), supplements.end());
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 std::string findKernelFlavor( const CapSet & cset, const Dep & dep )
00189 {
00190 for ( CapSet::iterator it = cset.begin(); it != cset.end(); ++it )
00191 {
00192
00193
00194
00195
00196
00197 capability::NamedCap::constPtr cap = capability::asKind<capability::NamedCap>(*it);
00198 if ( cap
00199 && cap->name().substr( 0, 7 ) == "kernel-"
00200 && ( dep == Dep::REQUIRES || cap->edition() != Edition::noedition ) )
00201 {
00202 std::string s( cap->name() );
00203 return s.erase(0,7);
00204 }
00205 }
00206 return "";
00207 }
00208
00209 void rewriteKernelDeps( Dependencies & deps )
00210 {
00211
00212 Dep dep = Dep::REQUIRES;
00213 CapSet cset = deps[dep];
00214 std::string flavor( findKernelFlavor( cset, dep ) );
00215 if (flavor.empty()) {
00216 dep = Dep::PROVIDES;
00217 cset = deps[dep];
00218 flavor = findKernelFlavor( cset, dep );
00219 }
00220
00221 if (flavor.empty())
00222 return;
00223
00224
00225
00226
00227
00228 flavor.append( ":" );
00229 CapFactory factory;
00230 deps[dep].clear();
00231 for (CapSet::const_iterator it = cset.begin(); it != cset.end(); ++it) {
00232 std::string idx( it->index() );
00233 if ( idx.substr( 0, 7 ) == "kernel("
00234 && idx.find( ":" ) == std::string::npos )
00235 {
00236 capability::VersionedCap::constPtr vercap = capability::asKind<capability::VersionedCap>(*it);
00237 if ( vercap )
00238 deps[dep].insert( factory.parse( vercap->refers(), idx.insert( 7, flavor ), vercap->op(), vercap->edition() ) );
00239 }
00240 else {
00241 deps[dep].insert( *it );
00242 }
00243 }
00244 return;
00245 }
00246
00247 }
00248
00250
00251
00252
00253
00254 Resolvable::Impl::Impl( const Kind & kind_r,
00255 const NVRAD & nvrad_r )
00256 : _kind( kind_r )
00257 , _name( nvrad_r.name )
00258 , _edition( nvrad_r.edition )
00259 , _arch( nvrad_r.arch )
00260 , _deps( nvrad_r )
00261 {
00262
00263
00264 if ( _kind != ResTraits<SystemResObject>::kind )
00265 {
00266 filterExtraSupplements( nvrad_r, _deps );
00267 filterExtraProvides( nvrad_r, _deps );
00268 }
00269
00270
00271 CapSet::iterator it = _deps[Dep::PROVIDES].find( CapFactory().parse( _kind, _name ) );
00272 if ( it != _deps[Dep::PROVIDES].end() )
00273 {
00274 dumpOn( WAR << "Strip self provides without edition in " ) << endl;
00275 _deps[Dep::PROVIDES].erase( it );
00276 }
00277
00278
00279 _deps[Dep::PROVIDES].insert( CapFactory()
00280 .parse( _kind, _name, Rel::EQ, _edition ) );
00281
00282
00283 filterUnwantedReq( nvrad_r[Dep::PREREQUIRES], _deps[Dep::PREREQUIRES] );
00284 filterUnwantedReq( nvrad_r[Dep::REQUIRES], _deps[Dep::REQUIRES] );
00285
00286
00287 if ( _kind == ResTraits<Package>::kind )
00288 {
00289 rewriteKernelDeps( _deps );
00290 }
00291
00292
00293 _deps[Dep::REQUIRES].insert( _deps[Dep::PREREQUIRES].begin(),
00294 _deps[Dep::PREREQUIRES].end() );
00295
00296 if ( _arch.empty() )
00297 dumpOn( WAR << "Has empty Arch: " ) << std::endl;
00298 }
00299
00300 std::ostream & Resolvable::Impl::dumpOn( std::ostream & str ) const
00301 {
00302 return str << '[' << kind() << ']'
00303 << name() << '-' << edition() << '.' << arch();
00304 }
00305
00307 }