libzypp  12.16.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 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::tr1::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  try
134  {
135  Target_Ptr trg( getZYpp()->target() );
136  if ( trg )
137  vendorPath = trg->root() / vendorPath;
138  }
139  catch ( ... )
140  {
141  // noop: Someone decided to let target() throw if the ptr is NULL ;(
142  }
143 
144  // creating entries
145  addVendorDirectory (vendorPath);
146 
147  // Checking if suse,opensuse has been defined, else create entries:
148  // - if both are defined we leve them as thay are.
149  // - if only one of them is defined, we add the other to the same group.
150  // - if both are undefined they make up a new group
151  VendorMap::const_iterator suseit( _vendorMap.find("suse") );
152  VendorMap::const_iterator opensuseit( _vendorMap.find("opensuse") );
153  if ( suseit == _vendorMap.end() )
154  {
155  if ( opensuseit == _vendorMap.end() )
156  {
157  // both are undefined
158  _vendorMap["suse"] = _vendorMap["opensuse"] = ++vendorGroupCounter;
159  }
160  else
161  {
162  // add suse to opensuse
163  _vendorMap["suse"] = opensuseit->second;
164  }
165  }
166  else if ( opensuseit == _vendorMap.end() )
167  {
168  // add opensuse to suse
169  _vendorMap["opensuse"] = suseit->second;
170  }
171 
172  MIL << *this << endl;
173  }
174 
175  void VendorAttr::_addVendorList( VendorList & vendorList_r ) const
176  {
177  unsigned int nextId = vendorGroupCounter + 1;
178  // convert to lowercase and check if a vendor is already defined
179  // in an existing group.
180 
181  for_( it, vendorList_r.begin(), vendorList_r.end() )
182  {
183  *it = str::toLower( *it );
184  if (_vendorMap.find(*it) != _vendorMap.end())
185  {
186  if (nextId != vendorGroupCounter + 1 &&
187  nextId != _vendorMap[*it])
188  {
189  // We have at least 3 groups which has to be mixed --> mix the third group to the first
190  unsigned int moveID = _vendorMap[*it];
191  for_( itMap, _vendorMap.begin(), _vendorMap.end() )
192  {
193  if (itMap->second == moveID)
194  itMap->second = nextId;
195  }
196  }
197  else
198  {
199  nextId = _vendorMap[*it];
200  WAR << "Vendor " << *it << " is already used in another vendor group. --> mixing these groups" << endl;
201  }
202  }
203  }
204  // add new entries
205  for_( it, vendorList_r.begin(), vendorList_r.end() )
206  {
207  _vendorMap[*it] = nextId;
208  }
209 
210  if (nextId == vendorGroupCounter + 1)
211  ++vendorGroupCounter;
212 
213  // invalidate any match cache
214  vendorMatchIdReset();
215  }
216 
217  bool VendorAttr::addVendorFile( const Pathname & filename ) const
218  {
219  parser::IniDict dict;
220 
221  if ( PathInfo(filename).isExist())
222  {
223  InputStream is(filename);
224  dict.read(is);
225  }
226  else
227  {
228  MIL << filename << " not found." << endl;
229  return false;
230  }
231 
233  sit != dict.sectionsEnd();
234  ++sit )
235  {
236  string section(*sit);
237  //MIL << section << endl;
239  it != dict.entriesEnd(*sit);
240  ++it )
241  {
242  string entry(it->first);
243  string value(it->second);
244  if ( section == "main" )
245  {
246  if ( entry == "vendors" )
247  {
248  VendorList vendorlist;
249  str::split( value, back_inserter(vendorlist), "," );
250  _addVendorList (vendorlist);
251  break;
252  }
253  }
254  }
255  }
256 
257  return true;
258  }
259 
260  bool VendorAttr::addVendorDirectory( const Pathname & dirname ) const
261  {
262  parser::IniDict dict;
263 
264  if ( PathInfo(dirname).isExist())
265  {
266  InputStream is(dirname);
267  dict.read(is);
268  }
269  else
270  {
271  MIL << dirname << " not found." << endl;
272  return false;
273  }
274 
275  list<Pathname> filenames;
276 
277  filesystem::readdir( filenames,
278  dirname, false );
279  for (list<Pathname>::iterator it = filenames.begin();
280  it != filenames.end(); ++it) {
281  MIL << "Adding file " << *it << endl;
282  addVendorFile( *it );
283  }
284  return true;
285  }
286 
288  // vendor equivalence:
290 
291  bool VendorAttr::equivalent( IdString lVendor, IdString rVendor ) const
292  {
293  if ( lVendor == rVendor )
294  return true;
295  return vendorMatchId( lVendor ) == vendorMatchId( rVendor );
296  }
297 
298  bool VendorAttr::equivalent( const Vendor & lVendor, const Vendor & rVendor ) const
299  { return equivalent( IdString( lVendor ), IdString( rVendor ) );
300  }
301 
302  bool VendorAttr::equivalent( sat::Solvable lVendor, sat::Solvable rVendor ) const
303  { return equivalent( lVendor.vendor(), rVendor.vendor() ); }
304 
305  bool VendorAttr::equivalent( const PoolItem & lVendor, const PoolItem & rVendor ) const
306  { return equivalent( lVendor.satSolvable().vendor(), rVendor.satSolvable().vendor() ); }
307 
309 
310  std::ostream & operator<<( std::ostream & str, const VendorAttr & /*obj*/ )
311  {
312  str << "Equivalent vendors:";
313  for_( it, _vendorMap.begin(), _vendorMap.end() )
314  {
315  str << endl << " [" << it->second << "] " << it->first;
316  }
317  return str;
318  }
319 
321 } // namespace zypp
323