libzypp  15.28.6
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 using namespace std;
38 
39 #undef ZYPP_BASE_LOGGER_LOGGROUP
40 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::VendorAttr"
41 
43 namespace zypp
44 {
45 
47  namespace
48  {
49 
50  typedef map<Vendor,unsigned int> VendorMap;
51  VendorMap _vendorMap;
52  unsigned int vendorGroupCounter;
53 
55  } // namespace
57 
59  namespace
60  {
61  typedef DefaultIntegral<int,0> VendorMatchEntry;
62  typedef std::unordered_map<IdString, VendorMatchEntry> VendorMatch;
63  int _nextId = -1;
64  VendorMatch _vendorMatch;
65 
67  inline void vendorMatchIdReset()
68  {
69  _nextId = -1;
70  _vendorMatch.clear();
71  }
72 
81  inline unsigned vendorMatchId( IdString vendor )
82  {
83  VendorMatchEntry & ent( _vendorMatch[vendor] );
84  if ( ! ent )
85  {
86  IdString lcvendor( str::toLower( vendor.asString() ) );
87  VendorMatchEntry & lcent( _vendorMatch[lcvendor] );
88  if ( ! lcent )
89  {
90  unsigned myid = 0;
91  // bnc#812608: no pefix compare in opensuse namespace
92  static const IdString openSUSE( "opensuse" );
93  if ( lcvendor == openSUSE || ! str::hasPrefix( lcvendor.c_str(), openSUSE.c_str() ) )
94  {
95  // Compare this entry with the global vendor map.
96  // Reversed to get the longest prefix.
97  for ( VendorMap::reverse_iterator it = _vendorMap.rbegin(); it != _vendorMap.rend(); ++it )
98  {
99  if ( str::hasPrefix( lcvendor.c_str(), it->first ) )
100  {
101  myid = it->second;
102  break; // found
103  }
104  }
105  }
106  if ( ! myid )
107  {
108  myid = --_nextId; // get a new class ID
109  }
110  ent = lcent = myid; // remember the new DI
111  }
112  else
113  {
114  ent = lcent; // take the ID from the lowercased vendor string
115  }
116  }
117  return ent;
118  }
120  } // namespace
122 
123  const VendorAttr & VendorAttr::instance()
124  {
125  static VendorAttr _val;
126  return _val;
127  }
128 
129  VendorAttr::VendorAttr ()
130  {
131  vendorGroupCounter = 1;
132  Pathname vendorPath (ZConfig::instance().vendorPath());
133  {
134  Target_Ptr trg( getZYpp()->getTarget() );
135  if ( trg )
136  vendorPath = trg->root() / vendorPath;
137  }
138  // creating entries
139  addVendorDirectory (vendorPath);
140 
141  // Checking if suse,opensuse has been defined, else create entries:
142  // - if both are defined we leve them as thay are.
143  // - if only one of them is defined, we add the other to the same group.
144  // - if both are undefined they make up a new group
145  VendorMap::const_iterator suseit( _vendorMap.find("suse") );
146  VendorMap::const_iterator opensuseit( _vendorMap.find("opensuse") );
147  if ( suseit == _vendorMap.end() )
148  {
149  if ( opensuseit == _vendorMap.end() )
150  {
151  // both are undefined
152  _vendorMap["suse"] = _vendorMap["opensuse"] = ++vendorGroupCounter;
153  }
154  else
155  {
156  // add suse to opensuse
157  _vendorMap["suse"] = opensuseit->second;
158  }
159  }
160  else if ( opensuseit == _vendorMap.end() )
161  {
162  // add opensuse to suse
163  _vendorMap["opensuse"] = suseit->second;
164  }
165 
166  MIL << *this << endl;
167  }
168 
169  void VendorAttr::_addVendorList( VendorList & vendorList_r ) const
170  {
171  unsigned int nextId = vendorGroupCounter + 1;
172  // convert to lowercase and check if a vendor is already defined
173  // in an existing group.
174 
175  for_( it, vendorList_r.begin(), vendorList_r.end() )
176  {
177  *it = str::toLower( *it );
178  if (_vendorMap.find(*it) != _vendorMap.end())
179  {
180  if (nextId != vendorGroupCounter + 1 &&
181  nextId != _vendorMap[*it])
182  {
183  // We have at least 3 groups which has to be mixed --> mix the third group to the first
184  unsigned int moveID = _vendorMap[*it];
185  for_( itMap, _vendorMap.begin(), _vendorMap.end() )
186  {
187  if (itMap->second == moveID)
188  itMap->second = nextId;
189  }
190  }
191  else
192  {
193  nextId = _vendorMap[*it];
194  WAR << "Vendor " << *it << " is already used in another vendor group. --> mixing these groups" << endl;
195  }
196  }
197  }
198  // add new entries
199  for_( it, vendorList_r.begin(), vendorList_r.end() )
200  {
201  _vendorMap[*it] = nextId;
202  }
203 
204  if (nextId == vendorGroupCounter + 1)
205  ++vendorGroupCounter;
206 
207  // invalidate any match cache
208  vendorMatchIdReset();
209  }
210 
211  bool VendorAttr::addVendorFile( const Pathname & filename ) const
212  {
213  parser::IniDict dict;
214 
215  if ( PathInfo(filename).isExist())
216  {
217  InputStream is(filename);
218  dict.read(is);
219  }
220  else
221  {
222  MIL << filename << " not found." << endl;
223  return false;
224  }
225 
227  sit != dict.sectionsEnd();
228  ++sit )
229  {
230  string section(*sit);
231  //MIL << section << endl;
233  it != dict.entriesEnd(*sit);
234  ++it )
235  {
236  string entry(it->first);
237  string value(it->second);
238  if ( section == "main" )
239  {
240  if ( entry == "vendors" )
241  {
242  VendorList vendorlist;
243  str::split( value, back_inserter(vendorlist), "," );
244  _addVendorList (vendorlist);
245  break;
246  }
247  }
248  }
249  }
250 
251  return true;
252  }
253 
254  bool VendorAttr::addVendorDirectory( const Pathname & dirname ) const
255  {
256  if ( ! PathInfo(dirname).isExist() )
257  {
258  MIL << dirname << " not found." << endl;
259  return false;
260  }
261 
262  list<Pathname> filenames;
263 
264  filesystem::readdir( filenames,
265  dirname, false );
266  for (list<Pathname>::iterator it = filenames.begin();
267  it != filenames.end(); ++it) {
268  MIL << "Adding file " << *it << endl;
269  addVendorFile( *it );
270  }
271  return true;
272  }
273 
275  // vendor equivalence:
277 
278  bool VendorAttr::equivalent( IdString lVendor, IdString rVendor ) const
279  {
280  if ( lVendor == rVendor )
281  return true;
282  return vendorMatchId( lVendor ) == vendorMatchId( rVendor );
283  }
284 
285  bool VendorAttr::equivalent( const Vendor & lVendor, const Vendor & rVendor ) const
286  { return equivalent( IdString( lVendor ), IdString( rVendor ) );
287  }
288 
289  bool VendorAttr::equivalent( sat::Solvable lVendor, sat::Solvable rVendor ) const
290  { return equivalent( lVendor.vendor(), rVendor.vendor() ); }
291 
292  bool VendorAttr::equivalent( const PoolItem & lVendor, const PoolItem & rVendor ) const
293  { return equivalent( lVendor.satSolvable().vendor(), rVendor.satSolvable().vendor() ); }
294 
296 
297  std::ostream & operator<<( std::ostream & str, const VendorAttr & /*obj*/ )
298  {
299  str << "Equivalent vendors:";
300  for_( it, _vendorMap.begin(), _vendorMap.end() )
301  {
302  str << endl << " [" << it->second << "] " << it->first;
303  }
304  return str;
305  }
306 
308 } // namespace zypp
310 
#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
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
unsigned split(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \t")
Split line_r into words.
Definition: String.h:518
#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
std::string toLower(const std::string &s)
Return lowercase version of s.
Definition: String.cc:175
std::ostream & operator<<(std::ostream &str, const zypp::shared_ptr< void > &obj)
Definition: PtrTypes.h:134
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
IdString vendor() const
The vendor.
Definition: Solvable.cc:345
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
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:1036