{ /////////////////////////////////////////////////////////////////
typedef map<Vendor,unsigned int> VendorMap;
- typedef vector<string> VendorList;
-
VendorMap _vendorMap;
- VendorMap _matchMap;
- unsigned int vendorGroupCounter;
+ unsigned int vendorGroupCounter;
- void addEquivalentVendors( VendorList & vendorList )
+ /////////////////////////////////////////////////////////////////
+ } // namespace
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ namespace
+ { /////////////////////////////////////////////////////////////////
+ typedef DefaultIntegral<int,0> VendorMatchEntry;
+ typedef std::tr1::unordered_map<IdString, VendorMatchEntry> VendorMatch;
+ int _nextId = -1;
+ VendorMatch _vendorMatch;
+
+ /** Reset match cache if global VendorMap was changed. */
+ inline void vendorMatchIdReset()
{
- unsigned int nextId = vendorGroupCounter + 1;
- // convert to lowercase and check if a vendor is already defined
- // in an existing group.
+ _nextId = -1;
+ _vendorMatch.clear();
+ }
- for (VendorList::iterator it = vendorList.begin();
- it != vendorList.end();
- it++) {
- *it = str::toLower( *it );
- if (_vendorMap.find(*it) != _vendorMap.end()) {
- if (nextId != vendorGroupCounter + 1 &&
- nextId != _vendorMap[*it]) {
- // We have at least 3 groups which has to be mixed --> mix the third group to the first
- unsigned int moveID = _vendorMap[*it];
- for (VendorMap::iterator itMap = _vendorMap.begin();
- itMap != _vendorMap.end();
- itMap++) {
- if (itMap->second == moveID)
- itMap->second = nextId;
- }
- } else {
- nextId = _vendorMap[*it];
- WAR << "Vendor " << *it << " is already used in another vendor group. --> mixing these groups"
- << endl;
- }
+ /**
+ * Helper mapping vendor string to eqivalence class ID.
+ *
+ * \li Return the vendor strings eqivalence class ID stored in _vendorMatch.
+ * \li If not found, assign and return the eqivalence class ID of the lowercased string.
+ * \li If not found, assign and return a new ID (look into the predefined VendorMap (id>0),
+ * otherwise create a new ID (<0)).
+ */
+ inline unsigned vendorMatchId( IdString vendor )
+ {
+ VendorMatchEntry & ent( _vendorMatch[vendor] );
+ if ( ! ent )
+ {
+ IdString lcvendor( str::toLower( vendor.asString() ) );
+ VendorMatchEntry & lcent( _vendorMatch[lcvendor] );
+ if ( ! lcent )
+ {
+ unsigned myid = 0;
+ // bnc#812608: no pefix compare in opensuse namespace
+ static const IdString openSUSE( "opensuse" );
+ if ( lcvendor == openSUSE || ! str::hasPrefix( lcvendor.c_str(), openSUSE.c_str() ) )
+ {
+ // Compare this entry with the global vendor map.
+ // Reversed to get the longest prefix.
+ for ( VendorMap::reverse_iterator it = _vendorMap.rbegin(); it != _vendorMap.rend(); ++it )
+ {
+ if ( str::hasPrefix( lcvendor.c_str(), it->first ) )
+ {
+ myid = it->second;
+ break; // found
+ }
}
+ }
+ if ( ! myid )
+ {
+ myid = --_nextId; // get a new class ID
+ }
+ ent = lcent = myid; // remember the new DI
+ }
+ else
+ {
+ ent = lcent; // take the ID from the lowercased vendor string
}
- // add new entries
- for (VendorList::iterator it = vendorList.begin();
- it != vendorList.end();
- it++) {
- _vendorMap[*it] = nextId;
- }
-
- if (nextId == vendorGroupCounter + 1)
- vendorGroupCounter++;
+ }
+ return ent;
}
-
-
/////////////////////////////////////////////////////////////////
} // namespace
///////////////////////////////////////////////////////////////////
VendorAttr::VendorAttr ()
{
- vendorGroupCounter = 1;
- Pathname xxx = ZConfig::instance().repoCachePath();
+ vendorGroupCounter = 1;
Pathname vendorPath (ZConfig::instance().vendorPath());
- try
{
- Target_Ptr trg( getZYpp()->target() );
- if ( trg )
- vendorPath = trg->root() / vendorPath;
+ Target_Ptr trg( getZYpp()->getTarget() );
+ if ( trg )
+ vendorPath = trg->root() / vendorPath;
+ }
+ // creating entries
+ addVendorDirectory (vendorPath);
+
+ // Checking if suse,opensuse has been defined, else create entries:
+ // - if both are defined we leve them as thay are.
+ // - if only one of them is defined, we add the other to the same group.
+ // - if both are undefined they make up a new group
+ VendorMap::const_iterator suseit( _vendorMap.find("suse") );
+ VendorMap::const_iterator opensuseit( _vendorMap.find("opensuse") );
+ if ( suseit == _vendorMap.end() )
+ {
+ if ( opensuseit == _vendorMap.end() )
+ {
+ // both are undefined
+ _vendorMap["suse"] = _vendorMap["opensuse"] = ++vendorGroupCounter;
+ }
+ else
+ {
+ // add suse to opensuse
+ _vendorMap["suse"] = opensuseit->second;
+ }
}
- catch ( ... )
+ else if ( opensuseit == _vendorMap.end() )
{
- // noop: Someone decided to let target() throw if the ptr is NULL ;(
+ // add opensuse to suse
+ _vendorMap["opensuse"] = suseit->second;
}
- // creating entries
- addVendorDirectory (vendorPath);
+ MIL << *this << endl;
+ }
- //checking if suse,opensuse has been defined. If not create entries
- if (_vendorMap.find("suse") != _vendorMap.end()) {
- if (_vendorMap.find("opensuse") == _vendorMap.end()) {
- _vendorMap["opensuse"] = vendorGroupCounter;
- }
- } else {
- if (_vendorMap.find("opensuse") == _vendorMap.end()) {
- // both are not available. Create one group with suse,opensuse
- _vendorMap["opensuse"] = vendorGroupCounter;
- _vendorMap["suse"] = vendorGroupCounter;
- } else {
- _vendorMap["suse"] = vendorGroupCounter;
- }
+ void VendorAttr::_addVendorList( VendorList & vendorList_r ) const
+ {
+ unsigned int nextId = vendorGroupCounter + 1;
+ // convert to lowercase and check if a vendor is already defined
+ // in an existing group.
+
+ for_( it, vendorList_r.begin(), vendorList_r.end() )
+ {
+ *it = str::toLower( *it );
+ if (_vendorMap.find(*it) != _vendorMap.end())
+ {
+ if (nextId != vendorGroupCounter + 1 &&
+ nextId != _vendorMap[*it])
+ {
+ // We have at least 3 groups which has to be mixed --> mix the third group to the first
+ unsigned int moveID = _vendorMap[*it];
+ for_( itMap, _vendorMap.begin(), _vendorMap.end() )
+ {
+ if (itMap->second == moveID)
+ itMap->second = nextId;
+ }
+ }
+ else
+ {
+ nextId = _vendorMap[*it];
+ WAR << "Vendor " << *it << " is already used in another vendor group. --> mixing these groups" << endl;
+ }
}
+ }
+ // add new entries
+ for_( it, vendorList_r.begin(), vendorList_r.end() )
+ {
+ _vendorMap[*it] = nextId;
+ }
- MIL << "Equivalent vendors:" << endl;
- for (VendorMap::iterator it = _vendorMap.begin();
- it != _vendorMap.end();
- it ++) {
- MIL << " " << it->first << " (group " << it->second << ")" << endl;
- }
+ if (nextId == vendorGroupCounter + 1)
+ ++vendorGroupCounter;
+
+ // invalidate any match cache
+ vendorMatchIdReset();
}
bool VendorAttr::addVendorFile( const Pathname & filename ) const
{
parser::IniDict dict;
-
+
if ( PathInfo(filename).isExist())
{
InputStream is(filename);
{
VendorList vendorlist;
str::split( value, back_inserter(vendorlist), "," );
- addEquivalentVendors (vendorlist);
+ _addVendorList (vendorlist);
break;
}
}
}
}
-
+
return true;
}
bool VendorAttr::addVendorDirectory( const Pathname & dirname ) const
{
- parser::IniDict dict;
-
- if ( PathInfo(dirname).isExist())
- {
- InputStream is(dirname);
- dict.read(is);
- }
- else
+ if ( ! PathInfo(dirname).isExist() )
{
MIL << dirname << " not found." << endl;
return false;
}
list<Pathname> filenames;
-
+
filesystem::readdir( filenames,
dirname, false );
for (list<Pathname>::iterator it = filenames.begin();
- it != filenames.end(); it++) {
+ it != filenames.end(); ++it) {
MIL << "Adding file " << *it << endl;
addVendorFile( *it );
- }
+ }
return true;
}
-
- bool VendorAttr::equivalent( const Vendor & lVendor, const Vendor & rVendor ) const
+ //////////////////////////////////////////////////////////////////
+ // vendor equivalence:
+ //////////////////////////////////////////////////////////////////
+
+ bool VendorAttr::equivalent( IdString lVendor, IdString rVendor ) const
{
- unsigned int lhsID = 0;
- unsigned int rhsID = 0;
- Vendor lhs = str::toLower (lVendor);
- Vendor rhs = str::toLower (rVendor);
-
- if ( lhs == rhs )
- return true;
-
- if (_matchMap.find(lhs) != _matchMap.end()) {
- lhsID = _matchMap[lhs];
- } else {
- // compare this entry with the vendor map
- for (VendorMap::reverse_iterator it = _vendorMap.rbegin();
- it != _vendorMap.rend();
- it++) {
- if (lhs.substr (0, it->first.size()) == it->first) {
- lhsID = it->second;
- _matchMap[lhs] = lhsID;
- break; // exit for
- }
- }
- }
+ if ( lVendor == rVendor )
+ return true;
+ return vendorMatchId( lVendor ) == vendorMatchId( rVendor );
+ }
- if (_matchMap.find(rhs) != _matchMap.end()) {
- rhsID = _matchMap[rhs];
- } else {
- // compare this entry with the vendor map
- for (VendorMap::reverse_iterator it = _vendorMap.rbegin();
- it != _vendorMap.rend();
- it++) {
- if (rhs.substr (0, it->first.size()) == it->first) {
- rhsID = it->second;
- _matchMap[rhs] = rhsID;
- break; // exit for
- }
- }
- }
-
- return( lhsID && rhsID && lhsID == lhsID );
+ bool VendorAttr::equivalent( const Vendor & lVendor, const Vendor & rVendor ) const
+ { return equivalent( IdString( lVendor ), IdString( rVendor ) );
+ }
+
+ bool VendorAttr::equivalent( sat::Solvable lVendor, sat::Solvable rVendor ) const
+ { return equivalent( lVendor.vendor(), rVendor.vendor() ); }
+
+ bool VendorAttr::equivalent( const PoolItem & lVendor, const PoolItem & rVendor ) const
+ { return equivalent( lVendor.satSolvable().vendor(), rVendor.satSolvable().vendor() ); }
+
+ //////////////////////////////////////////////////////////////////
+
+ std::ostream & operator<<( std::ostream & str, const VendorAttr & /*obj*/ )
+ {
+ str << "Equivalent vendors:";
+ for_( it, _vendorMap.begin(), _vendorMap.end() )
+ {
+ str << endl << " [" << it->second << "] " << it->first;
+ }
+ return str;
}
/////////////////////////////////////////////////////////////////