1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
12 Author: Michael Andres <ma@suse.de>
13 Maintainer: Michael Andres <ma@suse.de>
15 Purpose: Manage vendor attributes
25 #include "zypp/base/LogTools.h"
26 #include "zypp/base/IOStream.h"
27 #include "zypp/base/String.h"
29 #include "zypp/PathInfo.h"
30 #include "zypp/VendorAttr.h"
31 #include "zypp/ZYppFactory.h"
33 #include "zypp/ZConfig.h"
34 #include "zypp/PathInfo.h"
35 #include "zypp/parser/IniDict.h"
39 #undef ZYPP_BASE_LOGGER_LOGGROUP
40 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::VendorAttr"
42 ///////////////////////////////////////////////////////////////////
44 { /////////////////////////////////////////////////////////////////
46 ///////////////////////////////////////////////////////////////////
48 { /////////////////////////////////////////////////////////////////
50 typedef map<Vendor,unsigned int> VendorMap;
52 unsigned int vendorGroupCounter;
54 /////////////////////////////////////////////////////////////////
56 ///////////////////////////////////////////////////////////////////
58 ///////////////////////////////////////////////////////////////////
60 { /////////////////////////////////////////////////////////////////
61 typedef DefaultIntegral<int,0> VendorMatchEntry;
62 typedef std::tr1::unordered_map<IdString, VendorMatchEntry> VendorMatch;
64 VendorMatch _vendorMatch;
66 /** Reset match cache if global VendorMap was changed. */
67 inline void vendorMatchIdReset()
74 * Helper mapping vendor string to eqivalence class ID.
76 * \li Return the vendor strings eqivalence class ID stored in _vendorMatch.
77 * \li If not found, assign and return the eqivalence class ID of the lowercased string.
78 * \li If not found, assign and return a new ID (look into the predefined VendorMap (id>0),
79 * otherwise create a new ID (<0)).
81 inline unsigned vendorMatchId( IdString vendor )
83 VendorMatchEntry & ent( _vendorMatch[vendor] );
86 IdString lcvendor( str::toLower( vendor.asString() ) );
87 VendorMatchEntry & lcent( _vendorMatch[lcvendor] );
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 )
95 if ( str::hasPrefix( lcvendor.c_str(), it->first ) )
103 myid = --_nextId; // get a new class ID
105 ent = lcent = myid; // remember the new DI
109 ent = lcent; // take the ID from the lowercased vendor string
114 /////////////////////////////////////////////////////////////////
116 ///////////////////////////////////////////////////////////////////
118 const VendorAttr & VendorAttr::instance()
120 static VendorAttr _val;
124 VendorAttr::VendorAttr ()
126 vendorGroupCounter = 1;
127 Pathname vendorPath (ZConfig::instance().vendorPath());
130 Target_Ptr trg( getZYpp()->target() );
132 vendorPath = trg->root() / vendorPath;
136 // noop: Someone decided to let target() throw if the ptr is NULL ;(
140 addVendorDirectory (vendorPath);
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() )
150 if ( opensuseit == _vendorMap.end() )
152 // both are undefined
153 _vendorMap["suse"] = _vendorMap["opensuse"] = ++vendorGroupCounter;
157 // add suse to opensuse
158 _vendorMap["suse"] = opensuseit->second;
161 else if ( opensuseit == _vendorMap.end() )
163 // add opensuse to suse
164 _vendorMap["opensuse"] = suseit->second;
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() )
171 _vendorMap["opensuse build service"] = ++vendorGroupCounter;
175 MIL << *this << endl;
178 void VendorAttr::_addVendorList( VendorList & vendorList_r ) const
180 unsigned int nextId = vendorGroupCounter + 1;
181 // convert to lowercase and check if a vendor is already defined
182 // in an existing group.
184 for_( it, vendorList_r.begin(), vendorList_r.end() )
186 *it = str::toLower( *it );
187 if (_vendorMap.find(*it) != _vendorMap.end())
189 if (nextId != vendorGroupCounter + 1 &&
190 nextId != _vendorMap[*it])
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() )
196 if (itMap->second == moveID)
197 itMap->second = nextId;
202 nextId = _vendorMap[*it];
203 WAR << "Vendor " << *it << " is already used in another vendor group. --> mixing these groups" << endl;
208 for_( it, vendorList_r.begin(), vendorList_r.end() )
210 _vendorMap[*it] = nextId;
213 if (nextId == vendorGroupCounter + 1)
214 ++vendorGroupCounter;
216 // invalidate any match cache
217 vendorMatchIdReset();
220 bool VendorAttr::addVendorFile( const Pathname & filename ) const
222 parser::IniDict dict;
224 if ( PathInfo(filename).isExist())
226 InputStream is(filename);
231 MIL << filename << " not found." << endl;
235 for ( parser::IniDict::section_const_iterator sit = dict.sectionsBegin();
236 sit != dict.sectionsEnd();
239 string section(*sit);
240 //MIL << section << endl;
241 for ( parser::IniDict::entry_const_iterator it = dict.entriesBegin(*sit);
242 it != dict.entriesEnd(*sit);
245 string entry(it->first);
246 string value(it->second);
247 if ( section == "main" )
249 if ( entry == "vendors" )
251 VendorList vendorlist;
252 str::split( value, back_inserter(vendorlist), "," );
253 _addVendorList (vendorlist);
263 bool VendorAttr::addVendorDirectory( const Pathname & dirname ) const
265 parser::IniDict dict;
267 if ( PathInfo(dirname).isExist())
269 InputStream is(dirname);
274 MIL << dirname << " not found." << endl;
278 list<Pathname> filenames;
280 filesystem::readdir( filenames,
282 for (list<Pathname>::iterator it = filenames.begin();
283 it != filenames.end(); ++it) {
284 MIL << "Adding file " << *it << endl;
285 addVendorFile( *it );
290 //////////////////////////////////////////////////////////////////
291 // vendor equivalence:
292 //////////////////////////////////////////////////////////////////
294 bool VendorAttr::equivalent( IdString lVendor, IdString rVendor ) const
296 if ( lVendor == rVendor )
298 return vendorMatchId( lVendor ) == vendorMatchId( rVendor );
301 bool VendorAttr::equivalent( const Vendor & lVendor, const Vendor & rVendor ) const
302 { return equivalent( IdString( lVendor ), IdString( rVendor ) );
305 bool VendorAttr::equivalent( sat::Solvable lVendor, sat::Solvable rVendor ) const
306 { return equivalent( lVendor.vendor(), rVendor.vendor() ); }
308 bool VendorAttr::equivalent( const PoolItem & lVendor, const PoolItem & rVendor ) const
309 { return equivalent( lVendor.satSolvable().vendor(), rVendor.satSolvable().vendor() ); }
311 //////////////////////////////////////////////////////////////////
313 std::ostream & operator<<( std::ostream & str, const VendorAttr & /*obj*/ )
315 str << "Equivalent vendors:";
316 for_( it, _vendorMap.begin(), _vendorMap.end() )
318 str << endl << " [" << it->second << "] " << it->first;
323 /////////////////////////////////////////////////////////////////
325 ///////////////////////////////////////////////////////////////////