libzypp 9.41.1

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     { return replacer(mirrorlist_url); }
00069 
00070     Url &setmirrorListUrl()
00071     { return mirrorlist_url; }
00072 
00073     const std::set<Url> &baseUrls() const
00074     {
00075       if ( _baseUrls.empty() && ! (getmirrorListUrl().asString().empty()) )
00076       {
00077         emptybaseurls = true;
00078         repo::RepoMirrorList *rmirrorlist = NULL;
00079 
00080         DBG << "MetadataPath: " << metadatapath << endl;
00081         if( metadatapath.empty() )
00082           rmirrorlist = new repo::RepoMirrorList (getmirrorListUrl() );
00083         else
00084           rmirrorlist = new repo::RepoMirrorList (getmirrorListUrl(), metadatapath );
00085 
00086         std::vector<Url> rmurls = rmirrorlist->getUrls();
00087         delete rmirrorlist;
00088         rmirrorlist = NULL;
00089         _baseUrls.insert(rmurls.begin(), rmurls.end());
00090       }
00091       return _baseUrls;
00092     }
00093 
00094     std::set<Url> &baseUrls()
00095     { return _baseUrls; }
00096 
00097     bool baseurl2dump() const
00098     { return !emptybaseurls && !_baseUrls.empty(); }
00099 
00100   public:
00101     TriBool gpgcheck;
00102     TriBool keeppackages;
00103     Url gpgkey_url;
00104     repo::RepoType type;
00105     Pathname path;
00106     std::string service;
00107     std::string targetDistro;
00108     Pathname metadatapath;
00109     Pathname packagespath;
00110     DefaultIntegral<unsigned,defaultPriority> priority;
00111     mutable bool emptybaseurls;
00112     repo::RepoVariablesUrlReplacer replacer;
00113 
00114   private:
00115     Url mirrorlist_url;
00116     mutable std::set<Url> _baseUrls;
00117 
00118     friend Impl * rwcowClone<Impl>( const Impl * rhs );
00120     Impl * clone() const
00121     { return new Impl( *this ); }
00122   };
00124 
00126   inline std::ostream & operator<<( std::ostream & str, const RepoInfo::Impl & obj )
00127   {
00128     return str << "RepoInfo::Impl";
00129   }
00130 
00132   //
00133   //    CLASS NAME : RepoInfo
00134   //
00136 
00137   const RepoInfo RepoInfo::noRepo;
00138 
00140   //
00141   //    METHOD NAME : RepoInfo::RepoInfo
00142   //    METHOD TYPE : Ctor
00143   //
00144   RepoInfo::RepoInfo()
00145   : _pimpl( new Impl() )
00146   {}
00147 
00149   //
00150   //    METHOD NAME : RepoInfo::~RepoInfo
00151   //    METHOD TYPE : Dtor
00152   //
00153   RepoInfo::~RepoInfo()
00154   {
00155     //MIL << std::endl;
00156   }
00157 
00158   unsigned RepoInfo::priority() const
00159   { return _pimpl->priority; }
00160 
00161   unsigned RepoInfo::defaultPriority()
00162   { return Impl::defaultPriority; }
00163 
00164   void RepoInfo::setPriority( unsigned newval_r )
00165   { _pimpl->priority = newval_r ? newval_r : Impl::defaultPriority; }
00166 
00167   void RepoInfo::setGpgCheck( bool check )
00168   { _pimpl->gpgcheck = check; }
00169 
00170   void RepoInfo::setMirrorListUrl( const Url &url )
00171   { _pimpl->setmirrorListUrl() = url; }
00172 
00173   void RepoInfo::setGpgKeyUrl( const Url &url )
00174   { _pimpl->gpgkey_url = url; }
00175 
00176   void RepoInfo::addBaseUrl( const Url &url )
00177   { _pimpl->baseUrls().insert(url); }
00178 
00179   void RepoInfo::setBaseUrl( const Url &url )
00180   {
00181     _pimpl->baseUrls().clear();
00182     addBaseUrl(url);
00183   }
00184 
00185   void RepoInfo::setBaseUrls( url_set urls )
00186   { _pimpl->baseUrls().swap( urls ); }
00187 
00188   void RepoInfo::setPath( const Pathname &path )
00189   { _pimpl->path = path; }
00190 
00191   void RepoInfo::setType( const repo::RepoType &t )
00192   { _pimpl->type = t; }
00193 
00194   void RepoInfo::setProbedType( const repo::RepoType &t ) const
00195   { _pimpl->setProbedType( t ); }
00196 
00197 
00198   void RepoInfo::setMetadataPath( const Pathname &path )
00199   { _pimpl->metadatapath = path; }
00200 
00201   void RepoInfo::setPackagesPath( const Pathname &path )
00202   { _pimpl->packagespath = path; }
00203 
00204   void RepoInfo::setKeepPackages( bool keep )
00205   { _pimpl->keeppackages = keep; }
00206 
00207   void RepoInfo::setService( const std::string& name )
00208   { _pimpl->service = name; }
00209 
00210   void RepoInfo::setTargetDistribution( const std::string & targetDistribution )
00211   { _pimpl->targetDistro = targetDistribution; }
00212 
00213   bool RepoInfo::gpgCheck() const
00214   { return indeterminate(_pimpl->gpgcheck) ? true : (bool)_pimpl->gpgcheck; }
00215 
00216   bool RepoInfo::keepPackages() const
00217   { return indeterminate(_pimpl->keeppackages) ? false : (bool)_pimpl->keeppackages; }
00218 
00219   Pathname RepoInfo::metadataPath() const
00220   { return _pimpl->metadatapath; }
00221 
00222   Pathname RepoInfo::packagesPath() const
00223   { return _pimpl->packagespath; }
00224 
00225   repo::RepoType RepoInfo::type() const
00226   { return _pimpl->type; }
00227 
00228   Url RepoInfo::mirrorListUrl() const
00229   { return _pimpl->getmirrorListUrl(); }
00230 
00231   Url RepoInfo::gpgKeyUrl() const
00232   { return _pimpl->gpgkey_url; }
00233 
00234   std::set<Url> RepoInfo::baseUrls() const
00235   {
00236     RepoInfo::url_set replaced_urls;
00237     for ( url_set::const_iterator it = _pimpl->baseUrls().begin();
00238           it != _pimpl->baseUrls().end();
00239           ++it )
00240     {
00241       replaced_urls.insert(_pimpl->replacer(*it));
00242     }
00243     return replaced_urls;
00244   }
00245 
00246   Pathname RepoInfo::path() const
00247   { return _pimpl->path; }
00248 
00249   std::string RepoInfo::service() const
00250   { return _pimpl->service; }
00251 
00252   std::string RepoInfo::targetDistribution() const
00253   { return _pimpl->targetDistro; }
00254 
00255   RepoInfo::urls_const_iterator RepoInfo::baseUrlsBegin() const
00256   {
00257     return make_transform_iterator( _pimpl->baseUrls().begin(),
00258                                     _pimpl->replacer );
00259     //return _pimpl->baseUrls.begin();
00260   }
00261 
00262   RepoInfo::urls_const_iterator RepoInfo::baseUrlsEnd() const
00263   {
00264     //return _pimpl->baseUrls.end();
00265     return make_transform_iterator( _pimpl->baseUrls().end(),
00266                                     _pimpl->replacer );
00267   }
00268 
00269   RepoInfo::urls_size_type RepoInfo::baseUrlsSize() const
00270   { return _pimpl->baseUrls().size(); }
00271 
00272   bool RepoInfo::baseUrlsEmpty() const
00273   { return _pimpl->baseUrls().empty(); }
00274 
00275   bool RepoInfo::baseUrlSet() const
00276   { return _pimpl->baseurl2dump(); }
00277 
00279 
00280   bool RepoInfo::hasLicense() const
00281   {
00282     Pathname licenseTgz( _pimpl->licenseTgz() );
00283     SEC << licenseTgz << endl;
00284     SEC << PathInfo(licenseTgz) << endl;
00285 
00286     return ! licenseTgz.empty() &&  PathInfo(licenseTgz).isFile();
00287   }
00288 
00289   std::string RepoInfo::getLicense( const Locale & lang_r )
00290   {
00291     LocaleSet avlocales( getLicenseLocales() );
00292     if ( avlocales.empty() )
00293       return std::string();
00294 
00295     Locale getLang( Locale::bestMatch( avlocales, lang_r ) );
00296     if ( getLang == Locale::noCode
00297          && avlocales.find( Locale::noCode ) == avlocales.end() )
00298     {
00299       WAR << "License.tar.gz contains no fallback text! " << *this << endl;
00300       // Using the fist locale instead of returning no text at all.
00301       // So the user might recognize that there is a license, even if he
00302       // can't read it.
00303       getLang = *avlocales.begin();
00304     }
00305 
00306     // now extract the license file.
00307     static const std::string licenseFileFallback( "license.txt" );
00308     std::string licenseFile( getLang == Locale::noCode
00309                              ? licenseFileFallback
00310                              : str::form( "license.%s.txt", getLang.code().c_str() ) );
00311 
00312     ExternalProgram::Arguments cmd;
00313     cmd.push_back( "tar" );
00314     cmd.push_back( "-x" );
00315     cmd.push_back( "-z" );
00316     cmd.push_back( "-O" );
00317     cmd.push_back( "-f" );
00318     cmd.push_back( _pimpl->licenseTgz().asString() ); // if it not exists, avlocales was empty.
00319     cmd.push_back( licenseFile );
00320 
00321     std::string ret;
00322     ExternalProgram prog( cmd, ExternalProgram::Discard_Stderr );
00323     for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() )
00324     {
00325       ret += output;
00326     }
00327     prog.close();
00328     return ret;
00329   }
00330 
00331   LocaleSet RepoInfo::getLicenseLocales() const
00332   {
00333     Pathname licenseTgz( _pimpl->licenseTgz() );
00334     if ( licenseTgz.empty() || ! PathInfo( licenseTgz ).isFile() )
00335       return LocaleSet();
00336 
00337     ExternalProgram::Arguments cmd;
00338     cmd.push_back( "tar" );
00339     cmd.push_back( "-t" );
00340     cmd.push_back( "-z" );
00341     cmd.push_back( "-f" );
00342     cmd.push_back( licenseTgz.asString() );
00343 
00344     LocaleSet ret;
00345     ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout );
00346     for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() )
00347     {
00348       static const C_Str license( "license." );
00349       static const C_Str dotTxt( ".txt\n" );
00350       if ( str::hasPrefix( output, license ) && str::hasSuffix( output, dotTxt ) )
00351       {
00352         if ( output.size() <= license.size() +  dotTxt.size() ) // license.txt
00353           ret.insert( Locale() );
00354         else
00355           ret.insert( Locale( std::string( output.c_str()+license.size(), output.size()- license.size() - dotTxt.size() ) ) );
00356       }
00357       else
00358       {
00359         WAR << "  " << output;
00360       }
00361     }
00362     prog.close();
00363     return ret;
00364   }
00365 
00367 
00368   std::ostream & RepoInfo::dumpOn( std::ostream & str ) const
00369   {
00370     RepoInfoBase::dumpOn(str);
00371     if ( _pimpl->baseurl2dump() )
00372     {
00373       for ( urls_const_iterator it = baseUrlsBegin();
00374             it != baseUrlsEnd();
00375             ++it )
00376       {
00377         str << "- url         : " << *it << std::endl;
00378       }
00379     }
00380 
00381     // print if non empty value
00382 #define strif( tag_r, value ) {                 \
00383       const std::string & value_r( value );     \
00384       if ( ! value_r.empty() )                  \
00385         str << tag_r << value_r << std::endl; }
00386 
00387     strif( "- mirrorlist  : ", _pimpl->getmirrorListUrl().asString() );
00388     strif( "- path        : ", path().asString() );
00389     str << "- type        : " << type() << std::endl;
00390     str << "- priority    : " << priority() << std::endl;
00391     str << "- gpgcheck    : " << gpgCheck() << std::endl;
00392     strif( "- gpgkey      : ", gpgKeyUrl().asString() );
00393 
00394     if ( ! indeterminate(_pimpl->keeppackages) )
00395       str << "- keeppackages: " << keepPackages() << std::endl;
00396 
00397     strif( "- service     : ", service() );
00398     strif( "- targetdistro: ", targetDistribution() );
00399     strif( "- metadataPath: ", metadataPath().asString() );
00400     strif( "- packagesPath: ", packagesPath().asString() );
00401 
00402     return str;
00403   }
00404 
00405   std::ostream & RepoInfo::dumpAsIniOn( std::ostream & str ) const
00406   {
00407     RepoInfoBase::dumpAsIniOn(str);
00408 
00409     if ( _pimpl->baseurl2dump() )
00410     {
00411       str << "baseurl=";
00412       std::string indent;
00413       for ( url_set::const_iterator it = _pimpl->baseUrls().begin();
00414             it != _pimpl->baseUrls().end();
00415             ++it )
00416       {
00417         str << indent << *it << endl;
00418         if ( indent.empty() ) indent = "        ";      // "baseurl="
00419       }
00420     }
00421 
00422     if ( ! _pimpl->path.empty() )
00423       str << "path="<< path() << endl;
00424 
00425     if ( ! (_pimpl->getmirrorListUrl().asString().empty()) )
00426       str << "mirrorlist=" << _pimpl->getmirrorListUrl() << endl;
00427 
00428     str << "type=" << type().asString() << endl;
00429 
00430     if ( priority() != defaultPriority() )
00431       str << "priority=" << priority() << endl;
00432 
00433     if (!indeterminate(_pimpl->gpgcheck))
00434       str << "gpgcheck=" << (gpgCheck() ? "1" : "0") << endl;
00435     if ( ! (gpgKeyUrl().asString().empty()) )
00436       str << "gpgkey=" <<gpgKeyUrl() << endl;
00437 
00438     if (!indeterminate(_pimpl->keeppackages))
00439       str << "keeppackages=" << keepPackages() << endl;
00440 
00441     if( ! service().empty() )
00442       str << "service=" << service() << endl;
00443 
00444     return str;
00445   }
00446 
00447   std::ostream & RepoInfo::dumpAsXMLOn( std::ostream & str) const
00448   { return dumpAsXMLOn(str, ""); }
00449 
00450   std::ostream & RepoInfo::dumpAsXMLOn( std::ostream & str, const std::string & content) const
00451   {
00452     string tmpstr;
00453     str
00454       << "<repo"
00455       << " alias=\"" << escape(alias()) << "\""
00456       << " name=\"" << escape(name()) << "\"";
00457     if (type() != repo::RepoType::NONE)
00458       str << " type=\"" << type().asString() << "\"";
00459     str
00460       << " priority=\"" << priority() << "\""
00461       << " enabled=\"" << enabled() << "\""
00462       << " autorefresh=\"" << autorefresh() << "\""
00463       << " gpgcheck=\"" << gpgCheck() << "\"";
00464     if (!(tmpstr = gpgKeyUrl().asString()).empty())
00465       str << " gpgkey=\"" << escape(tmpstr) << "\"";
00466     if (!(tmpstr = mirrorListUrl().asString()).empty())
00467       str << " mirrorlist=\"" << escape(tmpstr) << "\"";
00468     str << ">" << endl;
00469 
00470     if ( _pimpl->baseurl2dump() )
00471     {
00472       for (RepoInfo::urls_const_iterator urlit = baseUrlsBegin();
00473            urlit != baseUrlsEnd(); ++urlit)
00474         str << "<url>" << escape(urlit->asString()) << "</url>" << endl;
00475     }
00476 
00477     str << "</repo>" << endl;
00478     return str;
00479   }
00480 
00481 
00482   std::ostream & operator<<( std::ostream & str, const RepoInfo & obj )
00483   {
00484     return obj.dumpOn(str);
00485   }
00486 
00487 
00489 } // namespace zypp