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
00057 FilterExtraDependency( Dependencies & d )
00058 : deps( d )
00059 { }
00060
00061 bool operator()( const Capability & cap_r ) const
00062 {
00063 if ( isKind<capability::ModaliasCap>(cap_r) )
00064 {
00065
00066
00067
00068 intrusive_ptr<const capability::ModaliasCap> cap( capability::asKind<capability::ModaliasCap>(cap_r) );
00069 if ( cap ) {
00070 std::string pkgname( cap->pkgname() );
00071 if ( pkgname.empty() ) {
00072 pkgname = "kernel";
00073 }
00074 deps[Dep::SUPPLEMENTS].insert( CapFactory().parse( ResTraits<Package>::kind, pkgname ) );
00075 deps[Dep::FRESHENS].insert(cap_r);
00076 }
00077 return true;
00078 }
00079
00080 if ( isKind<capability::HalCap>(cap_r) )
00081 {
00082 deps[Dep::SUPPLEMENTS].insert( cap_r );
00083 return true;
00084 }
00085
00086 if (cap_r.index().substr( 0, 7 ) != "locale(")
00087 return false;
00088
00089 CapFactory f;
00090
00091 std::string locales( cap_r.index(), 7 );
00092 std::string::size_type pos = locales.find( ":" );
00093 if (pos != std::string::npos) {
00094 deps[Dep::SUPPLEMENTS].insert( f.parse( ResTraits<Package>::kind, std::string( locales, 0, pos ) ) );
00095 locales.erase( 0, pos+1 );
00096 }
00097 pos = 0;
00098 std::string::size_type next = pos;
00099 while (pos < locales.size()) {
00100 next = locales.find( ";", pos );
00101 if (next == std::string::npos)
00102 next = locales.size()-1;
00103
00104 std::string loc( locales, pos, next-pos );
00105 getZYpp()->availableLocale( Locale( loc ) );
00106 deps[Dep::FRESHENS].insert( f.parse( ResTraits<Language>::kind, loc ) );
00107 pos = next + 1;
00108 }
00109 return true;
00110 }
00111 };
00112
00113 void filterExtraProvides( const Dependencies & from, Dependencies & to )
00114 {
00115 CapSet provides;
00116 FilterExtraDependency flp( to );
00117
00118 std::remove_copy_if( from[Dep::PROVIDES].begin(), from[Dep::PROVIDES].end(),
00119 std::inserter( provides, provides.end() ),
00120 flp );
00121 to[Dep::PROVIDES] = provides;
00122 }
00123
00124 void filterExtraSupplements( const Dependencies & from, Dependencies & to )
00125 {
00126 CapSet supplements;
00127 to[Dep::SUPPLEMENTS].clear();
00128
00129 FilterExtraDependency flp( to );
00130
00131 std::remove_copy_if( from[Dep::SUPPLEMENTS].begin(), from[Dep::SUPPLEMENTS].end(),
00132 std::inserter( supplements, supplements.end() ),
00133 flp );
00134 to[Dep::SUPPLEMENTS].insert(supplements.begin(), supplements.end());
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 std::string findKernelFlavor( const CapSet & cset, const Dep & dep )
00149 {
00150 for (CapSet::iterator it = cset.begin(); it != cset.end(); ++it) {
00151
00152
00153
00154
00155
00156
00157
00158 if ( it->index().substr( 0, 7 ) == "kernel-"
00159 && (dep == Dep::REQUIRES
00160 || it->edition() != Edition::noedition ) )
00161 {
00162 return it->index().erase( 0, 7 );
00163 }
00164 }
00165 return "";
00166 }
00167
00168 void rewriteKernelDeps( Dependencies & deps )
00169 {
00170
00171 Dep dep = Dep::REQUIRES;
00172 CapSet cset = deps[dep];
00173 std::string flavor( findKernelFlavor( cset, dep ) );
00174 if (flavor.empty()) {
00175 dep = Dep::PROVIDES;
00176 cset = deps[dep];
00177 flavor = findKernelFlavor( cset, dep );
00178 }
00179
00180 if (flavor.empty())
00181 return;
00182
00183
00184
00185
00186
00187 flavor.append( ":" );
00188 CapFactory factory;
00189 deps[dep].clear();
00190 for (CapSet::iterator it = cset.begin(); it != cset.end(); ++it) {
00191 std::string idx( it->index() );
00192 if ( idx.substr( 0, 7 ) == "kernel("
00193 && idx.find( ":" ) == std::string::npos )
00194 {
00195 deps[dep].insert( factory.parse( it->refers(), idx.insert( 7, flavor ), it->op(), it->edition() ) );
00196 }
00197 else {
00198 deps[dep].insert( *it );
00199 }
00200 }
00201 return;
00202 }
00203
00204 }
00205
00207
00208
00209
00210
00211 Resolvable::Impl::Impl( const Kind & kind_r,
00212 const NVRAD & nvrad_r )
00213 : _kind( kind_r )
00214 , _name( nvrad_r.name )
00215 , _edition( nvrad_r.edition )
00216 , _arch( nvrad_r.arch )
00217 , _deps( nvrad_r )
00218 {
00219
00220
00221 if ( _kind != ResTraits<SystemResObject>::kind )
00222 {
00223 filterExtraSupplements( nvrad_r, _deps );
00224 filterExtraProvides( nvrad_r, _deps );
00225 }
00226
00227
00228 CapSet::iterator it = _deps[Dep::PROVIDES].find( CapFactory().parse( _kind, _name ) );
00229 if ( it != _deps[Dep::PROVIDES].end() )
00230 {
00231 dumpOn( WAR << "Strip self provides without edition in " ) << endl;
00232 _deps[Dep::PROVIDES].erase( it );
00233 }
00234
00235
00236 _deps[Dep::PROVIDES].insert( CapFactory()
00237 .parse( _kind, _name, Rel::EQ, _edition ) );
00238
00239
00240 filterUnwantedReq( nvrad_r[Dep::PREREQUIRES], _deps[Dep::PREREQUIRES] );
00241 filterUnwantedReq( nvrad_r[Dep::REQUIRES], _deps[Dep::REQUIRES] );
00242
00243
00244 if ( _kind == ResTraits<Package>::kind )
00245 {
00246 rewriteKernelDeps( _deps );
00247 }
00248
00249
00250 _deps[Dep::REQUIRES].insert( _deps[Dep::PREREQUIRES].begin(),
00251 _deps[Dep::PREREQUIRES].end() );
00252
00253 if ( _arch.empty() )
00254 dumpOn( WAR << "Has empty Arch: " ) << std::endl;
00255 }
00256
00257 std::ostream & Resolvable::Impl::dumpOn( std::ostream & str ) const
00258 {
00259 return str << '[' << kind() << ']'
00260 << name() << '-' << edition() << '.' << arch();
00261 }
00262
00264 }