libzypp  17.35.19
RepoFileReader.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
13 #include <zypp/base/LogTools.h>
14 #include <zypp/base/String.h>
15 #include <zypp/base/StringV.h>
16 #include <utility>
17 #include <zypp-core/base/InputStream>
18 #include <zypp-core/base/UserRequestException>
19 
20 #include <zypp-core/parser/IniDict>
22 
23 using std::endl;
24 
26 namespace zypp
27 {
29  namespace parser
30  {
32  namespace {
33 
38  class RepoFileParser : public IniDict
39  {
40  public:
41  RepoFileParser( const InputStream & is_r )
42  { read( is_r ); }
43 
44  using IniDict::consume; // don't hide overloads we don't redefine here
45 
46  void consume( const std::string & section_r, const std::string & key_r, const std::string & value_r ) override
47  {
48  if ( key_r == "baseurl" )
49  {
50  _inMultiline = MultiLine::baseurl;
51  storeUrl( _baseurls[section_r], value_r );
52  }
53  else if ( key_r == "gpgkey" )
54  {
55  _inMultiline = MultiLine::gpgkey;
56  storeUrl( _gpgkeys[section_r], value_r );
57  }
58  else if ( key_r == "mirrorlist" )
59  {
60  _inMultiline = MultiLine::mirrorlist;
61  storeUrl( _mirrorlist[section_r], value_r );
62  }
63  else if ( key_r == "metalink" )
64  {
65  _inMultiline = MultiLine::metalink;
66  storeUrl( _metalink[section_r], value_r );
67  }
68  else
69  {
71  IniDict::consume( section_r, key_r, value_r );
72  }
73  }
74 
75  void garbageLine( const std::string & section_r, const std::string & line_r ) override
76  {
77  switch ( _inMultiline )
78  {
79  case MultiLine::baseurl:
80  storeUrl( _baseurls[section_r], line_r );
81  break;
82 
83  case MultiLine::gpgkey:
84  storeUrl( _gpgkeys[section_r], line_r );
85  break;
86 
87  case MultiLine::mirrorlist:
88  storeUrl( _mirrorlist[section_r], line_r );
89  break;
90 
91  case MultiLine::metalink:
92  storeUrl( _metalink[section_r], line_r );
93  break;
94 
95  case MultiLine::none:
96  IniDict::garbageLine( section_r, line_r ); // throw
97  break;
98  }
99  }
100 
101  std::list<Url> & baseurls( const std::string & section_r )
102  { return _baseurls[section_r]; }
103 
104  std::list<Url> & gpgkeys( const std::string & section_r )
105  { return _gpgkeys[section_r]; }
106 
107  std::list<Url> & mirrorlist( const std::string & section_r )
108  { return _mirrorlist[section_r]; }
109 
110  std::list<Url> & metalink( const std::string & section_r )
111  { return _metalink[section_r]; }
112 
113  private:
114  void storeUrl( std::list<Url> & store_r, const std::string & line_r )
115  {
116  // #285: Fedora/dnf allows WS separated urls (and an optional comma)
117  strv::splitRx( line_r, "[,[:blank:]]*[[:blank:]][,[:blank:]]*", [&store_r]( std::string_view w ) {
118  if ( ! w.empty() )
119  store_r.push_back( Url(std::string(w)) );
120  });
121  }
122 
123  enum class MultiLine { none, baseurl, gpgkey, mirrorlist, metalink };
125 
126  std::map<std::string,std::list<Url>> _baseurls;
127  std::map<std::string,std::list<Url>> _gpgkeys;
128  std::map<std::string,std::list<Url>> _mirrorlist;
129  std::map<std::string,std::list<Url>> _metalink;
130  };
131 
132  } //namespace
134 
139  static void repositories_in_stream( const InputStream &is,
140  const RepoFileReader::ProcessRepo &callback,
141  const ProgressData::ReceiverFnc &progress )
142  try {
143  RepoFileParser dict(is);
144  for_( its, dict.sectionsBegin(), dict.sectionsEnd() )
145  {
146  RepoInfo info;
147  info.setAlias(*its);
148  std::string proxy;
149  std::string proxyport;
150 
151  for_( it, dict.entriesBegin(*its), dict.entriesEnd(*its) )
152  {
153  //MIL << (*it).first << endl;
154  if (it->first == "name" )
155  info.setName(it-> second);
156  else if ( it->first == "enabled" )
157  info.setEnabled( str::strToTrue( it->second ) );
158  else if ( it->first == "priority" )
159  info.setPriority( str::strtonum<unsigned>( it->second ) );
160  else if ( it->first == "path" )
161  info.setPath( Pathname(it->second) );
162  else if ( it->first == "type" )
163  ; // bsc#1177427 et.al.: type in a .repo file is legacy - ignore it and let RepoManager probe
164  else if ( it->first == "autorefresh" )
165  info.setAutorefresh( str::strToTrue( it->second ) );
166  else if ( it->first == "gpgcheck" )
167  info.setGpgCheck( str::strToTriBool( it->second ) );
168  else if ( it->first == "repo_gpgcheck" )
169  info.setRepoGpgCheck( str::strToTrue( it->second ) );
170  else if ( it->first == "pkg_gpgcheck" )
171  info.setPkgGpgCheck( str::strToTrue( it->second ) );
172  else if ( it->first == "keeppackages" )
173  info.setKeepPackages( str::strToTrue( it->second ) );
174  else if ( it->first == "service" )
175  info.setService( it->second );
176  else if ( it->first == "proxy" )
177  {
178  // Translate it into baseurl queryparams
179  // NOTE: The hack here does not add proxy to mirrorlist urls but the
180  // original code worked without complains, so keep it for now.
181  static const str::regex ex( ":[0-9]+$" ); // portspec
182  str::smatch what;
183  if ( str::regex_match( it->second, what, ex ) )
184  {
185  proxy = it->second.substr( 0, it->second.size() - what[0].size() );
186  proxyport = what[0].substr( 1 );
187  }
188  else
189  {
190  proxy = it->second;
191  }
192  }
193  else
194  ERR << "Unknown attribute in [" << *its << "]: " << it->first << "=" << it->second << " ignored" << endl;
195  }
196 
197  for ( auto & url : dict.baseurls( *its ) )
198  {
199  if ( ! proxy.empty() && url.getQueryParam( "proxy" ).empty() )
200  {
201  url.setQueryParam( "proxy", proxy );
202  url.setQueryParam( "proxyport", proxyport );
203  }
204  info.addBaseUrl( url );
205  }
206 
207  if ( ! dict.gpgkeys( *its ).empty() )
208  info.setGpgKeyUrls( std::move(dict.gpgkeys( *its )) );
209 
210  if ( ! dict.mirrorlist( *its ).empty() )
211  info.setMirrorListUrls( std::move(dict.mirrorlist( *its )) );
212 
213  if ( ! dict.metalink( *its ).empty() )
214  info.setMetalinkUrls( std::move(dict.metalink( *its )) );
215 
216 
217  info.setFilepath(is.path());
218  MIL << info << endl;
219  // add it to the list.
220  callback(info);
221  //if (!progress.tick())
222  // ZYPP_THROW(AbortRequestException());
223  }
224  }
225  catch ( Exception & ex ) {
226  ex.addHistory( "Parsing .repo file "+is.name() );
227  ZYPP_RETHROW( ex );
228  }
229 
231  //
232  // CLASS NAME : RepoFileReader
233  //
235 
237  ProcessRepo callback,
238  const ProgressData::ReceiverFnc &progress )
239  : _callback(std::move(callback))
240  {
241  repositories_in_stream(InputStream(repo_file), _callback, progress);
242  }
243 
245  ProcessRepo callback,
246  const ProgressData::ReceiverFnc &progress )
247  : _callback(std::move(callback))
248  {
249  repositories_in_stream(is, _callback, progress);
250  }
251 
253  {}
254 
255 
256  std::ostream & operator<<( std::ostream & str, const RepoFileReader & obj )
257  {
258  return str;
259  }
260 
261  } // namespace parser
263 } // namespace zypp
MultiLine _inMultiline
#define MIL
Definition: Logger.h:100
unsigned size() const
Definition: Regex.cc:106
void setAutorefresh(bool autorefresh)
enable or disable autorefresh
Definition: RepoInfoBase.cc:91
Regular expression.
Definition: Regex.h:94
void setPriority(unsigned newval_r)
Set repository priority for solver.
Definition: RepoInfo.cc:407
std::map< std::string, std::list< Url > > _gpgkeys
std::map< std::string, std::list< Url > > _mirrorlist
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
Definition: progressdata.h:140
void setEnabled(bool enabled)
enable or disable the repository
Definition: RepoInfoBase.cc:88
std::map< std::string, std::list< Url > > _baseurls
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:28
void addHistory(const std::string &msg_r)
Add some message text to the history.
Definition: Exception.cc:176
void setAlias(const std::string &alias)
set the repository alias
Definition: RepoInfoBase.cc:94
String related utilities and Regular expression matching.
void setFilepath(const Pathname &filename)
set the path to the .repo file
Definition: Arch.h:363
What is known about a repository.
Definition: RepoInfo.h:71
void setGpgCheck(TriBool value_r)
Set the value for gpgCheck (or indeterminate to use the default).
Definition: RepoInfo.cc:414
Helper to create and pass std::istream.
Definition: inputstream.h:56
#define ERR
Definition: Logger.h:102
RepoFileReader(const Pathname &repo_file, ProcessRepo callback, const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
Constructor.
void setMirrorListUrls(url_set urls)
Like setMirrorListUrl but take an url_set.
Definition: RepoInfo.cc:525
TriBool strToTriBool(const C_Str &str)
Parse str into a bool if it&#39;s a legal true or false string; else indeterminate.
Definition: String.cc:94
static void repositories_in_stream(const InputStream &is, const RepoFileReader::ProcessRepo &callback, const ProgressData::ReceiverFnc &progress)
List of RepoInfo&#39;s from a file.
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:444
std::map< std::string, std::list< Url > > _metalink
std::ostream & operator<<(std::ostream &str, const ProductFileData &obj)
void setRepoGpgCheck(TriBool value_r)
Set the value for repoGpgCheck (or indeterminate to use the default).
Definition: RepoInfo.cc:432
void setPath(const Pathname &path)
set the product path.
Definition: RepoInfo.cc:565
void setService(const std::string &name)
sets service which added this repository
Definition: RepoInfo.cc:584
void setKeepPackages(bool keep)
Set if packaqes downloaded from this repository will be kept in local cache.
Definition: RepoInfo.cc:581
Read repository data from a .repo file.
const Pathname & path() const
Path to the input file or empty if no file.
Definition: inputstream.h:111
virtual void garbageLine(const std::string &section, const std::string &line)
Called whenever a garbage line is found.
Definition: iniparser.cc:72
function< bool(const RepoInfo &)> ProcessRepo
Callback definition.
zypp::Url Url
Definition: url.h:15
const ProcessCredentials & _callback
void consume(const std::string &section) override
Called when a section is found.
Definition: inidict.cc:64
void setGpgKeyUrls(url_set urls)
Set a list of gpgkey URLs defined for this repo.
Definition: RepoInfo.cc:534
Regular expression match result.
Definition: Regex.h:167
Base class for Exception.
Definition: Exception.h:146
void addBaseUrl(Url url)
Add a base url.
Definition: RepoInfo.cc:548
c++17: std::string_view tools
std::map< std::string, std::string > read(const Pathname &_path)
Read sysconfig file path_r and return (key,valye) pairs.
Definition: sysconfig.cc:34
bool regex_match(const std::string &s, smatch &matches, const regex &regex)
regex ZYPP_STR_REGEX regex ZYPP_STR_REGEX
Definition: Regex.h:70
void setMetalinkUrls(url_set urls)
Like setMirrorListUrls but expect metalink format.
Definition: RepoInfo.cc:531
void setName(const std::string &name)
set the repository name
Definition: RepoInfoBase.cc:97
Easy-to use interface to the ZYPP dependency resolver.
Definition: Application.cc:19
void setPkgGpgCheck(TriBool value_r)
Set the value for pkgGpgCheck (or indeterminate to use the default).
Definition: RepoInfo.cc:442
bool strToTrue(const C_Str &str)
Parsing boolean from string.
Definition: String.cc:64