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_("The signed repomd.xml file failed the 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           if ( ! *product )
00470           {
00471               ERR << "skipping invalid product from " << filename << endl;
00472               continue;
00473           }
00474           
00475         Product::Ptr p = createProduct( source_r, **product );
00476         store.insert (p);
00477       }
00478 
00479       if (product.errorStatus())
00480       {
00481         // TranslatorExplanation %s = product file
00482         report->finish( selfSourceRef(), str::form(_("Reading product from %s"), filename.asString().c_str()), source::SourceReport::INVALID, product.errorStatus()->msg() );
00483         ZYPP_THROW(SourceMetadataException( "Error reading product from " + filename.asString()+ " : " + product.errorStatus()->msg()));
00484       }
00485       else
00486       {
00487         // TranslatorExplanation %s = product file
00488         report->finish( selfSourceRef(), str::form(_("Reading product from %s"), filename.asString().c_str()), source::SourceReport::NO_ERROR, "" );
00489       }
00490     }
00491   }
00492   catch ( const Exception &e )
00493   {
00494     ZYPP_CAUGHT(e);
00495     // TranslatorExplanation %s = product file
00496     report->finish( selfSourceRef(), str::form(_("Reading product from %s"), filename.asString().c_str()), source::SourceReport::INVALID, e.msg() );
00497     ZYPP_THROW(SourceMetadataException(e.msg()));
00498   }
00499 
00500 }
00501 
00502 void YUMSourceImpl::providePackages(Source_Ref source_r, ResStore& store)
00503 {
00504   Pathname filename;
00505   callback::SendReport<SourceReport> report;
00506 
00507   // now put other and filelist data to structures for easier find
00508   map<NVRA, YUMFileListData_Ptr> files_data;
00509   map<NVRA, YUMOtherData_Ptr> other_data;
00510 
00511   try
00512   {
00513     for (std::list<YUMRepomdData_Ptr>::const_iterator it
00514          = _repo_files.begin();
00515          it != _repo_files.end();
00516          it++)
00517     {
00518       Pathname filename = metadataRoot() + (*it)->location;
00519       DBG << "Reading ifgz file " << filename << endl;
00520       ifgzstream st( filename.asString().c_str() );
00521 
00522       parser::ParserProgress::Ptr progress;
00523       YUMSourceEventHandler npp(report);
00524       progress.reset( new parser::ParserProgress( npp, get_stream_size(filename) ) );
00525       // TranslatorExplanation %s = package file list
00526       report->start( selfSourceRef(), str::form(_("Reading filelist from %s"), filename.asString().c_str()) );
00527 
00528       YUMFileListParser filelist ( st, "", progress );
00529       for (; ! filelist.atEnd(); ++filelist)
00530       {
00531         if (*filelist == NULL) continue;  // skip incompatible archs
00532         NVRA nvra( (*filelist)->name,
00533                    Edition( (*filelist)->ver, (*filelist)->rel, str::strtonum<int>( (*filelist)->epoch ) ),
00534                    Arch ( (*filelist)->arch ) );
00535         files_data[nvra] = *filelist;
00536       }
00537 
00538       if (filelist.errorStatus())
00539       {
00540         // TranslatorExplanation %s = package file list
00541         report->finish( selfSourceRef(), str::form(_("Reading filelist from %s"), filename.asString().c_str()), source::SourceReport::INVALID, filelist.errorStatus()->msg() );
00542         ZYPP_THROW(SourceMetadataException( "Error reading filelists from " + filename.asString()+ " : " + filelist.errorStatus()->msg()));
00543       }
00544       else
00545       {
00546         // TranslatorExplanation %s = package file list
00547         report->finish( selfSourceRef(), str::form(_("Reading filelist from %s"), filename.asString().c_str()), source::SourceReport::NO_ERROR, "" );
00548       }
00549     }
00550   }
00551   catch ( const Exception &e )
00552   {
00553     ZYPP_CAUGHT(e);
00554     // TranslatorExplanation %s = package file list
00555     report->finish( selfSourceRef(),str::form(_("Reading filelist from %s"), filename.asString().c_str()), source::SourceReport::INVALID, e.msg() );
00556     ZYPP_THROW(SourceMetadataException(e.msg()));
00557   }
00558 
00559   try
00560   {
00561     // now read primary data, merge them with filelist and changelog
00562     for (std::list<YUMRepomdData_Ptr>::const_iterator it = _repo_primary.begin(); it != _repo_primary.end(); it++)
00563     {
00564       filename = metadataRoot() + (*it)->location;
00565       DBG << "Reading file " << filename << endl;
00566 
00567       parser::ParserProgress::Ptr progress;
00568       YUMSourceEventHandler npp(report);
00569       progress.reset( new parser::ParserProgress( npp ) );
00570       // TranslatorExplanation %s = packages file
00571       report->start( selfSourceRef(), str::form(_("Reading packages from %s"), filename.asString().c_str()) );
00572 
00573       ifgzstream st ( filename.asString().c_str() );
00574 
00575       YUMPrimaryParser prim(st, "", progress);
00576       //YUMPrimaryParser prim(filename.asString(), "", progress);
00577       for (; !prim.atEnd(); ++prim)
00578       {
00579         if (*prim == NULL) continue;      // incompatible arch detected during parsing
00580 
00581         Arch arch;
00582         if (!(*prim)->arch.empty())
00583           arch = Arch((*prim)->arch);
00584 
00585         NVRA nvra( (*prim)->name,
00586                    Edition( (*prim)->ver, (*prim)->rel, str::strtonum<int>( (*prim)->epoch ) ),
00587                    arch );
00588         map<NVRA, YUMOtherData_Ptr>::iterator found_other = other_data.find( nvra );
00589         map<NVRA, YUMFileListData_Ptr>::iterator found_files = files_data.find( nvra );
00590 
00591         YUMFileListData filelist_empty;
00592         YUMOtherData other_empty;
00593         ResImplTraits<YUMPackageImpl>::Ptr impl;
00594         Package::Ptr p = createPackage( source_r, **prim, found_files != files_data.end()
00595                                         ? *(found_files->second)
00596                                         : filelist_empty,
00597                                         found_other != other_data.end()
00598                                         ? *(found_other->second)
00599                                         : other_empty,
00600                                         impl
00601                                       );
00602         ImplAndPackage iap = { impl, p };
00603         _package_impl[nvra] = iap;
00604 //                MIL << "inserting package "<< p->name() << std::endl;
00605         store.insert (p);
00606       }
00607 
00608       if (prim.errorStatus())
00609       {
00610         // TranslatorExplanation %s = packages file
00611         report->finish( selfSourceRef(), str::form(_("Reading packages from %s"), filename.asString().c_str()), source::SourceReport::INVALID, prim.errorStatus()->msg() );
00612         ZYPP_THROW(SourceMetadataException( "Error packages from " + filename.asString()+ " : " + prim.errorStatus()->msg()));
00613       }
00614       else
00615       {
00616         // TranslatorExplanation %s = packages file
00617         report->finish( selfSourceRef(), str::form(_("Reading packages from %s"), filename.asString().c_str()), source::SourceReport::NO_ERROR, "" );
00618       }
00619     }
00620   }
00621   catch ( const Exception &e )
00622   {
00623     ZYPP_CAUGHT(e);
00624     // TranslatorExplanation %s = packages file
00625     report->finish( selfSourceRef(), str::form(_("Reading packages from %s"), filename.asString().c_str()), source::SourceReport::INVALID, e.msg() );
00626     ZYPP_THROW(SourceMetadataException(e.msg()));
00627   }
00628 
00629 }
00630 
00631 void YUMSourceImpl::provideSelections(Source_Ref source_r, ResStore& store)
00632 {
00633   callback::SendReport<SourceReport> report;
00634   Pathname filename;
00635   try
00636   {
00637     for (std::list<YUMRepomdData_Ptr>::const_iterator it = _repo_group.begin();
00638          it != _repo_group.end();
00639          it++)
00640     {
00641       Pathname filename = metadataRoot() + (*it)->location;
00642       DBG << "Reading file " << filename << endl;
00643       ifgzstream st ( filename.asString().c_str() );
00644 
00645       parser::ParserProgress::Ptr progress;
00646       YUMSourceEventHandler npp(report);
00647       progress.reset( new parser::ParserProgress( npp ) );
00648       // TranslatorExplanation %s = selection metadata file
00649       report->start( selfSourceRef(), str::form(_("Reading selection from %s"), filename.asString().c_str()) );
00650 
00651       YUMGroupParser group(st, "", progress);
00652       for (; !group.atEnd(); ++group)
00653       {
00654         Selection::Ptr p = createGroup( source_r, **group );
00655         store.insert (p);
00656       }
00657 
00658       if (group.errorStatus())
00659       {
00660         // TranslatorExplanation %s = selection metadata file
00661         report->finish( selfSourceRef(), str::form(_("Reading selection from %s"), filename.asString().c_str()), source::SourceReport::INVALID, group.errorStatus()->msg() );
00662         ZYPP_THROW(SourceMetadataException( "Error Parsing selection " + filename.asString()+ " : " + group.errorStatus()->msg()));
00663       }
00664       else
00665       {
00666         // TranslatorExplanation %s = selection metadata file
00667         report->finish( selfSourceRef(), str::form(_("Reading selection from %s"), filename.asString().c_str()), source::SourceReport::NO_ERROR, "" );
00668       }
00669     }
00670   }
00671   catch ( const Exception &e )
00672   {
00673     ZYPP_CAUGHT(e);
00674     // TranslatorExplanation %s = selection metadata file
00675     report->finish( selfSourceRef(), str::form(_("Reading selection from %s"), filename.asString().c_str()), source::SourceReport::INVALID, e.msg() );
00676     ZYPP_THROW(SourceMetadataException(e.msg()));
00677   }
00678 
00679 }
00680 
00681 void YUMSourceImpl::providePatterns(Source_Ref source_r, ResStore& store)
00682 {
00683   callback::SendReport<SourceReport> report;
00684   Pathname filename;
00685   try
00686   {
00687     for (std::list<YUMRepomdData_Ptr>::const_iterator it = _repo_pattern.begin();
00688          it != _repo_pattern.end(); it++)
00689     {
00690       Pathname filename = metadataRoot() + (*it)->location;
00691 
00692       DBG << "Reading file " << filename << endl;
00693       ifgzstream st ( filename.asString().c_str() );
00694 
00695       parser::ParserProgress::Ptr progress;
00696       YUMSourceEventHandler npp(report);
00697       progress.reset( new parser::ParserProgress( npp )  );
00698       // TranslatorExplanation %s = pattern metadata file
00699       report->start( selfSourceRef(), str::form(_("Reading pattern from %s"), filename.asString().c_str()) );
00700 
00701       YUMPatternParser pattern(st, "", progress);
00702       for (; !pattern.atEnd(); ++pattern)
00703       {
00704         Pattern::Ptr p = createPattern( source_r, **pattern );
00705         store.insert (p);
00706       }
00707 
00708       if (pattern.errorStatus())
00709       {
00710         // TranslatorExplanation %s = pattern metadata file
00711         report->finish( selfSourceRef(), str::form(_("Reading pattern from %s"), filename.asString().c_str()), source::SourceReport::INVALID, pattern.errorStatus()->msg() );
00712         ZYPP_THROW(SourceMetadataException( "Error parsing pattern" + filename.asString()+ " : " + pattern.errorStatus()->msg()));
00713       }
00714       else
00715       {
00716         // TranslatorExplanation %s = pattern metadata file
00717         report->finish( selfSourceRef(), str::form(_("Reading pattern from %s"), filename.asString().c_str()), source::SourceReport::NO_ERROR, "" );
00718       }
00719     }
00720   }
00721   catch ( const Exception &e )
00722   {
00723     ZYPP_CAUGHT(e);
00724     // TranslatorExplanation %s = pattern metadata file
00725     report->finish( selfSourceRef(), str::form(_("Reading pattern from %s"), filename.asString().c_str()), source::SourceReport::INVALID, e.msg() );
00726     ZYPP_THROW(SourceMetadataException(e.msg()));
00727   }
00728 
00729 }
00730 
00731 void YUMSourceImpl::providePatches(Source_Ref source_r, ResStore& store)
00732 {
00733   std::list<std::string> patch_files;
00734   callback::SendReport<SourceReport> report;
00735   Pathname filename;
00736 
00737   try
00738   {
00739     for (std::list<YUMRepomdData_Ptr>::const_iterator it = _repo_patches.begin();
00740          it != _repo_patches.end();
00741          it++)
00742     {
00743       filename = metadataRoot() + (*it)->location;
00744 
00745       DBG << "Reading file " << filename << endl;
00746       ifgzstream st ( filename.asString().c_str() );
00747 
00748       parser::ParserProgress::Ptr progress;
00749       YUMSourceEventHandler npp(report);
00750       progress.reset( new parser::ParserProgress( npp ) );
00751       // TranslatorExplanation %s = patches index file
00752       report->start( selfSourceRef(), str::form(_("Reading patches index %s"), filename.asString().c_str()) );
00753       YUMPatchesParser patch(st, "", progress);
00754 
00755       for (; !patch.atEnd(); ++patch)
00756       {
00757         string filename = (*patch)->location;
00758         patch_files.push_back(filename);
00759       }
00760 
00761       if (patch.errorStatus())
00762       {
00763         // TranslatorExplanation %s = patches index file
00764         report->finish( selfSourceRef(), str::form(_("Reading patches index %s"), filename.asString().c_str()), source::SourceReport::INVALID, patch.errorStatus()->msg() );
00765         ZYPP_THROW(SourceMetadataException( "Error Parsing patch " + filename.asString()+ " : " + patch.errorStatus()->msg()));
00766       }
00767       else
00768       {
00769         // TranslatorExplanation %s = patches index file
00770         report->finish( selfSourceRef(), str::form(_("Reading patches index %s"), filename.asString().c_str()), source::SourceReport::NO_ERROR, "" );
00771       }
00772     }
00773   }
00774   catch ( const Exception &e )
00775   {
00776     ZYPP_CAUGHT(e);
00777     // TranslatorExplanation %s = patches index file
00778     report->finish( selfSourceRef(), str::form(_("Reading patches index %s"), filename.asString().c_str()), source::SourceReport::INVALID, e.msg() );
00779     ZYPP_THROW(SourceMetadataException(e.msg()));
00780   }
00781 
00782   try
00783   {
00784     //---------------------------------
00785     // now the individual patch files
00786     for (std::list<std::string>::const_iterator it = patch_files.begin();
00787          it != patch_files.end();
00788          it++)
00789     {
00790       filename = metadataRoot() + *it;
00791       DBG << "Reading file " << filename << endl;
00792 
00793       //FIXME error handling
00794       ifgzstream st ( filename.asString().c_str() );
00795 
00796       parser::ParserProgress::Ptr progress;
00797       YUMSourceEventHandler npp(report);
00798       progress.reset( new parser::ParserProgress( npp ) );
00799 
00800       // TranslatorExplanation %s = patch metadata file
00801       report->start( selfSourceRef(), str::form(_("Reading patch %s"), filename.asString().c_str()) );
00802 
00803       YUMPatchParser ptch(st, "", progress);
00804       for (; !ptch.atEnd(); ++ptch)
00805       {
00806         Patch::Ptr p = createPatch( source_r, **ptch );
00807         store.insert (p);
00808         Patch::AtomList atoms = p->atoms();
00809         for (Patch::AtomList::iterator at = atoms.begin(); at != atoms.end(); at++)
00810         {
00811           _store.insert (*at);
00812         }
00813       }
00814 
00815       if (ptch.errorStatus())
00816       {
00817         // TranslatorExplanation %s = patch metadata file
00818         report->finish( selfSourceRef(), str::form(_("Reading patch %s"), filename.asString().c_str()), source::SourceReport::INVALID, ptch.errorStatus()->msg() );
00819         ZYPP_THROW(SourceMetadataException( "Error Parsing patch " + filename.asString()+ " : " + ptch.errorStatus()->msg()));
00820       }
00821       else
00822       {
00823         // TranslatorExplanation %s = patch metadata file
00824         report->finish( selfSourceRef(), str::form(_("Reading patch %s"), filename.asString().c_str()), source::SourceReport::NO_ERROR, "" );
00825       }
00826     }
00827   }
00828   catch ( const Exception &e )
00829   {
00830     ERR << "Cannot read patch metadata" << endl;
00831     ZYPP_CAUGHT(e);
00832     // TranslatorExplanation %s = patch metadata file
00833     report->finish( selfSourceRef(), str::form(_("Reading patch %s"), filename.asString().c_str()), source::SourceReport::INVALID, e.msg() );
00834     ZYPP_THROW(SourceMetadataException(e.msg()));
00835   }
00836 }
00837 
00838 ResStore YUMSourceImpl::provideResolvablesByKind(Source_Ref source_r, zypp::Resolvable::Kind kind)
00839 {
00840   ResStore store;
00841 
00842   //readRepomd();
00843 
00844   if ( kind == ResTraits<Product>::kind )
00845     provideProducts ( selfSourceRef(), store );
00846   else if ( kind == ResTraits<Package>::kind )
00847     providePackages (selfSourceRef(), store );
00848   else if ( kind == ResTraits<Selection>::kind )
00849     provideSelections ( selfSourceRef(), store );
00850   else if ( kind == ResTraits<Pattern>::kind )
00851     providePatterns ( selfSourceRef(), store );
00852   else if ( kind == ResTraits<Pattern>::kind )
00853     providePatches ( selfSourceRef(), store );
00854 
00855   return store;
00856 }
00857 
00858 void YUMSourceImpl::createResolvables(Source_Ref source_r)
00859 {
00860 
00861   //readRepomd();
00862   provideProducts(selfSourceRef(), _store);
00863   providePackages(selfSourceRef(), _store);
00864   provideSelections(selfSourceRef(), _store);
00865   providePatterns(selfSourceRef(), _store);
00866   providePatches(selfSourceRef(), _store);
00867 
00868 }
00869 
00870 
00871 Package::Ptr YUMSourceImpl::createPackage(
00872   Source_Ref source_r,
00873   const zypp::parser::yum::YUMPrimaryData & parsed,
00874   const zypp::parser::yum::YUMFileListData & filelist,
00875   const zypp::parser::yum::YUMOtherData & other,
00876   ResImplTraits<YUMPackageImpl>::Ptr & impl
00877 )
00878 {
00879   try
00880   {
00881     impl = new YUMPackageImpl( source_r, parsed, filelist, other );
00882 
00883     Dependencies deps( createDependencies( parsed, ResTraits<Package>::kind ) );
00884 
00885     CapFactory f;
00886 
00887     for (std::list<FileData>::const_iterator it = filelist.files.begin();
00888          it != filelist.files.end();
00889          it++)
00890     {
00891       deps[Dep::PROVIDES].insert( f.parse( ResTraits<Package>::kind, it->name ) );
00892     }
00893 
00894     Arch arch;
00895     if (!parsed.arch.empty())
00896       arch = Arch(parsed.arch);
00897 
00898     // Collect basic Resolvable data
00899     NVRAD dataCollect( parsed.name,
00900                        Edition( parsed.ver, parsed.rel, parsed.epoch ),
00901                        arch,
00902                        deps
00903                      );
00904     Package::Ptr package = detail::makeResolvableFromImpl(
00905                              dataCollect, impl
00906                            );
00907     return package;
00908   }
00909   catch (const Exception & excpt_r)
00910   {
00911     ZYPP_CAUGHT(excpt_r);
00912     ZYPP_THROW(Exception("Cannot create package object"));
00913   }
00914   return 0L;
00915 }
00916 
00917 Atom::Ptr YUMSourceImpl::augmentPackage(
00918   Source_Ref source_r,
00919   const zypp::parser::yum::YUMPatchPackage & parsed
00920 )
00921 {
00922   try
00923   {
00924     Arch arch;
00925     if (!parsed.arch.empty())
00926       arch = Arch( parsed.arch );
00927 
00928     Edition edition( parsed.ver, parsed.rel, parsed.epoch );
00929     NVRA nvra( parsed.name,
00930                edition,
00931                arch );
00932 
00933     DBG << "augmentPackage(" << nvra << ")" << endl;
00934 
00935     // create Atom
00936     CapFactory f;
00937     Dependencies deps = createDependencies( parsed, ResTraits<Package>::kind );
00938 //        deps[Dep::REQUIRES].insert( f.parse( ResTraits<Package>::kind, parsed.name, Rel::EQ, edition ) );
00939     NVRAD atomdata( nvra, deps );
00940     ResImplTraits<YUMAtomImpl>::Ptr atomimpl = new YUMAtomImpl( source_r );
00941     Atom::Ptr atom = detail::makeResolvableFromImpl( atomdata, atomimpl );
00942 
00943     //source_r
00944     PackageImplMapT::const_iterator it = _package_impl.find( nvra );
00945     if (it == _package_impl.end())
00946     {
00947       WAR << "Patch augments non-existant package " << nvra << endl;
00948     }
00949     else
00950     {
00951       ResImplTraits<YUMPackageImpl>::Ptr impl = it->second.impl;
00952 
00953       if (!parsed.location.empty())
00954       {
00955         impl->_location = parsed.location;
00956         impl->_mediaNumber = str::strtonum<unsigned>( parsed.media );
00957         impl->_checksum = CheckSum(parsed.checksumType, parsed.checksum);
00958       }
00959       impl->_install_only = parsed.installOnly;
00960 
00961       //DBG << "Inserting patch RPMs" << endl;
00962       impl->_patch_rpms = std::list<YUMPackageImpl::PatchRpm>();
00963       for ( std::list<YUMPatchRpm>::const_iterator it = parsed.patchRpms.begin();
00964             it != parsed.patchRpms.end(); ++it )
00965       {
00966         YUMPackageImpl::PatchRpm patch_rpm;
00967 
00968         patch_rpm.location( source::OnMediaLocation()
00969                             .medianr( str::strtonum<unsigned>( it->media ) )
00970                             .filename( it->location )
00971                             .checksum( CheckSum( it->checksumType, it->checksum ) )
00972                             .downloadsize( str::strtonum<ByteCount::SizeType>( it->downloadsize ) ) );
00973 
00974         for ( std::list<YUMPatchBaseVersion>::const_iterator bvit = it->baseVersions.begin();
00975               bvit != it->baseVersions.end(); ++bvit )
00976         {
00977           patch_rpm.baseversion( Edition( bvit->edition.ver,
00978                                           bvit->edition.rel,
00979                                           bvit->edition.epoch ) );
00980         }
00981 
00982         patch_rpm.buildtime( str::strtonum<Date::ValueType>( it->buildtime ) );
00983 
00984         impl->_patch_rpms.push_back( patch_rpm );
00985       }
00986 
00987       //DBG << "Inserting delta RPMs" << endl;
00988       impl->_delta_rpms = std::list<YUMPackageImpl::DeltaRpm>();
00989       for ( std::list<YUMDeltaRpm>::const_iterator it = parsed.deltaRpms.begin();
00990             it != parsed.deltaRpms.end(); ++it )
00991       {
00992         YUMPackageImpl::DeltaRpm delta_rpm;
00993 
00994         delta_rpm.location( source::OnMediaLocation()
00995                             .medianr( str::strtonum<unsigned>( it->media ) )
00996                             .filename( it->location )
00997                             .checksum( CheckSum( it->checksumType, it->checksum ) )
00998                             .downloadsize( str::strtonum<ByteCount::SizeType>( it->downloadsize ) ) );
00999 
01000         const YUMDeltaBaseVersion & ybv( it->baseVersion );
01001         delta_rpm.baseversion( YUMPackageImpl::DeltaRpm::BaseVersion()
01002                                .edition( Edition( ybv.edition.ver,
01003                                                   ybv.edition.rel,
01004                                                   ybv.edition.epoch ) )
01005                                .buildtime( str::strtonum<Date::ValueType>( ybv.buildtime ) )
01006                                .checksum( CheckSum::md5( ybv.md5sum ) )
01007                                .sequenceinfo( ybv.sequence_info )
01008                              );
01009 
01010         delta_rpm.buildtime( str::strtonum<Date::ValueType>( it->buildtime ) );
01011 
01012         impl->_delta_rpms.push_back( delta_rpm );
01013       }
01014     }
01015     return atom;
01016   }
01017   catch (const Exception & excpt_r)
01018   {
01019     ZYPP_CAUGHT(excpt_r);
01020     ZYPP_THROW(Exception("Cannot create augmented package object"));
01021   }
01022   return 0L;
01023 }
01024 
01025 Selection::Ptr YUMSourceImpl::createGroup(
01026   Source_Ref source_r,
01027   const zypp::parser::yum::YUMGroupData & parsed
01028 )
01029 {
01030   try
01031   {
01032     ResImplTraits<YUMGroupImpl>::Ptr impl(new YUMGroupImpl(source_r, parsed));
01033     // Collect basic Resolvable data
01034     NVRAD dataCollect( parsed.groupId,
01035                        Edition::noedition,                      // group has just a name,
01036                        Arch_noarch,                             //   pattern has edition & arch
01037                        createGroupDependencies(parsed));
01038     Selection::Ptr group = detail::makeResolvableFromImpl(
01039                              dataCollect, impl
01040                            );
01041     return group;
01042   }
01043   catch (const Exception & excpt_r)
01044   {
01045     ZYPP_CAUGHT(excpt_r);
01046     ZYPP_THROW(Exception("Cannot create package group object"));
01047   }
01048   return 0L;
01049 }
01050 
01051 Pattern::Ptr YUMSourceImpl::createPattern(
01052   Source_Ref source_r,
01053   const zypp::parser::yum::YUMPatternData & parsed
01054 )
01055 {
01056   try
01057   {
01058     ResImplTraits<YUMPatternImpl>::Ptr impl(new YUMPatternImpl(source_r, parsed));
01059     // Collect basic Resolvable data
01060     Arch arch;
01061     if (!parsed.arch.empty())
01062       arch = Arch(parsed.arch);
01063 
01064     NVRAD dataCollect( parsed.name,
01065                        Edition( parsed.ver, parsed.rel, parsed.epoch ),
01066                        arch,
01067                        createDependencies(parsed, ResTraits<Pattern>::kind));
01068     Pattern::Ptr pattern = detail::makeResolvableFromImpl(
01069                              dataCollect, impl
01070                            );
01071     return pattern;
01072   }
01073   catch (const Exception & excpt_r)
01074   {
01075     ZYPP_CAUGHT(excpt_r);
01076     ZYPP_THROW(Exception("Cannot create installation pattern object"));
01077   }
01078   return 0L;
01079 }
01080 
01081 Message::Ptr YUMSourceImpl::createMessage(
01082   Source_Ref source_r,
01083   const zypp::parser::yum::YUMPatchMessage & parsed,
01084   Patch::constPtr patch
01085 )
01086 {
01087   try
01088   {
01089     ResImplTraits<YUMMessageImpl>::Ptr impl(new YUMMessageImpl(source_r, parsed, patch));
01090     Arch arch;
01091     if (!parsed.arch.empty())
01092       arch = Arch(parsed.arch);
01093     // Collect basic Resolvable data
01094     NVRAD dataCollect( parsed.name,
01095                        Edition( parsed.ver, parsed.rel, parsed.epoch ),
01096                        arch,
01097                        createDependencies(parsed,
01098                                           ResTraits<Message>::kind)
01099                      );
01100     Message::Ptr message = detail::makeResolvableFromImpl(
01101                              dataCollect, impl
01102                            );
01103     return message;
01104   }
01105   catch (const Exception & excpt_r)
01106   {
01107     ZYPP_CAUGHT(excpt_r);
01108     ZYPP_THROW(Exception("Cannot create message object"));
01109   }
01110   return 0L;
01111 }
01112 
01113 Script::Ptr YUMSourceImpl::createScript(
01114   Source_Ref source_r,
01115   const zypp::parser::yum::YUMPatchScript & parsed
01116 )
01117 {
01118   try
01119   {
01120     ResImplTraits<YUMScriptImpl>::Ptr impl(new YUMScriptImpl(source_r, parsed));
01121     Arch arch;
01122     if (!parsed.arch.empty())
01123       arch = Arch(parsed.arch);
01124     // Collect basic Resolvable data
01125     NVRAD dataCollect( parsed.name,
01126                        Edition( parsed.ver, parsed.rel, parsed.epoch ),
01127                        arch,
01128                        createDependencies(parsed,
01129                                           ResTraits<Script>::kind)
01130                      );
01131     Script::Ptr script = detail::makeResolvableFromImpl(
01132                            dataCollect, impl
01133                          );
01134     return script;
01135   }
01136   catch (const Exception & excpt_r)
01137   {
01138     ZYPP_CAUGHT(excpt_r);
01139     ZYPP_THROW(Exception("Cannot create script object"));
01140   }
01141   return 0L;
01142 }
01143 
01144 Product::Ptr YUMSourceImpl::createProduct(
01145   Source_Ref source_r,
01146   const zypp::parser::yum::YUMProductData & parsed
01147 )
01148 {
01149   try
01150   {
01151     ResImplTraits<YUMProductImpl>::Ptr impl(new YUMProductImpl(source_r, parsed));
01152 
01153     // Collect basic Resolvable data
01154     Arch arch;
01155     if (!parsed.arch.empty())
01156       arch = Arch(parsed.arch);
01157     
01158     string name(parsed.name);
01159     std::replace(name.begin(), name.end(), ' ', '_');
01160     
01161     NVRAD dataCollect( name,
01162                        Edition( parsed.ver, parsed.rel, parsed.epoch ),
01163                        arch,
01164                        createDependencies(parsed,
01165                                           ResTraits<Product>::kind)
01166                      );
01167     Product::Ptr product = detail::makeResolvableFromImpl(
01168                              dataCollect, impl
01169                            );
01170     return product;
01171   }
01172   catch (const Exception & excpt_r)
01173   {
01174     ZYPP_CAUGHT(excpt_r);
01175     ZYPP_THROW(Exception("Cannot create product object"));
01176   }
01177   return 0L;
01178 }
01179 
01180 Patch::Ptr YUMSourceImpl::createPatch(
01181   Source_Ref source_r,
01182   const zypp::parser::yum::YUMPatchData & parsed
01183 )
01184 {
01185   try
01186   {
01187     ResImplTraits<YUMPatchImpl>::Ptr impl(new YUMPatchImpl(source_r, parsed, *this));
01188 
01189     Arch arch;
01190     if (!parsed.arch.empty())
01191       arch = Arch(parsed.arch);
01192 
01193     // Collect basic Resolvable data
01194     NVRAD dataCollect( parsed.name,
01195                        Edition( parsed.ver, parsed.rel, parsed.epoch ),
01196                        arch,
01197                        createDependencies( parsed,
01198                                            ResTraits<Patch>::kind)
01199                      );
01200     Patch::Ptr patch = detail::makeResolvableFromImpl(
01201                          dataCollect, impl
01202                        );
01203     // now process the atoms
01204     CapFactory _f;
01205     Capability cap( _f.parse(
01206                       Patch::TraitsType::kind,
01207                       parsed.name,
01208                       Rel::EQ,
01209                       Edition(parsed.ver, parsed.rel, parsed.epoch)
01210                     ));
01211 
01212     // maps name to parser data in order to find 'best' architectureC
01213     typedef std::map<std::string, shared_ptr<YUMPatchPackage> > PkgAtomsMap;
01214     PkgAtomsMap pkg_atoms;
01215 
01216     for (std::list<shared_ptr<YUMPatchAtom> >::const_iterator it
01217          = parsed.atoms.begin();
01218          it != parsed.atoms.end();
01219          it++)
01220     {
01221       switch ((*it)->atomType())
01222       {
01223         // for packages, try to find best architecture for name-version-release first (#168840)
01224         // we can't use the name alone as there might be different editions for the same name
01225         // with different architecture.
01226         // So we only choose the best architecture if name-version-edition matches (#170098)
01227 
01228       case YUMPatchAtom::Package:
01229         {
01230           shared_ptr<YUMPatchPackage> package_data
01231           = dynamic_pointer_cast<YUMPatchPackage>(*it);
01232           string atomkey( package_data->name + "-" + package_data->epoch + ":" + package_data->ver + "-" + package_data->rel );
01233 
01234           // check if atomkey is already known
01235           PkgAtomsMap::iterator pa_pos = pkg_atoms.find( atomkey );
01236           if (pa_pos != pkg_atoms.end())
01237           {
01238             try
01239             {
01240               Arch oldarch, newarch;
01241               if (!(pa_pos->second->arch.empty())) oldarch = Arch( pa_pos->second->arch );
01242               if (!(package_data->arch.empty())) newarch = Arch( package_data->arch );
01243               if (newarch.compatibleWith( getZYpp()->architecture() ) )
01244               {                 // new one is compatible (if not, we don't care)
01245 
01246                 if (!oldarch.compatibleWith( getZYpp()->architecture() )                        // old one is not compatible
01247                     || oldarch.compare( newarch ) < 0)                                  //  or compatible but worse
01248                 {
01249                   pa_pos->second = package_data;                                // new one is it !
01250                 }
01251               }
01252             }
01253             catch ( const Exception & excpt_r )
01254             {
01255               ZYPP_CAUGHT( excpt_r );
01256               ERR << "Package " << package_data->name << " in patch's atomlist has bad architecture '" << package_data->arch << "'" << endl;
01257             }
01258           }
01259           else
01260           {
01261             pkg_atoms[atomkey] = package_data;                                  // first occurence of this atomkey
01262           }
01263           break;
01264         }
01265       case YUMPatchAtom::Message:
01266         {
01267           shared_ptr<YUMPatchMessage> message_data
01268           = dynamic_pointer_cast<YUMPatchMessage>(*it);
01269           Message::Ptr message = createMessage(source_r, *message_data, patch);
01270           impl->_atoms.push_back(message);
01271           break;
01272         }
01273       case YUMPatchAtom::Script:
01274         {
01275           shared_ptr<YUMPatchScript> script_data
01276           = dynamic_pointer_cast<YUMPatchScript>(*it);
01277           Script::Ptr script = createScript(source_r, *script_data);
01278           impl->_atoms.push_back(script);
01279           break;
01280         }
01281       default:
01282         ERR << "Unknown type of atom" << endl;
01283       }
01284 #if 0                                   // atoms require their patch, why ?
01285       for (Patch::AtomList::iterator it = impl->_atoms.begin();
01286            it != impl->_atoms.end();
01287            it++)
01288       {
01289         (*it)->injectRequires(cap);
01290       }
01291 #endif
01292     }
01293 
01294     for (PkgAtomsMap::const_iterator pa_pos = pkg_atoms.begin(); pa_pos != pkg_atoms.end(); ++pa_pos)
01295     {
01296       Atom::Ptr atom = augmentPackage( source_r, *(pa_pos->second) );
01297       impl->_atoms.push_back(atom);
01298     }
01299 
01300     return patch;
01301   }
01302   catch (const Exception & excpt_r)
01303   {
01304     ZYPP_CAUGHT(excpt_r);
01305     ZYPP_THROW(Exception("Cannot create patch object"));
01306   }
01307   return 0L;
01308 }
01309 
01310 Dependencies YUMSourceImpl::createDependencies(
01311   const zypp::parser::yum::YUMObjectData & parsed,
01312   const Resolvable::Kind my_kind
01313 )
01314 {
01315   Dependencies _deps;
01316   for (std::list<YUMDependency>::const_iterator it = parsed.provides.begin();
01317        it != parsed.provides.end();
01318        it++)
01319   {
01320     _deps[Dep::PROVIDES].insert(createCapability(*it, my_kind));
01321   }
01322 
01323   for (std::list<YUMDependency>::const_iterator it = parsed.conflicts.begin();
01324        it != parsed.conflicts.end();
01325        it++)
01326   {
01327     _deps[Dep::CONFLICTS].insert(createCapability(*it, my_kind));
01328   }
01329 
01330   for (std::list<YUMDependency>::const_iterator it = parsed.obsoletes.begin();
01331        it != parsed.obsoletes.end();
01332        it++)
01333   {
01334     _deps[Dep::OBSOLETES].insert(createCapability(*it, my_kind));
01335   }
01336 
01337   for (std::list<YUMDependency>::const_iterator it = parsed.freshens.begin();
01338        it != parsed.freshens.end();
01339        it++)
01340   {
01341     _deps[Dep::FRESHENS].insert(createCapability(*it, my_kind));
01342   }
01343 
01344   for (std::list<YUMDependency>::const_iterator it = parsed.recommends.begin();
01345        it != parsed.recommends.end();
01346        it++)
01347   {
01348     _deps[Dep::RECOMMENDS].insert(createCapability(*it, my_kind));
01349   }
01350 
01351   for (std::list<YUMDependency>::const_iterator it = parsed.suggests.begin();
01352        it != parsed.suggests.end();
01353        it++)
01354   {
01355     _deps[Dep::SUGGESTS].insert(createCapability(*it, my_kind));
01356   }
01357 
01358   for (std::list<YUMDependency>::const_iterator it = parsed.supplements.begin();
01359        it != parsed.supplements.end();
01360        it++)
01361   {
01362     _deps[Dep::SUPPLEMENTS].insert(createCapability(*it, my_kind));
01363   }
01364 
01365   for (std::list<YUMDependency>::const_iterator it = parsed.enhances.begin();
01366        it != parsed.enhances.end();
01367        it++)
01368   {
01369     _deps[Dep::ENHANCES].insert(createCapability(*it, my_kind));
01370   }
01371 
01372   for (std::list<YUMDependency>::const_iterator it = parsed.prerequires.begin();
01373        it != parsed.prerequires.end();
01374        it++)
01375   {
01376     _deps[Dep::PREREQUIRES].insert(createCapability(*it, my_kind));
01377   }
01378 
01379   for (std::list<YUMDependency>::const_iterator it = parsed.requires.begin();
01380        it != parsed.requires.end();
01381        it++)
01382   {
01383     if (it->pre == "1")
01384       _deps[Dep::PREREQUIRES].insert(createCapability(*it, my_kind));
01385     else
01386       _deps[Dep::REQUIRES].insert(createCapability(*it, my_kind));
01387   }
01388 
01389   return _deps;
01390 }
01391 
01392 Dependencies YUMSourceImpl::createGroupDependencies(
01393   const zypp::parser::yum::YUMGroupData & parsed
01394 )
01395 {
01396   Dependencies _deps;
01397 
01398   for (std::list<PackageReq>::const_iterator it = parsed.packageList.begin();
01399        it != parsed.packageList.end();
01400        it++)
01401   {
01402     Dep _dep_kind = Dep::REQUIRES;
01403     if (it->type == "mandatory" || it->type == "")
01404     {
01405       _dep_kind = Dep::REQUIRES;
01406     }
01407     else if (it->type == "default")
01408     {
01409       _dep_kind = Dep::RECOMMENDS;
01410     }
01411     else if (it->type == "optional")
01412     {
01413       _dep_kind = Dep::SUGGESTS;
01414     }
01415     _deps[_dep_kind].insert(createCapability(YUMDependency(
01416                               "",
01417                               it->name,
01418                               "EQ",
01419                               it->epoch,
01420                               it->ver,
01421                               it->rel,
01422                               ""
01423                             ),
01424                             ResTraits<Package>::kind));
01425   }
01426   for (std::list<MetaPkg>::const_iterator it = parsed.grouplist.begin();
01427        it != parsed.grouplist.end();
01428        it++)
01429   {
01430     Dep _dep_kind = Dep::REQUIRES;
01431     if (it->type == "mandatory" || it->type == "")
01432     {
01433       _dep_kind = Dep::REQUIRES;
01434     }
01435     else if (it->type == "default")
01436     {
01437       _dep_kind = Dep::RECOMMENDS;
01438     }
01439     else if (it->type == "optional")
01440     {
01441       _dep_kind = Dep::SUGGESTS;
01442     }
01443     _deps[_dep_kind].insert(createCapability(YUMDependency(
01444                               "",
01445                               it->name,
01446                               "",
01447                               "",
01448                               "",
01449                               "",
01450                               ""
01451                             ),
01452                             ResTraits<Selection>::kind));
01453   }
01454   return _deps;
01455 }
01456 
01457 Capability YUMSourceImpl::createCapability(const YUMDependency & dep,
01458     const Resolvable::Kind & my_kind)
01459 {
01460   CapFactory _f;
01461   Resolvable::Kind _kind = dep.kind == "" ? my_kind : Resolvable::Kind(dep.kind);
01462   Capability cap;
01463   if ( ! dep.isEncoded() )
01464   {
01465     cap = _f.parse(
01466             _kind,
01467             dep.name,
01468             Rel(dep.flags),
01469             Edition(dep.ver, dep.rel, dep.epoch)
01470           );
01471   }
01472   else
01473   {
01474     cap = _f.parse( _kind, dep.encoded );
01475   }
01476   return cap;
01477 }
01478 
01479 } // namespace yum
01481 } // namespace source
01484 } // namespace zypp

Generated on Thu Apr 24 02:24:57 2008 for zypp by  doxygen 1.4.6