libzypp 8.13.6
|
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