libzypp  17.28.5
VendorAttr.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
11 #include <iostream>
12 #include <fstream>
13 #include <set>
14 #include <map>
15 #include <vector>
16 
17 #include <zypp/base/LogTools.h>
18 #include <zypp/base/IOStream.h>
19 #include <zypp/base/StringV.h>
20 
21 #include <zypp/PathInfo.h>
22 #include <zypp/VendorAttr.h>
23 #include <zypp/ZYppFactory.h>
24 
25 #include <zypp/ZConfig.h>
26 #include <zypp/PathInfo.h>
27 #include <zypp/parser/IniDict.h>
28 
29 #undef ZYPP_BASE_LOGGER_LOGGROUP
30 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::VendorAttr"
31 
33 namespace zypp
34 {
35 
40  class VendorAttr::Impl // : private base::NonCopyable
41  {
42  friend std::ostream & operator<<( std::ostream & str, const Impl & obj );
43  public:
50  Impl()
51  { _vendorGroupMap["suse"] = ++_vendorGroupId; }
52 
53  public:
55  void addVendorList( VendorList && vendorList_r );
56 
58  bool equivalent( IdString lVendor, IdString rVendor ) const
59  { return lVendor == rVendor || vendorMatchId( lVendor ) == vendorMatchId( rVendor ); }
60 
62  bool relaxedEquivalent( IdString lVendor, IdString rVendor ) const
63  {
64  if ( equivalent( lVendor, rVendor ) )
65  return true;
66 
67  static const IdString suse { "suse" };
68  static const IdString opensuse { "opensuse" };
69  unsigned sid = vendorMatchId( suse );
70  unsigned oid = vendorMatchId( opensuse );
71  if ( sid == oid )
72  return false; // (suse/opensuse) are equivalent, so these are not
73 
74  auto isSuse = [sid,oid]( unsigned v )-> bool { return v==sid || v==oid; };
75  return isSuse( vendorMatchId(lVendor) ) && isSuse( vendorMatchId(rVendor) );
76  }
77 
78  unsigned foreachVendorList( std::function<bool(VendorList)> fnc_r ) const
79  {
80  std::map<unsigned,VendorList> lists;
81  for( const auto & el : _vendorGroupMap )
82  lists[el.second].push_back( el.first );
83 
84  unsigned ret = 0;
85  for ( auto el : lists ) {
86  VendorList & vlist { el.second };
87  if ( vlist.empty() )
88  continue;
89  ++ret;
90  if ( fnc_r && !fnc_r( std::move(vlist) ) )
91  break;
92  }
93  return ret;
94  }
95 
96  private:
97  using VendorGroupMap = std::map<std::string,unsigned>;
99  unsigned _vendorGroupId = 0;
100 
101  private:
103  typedef std::unordered_map<IdString, VendorMatchEntry> VendorMatch;
105  mutable unsigned _nextId = 0;
106 
109  {
110  _nextId = 0;
111  _vendorMatch.clear();
112  }
113 
121  unsigned vendorMatchId( IdString vendor ) const;
122 
123  private:
124  friend Impl * rwcowClone<Impl>( const Impl * rhs );
126  Impl * clone() const
127  { return new Impl( *this ); }
128  };
129 
130  unsigned VendorAttr::Impl::vendorMatchId( IdString vendor ) const
131  {
132  VendorMatchEntry & ent { _vendorMatch[vendor] };
133  if ( ! ent )
134  {
135  IdString lcvendor { str::toLower( vendor.asString() ) };
136  VendorMatchEntry & lcent( _vendorMatch[lcvendor] );
137  if ( ! lcent )
138  {
139  // Cache miss - check whether it belongs to a vendor group.
140  // Otherwise assign a new class ID to it.
141  unsigned myid = 0;
142 
143  // bnc#812608: no prefix compare in opensuse namespace
144  if ( str::hasPrefix( lcvendor.c_str(), "opensuse" ) )
145  {
146  if ( auto it = _vendorGroupMap.find( lcvendor.c_str() ); it != _vendorGroupMap.end() )
147  myid = it->second;
148  }
149  else
150  {
151  // Compare this entry with the global vendor map.
152  // Reversed to get the longest prefix.
153  for ( VendorGroupMap::const_reverse_iterator it = _vendorGroupMap.rbegin(); it != _vendorGroupMap.rend(); ++it )
154  {
155  if ( str::hasPrefix( lcvendor.c_str(), it->first ) ) {
156  myid = it->second;
157  break; // found
158  }
159  }
160  }
161 
162  if ( ! myid )
163  myid = --_nextId; // get a new class ID
164 
165  ent = lcent = myid; // remember the new DI
166  }
167  else
168  ent = lcent; // take the ID from the lowercased vendor string
169  }
170  return ent;
171  }
172 
174  {
175  // Will add a new equivalence group unless we merge with existing groups.
176  unsigned targetId = _vendorGroupId + 1;
177 
178  // (!) Convert the group strings in place to lowercase before adding/checking.
179  // Extend/join already existing groups if they are referenced.
180  for ( std::string & vendor : vendorList_r )
181  {
182  vendor = str::toLower( std::move(vendor) );
183 
184  if ( _vendorGroupMap.count( vendor ) )
185  {
186  unsigned joinId = _vendorGroupMap[vendor];
187  if ( targetId == _vendorGroupId + 1 ) {
188  targetId = joinId; // will extend the existing group
189  }
190  else if ( targetId != joinId ) {
191  // yet another existing group -> join it into the target group
192  for ( auto & el : _vendorGroupMap ) {
193  if ( el.second == joinId )
194  el.second = targetId;
195  }
196  }
197  vendor.clear(); // no need to add it later
198  }
199  }
200 
201  // Now add the new entries
202  for ( std::string & vendor : vendorList_r ) {
203  if ( ! vendor.empty() )
204  _vendorGroupMap[vendor] = targetId;
205  }
206 
207  if ( targetId == _vendorGroupId + 1 )
208  ++_vendorGroupId;
209 
210  // invalidate any match cache
211  vendorMatchIdReset();
212  }
213 
215  inline std::ostream & operator<<( std::ostream & str, const VendorAttr::Impl & obj )
216  {
217  str << "Equivalent vendors:";
218  for( const auto & p : obj._vendorGroupMap ) {
219  str << endl << " [" << p.second << "] " << p.first;
220  }
221  return str;
222  }
223 
225  //
226  // CLASS NAME : VendorAttr
227  //
229 
231  {
232  Target_Ptr trg { getZYpp()->getTarget() };
233  return trg ? trg->vendorAttr() : noTargetInstance();
234  }
235 
237  {
238  static VendorAttr _val { ZConfig::instance().vendorPath() };
239  return _val;
240  }
241 
243  : _pimpl( new Impl )
244  {
245  MIL << "Initial: " << *this << endl;
246  }
247 
248  VendorAttr::VendorAttr( const Pathname & initial_r )
249  : _pimpl( new Impl )
250  {
251  addVendorDirectory( initial_r );
252  MIL << "Initial " << initial_r << ": " << *this << endl;
253  }
254 
256  {}
257 
258  bool VendorAttr::addVendorDirectory( const Pathname & dirname_r )
259  {
260  if ( PathInfo pi { dirname_r }; ! pi.isDir() ) {
261  MIL << "Not a directory " << pi << endl;
262  return false;
263  }
264 
266  [this]( const Pathname & dir_r, const std::string & str_r )->bool
267  {
268  this->addVendorFile( dir_r/str_r );
269  return true;
270  }
271  );
272  return true;
273  }
274 
275  bool VendorAttr::addVendorFile( const Pathname & filename_r )
276  {
277  if ( PathInfo pi { filename_r }; ! pi.isFile() ) {
278  MIL << "Not a file " << pi << endl;
279  return false;
280  }
281 
282  parser::IniDict dict { InputStream(filename_r) };
283  for ( const auto & el : dict.entries("main") )
284  {
285  if ( el.first == "vendors" )
286  {
287  VendorList tmp;
288  strv::split( el.second, ",", strv::Trim::trim,
289  [&tmp]( std::string_view word ) {
290  if ( ! word.empty() )
291  tmp.push_back( std::string(word) );
292  } );
293  _addVendorList( std::move(tmp) );
294  break;
295  }
296  }
297  return true;
298  }
299 
300  void VendorAttr::_addVendorList( VendorList && vendorList_r )
301  { _pimpl->addVendorList( std::move(vendorList_r) ); }
302 
303  unsigned VendorAttr::foreachVendorList( std::function<bool(VendorList)> fnc_r ) const
304  { return _pimpl->foreachVendorList( std::move(fnc_r) ); }
305 
306 #if LEGACY(1722)
307  bool VendorAttr::addVendorDirectory( const Pathname & dirname ) const
308  { return const_cast<VendorAttr*>(this)->addVendorDirectory( dirname ); }
309 
310  bool VendorAttr::addVendorFile( const Pathname & filename ) const
311  { return const_cast<VendorAttr*>(this)->addVendorFile( filename ); }
312 
313  void VendorAttr::_addVendorList( std::vector<std::string> & vendorList_r ) const
314  { return const_cast<VendorAttr*>(this)->_addVendorList( VendorList( vendorList_r.begin(), vendorList_r.end() ) ); }
315 
316  void VendorAttr::_addVendorList( std::vector<IdString> && list_r )
317  {
318  VendorList tmp;
319  for ( const auto & el : list_r )
320  tmp.push_back( std::string(el) );
321  _addVendorList( std::move(tmp) );
322  }
323 #endif
324  // vendor equivalence:
327 
328  bool VendorAttr::equivalent( IdString lVendor, IdString rVendor ) const
329  { return _pimpl->equivalent( lVendor, rVendor );}
330 
331  bool VendorAttr::equivalent( const Vendor & lVendor, const Vendor & rVendor ) const
332  { return _pimpl->equivalent( IdString( lVendor ), IdString( rVendor ) ); }
333 
334  bool VendorAttr::equivalent( sat::Solvable lVendor, sat::Solvable rVendor ) const
335  { return _pimpl->equivalent( lVendor.vendor(), rVendor.vendor() ); }
336 
337  bool VendorAttr::equivalent( const PoolItem & lVendor, const PoolItem & rVendor ) const
338  { return _pimpl->equivalent( lVendor.satSolvable().vendor(), rVendor.satSolvable().vendor() ); }
339 
340 
341  bool VendorAttr::relaxedEquivalent( IdString lVendor, IdString rVendor ) const
342  { return _pimpl->relaxedEquivalent( lVendor, rVendor );}
343 
344  bool VendorAttr::relaxedEquivalent( const Vendor & lVendor, const Vendor & rVendor ) const
345  { return _pimpl->relaxedEquivalent( IdString( lVendor ), IdString( rVendor ) ); }
346 
348  { return _pimpl->relaxedEquivalent( lVendor.vendor(), rVendor.vendor() ); }
349 
350  bool VendorAttr::relaxedEquivalent( const PoolItem & lVendor, const PoolItem & rVendor ) const
351  { return _pimpl->relaxedEquivalent( lVendor.satSolvable().vendor(), rVendor.satSolvable().vendor() ); }
352 
354 
355  std::ostream & operator<<( std::ostream & str, const VendorAttr & obj )
356  { return str << *obj._pimpl; }
357 
359 } // namespace zypp
361 
VendorMatch _vendorMatch
Cache mapping vendor strings to equivalence class ID.
Definition: VendorAttr.cc:104
#define MIL
Definition: Logger.h:96
A Solvable object within the sat Pool.
Definition: Solvable.h:53
IdString vendor() const
The vendor.
Definition: Solvable.cc:357
std::ostream & operator<<(std::ostream &str, const VendorAttr::Impl &obj)
Definition: VendorAttr.cc:215
unsigned _nextId
Least equivalence class ID in use (decremented).
Definition: VendorAttr.cc:105
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:126
bool equivalent(const Vendor &lVendor, const Vendor &rVendor) const
Return whether two vendor strings should be treated as the same vendor.
Definition: VendorAttr.cc:331
std::ostream & operator<<(std::ostream &str, const InputStream &obj)
Definition: InputStream.cc:166
VendorAttr()
Ctor providing the default set.
Definition: VendorAttr.cc:242
void addVendorList(VendorList &&vendorList_r)
Add a new equivalent vendor set.
Definition: VendorAttr.cc:173
RWCOW_pointer< Impl > _pimpl
Implementation class.
Definition: VendorAttr.h:161
DefaultIntegral< unsigned, 0 > VendorMatchEntry
Definition: VendorAttr.cc:102
unsigned foreachVendorList(std::function< bool(VendorList)> fnc_r) const
Definition: VendorAttr.cc:78
int dirForEach(const Pathname &dir_r, const StrMatcher &matcher_r, function< bool(const Pathname &, const char *const)> fnc_r)
Definition: PathInfo.cc:32
std::vector< std::string > VendorList
Preferred type to pass equivalent vendor strings.
Definition: VendorAttr.h:103
String related utilities and Regular expression matching.
unsigned foreachVendorList(std::function< bool(VendorList)> fnc_r) const
Call fnc_r for each equivalent vendor list (return false to break).
Definition: VendorAttr.cc:303
bool addVendorDirectory(const Pathname &dirname_r)
Adding new equivalent vendors described in a directory.
Definition: VendorAttr.cc:258
std::string Vendor
Definition: Vendor.h:22
Access to the sat-pools string space.
Definition: IdString.h:42
Pathname vendorPath() const
Directory for equivalent vendor definitions (configPath()/vendors.d)
Definition: ZConfig.cc:1024
Helper to create and pass std::istream.
Definition: InputStream.h:56
void _addVendorList(VendorList &&list_r)
Definition: VendorAttr.cc:300
bool addVendorFile(const Pathname &filename_r)
Adding new equivalent vendors described in a file.
Definition: VendorAttr.cc:275
Impl * clone() const
clone for RWCOW_pointer
Definition: VendorAttr.cc:126
~VendorAttr()
Dtor.
Definition: VendorAttr.cc:255
VendorAttr implementation.
Definition: VendorAttr.cc:40
const StrMatcher & matchNoDots()
Convenience returning StrMatcher( "[^.]*", Match::GLOB )
Definition: PathInfo.cc:26
unsigned split(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \, const Trim trim_r=NO_TRIM)
Split line_r into words.
Definition: String.h:531
std::string trim(const std::string &s, const Trim trim_r)
Definition: String.cc:223
static VendorAttr & noTargetInstance()
Singleton, settings used if no Target is active.
Definition: VendorAttr.cc:236
void vendorMatchIdReset()
Reset vendor match cache if _vendorGroupMap was changed.
Definition: VendorAttr.cc:108
Definition of vendor equivalence.
Definition: VendorAttr.h:60
bool relaxedEquivalent(const Vendor &lVendor, const Vendor &rVendor) const
Like equivalent but always unifies suse and openSUSE vendor.
Definition: VendorAttr.cc:344
bool equivalent(IdString lVendor, IdString rVendor) const
Return whether two vendor strings should be treated as equivalent.
Definition: VendorAttr.cc:58
std::string toLower(const std::string &s)
Return lowercase version of s.
Definition: String.cc:177
Parses a INI file and offers its structure as a dictionary.
Definition: IniDict.h:41
friend std::ostream & operator<<(std::ostream &str, const Impl &obj)
std::unordered_map< IdString, VendorMatchEntry > VendorMatch
Definition: VendorAttr.cc:103
unsigned _vendorGroupId
Highest group ID in use (incremented).
Definition: VendorAttr.cc:99
VendorGroupMap _vendorGroupMap
Vendor group definition. Equivalent groups share the same ID.
Definition: VendorAttr.cc:98
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:218
Combining sat::Solvable and ResStatus.
Definition: PoolItem.h:50
std::string asString() const
Conversion to std::string
Definition: IdString.h:98
std::map< std::string, unsigned > VendorGroupMap
Definition: VendorAttr.cc:97
static const VendorAttr & instance()
(Pseudo)Singleton, mapped to the current Target::vendorAttr settings or to noTargetInstance.
Definition: VendorAttr.cc:230
unsigned vendorMatchId(IdString vendor) const
Helper mapping a vendor string to it&#39;s eqivalence class ID.
Definition: VendorAttr.cc:130
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
Solvable satSolvable() const
Return the corresponding sat::Solvable.
Definition: SolvableType.h:57
bool relaxedEquivalent(IdString lVendor, IdString rVendor) const
Return whether two vendor strings should be treated as equivalent or are (suse/opensuse).
Definition: VendorAttr.cc:62
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:1027