libzypp: zypp/parser/RepoindexFileReader.cc Source File

libzypp 17.38.14

RepoindexFileReader.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12#include <iostream>
13#include <unordered_map>
14
15#include <zypp-core/base/String.h>
16#include <zypp-core/base/Logger.h>
17#include <zypp-core/base/Gettext.h>
18#include <utility>
19#include <zypp-core/base/InputStream>
20#include <zypp-core/base/DefaultIntegral>
21
22#include <zypp-core/Pathname.h>
23
24#include <zypp/parser/xml/Reader.h>
25#include <zypp-core/parser/ParseException>
26
27#include <zypp/RepoInfo.h>
28
29#include <zypp/parser/RepoindexFileReader.h>
30
31
32#undef ZYPP_BASE_LOGGER_LOGGROUP
33#define ZYPP_BASE_LOGGER_LOGGROUP "parser"
34
35using std::endl;
36
37namespace zypp
38{
39 namespace parser
40 {
41 using xml::Reader;
42 using xml::XmlString;
43
45 namespace
46 {
47 class VarReplacer : private base::NonCopyable
48 {
49 public:
51 void setGlobalVar( const std::string & key_r, const std::string & val_r )
52 { _global[key_r] = replace( val_r ); }
53
55 void setSectionVar( const std::string & key_r, const std::string & val_r )
56 { _section[key_r] = replace( val_r ); }
57
59 void clearSectionVars()
60 { _section.clear(); }
61
62 std::string replace( const std::string & val_r ) const
63 {
64 std::string::size_type vbeg = val_r.find( "%{", 0 );
65 if ( vbeg == std::string::npos )
66 return val_r;
67
68 str::Str ret;
69 std::string::size_type cbeg = 0;
70 for( ; vbeg != std::string::npos; vbeg = val_r.find( "%{", vbeg ) )
71 {
72 std::string::size_type nbeg = vbeg+2;
73 std::string::size_type nend = val_r.find( '}', nbeg );
74 if ( nend == std::string::npos )
75 {
76 WAR << "Incomplete variable in '" << val_r << "'" << endl;
77 break;
78 }
79 const std::string * varptr = getVar( val_r.substr( nbeg, nend-nbeg ) );
80 if ( varptr )
81 {
82 if ( cbeg < vbeg )
83 ret << val_r.substr( cbeg, vbeg-cbeg );
84 ret << *varptr;
85 cbeg = nend+1;
86 }
87 else
88 WAR << "Undefined variable %{" << val_r.substr( nbeg, nend-nbeg ) << "} in '" << val_r << "'" << endl;
89 vbeg = nend+1;
90 }
91 if ( cbeg < val_r.size() )
92 ret << val_r.substr( cbeg );
93
94 return ret;
95 }
96
97 private:
98 const std::string * getVar( const std::string & key_r ) const
99 {
100 const std::string * ret = getVar( key_r, _section );
101 if ( not ret )
102 ret = getVar( key_r, _global );
103 return ret;
104 }
105
106 const std::string * getVar( const std::string & key_r, const std::unordered_map<std::string,std::string> & map_r ) const
107 {
108 const auto & iter = map_r.find( key_r );
109 if ( iter != map_r.end() )
110 return &(iter->second);
111 return nullptr;
112 }
113
114 private:
115 std::unordered_map<std::string,std::string> _global;
116 std::unordered_map<std::string,std::string> _section;
117 };
118 } // namespace
120
122 //
123 // CLASS NAME : RepoindexFileReader::Impl
124 //
125 class RepoindexFileReader::Impl : private base::NonCopyable
126 {
127 public:
133 Impl(const InputStream &is, ProcessResource &&callback);
134
138 bool consumeNode( Reader & reader_r );
139
140 DefaultIntegral<Date::Duration,0> _ttl;
141
142 private:
143 bool getAttrValue( const std::string & key_r, Reader & reader_r, std::string & value_r )
144 {
145 const XmlString & s( reader_r->getAttribute( key_r ) );
146 if ( s.get() )
147 {
148 value_r = _replacer.replace( s.asString() );
149 return !value_r.empty();
150 }
151 value_r.clear();
152 return false;
153 }
154
155 private:
157 ProcessResource _callback;
158 VarReplacer _replacer;
159 };
160
161
162 RepoindexFileReader::Impl::Impl(const InputStream &is,
163 ProcessResource &&callback)
164 : _callback(std::move(callback))
165 {
166 Reader reader( is );
167 MIL << "Reading " << is.path() << endl;
168 reader.foreachNode( bind( &RepoindexFileReader::Impl::consumeNode, this, _1 ) );
169 }
170
171 // --------------------------------------------------------------------------
172
173 /*
174 * xpath and multiplicity of processed nodes are included in the code
175 * for convenience:
176 *
177 * // xpath: <xpath> (?|*|+)
178 *
179 * if multiplicity is ommited, then the node has multiplicity 'one'.
180 */
181
182 // --------------------------------------------------------------------------
183
184 bool RepoindexFileReader::Impl::consumeNode( Reader & reader_r )
185 {
186 if ( reader_r->nodeType() == XML_READER_TYPE_ELEMENT )
187 {
188 // xpath: /repoindex
189 if ( reader_r->name() == "repoindex" )
190 {
191 while ( reader_r.nextNodeAttribute() )
192 {
193 const std::string & name( reader_r->localName().asString() );
194 const std::string & value( reader_r->value().asString() );
195 _replacer.setGlobalVar( name, value );
196 // xpath: /repoindex@ttl
197 if ( name == "ttl" )
198 _ttl = str::strtonum<Date::Duration>(value);
199 }
200 return true;
201 }
202
203 // xpath: /repoindex/data (+)
204 if ( reader_r->name() == "repo" )
205 {
206 // TODO: Ideally the repo values here are interpreted the same way as
207 // corresponding ones in the RepoFileReader. Check whether we can introduce
208 // a RepoInfo ctor from a string dict. Using it here and in RepoFileReader.
209 // For now we try to parse the same way as in RepoFileReader.
210
211 RepoInfo info;
212 // Set some defaults that are not contained in the repo information
213 info.setAutorefresh( true );
214 info.setEnabled(false);
215
216 std::string attrValue;
217 _replacer.clearSectionVars();
218
219 // required alias
220 // mandatory, so we can allow it in var replacement without reset
221 if ( getAttrValue( "alias", reader_r, attrValue ) )
222 {
223 info.setAlias( attrValue );
224 _replacer.setSectionVar( "alias", attrValue );
225 }
226 else
227 throw ParseException(str::form(_("Required attribute '%s' is missing."), "alias"));
228
229 // required url
230 // SLES HACK: or path, but beware of the hardcoded '/repo' prefix!
231 {
232 std::string urlstr;
233 std::string pathstr;
234 getAttrValue( "url", reader_r, urlstr );
235 getAttrValue( "path", reader_r, pathstr );
236 if ( urlstr.empty() )
237 {
238 if ( pathstr.empty() )
239 // TODO: In fact we'd like to pass and check for url or mirrorlist at the end (check below).
240 // But there is legacy code in serviceswf.cc where an empty baseurl is replaced by
241 // the service Url. We need to check what kind of feature hides behind this code.
242 // So for now we keep requiring an url attribut.
243 throw ParseException(str::form(_("One or both of '%s' or '%s' attributes is required."), "url", "path"));
244 else
245 info.setPath( Pathname("/repo") / pathstr );
246 }
247 else
248 {
249 if ( pathstr.empty() )
250 info.setBaseUrl( Url(urlstr) );
251 else
252 {
253 Url url( urlstr );
254 url.setPathName( Pathname(url.getPathName()) / "repo" / pathstr );
255 info.setBaseUrl( url );
256 }
257 _replacer.setSectionVar( "url", urlstr );
258 }
259 }
260
261 // optional name
262 if ( getAttrValue( "name", reader_r, attrValue ) )
263 info.setName( attrValue );
264
265 // optional targetDistro
266 if ( getAttrValue( "distro_target", reader_r, attrValue ) )
267 info.setTargetDistribution( attrValue );
268
269 // optional priority
270 if ( getAttrValue( "priority", reader_r, attrValue ) )
271 info.setPriority( str::strtonum<unsigned>( attrValue ) );
272
273 // optional enabled
274 if ( getAttrValue( "enabled", reader_r, attrValue ) )
275 info.setEnabled( str::strToBool( attrValue, info.enabled() ) );
276
277 // optional autorefresh
278 if ( getAttrValue( "autorefresh", reader_r, attrValue ) )
279 info.setAutorefresh( str::strToBool( attrValue, info.autorefresh() ) );
280
281 // optional *gpgcheck
282 if ( getAttrValue( "gpgcheck", reader_r, attrValue ) )
283 info.setGpgCheck( str::strToTriBool( attrValue ) );
284 if ( getAttrValue( "repo_gpgcheck", reader_r, attrValue ) )
285 info.setRepoGpgCheck( str::strToTrue( attrValue ) );
286 if ( getAttrValue( "pkg_gpgcheck", reader_r, attrValue ) )
287 info.setPkgGpgCheck( str::strToTrue( attrValue ) );
288
289 // optional keeppackages
290 if ( getAttrValue( "keeppackages", reader_r, attrValue ) )
291 info.setKeepPackages( str::strToTrue( attrValue ) );
292
293 // optional gpgkey
294 if ( getAttrValue( "gpgkey", reader_r, attrValue ) )
295 info.setGpgKeyUrl( Url(attrValue) );
296
297 // optional mirrorlist
298 if ( getAttrValue( "mirrorlist", reader_r, attrValue ) )
299 info.setMirrorlistUrl( Url(attrValue) );
300
301 // optional metalink
302 if ( getAttrValue( "metalink", reader_r, attrValue ) )
303 info.setMetalinkUrl( Url(attrValue) );
304
305 DBG << info << endl;
306 // require at least one Url
307 // NOTE: Some legacy feature in serviceswf.cc allows a path without baseurl and
308 // combines this with the service url. That's why we require empty url and path
309 // in order to fail.
310 if ( info.baseUrlsEmpty() && info.path().empty() && not info.mirrorListUrl().isValid() ) {
311 throw ParseException(str::form(_("Neither '%s' nor '%s' nor '%s' attribute is defined for service repo '%s'."),
312 "url", "mirrorlist", "metalink", info.alias().c_str()));
313 }
314
315 // ignore the rest
316 // Specially: bsc#1177427 et.al.: type in a .repo file is legacy - ignore it
317 _callback(info);
318 return true;
319 }
320 }
321
322 return true;
323 }
324
325
327 //
328 // CLASS NAME : RepoindexFileReader
329 //
331
332 RepoindexFileReader::RepoindexFileReader( Pathname repoindex_file, ProcessResource callback )
333 : _pimpl(new Impl( InputStream(std::move(repoindex_file)), std::move(callback) ))
334 {}
335
336 RepoindexFileReader::RepoindexFileReader(const InputStream &is, ProcessResource callback )
337 : _pimpl(new Impl( is, std::move(callback) ))
338 {}
339
340 RepoindexFileReader::~RepoindexFileReader()
341 {}
342
343 Date::Duration RepoindexFileReader::ttl() const { return _pimpl->_ttl; }
344
345 } // ns parser
346} // ns zypp
347
348// vim: set ts=2 sts=2 sw=2 et ai:
Gettext.h
_
#define _(MSG)
Definition Gettext.h:39
Logger.h
DBG
#define DBG
Definition Logger.h:102
MIL
#define MIL
Definition Logger.h:103
WAR
#define WAR
Definition Logger.h:104
Pathname.h
Reader.h
RepoInfo.h
RepoindexFileReader.h
Interface of repoindex.xml file reader.
String.h
zypp::Date::Duration
time_t Duration
Definition Date.h:39
zypp::DefaultIntegral
Integral type with defined initial value when default constructed.
Definition defaultintegral.h:42
zypp::InputStream
Helper to create and pass std::istream.
Definition inputstream.h:57
zypp::InputStream::path
const Pathname & path() const
Path to the input file or empty if no file.
Definition inputstream.h:111
zypp::Pathname::Pathname
Pathname()
Default ctor: an empty path.
Definition Pathname.h:51
zypp::RepoInfo
What is known about a repository.
Definition RepoInfo.h:72
zypp::RepoInfo::setPkgGpgCheck
void setPkgGpgCheck(TriBool value_r)
Set the value for pkgGpgCheck (or indeterminate to use the default).
Definition RepoInfo.cc:654
zypp::RepoInfo::setMetalinkUrl
void setMetalinkUrl(const Url &url)
Set the raw metalink url.
Definition RepoInfo.cc:737
zypp::RepoInfo::setMirrorlistUrl
void setMirrorlistUrl(const Url &url)
Set the raw mirrorlist url.
Definition RepoInfo.cc:734
zypp::RepoInfo::setGpgKeyUrl
void setGpgKeyUrl(const Url &gpgkey)
(leagcy API) Set the gpgkey URL defined for this repo
Definition RepoInfo.cc:758
zypp::RepoInfo::baseUrlsEmpty
bool baseUrlsEmpty() const
whether repository urls are available
Definition RepoInfo.cc:903
zypp::RepoInfo::setKeepPackages
void setKeepPackages(bool keep)
Set if packaqes downloaded from this repository will be kept in local cache.
Definition RepoInfo.cc:819
zypp::RepoInfo::setBaseUrl
void setBaseUrl(Url url)
Clears current base URL list and adds url.
Definition RepoInfo.cc:777
zypp::RepoInfo::setGpgCheck
void setGpgCheck(TriBool value_r)
Set the value for gpgCheck (or indeterminate to use the default).
Definition RepoInfo.cc:626
zypp::RepoInfo::path
Pathname path() const
Repository path.
Definition RepoInfo.cc:879
zypp::RepoInfo::mirrorListUrl
Url mirrorListUrl() const
Url of a file which contains a list of repository urls.
Definition RepoInfo.cc:849
zypp::RepoInfo::setTargetDistribution
void setTargetDistribution(const std::string &targetDistribution)
Sets the distribution for which is this repository meant.
Definition RepoInfo.cc:825
zypp::RepoInfo::setPath
void setPath(const Pathname &path)
set the product path.
Definition RepoInfo.cc:800
zypp::RepoInfo::setPriority
void setPriority(unsigned newval_r)
Set repository priority for solver.
Definition RepoInfo.cc:619
zypp::RepoInfo::setRepoGpgCheck
void setRepoGpgCheck(TriBool value_r)
Set the value for repoGpgCheck (or indeterminate to use the default).
Definition RepoInfo.cc:644
zypp::Url
Url manipulation class.
Definition Url.h:93
zypp::Url::Url
Url()
Definition Url.cc:306
zypp::Url::isValid
bool isValid() const
Verifies the Url.
Definition Url.cc:516
zypp::filesystem::Pathname
Pathname.
Definition Pathname.h:48
zypp::filesystem::Pathname::empty
bool empty() const
Test for an empty path.
Definition Pathname.h:117
zypp::parser::ParseException::ParseException
ParseException()
Default ctor.
Definition parseexception.cc:29
zypp::parser::RepoindexFileReader::Impl
Definition RepoindexFileReader.cc:126
zypp::parser::RepoindexFileReader::Impl::_ttl
DefaultIntegral< Date::Duration, 0 > _ttl
Definition RepoindexFileReader.cc:140
zypp::parser::RepoindexFileReader::Impl::consumeNode
bool consumeNode(Reader &reader_r)
Callback provided to the XML parser.
Definition RepoindexFileReader.cc:184
zypp::parser::RepoindexFileReader::Impl::_replacer
VarReplacer _replacer
Definition RepoindexFileReader.cc:158
zypp::parser::RepoindexFileReader::Impl::Impl
Impl(const InputStream &is, ProcessResource &&callback)
CTOR.
Definition RepoindexFileReader.cc:162
zypp::parser::RepoindexFileReader::Impl::_callback
ProcessResource _callback
Function for processing collected data.
Definition RepoindexFileReader.cc:157
zypp::parser::RepoindexFileReader::Impl::getAttrValue
bool getAttrValue(const std::string &key_r, Reader &reader_r, std::string &value_r)
Definition RepoindexFileReader.cc:143
zypp::parser::RepoindexFileReader::ProcessResource
function< bool(const RepoInfo &)> ProcessResource
Callback definition.
Definition RepoindexFileReader.h:52
zypp::parser::RepoindexFileReader::_pimpl
RW_pointer< Impl, rw_pointer::Scoped< Impl > > _pimpl
Definition RepoindexFileReader.h:86
zypp::parser::RepoindexFileReader::RepoindexFileReader
RepoindexFileReader(Pathname repoindexFile, ProcessResource callback)
CTOR.
Definition RepoindexFileReader.cc:332
zypp::parser::RepoindexFileReader::ttl
Date::Duration ttl() const
Metadata TTL (repoindex.xml:xpath:/repoindex@ttl or 0).
Definition RepoindexFileReader.cc:343
zypp::parser::RepoindexFileReader::~RepoindexFileReader
~RepoindexFileReader()
DTOR.
Definition RepoindexFileReader.cc:340
zypp::repo::RepoInfoBase::setAutorefresh
void setAutorefresh(bool autorefresh)
enable or disable autorefresh
Definition RepoInfoBase.cc:92
zypp::repo::RepoInfoBase::setAlias
void setAlias(const std::string &alias)
set the repository alias
Definition RepoInfoBase.cc:95
zypp::repo::RepoInfoBase::setName
void setName(const std::string &name)
set the repository name
Definition RepoInfoBase.cc:98
zypp::repo::RepoInfoBase::autorefresh
bool autorefresh() const
If true, the repostory must be refreshed before creating resolvables from it.
Definition RepoInfoBase.cc:107
zypp::repo::RepoInfoBase::enabled
bool enabled() const
If enabled is false, then this repository must be ignored as if does not exists, except when checking...
Definition RepoInfoBase.cc:104
zypp::repo::RepoInfoBase::setEnabled
void setEnabled(bool enabled)
enable or disable the repository
Definition RepoInfoBase.cc:89
zypp::repo::RepoInfoBase::alias
std::string alias() const
unique identifier for this source.
Definition RepoInfoBase.cc:110
zypp::xml::Node::localName
XmlString localName() const
The local name of the node.
Definition Node.h:114
zypp::xml::Node::nodeType
NodeType nodeType() const
Get the node type of the current node.
Definition Node.h:126
zypp::xml::Node::value
XmlString value() const
Provides the text value of the node if present.
Definition Node.h:143
zypp::xml::Node::getAttribute
XmlString getAttribute(const char *name_r) const
Provides a copy of the attribute value with the specified qualified name.
Definition Node.h:71
zypp::xml::Node::name
XmlString name() const
The qualified name of the node, equal to Prefix :LocalName.
Definition Node.h:118
zypp::xml::Reader
xmlTextReader based interface to iterate xml streams.
Definition Reader.h:96
zypp::xml::Reader::nextNodeAttribute
bool nextNodeAttribute()
Definition Reader.cc:162
zypp::xml::Reader::foreachNode
bool foreachNode(const ProcessNode &fnc_r)
Definition Reader.h:144
zypp::xml::XmlString
xmlChar * wrapper.
Definition XmlString.h:41
zypp::xml::XmlString::asString
std::string asString() const
Explicit conversion to std::string.
Definition XmlString.h:77
zypp::xml::XmlString::get
const xmlChar * get() const
Access the xmlChar *.
Definition XmlString.h:61
std
Definition ansi.h:855
zypp::base::NonCopyable
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition NonCopyable.h:26
zypp::callback
Callbacks light.
Definition Callback.h:146
zypp::str::strToTrue
bool strToTrue(const C_Str &str)
Parsing boolean from string.
Definition String.cc:66
zypp::str::strToTriBool
TriBool strToTriBool(const C_Str &str)
Parse str into a bool if it's a legal true or false string; else indeterminate.
Definition String.cc:96
zypp::str::form
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:39
zypp::str::strToBool
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
Definition String.h:500
zypp::str::strtonum
TInt strtonum(const C_Str &str)
Parsing numbers from string.
zypp::url
Url details namespace.
Definition UrlBase.cc:58
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition CodePitfalls.doc:2