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