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::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 // 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() ) )
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 )
99 if ( str::hasPrefix( lcvendor.c_str(), it->first ) )
108 myid = --_nextId; // get a new class ID
110 ent = lcent = myid; // remember the new DI
114 ent = lcent; // take the ID from the lowercased vendor string
119 /////////////////////////////////////////////////////////////////
121 ///////////////////////////////////////////////////////////////////
123 const VendorAttr & VendorAttr::instance()
125 static VendorAttr _val;
129 VendorAttr::VendorAttr ()
131 vendorGroupCounter = 1;
132 Pathname vendorPath (ZConfig::instance().vendorPath());
134 Target_Ptr trg( getZYpp()->getTarget() );
136 vendorPath = trg->root() / vendorPath;
139 addVendorDirectory (vendorPath);
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() )
149 if ( opensuseit == _vendorMap.end() )
151 // both are undefined
152 _vendorMap["suse"] = _vendorMap["opensuse"] = ++vendorGroupCounter;
156 // add suse to opensuse
157 _vendorMap["suse"] = opensuseit->second;
160 else if ( opensuseit == _vendorMap.end() )
162 // add opensuse to suse
163 _vendorMap["opensuse"] = suseit->second;
166 MIL << *this << endl;
169 void VendorAttr::_addVendorList( VendorList & vendorList_r ) const
171 unsigned int nextId = vendorGroupCounter + 1;
172 // convert to lowercase and check if a vendor is already defined
173 // in an existing group.
175 for_( it, vendorList_r.begin(), vendorList_r.end() )
177 *it = str::toLower( *it );
178 if (_vendorMap.find(*it) != _vendorMap.end())
180 if (nextId != vendorGroupCounter + 1 &&
181 nextId != _vendorMap[*it])
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() )
187 if (itMap->second == moveID)
188 itMap->second = nextId;
193 nextId = _vendorMap[*it];
194 WAR << "Vendor " << *it << " is already used in another vendor group. --> mixing these groups" << endl;
199 for_( it, vendorList_r.begin(), vendorList_r.end() )
201 _vendorMap[*it] = nextId;
204 if (nextId == vendorGroupCounter + 1)
205 ++vendorGroupCounter;
207 // invalidate any match cache
208 vendorMatchIdReset();
211 bool VendorAttr::addVendorFile( const Pathname & filename ) const
213 parser::IniDict dict;
215 if ( PathInfo(filename).isExist())
217 InputStream is(filename);
222 MIL << filename << " not found." << endl;
226 for ( parser::IniDict::section_const_iterator sit = dict.sectionsBegin();
227 sit != dict.sectionsEnd();
230 string section(*sit);
231 //MIL << section << endl;
232 for ( parser::IniDict::entry_const_iterator it = dict.entriesBegin(*sit);
233 it != dict.entriesEnd(*sit);
236 string entry(it->first);
237 string value(it->second);
238 if ( section == "main" )
240 if ( entry == "vendors" )
242 VendorList vendorlist;
243 str::split( value, back_inserter(vendorlist), "," );
244 _addVendorList (vendorlist);
254 bool VendorAttr::addVendorDirectory( const Pathname & dirname ) const
256 if ( ! PathInfo(dirname).isExist() )
258 MIL << dirname << " not found." << endl;
262 list<Pathname> filenames;
264 filesystem::readdir( filenames,
266 for (list<Pathname>::iterator it = filenames.begin();
267 it != filenames.end(); ++it) {
268 MIL << "Adding file " << *it << endl;
269 addVendorFile( *it );
274 //////////////////////////////////////////////////////////////////
275 // vendor equivalence:
276 //////////////////////////////////////////////////////////////////
278 bool VendorAttr::equivalent( IdString lVendor, IdString rVendor ) const
280 if ( lVendor == rVendor )
282 return vendorMatchId( lVendor ) == vendorMatchId( rVendor );
285 bool VendorAttr::equivalent( const Vendor & lVendor, const Vendor & rVendor ) const
286 { return equivalent( IdString( lVendor ), IdString( rVendor ) );
289 bool VendorAttr::equivalent( sat::Solvable lVendor, sat::Solvable rVendor ) const
290 { return equivalent( lVendor.vendor(), rVendor.vendor() ); }
292 bool VendorAttr::equivalent( const PoolItem & lVendor, const PoolItem & rVendor ) const
293 { return equivalent( lVendor.satSolvable().vendor(), rVendor.satSolvable().vendor() ); }
295 //////////////////////////////////////////////////////////////////
297 std::ostream & operator<<( std::ostream & str, const VendorAttr & /*obj*/ )
299 str << "Equivalent vendors:";
300 for_( it, _vendorMap.begin(), _vendorMap.end() )
302 str << endl << " [" << it->second << "] " << it->first;
307 /////////////////////////////////////////////////////////////////
309 ///////////////////////////////////////////////////////////////////