libzypp  17.25.1
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 
61  private:
62  using VendorGroupMap = std::map<std::string,unsigned>;
64  unsigned _vendorGroupId = 0;
65 
66  private:
68  typedef std::unordered_map<IdString, VendorMatchEntry> VendorMatch;
70  mutable unsigned _nextId = 0;
71 
74  {
75  _nextId = 0;
76  _vendorMatch.clear();
77  }
78 
86  unsigned vendorMatchId( IdString vendor ) const;
87 
88  private:
89  friend Impl * rwcowClone<Impl>( const Impl * rhs );
91  Impl * clone() const
92  { return new Impl( *this ); }
93  };
94 
95  unsigned VendorAttr::Impl::vendorMatchId( IdString vendor ) const
96  {
97  VendorMatchEntry & ent { _vendorMatch[vendor] };
98  if ( ! ent )
99  {
100  IdString lcvendor { str::toLower( vendor.asString() ) };
101  VendorMatchEntry & lcent( _vendorMatch[lcvendor] );
102  if ( ! lcent )
103  {
104  // Cache miss - check whether it belongs to a vendor group.
105  // Otherwise assign a new class ID to it.
106  unsigned myid = 0;
107 
108  // bnc#812608: no prefix compare in opensuse namespace
109  if ( str::hasPrefix( lcvendor.c_str(), "opensuse" ) )
110  {
111  if ( auto it = _vendorGroupMap.find( lcvendor.c_str() ); it != _vendorGroupMap.end() )
112  myid = it->second;
113  }
114  else
115  {
116  // Compare this entry with the global vendor map.
117  // Reversed to get the longest prefix.
118  for ( VendorGroupMap::const_reverse_iterator it = _vendorGroupMap.rbegin(); it != _vendorGroupMap.rend(); ++it )
119  {
120  if ( str::hasPrefix( lcvendor.c_str(), it->first ) ) {
121  myid = it->second;
122  break; // found
123  }
124  }
125  }
126 
127  if ( ! myid )
128  myid = --_nextId; // get a new class ID
129 
130  ent = lcent = myid; // remember the new DI
131  }
132  else
133  ent = lcent; // take the ID from the lowercased vendor string
134  }
135  return ent;
136  }
137 
139  {
140  // Will add a new equivalence group unless we merge with existing groups.
141  unsigned targetId = _vendorGroupId + 1;
142 
143  // (!) Convert the group strings in place to lowercase before adding/checking.
144  // Extend/join already existing groups if they are referenced.
145  for ( std::string & vendor : vendorList_r )
146  {
147  vendor = str::toLower( std::move(vendor) );
148 
149  if ( _vendorGroupMap.count( vendor ) )
150  {
151  unsigned joinId = _vendorGroupMap[vendor];
152  if ( targetId == _vendorGroupId + 1 ) {
153  targetId = joinId; // will extend the existing group
154  }
155  else if ( targetId != joinId ) {
156  // yet another existing group -> join it into the target group
157  for ( auto & el : _vendorGroupMap ) {
158  if ( el.second == joinId )
159  el.second = targetId;
160  }
161  }
162  vendor.clear(); // no need to add it later
163  }
164  }
165 
166  // Now add the new entries
167  for ( std::string & vendor : vendorList_r ) {
168  if ( ! vendor.empty() )
169  _vendorGroupMap[vendor] = targetId;
170  }
171 
172  if ( targetId == _vendorGroupId + 1 )
173  ++_vendorGroupId;
174 
175  // invalidate any match cache
176  vendorMatchIdReset();
177  }
178 
180  inline std::ostream & operator<<( std::ostream & str, const VendorAttr::Impl & obj )
181  {
182  str << "Equivalent vendors:";
183  for( const auto & p : obj._vendorGroupMap ) {
184  str << endl << " [" << p.second << "] " << p.first;
185  }
186  return str;
187  }
188 
190  //
191  // CLASS NAME : VendorAttr
192  //
194 
196  {
197  Target_Ptr trg { getZYpp()->getTarget() };
198  return trg ? trg->vendorAttr() : noTargetInstance();
199  }
200 
202  {
203  static VendorAttr _val { ZConfig::instance().vendorPath() };
204  return _val;
205  }
206 
208  : _pimpl( new Impl )
209  {
210  MIL << "Initial: " << *this << endl;
211  }
212 
213  VendorAttr::VendorAttr( const Pathname & initial_r )
214  : _pimpl( new Impl )
215  {
216  addVendorDirectory( initial_r );
217  MIL << "Initial " << initial_r << ": " << *this << endl;
218  }
219 
221  {}
222 
223  bool VendorAttr::addVendorDirectory( const Pathname & dirname_r )
224  {
225  if ( PathInfo pi { dirname_r }; ! pi.isDir() ) {
226  MIL << "Not a directory " << pi << endl;
227  return false;
228  }
229 
231  [this]( const Pathname & dir_r, const std::string & str_r )->bool
232  {
233  this->addVendorFile( dir_r/str_r );
234  return true;
235  }
236  );
237  return true;
238  }
239 
240  bool VendorAttr::addVendorFile( const Pathname & filename_r )
241  {
242  if ( PathInfo pi { filename_r }; ! pi.isFile() ) {
243  MIL << "Not a file " << pi << endl;
244  return false;
245  }
246 
247  parser::IniDict dict { InputStream(filename_r) };
248  for ( const auto & el : dict.entries("main") )
249  {
250  if ( el.first == "vendors" )
251  {
252  VendorList tmp;
253  strv::split( el.second, ",", strv::Trim::trim,
254  [&tmp]( std::string_view word ) {
255  if ( ! word.empty() )
256  tmp.push_back( std::string(word) );
257  } );
258  _addVendorList( std::move(tmp) );
259  break;
260  }
261  }
262  return true;
263  }
264 
265  void VendorAttr::_addVendorList( VendorList && vendorList_r )
266  { _pimpl->addVendorList( std::move(vendorList_r) ); }
267 
268 #if LEGACY(1722)
269  bool VendorAttr::addVendorDirectory( const Pathname & dirname ) const
270  { return const_cast<VendorAttr*>(this)->addVendorDirectory( dirname ); }
271 
272  bool VendorAttr::addVendorFile( const Pathname & filename ) const
273  { return const_cast<VendorAttr*>(this)->addVendorFile( filename ); }
274 
275  void VendorAttr::_addVendorList( std::vector<std::string> & vendorList_r ) const
276  { return const_cast<VendorAttr*>(this)->_addVendorList( VendorList( vendorList_r.begin(), vendorList_r.end() ) ); }
277 
278  void VendorAttr::_addVendorList( std::vector<IdString> && list_r )
279  {
280  VendorList tmp;
281  for ( const auto & el : list_r )
282  tmp.push_back( std::string(el) );
283  _addVendorList( std::move(tmp) );
284  }
285 #endif
286  // vendor equivalence:
289 
290  bool VendorAttr::equivalent( IdString lVendor, IdString rVendor ) const
291  { return _pimpl->equivalent( lVendor, rVendor );}
292 
293  bool VendorAttr::equivalent( const Vendor & lVendor, const Vendor & rVendor ) const
294  { return _pimpl->equivalent( IdString( lVendor ), IdString( rVendor ) ); }
295 
296  bool VendorAttr::equivalent( sat::Solvable lVendor, sat::Solvable rVendor ) const
297  { return _pimpl->equivalent( lVendor.vendor(), rVendor.vendor() ); }
298 
299  bool VendorAttr::equivalent( const PoolItem & lVendor, const PoolItem & rVendor ) const
300  { return _pimpl->equivalent( lVendor.satSolvable().vendor(), rVendor.satSolvable().vendor() ); }
301 
303 
304  std::ostream & operator<<( std::ostream & str, const VendorAttr & obj )
305  { return str << *obj._pimpl; }
306 
308 } // namespace zypp
310 
zypp::VendorAttr::_pimpl
RWCOW_pointer< Impl > _pimpl
Implementation class.
Definition: VendorAttr.h:146
zypp::PoolItem
Combining sat::Solvable and ResStatus.
Definition: PoolItem.h:50
zypp::Vendor
std::string Vendor
Definition: Vendor.h:22
zypp::filesystem::matchNoDots
const StrMatcher & matchNoDots()
Convenience returning StrMatcher( "[^.]*", Match::GLOB )
Definition: PathInfo.cc:531
PathInfo.h
zypp::VendorAttr::Impl::VendorMatchEntry
DefaultIntegral< unsigned, 0 > VendorMatchEntry
Definition: VendorAttr.cc:67
zypp::sat::Solvable
A Solvable object within the sat Pool.
Definition: Solvable.h:53
ZYppFactory.h
zypp::VendorAttr::equivalent
bool equivalent(const Vendor &lVendor, const Vendor &rVendor) const
Return whether two vendor strings should be treated as the same vendor.
Definition: VendorAttr.cc:293
zypp::VendorAttr::Impl::vendorMatchId
unsigned vendorMatchId(IdString vendor) const
Helper mapping a vendor string to it's eqivalence class ID.
Definition: VendorAttr.cc:95
zypp::VendorAttr::Impl::_vendorMatch
VendorMatch _vendorMatch
Cache mapping vendor strings to equivalence class ID.
Definition: VendorAttr.cc:69
zypp::sat::SolvableType::satSolvable
Solvable satSolvable() const
Return the corresponding sat::Solvable.
Definition: SolvableType.h:57
zypp::VendorAttr::Impl::operator<<
std::ostream & operator<<(std::ostream &str, const VendorAttr::Impl &obj)
Definition: VendorAttr.cc:180
zypp::VendorAttr::Impl::_nextId
unsigned _nextId
Least equivalence class ID in use (decremented).
Definition: VendorAttr.cc:70
zypp::VendorAttr::addVendorDirectory
bool addVendorDirectory(const Pathname &dirname_r)
Adding new equivalent vendors described in a directory.
Definition: VendorAttr.cc:223
ZConfig.h
MIL
#define MIL
Definition: Logger.h:79
zypp::ZConfig::vendorPath
Pathname vendorPath() const
Directory for equivalent vendor definitions (configPath()/vendors.d)
Definition: ZConfig.cc:996
zypp::VendorAttr
Definition of vendor equivalence.
Definition: VendorAttr.h:60
IOStream.h
zypp::parser::IniDict
Parses a INI file and offers its structure as a dictionary.
Definition: IniDict.h:41
zypp::IdString::asString
std::string asString() const
Conversion to std::string
Definition: IdString.h:98
zypp::IdString
Access to the sat-pools string space.
Definition: IdString.h:42
zypp::VendorAttr::Impl::clone
Impl * clone() const
clone for RWCOW_pointer
Definition: VendorAttr.cc:91
LogTools.h
zypp::filesystem::PathInfo
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:220
zypp::strv::split
unsigned split(std::string_view line_r, std::string_view sep_r, Trim trim_r, std::function< void(std::string_view)> fnc_r)
Definition: StringV.cc:20
zypp::VendorAttr::Impl::equivalent
bool equivalent(IdString lVendor, IdString rVendor) const
Return whether two vendor strings should be treated as equivalent.
Definition: VendorAttr.cc:58
zypp::VendorAttr::Impl::Impl
Impl()
Ctor.
Definition: VendorAttr.cc:50
zypp::VendorAttr::addVendorFile
bool addVendorFile(const Pathname &filename_r)
Adding new equivalent vendors described in a file.
Definition: VendorAttr.cc:240
zypp::ZConfig::instance
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:126
zypp::InputStream
Helper to create and pass std::istream.
Definition: InputStream.h:56
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
zypp::str::toLower
std::string toLower(const std::string &s)
Return lowercase version of s.
Definition: String.cc:172
zypp::VendorAttr::Impl::vendorMatchIdReset
void vendorMatchIdReset()
Reset vendor match cache if _vendorGroupMap was changed.
Definition: VendorAttr.cc:73
zypp::VendorAttr::_addVendorList
void _addVendorList(VendorList &&list_r)
Definition: VendorAttr.cc:265
zypp::VendorAttr::Impl::operator<<
friend std::ostream & operator<<(std::ostream &str, const Impl &obj)
zypp::DefaultIntegral< unsigned, 0 >
zypp::VendorAttr::Impl::VendorMatch
std::unordered_map< IdString, VendorMatchEntry > VendorMatch
Definition: VendorAttr.cc:68
zypp::operator<<
std::ostream & operator<<(std::ostream &str, const Exception &obj)
Definition: Exception.cc:147
IniDict.h
Target_Ptr
zypp::VendorAttr::VendorList
std::vector< std::string > VendorList
Preferred type to pass equivalent vendor strings.
Definition: VendorAttr.h:103
zypp::filesystem::Pathname
Pathname.
Definition: Pathname.h:44
zypp::VendorAttr::Impl::_vendorGroupId
unsigned _vendorGroupId
Highest group ID in use (incremented).
Definition: VendorAttr.cc:64
VendorAttr.h
zypp::VendorAttr::instance
static const VendorAttr & instance()
(Pseudo)Singleton, mapped to the current Target::vendorAttr settings or to noTargetInstance.
Definition: VendorAttr.cc:195
zypp::VendorAttr::Impl::_vendorGroupMap
VendorGroupMap _vendorGroupMap
Vendor group definition. Equivalent groups share the same ID.
Definition: VendorAttr.cc:63
zypp::VendorAttr::Impl
VendorAttr implementation.
Definition: VendorAttr.cc:40
zypp::VendorAttr::~VendorAttr
~VendorAttr()
Dtor.
Definition: VendorAttr.cc:220
str
String related utilities and Regular expression matching.
zypp::str::hasPrefix
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:1023
zypp::VendorAttr::Impl::VendorGroupMap
std::map< std::string, unsigned > VendorGroupMap
Definition: VendorAttr.cc:62
zypp::str::trim
std::string trim(const std::string &s, const Trim trim_r)
Definition: String.cc:216
zypp::VendorAttr::Impl::addVendorList
void addVendorList(VendorList &&vendorList_r)
Add a new equivalent vendor set.
Definition: VendorAttr.cc:138
zypp::filesystem::dirForEach
int dirForEach(const Pathname &dir_r, function< bool(const Pathname &, const char *const)> fnc_r)
Invoke callback function fnc_r for each entry in directory dir_r.
Definition: PathInfo.cc:537
zypp::VendorAttr::noTargetInstance
static VendorAttr & noTargetInstance()
Singleton, settings used if no Target is active.
Definition: VendorAttr.cc:201
StringV.h
zypp::sat::Solvable::vendor
IdString vendor() const
The vendor.
Definition: Solvable.cc:356
zypp::VendorAttr::VendorAttr
VendorAttr()
Ctor providing the default set.
Definition: VendorAttr.cc:207