libzypp  16.22.5
VendorAttr.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
9 /*
10  File: VendorAttr.cc
11 
12  Author: Michael Andres <ma@suse.de>
13  Maintainer: Michael Andres <ma@suse.de>
14 
15  Purpose: Manage vendor attributes
16 
17 /-*/
18 
19 #include <iostream>
20 #include <fstream>
21 #include <set>
22 #include <map>
23 #include <vector>
24 
25 #include "zypp/base/LogTools.h"
26 #include "zypp/base/IOStream.h"
27 #include "zypp/base/String.h"
28 
29 #include "zypp/PathInfo.h"
30 #include "zypp/VendorAttr.h"
31 #include "zypp/ZYppFactory.h"
32 
33 #include "zypp/ZConfig.h"
34 #include "zypp/PathInfo.h"
35 #include "zypp/parser/IniDict.h"
36 
37 #undef ZYPP_BASE_LOGGER_LOGGROUP
38 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::VendorAttr"
39 
41 namespace zypp
42 {
43 
45  namespace
46  {
47 
48  typedef std::map<Vendor,unsigned> VendorMap;
49  VendorMap _vendorMap;
50  unsigned vendorGroupCounter;
51 
53  } // namespace
55 
57  namespace
58  {
59  typedef DefaultIntegral<int,0> VendorMatchEntry;
60  typedef std::unordered_map<IdString, VendorMatchEntry> VendorMatch;
61  int _nextId = -1;
62  VendorMatch _vendorMatch;
63 
65  inline void vendorMatchIdReset()
66  {
67  _nextId = -1;
68  _vendorMatch.clear();
69  }
70 
79  inline unsigned vendorMatchId( IdString vendor )
80  {
81  VendorMatchEntry & ent( _vendorMatch[vendor] );
82  if ( ! ent )
83  {
84  IdString lcvendor( str::toLower( vendor.asString() ) );
85  VendorMatchEntry & lcent( _vendorMatch[lcvendor] );
86  if ( ! lcent )
87  {
88  unsigned myid = 0;
89  // bnc#812608: no pefix compare in opensuse namespace
90  static const IdString openSUSE( "opensuse" );
91  if ( lcvendor == openSUSE || ! str::hasPrefix( lcvendor.c_str(), openSUSE.c_str() ) )
92  {
93  // Compare this entry with the global vendor map.
94  // Reversed to get the longest prefix.
95  for ( VendorMap::reverse_iterator it = _vendorMap.rbegin(); it != _vendorMap.rend(); ++it )
96  {
97  if ( str::hasPrefix( lcvendor.c_str(), it->first ) )
98  {
99  myid = it->second;
100  break; // found
101  }
102  }
103  }
104  if ( ! myid )
105  {
106  myid = --_nextId; // get a new class ID
107  }
108  ent = lcent = myid; // remember the new DI
109  }
110  else
111  {
112  ent = lcent; // take the ID from the lowercased vendor string
113  }
114  }
115  return ent;
116  }
118  } // namespace
120 
122  {
123  static VendorAttr _val;
124  return _val;
125  }
126 
128  {
129  vendorGroupCounter = 1;
130  Pathname vendorPath (ZConfig::instance().vendorPath());
131  {
132  Target_Ptr trg( getZYpp()->getTarget() );
133  if ( trg )
134  vendorPath = trg->root() / vendorPath;
135  }
136  // creating entries
137  addVendorDirectory (vendorPath);
138 
139  // bsc#1030686: The legacy default equivalence of 'suse' and 'opensuse'
140  // has been removed. Unless they are mentioned in a custom rule, create
141  // separate classes for them.
142  if ( _vendorMap.find("suse") == _vendorMap.end() )
143  _vendorMap["suse"] = ++vendorGroupCounter;
144 
145  if ( _vendorMap.find("opensuse") == _vendorMap.end() )
146  _vendorMap["opensuse"] = ++vendorGroupCounter;
147 
148  MIL << *this << endl;
149  }
150 
151  void VendorAttr::_addVendorList( VendorList & vendorList_r ) const
152  {
153  unsigned int nextId = vendorGroupCounter + 1;
154  // convert to lowercase and check if a vendor is already defined
155  // in an existing group.
156 
157  for_( it, vendorList_r.begin(), vendorList_r.end() )
158  {
159  *it = str::toLower( *it );
160  if (_vendorMap.find(*it) != _vendorMap.end())
161  {
162  if (nextId != vendorGroupCounter + 1 &&
163  nextId != _vendorMap[*it])
164  {
165  // We have at least 3 groups which has to be mixed --> mix the third group to the first
166  unsigned int moveID = _vendorMap[*it];
167  for_( itMap, _vendorMap.begin(), _vendorMap.end() )
168  {
169  if (itMap->second == moveID)
170  itMap->second = nextId;
171  }
172  }
173  else
174  {
175  nextId = _vendorMap[*it];
176  WAR << "Vendor " << *it << " is already used in another vendor group. --> mixing these groups" << endl;
177  }
178  }
179  }
180  // add new entries
181  for_( it, vendorList_r.begin(), vendorList_r.end() )
182  {
183  _vendorMap[*it] = nextId;
184  }
185 
186  if (nextId == vendorGroupCounter + 1)
187  ++vendorGroupCounter;
188 
189  // invalidate any match cache
190  vendorMatchIdReset();
191  }
192 
193  bool VendorAttr::addVendorFile( const Pathname & filename ) const
194  {
195  parser::IniDict dict;
196 
197  if ( PathInfo(filename).isExist())
198  {
199  InputStream is(filename);
200  dict.read(is);
201  }
202  else
203  {
204  MIL << filename << " not found." << endl;
205  return false;
206  }
207 
209  sit != dict.sectionsEnd();
210  ++sit )
211  {
212  std::string section(*sit);
213  //MIL << section << endl;
215  it != dict.entriesEnd(*sit);
216  ++it )
217  {
218  std::string entry(it->first);
219  std::string value(it->second);
220  if ( section == "main" )
221  {
222  if ( entry == "vendors" )
223  {
224  VendorList vendorlist;
225  str::split( value, back_inserter(vendorlist), "," );
226  _addVendorList (vendorlist);
227  break;
228  }
229  }
230  }
231  }
232 
233  return true;
234  }
235 
236  bool VendorAttr::addVendorDirectory( const Pathname & dirname ) const
237  {
238  if ( ! PathInfo(dirname).isExist() )
239  {
240  MIL << dirname << " not found." << endl;
241  return false;
242  }
243 
244  std::list<Pathname> filenames;
245  filesystem::readdir( filenames, dirname, false );
246  for_( it, filenames.begin(), filenames.end() ) {
247  MIL << "Adding file " << *it << endl;
248  addVendorFile( *it );
249  }
250  return true;
251  }
252 
254  // vendor equivalence:
256 
257  bool VendorAttr::equivalent( IdString lVendor, IdString rVendor ) const
258  {
259  if ( lVendor == rVendor )
260  return true;
261  return vendorMatchId( lVendor ) == vendorMatchId( rVendor );
262  }
263 
264  bool VendorAttr::equivalent( const Vendor & lVendor, const Vendor & rVendor ) const
265  { return equivalent( IdString( lVendor ), IdString( rVendor ) );
266  }
267 
268  bool VendorAttr::equivalent( sat::Solvable lVendor, sat::Solvable rVendor ) const
269  { return equivalent( lVendor.vendor(), rVendor.vendor() ); }
270 
271  bool VendorAttr::equivalent( const PoolItem & lVendor, const PoolItem & rVendor ) const
272  { return equivalent( lVendor.satSolvable().vendor(), rVendor.satSolvable().vendor() ); }
273 
275 
276  std::ostream & operator<<( std::ostream & str, const VendorAttr & /*obj*/ )
277  {
278  str << "Equivalent vendors:";
279  for_( it, _vendorMap.begin(), _vendorMap.end() )
280  {
281  str << endl << " [" << it->second << "] " << it->first;
282  }
283  return str;
284  }
285 
287 } // namespace zypp
289 
#define MIL
Definition: Logger.h:64
A Solvable object within the sat Pool.
Definition: Solvable.h:53
MapKVIteratorTraits< SectionSet >::Key_const_iterator section_const_iterator
Definition: IniDict.h:46
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:122
std::vector< std::string > VendorList
Definition: VendorAttr.h:46
std::string Vendor
Definition: Vendor.h:22
Access to the sat-pools string space.
Definition: IdString.h:41
Helper to create and pass std::istream.
Definition: InputStream.h:56
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:27
void read(const InputStream &is, const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
Fill a dictionary from a InputStream containing a ini structured file.
Definition: IniDict.cc:46
bool equivalent(const Vendor &lVendor, const Vendor &rVendor) const
Return whether two vendor strings should be treated as the same vendor.
Definition: VendorAttr.cc:264
unsigned split(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \t")
Split line_r into words.
Definition: String.h:519
std::ostream & operator<<(std::ostream &str, const Exception &obj)
Definition: Exception.cc:147
#define WAR
Definition: Logger.h:65
Definition of vendor equivalence.
Definition: VendorAttr.h:43
section_const_iterator sectionsBegin() const
Definition: IniDict.cc:94
entry_const_iterator entriesEnd(const std::string &section) const
Definition: IniDict.cc:82
bool addVendorDirectory(const Pathname &dirname) const
Adding new equivalent vendors described in a directory.
Definition: VendorAttr.cc:236
std::string toLower(const std::string &s)
Return lowercase version of s.
Definition: String.cc:175
Parses a INI file and offers its structure as a dictionary.
Definition: IniDict.h:40
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition: PathInfo.cc:598
void _addVendorList(VendorList &) const
Definition: VendorAttr.cc:151
IdString vendor() const
The vendor.
Definition: Solvable.cc:357
entry_const_iterator entriesBegin(const std::string &section) const
Definition: IniDict.cc:71
Solvable satSolvable() const
Return the corresponding sat::Solvable.
Definition: SolvableType.h:57
Combining sat::Solvable and ResStatus.
Definition: PoolItem.h:50
EntrySet::const_iterator entry_const_iterator
Definition: IniDict.h:47
static const VendorAttr & instance()
Singleton.
Definition: VendorAttr.cc:121
section_const_iterator sectionsEnd() const
Definition: IniDict.cc:99
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:1037
bool addVendorFile(const Pathname &filename) const
Adding new equivalent vendors described in a file.
Definition: VendorAttr.cc:193