YUMSourceImpl.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00013 #include "zypp/source/yum/YUMSourceImpl.h"
00014 #include "zypp/source/yum/YUMAtomImpl.h"
00015 #include "zypp/source/yum/YUMPackageImpl.h"
00016 #include "zypp/source/yum/YUMScriptImpl.h"
00017 #include "zypp/source/yum/YUMMessageImpl.h"
00018 #include "zypp/source/yum/YUMPatchImpl.h"
00019 #include "zypp/source/yum/YUMProductImpl.h"
00020 #include "zypp/source/yum/YUMGroupImpl.h"
00021 #include "zypp/source/yum/YUMPatternImpl.h"
00022 
00023 #include "zypp/NVRA.h"
00024 #include "zypp/PathInfo.h"
00025 #include "zypp/base/Logger.h"
00026 #include "zypp/base/Exception.h"
00027 #include "zypp/CapFactory.h"
00028 #include "zypp/Digest.h"
00029 #include "zypp/ExternalProgram.h"
00030 #include "zypp/TmpPath.h"
00031 #include "zypp/ZYppFactory.h"
00032 #include "zypp/KeyRing.h"
00033 
00034 #include "zypp/parser/yum/YUMParser.h"
00035 #include "zypp/SourceFactory.h"
00036 #include "zypp/ZYppCallbacks.h"
00037 #include "zypp/SilentCallbacks.h"
00038 
00039 #include "zypp/base/GzStream.h"
00040 #include "zypp/base/Gettext.h"
00041 #include "zypp/PathInfo.h"
00042 
00043 #include <fstream>
00044 
00045 using namespace std;
00046 using namespace zypp::detail;
00047 using namespace zypp::parser::yum;
00048 
00050 namespace zypp
00051 { 
00052 
00053 namespace source
00054 { 
00055 namespace yum
00056 {
00057 
00058 bool YUMProber::operator()()
00059 {
00060   MIL << "Probing for YUM source..." << std::endl;
00061   bool result = false;
00062   media::MediaManager mm;
00063   result = mm.doesFileExist(_media_id, _path + Pathname("/repodata/repomd.xml"));
00064   if ( result )
00065   {
00066     MIL << "YUM source detected..." << std::endl;
00067     return true;
00068   }
00069 
00070   MIL << "Not a YUM source..." << std::endl;
00071   return false;
00072 }
00073 
00074 struct YUMSourceEventHandler
00075 {
00076   YUMSourceEventHandler( callback::SendReport<SourceReport> &report ) : _report(report)
00077   {}
00078 
00079   void operator()( int p )
00080   {
00081     _report->progress(p);
00082   }
00083 
00084   callback::SendReport<SourceReport> &_report;
00085 };
00086 
00087 static long int get_stream_size( const Pathname &p )
00088 {
00089   ifgzstream input( p.asString().c_str() );
00090 
00091   if ( input.bad() )
00092     ZYPP_THROW(Exception("Can't read " + p.asString() + " to calculate compressed stream size"));
00093 
00094   // get the size of the stream
00095   DBG << "Getting size of the stream." << std::endl;
00096   input.seekg (0, ios::end);
00097   long int stream_size = input.tellg();
00098   DBG << "XML stream size: " << stream_size << std::endl;
00099   return stream_size;
00100 }
00101 
00103 //
00104 //        CLASS NAME : YUMSourceImpl
00105 //
00107 
00108 YUMSourceImpl::YUMSourceImpl()
00109 {}
00110 
00111 Date YUMSourceImpl::timestamp() const
00112 {
00113   return PathInfo(repomdFile()).mtime();
00114 }
00115 
00116 bool YUMSourceImpl::cacheExists()
00117 {
00118   bool exists = PathInfo(repomdFile()).isExist();
00119   if (exists)
00120     MIL << "YUM cache found at " << _cache_dir << std::endl;
00121   else
00122     MIL << "YUM cache not found" << std::endl;
00123 
00124   return exists;
00125 }
00126 
00127 const Pathname YUMSourceImpl::metadataRoot() const
00128 {
00129   return _cache_dir.empty() ? tmpMetadataDir() : _cache_dir;
00130 }
00131 
00132 const Pathname YUMSourceImpl::repomdFile() const
00133 {
00134   return metadataRoot() + "/repodata/repomd.xml";
00135 }
00136 
00137 const Pathname YUMSourceImpl::repomdFileSignature() const
00138 {
00139   return metadataRoot() + "/repodata/repomd.xml.asc";
00140 }
00141 
00142 const Pathname YUMSourceImpl::repomdFileKey() const
00143 {
00144   return metadataRoot() + "/repodata/repomd.xml.key";
00145 }
00146 
00147 const TmpDir YUMSourceImpl::downloadMetadata()
00148 {
00149   TmpDir tmpdir;
00150   int copy_result;
00151   MIL << "Downloading metadata to " << tmpdir.path() << std::endl;
00152 
00153   Pathname local_dir = tmpdir.path();
00154   if (0 != assert_dir(local_dir + "/repodata" , 0755))
00155     ZYPP_THROW(Exception("Cannot create /repodata in download directory"));
00156 
00157   MIL << "Storing data to tmp dir " << local_dir << endl;
00158 
00159   // first read list of all files in the repository
00160   Pathname remote_repomd;
00161   try
00162   {
00163     remote_repomd = provideFile(_path + "/repodata/repomd.xml");
00164   }
00165   catch (Exception &e)
00166   {
00167     ZYPP_CAUGHT(e);
00168     ZYPP_THROW(SourceIOException("Can't provide " + _path.asString() + "/repodata/repomd.xml from " + url().asString() ));
00169   }
00170 
00171   // provide optional files
00172   Pathname remote_repomd_key;
00173   Pathname remote_repomd_signature;
00174   try
00175   {
00176     remote_repomd_key = tryToProvideFile( _path + "/repodata/repomd.xml.key");
00177   }
00178   catch ( const Exception &e )
00179   {
00180     WAR << "Repository does not contain repomd signing key" << std::endl;
00181   }
00182 
00183   try
00184   {
00185     remote_repomd_signature = tryToProvideFile( _path + "/repodata/repomd.xml.asc");
00186   }
00187   catch ( const Exception &e )
00188   {
00189     WAR << "Repository does not contain repomd signature" << std::endl;
00190   }
00191 
00192   copy_result = filesystem::copy( remote_repomd, local_dir + "/repodata/repomd.xml");
00193   if ( copy_result != 0 )
00194     ZYPP_THROW(SourceIOException("Can't copy " + remote_repomd.asString() + " to " + local_dir.asString() + "/repodata/repomd.xml"));
00195 
00196   if (PathInfo(remote_repomd_key).isExist())
00197   {
00198     copy_result = filesystem::copy( remote_repomd_key, local_dir + "/repodata/repomd.xml.key");
00199     if ( copy_result != 0 )
00200       ZYPP_THROW(SourceIOException("Can't copy " + remote_repomd_key.asString() + " to " + local_dir.asString() + "/repodata/repomd.xml.key"));
00201 
00202     getZYpp()->keyRing()->importKey(local_dir + "/repodata/repomd.xml.key" , false);
00203   }
00204 
00205   if (PathInfo(remote_repomd_signature).isExist())
00206   {
00207     copy_result = filesystem::copy( remote_repomd_signature, local_dir + "/repodata/repomd.xml.asc");
00208     if ( copy_result != 0 )
00209       ZYPP_THROW(SourceIOException("Can't copy " + remote_repomd_signature.asString() + " to " + local_dir.asString() + "/repodata/repomd.xml.asc"));
00210   }
00211 
00212   DBG << "Reading file " << remote_repomd << endl;
00213   ifstream repo_st(remote_repomd.asString().c_str());
00214 
00215   callback::SendReport<SourceReport> report;
00216   report->start( selfSourceRef(), _("Reading index files") );
00217   YUMRepomdParser repomd(repo_st, "");
00218 
00219 
00220   for (; ! repomd.atEnd(); ++repomd)
00221   {
00222     if ((*repomd)->type == "other")     // don't parse 'other.xml' (#159316)
00223       continue;
00224 
00225     getPossiblyCachedMetadataFile( _path + (*repomd)->location, local_dir + (*repomd)->location, _cache_dir + (*repomd)->location, CheckSum((*repomd)->checksumType, (*repomd)->checksum) );
00226 
00227     // if it is a patch, we read the patches individually
00228     if ((*repomd)->type == "patches")
00229     {
00230       // use the local copy now
00231       Pathname patches_list = local_dir + (*repomd)->location;
00232       MIL << "Reading patches file " << patches_list << std::endl;
00233       ifgzstream st ( patches_list.asString().c_str() );
00234       YUMPatchesParser patch(st, "");
00235       for (; !patch.atEnd(); ++patch)
00236       {
00237         getPossiblyCachedMetadataFile( _path + (*patch)->location, local_dir + (*patch)->location, _cache_dir + (*patch)->location, CheckSum((*patch)->checksumType, (*patch)->checksum) );
00238       } // end of single patch parsing
00239     }// end of patches file parsing
00240   } // end of copying
00241   report->finish( selfSourceRef(), _("Reading index files"), source::SourceReport::NO_ERROR, "" );
00242 
00243 
00244   // check signature
00245   MIL << "Checking [" << (local_dir + "/repodata/repomd.xml") << "] signature"  << endl;
00246   if (! getZYpp()->keyRing()->verifyFileSignatureWorkflow(local_dir + "/repodata/repomd.xml", (_path + "/repodata/repomd.xml").asString()+ " (" + url().asString() + ")", local_dir + "/repodata/repomd.xml.asc"))
00247     ZYPP_THROW(SourceMetadataException(N_("Signed repomd.xml file fails signature check")));
00248 
00249   // ok, now we have a consistent repo in the tmpdir.
00250   return tmpdir;
00251 }
00252 
00253 void YUMSourceImpl::factoryInit()
00254 {
00255   resetMediaVerifier();
00256 
00257   bool cache = cacheExists();
00258   if ( cache )
00259   {
00260     DBG << "Cached metadata found in [" << _cache_dir << "]." << endl;
00261     if ( autorefresh() )
00262       storeMetadata(_cache_dir);
00263     else
00264       readRepomd();
00265   }
00266   else
00267   {
00268     if ( _cache_dir.empty() || !PathInfo(_cache_dir).isExist() )
00269     {
00270       DBG << "Cache dir not set. Downloading to temp dir: " << tmpMetadataDir() << std::endl;
00271       // as we have no local dir set we use a tmp one, but we use a member variable because
00272       // it cant go out of scope while the source exists.
00273       saveMetadataTo(tmpMetadataDir());
00274     }
00275     else
00276     {
00277       DBG << "Cached metadata not found in [" << _cache_dir << "]. Will download." << std::endl;
00278       saveMetadataTo(_cache_dir);
00279     }
00280     readRepomd();
00281   }
00282 
00283   MIL << "YUM source initialized." << std::endl;
00284   MIL << "   Url      : " << url() << std::endl;
00285   MIL << "   Alias    : " << alias() << std::endl;
00286   MIL << "   Path     : " << path() << std::endl;
00287   MIL << "   Metadata : " << metadataRoot() << (_cache_dir.empty() ? " [TMP]" : " [CACHE]") << std::endl;
00288 }
00289 
00290 bool YUMSourceImpl::downloadNeeded(const Pathname & localdir)
00291 {
00292   // we can only assume repomd intact means the source changed if the source is signed.
00293   if ( cacheExists() && PathInfo( repomdFileSignature() ).isExist() )
00294   {
00295     Pathname remote_repomd;
00296     try
00297     {
00298       remote_repomd = provideFile(_path + "/repodata/repomd.xml");
00299     }
00300     catch (Exception &e)
00301     {
00302       ZYPP_THROW(Exception("Can't provide " + _path.asString() + "/repodata/repomd.xml from " + url().asString() ));
00303     }
00304 
00305     CheckSum old_repomd_checksum( "SHA1", filesystem::sha1sum(localdir + "/repodata/repomd.xml"));
00306     CheckSum new_repomd_checksum( "SHA1", filesystem::sha1sum(remote_repomd));
00307     if ( (new_repomd_checksum == old_repomd_checksum) && (!new_repomd_checksum.empty()) && (! old_repomd_checksum.empty()))
00308     {
00309       return false;
00310     }
00311   }
00312   return true;
00313 }
00314 
00315 void YUMSourceImpl::storeMetadata(const Pathname & cache_dir_r)
00316 {
00317   if ( !_cache_dir.empty() )
00318   {
00319     saveMetadataTo(cache_dir_r);
00320   }
00321   else
00322   {
00323     // no previous cache, use the data read temporarely
00324     copyLocalMetadata(tmpMetadataDir(), cache_dir_r);
00325   }
00326 
00327   MIL << "Metadata saved in " << cache_dir_r << ". Setting as cache." << std::endl;
00328   _cache_dir = cache_dir_r;
00329  
00330   readRepomd();
00331 }
00332 
00333 void YUMSourceImpl::saveMetadataTo(const Pathname & dir_r)
00334 {
00335   TmpDir download_tmp_dir;
00336 
00337   bool need_to_refresh = true;
00338   try
00339   {
00340     need_to_refresh = downloadNeeded(dir_r);
00341   }
00342   catch (Exception &e)
00343   {
00344     ZYPP_THROW(Exception("Can't check if source has changed or not. Aborting refresh."));
00345   }
00346 
00347   if ( need_to_refresh )
00348   {
00349     MIL << "YUM source '" << alias() << "' has changed since last download. Re-reading metadata into " << dir_r << endl;
00350   }
00351   else
00352   {
00353     MIL << "YUM source '" << alias() << "' has not changed. Refresh completed. SHA1 of repomd.xml file is  the same." << std::endl;
00354     return;
00355   }
00356 
00357   try
00358   {
00359     download_tmp_dir = downloadMetadata();
00360   }
00361   catch (Exception &e)
00362   {
00363     ZYPP_THROW(Exception("Downloading metadata failed (is YUM source?) or user did not accept remote source. Aborting refresh."));
00364   }
00365 
00366   copyLocalMetadata(download_tmp_dir, dir_r);
00367 
00368   // download_tmp_dir go out of scope now but it is ok as we already copied the content.
00369 }
00370 
00371 
00372 void YUMSourceImpl::readRepomd()
00373 {
00374   _repo_primary.clear();
00375   _repo_files.clear();
00376   _repo_group.clear();
00377   _repo_pattern.clear();
00378   _repo_product.clear();
00379   _repo_patches.clear();
00380   
00381   parser::ParserProgress::Ptr progress;
00382   callback::SendReport<SourceReport> report;
00383   YUMSourceEventHandler npp(report);
00384   progress.reset( new parser::ParserProgress( npp ) );
00385 
00386   report->start( selfSourceRef(), "Parsing index file" );
00387   try
00388   {
00389     DBG << "Reading ifgz file " << repomdFile() << endl;
00390     ifgzstream repo_st(repomdFile().asString().c_str());
00391     YUMRepomdParser repomd(repo_st, "", progress);
00392     for (; ! repomd.atEnd(); ++repomd)
00393     {
00394       // note that we skip adding other.xml to the list of files to provide
00395       if ((*repomd)->type == "primary")
00396         _repo_primary.push_back(*repomd);
00397       else if ((*repomd)->type == "filelists")
00398         _repo_files.push_back(*repomd);
00399       else if ((*repomd)->type == "group")
00400         _repo_group.push_back(*repomd);
00401       else if ((*repomd)->type == "pattern")
00402         _repo_pattern.push_back(*repomd);
00403       else if ((*repomd)->type == "product")
00404         _repo_product.push_back(*repomd);
00405       else if ((*repomd)->type == "patches")
00406         _repo_patches.push_back(*repomd);
00407       else if ((*repomd)->type != "other")        // type "other" is ok, anything else not
00408         ERR << "Unknown type of repo file: " << (*repomd)->type << endl;
00409     }
00410     report->finish( selfSourceRef(), "Parsing index file", source::SourceReport::NO_ERROR, "" );
00411   }
00412   catch ( const Exception &  excpt_r )
00413   {
00414     ZYPP_CAUGHT( excpt_r );       // log the caught exception
00415     report->finish( selfSourceRef(), "Parsing index file", source::SourceReport::INVALID, "" );
00416     ZYPP_THROW( SourceMetadataException("Error parsing repomd.xml file") );
00417 
00418   }
00419 }
00420 
00421 std::set<zypp::Resolvable::Kind>
00422 YUMSourceImpl::resolvableKinds() const
00423 {
00424   std::set<zypp::Resolvable::Kind> kinds;
00425   
00426   if (_repo_product.size() > 0 )
00427     kinds.insert( ResTraits<zypp::Product>::kind ); 
00428   
00429   if (_repo_pattern.size() > 0 )
00430     kinds.insert( ResTraits<zypp::Pattern>::kind );
00431   
00432   if (_repo_group.size() > 0 )
00433     kinds.insert( ResTraits<zypp::Selection>::kind );
00434   
00435   if (_repo_primary.size() > 0 )
00436   kinds.insert( ResTraits<zypp::Package>::kind );
00437   
00438   if (_repo_patches.size() > 0 )
00439     kinds.insert( ResTraits<zypp::Patch>::kind );
00440   
00441   return kinds;
00442 }
00443 
00444 void YUMSourceImpl::provideProducts(Source_Ref source_r, ResStore& store)
00445 {
00446   Pathname filename;
00447   callback::SendReport<SourceReport> report;
00448 
00449   try
00450   {
00451     for (std::list<YUMRepomdData_Ptr>::const_iterator it = _repo_product.begin();
00452          it != _repo_product.end();
00453          it++)
00454     {
00455       filename = metadataRoot() + (*it)->location;
00456       ifgzstream st ( filename.asString().c_str() );
00457 
00458       parser::ParserProgress::Ptr progress;
00459       callback::SendReport<SourceReport> report;
00460       YUMSourceEventHandler npp(report);
00461       progress.reset( new parser::ParserProgress( npp ) );
00462 
00463        // TranslatorExplanation %s = product file
00464       report->start( selfSourceRef(), str::form(_("Reading product from %s"), filename.asString().c_str()) );
00465       
00466       YUMProductParser product(st, "", progress);
00467       for (; !product.atEnd(); ++product)
00468       {
00469         Product::Ptr p = createProduct( source_r, **product );
00470         store.insert (p);
00471       }
00472 
00473       if (product.errorStatus())
00474       {
00475         // TranslatorExplanation %s = product file
00476         report->finish( selfSourceRef(), str::form(_("Reading product from %s"), filename.asString().c_str()), source::SourceReport::INVALID, product.errorStatus()->msg() );
00477         ZYPP_THROW(SourceMetadataException( "Error reading product from " + filename.asString()+ " : " + product.errorStatus()->msg()));
00478       }
00479       else
00480       {
00481         // TranslatorExplanation %s = product file
00482         report->finish( selfSourceRef(), str::form(_("Reading product from %s"), filename.asString().c_str()), source::SourceReport::NO_ERROR, "" );
00483       }
00484     }
00485   }
00486   catch ( const Exception &e )
00487   {
00488     ZYPP_CAUGHT(e);
00489     // TranslatorExplanation %s = product file
00490     report->finish( selfSourceRef(), str::form(_("Reading product from %s"), filename.asString().c_str()), source::SourceReport::INVALID, e.msg() );
00491     ZYPP_THROW(SourceMetadataException(e.msg()));
00492   }
00493 
00494 }
00495 
00496 void YUMSourceImpl::providePackages(Source_Ref source_r, ResStore& store)
00497 {
00498   Pathname filename;
00499   callback::SendReport<SourceReport> report;
00500 
00501   // now put other and filelist data to structures for easier find
00502   map<NVRA, YUMFileListData_Ptr> files_data;
00503   map<NVRA, YUMOtherData_Ptr> other_data;
00504 
00505   try
00506   {
00507     for (std::list<YUMRepomdData_Ptr>::const_iterator it
00508          = _repo_files.begin();
00509          it != _repo_files.end();
00510          it++)
00511     {
00512       Pathname filename = metadataRoot() + (*it)->location;
00513       DBG << "Reading ifgz file " << filename << endl;
00514       ifgzstream st( filename.asString().c_str() );
00515 
00516       parser::ParserProgress::Ptr progress;
00517       YUMSourceEventHandler npp(report);
00518       progress.reset( new parser::ParserProgress( npp, get_stream_size(filename) ) );
00519       // TranslatorExplanation %s = package file list
00520       report->start( selfSourceRef(), str::form(_("Reading filelist from %s"), filename.asString().c_str()) );
00521 
00522       YUMFileListParser filelist ( st, "", progress );
00523       for (; ! filelist.atEnd(); ++filelist)
00524       {
00525         if (*filelist == NULL) continue;  // skip incompatible archs
00526         NVRA nvra( (*filelist)->name,
00527                    Edition( (*filelist)->ver, (*filelist)->rel, str::strtonum<int>( (*filelist)->epoch ) ),
00528                    Arch ( (*filelist)->arch ) );
00529         files_data[nvra] = *filelist;
00530       }
00531 
00532       if (filelist.errorStatus())
00533       {
00534         // TranslatorExplanation %s = package file list
00535         report->finish( selfSourceRef(), str::form(_("Reading filelist from %s"), filename.asString().c_str()), source::SourceReport::INVALID, filelist.errorStatus()->msg() );
00536         ZYPP_THROW(SourceMetadataException( "Error reading filelists from " + filename.asString()+ " : " + filelist.errorStatus()->msg()));
00537       }
00538       else
00539       {
00540         // TranslatorExplanation %s = package file list
00541         report->finish( selfSourceRef(), str::form(_("Reading filelist from %s"), filename.asString().c_str()), source::SourceReport::NO_ERROR, "" );
00542       }
00543     }
00544   }
00545   catch ( const Exception &e )
00546   {
00547     ZYPP_CAUGHT(e);
00548     // TranslatorExplanation %s = package file list
00549     report->finish( selfSourceRef(),str::form(_("Reading filelist from %s"), filename.asString().c_str()), source::SourceReport::INVALID, e.msg() );
00550     ZYPP_THROW(SourceMetadataException(e.msg()));
00551   }
00552 
00553   try
00554   {
00555     // now read primary data, merge them with filelist and changelog
00556     for (std::list<YUMRepomdData_Ptr>::const_iterator it = _repo_primary.begin(); it != _repo_primary.end(); it++)
00557     {
00558       filename = metadataRoot() + (*it)->location;
00559       DBG << "Reading file " << filename << endl;
00560 
00561       parser::ParserProgress::Ptr progress;
00562       YUMSourceEventHandler npp(report);
00563       progress.reset( new parser::ParserProgress( npp ) );
00564       // TranslatorExplanation %s = packages file
00565       report->start( selfSourceRef(), str::form(_("Reading packages from %s"), filename.asString().c_str()) );
00566 
00567       ifgzstream st ( filename.asString().c_str() );
00568 
00569       YUMPrimaryParser prim(st, "", progress);
00570       //YUMPrimaryParser prim(filename.asString(), "", progress);
00571       for (; !prim.atEnd(); ++prim)
00572       {
00573         if (*prim == NULL) continue;      // incompatible arch detected during parsing
00574 
00575         Arch arch;
00576         if (!(*prim)->arch.empty())
00577           arch = Arch((*prim)->arch);
00578 
00579         NVRA nvra( (*prim)->name,
00580                    Edition( (*prim)->ver, (*prim)->rel, str::strtonum<int>( (*prim)->epoch ) ),
00581                    arch );
00582         map<NVRA, YUMOtherData_Ptr>::iterator found_other = other_data.find( nvra );
00583         map<NVRA, YUMFileListData_Ptr>::iterator found_files = files_data.find( nvra );
00584 
00585         YUMFileListData filelist_empty;
00586         YUMOtherData other_empty;
00587         ResImplTraits<YUMPackageImpl>::Ptr impl;
00588         Package::Ptr p = createPackage( source_r, **prim, found_files != files_data.end()
00589                                         ? *(found_files->second)
00590                                         : filelist_empty,
00591                                         found_other != other_data.end()
00592                                         ? *(found_other->second)
00593                                         : other_empty,
00594                                         impl
00595                                       );
00596         ImplAndPackage iap = { impl, p };
00597         _package_impl[nvra] = iap;
00598 //                MIL << "inserting package "<< p->name() << std::endl;
00599         store.insert (p);
00600       }
00601 
00602       if (prim.errorStatus())
00603       {
00604         // TranslatorExplanation %s = packages file
00605         report->finish( selfSourceRef(), str::form(_("Reading packages from %s"), filename.asString().c_str()), source::SourceReport::INVALID, prim.errorStatus()->msg() );
00606         ZYPP_THROW(SourceMetadataException( "Error packages from " + filename.asString()+ " : " + prim.errorStatus()->msg()));
00607       }
00608       else
00609       {
00610         // TranslatorExplanation %s = packages file
00611         report->finish( selfSourceRef(), str::form(_("Reading packages from %s"), filename.asString().c_str()), source::SourceReport::NO_ERROR, "" );
00612       }
00613     }
00614   }
00615   catch ( const Exception &e )
00616   {
00617     ZYPP_CAUGHT(e);
00618     // TranslatorExplanation %s = packages file
00619     report->finish( selfSourceRef(), str::form(_("Reading packages from %s"), filename.asString().c_str()), source::SourceReport::INVALID, e.msg() );
00620     ZYPP_THROW(SourceMetadataException(e.msg()));
00621   }
00622 
00623 }
00624 
00625 void YUMSourceImpl::provideSelections(Source_Ref source_r, ResStore& store)
00626 {
00627   callback::SendReport<SourceReport> report;
00628   Pathname filename;
00629   try
00630   {
00631     for (std::list<YUMRepomdData_Ptr>::const_iterator it = _repo_group.begin();
00632          it != _repo_group.end();
00633          it++)
00634     {
00635       Pathname filename = metadataRoot() + (*it)->location;
00636       DBG << "Reading file " << filename << endl;
00637       ifgzstream st ( filename.asString().c_str() );
00638 
00639       parser::ParserProgress::Ptr progress;
00640       YUMSourceEventHandler npp(report);
00641       progress.reset( new parser::ParserProgress( npp ) );
00642       // TranslatorExplanation %s = selection metadata file
00643       report->start( selfSourceRef(), str::form(_("Reading selection from %s"), filename.asString().c_str()) );
00644 
00645       YUMGroupParser group(st, "", progress);
00646       for (; !group.atEnd(); ++group)
00647       {
00648         Selection::Ptr p = createGroup( source_r, **group );
00649         store.insert (p);
00650       }
00651 
00652       if (group.errorStatus())
00653       {
00654         // TranslatorExplanation %s = selection metadata file
00655         report->finish( selfSourceRef(), str::form(_("Reading selection from %s"), filename.asString().c_str()), source::SourceReport::INVALID, group.errorStatus()->msg() );
00656         ZYPP_THROW(SourceMetadataException( "Error Parsing selection " + filename.asString()+ " : " + group.errorStatus()->msg()));
00657       }
00658       else
00659       {
00660         // TranslatorExplanation %s = selection metadata file
00661         report->finish( selfSourceRef(), str::form(_("Reading selection from %s"), filename.asString().c_str()), source::SourceReport::NO_ERROR, "" );
00662       }
00663     }
00664   }
00665   catch ( const Exception &e )
00666   {
00667     ZYPP_CAUGHT(e);
00668     // TranslatorExplanation %s = selection metadata file
00669     report->finish( selfSourceRef(), str::form(_("Reading selection from %s"), filename.asString().c_str()), source::SourceReport::INVALID, e.msg() );
00670     ZYPP_THROW(SourceMetadataException(e.msg()));
00671   }
00672 
00673 }
00674 
00675 void YUMSourceImpl::providePatterns(Source_Ref source_r, ResStore& store)
00676 {
00677   callback::SendReport<SourceReport> report;
00678   Pathname filename;
00679   try
00680   {
00681     for (std::list<YUMRepomdData_Ptr>::const_iterator it = _repo_pattern.begin();
00682          it != _repo_pattern.end(); it++)
00683     {
00684       Pathname filename = metadataRoot() + (*it)->location;
00685 
00686       DBG << "Reading file " << filename << endl;
00687       ifgzstream st ( filename.asString().c_str() );
00688 
00689       parser::ParserProgress::Ptr progress;
00690       YUMSourceEventHandler npp(report);
00691       progress.reset( new parser::ParserProgress( npp )  );
00692       // TranslatorExplanation %s = pattern metadata file
00693       report->start( selfSourceRef(), str::form(_("Reading pattern from %s"), filename.asString().c_str()) );
00694 
00695       YUMPatternParser pattern(st, "", progress);
00696       for (; !pattern.atEnd(); ++pattern)
00697       {
00698         Pattern::Ptr p = createPattern( source_r, **pattern );
00699         store.insert (p);
00700       }
00701 
00702       if (pattern.errorStatus())
00703       {
00704         // TranslatorExplanation %s = pattern metadata file
00705         report->finish( selfSourceRef(), str::form(_("Reading pattern from %s"), filename.asString().c_str()), source::SourceReport::INVALID, pattern.errorStatus()->msg() );
00706         ZYPP_THROW(SourceMetadataException( "Error parsing pattern" + filename.asString()+ " : " + pattern.errorStatus()->msg()));
00707       }
00708       else
00709       {
00710         // TranslatorExplanation %s = pattern metadata file
00711         report->finish( selfSourceRef(), str::form(_("Reading pattern from %s"), filename.asString().c_str()), source::SourceReport::NO_ERROR, "" );
00712       }
00713     }
00714   }
00715   catch ( const Exception &e )
00716   {
00717     ZYPP_CAUGHT(e);
00718     // TranslatorExplanation %s = pattern metadata file
00719     report->finish( selfSourceRef(), str::form(_("Reading pattern from %s"), filename.asString().c_str()), source::SourceReport::INVALID, e.msg() );
00720     ZYPP_THROW(SourceMetadataException(e.msg()));
00721   }
00722 
00723 }
00724 
00725 void YUMSourceImpl::providePatches(Source_Ref source_r, ResStore& store)
00726 {
00727   std::list<std::string> patch_files;
00728   callback::SendReport<SourceReport> report;
00729   Pathname filename;
00730 
00731   try
00732   {
00733     for (std::list<YUMRepomdData_Ptr>::const_iterator it = _repo_patches.begin();
00734          it != _repo_patches.end();
00735          it++)
00736     {
00737       filename = metadataRoot() + (*it)->location;
00738 
00739       DBG << "Reading file " << filename << endl;
00740       ifgzstream st ( filename.asString().c_str() );
00741 
00742       parser::ParserProgress::Ptr progress;
00743       YUMSourceEventHandler npp(report);
00744       progress.reset( new parser::ParserProgress( npp ) );
00745       // TranslatorExplanation %s = patches index file
00746       report->start( selfSourceRef(), str::form(_("Reading patches index %s"), filename.asString().c_str()) );
00747       YUMPatchesParser patch(st, "", progress);
00748 
00749       for (; !patch.atEnd(); ++patch)
00750       {
00751         string filename = (*patch)->location;
00752         patch_files.push_back(filename);
00753       }
00754 
00755       if (patch.errorStatus())
00756       {
00757         // TranslatorExplanation %s = patches index file
00758         report->finish( selfSourceRef(), str::form(_("Reading patches index %s"), filename.asString().c_str()), source::SourceReport::INVALID, patch.errorStatus()->msg() );
00759         ZYPP_THROW(SourceMetadataException( "Error Parsing patch " + filename.asString()+ " : " + patch.errorStatus()->msg()));
00760       }
00761       else
00762       {
00763         // TranslatorExplanation %s = patches index file
00764         report->finish( selfSourceRef(), str::form(_("Reading patches index %s"), filename.asString().c_str()), source::SourceReport::NO_ERROR, "" );
00765       }
00766     }
00767   }
00768   catch ( const Exception &e )
00769   {
00770     ZYPP_CAUGHT(e);
00771     // TranslatorExplanation %s = patches index file
00772     report->finish( selfSourceRef(), str::form(_("Reading patches index %s"), filename.asString().c_str()), source::SourceReport::INVALID, e.msg() );
00773     ZYPP_THROW(SourceMetadataException(e.msg()));
00774   }
00775 
00776   try
00777   {
00778     //---------------------------------
00779     // now the individual patch files
00780     for (std::list<std::string>::const_iterator it = patch_files.begin();
00781          it != patch_files.end();
00782          it++)
00783     {
00784       filename = metadataRoot() + *it;
00785       DBG << "Reading file " << filename << endl;
00786 
00787       //FIXME error handling
00788       ifgzstream st ( filename.asString().c_str() );
00789 
00790       parser::ParserProgress::Ptr progress;
00791       YUMSourceEventHandler npp(report);
00792       progress.reset( new parser::ParserProgress( npp ) );
00793 
00794       // TranslatorExplanation %s = patch metadata file
00795       report->start( selfSourceRef(), str::form(_("Reading patch %s"), filename.asString().c_str()) );
00796 
00797       YUMPatchParser ptch(st, "", progress);
00798       for (; !ptch.atEnd(); ++ptch)
00799       {
00800         Patch::Ptr p = createPatch( source_r, **ptch );
00801         store.insert (p);
00802         Patch::AtomList atoms = p->atoms();
00803         for (Patch::AtomList::iterator at = atoms.begin(); at != atoms.end(); at++)
00804         {
00805           _store.insert (*at);
00806         }
00807       }
00808 
00809       if (ptch.errorStatus())
00810       {
00811         // TranslatorExplanation %s = patch metadata file
00812         report->finish( selfSourceRef(), str::form(_("Reading patch %s"), filename.asString().c_str()), source::SourceReport::INVALID, ptch.errorStatus()->msg() );
00813         ZYPP_THROW(SourceMetadataException( "Error Parsing patch " + filename.asString()+ " : " + ptch.errorStatus()->msg()));
00814       }
00815       else
00816       {
00817         // TranslatorExplanation %s = patch metadata file
00818         report->finish( selfSourceRef(), str::form(_("Reading patch %s"), filename.asString().c_str()), source::SourceReport::NO_ERROR, "" );
00819       }
00820     }
00821   }
00822   catch ( const Exception &e )
00823   {
00824     ERR << "Cannot read patch metadata" << endl;
00825     ZYPP_CAUGHT(e);
00826     // TranslatorExplanation %s = patch metadata file
00827     report->finish( selfSourceRef(), str::form(_("Reading patch %s"), filename.asString().c_str()), source::SourceReport::INVALID, e.msg() );
00828     ZYPP_THROW(SourceMetadataException(e.msg()));
00829   }
00830 }
00831 
00832 ResStore YUMSourceImpl::provideResolvablesByKind(Source_Ref source_r, zypp::Resolvable::Kind kind)
00833 {
00834   ResStore store;
00835 
00836   //readRepomd();
00837 
00838   if ( kind == ResTraits<Product>::kind )
00839     provideProducts ( selfSourceRef(), store );
00840   else if ( kind == ResTraits<Package>::kind )
00841     providePackages (selfSourceRef(), store );
00842   else if ( kind == ResTraits<Selection>::kind )
00843     provideSelections ( selfSourceRef(), store );
00844   else if ( kind == ResTraits<Pattern>::kind )
00845     providePatterns ( selfSourceRef(), store );
00846   else if ( kind == ResTraits<Pattern>::kind )
00847     providePatches ( selfSourceRef(), store );
00848 
00849   return store;
00850 }
00851 
00852 void YUMSourceImpl::createResolvables(Source_Ref source_r)
00853 {
00854 
00855   //readRepomd();
00856   provideProducts(selfSourceRef(), _store);
00857   providePackages(selfSourceRef(), _store);
00858   provideSelections(selfSourceRef(), _store);
00859   providePatterns(selfSourceRef(), _store);
00860   providePatches(selfSourceRef(), _store);
00861 
00862 }
00863 
00864 
00865 Package::Ptr YUMSourceImpl::createPackage(
00866   Source_Ref source_r,
00867   const zypp::parser::yum::YUMPrimaryData & parsed,
00868   const zypp::parser::yum::YUMFileListData & filelist,
00869   const zypp::parser::yum::YUMOtherData & other,
00870   ResImplTraits<YUMPackageImpl>::Ptr & impl
00871 )
00872 {
00873   try
00874   {
00875     impl = new YUMPackageImpl( source_r, parsed, filelist, other );
00876 
00877     Dependencies deps( createDependencies( parsed, ResTraits<Package>::kind ) );
00878 
00879     CapFactory f;
00880 
00881     for (std::list<FileData>::const_iterator it = filelist.files.begin();
00882          it != filelist.files.end();
00883          it++)
00884     {
00885       deps[Dep::PROVIDES].insert( f.parse( ResTraits<Package>::kind, it->name ) );
00886     }
00887 
00888     Arch arch;
00889     if (!parsed.arch.empty())
00890       arch = Arch(parsed.arch);
00891 
00892     // Collect basic Resolvable data
00893     NVRAD dataCollect( parsed.name,
00894                        Edition( parsed.ver, parsed.rel, parsed.epoch ),
00895                        arch,
00896                        deps
00897                      );
00898     Package::Ptr package = detail::makeResolvableFromImpl(
00899                              dataCollect, impl
00900                            );
00901     return package;
00902   }
00903   catch (const Exception & excpt_r)
00904   {
00905     ZYPP_CAUGHT(excpt_r);
00906     ZYPP_THROW(Exception("Cannot create package object"));
00907   }
00908   return 0L;
00909 }
00910 
00911 Atom::Ptr YUMSourceImpl::augmentPackage(
00912   Source_Ref source_r,
00913   const zypp::parser::yum::YUMPatchPackage & parsed
00914 )
00915 {
00916   try
00917   {
00918     Arch arch;
00919     if (!parsed.arch.empty())
00920       arch = Arch( parsed.arch );
00921 
00922     Edition edition( parsed.ver, parsed.rel, parsed.epoch );
00923     NVRA nvra( parsed.name,
00924                edition,
00925                arch );
00926 
00927     DBG << "augmentPackage(" << nvra << ")" << endl;
00928 
00929     // create Atom
00930     CapFactory f;
00931     Dependencies deps = createDependencies( parsed, ResTraits<Package>::kind );
00932 //        deps[Dep::REQUIRES].insert( f.parse( ResTraits<Package>::kind, parsed.name, Rel::EQ, edition ) );
00933     NVRAD atomdata( nvra, deps );
00934     ResImplTraits<YUMAtomImpl>::Ptr atomimpl = new YUMAtomImpl( source_r );
00935     Atom::Ptr atom = detail::makeResolvableFromImpl( atomdata, atomimpl );
00936 
00937     //source_r
00938     PackageImplMapT::const_iterator it = _package_impl.find( nvra );
00939     if (it == _package_impl.end())
00940     {
00941       WAR << "Patch augments non-existant package " << nvra << endl;
00942     }
00943     else
00944     {
00945       ResImplTraits<YUMPackageImpl>::Ptr impl = it->second.impl;
00946 
00947       if (!parsed.location.empty())
00948       {
00949         impl->_location = parsed.location;
00950         impl->_mediaNumber = str::strtonum<unsigned>( parsed.media );
00951         impl->_checksum = CheckSum(parsed.checksumType, parsed.checksum);
00952       }
00953       impl->_install_only = parsed.installOnly;
00954 
00955       //DBG << "Inserting patch RPMs" << endl;
00956       impl->_patch_rpms = std::list<YUMPackageImpl::PatchRpm>();
00957       for ( std::list<YUMPatchRpm>::const_iterator it = parsed.patchRpms.begin();
00958             it != parsed.patchRpms.end(); ++it )
00959       {
00960         YUMPackageImpl::PatchRpm patch_rpm;
00961 
00962         patch_rpm.location( source::OnMediaLocation()
00963                             .medianr( str::strtonum<unsigned>( it->media ) )
00964                             .filename( it->location )
00965                             .checksum( CheckSum( it->checksumType, it->checksum ) )
00966                             .downloadsize( str::strtonum<ByteCount::SizeType>( it->downloadsize ) ) );
00967 
00968         for ( std::list<YUMPatchBaseVersion>::const_iterator bvit = it->baseVersions.begin();
00969               bvit != it->baseVersions.end(); ++bvit )
00970         {
00971           patch_rpm.baseversion( Edition( bvit->edition.ver,
00972                                           bvit->edition.rel,
00973                                           bvit->edition.epoch ) );
00974         }
00975 
00976         patch_rpm.buildtime( str::strtonum<Date::ValueType>( it->buildtime ) );
00977 
00978         impl->_patch_rpms.push_back( patch_rpm );
00979       }
00980 
00981       //DBG << "Inserting delta RPMs" << endl;
00982       impl->_delta_rpms = std::list<YUMPackageImpl::DeltaRpm>();
00983       for ( std::list<YUMDeltaRpm>::const_iterator it = parsed.deltaRpms.begin();
00984             it != parsed.deltaRpms.end(); ++it )
00985       {
00986         YUMPackageImpl::DeltaRpm delta_rpm;
00987 
00988         delta_rpm.location( source::OnMediaLocation()
00989                             .medianr( str::strtonum<unsigned>( it->media ) )
00990                             .filename( it->location )
00991                             .checksum( CheckSum( it->checksumType, it->checksum ) )
00992                             .downloadsize( str::strtonum<ByteCount::SizeType>( it->downloadsize ) ) );
00993 
00994         const YUMDeltaBaseVersion & ybv( it->baseVersion );
00995         delta_rpm.baseversion( YUMPackageImpl::DeltaRpm::BaseVersion()
00996                                .edition( Edition( ybv.edition.ver,
00997                                                   ybv.edition.rel,
00998                                                   ybv.edition.epoch ) )
00999                                .buildtime( str::strtonum<Date::ValueType>( ybv.buildtime ) )
01000                                .checksum( CheckSum::md5( ybv.md5sum ) )
01001                                .sequenceinfo( ybv.sequence_info )
01002                              );
01003 
01004         delta_rpm.buildtime( str::strtonum<Date::ValueType>( it->buildtime ) );
01005 
01006         impl->_delta_rpms.push_back( delta_rpm );
01007       }
01008     }
01009     return atom;
01010   }
01011   catch (const Exception & excpt_r)
01012   {
01013     ZYPP_CAUGHT(excpt_r);
01014     ZYPP_THROW(Exception("Cannot create augmented package object"));
01015   }
01016   return 0L;
01017 }
01018 
01019 Selection::Ptr YUMSourceImpl::createGroup(
01020   Source_Ref source_r,
01021   const zypp::parser::yum::YUMGroupData & parsed
01022 )
01023 {
01024   try
01025   {
01026     ResImplTraits<YUMGroupImpl>::Ptr impl(new YUMGroupImpl(source_r, parsed));
01027     // Collect basic Resolvable data
01028     NVRAD dataCollect( parsed.groupId,
01029                        Edition::noedition,                      // group has just a name,
01030                        Arch_noarch,                             //   pattern has edition & arch
01031                        createGroupDependencies(parsed));
01032     Selection::Ptr group = detail::makeResolvableFromImpl(
01033                              dataCollect, impl
01034                            );
01035     return group;
01036   }
01037   catch (const Exception & excpt_r)
01038   {
01039     ZYPP_CAUGHT(excpt_r);
01040     ZYPP_THROW(Exception("Cannot create package group object"));
01041   }
01042   return 0L;
01043 }
01044 
01045 Pattern::Ptr YUMSourceImpl::createPattern(
01046   Source_Ref source_r,
01047   const zypp::parser::yum::YUMPatternData & parsed
01048 )
01049 {
01050   try
01051   {
01052     ResImplTraits<YUMPatternImpl>::Ptr impl(new YUMPatternImpl(source_r, parsed));
01053     // Collect basic Resolvable data
01054     Arch arch;
01055     if (!parsed.arch.empty())
01056       arch = Arch(parsed.arch);
01057 
01058     NVRAD dataCollect( parsed.name,
01059                        Edition( parsed.ver, parsed.rel, parsed.epoch ),
01060                        arch,
01061                        createDependencies(parsed, ResTraits<Pattern>::kind));
01062     Pattern::Ptr pattern = detail::makeResolvableFromImpl(
01063                              dataCollect, impl
01064                            );
01065     return pattern;
01066   }
01067   catch (const Exception & excpt_r)
01068   {
01069     ZYPP_CAUGHT(excpt_r);
01070     ZYPP_THROW(Exception("Cannot create installation pattern object"));
01071   }
01072   return 0L;
01073 }
01074 
01075 Message::Ptr YUMSourceImpl::createMessage(
01076   Source_Ref source_r,
01077   const zypp::parser::yum::YUMPatchMessage & parsed,
01078   Patch::constPtr patch
01079 )
01080 {
01081   try
01082   {
01083     ResImplTraits<YUMMessageImpl>::Ptr impl(new YUMMessageImpl(source_r, parsed, patch));
01084     Arch arch;
01085     if (!parsed.arch.empty())
01086       arch = Arch(parsed.arch);
01087     // Collect basic Resolvable data
01088     NVRAD dataCollect( parsed.name,
01089                        Edition( parsed.ver, parsed.rel, parsed.epoch ),
01090                        arch,
01091                        createDependencies(parsed,
01092                                           ResTraits<Message>::kind)
01093                      );
01094     Message::Ptr message = detail::makeResolvableFromImpl(
01095                              dataCollect, impl
01096                            );
01097     return message;
01098   }
01099   catch (const Exception & excpt_r)
01100   {
01101     ZYPP_CAUGHT(excpt_r);
01102     ZYPP_THROW(Exception("Cannot create message object"));
01103   }
01104   return 0L;
01105 }
01106 
01107 Script::Ptr YUMSourceImpl::createScript(
01108   Source_Ref source_r,
01109   const zypp::parser::yum::YUMPatchScript & parsed
01110 )
01111 {
01112   try
01113   {
01114     ResImplTraits<YUMScriptImpl>::Ptr impl(new YUMScriptImpl(source_r, parsed));
01115     Arch arch;
01116     if (!parsed.arch.empty())
01117       arch = Arch(parsed.arch);
01118     // Collect basic Resolvable data
01119     NVRAD dataCollect( parsed.name,
01120                        Edition( parsed.ver, parsed.rel, parsed.epoch ),
01121                        arch,
01122                        createDependencies(parsed,
01123                                           ResTraits<Script>::kind)
01124                      );
01125     Script::Ptr script = detail::makeResolvableFromImpl(
01126                            dataCollect, impl
01127                          );
01128     return script;
01129   }
01130   catch (const Exception & excpt_r)
01131   {
01132     ZYPP_CAUGHT(excpt_r);
01133     ZYPP_THROW(Exception("Cannot create script object"));
01134   }
01135   return 0L;
01136 }
01137 
01138 Product::Ptr YUMSourceImpl::createProduct(
01139   Source_Ref source_r,
01140   const zypp::parser::yum::YUMProductData & parsed
01141 )
01142 {
01143   try
01144   {
01145     ResImplTraits<YUMProductImpl>::Ptr impl(new YUMProductImpl(source_r, parsed));
01146 
01147     // Collect basic Resolvable data
01148     Arch arch;
01149     if (!parsed.arch.empty())
01150       arch = Arch(parsed.arch);
01151     
01152     string name(parsed.name);
01153     std::replace(name.begin(), name.end(), ' ', '_');
01154     
01155     NVRAD dataCollect( name,
01156                        Edition( parsed.ver, parsed.rel, parsed.epoch ),
01157                        arch,
01158                        createDependencies(parsed,
01159                                           ResTraits<Product>::kind)
01160                      );
01161     Product::Ptr product = detail::makeResolvableFromImpl(
01162                              dataCollect, impl
01163                            );
01164     return product;
01165   }
01166   catch (const Exception & excpt_r)
01167   {
01168     ZYPP_CAUGHT(excpt_r);
01169     ZYPP_THROW(Exception("Cannot create product object"));
01170   }
01171   return 0L;
01172 }
01173 
01174 Patch::Ptr YUMSourceImpl::createPatch(
01175   Source_Ref source_r,
01176   const zypp::parser::yum::YUMPatchData & parsed
01177 )
01178 {
01179   try
01180   {
01181     ResImplTraits<YUMPatchImpl>::Ptr impl(new YUMPatchImpl(source_r, parsed, *this));
01182 
01183     Arch arch;
01184     if (!parsed.arch.empty())
01185       arch = Arch(parsed.arch);
01186 
01187     // Collect basic Resolvable data
01188     NVRAD dataCollect( parsed.name,
01189                        Edition( parsed.ver, parsed.rel, parsed.epoch ),
01190                        arch,
01191                        createDependencies( parsed,
01192                                            ResTraits<Patch>::kind)
01193                      );
01194     Patch::Ptr patch = detail::makeResolvableFromImpl(
01195                          dataCollect, impl
01196                        );
01197     // now process the atoms
01198     CapFactory _f;
01199     Capability cap( _f.parse(
01200                       Patch::TraitsType::kind,
01201                       parsed.name,
01202                       Rel::EQ,
01203                       Edition(parsed.ver, parsed.rel, parsed.epoch)
01204                     ));
01205 
01206     // maps name to parser data in order to find 'best' architectureC
01207     typedef std::map<std::string, shared_ptr<YUMPatchPackage> > PkgAtomsMap;
01208     PkgAtomsMap pkg_atoms;
01209 
01210     for (std::list<shared_ptr<YUMPatchAtom> >::const_iterator it
01211          = parsed.atoms.begin();
01212          it != parsed.atoms.end();
01213          it++)
01214     {
01215       switch ((*it)->atomType())
01216       {
01217         // for packages, try to find best architecture for name-version-release first (#168840)
01218         // we can't use the name alone as there might be different editions for the same name
01219         // with different architecture.
01220         // So we only choose the best architecture if name-version-edition matches (#170098)
01221 
01222       case YUMPatchAtom::Package:
01223         {
01224           shared_ptr<YUMPatchPackage> package_data
01225           = dynamic_pointer_cast<YUMPatchPackage>(*it);
01226           string atomkey( package_data->name + "-" + package_data->epoch + ":" + package_data->ver + "-" + package_data->rel );
01227 
01228           // check if atomkey is already known
01229           PkgAtomsMap::iterator pa_pos = pkg_atoms.find( atomkey );
01230           if (pa_pos != pkg_atoms.end())
01231           {
01232             try
01233             {
01234               Arch oldarch, newarch;
01235               if (!(pa_pos->second->arch.empty())) oldarch = Arch( pa_pos->second->arch );
01236               if (!(package_data->arch.empty())) newarch = Arch( package_data->arch );
01237               if (newarch.compatibleWith( getZYpp()->architecture() ) )
01238               {                 // new one is compatible (if not, we don't care)
01239 
01240                 if (!oldarch.compatibleWith( getZYpp()->architecture() )                        // old one is not compatible
01241                     || oldarch.compare( newarch ) < 0)                                  //  or compatible but worse
01242                 {
01243                   pa_pos->second = package_data;                                // new one is it !
01244                 }
01245               }
01246             }
01247             catch ( const Exception & excpt_r )
01248             {
01249               ZYPP_CAUGHT( excpt_r );
01250               ERR << "Package " << package_data->name << " in patch's atomlist has bad architecture '" << package_data->arch << "'" << endl;
01251             }
01252           }
01253           else
01254           {
01255             pkg_atoms[atomkey] = package_data;                                  // first occurence of this atomkey
01256           }
01257           break;
01258         }
01259       case YUMPatchAtom::Message:
01260         {
01261           shared_ptr<YUMPatchMessage> message_data
01262           = dynamic_pointer_cast<YUMPatchMessage>(*it);
01263           Message::Ptr message = createMessage(source_r, *message_data, patch);
01264           impl->_atoms.push_back(message);
01265           break;
01266         }
01267       case YUMPatchAtom::Script:
01268         {
01269           shared_ptr<YUMPatchScript> script_data
01270           = dynamic_pointer_cast<YUMPatchScript>(*it);
01271           Script::Ptr script = createScript(source_r, *script_data);
01272           impl->_atoms.push_back(script);
01273           break;
01274         }
01275       default:
01276         ERR << "Unknown type of atom" << endl;
01277       }
01278 #if 0                                   // atoms require their patch, why ?
01279       for (Patch::AtomList::iterator it = impl->_atoms.begin();
01280            it != impl->_atoms.end();
01281            it++)
01282       {
01283         (*it)->injectRequires(cap);
01284       }
01285 #endif
01286     }
01287 
01288     for (PkgAtomsMap::const_iterator pa_pos = pkg_atoms.begin(); pa_pos != pkg_atoms.end(); ++pa_pos)
01289     {
01290       Atom::Ptr atom = augmentPackage( source_r, *(pa_pos->second) );
01291       impl->_atoms.push_back(atom);
01292     }
01293 
01294     return patch;
01295   }
01296   catch (const Exception & excpt_r)
01297   {
01298     ZYPP_CAUGHT(excpt_r);
01299     ZYPP_THROW(Exception("Cannot create patch object"));
01300   }
01301   return 0L;
01302 }
01303 
01304 Dependencies YUMSourceImpl::createDependencies(
01305   const zypp::parser::yum::YUMObjectData & parsed,
01306   const Resolvable::Kind my_kind
01307 )
01308 {
01309   Dependencies _deps;
01310   for (std::list<YUMDependency>::const_iterator it = parsed.provides.begin();
01311        it != parsed.provides.end();
01312        it++)
01313   {
01314     _deps[Dep::PROVIDES].insert(createCapability(*it, my_kind));
01315   }
01316 
01317   for (std::list<YUMDependency>::const_iterator it = parsed.conflicts.begin();
01318        it != parsed.conflicts.end();
01319        it++)
01320   {
01321     _deps[Dep::CONFLICTS].insert(createCapability(*it, my_kind));
01322   }
01323 
01324   for (std::list<YUMDependency>::const_iterator it = parsed.obsoletes.begin();
01325        it != parsed.obsoletes.end();
01326        it++)
01327   {
01328     _deps[Dep::OBSOLETES].insert(createCapability(*it, my_kind));
01329   }
01330 
01331   for (std::list<YUMDependency>::const_iterator it = parsed.freshens.begin();
01332        it != parsed.freshens.end();
01333        it++)
01334   {
01335     _deps[Dep::FRESHENS].insert(createCapability(*it, my_kind));
01336   }
01337 
01338   for (std::list<YUMDependency>::const_iterator it = parsed.recommends.begin();
01339        it != parsed.recommends.end();
01340        it++)
01341   {
01342     _deps[Dep::RECOMMENDS].insert(createCapability(*it, my_kind));
01343   }
01344 
01345   for (std::list<YUMDependency>::const_iterator it = parsed.suggests.begin();
01346        it != parsed.suggests.end();
01347        it++)
01348   {
01349     _deps[Dep::SUGGESTS].insert(createCapability(*it, my_kind));
01350   }
01351 
01352   for (std::list<YUMDependency>::const_iterator it = parsed.supplements.begin();
01353        it != parsed.supplements.end();
01354        it++)
01355   {
01356     _deps[Dep::SUPPLEMENTS].insert(createCapability(*it, my_kind));
01357   }
01358 
01359   for (std::list<YUMDependency>::const_iterator it = parsed.enhances.begin();
01360        it != parsed.enhances.end();
01361        it++)
01362   {
01363     _deps[Dep::ENHANCES].insert(createCapability(*it, my_kind));
01364   }
01365 
01366   for (std::list<YUMDependency>::const_iterator it = parsed.prerequires.begin();
01367        it != parsed.prerequires.end();
01368        it++)
01369   {
01370     _deps[Dep::PREREQUIRES].insert(createCapability(*it, my_kind));
01371   }
01372 
01373   for (std::list<YUMDependency>::const_iterator it = parsed.requires.begin();
01374        it != parsed.requires.end();
01375        it++)
01376   {
01377     if (it->pre == "1")
01378       _deps[Dep::PREREQUIRES].insert(createCapability(*it, my_kind));
01379     else
01380       _deps[Dep::REQUIRES].insert(createCapability(*it, my_kind));
01381   }
01382 
01383   return _deps;
01384 }
01385 
01386 Dependencies YUMSourceImpl::createGroupDependencies(
01387   const zypp::parser::yum::YUMGroupData & parsed
01388 )
01389 {
01390   Dependencies _deps;
01391 
01392   for (std::list<PackageReq>::const_iterator it = parsed.packageList.begin();
01393        it != parsed.packageList.end();
01394        it++)
01395   {
01396     Dep _dep_kind = Dep::REQUIRES;
01397     if (it->type == "mandatory" || it->type == "")
01398     {
01399       _dep_kind = Dep::REQUIRES;
01400     }
01401     else if (it->type == "default")
01402     {
01403       _dep_kind = Dep::RECOMMENDS;
01404     }
01405     else if (it->type == "optional")
01406     {
01407       _dep_kind = Dep::SUGGESTS;
01408     }
01409     _deps[_dep_kind].insert(createCapability(YUMDependency(
01410                               "",
01411                               it->name,
01412                               "EQ",
01413                               it->epoch,
01414                               it->ver,
01415                               it->rel,
01416                               ""
01417                             ),
01418                             ResTraits<Package>::kind));
01419   }
01420   for (std::list<MetaPkg>::const_iterator it = parsed.grouplist.begin();
01421        it != parsed.grouplist.end();
01422        it++)
01423   {
01424     Dep _dep_kind = Dep::REQUIRES;
01425     if (it->type == "mandatory" || it->type == "")
01426     {
01427       _dep_kind = Dep::REQUIRES;
01428     }
01429     else if (it->type == "default")
01430     {
01431       _dep_kind = Dep::RECOMMENDS;
01432     }
01433     else if (it->type == "optional")
01434     {
01435       _dep_kind = Dep::SUGGESTS;
01436     }
01437     _deps[_dep_kind].insert(createCapability(YUMDependency(
01438                               "",
01439                               it->name,
01440                               "",
01441                               "",
01442                               "",
01443                               "",
01444                               ""
01445                             ),
01446                             ResTraits<Selection>::kind));
01447   }
01448   return _deps;
01449 }
01450 
01451 Capability YUMSourceImpl::createCapability(const YUMDependency & dep,
01452     const Resolvable::Kind & my_kind)
01453 {
01454   CapFactory _f;
01455   Resolvable::Kind _kind = dep.kind == "" ? my_kind : Resolvable::Kind(dep.kind);
01456   Capability cap;
01457   if ( ! dep.isEncoded() )
01458   {
01459     cap = _f.parse(
01460             _kind,
01461             dep.name,
01462             Rel(dep.flags),
01463             Edition(dep.ver, dep.rel, dep.epoch)
01464           );
01465   }
01466   else
01467   {
01468     cap = _f.parse( _kind, dep.encoded );
01469   }
01470   return cap;
01471 }
01472 
01473 } // namespace yum
01475 } // namespace source
01478 } // namespace zypp

Generated on Tue Nov 28 16:49:32 2006 for zypp by  doxygen 1.5.0