Imported Upstream version 14.45.0
[platform/upstream/libzypp.git] / zypp / VendorAttr.cc
index 13809c5..2cef434 100644 (file)
@@ -48,52 +48,74 @@ namespace zypp
   { /////////////////////////////////////////////////////////////////
 
     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
   ///////////////////////////////////////////////////////////////////
@@ -106,50 +128,90 @@ namespace zypp
 
   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);
@@ -179,85 +241,67 @@ namespace zypp
                  {
                      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;
   }
 
   /////////////////////////////////////////////////////////////////