RepoInfo.cc

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

doxygen