SuseTagsImpl.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 #include <fstream>
00014 
00015 #include <boost/bind.hpp>
00016 
00017 #include "zypp/base/Logger.h"
00018 #include "zypp/base/Exception.h"
00019 #include "zypp/base/Gettext.h"
00020 
00021 #include "zypp/PathInfo.h"
00022 #include "zypp/Digest.h"
00023 #include "zypp/CheckSum.h"
00024 #include "zypp/KeyRing.h"
00025 
00026 #include "zypp/parser/ParserProgress.h"
00027 #include "zypp/source/susetags/SuseTagsImpl.h"
00028 #include "zypp/source/susetags/PackagesParser.h"
00029 #include "zypp/source/susetags/PackagesLangParser.h"
00030 #include "zypp/source/susetags/SelectionTagFileParser.h"
00031 #include "zypp/source/susetags/PatternTagFileParser.h"
00032 #include "zypp/source/susetags/ProductMetadataParser.h"
00033 
00034 #include "zypp/SourceFactory.h"
00035 #include "zypp/ZYppCallbacks.h"
00036 #include "zypp/ZYppFactory.h"
00037 
00038 using std::endl;
00039 
00041 namespace zypp
00042 { 
00043 
00044 namespace source
00045 { 
00046 
00047 namespace susetags
00048 { 
00049 
00050 
00051 struct NullParseProgress
00052 {
00053   NullParseProgress( Pathname /*file*/ )
00054   //: _file(file)
00055   {}
00056   void operator()( int /*p*/ )
00057   {}
00058   //Pathname _file;
00059 };
00060 
00061 struct SourceEventHandler
00062 {
00063   SourceEventHandler( callback::SendReport<SourceReport> &report ) : _report(report)
00064   {}
00065 
00066   void operator()( int p )
00067   {
00068     _report->progress(p);
00069   }
00070 
00071   callback::SendReport<SourceReport> &_report;
00072 };
00073 
00074 
00075 bool SuseTagsProber::operator()()
00076 {
00077   MIL << "Probing for YaST source..." << std::endl;
00078   bool result = false;
00079   media::MediaManager mm;
00080   result = mm.doesFileExist(_media_id, _path + Pathname("/content"));
00081 
00082   if ( result )
00083   {
00084     MIL << "YaST source detected..." << std::endl;
00085     return true;
00086   }
00087 
00088   MIL << "Not a YaST source..." << std::endl;
00089   return false;
00090 }
00091 
00093 //
00094 //      METHOD NAME : SuseTagsImpl::SuseTagsImpl
00095 //      METHOD TYPE : Ctor
00096 //
00097 SuseTagsImpl::SuseTagsImpl()
00098 {}
00099 
00100 const Pathname SuseTagsImpl::metadataRoot() const
00101 {
00102   return _cache_dir.empty() ? tmpMetadataDir() : _cache_dir;
00103 }
00104 
00105 const Pathname SuseTagsImpl::contentFile() const
00106 {
00107   return metadataRoot() + "/DATA" + "content";
00108 }
00109 
00110 const Pathname SuseTagsImpl::contentFileSignature() const
00111 {
00112   return metadataRoot() + "/DATA" + "content.asc";
00113 }
00114 
00115 const Pathname SuseTagsImpl::contentFileKey() const
00116 {
00117   return metadataRoot() + "/DATA" + "/content.key";
00118 }
00119 
00120 const Pathname SuseTagsImpl::mediaFile() const
00121 {
00122   return metadataRoot() + "MEDIA/media.1/media";
00123 }
00124 
00125 const Pathname SuseTagsImpl::descrDir() const
00126 {
00127   return metadataRoot() + "DATA/descr";
00128 }
00129 
00130 const Pathname SuseTagsImpl::dataDir() const
00131 {
00132   return _data_dir;
00133 }
00134 
00135 const Pathname SuseTagsImpl::mediaDescrDir() const
00136 {
00137   return _media_descr_dir;
00138 }
00139 
00140 std::set<zypp::Resolvable::Kind>
00141   SuseTagsImpl::resolvableKinds() const
00142   {
00143     std::set<zypp::Resolvable::Kind> kinds;
00144 
00145     kinds.insert( ResTraits<zypp::Product>::kind );
00146 
00147     if ( PathInfo(descrDir() + "patterns").isExist() )
00148       kinds.insert( ResTraits<zypp::Pattern>::kind );
00149 
00150     if ( PathInfo(descrDir() + "selections").isExist() )
00151       kinds.insert( ResTraits<zypp::Selection>::kind );
00152 
00153     if ( PathInfo(descrDir() + "packages").isExist() )
00154       kinds.insert( ResTraits<zypp::Package>::kind );
00155 
00156     return kinds;
00157   }
00158 
00159 bool SuseTagsImpl::downloadNeeded(const Pathname & localdir)
00160 {
00161   Pathname new_media_file;
00162   try
00163   {
00164     new_media_file = tryToProvideFile("media.1/media");
00165   }
00166   catch ( const Exception &e )
00167   {
00168     MIL << "media file used to determine if source changed not found. Assuming refresh needed." << std::endl;
00169     return true;
00170   }
00171 
00172   // before really download all the data and init the cache, check
00173   // if the source has really changed, otherwise, make it quick
00174   Pathname cached_media_file = localdir + "/MEDIA/media.1/media";
00175   if ( cacheExists() )
00176   {
00177     CheckSum old_media_file_checksum( "SHA1", filesystem::sha1sum(cached_media_file));
00178     CheckSum new_media_file_checksum( "SHA1", filesystem::sha1sum(new_media_file));
00179     if ( (new_media_file_checksum == old_media_file_checksum) && (!new_media_file_checksum.empty()) && (! old_media_file_checksum.empty()))
00180     {
00181       MIL << "susetags source " << alias() << " has not changed. Refresh completed. SHA1 of media.1/media file is " << old_media_file_checksum.checksum() << std::endl;
00182       return false;
00183     }
00184   }
00185   MIL << "susetags source " << alias() << " has changed. Refresh needed." << std::endl;
00186   return true;
00187 }
00188 
00189 void SuseTagsImpl::readMediaFile(const Pathname &p)
00190 {
00191   media::MediaManager media_mgr;
00192 
00193   std::ifstream pfile( p.asString().c_str() );
00194   if ( pfile.bad() )
00195   {
00196     ZYPP_THROW(SourceIOException("Can't read media.1/media") );
00197   }
00198   _media_vendor = str::getline( pfile, str::TRIM );
00199   if ( pfile.fail() )
00200   {
00201     ZYPP_THROW(SourceIOException("Can't read media.1/media") );
00202   }
00203   _media_id = str::getline( pfile, str::TRIM );
00204   if ( pfile.fail() )
00205   {
00206     ZYPP_THROW(SourceIOException("Can't read media.1/media") );
00207   }
00208   std::string media_count_str = str::getline( pfile, str::TRIM );
00209   if ( pfile.fail() )
00210   {
00211     ZYPP_THROW(SourceIOException("Can't read media.1/media") );
00212   }
00213   _media_count = str::strtonum<unsigned>( media_count_str );
00214 
00215   try
00216   {
00217     MIL << "Adding susetags media verifier: " << endl;
00218     MIL << "Vendor: " << _media_vendor << endl;
00219     MIL << "Media ID: " << _media_id << endl;
00220 
00221     // get media ID, but not attaching
00222     media::MediaAccessId _media = _media_set->getMediaAccessId(1, true);
00223     media_mgr.delVerifier(_media);
00224     media_mgr.addVerifier(_media, media::MediaVerifierRef(
00225                             new SourceImpl::Verifier ( _media_vendor, _media_id) ));
00226   }
00227   catch (const Exception & excpt_r)
00228   {
00229 #warning FIXME: If media data is not set, verifier is not set. Should the media
00230     ZYPP_CAUGHT(excpt_r);
00231     WAR << "Verifier not found" << endl;
00232   }
00233 }
00234 
00235 TmpDir SuseTagsImpl::downloadMetadata()
00236 {
00237   resetMediaVerifier();
00238 
00239   TmpDir tmpdir;
00240   MIL << "Downloading metadata to " << tmpdir.path() << std::endl;
00241 
00242   Pathname local_dir = tmpdir.path();
00243 
00244   // (#163196)
00245   // before we used _descr_dir, which is is wrong if we
00246   // store metadata already running from cache
00247   // because it points to a local file and not
00248   // to the media. So use the original media descr_dir.
00249   Pathname media_src;
00250   Pathname descr_src;
00251   Pathname content_src;
00252 
00253   // init the cache structure
00254   if (0 != assert_dir(local_dir + "DATA", 0755))
00255     ZYPP_THROW(SourceIOException("Cannot create /DATA directory in download dir." + local_dir.asString()));
00256   if (0 != assert_dir(local_dir + "MEDIA", 0755))
00257     ZYPP_THROW(SourceIOException("Cannot create /MEDIA directory in download dir." + local_dir.asString()));
00258   if (0 != assert_dir(local_dir + "PUBLICKEYS", 0755))
00259     ZYPP_THROW(SourceIOException("Cannot create /PUBLICKEYS directory in download dir." + local_dir.asString()));
00260 
00261   try
00262   {
00263     media_src = provideDirTree("media.1");
00264   }
00265   catch (Exception &e)
00266   {
00267     ZYPP_THROW(SourceIOException("Can't provide " + _path.asString() + "/media.1 from " + url().asString() ));
00268   }
00269 
00270   if ( filesystem::copy_dir(media_src, local_dir + "MEDIA") != 0 )
00271     ZYPP_THROW(SourceIOException("Unable to copy media directory to " + (local_dir + "/MEDIA").asString()));
00272 
00273   MIL << "cached media directory" << std::endl;
00274 
00275   // media is provided, now we can install a media verifier.
00276   readMediaFile(local_dir + "/MEDIA/media.1/media");
00277 
00278   try
00279   {
00280     content_src = provideFile( _path + "content");
00281   }
00282   catch (Exception &e)
00283   {
00284     ZYPP_THROW(SourceIOException("Can't provide " + _path.asString() + "/content from " + url().asString() ));
00285   }
00286 
00287   if ( filesystem::copy(content_src, local_dir + "DATA/content") != 0)
00288     ZYPP_THROW(SourceIOException("Unable to copy the content file to " + (local_dir + "DATA/content").asString()));
00289 
00290   // get the list of cache keys
00291   std::list<std::string> files;
00292   dirInfo( 1, files, _path);
00293 
00294   // cache all the public keys
00295   for ( std::list<std::string>::const_iterator it = files.begin(); it != files.end(); ++it)
00296   {
00297     ZYpp::Ptr z = getZYpp();
00298 
00299     std::string filename = *it;
00300     if ( filename.substr(0, 10) == "gpg-pubkey" )
00301     {
00302       Pathname key_src;
00303       try
00304       {
00305         key_src = provideFile(_path + filename);
00306       }
00307       catch (Exception &e)
00308       {
00309         ZYPP_THROW(SourceIOException("Can't provide " + (_path + filename).asString() + " from " + url().asString() ));
00310       }
00311 
00312       MIL << "Trying to cache " << key_src << std::endl;
00313 
00314       if ( filesystem::copy(key_src, local_dir + "PUBLICKEYS/" + filename) != 0 )
00315         ZYPP_THROW(SourceIOException("Unable to copy key " + key_src.asString() + " to " + (local_dir + "PUBLICKEYS").asString()));
00316 
00317       MIL << "cached " << filename << std::endl;
00318       z->keyRing()->importKey(local_dir + "PUBLICKEYS/" + filename, false);
00319     }
00320     else if ( (filename == "content.asc") || (filename == "content.key"))
00321     {
00322       Pathname src_data;
00323       try
00324       {
00325         src_data = provideFile(_path + filename);
00326       }
00327       catch (Exception &e)
00328       {
00329         ZYPP_THROW(SourceIOException("Can't provide " + filename + " from " + url().asString() + ". File was listed as available."));
00330       }
00331 
00332       if ( filesystem::copy( src_data, local_dir + "DATA/" + filename) != 0 )
00333         ZYPP_THROW(SourceIOException("Unable to copy " + filename + " to " + (local_dir + "/DATA").asString()));
00334 
00335       if ( filename == "content.key" )
00336         z->keyRing()->importKey(local_dir + "DATA/content.key", false);
00337 
00338       MIL << "cached " << filename << std::endl;
00339     }
00340   }
00341 
00342   // verify it is a valid content file
00343   ZYpp::Ptr z = getZYpp();
00344   MIL << "SuseTags source: checking 'content' file vailidity using digital signature.." << endl;
00345   // verify the content file
00346   bool valid = z->keyRing()->verifyFileSignatureWorkflow( local_dir + "/DATA/content", (path() + "content").asString() + " (" + url().asString() + ")", local_dir + "/DATA/content.asc");
00347 
00348   // the source is not valid and the user did not want to continue
00349   if (!valid)
00350     ZYPP_THROW (SourceUserRejectedException( "Error. Source signature does not validate and user does not want to continue. "));
00351 
00352   // now we have the content file copied, we need to init data and descrdir from the product
00353   readContentFile(local_dir + "/DATA/content");
00354 
00355   // make sure a local descr dir exists
00356   if ( assert_dir( local_dir + "/DATA/descr") != 0 )
00357     ZYPP_THROW (SourceIOException( "Error. Can't create local descr directory. "));
00358 
00359   // we can get the list of files in description dir in 2 ways
00360   // from the checksum list, or ls'ing the dir via directory.yast
00361   if ( ! _prodImpl->_descr_files_checksums.empty() )
00362   {
00363     // iterate through all available checksums
00364     for ( std::map<std::string, CheckSum>::const_iterator it = _prodImpl->_descr_files_checksums.begin(); it != _prodImpl->_descr_files_checksums.end(); ++it)
00365     {
00366       std::string key = it->first;
00367       getPossiblyCachedMetadataFile( mediaDescrDir() + key, local_dir + "/DATA/descr" + key, _cache_dir + "/DATA/descr" + key,  _prodImpl->_descr_files_checksums[key] );
00368     }
00369   }
00370   else
00371   {
00372     // in case we dont have list of valid files in content file, we just glob for them
00373     std::list<std::string> descr_dir_file_list;
00374     try
00375     {
00376       dirInfo( 1, descr_dir_file_list, mediaDescrDir());
00377     }
00378     catch (Exception &e)
00379     {
00380       ZYPP_THROW(SourceIOException("Can't list description directory content from " + url().asString() ));
00381     }
00382 
00383     for ( std::list<std::string>::const_iterator it = descr_dir_file_list.begin(); it != descr_dir_file_list.end(); ++it)
00384     {
00385       std::string filename = *it;
00386       getPossiblyCachedMetadataFile( mediaDescrDir() + filename, local_dir + "/DATA/descr" + filename, _cache_dir + "/DATA/descr" + filename, CheckSum() );
00387     }
00388   }
00389 
00390   return tmpdir;
00391 }
00392 
00393 void SuseTagsImpl::initCacheDir(const Pathname & cache_dir_r)
00394 {
00395   // refuse to use stupid paths as cache dir
00396   if (cache_dir_r == Pathname("/") )
00397     ZYPP_THROW(SourceIOException("I refuse to use / as cache dir"));
00398 
00399   if (0 != assert_dir(cache_dir_r.dirname(), 0700))
00400     ZYPP_THROW(SourceIOException("Cannot create cache directory" + cache_dir_r.asString()));
00401 
00402   filesystem::clean_dir(cache_dir_r);
00403   filesystem::mkdir(cache_dir_r + "DATA");
00404   filesystem::mkdir(cache_dir_r + "MEDIA");
00405   //filesystem::mkdir(cache_dir_r + "DESCRIPTION");
00406   filesystem::mkdir(cache_dir_r + "PUBLICKEYS");
00407 }
00408 
00409 void SuseTagsImpl::storeMetadata(const Pathname & cache_dir_r)
00410 {
00411   if ( !_cache_dir.empty() )
00412   {
00413     saveMetadataTo(cache_dir_r);
00414   }
00415   else
00416   {
00417     // no previous cache, use the data read temporarely
00418     copyLocalMetadata(tmpMetadataDir(), cache_dir_r);
00419   }
00420 
00421   MIL << "Metadata saved in " << cache_dir_r << ". Setting as cache." << std::endl;
00422   _cache_dir = cache_dir_r;
00423 }
00424 
00425 void SuseTagsImpl::saveMetadataTo(const Pathname & dir_r)
00426 {
00427   TmpDir download_tmp_dir;
00428 
00429   bool need_to_refresh = true;
00430   try
00431   {
00432     need_to_refresh = downloadNeeded(dir_r);
00433   }
00434   catch (Exception &e)
00435   {
00436     ZYPP_THROW(SourceIOException("Can't check if source has changed or not. Aborting refresh."));
00437   }
00438 
00439   if ( need_to_refresh )
00440   {
00441     MIL << "SuseTags source " << alias() << " has changed since last download. Re-reading metadata into " << dir_r << endl;
00442   }
00443   else
00444   {
00445     MIL << "SUSEtags source " << alias() << " has not changed. Refresh completed. timestamp of media file is  the same." << std::endl;
00446     return;
00447   }
00448 
00449   download_tmp_dir = downloadMetadata();
00450   copyLocalMetadata(download_tmp_dir, dir_r);
00451 
00452   // download_tmp_dir go out of scope now but it is ok as we already copied the content.
00453 }
00454 
00455 bool SuseTagsImpl::cacheExists() const
00456 {
00457   MIL << "Checking if source cache exists in "<< _cache_dir << std::endl;
00458   bool exists = true;
00459 
00460   bool data_exists = PathInfo(_cache_dir + "DATA").isExist();
00461   exists = exists && data_exists;
00462 
00463   //bool description_exists = PathInfo(_cache_dir + "DESCRIPTION").isExist();
00464   //exists = exists && description_exists;
00465 
00466   bool media_exists = PathInfo(_cache_dir + "MEDIA").isExist();
00467   exists = exists && media_exists;
00468 
00469   bool media_file_exists = PathInfo(_cache_dir + "MEDIA/media.1/media").isExist();
00470   exists = exists && media_file_exists;
00471 
00472   MIL << "DATA " << (data_exists ? "exists" : "not found") << ", MEDIA " << (media_exists ? "exists" : "not found") << ", MEDIA/media.1/media " <<  (media_file_exists ? "exists" : "not found") << std::endl;
00473   return exists;
00474 }
00475 
00476 void SuseTagsImpl::factoryInit()
00477 {
00478   bool cache = cacheExists();
00479   if ( cache )
00480   {
00481     MIL << "Cached metadata found in [" << _cache_dir << "]." << endl;
00482     // we need to read the content file to init data dir and descr dir
00483     // in the media.
00484     readMediaFile(mediaFile());
00485     readContentFile(contentFile());
00486 
00487     if ( autorefresh() )
00488       storeMetadata(_cache_dir);
00489   }
00490   else
00491   {
00492     if ( _cache_dir.empty() || !PathInfo(_cache_dir).isExist() )
00493     {
00494       MIL << "Cache dir not set. Downloading to temp dir: " << tmpMetadataDir() << std::endl;
00495       // as we have no local dir set we use a tmp one, but we use a member variable because
00496       // it cant go out of scope while the source exists.
00497       saveMetadataTo(tmpMetadataDir());
00498     }
00499     else
00500     {
00501       MIL << "Cached metadata not found in [" << _cache_dir << "]. Will download." << std::endl;
00502       saveMetadataTo(_cache_dir);
00503     }
00504   }
00505 
00506   if ( alias().empty() )
00507     setAlias(_product->summary());
00508 
00509   MIL << "SUSETags source initialized." << std::endl;
00510   MIL << "   Url      : " << url() << std::endl;
00511   MIL << "   alias    : " << alias() << std::endl;
00512   MIL << "   Path     : " << path() << std::endl;
00513   MIL << "   Data     : " << dataDir() << std::endl;
00514   MIL << "   Metadata : " << metadataRoot() << (_cache_dir.empty() ? " [TMP]" : " [CACHE]") << std::endl;
00515   MIL << "   N-Media  : " << numberOfMedia() << std::endl;
00516 }
00517 
00518 void SuseTagsImpl::createResolvables(Source_Ref source_r)
00519 {
00520   provideProducts ( source_r, _store );
00521   providePackages ( source_r, _store );
00522   provideSelections ( source_r, _store );
00523   providePatterns ( source_r, _store );
00524 }
00525 
00526 const std::list<Pathname> SuseTagsImpl::publicKeys()
00527 {
00528   std::list<std::string> files;
00529   std::list<Pathname> paths;
00530 
00531   MIL << "Reading public keys..." << std::endl;
00532   filesystem::readdir(files, metadataRoot() + "PUBLICKEYS");
00533   for ( std::list<std::string>::const_iterator it = files.begin(); it != files.end(); ++it)
00534     paths.push_back(Pathname(*it));
00535 
00536   MIL << "read " << files.size() << " keys from cache " << metadataRoot() << std::endl;
00537   return paths;
00538 }
00539 
00540 ResStore SuseTagsImpl::createResolvablesByKind(Source_Ref source_r, Resolvable::Kind kind)
00541 {
00542   ResStore store;
00543 
00544   if ( kind == ResTraits<Product>::kind )
00545     provideProducts ( source_r, store );
00546   else if ( kind == ResTraits<Package>::kind )
00547     providePackages ( source_r, store );
00548   else if ( kind == ResTraits<Selection>::kind )
00549     provideSelections ( source_r, store );
00550   else if ( kind == ResTraits<Pattern>::kind )
00551     providePatterns ( source_r, store );
00552   return store;
00553 }
00554 
00556 //
00557 //      METHOD NAME : SuseTagsImpl::~SuseTagsImpl
00558 //      METHOD TYPE : Dtor
00559 //
00560 SuseTagsImpl::~SuseTagsImpl()
00561 {}
00562 
00563 Pathname SuseTagsImpl::sourceDir( const std::string & dir )
00564 {
00565   return Pathname( _data_dir + Pathname( dir ) + "/");
00566 }
00567 
00568 media::MediaVerifierRef SuseTagsImpl::verifier(media::MediaNr media_nr)
00569 {
00570   return media::MediaVerifierRef(
00571            new SourceImpl::Verifier (_media_vendor, _media_id, media_nr));
00572 }
00573 
00574 unsigned SuseTagsImpl::numberOfMedia(void) const
00575 {
00576   return _media_count;
00577 }
00578 
00579 std::string SuseTagsImpl::vendor (void) const
00580 {
00581   return _prodImpl->vendor();
00582 }
00583 
00584 std::string SuseTagsImpl::unique_id (void) const
00585 {
00586   return _media_id;
00587 }
00588 
00589 Date SuseTagsImpl::timestamp() const
00590 {
00591   return PathInfo(contentFile()).mtime();
00592 }
00593 
00594 void SuseTagsImpl::readContentFile(const Pathname &content_file)
00595 {
00596   SourceFactory factory;
00597   try
00598   {
00599     DBG << "Going to parse content file " << content_file << endl;
00600 
00601     ProductMetadataParser p;
00602     p.parse( content_file, factory.createFrom(this) );
00603     _product = p.result;
00604 
00605     // data dir is the same, it is determined by the content file
00606     _data_dir = _path + p.prodImpl->_data_dir;
00607     // description dir also changes when using cache
00608     _media_descr_dir = _path + p.prodImpl->_description_dir;
00609 
00610     MIL << "Read product: " << _product->summary() << endl;
00611 
00612     _prodImpl = p.prodImpl;
00613   }
00614   catch ( const Exception & e )
00615   {
00616     ZYPP_THROW (SourceMetadataException("Cannot parse content file: " + e.msg()));
00617   }
00618 }
00619 
00620 void SuseTagsImpl::provideProducts(Source_Ref source_r, ResStore &store)
00621 {
00622   MIL << "Adding product: " << _product->summary() << " to the store" << endl;
00623   store.insert( _product );
00624 }
00625 
00626 void SuseTagsImpl::providePackages(Source_Ref source_r, ResStore &store)
00627 {
00628   Pathname p = descrDir() + "packages";
00629 
00630   //verifyFile( p, "packages");
00631 
00632   DBG << "Going to parse " << p << endl;
00633 
00634   parser::ParserProgress::Ptr progress;
00635   //progress.reset( new parser::ParserProgress(npp) );
00636 
00637   callback::SendReport<SourceReport> report;
00638   SourceEventHandler npp(report);
00639 
00640   progress.reset( new parser::ParserProgress( npp ) );
00641   report->start( selfSourceRef(), _("Reading packages file") );
00642 
00643   PkgContent content;
00644 
00645   try
00646   {
00647     content = parsePackages( progress, source_r, this, p );
00648   }
00649   catch ( const Exception &e )
00650   {
00651     report->finish( selfSourceRef(), _("Reading packages file"), source::SourceReport::INVALID, e.msg() );
00652     ZYPP_THROW(SourceMetadataException("Can't parse packages file: " + e.msg()));
00653   }
00654   report->finish( selfSourceRef(), _("Reading packages file"), source::SourceReport::NO_ERROR, "" );
00655 
00656 #warning Should use correct locale and locale fallback list
00657   // note, this locale detection has nothing to do with translated text.
00658   // basically we are only loading the data we need. Instead of parsing all
00659   // package description we fill the TranslatedText properties only
00660   // with the detected locale.
00661 
00662   ZYpp::Ptr z = getZYpp();
00663   Locale lang( z->getTextLocale() );
00664 
00665   std::string packages_lang_prefix( "packages." );
00666   std::string packages_lang_name;
00667 
00668   // get the list of available packages.X trsnlation files
00669   std::list<std::string> all_files;
00670   filesystem::readdir(all_files, descrDir());
00671 
00672   std::list<std::string> _pkg_translations;
00673   for ( std::list<std::string>::const_iterator it = all_files.begin(); it != all_files.end(); ++it)
00674   {
00675     if ( ((*it).substr(0, 9) == "packages." ) && ((*it) != "packages.DU" ))
00676     {
00677       MIL << *it << " available as package data translation." << std::endl;
00678       _pkg_translations.push_back(*it);
00679     }
00680   }
00681 
00682   // find the most apropiate file
00683   bool trymore = true;
00684   while ( (lang != Locale()) && trymore )
00685   {
00686     packages_lang_name = packages_lang_prefix + lang.code();
00687     MIL << "Translation candidate: " << lang.code() << std::endl;
00688     try
00689     {
00690       // only provide it if it exists
00691       if ( find( _pkg_translations.begin(), _pkg_translations.end(), packages_lang_name ) != _pkg_translations.end() )
00692       {
00693         p = descrDir() + packages_lang_name;
00694         if ( PathInfo(p).isExist() )
00695         {
00696           MIL << packages_lang_name << " found" << std::endl;
00697           DBG << "Going to parse " << p << endl;
00698           //verifyFile( p, packages_lang_name);
00699 
00700           SourceEventHandler lang_progress_handler(report);
00701           progress.reset( new parser::ParserProgress( lang_progress_handler ) );
00702           
00703           // TranslatorExplanation %s = language name
00704           report->start( selfSourceRef(), str::form(_("Reading translation: %s"), packages_lang_name.c_str()) );
00705           parsePackagesLang( progress, this, p, lang, content );
00706           trymore = false;
00707           // TranslatorExplanation %s = language name
00708           report->finish( selfSourceRef(), str::form(_("Reading translation: %s"), packages_lang_name.c_str()), source::SourceReport::NO_ERROR, "" );
00709         }
00710         else
00711         {
00712           ERR << packages_lang_name << " can't be provided, even if it should" << endl;
00713         }
00714       }
00715       else
00716       {
00717         MIL << "Skipping translation candidate " << packages_lang_name << " (not present in media)" << endl;
00718       }
00719     }
00720     catch ( const Exception &e )
00721     {
00722       report->finish( selfSourceRef(), str::form(_("Reading translation: %s"), packages_lang_name.c_str()), source::SourceReport::INVALID, e.msg() );
00723       ZYPP_CAUGHT(e);
00724     }
00725     lang = lang.fallback();
00726   }
00727 
00728   MIL << _package_data.size() << " packages holding real data" << std::endl;
00729   MIL << content.size() << " packages parsed" << std::endl;
00730 
00731   int counter =0;
00732   for ( std::map<NVRA, DefaultFalseBool>::const_iterator it = _is_shared.begin(); it != _is_shared.end(); ++it)
00733   {
00734     if ( it->second)
00735       counter++;
00736   }
00737 
00738   MIL << counter << " packages sharing data" << std::endl;
00739 
00740 
00741   PkgDiskUsage du;
00742   try
00743   {
00744     p = descrDir() +  + "packages.DU";
00745     //verifyFile( p, "packages.DU");
00746     parser::ParserProgress::Ptr progress;
00747     NullParseProgress npp(p);
00748     progress.reset( new parser::ParserProgress(npp) );
00749     du = parsePackagesDiskUsage(progress, p);
00750   }
00751   catch (Exception & excpt_r)
00752   {
00753     WAR << "Problem trying to parse the disk usage info" << endl;
00754   }
00755 
00756   for (PkgContent::const_iterator it = content.begin(); it != content.end(); ++it)
00757   {
00758     it->second->_diskusage = du[it->first /* NVRAD */];
00759     Package::Ptr pkg = detail::makeResolvableFromImpl( it->first, it->second );
00760     store.insert( pkg );
00761 
00762     //MIL << "Package " << pkg->summary() << std::endl;
00763     //MIL << "        " << pkg->description() << std::endl;
00764     //MIL << "----------------------------------" << std::endl;
00765 
00766   }
00767   DBG << "SuseTagsImpl (fake) from " << p << ": "
00768   << content.size() << " packages" << endl;
00769 }
00770 
00771 void SuseTagsImpl::provideSelections(Source_Ref source_r, ResStore &store)
00772 {
00773   Pathname p;
00774 
00775   bool file_found = true;
00776 
00777   // parse selections
00778   p = descrDir() + "selections";
00779   if ( ! PathInfo(p).isExist() )
00780   {
00781     MIL << p << " not found." << endl;
00782     file_found = false;
00783   }
00784 
00785   if (file_found)
00786   {
00787     //verifyFile( p, "selections");
00788     std::ifstream sels (p.asString().c_str());
00789 
00790     while (sels && !sels.eof())
00791     {
00792       std::string selfile;
00793       getline(sels,selfile);
00794 
00795       if (selfile.empty() ) continue;
00796       DBG << "Going to parse selection " << selfile << endl;
00797 
00798       Pathname file = descrDir() + selfile;
00799       //verifyFile( file, selfile);
00800 
00801       MIL << "Selection file to parse " << file << endl;
00802       parser::ParserProgress::Ptr progress;
00803       NullParseProgress npp(file);
00804       progress.reset( new parser::ParserProgress(npp) );
00805       Selection::Ptr sel( parseSelection( progress, source_r, file ) );
00806 
00807       if (sel)
00808       {
00809         DBG << "Selection:" << sel << endl;
00810         store.insert( sel );
00811         DBG << "Parsing of " << file << " done" << endl;
00812       }
00813       else
00814       {
00815         DBG << "Parsing of " << file << " failed" << endl;
00816       }
00817 
00818 
00819     }
00820   }
00821 }
00822 
00823 void SuseTagsImpl::providePatterns(Source_Ref source_r, ResStore &store)
00824 {
00825   Pathname p;
00826 
00827   // parse patterns
00828   bool file_found = true;
00829 
00830   p = descrDir() + "patterns";
00831   if ( ! PathInfo(p).isExist() )
00832   {
00833     MIL << p << " not found." << endl;
00834     file_found = false;
00835   }
00836 
00837   if ( file_found )
00838   {
00839     //verifyFile( p, "patterns");
00840     std::ifstream pats (p.asString().c_str());
00841 
00842     while (pats && !pats.eof())
00843     {
00844       std::string patfile;
00845       getline(pats,patfile);
00846 
00847       if (patfile.empty() ) continue;
00848 
00849       DBG << "Going to parse pattern " << patfile << endl;
00850 
00851       Pathname file = descrDir() + patfile;
00852 
00853       MIL << "Pattern file to parse " << file << endl;
00854       parser::ParserProgress::Ptr progress;
00855       NullParseProgress npp(file);
00856       progress.reset( new parser::ParserProgress(npp) );
00857       Pattern::Ptr pat( parsePattern( progress, source_r, file ) );
00858 
00859       if (pat)
00860       {
00861         DBG << "Pattern:" << pat << endl;
00862         _store.insert( pat );
00863         DBG << "Parsing of " << file << " done" << endl;
00864       }
00865       else
00866       {
00867         DBG << "Parsing of " << file << " failed" << endl;
00868       }
00869     }
00870   }
00871 }
00872 
00874 //
00875 //      METHOD NAME : SuseTagsImpl::dumpOn
00876 //      METHOD TYPE : std::ostream &
00877 //
00878 std::ostream & SuseTagsImpl::dumpOn( std::ostream & str ) const
00879 {
00880   return SourceImpl::dumpOn( str );
00881 }
00882 
00884 } // namespace susetags
00887 } // namespace source
00890 } // namespace zypp

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