~thopiekar/zypper/libzypp-manual-import

« back to all changes in this revision

Viewing changes to zypp/VendorAttr.cc

  • Committer: Thomas-Karl Pietrowski
  • Date: 2014-01-29 22:44:28 UTC
  • Revision ID: thopiekar@googlemail.com-20140129224428-gpcqnsdakby362n8
firstĀ import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*---------------------------------------------------------------------\
 
2
|                          ____ _   __ __ ___                          |
 
3
|                         |__  / \ / / . \ . \                         |
 
4
|                           / / \ V /|  _/  _/                         |
 
5
|                          / /__ | | | | | |                           |
 
6
|                         /_____||_| |_| |_|                           |
 
7
|                                                                      |
 
8
\---------------------------------------------------------------------*/
 
9
/*
 
10
  File:       VendorAttr.cc
 
11
 
 
12
  Author:     Michael Andres <ma@suse.de>
 
13
  Maintainer: Michael Andres <ma@suse.de>
 
14
 
 
15
  Purpose: Manage vendor attributes
 
16
 
 
17
/-*/
 
18
 
 
19
#include <iostream>
 
20
#include <fstream>
 
21
#include <set>
 
22
#include <map>
 
23
#include <vector>
 
24
 
 
25
#include "zypp/base/LogTools.h"
 
26
#include "zypp/base/IOStream.h"
 
27
#include "zypp/base/String.h"
 
28
 
 
29
#include "zypp/PathInfo.h"
 
30
#include "zypp/VendorAttr.h"
 
31
#include "zypp/ZYppFactory.h"
 
32
 
 
33
#include "zypp/ZConfig.h"
 
34
#include "zypp/PathInfo.h"
 
35
#include "zypp/parser/IniDict.h"
 
36
 
 
37
using namespace std;
 
38
 
 
39
#undef  ZYPP_BASE_LOGGER_LOGGROUP
 
40
#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::VendorAttr"
 
41
 
 
42
///////////////////////////////////////////////////////////////////
 
43
namespace zypp
 
44
{ /////////////////////////////////////////////////////////////////
 
45
 
 
46
  ///////////////////////////////////////////////////////////////////
 
47
  namespace
 
48
  { /////////////////////////////////////////////////////////////////
 
49
 
 
50
    typedef map<Vendor,unsigned int> VendorMap;
 
51
    VendorMap _vendorMap;
 
52
    unsigned int vendorGroupCounter;
 
53
 
 
54
    /////////////////////////////////////////////////////////////////
 
55
  } // namespace
 
56
  ///////////////////////////////////////////////////////////////////
 
57
 
 
58
  ///////////////////////////////////////////////////////////////////
 
59
  namespace
 
60
  { /////////////////////////////////////////////////////////////////
 
61
    typedef DefaultIntegral<int,0>                              VendorMatchEntry;
 
62
    typedef std::tr1::unordered_map<IdString, VendorMatchEntry> VendorMatch;
 
63
    int         _nextId = -1;
 
64
    VendorMatch _vendorMatch;
 
65
 
 
66
    /** Reset match cache if global VendorMap was changed. */
 
67
    inline void vendorMatchIdReset()
 
68
    {
 
69
      _nextId = -1;
 
70
      _vendorMatch.clear();
 
71
    }
 
72
 
 
73
    /**
 
74
     * Helper mapping vendor string to eqivalence class ID.
 
75
     *
 
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)).
 
80
     */
 
81
    inline unsigned vendorMatchId( IdString vendor )
 
82
    {
 
83
      VendorMatchEntry & ent( _vendorMatch[vendor] );
 
84
      if ( ! ent )
 
85
      {
 
86
        IdString lcvendor( str::toLower( vendor.asString() ) );
 
87
        VendorMatchEntry & lcent( _vendorMatch[lcvendor] );
 
88
        if ( ! lcent )
 
89
        {
 
90
          unsigned myid = 0;
 
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() ) )
 
94
          {
 
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 )
 
98
            {
 
99
              if ( str::hasPrefix( lcvendor.c_str(), it->first ) )
 
100
              {
 
101
                myid = it->second;
 
102
                break; // found
 
103
              }
 
104
            }
 
105
          }
 
106
          if ( ! myid )
 
107
          {
 
108
            myid = --_nextId; // get a new class ID
 
109
          }
 
110
          ent = lcent = myid; // remember the new DI
 
111
        }
 
112
        else
 
113
        {
 
114
          ent = lcent; // take the ID from the lowercased vendor string
 
115
        }
 
116
      }
 
117
      return ent;
 
118
    }
 
119
    /////////////////////////////////////////////////////////////////
 
120
  } // namespace
 
121
  ///////////////////////////////////////////////////////////////////
 
122
 
 
123
  const VendorAttr & VendorAttr::instance()
 
124
  {
 
125
      static VendorAttr _val;
 
126
      return _val;
 
127
  }
 
128
 
 
129
  VendorAttr::VendorAttr ()
 
130
  {
 
131
      vendorGroupCounter = 1;
 
132
      Pathname vendorPath (ZConfig::instance().vendorPath());
 
133
      {
 
134
        Target_Ptr trg( getZYpp()->getTarget() );
 
135
        if ( trg )
 
136
          vendorPath = trg->root() / vendorPath;
 
137
      }
 
138
      // creating entries
 
139
      addVendorDirectory (vendorPath);
 
140
 
 
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() )
 
148
      {
 
149
        if ( opensuseit == _vendorMap.end() )
 
150
        {
 
151
          // both are undefined
 
152
          _vendorMap["suse"] = _vendorMap["opensuse"] = ++vendorGroupCounter;
 
153
        }
 
154
        else
 
155
        {
 
156
          // add suse to opensuse
 
157
          _vendorMap["suse"] = opensuseit->second;
 
158
        }
 
159
      }
 
160
      else if ( opensuseit == _vendorMap.end() )
 
161
      {
 
162
        // add opensuse to suse
 
163
        _vendorMap["opensuse"] = suseit->second;
 
164
      }
 
165
 
 
166
      MIL << *this << endl;
 
167
  }
 
168
 
 
169
  void VendorAttr::_addVendorList( VendorList & vendorList_r ) const
 
170
  {
 
171
    unsigned int nextId = vendorGroupCounter + 1;
 
172
        // convert to lowercase and check if a vendor is already defined
 
173
        // in an existing group.
 
174
 
 
175
    for_( it, vendorList_r.begin(), vendorList_r.end() )
 
176
    {
 
177
      *it = str::toLower( *it );
 
178
      if (_vendorMap.find(*it) != _vendorMap.end())
 
179
      {
 
180
        if (nextId != vendorGroupCounter + 1 &&
 
181
            nextId != _vendorMap[*it])
 
182
        {
 
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() )
 
186
          {
 
187
            if (itMap->second == moveID)
 
188
              itMap->second = nextId;
 
189
          }
 
190
        }
 
191
        else
 
192
        {
 
193
          nextId = _vendorMap[*it];
 
194
          WAR << "Vendor " << *it << " is already used in another vendor group. --> mixing these groups" << endl;
 
195
        }
 
196
      }
 
197
    }
 
198
        // add new entries
 
199
    for_( it, vendorList_r.begin(), vendorList_r.end() )
 
200
    {
 
201
      _vendorMap[*it] = nextId;
 
202
    }
 
203
 
 
204
    if (nextId == vendorGroupCounter + 1)
 
205
      ++vendorGroupCounter;
 
206
 
 
207
    // invalidate any match cache
 
208
    vendorMatchIdReset();
 
209
  }
 
210
 
 
211
  bool VendorAttr::addVendorFile( const Pathname & filename ) const
 
212
  {
 
213
      parser::IniDict dict;
 
214
 
 
215
      if ( PathInfo(filename).isExist())
 
216
      {
 
217
          InputStream is(filename);
 
218
          dict.read(is);
 
219
      }
 
220
      else
 
221
      {
 
222
          MIL << filename << " not found." << endl;
 
223
          return false;
 
224
      }
 
225
 
 
226
      for ( parser::IniDict::section_const_iterator sit = dict.sectionsBegin();
 
227
            sit != dict.sectionsEnd();
 
228
            ++sit )
 
229
      {
 
230
          string section(*sit);
 
231
          //MIL << section << endl;
 
232
          for ( parser::IniDict::entry_const_iterator it = dict.entriesBegin(*sit);
 
233
                it != dict.entriesEnd(*sit);
 
234
                ++it )
 
235
          {
 
236
              string entry(it->first);
 
237
              string value(it->second);
 
238
              if ( section == "main" )
 
239
              {
 
240
                  if ( entry == "vendors" )
 
241
                  {
 
242
                      VendorList vendorlist;
 
243
                      str::split( value, back_inserter(vendorlist), "," );
 
244
                      _addVendorList (vendorlist);
 
245
                      break;
 
246
                  }
 
247
              }
 
248
          }
 
249
      }
 
250
 
 
251
      return true;
 
252
  }
 
253
 
 
254
  bool VendorAttr::addVendorDirectory( const Pathname & dirname ) const
 
255
  {
 
256
      parser::IniDict dict;
 
257
 
 
258
      if ( PathInfo(dirname).isExist())
 
259
      {
 
260
          InputStream is(dirname);
 
261
          dict.read(is);
 
262
      }
 
263
      else
 
264
      {
 
265
          MIL << dirname << " not found." << endl;
 
266
          return false;
 
267
      }
 
268
 
 
269
      list<Pathname> filenames;
 
270
 
 
271
      filesystem::readdir( filenames,
 
272
                           dirname, false );
 
273
      for (list<Pathname>::iterator it = filenames.begin();
 
274
           it != filenames.end(); ++it) {
 
275
          MIL << "Adding file " << *it << endl;
 
276
          addVendorFile( *it );
 
277
      }
 
278
      return true;
 
279
  }
 
280
 
 
281
  //////////////////////////////////////////////////////////////////
 
282
  // vendor equivalence:
 
283
  //////////////////////////////////////////////////////////////////
 
284
 
 
285
  bool VendorAttr::equivalent( IdString lVendor, IdString rVendor ) const
 
286
  {
 
287
    if ( lVendor == rVendor )
 
288
      return true;
 
289
    return vendorMatchId( lVendor ) == vendorMatchId( rVendor );
 
290
  }
 
291
 
 
292
  bool VendorAttr::equivalent( const Vendor & lVendor, const Vendor & rVendor ) const
 
293
  { return equivalent( IdString( lVendor ), IdString( rVendor ) );
 
294
  }
 
295
 
 
296
  bool VendorAttr::equivalent( sat::Solvable lVendor, sat::Solvable rVendor ) const
 
297
  { return equivalent( lVendor.vendor(), rVendor.vendor() ); }
 
298
 
 
299
  bool VendorAttr::equivalent( const PoolItem & lVendor, const PoolItem & rVendor ) const
 
300
  { return equivalent( lVendor.satSolvable().vendor(), rVendor.satSolvable().vendor() ); }
 
301
 
 
302
  //////////////////////////////////////////////////////////////////
 
303
 
 
304
  std::ostream & operator<<( std::ostream & str, const VendorAttr & /*obj*/ )
 
305
  {
 
306
    str << "Equivalent vendors:";
 
307
    for_( it, _vendorMap.begin(), _vendorMap.end() )
 
308
    {
 
309
      str << endl << "   [" << it->second << "] " << it->first;
 
310
    }
 
311
    return str;
 
312
  }
 
313
 
 
314
  /////////////////////////////////////////////////////////////////
 
315
} // namespace zypp
 
316
///////////////////////////////////////////////////////////////////
 
317