libzypp
10.5.0
|
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::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 //return _pimpl->baseUrls.begin(); 00257 } 00258 00259 RepoInfo::urls_const_iterator RepoInfo::baseUrlsEnd() const 00260 { 00261 //return _pimpl->baseUrls.end(); 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 // Using the fist locale instead of returning no text at all. 00298 // So the user might recognize that there is a license, even if he 00299 // can't read it. 00300 getLang = *avlocales.begin(); 00301 } 00302 00303 // now extract the license file. 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() ); // if it not exists, avlocales was empty. 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() ) // license.txt 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 // print if non empty value 00379 auto strif( [&] ( const std::string & tag_r, const std::string & value_r ) { 00380 if ( ! value_r.empty() ) 00381 str << tag_r << value_r << std::endl; 00382 }); 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 << " enabled=\"" << enabled() << "\"" 00456 << " autorefresh=\"" << autorefresh() << "\"" 00457 << " gpgcheck=\"" << gpgCheck() << "\""; 00458 if (!(tmpstr = gpgKeyUrl().asString()).empty()) 00459 str << " gpgkey=\"" << escape(tmpstr) << "\""; 00460 if (!(tmpstr = mirrorListUrl().asString()).empty()) 00461 str << " mirrorlist=\"" << escape(tmpstr) << "\""; 00462 str << ">" << endl; 00463 00464 if ( _pimpl->baseurl2dump() ) 00465 { 00466 for (RepoInfo::urls_const_iterator urlit = baseUrlsBegin(); 00467 urlit != baseUrlsEnd(); ++urlit) 00468 str << "<url>" << escape(urlit->asString()) << "</url>" << endl; 00469 } 00470 00471 str << "</repo>" << endl; 00472 return str; 00473 } 00474 00475 00476 std::ostream & operator<<( std::ostream & str, const RepoInfo & obj ) 00477 { 00478 return obj.dumpOn(str); 00479 } 00480 00481 00483 } // namespace zypp