libzypp 17.37.0
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/base/String.h>
16#include <zypp/base/Logger.h>
17#include <zypp/base/Gettext.h>
18#include <utility>
19#include <zypp-core/base/InputStream>
20#include <zypp-core/base/DefaultIntegral>
21
22#include <zypp/Pathname.h>
23
25#include <zypp-core/parser/ParseException>
26
27#include <zypp/RepoInfo.h>
28
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 setVar( const std::string & key_r, const std::string & val_r )
52 {
53 //MIL << "*** Inject " << key_r << " = " << val_r;
54 _vars[key_r] = replace( val_r );
55 //MIL << " (" << _vars[key_r] << ")" << endl;
56 }
57
58 std::string replace( const std::string & val_r ) const
59 {
60 std::string::size_type vbeg = val_r.find( "%{", 0 );
61 if ( vbeg == std::string::npos )
62 return val_r;
63
64 str::Str ret;
65 std::string::size_type cbeg = 0;
66 for( ; vbeg != std::string::npos; vbeg = val_r.find( "%{", vbeg ) )
67 {
68 std::string::size_type nbeg = vbeg+2;
69 std::string::size_type nend = val_r.find( '}', nbeg );
70 if ( nend == std::string::npos )
71 {
72 WAR << "Incomplete variable in '" << val_r << "'" << endl;
73 break;
74 }
75 const auto & iter = _vars.find( val_r.substr( nbeg, nend-nbeg ) );
76 if ( iter != _vars.end() )
77 {
78 if ( cbeg < vbeg )
79 ret << val_r.substr( cbeg, vbeg-cbeg );
80 ret << iter->second;
81 cbeg = nend+1;
82 }
83 else
84 WAR << "Undefined variable %{" << val_r.substr( nbeg, nend-nbeg ) << "} in '" << val_r << "'" << endl;
85 vbeg = nend+1;
86 }
87 if ( cbeg < val_r.size() )
88 ret << val_r.substr( cbeg );
89
90 return ret;
91 }
92 private:
93 std::unordered_map<std::string,std::string> _vars;
94 };
95 } // namespace
97
99 //
100 // CLASS NAME : RepoindexFileReader::Impl
101 //
103 {
104 public:
111
115 bool consumeNode( Reader & reader_r );
116
118
119 private:
120 bool getAttrValue( const std::string & key_r, Reader & reader_r, std::string & value_r )
121 {
122 const XmlString & s( reader_r->getAttribute( key_r ) );
123 if ( s.get() )
124 {
125 value_r = _replacer.replace( s.asString() );
126 return !value_r.empty();
127 }
128 value_r.clear();
129 return false;
130 }
131
132 private:
135 VarReplacer _replacer;
136 };
137
138
141 : _callback(std::move(callback))
142 {
143 Reader reader( is );
144 MIL << "Reading " << is.path() << endl;
145 reader.foreachNode( bind( &RepoindexFileReader::Impl::consumeNode, this, _1 ) );
146 }
147
148 // --------------------------------------------------------------------------
149
150 /*
151 * xpath and multiplicity of processed nodes are included in the code
152 * for convenience:
153 *
154 * // xpath: <xpath> (?|*|+)
155 *
156 * if multiplicity is ommited, then the node has multiplicity 'one'.
157 */
158
159 // --------------------------------------------------------------------------
160
162 {
163 if ( reader_r->nodeType() == XML_READER_TYPE_ELEMENT )
164 {
165 // xpath: /repoindex
166 if ( reader_r->name() == "repoindex" )
167 {
168 while ( reader_r.nextNodeAttribute() )
169 {
170 const std::string & name( reader_r->localName().asString() );
171 const std::string & value( reader_r->value().asString() );
172 _replacer.setVar( name, value );
173 // xpath: /repoindex@ttl
174 if ( name == "ttl" )
176 }
177 return true;
178 }
179
180 // xpath: /repoindex/data (+)
181 if ( reader_r->name() == "repo" )
182 {
183 // TODO: Ideally the repo values here are interpreted the same way as
184 // corresponding ones in the RepoFileReader. Check whether we can introduce
185 // a RepoInfo ctor from a string dict. Using it here and in RepoFileReader.
186 // For now we try to parse the same way as in RepoFileReader.
187
188 RepoInfo info;
189 // Set some defaults that are not contained in the repo information
190 info.setAutorefresh( true );
191 info.setEnabled(false);
192
193 std::string attrValue;
194
195 // required alias
196 // mandatory, so we can allow it in var replacement without reset
197 if ( getAttrValue( "alias", reader_r, attrValue ) )
198 {
199 info.setAlias( attrValue );
200 _replacer.setVar( "alias", attrValue );
201 }
202 else
203 throw ParseException(str::form(_("Required attribute '%s' is missing."), "alias"));
204
205 // required url
206 // SLES HACK: or path, but beware of the hardcoded '/repo' prefix!
207 {
208 std::string urlstr;
209 std::string pathstr;
210 getAttrValue( "url", reader_r, urlstr );
211 getAttrValue( "path", reader_r, pathstr );
212 if ( urlstr.empty() )
213 {
214 if ( pathstr.empty() )
215 throw ParseException(str::form(_("One or both of '%s' or '%s' attributes is required."), "url", "path"));
216 else
217 info.setPath( Pathname("/repo") / pathstr );
218 }
219 else
220 {
221 if ( pathstr.empty() )
222 info.setBaseUrl( Url(urlstr) );
223 else
224 {
225 Url url( urlstr );
226 url.setPathName( Pathname(url.getPathName()) / "repo" / pathstr );
227 info.setBaseUrl( url );
228 }
229 }
230 }
231
232 // optional name
233 if ( getAttrValue( "name", reader_r, attrValue ) )
234 info.setName( attrValue );
235
236 // optional targetDistro
237 if ( getAttrValue( "distro_target", reader_r, attrValue ) )
238 info.setTargetDistribution( attrValue );
239
240 // optional priority
241 if ( getAttrValue( "priority", reader_r, attrValue ) )
242 info.setPriority( str::strtonum<unsigned>( attrValue ) );
243
244 // optional enabled
245 if ( getAttrValue( "enabled", reader_r, attrValue ) )
246 info.setEnabled( str::strToBool( attrValue, info.enabled() ) );
247
248 // optional autorefresh
249 if ( getAttrValue( "autorefresh", reader_r, attrValue ) )
250 info.setAutorefresh( str::strToBool( attrValue, info.autorefresh() ) );
251
252 // optional *gpgcheck
253 if ( getAttrValue( "gpgcheck", reader_r, attrValue ) )
254 info.setGpgCheck( str::strToTriBool( attrValue ) );
255 if ( getAttrValue( "repo_gpgcheck", reader_r, attrValue ) )
256 info.setRepoGpgCheck( str::strToTrue( attrValue ) );
257 if ( getAttrValue( "pkg_gpgcheck", reader_r, attrValue ) )
258 info.setPkgGpgCheck( str::strToTrue( attrValue ) );
259
260 // optional keeppackages
261 if ( getAttrValue( "keeppackages", reader_r, attrValue ) )
262 info.setKeepPackages( str::strToTrue( attrValue ) );
263
264 // optional gpgkey
265 if ( getAttrValue( "gpgkey", reader_r, attrValue ) )
266 info.setGpgKeyUrl( Url(attrValue) );
267
268 // optional mirrorlist
269 if ( getAttrValue( "mirrorlist", reader_r, attrValue ) )
270 info.setMirrorListUrl( Url(attrValue) );
271
272 // optional metalink
273 if ( getAttrValue( "metalink", reader_r, attrValue ) )
274 info.setMetalinkUrl( Url(attrValue) );
275
276 DBG << info << endl;
277
278 // ignore the rest
279 // Specially: bsc#1177427 et.al.: type in a .repo file is legacy - ignore it
280 _callback(info);
281 return true;
282 }
283 }
284
285 return true;
286 }
287
288
290 //
291 // CLASS NAME : RepoindexFileReader
292 //
294
296 : _pimpl(new Impl( InputStream(std::move(repoindex_file)), std::move(callback) ))
297 {}
298
302
305
307
308 } // ns parser
309} // ns zypp
310
311// vim: set ts=2 sts=2 sw=2 et ai:
Interface of repoindex.xml file reader.
time_t Duration
Definition Date.h:39
Integral type with defined initial value when default constructed.
Helper to create and pass std::istream.
Definition inputstream.h:57
const Pathname & path() const
Path to the input file or empty if no file.
What is known about a repository.
Definition RepoInfo.h:72
void setPkgGpgCheck(TriBool value_r)
Set the value for pkgGpgCheck (or indeterminate to use the default).
Definition RepoInfo.cc:542
void setMetalinkUrl(const Url &url)
Like setMirrorListUrl but expect metalink format.
Definition RepoInfo.cc:628
void setGpgKeyUrl(const Url &gpgkey)
(leagcy API) Set the gpgkey URL defined for this repo
Definition RepoInfo.cc:637
void setKeepPackages(bool keep)
Set if packaqes downloaded from this repository will be kept in local cache.
Definition RepoInfo.cc:698
void setMirrorListUrl(const Url &url)
Set mirror list url.
Definition RepoInfo.cc:622
void setBaseUrl(Url url)
Clears current base URL list and adds url.
Definition RepoInfo.cc:656
void setGpgCheck(TriBool value_r)
Set the value for gpgCheck (or indeterminate to use the default).
Definition RepoInfo.cc:514
void setTargetDistribution(const std::string &targetDistribution)
Sets the distribution for which is this repository meant.
Definition RepoInfo.cc:704
void setPath(const Pathname &path)
set the product path.
Definition RepoInfo.cc:679
void setPriority(unsigned newval_r)
Set repository priority for solver.
Definition RepoInfo.cc:507
void setRepoGpgCheck(TriBool value_r)
Set the value for repoGpgCheck (or indeterminate to use the default).
Definition RepoInfo.cc:532
Url manipulation class.
Definition Url.h:93
DefaultIntegral< Date::Duration, 0 > _ttl
bool consumeNode(Reader &reader_r)
Callback provided to the XML parser.
Impl(const InputStream &is, ProcessResource &&callback)
CTOR.
ProcessResource _callback
Function for processing collected data.
bool getAttrValue(const std::string &key_r, Reader &reader_r, std::string &value_r)
function< bool(const RepoInfo &)> ProcessResource
Callback definition.
RW_pointer< Impl, rw_pointer::Scoped< Impl > > _pimpl
RepoindexFileReader(Pathname repoindexFile, ProcessResource callback)
CTOR.
Date::Duration ttl() const
Metadata TTL (repoindex.xml:xpath:/repoindex@ttl or 0).
void setAutorefresh(bool autorefresh)
enable or disable autorefresh
void setAlias(const std::string &alias)
set the repository alias
void setName(const std::string &name)
set the repository name
bool autorefresh() const
If true, the repostory must be refreshed before creating resolvables from it.
bool enabled() const
If enabled is false, then this repository must be ignored as if does not exists, except when checking...
void setEnabled(bool enabled)
enable or disable the repository
XmlString localName() const
The local name of the node.
Definition Node.h:114
NodeType nodeType() const
Get the node type of the current node.
Definition Node.h:126
XmlString value() const
Provides the text value of the node if present.
Definition Node.h:143
XmlString getAttribute(const char *name_r) const
Provides a copy of the attribute value with the specified qualified name.
Definition Node.h:71
XmlString name() const
The qualified name of the node, equal to Prefix :LocalName.
Definition Node.h:118
xmlTextReader based interface to iterate xml streams.
Definition Reader.h:96
bool nextNodeAttribute()
Definition Reader.cc:162
bool foreachNode(const ProcessNode &fnc_r)
Definition Reader.h:144
xmlChar * wrapper.
Definition XmlString.h:41
std::string asString() const
Explicit conversion to std::string.
Definition XmlString.h:77
const xmlChar * get() const
Access the xmlChar *.
Definition XmlString.h:61
Definition Arch.h:364
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition NonCopyable.h:26
Callbacks light.
Definition Callback.h:146
bool strToTrue(const C_Str &str)
Parsing boolean from string.
Definition String.cc:66
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
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:39
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
Definition String.h:500
TInt strtonum(const C_Str &str)
Parsing numbers from string.
Url details namespace.
Definition UrlBase.cc:58
Easy-to use interface to the ZYPP dependency resolver.
#define _(MSG)
Definition Gettext.h:39
#define DBG
Definition Logger.h:99
#define MIL
Definition Logger.h:100
#define WAR
Definition Logger.h:101
Interface to gettext.