libzypp
10.5.0
|
00001 /*---------------------------------------------------------------------\ 00002 | ____ _ __ __ ___ | 00003 | |__ / \ / / . \ . \ | 00004 | / / \ V /| _/ _/ | 00005 | / /__ | | | | | | | 00006 | /_____||_| |_| |_| | 00007 | | 00008 \---------------------------------------------------------------------*/ 00009 /* 00010 File: VendorAttr.cc 00011 00012 Author: Michael Andres <ma@suse.de> 00013 Maintainer: Michael Andres <ma@suse.de> 00014 00015 Purpose: Manage vendor attributes 00016 00017 /-*/ 00018 00019 #include <iostream> 00020 #include <fstream> 00021 #include <set> 00022 #include <map> 00023 #include <vector> 00024 00025 #include "zypp/base/LogTools.h" 00026 #include "zypp/base/IOStream.h" 00027 #include "zypp/base/String.h" 00028 00029 #include "zypp/PathInfo.h" 00030 #include "zypp/VendorAttr.h" 00031 #include "zypp/ZYppFactory.h" 00032 00033 #include "zypp/ZConfig.h" 00034 #include "zypp/PathInfo.h" 00035 #include "zypp/parser/IniDict.h" 00036 00037 using namespace std; 00038 00039 #undef ZYPP_BASE_LOGGER_LOGGROUP 00040 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::VendorAttr" 00041 00043 namespace zypp 00044 { 00045 00047 namespace 00048 { 00049 00050 typedef map<Vendor,unsigned int> VendorMap; 00051 VendorMap _vendorMap; 00052 unsigned int vendorGroupCounter; 00053 00055 } // namespace 00057 00059 namespace 00060 { 00061 typedef DefaultIntegral<int,0> VendorMatchEntry; 00062 typedef std::tr1::unordered_map<IdString, VendorMatchEntry> VendorMatch; 00063 int _nextId = -1; 00064 VendorMatch _vendorMatch; 00065 00067 inline void vendorMatchIdReset() 00068 { 00069 _nextId = -1; 00070 _vendorMatch.clear(); 00071 } 00072 00081 inline unsigned vendorMatchId( IdString vendor ) 00082 { 00083 VendorMatchEntry & ent( _vendorMatch[vendor] ); 00084 if ( ! ent ) 00085 { 00086 IdString lcvendor( str::toLower( vendor.asString() ) ); 00087 VendorMatchEntry & lcent( _vendorMatch[lcvendor] ); 00088 if ( ! lcent ) 00089 { 00090 unsigned myid = 0; 00091 // Compare this entry with the global vendor map. 00092 // Reversed to get the longes prefix. 00093 for ( VendorMap::reverse_iterator it = _vendorMap.rbegin(); it != _vendorMap.rend(); ++it ) 00094 { 00095 if ( str::hasPrefix( lcvendor.c_str(), it->first ) ) 00096 { 00097 myid = it->second; 00098 break; // found 00099 } 00100 } 00101 if ( ! myid ) 00102 { 00103 myid = --_nextId; // get a new class ID 00104 } 00105 ent = lcent = myid; // remember the new DI 00106 } 00107 else 00108 { 00109 ent = lcent; // take the ID from the lowercased vendor string 00110 } 00111 } 00112 return ent; 00113 } 00115 } // namespace 00117 00118 const VendorAttr & VendorAttr::instance() 00119 { 00120 static VendorAttr _val; 00121 return _val; 00122 } 00123 00124 VendorAttr::VendorAttr () 00125 { 00126 vendorGroupCounter = 1; 00127 Pathname vendorPath (ZConfig::instance().vendorPath()); 00128 try 00129 { 00130 Target_Ptr trg( getZYpp()->target() ); 00131 if ( trg ) 00132 vendorPath = trg->root() / vendorPath; 00133 } 00134 catch ( ... ) 00135 { 00136 // noop: Someone decided to let target() throw if the ptr is NULL ;( 00137 } 00138 00139 // creating entries 00140 addVendorDirectory (vendorPath); 00141 00142 // Checking if suse,opensuse has been defined, else create entries: 00143 // - if both are defined we leve them as thay are. 00144 // - if only one of them is defined, we add the other to the same group. 00145 // - if both are undefined they make up a new group 00146 VendorMap::const_iterator suseit( _vendorMap.find("suse") ); 00147 VendorMap::const_iterator opensuseit( _vendorMap.find("opensuse") ); 00148 if ( suseit == _vendorMap.end() ) 00149 { 00150 if ( opensuseit == _vendorMap.end() ) 00151 { 00152 // both are undefined 00153 _vendorMap["suse"] = _vendorMap["opensuse"] = ++vendorGroupCounter; 00154 } 00155 else 00156 { 00157 // add suse to opensuse 00158 _vendorMap["suse"] = opensuseit->second; 00159 } 00160 } 00161 else if ( opensuseit == _vendorMap.end() ) 00162 { 00163 // add opensuse to suse 00164 _vendorMap["opensuse"] = suseit->second; 00165 } 00166 00167 // Take care 'opensuse build service' gets it's own class. 00168 VendorMap::const_iterator obsit( _vendorMap.find("opensuse build service") ); 00169 if ( obsit == _vendorMap.end() ) 00170 { 00171 _vendorMap["opensuse build service"] = ++vendorGroupCounter; 00172 } 00173 00174 00175 MIL << *this << endl; 00176 } 00177 00178 void VendorAttr::_addVendorList( VendorList & vendorList_r ) const 00179 { 00180 unsigned int nextId = vendorGroupCounter + 1; 00181 // convert to lowercase and check if a vendor is already defined 00182 // in an existing group. 00183 00184 for_( it, vendorList_r.begin(), vendorList_r.end() ) 00185 { 00186 *it = str::toLower( *it ); 00187 if (_vendorMap.find(*it) != _vendorMap.end()) 00188 { 00189 if (nextId != vendorGroupCounter + 1 && 00190 nextId != _vendorMap[*it]) 00191 { 00192 // We have at least 3 groups which has to be mixed --> mix the third group to the first 00193 unsigned int moveID = _vendorMap[*it]; 00194 for_( itMap, _vendorMap.begin(), _vendorMap.end() ) 00195 { 00196 if (itMap->second == moveID) 00197 itMap->second = nextId; 00198 } 00199 } 00200 else 00201 { 00202 nextId = _vendorMap[*it]; 00203 WAR << "Vendor " << *it << " is already used in another vendor group. --> mixing these groups" << endl; 00204 } 00205 } 00206 } 00207 // add new entries 00208 for_( it, vendorList_r.begin(), vendorList_r.end() ) 00209 { 00210 _vendorMap[*it] = nextId; 00211 } 00212 00213 if (nextId == vendorGroupCounter + 1) 00214 ++vendorGroupCounter; 00215 00216 // invalidate any match cache 00217 vendorMatchIdReset(); 00218 } 00219 00220 bool VendorAttr::addVendorFile( const Pathname & filename ) const 00221 { 00222 parser::IniDict dict; 00223 00224 if ( PathInfo(filename).isExist()) 00225 { 00226 InputStream is(filename); 00227 dict.read(is); 00228 } 00229 else 00230 { 00231 MIL << filename << " not found." << endl; 00232 return false; 00233 } 00234 00235 for ( parser::IniDict::section_const_iterator sit = dict.sectionsBegin(); 00236 sit != dict.sectionsEnd(); 00237 ++sit ) 00238 { 00239 string section(*sit); 00240 //MIL << section << endl; 00241 for ( parser::IniDict::entry_const_iterator it = dict.entriesBegin(*sit); 00242 it != dict.entriesEnd(*sit); 00243 ++it ) 00244 { 00245 string entry(it->first); 00246 string value(it->second); 00247 if ( section == "main" ) 00248 { 00249 if ( entry == "vendors" ) 00250 { 00251 VendorList vendorlist; 00252 str::split( value, back_inserter(vendorlist), "," ); 00253 _addVendorList (vendorlist); 00254 break; 00255 } 00256 } 00257 } 00258 } 00259 00260 return true; 00261 } 00262 00263 bool VendorAttr::addVendorDirectory( const Pathname & dirname ) const 00264 { 00265 parser::IniDict dict; 00266 00267 if ( PathInfo(dirname).isExist()) 00268 { 00269 InputStream is(dirname); 00270 dict.read(is); 00271 } 00272 else 00273 { 00274 MIL << dirname << " not found." << endl; 00275 return false; 00276 } 00277 00278 list<Pathname> filenames; 00279 00280 filesystem::readdir( filenames, 00281 dirname, false ); 00282 for (list<Pathname>::iterator it = filenames.begin(); 00283 it != filenames.end(); ++it) { 00284 MIL << "Adding file " << *it << endl; 00285 addVendorFile( *it ); 00286 } 00287 return true; 00288 } 00289 00291 // vendor equivalence: 00293 00294 bool VendorAttr::equivalent( IdString lVendor, IdString rVendor ) const 00295 { 00296 if ( lVendor == rVendor ) 00297 return true; 00298 return vendorMatchId( lVendor ) == vendorMatchId( rVendor ); 00299 } 00300 00301 bool VendorAttr::equivalent( const Vendor & lVendor, const Vendor & rVendor ) const 00302 { return equivalent( IdString( lVendor ), IdString( rVendor ) ); 00303 } 00304 00305 bool VendorAttr::equivalent( sat::Solvable lVendor, sat::Solvable rVendor ) const 00306 { return equivalent( lVendor.vendor(), rVendor.vendor() ); } 00307 00308 bool VendorAttr::equivalent( const PoolItem & lVendor, const PoolItem & rVendor ) const 00309 { return equivalent( lVendor.satSolvable().vendor(), rVendor.satSolvable().vendor() ); } 00310 00312 00313 std::ostream & operator<<( std::ostream & str, const VendorAttr & /*obj*/ ) 00314 { 00315 str << "Equivalent vendors:"; 00316 for_( it, _vendorMap.begin(), _vendorMap.end() ) 00317 { 00318 str << endl << " [" << it->second << "] " << it->first; 00319 } 00320 return str; 00321 } 00322 00324 } // namespace zypp 00326