libzypp  11.13.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  // Compare this entry with the global vendor map.
92  // Reversed to get the longes prefix.
93  for ( VendorMap::reverse_iterator it = _vendorMap.rbegin(); it != _vendorMap.rend(); ++it )
94  {
95  if ( str::hasPrefix( lcvendor.c_str(), it->first ) )
96  {
97  myid = it->second;
98  break; // found
99  }
100  }
101  if ( ! myid )
102  {
103  myid = --_nextId; // get a new class ID
104  }
105  ent = lcent = myid; // remember the new DI
106  }
107  else
108  {
109  ent = lcent; // take the ID from the lowercased vendor string
110  }
111  }
112  return ent;
113  }
115  } // namespace
117 
118  const VendorAttr & VendorAttr::instance()
119  {
120  static VendorAttr _val;
121  return _val;
122  }
123 
124  VendorAttr::VendorAttr ()
125  {
126  vendorGroupCounter = 1;
127  Pathname vendorPath (ZConfig::instance().vendorPath());
128  try
129  {
130  Target_Ptr trg( getZYpp()->target() );
131  if ( trg )
132  vendorPath = trg->root() / vendorPath;
133  }
134  catch ( ... )
135  {
136  // noop: Someone decided to let target() throw if the ptr is NULL ;(
137  }
138 
139  // creating entries
140  addVendorDirectory (vendorPath);
141 
142  // Checking if suse,opensuse has been defined, else create entries:
143  // - if both are defined we leve them as thay are.
144  // - if only one of them is defined, we add the other to the same group.
145  // - if both are undefined they make up a new group
146  VendorMap::const_iterator suseit( _vendorMap.find("suse") );
147  VendorMap::const_iterator opensuseit( _vendorMap.find("opensuse") );
148  if ( suseit == _vendorMap.end() )
149  {
150  if ( opensuseit == _vendorMap.end() )
151  {
152  // both are undefined
153  _vendorMap["suse"] = _vendorMap["opensuse"] = ++vendorGroupCounter;
154  }
155  else
156  {
157  // add suse to opensuse
158  _vendorMap["suse"] = opensuseit->second;
159  }
160  }
161  else if ( opensuseit == _vendorMap.end() )
162  {
163  // add opensuse to suse
164  _vendorMap["opensuse"] = suseit->second;
165  }
166 
167  // Take care 'opensuse build service' gets it's own class.
168  VendorMap::const_iterator obsit( _vendorMap.find("opensuse build service") );
169  if ( obsit == _vendorMap.end() )
170  {
171  _vendorMap["opensuse build service"] = ++vendorGroupCounter;
172  }
173 
174 
175  MIL << *this << endl;
176  }
177 
178  void VendorAttr::_addVendorList( VendorList & vendorList_r ) const
179  {
180  unsigned int nextId = vendorGroupCounter + 1;
181  // convert to lowercase and check if a vendor is already defined
182  // in an existing group.
183 
184  for_( it, vendorList_r.begin(), vendorList_r.end() )
185  {
186  *it = str::toLower( *it );
187  if (_vendorMap.find(*it) != _vendorMap.end())
188  {
189  if (nextId != vendorGroupCounter + 1 &&
190  nextId != _vendorMap[*it])
191  {
192  // We have at least 3 groups which has to be mixed --> mix the third group to the first
193  unsigned int moveID = _vendorMap[*it];
194  for_( itMap, _vendorMap.begin(), _vendorMap.end() )
195  {
196  if (itMap->second == moveID)
197  itMap->second = nextId;
198  }
199  }
200  else
201  {
202  nextId = _vendorMap[*it];
203  WAR << "Vendor " << *it << " is already used in another vendor group. --> mixing these groups" << endl;
204  }
205  }
206  }
207  // add new entries
208  for_( it, vendorList_r.begin(), vendorList_r.end() )
209  {
210  _vendorMap[*it] = nextId;
211  }
212 
213  if (nextId == vendorGroupCounter + 1)
214  ++vendorGroupCounter;
215 
216  // invalidate any match cache
217  vendorMatchIdReset();
218  }
219 
220  bool VendorAttr::addVendorFile( const Pathname & filename ) const
221  {
222  parser::IniDict dict;
223 
224  if ( PathInfo(filename).isExist())
225  {
226  InputStream is(filename);
227  dict.read(is);
228  }
229  else
230  {
231  MIL << filename << " not found." << endl;
232  return false;
233  }
234 
236  sit != dict.sectionsEnd();
237  ++sit )
238  {
239  string section(*sit);
240  //MIL << section << endl;
242  it != dict.entriesEnd(*sit);
243  ++it )
244  {
245  string entry(it->first);
246  string value(it->second);
247  if ( section == "main" )
248  {
249  if ( entry == "vendors" )
250  {
251  VendorList vendorlist;
252  str::split( value, back_inserter(vendorlist), "," );
253  _addVendorList (vendorlist);
254  break;
255  }
256  }
257  }
258  }
259 
260  return true;
261  }
262 
263  bool VendorAttr::addVendorDirectory( const Pathname & dirname ) const
264  {
265  parser::IniDict dict;
266 
267  if ( PathInfo(dirname).isExist())
268  {
269  InputStream is(dirname);
270  dict.read(is);
271  }
272  else
273  {
274  MIL << dirname << " not found." << endl;
275  return false;
276  }
277 
278  list<Pathname> filenames;
279 
280  filesystem::readdir( filenames,
281  dirname, false );
282  for (list<Pathname>::iterator it = filenames.begin();
283  it != filenames.end(); ++it) {
284  MIL << "Adding file " << *it << endl;
285  addVendorFile( *it );
286  }
287  return true;
288  }
289 
291  // vendor equivalence:
293 
294  bool VendorAttr::equivalent( IdString lVendor, IdString rVendor ) const
295  {
296  if ( lVendor == rVendor )
297  return true;
298  return vendorMatchId( lVendor ) == vendorMatchId( rVendor );
299  }
300 
301  bool VendorAttr::equivalent( const Vendor & lVendor, const Vendor & rVendor ) const
302  { return equivalent( IdString( lVendor ), IdString( rVendor ) );
303  }
304 
305  bool VendorAttr::equivalent( sat::Solvable lVendor, sat::Solvable rVendor ) const
306  { return equivalent( lVendor.vendor(), rVendor.vendor() ); }
307 
308  bool VendorAttr::equivalent( const PoolItem & lVendor, const PoolItem & rVendor ) const
309  { return equivalent( lVendor.satSolvable().vendor(), rVendor.satSolvable().vendor() ); }
310 
312 
313  std::ostream & operator<<( std::ostream & str, const VendorAttr & /*obj*/ )
314  {
315  str << "Equivalent vendors:";
316  for_( it, _vendorMap.begin(), _vendorMap.end() )
317  {
318  str << endl << " [" << it->second << "] " << it->first;
319  }
320  return str;
321  }
322 
324 } // namespace zypp
326