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

Generated on Fri Jul 4 16:57:59 2008 for zypp by  doxygen 1.5.0