12#include <zypp/base/LogTools.h>
13#include <zypp/base/String.h>
14#include <zypp/base/Regex.h>
21#include <zypp/base/NonCopyable.h>
23#define ZYPP_DBG_VAREXPAND 0
24#if ( ZYPP_DBG_VAREXPAND )
25#warning ZYPP_DBG_VAREXPAND is on
37 const char * env = getenv(
"ZYPP_REPO_RELEASEVER");
38 return( env ? env :
"" );
64 FindVar(
const std::string & str_r,
bool embedded_r )
66 ,
_sbeg( str_r.c_str() )
85 if ( _vbeg && !_vend )
86 _send = findVarStart( _vbeg+1 );
91 }
while( ! findVarEnd() );
105 std::string var()
const
106 {
return std::string( _vbeg, _vend ); }
109 std::string varName()
const
110 {
return std::string( _nbeg, _nend ); }
113 bool varIsConditional()
const
114 {
return( *(_vbeg+1) ==
'{' && *_nend ==
':' ); }
123 {
return( varIsConditional() ? *(_nend+1) : *_vbeg ); }
126 std::string varEmbedded()
const
127 {
return( varIsConditional() ? std::string( _nend+2, _vend-1 ) : std::string() ); }
131 bool hasVarPrefix()
const
132 {
return ( _sbeg != _vbeg ); }
135 std::string varPrefix()
const
136 {
return std::string( _sbeg, _vbeg ); }
144 const char * findVarStart(
const char * sbeg_r )
const
146 for ( ; *sbeg_r; ++sbeg_r )
147 if ( *sbeg_r ==
'$' || ( _embedded && *sbeg_r ==
'\\' ) )
153 bool isnamech(
int ch )
const
154 {
return ch ==
'_' || isalnum( ch ); }
160 if ( ! findVarEnd( _vbeg, _nbeg, _nend, _vend ) )
162 _send = findVarStart( _vend );
167 const char * findVarEnd(
const char * vbeg )
const
170 const char * nbeg =
nullptr;
171 const char * nend =
nullptr;
172 const char * vend =
nullptr;
173 findVarEnd( vbeg, nbeg, nend, vend );
178 bool findVarEnd(
const char * vbeg,
const char *& nbeg,
const char *& nend,
const char *& vend )
const
181 if ( *_vbeg ==
'\\' )
188 nend = vend = vbeg+2;
197 bool braced = ( *(vbeg+1) ==
'{' );
198 nbeg = vbeg+( braced ? 2 : 1 );
199 if ( !isnamech( *nbeg ) )
201 for ( nend = nbeg+1; isnamech( *nend ); ++nend )
213 else if ( *nend ==
':' )
215 const char * scan = nend+1;
216 if ( *scan ==
'+' || *scan ==
'-' )
228 else if ( *scan ==
'$' )
231 if ( ! (scan = findVarEnd( scan )) )
234 else if ( *scan ==
'}' )
254 return( vend !=
nullptr );
263 if ( ! _expand( ret, value_r, level_r, varRetriever_r ) )
271 if ( ! _expand( ret, value_r, level_r, varRetriever_r ) )
272 ret = std::move(value_r);
279 inline bool _expand( std::string & result_r,
const std::string & value_r,
unsigned level_r,
RepoVarExpand::VarRetriever & varRetriever_r )
281#if ( ZYPP_DBG_VAREXPAND )
282 cout << std::string( 2*level_r,
' ' ) <<
"\033[7m>>" << value_r <<
"<<\033[27m" << endl;
283 std::ostringstream dbg;
284 const char * dbgsbeg = value_r.c_str();
286 dbg << std::string( 2*level_r,
' ' ) <<
">>";
289 bool expanded =
false;
291 if ( ! value_r.empty() )
293 FindVar scan( value_r, level_r );
294 while ( scan.nextVar() )
296 static const std::string _emptyValue;
297 const std::string *
const knownVar = ( varRetriever_r ? varRetriever_r( scan.varName() ) :
nullptr );
298 const std::string & varValue( knownVar ? *knownVar : _emptyValue );
300#if ( ZYPP_DBG_VAREXPAND )
301 dbg << std::string(dbgsbeg,scan._vbeg) <<
"\033[3" << ((dbgi%5)+1) <<
"m" << scan.var() <<
"\033[0m";
302 cout << dbg.str() <<
"|<< " << scan.varName() <<
" " << (knownVar?
"("+varValue+
")":
"-") <<
" {" << scan.varEmbedded() <<
"}" << endl;
303 dbgsbeg = scan._vend;
307 bool mustSubstitute =
false;
308 std::string substitutionValue;
310 int varType = scan.varType();
311 if ( varType ==
'$' )
315 mustSubstitute =
true;
316 substitutionValue = varValue;
321 else if ( varType ==
'-' )
323 mustSubstitute =
true;
324 if ( varValue.empty() )
325 substitutionValue = expand( scan.varEmbedded(), level_r+1, varRetriever_r );
327 substitutionValue = varValue;
329 else if ( varType ==
'+' )
331 mustSubstitute =
true;
332 if ( ! varValue.empty() )
333 substitutionValue = expand( scan.varEmbedded(), level_r+1, varRetriever_r );
337 else if ( varType ==
'\\' )
339 mustSubstitute =
true;
340 substitutionValue = scan.varName();
345 if ( mustSubstitute )
347 if ( scan.hasVarPrefix() )
348 result_r += scan.varPrefix();
349 if ( ! substitutionValue.empty() )
350 result_r += substitutionValue;
355#if ( ZYPP_DBG_VAREXPAND )
356 dbg << std::string( dbgsbeg ) << (scan._sbeg == value_r.c_str() ?
"<<\033[36m(moved)\033[0m" :
"");
360 if ( scan._sbeg != value_r.c_str() )
364 result_r += std::string( scan._sbeg );
370#if ( ZYPP_DBG_VAREXPAND )
372 cout << dbg.str() << endl;
373 cout << std::string( 2*level_r,
' ' ) <<
"\033[36m->" << result_r <<
"<-\033[0m" << endl;
381 {
return expand( value_r, 0, varRetriever_r ); }
384 {
return expand( std::move(value_r), 0, varRetriever_r ); }
391 class RepoVarsMap :
public std::map<std::string,std::string>
394 static RepoVarsMap & instance()
395 {
static RepoVarsMap _instance;
return _instance; }
397 static const std::string * lookup(
const std::string & name_r )
398 {
return instance()._lookup( name_r ); }
401 const std::string * _lookup(
const std::string & name_r )
406 auto guard { getZYpp() };
415 deriveFromReleasever(
"releasever",
false );
422 std::string & var(
operator[](
"arch" ) );
423 if ( var.empty() ) var = arch.asString();
426 std::string & var(
operator[](
"basearch" ) );
427 if ( var.empty() ) var = arch.baseArch().asString();
432 const std::string * ret = checkOverride( name_r );
436 iterator it = find( name_r );
444 std::ostream &
dumpOn( std::ostream &
str )
const
446 for (
auto && kv : *
this )
448 str <<
'{' << kv.first <<
'=' << kv.second <<
'}' << endl;
455 bool parse(
const Pathname & dir_r,
const std::string & str_r )
457 std::ifstream file( (dir_r/str_r).c_str() );
463 void deriveFromReleasever(
const std::string & stem_r,
bool overwrite_r )
465 if ( count( stem_r ) )
467 const std::string & stem_major( stem_r+
"_major" );
468 const std::string & stem_minor( stem_r+
"_minor" );
470 splitReleaseverTo(
operator[]( stem_r ), &
operator[]( stem_major ), &
operator[]( stem_minor ) );
472 splitReleaseverTo(
operator[]( stem_r ),
473 count( stem_major ) ?
nullptr : &
operator[]( stem_major ),
474 count( stem_minor ) ?
nullptr : &
operator[]( stem_minor ) );
479 void splitReleaseverTo(
const std::string & releasever_r, std::string * major_r, std::string * minor_r )
const
481 if ( major_r || minor_r )
483 std::string::size_type pos = releasever_r.find(
"." );
484 if ( pos == std::string::npos )
486 if ( major_r ) *major_r = releasever_r;
487 if ( minor_r ) minor_r->clear();
491 if ( major_r ) *major_r = releasever_r.substr( 0, pos );
492 if ( minor_r ) *minor_r = releasever_r.substr( pos+1 ) ;
498 const std::string * checkOverride(
const std::string & name_r )
503 && ( name_r.size() == 10
504 || strcmp( name_r.c_str()+10,
"_minor" ) == 0
505 || strcmp( name_r.c_str()+10,
"_major" ) == 0 ) )
511 if ( val !=
operator[](
"$releasever" ) )
513 operator[](
"$releasever" ) = std::move(val);
514 deriveFromReleasever(
"$releasever",
true );
516 return &operator[](
"$"+name_r );
518 else if ( !count( name_r ) )
523 val = trg->distributionVersion();
527 if ( val !=
operator[](
"$_releasever" ) )
529 operator[](
"$_releasever" ) = std::move(val);
530 deriveFromReleasever(
"$_releasever",
true );
532 return &operator[](
"$_"+name_r );
560 Url tmpurl { value };
565 if ( !replaced.empty() )
581 using namespace zypp;
584 { repo::RepoVarsMap::instance().clear(); }
const char * _nend
${variable[:]-word} / ${variable[}]
const char * _sbeg
start of string to scan
const char * _nbeg
${[v]ariable:-word} / ${[v]ariable}
const char * _vend
${variable:-word}[] / ${variable}[]
bool _embedded
A (formerly) embedded string may have esacped $, closebrace and backslash.
const char * _send
end of scan (next $ or nullptr if done)
const char * _vbeg
[$]{variable:-word} / [$]{variable} / if embedded also on [\]
std::string distributionVersion() const
This is version attribute of the installed base product.
void setViewOptions(const ViewOptions &vopts)
Change the view options of the current object.
std::string getUsername(EEncoding eflag=zypp::url::E_DECODED) const
Returns the username from the URL authority.
ViewOptions getViewOptions() const
Return the view options of the current object.
void setPassword(const std::string &pass, EEncoding eflag=zypp::url::E_DECODED)
Set the password in the URL authority.
void setUsername(const std::string &user, EEncoding eflag=zypp::url::E_DECODED)
Set the username in the URL authority.
std::string getPassword(EEncoding eflag=zypp::url::E_DECODED) const
Returns the password from the URL authority.
static ZConfig & instance()
Singleton ctor.
String related utilities and Regular expression matching.
std::string ZYPP_REPO_RELEASEVER()
Use faked releasever (e.g.
const StrMatcher & matchNoDots()
Convenience returning StrMatcher( "[^.]*", Match::GLOB )
int dirForEach(const Pathname &dir_r, const StrMatcher &matcher_r, function< bool(const Pathname &, const char *const)> fnc_r)
std::string asString(const Url &url_r)
std::string getline(std::istream &str, const Trim trim_r)
Return stream content up to (but not returning) the next newline.
bool startsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasPrefix
@ E_ENCODED
Flag to request encoded string(s).
Easy-to use interface to the ZYPP dependency resolver.
std::ostream & dumpOn(std::ostream &str, const Capability &obj)
void repoVariablesReset()
Functor expanding repo variables in a string.
function< const std::string *(const std::string &)> VarRetriever
Function taking a variable name and returning a pointer to the variable value or nullptr if unset.
std::string operator()(const std::string &value_r, VarRetriever varRetriever_r) const
Return a copy of value_r with embedded variables expanded.
std::string operator()(const std::string &value_r) const
Url operator()(const Url &url_r) const
Url::asString() view options.
static const ViewOption WITH_PASSWORD
Option to include password in the URL string.
static const ViewOption WITH_USERNAME
Option to include username in the URL string.