libzypp 8.13.6

RepoInfo.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 #include <vector>
00014 
00015 #include "zypp/base/Logger.h"
00016 #include "zypp/base/DefaultIntegral.h"
00017 #include "zypp/parser/xml/XmlEscape.h"
00018 
00019 #include "zypp/RepoInfo.h"
00020 #include "zypp/repo/RepoInfoBaseImpl.h"
00021 #include "zypp/repo/RepoMirrorList.h"
00022 #include "zypp/ExternalProgram.h"
00023 #include "zypp/media/MediaAccess.h"
00024 
00025 using namespace std;
00026 using zypp::xml::escape;
00027 
00029 namespace zypp
00030 { 
00031 
00033   //
00034   //    CLASS NAME : RepoInfo::Impl
00035   //
00037   struct RepoInfo::Impl : public repo::RepoInfoBase::Impl
00038   {
00039     Impl()
00040       : repo::RepoInfoBase::Impl()
00041       , gpgcheck(indeterminate)
00042       , keeppackages(indeterminate)
00043       , type(repo::RepoType::NONE_e)
00044       , emptybaseurls(false)
00045     {}
00046 
00047     ~Impl()
00048     {}
00049 
00050   public:
00051     static const unsigned defaultPriority = 99;
00052 
00053     void setProbedType( const repo::RepoType & t ) const
00054     {
00055       if ( type == repo::RepoType::NONE
00056            && t != repo::RepoType::NONE )
00057       {
00058         // lazy init!
00059         const_cast<Impl*>(this)->type = t;
00060       }
00061     }
00062 
00063   public:
00064     Pathname licenseTgz() const
00065     { return metadatapath.empty() ? Pathname() : metadatapath / path / "license.tar.gz"; }
00066 
00067     Url getmirrorListUrl() const
00068     {
00069       return replacer(mirrorlist_url);
00070     }
00071 
00072     Url &setmirrorListUrl()
00073     {
00074       return mirrorlist_url;
00075     }
00076 
00077     const std::set<Url> &baseUrls() const
00078     {
00079       if ( _baseUrls.empty() && ! (getmirrorListUrl().asString().empty()) )
00080       {
00081         emptybaseurls = true;
00082         repo::RepoMirrorList *rmirrorlist = NULL;
00083 
00084         DBG << "MetadataPath: " << metadatapath << endl;
00085         if( metadatapath.empty() )
00086           rmirrorlist = new repo::RepoMirrorList (getmirrorListUrl() );
00087         else
00088           rmirrorlist = new repo::RepoMirrorList (getmirrorListUrl(), metadatapath );
00089 
00090         std::vector<Url> rmurls = rmirrorlist->getUrls();
00091         delete rmirrorlist;
00092         rmirrorlist = NULL;
00093         _baseUrls.insert(rmurls.begin(), rmurls.end());
00094       }
00095       return _baseUrls;
00096     }
00097 
00098     std::set<Url> &baseUrls()
00099     {
00100       return _baseUrls;
00101     }
00102 
00103     bool baseurl2dump() const
00104     {
00105       return !emptybaseurls && !_baseUrls.empty();
00106     }
00107 
00109     bool keepPackagesDefault() const
00110     {
00111       if (indeterminate(keeppackages))
00112       {
00113         if (_baseUrls.empty())
00114           return mirrorlist_url.schemeIsDownloading();
00115         else
00116           return _baseUrls.begin()->schemeIsDownloading();
00117       }
00118       return (bool) keeppackages;
00119     }
00120 
00121   public:
00122     TriBool gpgcheck;
00123     TriBool keeppackages;
00124     Url gpgkey_url;
00125     repo::RepoType type;
00126     Pathname path;
00127     std::string service;
00128     std::string targetDistro;
00129     Pathname metadatapath;
00130     Pathname packagespath;
00131     DefaultIntegral<unsigned,defaultPriority> priority;
00132     mutable bool emptybaseurls;
00133     repo::RepoVariablesUrlReplacer replacer;
00134 
00135   private:
00136     Url mirrorlist_url;
00137     mutable std::set<Url> _baseUrls;
00138 
00139     friend Impl * rwcowClone<Impl>( const Impl * rhs );
00141     Impl * clone() const
00142     { return new Impl( *this ); }
00143   };
00145 
00147   inline std::ostream & operator<<( std::ostream & str, const RepoInfo::Impl & obj )
00148   {
00149     return str << "RepoInfo::Impl";
00150   }
00151 
00153   //
00154   //    CLASS NAME : RepoInfo
00155   //
00157 
00158   const RepoInfo RepoInfo::noRepo;
00159 
00161   //
00162   //    METHOD NAME : RepoInfo::RepoInfo
00163   //    METHOD TYPE : Ctor
00164   //
00165   RepoInfo::RepoInfo()
00166   : _pimpl( new Impl() )
00167   {}
00168 
00170   //
00171   //    METHOD NAME : RepoInfo::~RepoInfo
00172   //    METHOD TYPE : Dtor
00173   //
00174   RepoInfo::~RepoInfo()
00175   {
00176     //MIL << std::endl;
00177   }
00178 
00179   unsigned RepoInfo::priority() const
00180   { return _pimpl->priority; }
00181   unsigned RepoInfo::defaultPriority()
00182   { return Impl::defaultPriority; }
00183   void RepoInfo::setPriority( unsigned newval_r )
00184   {
00185     _pimpl->priority = newval_r ? newval_r : Impl::defaultPriority;
00186   }
00187 
00188   void RepoInfo::setGpgCheck( bool check )
00189   {
00190     _pimpl->gpgcheck = check;
00191   }
00192 
00193   void RepoInfo::setMirrorListUrl( const Url &url )
00194   {
00195     _pimpl->setmirrorListUrl() = url;
00196   }
00197 
00198   void RepoInfo::setGpgKeyUrl( const Url &url )
00199   {
00200     _pimpl->gpgkey_url = url;
00201   }
00202 
00203   void RepoInfo::addBaseUrl( const Url &url )
00204   {
00205     _pimpl->baseUrls().insert(url);
00206   }
00207 
00208   void RepoInfo::setBaseUrl( const Url &url )
00209   {
00210     _pimpl->baseUrls().clear();
00211     addBaseUrl(url);
00212   }
00213 
00214   void RepoInfo::setPath( const Pathname &path )
00215   {
00216     _pimpl->path = path;
00217   }
00218 
00219   void RepoInfo::setType( const repo::RepoType &t )
00220   {
00221     _pimpl->type = t;
00222   }
00223 
00224   void RepoInfo::setProbedType( const repo::RepoType &t ) const
00225   { _pimpl->setProbedType( t ); }
00226 
00227 
00228   void RepoInfo::setMetadataPath( const Pathname &path )
00229   {
00230     _pimpl->metadatapath = path;
00231   }
00232 
00233   void RepoInfo::setPackagesPath( const Pathname &path )
00234   {
00235     _pimpl->packagespath = path;
00236   }
00237 
00238   void RepoInfo::setKeepPackages( bool keep )
00239   {
00240     _pimpl->keeppackages = keep;
00241   }
00242 
00243   void RepoInfo::setService( const std::string& name )
00244   {
00245     _pimpl->service = name;
00246   }
00247 
00248   void RepoInfo::setTargetDistribution(
00249       const std::string & targetDistribution)
00250   {
00251     _pimpl->targetDistro = targetDistribution;
00252   }
00253 
00254   bool RepoInfo::gpgCheck() const
00255   { return indeterminate(_pimpl->gpgcheck) ? true : (bool) _pimpl->gpgcheck; }
00256 
00257   Pathname RepoInfo::metadataPath() const
00258   { return _pimpl->metadatapath; }
00259 
00260   Pathname RepoInfo::packagesPath() const
00261   { return _pimpl->packagespath; }
00262 
00263   repo::RepoType RepoInfo::type() const
00264   { return _pimpl->type; }
00265 
00266   Url RepoInfo::mirrorListUrl() const
00267   {
00268     return _pimpl->getmirrorListUrl();
00269   }
00270 
00271   Url RepoInfo::gpgKeyUrl() const
00272   { return _pimpl->gpgkey_url; }
00273 
00274   std::set<Url> RepoInfo::baseUrls() const
00275   {
00276     RepoInfo::url_set replaced_urls;
00277     for ( url_set::const_iterator it = _pimpl->baseUrls().begin();
00278           it != _pimpl->baseUrls().end();
00279           ++it )
00280     {
00281       replaced_urls.insert(_pimpl->replacer(*it));
00282     }
00283     return replaced_urls;
00284   }
00285 
00286   Pathname RepoInfo::path() const
00287   { return _pimpl->path; }
00288 
00289   std::string RepoInfo::service() const
00290   { return _pimpl->service; }
00291 
00292   std::string RepoInfo::targetDistribution() const
00293   { return _pimpl->targetDistro; }
00294 
00295   RepoInfo::urls_const_iterator RepoInfo::baseUrlsBegin() const
00296   {
00297     return make_transform_iterator( _pimpl->baseUrls().begin(),
00298                                     _pimpl->replacer );
00299     //return _pimpl->baseUrls.begin();
00300   }
00301 
00302   RepoInfo::urls_const_iterator RepoInfo::baseUrlsEnd() const
00303   {
00304     //return _pimpl->baseUrls.end();
00305     return make_transform_iterator( _pimpl->baseUrls().end(),
00306                                     _pimpl->replacer );
00307   }
00308 
00309   RepoInfo::urls_size_type RepoInfo::baseUrlsSize() const
00310   { return _pimpl->baseUrls().size(); }
00311 
00312   bool RepoInfo::baseUrlsEmpty() const
00313   { return _pimpl->baseUrls().empty(); }
00314 
00315   bool RepoInfo::baseUrlSet() const
00316   { return _pimpl->baseurl2dump(); }
00317 
00318   // false by default (if not set by setKeepPackages)
00319   bool RepoInfo::keepPackages() const
00320   {
00321     return _pimpl->keepPackagesDefault();
00322   }
00323 
00325 
00326   bool RepoInfo::hasLicense() const
00327   {
00328     Pathname licenseTgz( _pimpl->licenseTgz() );
00329     SEC << licenseTgz << endl;
00330     SEC << PathInfo(licenseTgz) << endl;
00331 
00332     return ! licenseTgz.empty() &&  PathInfo(licenseTgz).isFile();
00333   }
00334 
00335   std::string RepoInfo::getLicense( const Locale & lang_r )
00336   {
00337     LocaleSet avlocales( getLicenseLocales() );
00338     if ( avlocales.empty() )
00339       return std::string();
00340 
00341     Locale getLang( Locale::bestMatch( avlocales, lang_r ) );
00342     if ( getLang == Locale::noCode
00343          && avlocales.find( Locale::noCode ) == avlocales.end() )
00344     {
00345       WAR << "License.tar.gz contains no fallback text! " << *this << endl;
00346       // Using the fist locale instead of returning no text at all.
00347       // So the user might recognize that there is a license, even if he
00348       // can't read it.
00349       getLang = *avlocales.begin();
00350     }
00351 
00352     // now extract the license file.
00353     static const std::string licenseFileFallback( "license.txt" );
00354     std::string licenseFile( getLang == Locale::noCode
00355                              ? licenseFileFallback
00356                              : str::form( "license.%s.txt", getLang.code().c_str() ) );
00357 
00358     ExternalProgram::Arguments cmd;
00359     cmd.push_back( "tar" );
00360     cmd.push_back( "-x" );
00361     cmd.push_back( "-z" );
00362     cmd.push_back( "-O" );
00363     cmd.push_back( "-f" );
00364     cmd.push_back( _pimpl->licenseTgz().asString() ); // if it not exists, avlocales was empty.
00365     cmd.push_back( licenseFile );
00366 
00367     std::string ret;
00368     ExternalProgram prog( cmd, ExternalProgram::Discard_Stderr );
00369     for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() )
00370     {
00371       ret += output;
00372     }
00373     prog.close();
00374     return ret;
00375   }
00376 
00377   LocaleSet RepoInfo::getLicenseLocales() const
00378   {
00379     Pathname licenseTgz( _pimpl->licenseTgz() );
00380     if ( licenseTgz.empty() || ! PathInfo( licenseTgz ).isFile() )
00381       return LocaleSet();
00382 
00383     ExternalProgram::Arguments cmd;
00384     cmd.push_back( "tar" );
00385     cmd.push_back( "-t" );
00386     cmd.push_back( "-z" );
00387     cmd.push_back( "-f" );
00388     cmd.push_back( licenseTgz.asString() );
00389 
00390     LocaleSet ret;
00391     ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout );
00392     for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() )
00393     {
00394       static const C_Str license( "license." );
00395       static const C_Str dotTxt( ".txt\n" );
00396       if ( str::hasPrefix( output, license ) && str::hasSuffix( output, dotTxt ) )
00397       {
00398         if ( output.size() <= license.size() +  dotTxt.size() ) // license.txt
00399           ret.insert( Locale() );
00400         else
00401           ret.insert( Locale( std::string( output.c_str()+license.size(), output.size()- license.size() - dotTxt.size() ) ) );
00402       }
00403       else
00404       {
00405         WAR << "  " << output;
00406       }
00407     }
00408     prog.close();
00409     return ret;
00410   }
00411 
00413 
00414   std::ostream & RepoInfo::dumpOn( std::ostream & str ) const
00415   {
00416     RepoInfoBase::dumpOn(str);
00417     if ( _pimpl->baseurl2dump() )
00418     {
00419       for ( urls_const_iterator it = baseUrlsBegin();
00420             it != baseUrlsEnd();
00421             ++it )
00422       {
00423         str << "- url         : " << *it << std::endl;
00424       }
00425     }
00426     if ( ! (_pimpl->getmirrorListUrl().asString().empty())  )
00427     {
00428       str << "- mirrorlist  : " << _pimpl->getmirrorListUrl() << std::endl;
00429     }
00430     str << "- path        : " << path() << std::endl;
00431     str << "- type        : " << type() << std::endl;
00432     str << "- priority    : " << priority() << std::endl;
00433 
00434     str << "- gpgcheck    : " << gpgCheck() << std::endl;
00435     str << "- gpgkey      : " << gpgKeyUrl() << std::endl;
00436 
00437     if (!indeterminate(_pimpl->keeppackages))
00438       str << "- keeppackages: " << keepPackages() << std::endl;
00439 
00440     str << "- service     : " << service() << std::endl;
00441 
00442     if (!targetDistribution().empty())
00443       str << "- targetdistro: " << targetDistribution() << std::endl;
00444 
00445     if (!metadataPath().empty())
00446       str << "- metadataPath: " << metadataPath() << std::endl;
00447 
00448     if (!packagesPath().empty())
00449       str << "- packagesPath: " << packagesPath() << std::endl;
00450 
00451     return str;
00452   }
00453 
00454   std::ostream & RepoInfo::dumpAsIniOn( std::ostream & str ) const
00455   {
00456     RepoInfoBase::dumpAsIniOn(str);
00457 
00458     if ( _pimpl->baseurl2dump() )
00459     {
00460       str << "baseurl=";
00461       for ( url_set::const_iterator it = _pimpl->baseUrls().begin();
00462             it != _pimpl->baseUrls().end();
00463             ++it )
00464       {
00465         str << *it << endl;
00466       }
00467     }
00468 
00469     if ( ! _pimpl->path.empty() )
00470       str << "path="<< path() << endl;
00471 
00472     if ( ! (_pimpl->getmirrorListUrl().asString().empty()) )
00473       str << "mirrorlist=" << _pimpl->getmirrorListUrl() << endl;
00474 
00475     str << "type=" << type().asString() << endl;
00476 
00477     if ( priority() != defaultPriority() )
00478       str << "priority=" << priority() << endl;
00479 
00480     if (!indeterminate(_pimpl->gpgcheck))
00481       str << "gpgcheck=" << (gpgCheck() ? "1" : "0") << endl;
00482     if ( ! (gpgKeyUrl().asString().empty()) )
00483       str << "gpgkey=" <<gpgKeyUrl() << endl;
00484 
00485     if (!indeterminate(_pimpl->keeppackages))
00486       str << "keeppackages=" << keepPackages() << endl;
00487 
00488     if( ! service().empty() )
00489       str << "service=" << service() << endl;
00490 
00491     return str;
00492   }
00493 
00494   std::ostream & RepoInfo::dumpAsXMLOn( std::ostream & str) const
00495   { return dumpAsXMLOn(str, ""); }
00496 
00497   std::ostream & RepoInfo::dumpAsXMLOn( std::ostream & str, const std::string & content) const
00498   {
00499     string tmpstr;
00500     str
00501       << "<repo"
00502       << " alias=\"" << escape(alias()) << "\""
00503       << " name=\"" << escape(name()) << "\"";
00504     if (type() != repo::RepoType::NONE)
00505       str << " type=\"" << type().asString() << "\"";
00506     str
00507       << " enabled=\"" << enabled() << "\""
00508       << " autorefresh=\"" << autorefresh() << "\""
00509       << " gpgcheck=\"" << gpgCheck() << "\"";
00510     if (!(tmpstr = gpgKeyUrl().asString()).empty())
00511       str << " gpgkey=\"" << escape(tmpstr) << "\"";
00512     if (!(tmpstr = mirrorListUrl().asString()).empty())
00513       str << " mirrorlist=\"" << escape(tmpstr) << "\"";
00514     str << ">" << endl;
00515 
00516     if ( _pimpl->baseurl2dump() )
00517     {
00518       for (RepoInfo::urls_const_iterator urlit = baseUrlsBegin();
00519            urlit != baseUrlsEnd(); ++urlit)
00520         str << "<url>" << escape(urlit->asString()) << "</url>" << endl;
00521     }
00522 
00523     str << "</repo>" << endl;
00524     return str;
00525   }
00526 
00527 
00528   std::ostream & operator<<( std::ostream & str, const RepoInfo & obj )
00529   {
00530     return obj.dumpOn(str);
00531   }
00532 
00533 
00535 } // namespace zypp