00001
00002
00003
00004
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 )
00054
00055 {}
00056 void operator()( int )
00057 {}
00058
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
00139
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
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
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
00229
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
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
00314
00315
00316
00317
00318 Pathname media_src;
00319 Pathname descr_src;
00320 Pathname content_src;
00321
00322
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
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
00360 std::list<std::string> files;
00361 dirInfo( 1, files, _path);
00362
00363
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
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
00394 MIL << "SuseTags source: checking 'content' file vailidity using digital signature.." << endl;
00395
00396 bool valid = z->keyRing()->verifyFileSignatureWorkflow( local_dir + "/DATA/content", (path() + "content").asString() + " (" + url().asString() + ")", local_dir + "/DATA/content.asc");
00397
00398
00399 if (!valid)
00400 ZYPP_THROW (SourceUserRejectedException( "Error. Source signature does not validate and user does not want to continue. "));
00401
00402
00403 readContentFile(local_dir + "/DATA/content");
00404
00405
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
00428 if ( assert_dir( local_dir + "/DATA/descr") != 0 )
00429 ZYPP_THROW (SourceIOException( "Error. Can't create local descr directory. "));
00430
00431
00432
00433 if ( ! _prodImpl->_descr_files_checksums.empty() )
00434 {
00435
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
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
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
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
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
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
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
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
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
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
00560
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
00579
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
00592
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
00654
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
00702 _data_dir = _path + p.prodImpl->_data_dir;
00703
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
00727
00728 DBG << "Going to parse " << p << endl;
00729
00730 parser::ParserProgress::Ptr progress;
00731
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
00754
00755
00756
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
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
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
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
00795
00796 SourceEventHandler lang_progress_handler(report);
00797 progress.reset( new parser::ParserProgress( lang_progress_handler ) );
00798
00799
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
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
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 ];
00855 Package::Ptr pkg = detail::makeResolvableFromImpl( it->first, it->second );
00856 store.insert( pkg );
00857
00858
00859
00860
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
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
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
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
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
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
00972
00973
00974 std::ostream & SuseTagsImpl::dumpOn( std::ostream & str ) const
00975 {
00976 return SourceImpl::dumpOn( str );
00977 }
00978
00980 }
00983 }
00986 }