ResolvableImpl.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
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             // in case cap provides a packagename, inject a SUPPLEMENTS.
00066             // if modalias does not provide a packagename, default to "kernel" (#184840)
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";             // every kernel provides "kernel", so this triggers always
00073               }
00074               deps[Dep::SUPPLEMENTS].insert( CapFactory().parse( ResTraits<Package>::kind, pkgname ) );
00075               deps[Dep::FRESHENS].insert(cap_r);
00076             }
00077             return true;        // strip from original deps, we just splitted it to supplements/freshens
00078           }
00079 
00080         if ( isKind<capability::HalCap>(cap_r) )
00081           {
00082             deps[Dep::SUPPLEMENTS].insert( cap_r );
00083             return true;        // strip from provides
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 );                        // strip "locale("
00092         std::string::size_type pos = locales.find( ":" );               // colon given ?
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 );                    // look for ; separator
00101             if (next == std::string::npos)
00102                 next = locales.size()-1;                        // none left, set next to end-1 (strip trailing ')' )
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     // rewrite dependencies from
00138     //   kernel(xxx) = yyy
00139     // to
00140     //   kernel($FLAVOR:xxx) = yyy
00141     // $flavor is determined by searching through
00142     //   PROVIDES (for kernel-$flavor, by kernel package)
00143     // or
00144     //   REQUIRES (for kernel-$flavor, by kmp package)
00145     // see bugzilla #190163
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         // check for "kernel-" in deps
00153         // if its a requires, take it as is
00154         // if its a provides, check for non-empty edition since
00155         //   kernels provide "kernel-flavor-nongpl" (empty edition)
00156         //     and "kernel-flavor = x.y" (non-empty edition)
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 );     // erase "kernel-"
00163         }
00164       }
00165       return "";
00166     }
00167 
00168     void rewriteKernelDeps( Dependencies & deps )
00169     {
00170       // check the smaller set (requires) first
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())               // not a kernel / kmp package
00181         return;
00182 
00183       // flavor == kernel flavor
00184       // cset == CapSet to be rewritten (provides for kernel, requires for kmp)
00185       // dep == deps to be set in 'to'
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("            // capability is "kernel(..."
00193              && idx.find( ":" ) == std::string::npos )  //  without a colon
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   //    METHOD NAME : Resolvable::Impl::Impl
00209   //    METHOD TYPE : Ctor
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     // check if we provide/supplements any extra ('locale(...)', 'modalias(...)', ...) tags
00220     //  and split them up to freshens/supplements (except for SystemResObject)
00221     if ( _kind != ResTraits<SystemResObject>::kind )
00222       {
00223         filterExtraSupplements( nvrad_r, _deps );
00224         filterExtraProvides( nvrad_r, _deps );
00225       }
00226 
00227     // remove malicious self provides
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     // assert self provides
00236     _deps[Dep::PROVIDES].insert( CapFactory()
00237                                  .parse( _kind, _name, Rel::EQ, _edition ) );
00238 
00239     // Filter 'rpmlib(...)' requirements (refill from nvrad_r)
00240     filterUnwantedReq( nvrad_r[Dep::PREREQUIRES], _deps[Dep::PREREQUIRES] );
00241     filterUnwantedReq( nvrad_r[Dep::REQUIRES], _deps[Dep::REQUIRES] );
00242 
00243     // check for kernel(xxx) and rewrite them to kernel(flavor:xxx)
00244     if ( _kind == ResTraits<Package>::kind )
00245       {
00246         rewriteKernelDeps( _deps );   
00247       }
00248 
00249     // assert all prerequires are in requires too
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 } // namespace zypp

Generated on Wed Sep 27 01:16:30 2006 for zypp by  doxygen 1.4.6