RepoInfo.cc
Go to the documentation of this file.00001
00002
00003
00004
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
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
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
00134
00136
00137 const RepoInfo RepoInfo::noRepo;
00138
00140
00141
00142
00143
00144 RepoInfo::RepoInfo()
00145 : _pimpl( new Impl() )
00146 {}
00147
00149
00150
00151
00152
00153 RepoInfo::~RepoInfo()
00154 {
00155
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::setPath( const Pathname &path )
00186 { _pimpl->path = path; }
00187
00188 void RepoInfo::setType( const repo::RepoType &t )
00189 { _pimpl->type = t; }
00190
00191 void RepoInfo::setProbedType( const repo::RepoType &t ) const
00192 { _pimpl->setProbedType( t ); }
00193
00194
00195 void RepoInfo::setMetadataPath( const Pathname &path )
00196 { _pimpl->metadatapath = path; }
00197
00198 void RepoInfo::setPackagesPath( const Pathname &path )
00199 { _pimpl->packagespath = path; }
00200
00201 void RepoInfo::setKeepPackages( bool keep )
00202 { _pimpl->keeppackages = keep; }
00203
00204 void RepoInfo::setService( const std::string& name )
00205 { _pimpl->service = name; }
00206
00207 void RepoInfo::setTargetDistribution( const std::string & targetDistribution )
00208 { _pimpl->targetDistro = targetDistribution; }
00209
00210 bool RepoInfo::gpgCheck() const
00211 { return indeterminate(_pimpl->gpgcheck) ? true : (bool)_pimpl->gpgcheck; }
00212
00213 bool RepoInfo::keepPackages() const
00214 { return indeterminate(_pimpl->keeppackages) ? false : (bool)_pimpl->keeppackages; }
00215
00216 Pathname RepoInfo::metadataPath() const
00217 { return _pimpl->metadatapath; }
00218
00219 Pathname RepoInfo::packagesPath() const
00220 { return _pimpl->packagespath; }
00221
00222 repo::RepoType RepoInfo::type() const
00223 { return _pimpl->type; }
00224
00225 Url RepoInfo::mirrorListUrl() const
00226 { return _pimpl->getmirrorListUrl(); }
00227
00228 Url RepoInfo::gpgKeyUrl() const
00229 { return _pimpl->gpgkey_url; }
00230
00231 std::set<Url> RepoInfo::baseUrls() const
00232 {
00233 RepoInfo::url_set replaced_urls;
00234 for ( url_set::const_iterator it = _pimpl->baseUrls().begin();
00235 it != _pimpl->baseUrls().end();
00236 ++it )
00237 {
00238 replaced_urls.insert(_pimpl->replacer(*it));
00239 }
00240 return replaced_urls;
00241 }
00242
00243 Pathname RepoInfo::path() const
00244 { return _pimpl->path; }
00245
00246 std::string RepoInfo::service() const
00247 { return _pimpl->service; }
00248
00249 std::string RepoInfo::targetDistribution() const
00250 { return _pimpl->targetDistro; }
00251
00252 RepoInfo::urls_const_iterator RepoInfo::baseUrlsBegin() const
00253 {
00254 return make_transform_iterator( _pimpl->baseUrls().begin(),
00255 _pimpl->replacer );
00256
00257 }
00258
00259 RepoInfo::urls_const_iterator RepoInfo::baseUrlsEnd() const
00260 {
00261
00262 return make_transform_iterator( _pimpl->baseUrls().end(),
00263 _pimpl->replacer );
00264 }
00265
00266 RepoInfo::urls_size_type RepoInfo::baseUrlsSize() const
00267 { return _pimpl->baseUrls().size(); }
00268
00269 bool RepoInfo::baseUrlsEmpty() const
00270 { return _pimpl->baseUrls().empty(); }
00271
00272 bool RepoInfo::baseUrlSet() const
00273 { return _pimpl->baseurl2dump(); }
00274
00276
00277 bool RepoInfo::hasLicense() const
00278 {
00279 Pathname licenseTgz( _pimpl->licenseTgz() );
00280 SEC << licenseTgz << endl;
00281 SEC << PathInfo(licenseTgz) << endl;
00282
00283 return ! licenseTgz.empty() && PathInfo(licenseTgz).isFile();
00284 }
00285
00286 std::string RepoInfo::getLicense( const Locale & lang_r )
00287 {
00288 LocaleSet avlocales( getLicenseLocales() );
00289 if ( avlocales.empty() )
00290 return std::string();
00291
00292 Locale getLang( Locale::bestMatch( avlocales, lang_r ) );
00293 if ( getLang == Locale::noCode
00294 && avlocales.find( Locale::noCode ) == avlocales.end() )
00295 {
00296 WAR << "License.tar.gz contains no fallback text! " << *this << endl;
00297
00298
00299
00300 getLang = *avlocales.begin();
00301 }
00302
00303
00304 static const std::string licenseFileFallback( "license.txt" );
00305 std::string licenseFile( getLang == Locale::noCode
00306 ? licenseFileFallback
00307 : str::form( "license.%s.txt", getLang.code().c_str() ) );
00308
00309 ExternalProgram::Arguments cmd;
00310 cmd.push_back( "tar" );
00311 cmd.push_back( "-x" );
00312 cmd.push_back( "-z" );
00313 cmd.push_back( "-O" );
00314 cmd.push_back( "-f" );
00315 cmd.push_back( _pimpl->licenseTgz().asString() );
00316 cmd.push_back( licenseFile );
00317
00318 std::string ret;
00319 ExternalProgram prog( cmd, ExternalProgram::Discard_Stderr );
00320 for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() )
00321 {
00322 ret += output;
00323 }
00324 prog.close();
00325 return ret;
00326 }
00327
00328 LocaleSet RepoInfo::getLicenseLocales() const
00329 {
00330 Pathname licenseTgz( _pimpl->licenseTgz() );
00331 if ( licenseTgz.empty() || ! PathInfo( licenseTgz ).isFile() )
00332 return LocaleSet();
00333
00334 ExternalProgram::Arguments cmd;
00335 cmd.push_back( "tar" );
00336 cmd.push_back( "-t" );
00337 cmd.push_back( "-z" );
00338 cmd.push_back( "-f" );
00339 cmd.push_back( licenseTgz.asString() );
00340
00341 LocaleSet ret;
00342 ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout );
00343 for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() )
00344 {
00345 static const C_Str license( "license." );
00346 static const C_Str dotTxt( ".txt\n" );
00347 if ( str::hasPrefix( output, license ) && str::hasSuffix( output, dotTxt ) )
00348 {
00349 if ( output.size() <= license.size() + dotTxt.size() )
00350 ret.insert( Locale() );
00351 else
00352 ret.insert( Locale( std::string( output.c_str()+license.size(), output.size()- license.size() - dotTxt.size() ) ) );
00353 }
00354 else
00355 {
00356 WAR << " " << output;
00357 }
00358 }
00359 prog.close();
00360 return ret;
00361 }
00362
00364
00365 std::ostream & RepoInfo::dumpOn( std::ostream & str ) const
00366 {
00367 RepoInfoBase::dumpOn(str);
00368 if ( _pimpl->baseurl2dump() )
00369 {
00370 for ( urls_const_iterator it = baseUrlsBegin();
00371 it != baseUrlsEnd();
00372 ++it )
00373 {
00374 str << "- url : " << *it << std::endl;
00375 }
00376 }
00377
00378
00379 #define strif( tag_r, value ) { \
00380 const std::string & value_r( value ); \
00381 if ( ! value_r.empty() ) \
00382 str << tag_r << value_r << std::endl; }
00383
00384 strif( "- mirrorlist : ", _pimpl->getmirrorListUrl().asString() );
00385 strif( "- path : ", path().asString() );
00386 str << "- type : " << type() << std::endl;
00387 str << "- priority : " << priority() << std::endl;
00388 str << "- gpgcheck : " << gpgCheck() << std::endl;
00389 strif( "- gpgkey : ", gpgKeyUrl().asString() );
00390
00391 if ( ! indeterminate(_pimpl->keeppackages) )
00392 str << "- keeppackages: " << keepPackages() << std::endl;
00393
00394 strif( "- service : ", service() );
00395 strif( "- targetdistro: ", targetDistribution() );
00396 strif( "- metadataPath: ", metadataPath().asString() );
00397 strif( "- packagesPath: ", packagesPath().asString() );
00398
00399 return str;
00400 }
00401
00402 std::ostream & RepoInfo::dumpAsIniOn( std::ostream & str ) const
00403 {
00404 RepoInfoBase::dumpAsIniOn(str);
00405
00406 if ( _pimpl->baseurl2dump() )
00407 {
00408 str << "baseurl=";
00409 for ( url_set::const_iterator it = _pimpl->baseUrls().begin();
00410 it != _pimpl->baseUrls().end();
00411 ++it )
00412 {
00413 str << *it << endl;
00414 }
00415 }
00416
00417 if ( ! _pimpl->path.empty() )
00418 str << "path="<< path() << endl;
00419
00420 if ( ! (_pimpl->getmirrorListUrl().asString().empty()) )
00421 str << "mirrorlist=" << _pimpl->getmirrorListUrl() << endl;
00422
00423 str << "type=" << type().asString() << endl;
00424
00425 if ( priority() != defaultPriority() )
00426 str << "priority=" << priority() << endl;
00427
00428 if (!indeterminate(_pimpl->gpgcheck))
00429 str << "gpgcheck=" << (gpgCheck() ? "1" : "0") << endl;
00430 if ( ! (gpgKeyUrl().asString().empty()) )
00431 str << "gpgkey=" <<gpgKeyUrl() << endl;
00432
00433 if (!indeterminate(_pimpl->keeppackages))
00434 str << "keeppackages=" << keepPackages() << endl;
00435
00436 if( ! service().empty() )
00437 str << "service=" << service() << endl;
00438
00439 return str;
00440 }
00441
00442 std::ostream & RepoInfo::dumpAsXMLOn( std::ostream & str) const
00443 { return dumpAsXMLOn(str, ""); }
00444
00445 std::ostream & RepoInfo::dumpAsXMLOn( std::ostream & str, const std::string & content) const
00446 {
00447 string tmpstr;
00448 str
00449 << "<repo"
00450 << " alias=\"" << escape(alias()) << "\""
00451 << " name=\"" << escape(name()) << "\"";
00452 if (type() != repo::RepoType::NONE)
00453 str << " type=\"" << type().asString() << "\"";
00454 str
00455 << " priority=\"" << priority() << "\""
00456 << " enabled=\"" << enabled() << "\""
00457 << " autorefresh=\"" << autorefresh() << "\""
00458 << " gpgcheck=\"" << gpgCheck() << "\"";
00459 if (!(tmpstr = gpgKeyUrl().asString()).empty())
00460 str << " gpgkey=\"" << escape(tmpstr) << "\"";
00461 if (!(tmpstr = mirrorListUrl().asString()).empty())
00462 str << " mirrorlist=\"" << escape(tmpstr) << "\"";
00463 str << ">" << endl;
00464
00465 if ( _pimpl->baseurl2dump() )
00466 {
00467 for (RepoInfo::urls_const_iterator urlit = baseUrlsBegin();
00468 urlit != baseUrlsEnd(); ++urlit)
00469 str << "<url>" << escape(urlit->asString()) << "</url>" << endl;
00470 }
00471
00472 str << "</repo>" << endl;
00473 return str;
00474 }
00475
00476
00477 std::ostream & operator<<( std::ostream & str, const RepoInfo & obj )
00478 {
00479 return obj.dumpOn(str);
00480 }
00481
00482
00484 }