ResolvableImpl.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 #include "zypp/base/Logger.h"
00014 
00015 #include "zypp/ZYpp.h"
00016 #include "zypp/ZYppFactory.h"
00017 
00018 #include "zypp/base/Algorithm.h"
00019 #include "zypp/detail/ResolvableImpl.h"
00020 #include "zypp/capability/CapabilityImpl.h"
00021 #include "zypp/capability/Capabilities.h"
00022 
00023 using std::endl;
00024 
00026 namespace zypp
00027 { 
00028 
00029   namespace
00030   {
00031     struct FilterUnwantedReq
00032     {
00033       bool operator()( const Capability & cap_r ) const
00034       {
00035         return cap_r.index().substr( 0, 7 ) == "rpmlib(";
00036       }
00037     };
00038 
00039     void filterUnwantedReq( const CapSet & from, CapSet & to )
00040     {
00041       to.clear();
00042       std::remove_copy_if( from.begin(), from.end(),
00043                            std::inserter( to, to.end() ),
00044                            FilterUnwantedReq() );
00045     }
00046   }
00047 
00048   namespace
00049   {
00050     struct FilterExtraDependency
00051     {
00052       Dependencies & deps;
00053 
00054       FilterExtraDependency( Dependencies & d )
00055         : deps( d )
00056       { }
00057 
00058       bool operator()( const Capability & cap_r ) const
00059       {
00060         if ( isKind<capability::ModaliasCap>(cap_r) )
00061           {
00062             // in case cap provides a packagename, inject a SUPPLEMENTS.
00063             // if modalias does not provide a packagename, default to "kernel" (#184840)
00064 
00065             intrusive_ptr<const capability::ModaliasCap> cap( capability::asKind<capability::ModaliasCap>(cap_r) );
00066             if ( cap ) {
00067               std::string pkgname( cap->pkgname() );
00068               if ( pkgname.empty() ) {
00069                 pkgname = "kernel";             // every kernel provides "kernel", so this triggers always
00070               }
00071               deps[Dep::SUPPLEMENTS].insert( CapFactory().parse( ResTraits<Package>::kind, pkgname ) );
00072               deps[Dep::FRESHENS].insert(cap_r);
00073             }
00074             return true;        // strip from original deps, we just splitted it to supplements/freshens
00075           }
00076 
00077         if ( isKind<capability::HalCap>(cap_r) )
00078           {
00079             deps[Dep::SUPPLEMENTS].insert( cap_r );
00080             return true;        // strip from provides
00081           }
00082 
00083         if (cap_r.index().substr( 0, 7 ) != "locale(")
00084             return false;
00085 
00086         CapFactory f;
00087 
00088         std::string locales( cap_r.index(), 7 );                        // strip "locale("
00089         std::string::size_type pos = locales.find( ":" );               // colon given ?
00090         if (pos != std::string::npos) {
00091             deps[Dep::SUPPLEMENTS].insert( f.parse( ResTraits<Package>::kind, std::string( locales, 0, pos ) ) );
00092             locales.erase( 0, pos+1 );
00093         }
00094         pos = 0;
00095         std::string::size_type next = pos;
00096         while (pos < locales.size()) {
00097             next = locales.find( ";", pos );                    // look for ; separator
00098             if (next == std::string::npos)
00099                 next = locales.size()-1;                        // none left, set next to end-1 (strip trailing ')' )
00100 
00101             std::string loc( locales, pos, next-pos );
00102             getZYpp()->availableLocale( Locale( loc ) );
00103             deps[Dep::FRESHENS].insert( f.parse( ResTraits<Language>::kind, loc ) );
00104             pos = next + 1;
00105         }
00106         return true;
00107       }
00108     };
00109 
00110     void filterExtraProvides( const Dependencies & from, Dependencies & to )
00111     {
00112       CapSet provides;
00113       FilterExtraDependency flp( to );
00114 
00115       std::remove_copy_if( from[Dep::PROVIDES].begin(), from[Dep::PROVIDES].end(),
00116                            std::inserter( provides, provides.end() ),
00117                            flp );
00118       to[Dep::PROVIDES] = provides;
00119     }
00120 
00121     void filterExtraSupplements( const Dependencies & from, Dependencies & to )
00122     {
00123       CapSet supplements;
00124       to[Dep::SUPPLEMENTS].clear();
00125 
00126       FilterExtraDependency flp( to );
00127 
00128       std::remove_copy_if( from[Dep::SUPPLEMENTS].begin(), from[Dep::SUPPLEMENTS].end(),
00129                            std::inserter( supplements, supplements.end() ),
00130                            flp );
00131       to[Dep::SUPPLEMENTS].insert(supplements.begin(), supplements.end());
00132     }
00133   }
00134 
00136   //
00137   //    METHOD NAME : Resolvable::Impl::Impl
00138   //    METHOD TYPE : Ctor
00139   //
00140   Resolvable::Impl::Impl( const Kind & kind_r,
00141                           const NVRAD & nvrad_r )
00142   : _kind( kind_r )
00143   , _name( nvrad_r.name )
00144   , _edition( nvrad_r.edition )
00145   , _arch( nvrad_r.arch )
00146   , _deps( nvrad_r )
00147   {
00148     // check if we provide/supplements any extra ('locale(...)', 'modalias(...)', ...) tags
00149     // and split them up to freshens/supplements (except for SystemResObject)
00150     if ( _kind != ResTraits<SystemResObject>::kind )
00151       {
00152         filterExtraSupplements( nvrad_r, _deps );
00153         filterExtraProvides( nvrad_r, _deps );
00154       }
00155 
00156     // remove malicious self provides
00157     CapSet::iterator it = _deps[Dep::PROVIDES].find( CapFactory().parse( _kind, _name ) );
00158       if ( it != _deps[Dep::PROVIDES].end() )
00159         {
00160           dumpOn( WAR << "Strip self provides without edition in " ) << endl;
00161           _deps[Dep::PROVIDES].erase( it );
00162         }
00163 
00164     // assert self provides
00165     _deps[Dep::PROVIDES].insert( CapFactory()
00166                                  .parse( _kind, _name, Rel::EQ, _edition ) );
00167 
00168     // Filter 'rpmlib(...)' requirements (refill from nvrad_r)
00169     filterUnwantedReq( nvrad_r[Dep::PREREQUIRES], _deps[Dep::PREREQUIRES] );
00170     filterUnwantedReq( nvrad_r[Dep::REQUIRES], _deps[Dep::REQUIRES] );
00171 
00172     // assert all prerequires are in requires too
00173     _deps[Dep::REQUIRES].insert( _deps[Dep::PREREQUIRES].begin(),
00174                                  _deps[Dep::PREREQUIRES].end() );
00175 
00176 
00177     if ( _arch.empty() )
00178       dumpOn( WAR << "Has empty Arch: " ) << std::endl;
00179   }
00180 
00181   std::ostream & Resolvable::Impl::dumpOn( std::ostream & str ) const
00182   {
00183     return str << '[' << kind() << ']'
00184                << name() << '-' << edition() << '.' << arch();
00185   }
00186 
00188 } // namespace zypp

Generated on Thu Jul 6 00:07:20 2006 for zypp by  doxygen 1.4.6