Imported Upstream version 14.45.0
[platform/upstream/libzypp.git] / zypp / RepoInfo.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/RepoInfo.cc
10  *
11 */
12 #include <iostream>
13 #include <vector>
14
15 #include "zypp/base/LogTools.h"
16 #include "zypp/base/DefaultIntegral.h"
17 #include "zypp/parser/xml/XmlEscape.h"
18
19 #include "zypp/RepoInfo.h"
20 #include "zypp/TriBool.h"
21 #include "zypp/Pathname.h"
22 #include "zypp/ZConfig.h"
23 #include "zypp/repo/RepoMirrorList.h"
24 #include "zypp/ExternalProgram.h"
25 #include "zypp/media/MediaAccess.h"
26
27 #include "zypp/base/IOStream.h"
28 #include "zypp/base/InputStream.h"
29 #include "zypp/parser/xml/Reader.h"
30
31 using std::endl;
32 using zypp::xml::escape;
33
34 ///////////////////////////////////////////////////////////////////
35 namespace zypp
36 { /////////////////////////////////////////////////////////////////
37
38   ///////////////////////////////////////////////////////////////////
39   //
40   //    CLASS NAME : RepoInfo::Impl
41   //
42   /** RepoInfo implementation. */
43   struct RepoInfo::Impl
44   {
45     Impl()
46       : _gpgCheck( indeterminate )
47       , _repoGpgCheck( indeterminate )
48       , _pkgGpgCheck( indeterminate )
49       , _validRepoSignature( indeterminate )
50       , keeppackages(indeterminate)
51       , type(repo::RepoType::NONE_e)
52       , emptybaseurls(false)
53     {}
54
55     ~Impl()
56     {}
57
58   public:
59     static const unsigned defaultPriority = 99;
60
61     void setProbedType( const repo::RepoType & t ) const
62     {
63       if ( type == repo::RepoType::NONE
64            && t != repo::RepoType::NONE )
65       {
66         // lazy init!
67         const_cast<Impl*>(this)->type = t;
68       }
69     }
70
71   public:
72     Pathname licenseTgz() const
73     { return metadatapath.empty() ? Pathname() : metadatapath / path / "license.tar.gz"; }
74
75     const RepoVariablesReplacedUrlList & baseUrls() const
76     {
77       const Url & mlurl( _mirrorListUrl.transformed() );        // Variables replaced!
78       if ( _baseUrls.empty() && ! mlurl.asString().empty() )
79       {
80         emptybaseurls = true;
81         DBG << "MetadataPath: " << metadatapath << endl;
82         repo::RepoMirrorList rmurls( mlurl, metadatapath );
83         _baseUrls.raw().insert( _baseUrls.raw().end(), rmurls.getUrls().begin(), rmurls.getUrls().end() );
84       }
85       return _baseUrls;
86     }
87
88     RepoVariablesReplacedUrlList & baseUrls()
89     { return _baseUrls; }
90
91     bool baseurl2dump() const
92     { return !emptybaseurls && !_baseUrls.empty(); }
93
94
95     const RepoVariablesReplacedUrlList & gpgKeyUrls() const
96     { return _gpgKeyUrls; }
97
98     RepoVariablesReplacedUrlList & gpgKeyUrls()
99     { return _gpgKeyUrls; }
100
101     void addContent( const std::string & keyword_r )
102     { _keywords.insert( keyword_r ); }
103
104     bool hasContent( const std::string & keyword_r ) const
105     {
106       if ( _keywords.empty() && ! metadatapath.empty() )
107       {
108         // HACK directly check master index file until RepoManager offers
109         // some content probing ans zypepr uses it.
110         /////////////////////////////////////////////////////////////////
111         MIL << "Empty keywords...." << metadatapath << endl;
112         Pathname master;
113         if ( PathInfo( (master=metadatapath/"/repodata/repomd.xml") ).isFile() )
114         {
115           //MIL << "GO repomd.." << endl;
116           xml::Reader reader( master );
117           while ( reader.seekToNode( 2, "content" ) )
118           {
119             _keywords.insert( reader.nodeText().asString() );
120             reader.seekToEndNode( 2, "content" );
121           }
122           _keywords.insert( "" );       // valid content in _keywords even if empty
123         }
124         else if ( PathInfo( (master=metadatapath/"/content") ).isFile() )
125         {
126           //MIL << "GO content.." << endl;
127           iostr::forEachLine( InputStream( master ),
128                             [this]( int num_r, std::string line_r )->bool
129                             {
130                               if ( str::startsWith( line_r, "REPOKEYWORDS" ) )
131                               {
132                                 std::vector<std::string> words;
133                                 if ( str::split( line_r, std::back_inserter(words) ) > 1
134                                   && words[0].length() == 12 /*"REPOKEYWORDS"*/ )
135                                 {
136                                   this->_keywords.insert( ++words.begin(), words.end() );
137                                 }
138                                 return true; // mult. occurrances are ok.
139                               }
140                               return( ! str::startsWith( line_r, "META " ) );   // no need to parse into META section.
141                             } );
142           _keywords.insert( "" );
143         }
144         /////////////////////////////////////////////////////////////////
145       }
146       return( _keywords.find( keyword_r ) != _keywords.end() );
147     }
148
149     /** Signature check result needs to be stored/retrieved from _metadatapath.
150      * Don't call them from outside validRepoSignature/setValidRepoSignature
151      */
152     //@{
153     TriBool internalValidRepoSignature() const
154     {
155       if ( ! indeterminate(_validRepoSignature) )               return _validRepoSignature;
156       // check metadata:
157       if ( ! metadatapath.empty() )
158       {
159         //TODO: a missing ".repo_gpgcheck" might be plaindir(no Downloader) or not yet refreshed signed repo!
160         TriBool linkval = triBoolFromPath( metadatapath / ".repo_gpgcheck" );
161         return linkval;
162       }
163       return indeterminate;
164     }
165
166     void internalSetValidRepoSignature( TriBool value_r )
167     {
168       if ( PathInfo(metadatapath).isDir() )
169       {
170         Pathname gpgcheckFile( metadatapath / ".repo_gpgcheck" );
171         if ( PathInfo(gpgcheckFile).isExist() )
172         {
173           TriBool linkval( indeterminate );
174           if ( triBoolFromPath( gpgcheckFile, linkval ) && linkval == value_r )
175             return;     // existing symlink fits value_r
176           else
177             filesystem::unlink( gpgcheckFile ); // will write a new one
178         }
179         filesystem::symlink( asString(value_r), gpgcheckFile );
180       }
181       _validRepoSignature = value_r;
182     }
183
184     bool triBoolFromPath( const Pathname & path_r, TriBool & ret_r ) const
185     {
186       static const Pathname truePath( "true" );
187       static const Pathname falsePath( "false" );
188       static const Pathname indeterminatePath( "indeterminate" );
189       Pathname linkval( filesystem::readlink( path_r ) );
190       bool known = true;
191       if ( linkval == truePath )
192         ret_r = true;
193       else if ( linkval == falsePath )
194         ret_r = false;
195       else if ( linkval == indeterminatePath )
196         ret_r = indeterminate;
197       else
198         known = false;
199       return known;
200     }
201
202     TriBool triBoolFromPath( const Pathname & path_r ) const
203     { TriBool ret(indeterminate); triBoolFromPath( path_r, ret ); return ret; }
204
205     //@}
206
207   public:
208     TriBool _gpgCheck;          ///< default gpgcheck behavior: Y/N/ZConf
209     TriBool _repoGpgCheck;      ///< need to check repo sign.: Y/N/(ZConf(Y/N/gpgCheck))
210     TriBool _pkgGpgCheck;       ///< need to check pkg sign.: Y/N/(ZConf(Y/N/gpgCheck && no valid repo sign.))
211   private:
212     TriBool _validRepoSignature;///< have  signed and valid repo metadata
213   public:
214     TriBool keeppackages;
215     RepoVariablesReplacedUrl _mirrorListUrl;
216     repo::RepoType type;
217     Pathname path;
218     std::string service;
219     std::string targetDistro;
220     Pathname metadatapath;
221     Pathname packagespath;
222     DefaultIntegral<unsigned,defaultPriority> priority;
223     mutable bool emptybaseurls;
224     repo::RepoVariablesUrlReplacer replacer;
225
226   private:
227     mutable RepoVariablesReplacedUrlList _baseUrls;
228     mutable std::set<std::string> _keywords;
229
230     RepoVariablesReplacedUrlList _gpgKeyUrls;
231
232     friend Impl * rwcowClone<Impl>( const Impl * rhs );
233     /** clone for RWCOW_pointer */
234     Impl * clone() const
235     { return new Impl( *this ); }
236   };
237   ///////////////////////////////////////////////////////////////////
238
239   /** \relates RepoInfo::Impl Stream output */
240   inline std::ostream & operator<<( std::ostream & str, const RepoInfo::Impl & obj )
241   {
242     return str << "RepoInfo::Impl";
243   }
244
245   ///////////////////////////////////////////////////////////////////
246   //
247   //    CLASS NAME : RepoInfo
248   //
249   ///////////////////////////////////////////////////////////////////
250
251   const RepoInfo RepoInfo::noRepo;
252
253   RepoInfo::RepoInfo()
254   : _pimpl( new Impl() )
255   {}
256
257   RepoInfo::~RepoInfo()
258   {}
259
260   unsigned RepoInfo::priority() const
261   { return _pimpl->priority; }
262
263   unsigned RepoInfo::defaultPriority()
264   { return Impl::defaultPriority; }
265
266   void RepoInfo::setPriority( unsigned newval_r )
267   { _pimpl->priority = newval_r ? newval_r : Impl::defaultPriority; }
268
269
270   bool RepoInfo::gpgCheck() const
271   { return indeterminate(_pimpl->_gpgCheck) ? ZConfig::instance().gpgCheck() : (bool)_pimpl->_gpgCheck; }
272
273   void RepoInfo::setGpgCheck( TriBool value_r )
274   { _pimpl->_gpgCheck = value_r; }
275
276   void RepoInfo::setGpgCheck( bool value_r ) // deprecated legacy and for squid
277   { setGpgCheck( TriBool(value_r) ); }
278
279
280   bool RepoInfo::repoGpgCheck() const
281   {
282     if ( ! indeterminate(_pimpl->_repoGpgCheck) )               return _pimpl->_repoGpgCheck;
283     if ( ! indeterminate(ZConfig::instance().repoGpgCheck()) )  return ZConfig::instance().repoGpgCheck();
284     return gpgCheck();  // no preference: follow gpgCheck
285   }
286
287   void RepoInfo::setRepoGpgCheck( TriBool value_r )
288   { _pimpl->_repoGpgCheck = value_r; }
289
290
291   bool RepoInfo::pkgGpgCheck() const
292   {
293     if ( ! indeterminate(_pimpl->_pkgGpgCheck) )                return _pimpl->_pkgGpgCheck;
294     if ( ! indeterminate(ZConfig::instance().pkgGpgCheck()) )   return ZConfig::instance().pkgGpgCheck();
295     // no preference: follow gpgCheck and check package if repo signature not available or not checked
296     return gpgCheck() && ( !repoGpgCheck() || !(bool)validRepoSignature() );    // !(bool)TriBool ==> false or indeterminate
297   }
298
299   void RepoInfo::setPkgGpgCheck( TriBool value_r )
300   { _pimpl->_pkgGpgCheck = value_r; }
301
302   void RepoInfo::getRawGpgChecks( TriBool & g_r, TriBool & r_r, TriBool & p_r ) const
303   {
304     g_r = _pimpl->_gpgCheck;
305     r_r = _pimpl->_repoGpgCheck;
306     p_r = _pimpl->_pkgGpgCheck;
307   }
308
309   TriBool RepoInfo::validRepoSignature() const
310   {
311     TriBool ret = _pimpl->internalValidRepoSignature();
312     // keep indeterminate(=unsigned) but invalidate any signature if !repoGpgCheck
313     if ( !indeterminate(ret) && !repoGpgCheck() )
314       ret = false;
315     return ret;
316   }
317
318   void RepoInfo::setValidRepoSignature( TriBool value_r )
319   { _pimpl->internalSetValidRepoSignature( value_r ); }
320
321
322   void RepoInfo::setMirrorListUrl( const Url & url_r )  // Raw
323   { _pimpl->_mirrorListUrl.raw() = url_r; }
324
325   void RepoInfo::setGpgKeyUrls( url_set urls )
326   { _pimpl->gpgKeyUrls().raw().swap( urls ); }
327
328   void RepoInfo::setGpgKeyUrl( const Url & url_r )
329   {
330     _pimpl->gpgKeyUrls().raw().clear();
331     _pimpl->gpgKeyUrls().raw().push_back( url_r );
332   }
333
334   void RepoInfo::addBaseUrl( const Url & url_r )
335   {
336     for ( const auto & url : _pimpl->baseUrls().raw() ) // Raw unique!
337       if ( url == url_r )
338         return;
339     _pimpl->baseUrls().raw().push_back( url_r );
340   }
341
342   void RepoInfo::setBaseUrl( const Url & url_r )
343   {
344     _pimpl->baseUrls().raw().clear();
345     _pimpl->baseUrls().raw().push_back( url_r );
346   }
347
348   void RepoInfo::setBaseUrls( url_set urls )
349   { _pimpl->baseUrls().raw().swap( urls ); }
350
351   void RepoInfo::setPath( const Pathname &path )
352   { _pimpl->path = path; }
353
354   void RepoInfo::setType( const repo::RepoType &t )
355   { _pimpl->type = t; }
356
357   void RepoInfo::setProbedType( const repo::RepoType &t ) const
358   { _pimpl->setProbedType( t ); }
359
360
361   void RepoInfo::setMetadataPath( const Pathname &path )
362   { _pimpl->metadatapath = path; }
363
364   void RepoInfo::setPackagesPath( const Pathname &path )
365   { _pimpl->packagespath = path; }
366
367   void RepoInfo::setKeepPackages( bool keep )
368   { _pimpl->keeppackages = keep; }
369
370   void RepoInfo::setService( const std::string& name )
371   { _pimpl->service = name; }
372
373   void RepoInfo::setTargetDistribution( const std::string & targetDistribution )
374   { _pimpl->targetDistro = targetDistribution; }
375
376   bool RepoInfo::keepPackages() const
377   { return indeterminate(_pimpl->keeppackages) ? false : (bool)_pimpl->keeppackages; }
378
379   Pathname RepoInfo::metadataPath() const
380   { return _pimpl->metadatapath; }
381
382   Pathname RepoInfo::packagesPath() const
383   { return _pimpl->packagespath; }
384
385   repo::RepoType RepoInfo::type() const
386   { return _pimpl->type; }
387
388   Url RepoInfo::mirrorListUrl() const                   // Variables replaced!
389   { return _pimpl->_mirrorListUrl.transformed(); }
390
391   Url RepoInfo::rawMirrorListUrl() const                // Raw
392   { return _pimpl->_mirrorListUrl.raw(); }
393
394   bool RepoInfo::gpgKeyUrlsEmpty() const
395   { return _pimpl->gpgKeyUrls().empty(); }
396
397   RepoInfo::urls_size_type RepoInfo::gpgKeyUrlsSize() const
398   { return _pimpl->gpgKeyUrls().size(); }
399
400   RepoInfo::url_set RepoInfo::gpgKeyUrls() const        // Variables replaced!
401   { return _pimpl->gpgKeyUrls().transformed(); }
402
403   RepoInfo::url_set RepoInfo::rawGpgKeyUrls() const     // Raw
404   { return _pimpl->gpgKeyUrls().raw(); }
405
406   Url RepoInfo::gpgKeyUrl() const                       // Variables replaced!
407   { return( _pimpl->gpgKeyUrls().empty() ? Url() : *_pimpl->gpgKeyUrls().transformedBegin() ); }
408
409   Url RepoInfo::rawGpgKeyUrl() const                    // Raw
410   { return( _pimpl->gpgKeyUrls().empty() ? Url() : *_pimpl->gpgKeyUrls().rawBegin() ) ; }
411
412   RepoInfo::url_set RepoInfo::baseUrls() const          // Variables replaced!
413   { return _pimpl->baseUrls().transformed(); }
414
415   RepoInfo::url_set RepoInfo::rawBaseUrls() const       // Raw
416   { return _pimpl->baseUrls().raw(); }
417
418   Pathname RepoInfo::path() const
419   { return _pimpl->path; }
420
421   std::string RepoInfo::service() const
422   { return _pimpl->service; }
423
424   std::string RepoInfo::targetDistribution() const
425   { return _pimpl->targetDistro; }
426
427   Url RepoInfo::rawUrl() const
428   { return( _pimpl->baseUrls().empty() ? Url() : *_pimpl->baseUrls().rawBegin() ); }
429
430   RepoInfo::urls_const_iterator RepoInfo::baseUrlsBegin() const
431   { return _pimpl->baseUrls().transformedBegin(); }
432
433   RepoInfo::urls_const_iterator RepoInfo::baseUrlsEnd() const
434   { return _pimpl->baseUrls().transformedEnd(); }
435
436   RepoInfo::urls_size_type RepoInfo::baseUrlsSize() const
437   { return _pimpl->baseUrls().size(); }
438
439   bool RepoInfo::baseUrlsEmpty() const
440   { return _pimpl->baseUrls().empty(); }
441
442   bool RepoInfo::baseUrlSet() const
443   { return _pimpl->baseurl2dump(); }
444
445
446   void RepoInfo::addContent( const std::string & keyword_r )
447   { _pimpl->addContent( keyword_r ); }
448
449   bool RepoInfo::hasContent( const std::string & keyword_r ) const
450   { return _pimpl->hasContent( keyword_r ); }
451
452   ///////////////////////////////////////////////////////////////////
453
454   bool RepoInfo::hasLicense() const
455   {
456     Pathname licenseTgz( _pimpl->licenseTgz() );
457     return ! licenseTgz.empty() &&  PathInfo(licenseTgz).isFile();
458   }
459
460   bool RepoInfo::needToAcceptLicense() const
461   {
462     static const std::string noAcceptanceFile = "no-acceptance-needed\n";
463     bool accept = true;
464
465     Pathname licenseTgz( _pimpl->licenseTgz() );
466     if ( licenseTgz.empty() || ! PathInfo( licenseTgz ).isFile() )
467       return false;     // no licenses at all
468
469     ExternalProgram::Arguments cmd;
470     cmd.push_back( "tar" );
471     cmd.push_back( "-t" );
472     cmd.push_back( "-z" );
473     cmd.push_back( "-f" );
474     cmd.push_back( licenseTgz.asString() );
475
476     ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout );
477     for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() )
478     {
479       if ( output == noAcceptanceFile )
480       {
481         accept = false;
482       }
483     }
484     MIL << "License for " << name() << " has to be accepted: " << (accept?"true":"false" ) << endl;
485     return accept;
486   }
487
488   std::string RepoInfo::getLicense( const Locale & lang_r )
489   { return const_cast<const RepoInfo *>(this)->getLicense( lang_r );  }
490
491   std::string RepoInfo::getLicense( const Locale & lang_r ) const
492   {
493     LocaleSet avlocales( getLicenseLocales() );
494     if ( avlocales.empty() )
495       return std::string();
496
497     Locale getLang( Locale::bestMatch( avlocales, lang_r ) );
498     if ( getLang == Locale::noCode
499          && avlocales.find( Locale::noCode ) == avlocales.end() )
500     {
501       WAR << "License.tar.gz contains no fallback text! " << *this << endl;
502       // Using the fist locale instead of returning no text at all.
503       // So the user might recognize that there is a license, even if he
504       // can't read it.
505       getLang = *avlocales.begin();
506     }
507
508     // now extract the license file.
509     static const std::string licenseFileFallback( "license.txt" );
510     std::string licenseFile( getLang == Locale::noCode
511                              ? licenseFileFallback
512                              : str::form( "license.%s.txt", getLang.code().c_str() ) );
513
514     ExternalProgram::Arguments cmd;
515     cmd.push_back( "tar" );
516     cmd.push_back( "-x" );
517     cmd.push_back( "-z" );
518     cmd.push_back( "-O" );
519     cmd.push_back( "-f" );
520     cmd.push_back( _pimpl->licenseTgz().asString() ); // if it not exists, avlocales was empty.
521     cmd.push_back( licenseFile );
522
523     std::string ret;
524     ExternalProgram prog( cmd, ExternalProgram::Discard_Stderr );
525     for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() )
526     {
527       ret += output;
528     }
529     prog.close();
530     return ret;
531   }
532
533   LocaleSet RepoInfo::getLicenseLocales() const
534   {
535     Pathname licenseTgz( _pimpl->licenseTgz() );
536     if ( licenseTgz.empty() || ! PathInfo( licenseTgz ).isFile() )
537       return LocaleSet();
538
539     ExternalProgram::Arguments cmd;
540     cmd.push_back( "tar" );
541     cmd.push_back( "-t" );
542     cmd.push_back( "-z" );
543     cmd.push_back( "-f" );
544     cmd.push_back( licenseTgz.asString() );
545
546     LocaleSet ret;
547     ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout );
548     for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() )
549     {
550       static const C_Str license( "license." );
551       static const C_Str dotTxt( ".txt\n" );
552       if ( str::hasPrefix( output, license ) && str::hasSuffix( output, dotTxt ) )
553       {
554         if ( output.size() <= license.size() +  dotTxt.size() ) // license.txt
555           ret.insert( Locale() );
556         else
557           ret.insert( Locale( std::string( output.c_str()+license.size(), output.size()- license.size() - dotTxt.size() ) ) );
558       }
559     }
560     prog.close();
561     return ret;
562   }
563
564   ///////////////////////////////////////////////////////////////////
565
566   std::ostream & RepoInfo::dumpOn( std::ostream & str ) const
567   {
568     RepoInfoBase::dumpOn(str);
569     if ( _pimpl->baseurl2dump() )
570     {
571       for ( const auto & url : _pimpl->baseUrls().raw() )
572       {
573         str << "- url         : " << url << std::endl;
574       }
575     }
576
577     // print if non empty value
578     auto strif( [&] ( const std::string & tag_r, const std::string & value_r ) {
579       if ( ! value_r.empty() )
580         str << tag_r << value_r << std::endl;
581     });
582
583     strif( "- mirrorlist  : ", rawMirrorListUrl().asString() );
584     strif( "- path        : ", path().asString() );
585     str << "- type        : " << type() << std::endl;
586     str << "- priority    : " << priority() << std::endl;
587
588     // Yes No Default(Y) Default(N)
589 #define OUTS(T,B) ( indeterminate(T) ? (std::string("D(")+(B?"Y":"N")+")") : ((bool)T?"Y":"N") )
590     str << "- gpgcheck    : " << OUTS(_pimpl->_gpgCheck,gpgCheck())
591                               << " repo" << OUTS(_pimpl->_repoGpgCheck,repoGpgCheck())
592                               << " sig" << asString( validRepoSignature(), "?", "Y", "N" )
593                               << " pkg" << OUTS(_pimpl->_pkgGpgCheck,pkgGpgCheck())
594                               << std::endl;
595 #undef OUTS
596
597     for ( const auto & url : _pimpl->gpgKeyUrls().raw() )
598     {
599       str << "- gpgkey      : " << url << std::endl;
600     }
601
602     if ( ! indeterminate(_pimpl->keeppackages) )
603       str << "- keeppackages: " << keepPackages() << std::endl;
604
605     strif( "- service     : ", service() );
606     strif( "- targetdistro: ", targetDistribution() );
607     strif( "- metadataPath: ", metadataPath().asString() );
608     strif( "- packagesPath: ", packagesPath().asString() );
609
610     return str;
611   }
612
613   std::ostream & RepoInfo::dumpAsIniOn( std::ostream & str ) const
614   {
615     RepoInfoBase::dumpAsIniOn(str);
616
617     if ( _pimpl->baseurl2dump() )
618     {
619       str << "baseurl=";
620       std::string indent;
621       for ( const auto & url : _pimpl->baseUrls().raw() )
622       {
623         str << indent << url << endl;
624         if ( indent.empty() ) indent = "        ";      // "baseurl="
625       }
626     }
627
628     if ( ! _pimpl->path.empty() )
629       str << "path="<< path() << endl;
630
631     if ( ! (rawMirrorListUrl().asString().empty()) )
632       str << "mirrorlist=" << rawMirrorListUrl() << endl;
633
634     str << "type=" << type().asString() << endl;
635
636     if ( priority() != defaultPriority() )
637       str << "priority=" << priority() << endl;
638
639     if ( ! indeterminate(_pimpl->_gpgCheck) )
640       str << "gpgcheck=" << (_pimpl->_gpgCheck ? "1" : "0") << endl;
641
642     if ( ! indeterminate(_pimpl->_repoGpgCheck) )
643       str << "repo_gpgcheck=" << (_pimpl->_repoGpgCheck ? "1" : "0") << endl;
644
645     if ( ! indeterminate(_pimpl->_pkgGpgCheck) )
646       str << "pkg_gpgcheck=" << (_pimpl->_pkgGpgCheck ? "1" : "0") << endl;
647
648     {
649       std::string indent( "gpgkey=");
650       for ( const auto & url : _pimpl->gpgKeyUrls().raw() )
651       {
652         str << indent << url << endl;
653         if ( indent[0] != ' ' )
654           indent = "       ";
655       }
656     }
657
658     if (!indeterminate(_pimpl->keeppackages))
659       str << "keeppackages=" << keepPackages() << endl;
660
661     if( ! service().empty() )
662       str << "service=" << service() << endl;
663
664     return str;
665   }
666
667   std::ostream & RepoInfo::dumpAsXmlOn( std::ostream & str, const std::string & content ) const
668   {
669     std::string tmpstr;
670     str
671       << "<repo"
672       << " alias=\"" << escape(alias()) << "\""
673       << " name=\"" << escape(name()) << "\"";
674     if (type() != repo::RepoType::NONE)
675       str << " type=\"" << type().asString() << "\"";
676     str
677       << " priority=\"" << priority() << "\""
678       << " enabled=\"" << enabled() << "\""
679       << " autorefresh=\"" << autorefresh() << "\""
680       << " gpgcheck=\"" << gpgCheck() << "\""
681       << " repo_gpgcheck=\"" << repoGpgCheck() << "\""
682       << " pkg_gpgcheck=\"" << pkgGpgCheck() << "\"";
683     if (!(tmpstr = gpgKeyUrl().asString()).empty())
684       str << " gpgkey=\"" << escape(tmpstr) << "\"";
685     if (!(tmpstr = mirrorListUrl().asString()).empty())
686       str << " mirrorlist=\"" << escape(tmpstr) << "\"";
687     str << ">" << endl;
688
689     if ( _pimpl->baseurl2dump() )
690     {
691       for_( it, baseUrlsBegin(), baseUrlsEnd() )        // !transform iterator replaces variables
692         str << "<url>" << escape((*it).asString()) << "</url>" << endl;
693     }
694
695     str << "</repo>" << endl;
696     return str;
697   }
698
699
700   std::ostream & operator<<( std::ostream & str, const RepoInfo & obj )
701   {
702     return obj.dumpOn(str);
703   }
704
705
706   /////////////////////////////////////////////////////////////////
707 } // namespace zypp
708 ///////////////////////////////////////////////////////////////////