~ubuntu-branches/ubuntu/jaunty/yum/jaunty

« back to all changes in this revision

Viewing changes to yum/comps.py

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings
  • Date: 2008-07-28 23:20:59 UTC
  • mfrom: (2.1.3 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080728232059-24lo1r17smhr71l8
Tags: 3.2.12-1.2
* Non-maintainer upload
* Updated for compatibility with current python-pyme (Closes: #490368)
  based on patch by Martin Meredith <mez@ubuntu.com>
  - Changed import in yum/misc.py
  - Set versioned dependency on python-pyme

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python
2
 
# -*- mode: python -*-
 
1
# This program is free software; you can redistribute it and/or modify
 
2
# it under the terms of the GNU General Public License as published by
 
3
# the Free Software Foundation; either version 2 of the License, or
 
4
# (at your option) any later version.
 
5
#
 
6
# This program is distributed in the hope that it will be useful,
 
7
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
8
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
9
# GNU Library General Public License for more details.
 
10
#
 
11
# You should have received a copy of the GNU General Public License
 
12
# along with this program; if not, write to the Free Software
 
13
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
14
# Copyright 2005 Duke University
3
15
 
4
 
from cElementTree import iterparse
5
 
import signal
6
 
import getopt
7
16
import sys
8
 
import exceptions
9
 
 
10
 
TRUE=1
11
 
FALSE=0
12
 
 
13
 
def parse_boolean(s):
14
 
    if s.lower() in ('yes', 'true'):
15
 
        return TRUE
16
 
    return FALSE
17
 
 
18
 
def getattrib(elem, key, default=None):
19
 
    '''Retrieve an attribute named key from elem. Return default if not found.
20
 
 
21
 
    This is required because ElementTree includes namespace information in the
22
 
    name of each attribute.
23
 
    '''
24
 
    for k, v in elem.attrib.iteritems():
25
 
        k = k.split('}', 1)[-1]
26
 
        if k == key:
27
 
            return v
28
 
    return default
29
 
 
30
 
class CompsException(exceptions.Exception):
31
 
    pass
32
 
 
33
 
class Group:
34
 
    def __init__(self, comps, elem=None):
35
 
        self.comps = comps
36
 
        self.user_visible = TRUE
37
 
        self.default = FALSE
38
 
        self.removable = FALSE
39
 
        self.name=""
 
17
from constants import *
 
18
try:
 
19
    from xml.etree import cElementTree
 
20
except ImportError:
 
21
    import cElementTree
 
22
iterparse = cElementTree.iterparse
 
23
from Errors import CompsException
 
24
#FIXME - compsexception isn't caught ANYWHERE so it's pointless to raise it
 
25
# switch all compsexceptions to grouperrors after api break
 
26
 
 
27
lang_attr = '{http://www.w3.org/XML/1998/namespace}lang'
 
28
 
 
29
def parse_boolean(strng):
 
30
    if BOOLEAN_STATES.has_key(strng.lower()):
 
31
        return BOOLEAN_STATES[strng.lower()]
 
32
    else:
 
33
        return False
 
34
 
 
35
def parse_number(strng):
 
36
    return int(strng)
 
37
 
 
38
class Group(object):
 
39
    def __init__(self, elem=None):
 
40
        self.user_visible = True
 
41
        self.default = False
 
42
        self.selected = False
 
43
        self.name = ""
40
44
        self.description = ""
41
45
        self.translated_name = {}
42
46
        self.translated_description = {}
43
 
        self.packages = {}
44
 
        self.langonly = None
45
 
        self.groups = {}
46
 
        self.metapkgs = {}
47
 
        self.requires = []
48
 
        self.id = None
 
47
        self.mandatory_packages = {}
 
48
        self.optional_packages = {}
 
49
        self.default_packages = {}
 
50
        self.conditional_packages = {}
 
51
        self.langonly = None ## what the hell is this?
 
52
        self.groupid = None
 
53
        self.display_order = 1024
 
54
        self.installed = False
 
55
        self.toremove = False
 
56
        
49
57
 
50
 
        # FIXME: this is a horrible, horrible hack.  but we can't stick it
51
 
        # in with the package without making the tuple larger and that's
52
 
        # certain to break something and I don't have time to track them
53
 
        # all down.  so we have to keep separate track of any "requirements"
54
 
        # the package has to have to be installed.  this is *only* used right
55
 
        # now for some i18n packages.  if it gets used for anything else, it
56
 
        # is guaranteed to break within anaconda.    jlk - 12 aug 2002
57
 
        self.pkgConditionals = {}
58
 
        
59
58
        if elem:
60
59
            self.parse(elem)
 
60
        
 
61
    def __str__(self):
 
62
        return self.name
 
63
    
 
64
    def _packageiter(self):
 
65
        # Gah, FIXME: real iterator/class
 
66
        lst = self.mandatory_packages.keys() + \
 
67
              self.optional_packages.keys() + \
 
68
              self.default_packages.keys() + \
 
69
              self.conditional_packages.keys() 
 
70
        
 
71
        return lst
 
72
    
 
73
    packages = property(_packageiter)
 
74
    
 
75
    def nameByLang(self, lang):
 
76
        if self.translated_name.has_key[lang]:
 
77
            return self.translated_name[lang]
 
78
        else:
 
79
            return self.name
 
80
 
 
81
 
 
82
    def descriptionByLang(self, lang):
 
83
        if self.translated_description.has_key[lang]:
 
84
            return self.translated_description[lang]
 
85
        else:
 
86
            return self.description
61
87
 
62
88
    def parse(self, elem):
63
 
 
64
89
        for child in elem:
65
 
            if child.tag == 'name':
 
90
 
 
91
            if child.tag == 'id':
 
92
                myid = child.text
 
93
                if self.groupid is not None:
 
94
                    raise CompsException
 
95
                self.groupid = myid
 
96
            
 
97
            elif child.tag == 'name':
66
98
                text = child.text
67
99
                if text:
68
100
                    text = text.encode('utf8')
69
 
                lang = getattrib(child, 'lang')
 
101
                
 
102
                lang = child.attrib.get(lang_attr)
70
103
                if lang:
71
104
                    self.translated_name[lang] = text
72
105
                else:
73
106
                    self.name = text
74
 
 
75
 
            elif child.tag == 'id':
76
 
                id = child.text
77
 
                if self.id is not None:
78
 
                    raise CompsException
79
 
                self.id = id
80
 
 
 
107
    
 
108
    
81
109
            elif child.tag == 'description':
82
110
                text = child.text
83
111
                if text:
84
112
                    text = text.encode('utf8')
85
 
                lang = getattrib(child, 'lang')
 
113
                    
 
114
                lang = child.attrib.get(lang_attr)
86
115
                if lang:
87
116
                    self.translated_description[lang] = text
88
117
                else:
89
 
                    self.description = text
90
 
 
 
118
                    if text:
 
119
                        self.description = text
 
120
    
91
121
            elif child.tag == 'uservisible':
92
122
                self.user_visible = parse_boolean(child.text)
 
123
    
 
124
            elif child.tag == 'display_order':
 
125
                self.display_order = parse_number(child.text)
93
126
 
94
127
            elif child.tag == 'default':
95
128
                self.default = parse_boolean(child.text)
96
 
 
97
 
            elif child.tag == 'requires':
98
 
                # FIXME: this isn't in use anymore
99
 
                text = child.text
100
 
                if text in self.requires:
101
 
                    raise CompsException
102
 
                self.requires.append(text)
103
 
 
104
 
            elif child.tag == 'langonly':
 
129
    
 
130
            elif child.tag == 'langonly': ## FIXME - what the hell is langonly?
105
131
                text = child.text
106
132
                if self.langonly is not None:
107
133
                    raise CompsException
108
134
                self.langonly = text
109
 
 
 
135
    
110
136
            elif child.tag == 'packagelist':
111
137
                self.parse_package_list(child)
112
 
 
113
 
            elif child.tag == 'grouplist':
114
 
                self.parse_group_list(child)
115
 
 
 
138
    
116
139
    def parse_package_list(self, packagelist_elem):
117
 
 
118
140
        for child in packagelist_elem:
119
141
            if child.tag == 'packagereq':
120
 
                type = child.attrib.get('type')
121
 
                if not type:
122
 
                    type = u'mandatory'
 
142
                genre = child.attrib.get('type')
 
143
                if not genre:
 
144
                    genre = u'mandatory'
123
145
 
124
 
                if type not in ('mandatory', 'default', 'optional'):
125
 
                    raise CompsException
 
146
                if genre not in ('mandatory', 'default', 'optional', 'conditional'):
 
147
                    # just ignore bad package lines
 
148
                    continue
126
149
 
127
150
                package = child.text
128
 
                self.packages[package] = (type, package)
129
 
 
130
 
                # see note above about the hack this is.
131
 
                reqs = child.attrib.get('requires')
132
 
                if reqs:
133
 
                    self.pkgConditionals[package] = reqs
 
151
                if genre == 'mandatory':
 
152
                    self.mandatory_packages[package] = 1
 
153
                elif genre == 'default':
 
154
                    self.default_packages[package] = 1
 
155
                elif genre == 'optional':
 
156
                    self.optional_packages[package] = 1
 
157
                elif genre == 'conditional':
 
158
                    self.conditional_packages[package] = child.attrib.get('requires')
 
159
 
 
160
 
 
161
 
 
162
    def add(self, obj):
 
163
        """Add another group object to this object"""
 
164
    
 
165
        # we only need package lists and any translation that we don't already
 
166
        # have
 
167
        
 
168
        for pkg in obj.mandatory_packages:
 
169
            self.mandatory_packages[pkg] = 1
 
170
        for pkg in obj.default_packages:
 
171
            self.default_packages[pkg] = 1
 
172
        for pkg in obj.optional_packages:
 
173
            self.optional_packages[pkg] = 1
 
174
        for pkg in obj.conditional_packages:
 
175
            self.conditional_packages[pkg] = obj.conditional_packages[pkg]
 
176
        
 
177
        # Handle cases where a comps.xml without name & decription tags
 
178
        # has been setup first, so the name & decription for this object is blank.
 
179
            
 
180
        
 
181
        if self.name == '' and obj.name != '':
 
182
            self.name = obj.name
 
183
 
 
184
        if self.description == '' and obj.description != '':
 
185
            self.description = obj.description
 
186
            
 
187
        # name and description translations
 
188
        for lang in obj.translated_name:
 
189
            if not self.translated_name.has_key(lang):
 
190
                self.translated_name[lang] = obj.translated_name[lang]
 
191
        
 
192
        for lang in obj.translated_description:
 
193
            if not self.translated_description.has_key(lang):
 
194
                self.translated_description[lang] = obj.translated_description[lang]
 
195
        
 
196
    def xml(self):
 
197
        """write out an xml stanza for the group object"""
 
198
        msg ="""        
 
199
  <group>
 
200
   <id>%s</id>
 
201
   <default>%s</default>
 
202
   <uservisible>%s</uservisible>
 
203
   <display_order>%s</display_order>\n""" % (self.groupid, str(self.default), 
 
204
                                  str(self.user_visible), self.display_order)
 
205
   
 
206
        if self.langonly:
 
207
            msg =+ """   <lang_only>%s</lang_only>""" % self.langonly
 
208
            
 
209
        msg +="""   <name>%s</name>\n""" % self.name
 
210
        for (lang, val) in self.translated_name.items():
 
211
            msg += """   <name xml:lang="%s">%s</name>\n""" % (lang, val)
 
212
        
 
213
        msg += """   <description>%s</description>\n""" % self.description
 
214
        for (lang, val) in self.translated_description.items():
 
215
            msg += """   <description xml:lang="%s">%s</description>\n""" % (lang, val)
 
216
 
 
217
        msg += """    <packagelist>\n"""
 
218
        for pkg in self.mandatory_packages.keys():
 
219
            msg += """      <packagereq type="mandatory">%s</packagereq>\n""" % pkg
 
220
        for pkg in self.default_packages.keys():
 
221
            msg += """      <packagereq type="default">%s</packagereq>\n""" % pkg
 
222
        for pkg in self.optional_packages.keys():
 
223
            msg += """      <packagereq type="optional">%s</packagereq>\n""" % pkg
 
224
        for (pkg, req) in self.conditional_packages.items():
 
225
            msg += """      <packagereq type="conditional" requires="%s">%s</packagereq>\n""" % (pkg, req)
 
226
        msg += """    </packagelist>\n"""
 
227
        msg += """  </group>"""
 
228
 
 
229
        return msg      
 
230
        
 
231
        
 
232
 
 
233
 
 
234
class Category(object):
 
235
    def __init__(self, elem=None):
 
236
        self.name = ""
 
237
        self.categoryid = None
 
238
        self.description = ""
 
239
        self.translated_name = {}
 
240
        self.translated_description = {}
 
241
        self.display_order = 1024
 
242
        self._groups = {}        
 
243
 
 
244
        if elem:
 
245
            self.parse(elem)
 
246
            
 
247
    def __str__(self):
 
248
        return self.name
 
249
    
 
250
    def _groupiter(self):
 
251
        return self._groups.keys()
 
252
    
 
253
    groups = property(_groupiter)
 
254
    
 
255
    def parse(self, elem):
 
256
        for child in elem:
 
257
            if child.tag == 'id':
 
258
                myid = child.text
 
259
                if self.categoryid is not None:
 
260
                    raise CompsException
 
261
                self.categoryid = myid
 
262
 
 
263
            elif child.tag == 'name':
 
264
                text = child.text
 
265
                if text:
 
266
                    text = text.encode('utf8')
 
267
                    
 
268
                lang = child.attrib.get(lang_attr)
 
269
                if lang:
 
270
                    self.translated_name[lang] = text
 
271
                else:
 
272
                    self.name = text
 
273
    
 
274
            elif child.tag == 'description':
 
275
                text = child.text
 
276
                if text:
 
277
                    text = text.encode('utf8')
 
278
                    
 
279
                lang = child.attrib.get(lang_attr)
 
280
                if lang:
 
281
                    self.translated_description[lang] = text
 
282
                else:
 
283
                    self.description = text
 
284
            
 
285
            elif child.tag == 'grouplist':
 
286
                self.parse_group_list(child)
 
287
 
 
288
            elif child.tag == 'display_order':
 
289
                self.display_order = parse_number(child.text)
134
290
 
135
291
    def parse_group_list(self, grouplist_elem):
136
 
 
137
292
        for child in grouplist_elem:
138
 
            if child.tag == 'groupreq':
139
 
                type = getattrib(child, 'type')
140
 
                if not type:
141
 
                    type = u'mandatory'
142
 
 
143
 
                if type not in ('mandatory', 'default', 'optional'):
144
 
                    raise CompsException
145
 
 
146
 
                group = child.text
147
 
                self.groups[group] = (type, group)
148
 
 
149
 
            elif child.tag == 'metapkg':
150
 
                type = getattrib(child, 'type')
151
 
                if not type:
152
 
                    type = u'default'
153
 
                if type not in ('default', 'optional'):
154
 
                    raise CompsException
155
 
                group = child.text
156
 
                self.metapkgs[group] = (type, group)
157
 
                
158
 
    def sanity_check(self):
159
 
        if not self.comps:
160
 
            raise CompsException
161
 
        if not self.name:
162
 
            raise CompsException
163
 
        for (type, package) in self.packages.values():
164
 
            try:
165
 
                self.comps.packages[package]
166
 
            except KeyError:
167
 
                pass
168
 
#                raise CompsException
169
 
            
170
 
 
171
 
class Package:
172
 
    def __init__(self, comps, elem=None):
173
 
        self.comps = comps
174
 
        self.name = None
175
 
        self.version = None
176
 
        self.supported = FALSE
177
 
        self.excludearch = None
178
 
        self.dependencies = []
179
 
        self.installed = 0
180
 
        if elem:
181
 
            self.parse(elem)
182
 
 
183
 
    def sanity_check(self):
184
 
        if self.name == None:
185
 
            return FALSE
186
 
 
187
 
    def parse_dependency_list(self, packagedeps_elem):
188
 
        for child in packagedeps_elem:
189
 
            if child.tag == 'dependency':
190
 
                self.dependencies.append(child.text)
191
 
 
192
 
    def parse(self, group_elem):
193
 
        for child in group_elem:
194
 
            if child.tag == 'name':
195
 
                self.name = child.text
196
 
 
197
 
            elif child.tag == 'version':
198
 
                self.version = child.text
199
 
 
200
 
            elif child.tag == 'excludearch':
201
 
                self.excludearch = child.text
202
 
 
203
 
            elif child.tag == 'packagelist':
204
 
                self.parse_package_list(child)
205
 
 
206
 
            elif child.tag == 'supported':
207
 
                self.supported = parse_boolean(child.text)
208
 
 
209
 
            elif child.tag == 'dependencylist':
210
 
                self.parse_dependency_list(child)
211
 
 
212
 
class GroupHierarchy(dict):
213
 
    def __init__(self, comps, elem=None):
214
 
        self.comps = comps
215
 
        self.order = []
216
 
        self.translations = {}
217
 
        if elem:
218
 
            self.parse(elem)
219
 
 
220
 
    def parse(self, elem):
221
 
        for child in elem:
222
 
            if child.tag == "category":
223
 
                self.parse_category(child)
224
 
            else:
225
 
                print "unhandled node in <comps.grouphierarchy>: " + child.tag
226
 
 
227
 
    def parse_category(self, category_elem):
228
 
        translations = {}
229
 
        subs = []
230
 
        name = None
231
 
        
232
 
        for child in category_elem:
233
 
            if child.tag == "name":
234
 
                text = child.text
235
 
                if text:
236
 
                    text = text.encode('utf8')
237
 
                lang = getattrib(child, 'lang')
238
 
                if lang:
239
 
                    translations[lang] = text
240
 
                else:
241
 
                    name = text
242
 
 
243
 
            elif child.tag == "subcategories":
244
 
                subs.extend(self.parse_subcategories(child))
245
 
 
246
 
            else:
247
 
                print "unhandled node in <comps.grouphierarchy.category>: " + \
248
 
                        elem.tag
249
 
 
250
 
        if not name:
251
 
            raise CompsException, "no name specified"
252
 
 
253
 
        if not self.has_key(name):
254
 
            self.order.append(name)
255
 
            self[name] = subs
256
 
        else:
257
 
            self[name] = self[name].extend(subs)
258
 
        self.translations[name] = translations
259
 
 
260
 
    def parse_subcategories(self, category_elem):
261
 
        ret = []
262
 
        for child in category_elem:
263
 
            if child.tag == "subcategory":
264
 
                id = child.text
265
 
                if not id:
266
 
                    raise CompsException
267
 
                ret.append(id)
268
 
            else:
269
 
                print "unhandled node in <comps.grouphierarchy.parse_category>:" + child.tag
270
 
 
271
 
        return ret
272
 
                
273
 
        
274
 
 
 
293
            if child.tag == 'groupid':
 
294
                groupid = child.text
 
295
                self._groups[groupid] = 1
 
296
 
 
297
    def add(self, obj):
 
298
        """Add another category object to this object"""
 
299
    
 
300
        for grp in obj.groups:
 
301
            self._groups[grp] = 1
 
302
        
 
303
        # name and description translations
 
304
        for lang in obj.translated_name:
 
305
            if not self.translated_name.has_key(lang):
 
306
                self.translated_name[lang] = obj.translated_name[lang]
 
307
        
 
308
        for lang in obj.translated_description:
 
309
            if not self.translated_description.has_key(lang):
 
310
                self.translated_description[lang] = obj.translated_description[lang]
 
311
 
 
312
    def xml(self):
 
313
        """write out an xml stanza for the group object"""
 
314
        msg ="""        
 
315
  <category>
 
316
   <id>%s</id>
 
317
   <display_order>%s</display_order>\n""" % (self.categoryid, self.display_order)
 
318
   
 
319
        msg +="""   <name>%s</name>\n""" % self.name
 
320
        for (lang, val) in self.translated_name.items():
 
321
            msg += """   <name xml:lang="%s">%s</name>\n""" % (lang, val)
 
322
        
 
323
        msg += """   <description>%s</description>\n""" % self.description
 
324
        for (lang, val) in self.translated_description.items():
 
325
            msg += """    <description xml:lang="%s">%s</description>\n""" % (lang, val)
 
326
 
 
327
        msg += """    <grouplist>\n"""
 
328
        for grp in self.groups:
 
329
            msg += """     <groupid>%s</groupid>\n""" % grp
 
330
        msg += """    </grouplist>\n"""
 
331
        msg += """  </category>\n"""
 
332
 
 
333
        return msg                
 
334
        
275
335
class Comps(object):
276
 
    def __init__(self, srcfile=None):
277
 
        self.groups = {}
278
 
        self.packages = {}
279
 
        self.hierarchy = {}
280
 
 
281
 
        if srcfile != None:
282
 
            self.load(srcfile)
283
 
 
284
 
    def load(self, srcfile):
 
336
    def __init__(self, overwrite_groups=False):
 
337
        self._groups = {}
 
338
        self._categories = {}
 
339
        self.compscount = 0
 
340
        self.overwrite_groups = overwrite_groups
 
341
        self.compiled = False # have groups been compiled into avail/installed 
 
342
                              # lists, yet.
 
343
 
 
344
 
 
345
    def __sort_order(self, item1, item2):
 
346
        if item1.display_order > item2.display_order:
 
347
            return 1
 
348
        elif item1.display_order == item2.display_order:
 
349
            return 0
 
350
        else:
 
351
            return -1
 
352
    
 
353
    def get_groups(self):
 
354
        grps = self._groups.values()
 
355
        grps.sort(self.__sort_order)
 
356
        return grps
 
357
        
 
358
    def get_categories(self):
 
359
        cats = self._categories.values()
 
360
        cats.sort(self.__sort_order)
 
361
        return cats
 
362
        
 
363
    
 
364
    groups = property(get_groups)
 
365
    categories = property(get_categories)
 
366
    
 
367
    
 
368
    
 
369
    def has_group(self, grpid):
 
370
        exists = self.return_group(grpid)
 
371
            
 
372
        if exists:
 
373
            return True
 
374
            
 
375
        return False
 
376
    
 
377
    def return_group(self, grpid):
 
378
        if self._groups.has_key(grpid):
 
379
            return self._groups[grpid]
 
380
        
 
381
        # do matches against group names and ids, too
 
382
        for group in self.groups:
 
383
            names = [ group.name, group.groupid ]
 
384
            names.extend(group.translated_name.values())
 
385
            if grpid in names:
 
386
                return group
 
387
 
 
388
        
 
389
        return None
 
390
 
 
391
 
 
392
    def add(self, srcfile = None):
 
393
        if not srcfile:
 
394
            raise CompsException
 
395
            
285
396
        if type(srcfile) == type('str'):
286
397
            # srcfile is a filename string
287
398
            infile = open(srcfile, 'rt')
288
399
        else:
289
400
            # srcfile is a file object
290
401
            infile = srcfile
291
 
 
 
402
        
 
403
        self.compscount += 1
 
404
        self.compiled = False
 
405
        
292
406
        parser = iterparse(infile)
293
 
 
294
 
        for event, elem in parser:
295
 
            if elem.tag == "group":
296
 
                group = Group(self, elem)
297
 
                self.groups[group.name] = group
298
 
 
299
 
            elif elem.tag == "package":
300
 
                package = Package(self, elem)
301
 
                self.packages[package.name] = package
302
 
 
303
 
            elif elem.tag == "grouphierarchy":
304
 
                self.hierarchy = GroupHierarchy(self, elem)
305
 
 
306
 
        if 0:
307
 
            for group in self.hierarchy.order:
308
 
                print group
309
 
                print self.hierarchy[group]
310
 
        if 0:
311
 
            for group in self.groups.values():
312
 
                print group.name
313
 
            for package in self.packages.values():
314
 
                print package.name
315
 
                print package.dependencies
316
 
            for group in self.groups.values():
317
 
                group.sanity_check()
318
 
            for package in self.packages.values():
319
 
                package.sanity_check()
320
 
 
321
 
 
322
 
usage = "usage: pkggroup.py compsfile.xml"
323
 
 
 
407
        try:
 
408
            for event, elem in parser:
 
409
                if elem.tag == "group":
 
410
                    group = Group(elem)
 
411
                    if self._groups.has_key(group.groupid):
 
412
                        thatgroup = self._groups[group.groupid]
 
413
                        thatgroup.add(group)
 
414
                    else:
 
415
                        self._groups[group.groupid] = group
 
416
 
 
417
                if elem.tag == "category":
 
418
                    category = Category(elem)
 
419
                    if self._categories.has_key(category.categoryid):
 
420
                        thatcat = self._categories[category.categoryid]
 
421
                        thatcat.add(category)
 
422
                    else:
 
423
                        self._categories[category.categoryid] = category
 
424
        except SyntaxError, e:
 
425
            raise CompsException, "comps file is empty/damaged"
 
426
            del parser
 
427
            
 
428
        del parser
 
429
        
 
430
    def compile(self, pkgtuplist):
 
431
        """ compile the groups into installed/available groups """
 
432
        
 
433
        # convert the tuple list to a simple dict of pkgnames
 
434
        inst_pkg_names = {}
 
435
        for (n,a,e,v,r) in pkgtuplist:
 
436
            inst_pkg_names[n] = 1
 
437
        
 
438
 
 
439
        for group in self.groups:
 
440
            # if there are mandatory packages in the group, then make sure
 
441
            # they're all installed.  if any are missing, then the group
 
442
            # isn't installed.
 
443
            if len(group.mandatory_packages) > 0:
 
444
                group.installed = True
 
445
                for pkgname in group.mandatory_packages:
 
446
                    if not inst_pkg_names.has_key(pkgname):
 
447
                        group.installed = False
 
448
                        break
 
449
            # if it doesn't have any of those then see if it has ANY of the
 
450
            # optional/default packages installed.
 
451
            # If so - then the group is installed
 
452
            else:
 
453
                check_pkgs = group.optional_packages.keys() + group.default_packages.keys() + group.conditional_packages.keys()
 
454
                group.installed = False
 
455
                for pkgname in check_pkgs:
 
456
                    if inst_pkg_names.has_key(pkgname):
 
457
                        group.installed = True
 
458
                        break
 
459
        
 
460
        self.compiled = True
 
461
    
 
462
    def xml(self):
 
463
        """returns the xml of the comps files in this class, merged"""
 
464
 
 
465
        if not self._groups and not self._categories:
 
466
            return ""
 
467
            
 
468
        msg = """<?xml version="1.0" encoding="UTF-8"?>
 
469
<!DOCTYPE comps PUBLIC "-//Red Hat, Inc.//DTD Comps info//EN" "comps.dtd">
 
470
<comps>
 
471
""" 
 
472
 
 
473
        for g in self.get_groups():
 
474
            msg += g.xml()
 
475
        for c in self.get_categories():
 
476
            msg += c.xml()
 
477
 
 
478
        msg += """</comps>\n"""
 
479
        
 
480
        return msg
 
481
            
 
482
        
 
483
        
324
484
def main():
325
485
 
326
 
    signal.signal(signal.SIGINT, signal.SIG_DFL)
327
 
    opts, args = getopt.getopt(sys.argv[1:], '',
328
 
                               ['help'])
329
 
 
330
 
    for opt, arg in opts:
331
 
        if opt == '--help':
332
 
            print usage
333
 
            sys.exit(0)
334
 
    if len(args) != 1:
335
 
        print >> sys.stderr, usage
336
 
        sys.exit(1)
337
486
    try:
338
 
        p = Comps(args[0])
 
487
        print sys.argv[1]
 
488
        p = Comps()
 
489
        for srcfile in sys.argv[1:]:
 
490
            p.add(srcfile)
339
491
 
 
492
        for group in p.groups:
 
493
            print group
 
494
            for pkg in group.packages:
 
495
                print '  ' + pkg
 
496
        
 
497
        for category in p.categories:
 
498
            print category.name
 
499
            for group in category.groups:
 
500
                print '  ' + group
 
501
                
340
502
    except IOError:
341
 
        print >> sys.stderr, "pkggroup.py: No such file:\'%s\'" % args[0]
 
503
        print >> sys.stderr, "newcomps.py: No such file:\'%s\'" % sys.argv[1]
342
504
        sys.exit(1)
 
505
        
343
506
if __name__ == '__main__':
344
507
    main()
 
508