Viewing file: GroupSet.py (40.14 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# # hdrlist.py: header list and group set management. # Parts from old anaconda/comps.py # # Erik Troan <ewt@redhat.com> # Matt Wilson <msw@redhat.com> # Michael Fulbright <msf@redhat.com> # Jeremy Katz <katzj@redhat.com> # # Copyright 2001-2003 Red Hat, Inc. # # This software may be freely redistributed under the terms of the GNU # library public license. # # You should have received a copy of the GNU Library Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #
import rpm import os,sys,time import urllib2
from rhpl.log import log from rhpl.translate import _, N_, _expandLang import rhpl.comps import rhpl.arch
from size_string import size_string from constants import * import method
def showMem(): f = open("/proc/self/status", "r") lines = f.readlines() f.close() for line in lines: if line.startswith("VmSize:"): vmsize = line.split(":")[1].strip() if line.startswith("VmRSS:"): vmrss = line.split(":")[1].strip() print vmsize, vmrss
def nevra(hdr): "Convenience function to return the NEVRA in canonical form for a header." if hdr[rpm.RPMTAG_EPOCH]: epoch = hdr[rpm.RPMTAG_EPOCH] else: epoch = "0"
return "%s-%s:%s-%s.%s" %(hdr[rpm.RPMTAG_NAME], epoch, hdr[rpm.RPMTAG_VERSION], hdr[rpm.RPMTAG_RELEASE], hdr[rpm.RPMTAG_ARCH])
def tenevra(te): "Convenience function to return the NEVRA in a canonical form for a te." if te.E(): epoch = te.E() else: epoch = "0"
return "%s-%s:%s-%s.%s" %(te.N(), epoch, te.V(), te.R(), te.A())
def getLangs(): if os.environ.has_key("LANG"): langs = _expandLang(os.environ["LANG"]) else: langs = [] return langs
# poor heuristic for figuring out the best of two packages with the same # name. it sucks, but it's the best we've got right now. # basically, we generally prefer the shorter name with some special-case # caveats. def betterPackageForProvides(h1, h2): # make sure we don't try to return a bogus arch if h1 is not None and rhpl.arch.score(h1['arch']) == 0: h1 = None if h2 is not None and rhpl.arch.score(h2['arch']) == 0: h2 = None # if one is none, return the other if h2 is None: return h1 if h1 is None: return h2
# if we're already being installed, then we're clearly the superior # answer if h1.isSelected(): return h1 if h2.isSelected(): return h2 # sendmail is preferred over postfix if h1['name'] == "sendmail" and h2['name'] == "postfix": return h1 if h2['name'] == "sendmail" and h1['name'] == "postfix": return h2
# we generally prefer non-devel over devel if h1['name'].endswith("-devel") and not h2["name"].endswith("-devel"): return h2 if h2['name'].endswith("-devel") and not h1["name"].endswith("-devel"): return h1
# else, shorter name wins # this handles glibc-debug, kernel-*, kde2-compat, etc if len(h1['name']) < len(h2['name']): return h1 if len(h2['name']) < len(h1['name']): return h2
# same package names, which is a better arch? score1 = rhpl.arch.score(h1['arch']) score2 = rhpl.arch.score(h2['arch']) if (score1 < score2): return h1 elif (score2 < score1): return h2
# okay, there's no convincing difference. just go with the first return h1
cached = {} # returns the best nevra in hdrlist to match dep def depMatch(dep, evr, flags, hdrlist): def versionMatch(h, evr, flags): if evr is None or not evr or not flags: return 1
# split the e:v-r into explicit epoch, version, release parts idx = evr.find(":") if idx != -1: epoch = evr[:idx] evr = evr[idx:] else: epoch = "0" idx = evr.find("-") if idx != -1: version = evr[:idx] release = evr[idx:] else: version = evr release = ""
if h[rpm.RPMTAG_EPOCH] is not None: hevr = (h[rpm.RPMTAG_EPOCH], h[rpm.RPMTAG_VERSION], h[rpm.RPMTAG_RELEASE]) else: hevr = ("0", h[rpm.RPMTAG_VERSION], h[rpm.RPMTAG_RELEASE])
cmp = rpm.labelCompare(hevr, (epoch, version, release))
if (cmp < 0) and (flags & (rpm.RPMSENSE_LESS)): return 1 elif (cmp > 0) and (flags & (rpm.RPMSENSE_GREATER)): return 1 elif (cmp == 0) and (flags & (rpm.RPMSENSE_EQUAL)): return 1
# evr doesn't match return 0 # ignore rpmlib if dep.startswith("rpmlib("): return None # try to see if it just exists first elif hdrlist.has_key(dep): return nevra(hdrlist[dep]) elif cached.has_key(dep): return cached[dep] # next, see if its a file dep elif dep[0] == "/": hdr = None for h in hdrlist.pkgs.values(): l = [] for f in h.hdr.fiFromHeader(): l.append(f[0]) if (dep in l): hdr = betterPackageForProvides(h, hdr) if hdr is not None: # cache all binaries from this package. helps with, eg, coreutils for f in hdr.hdr.fiFromHeader(): if f[0].find("bin") != -1: cached[f[0]] = nevra(hdr) cached[dep] = nevra(hdr) return nevra(hdr)
# else: # need to do this even on file deps too because they could be virtual # provides such as /usr/sbin/sendmail or /usr/bin/lpr. if 1: hdr = None for h in hdrlist.pkgs.values(): if (dep in h[rpm.RPMTAG_PROVIDENAME]): if versionMatch(h, evr, flags): hdr = betterPackageForProvides(h, hdr) elif LOOSEREQ: log("allowing %s to satisfy %s-%s" %(h.nevra(), dep, evr)) hdr = betterPackageForProvides(h, hdr) if hdr is not None: cached[dep] = nevra(hdr) return nevra(hdr) return None
class DependencyChecker: def __init__(self, grpset, how = "i"): self.grpset = grpset self.added = [] self.unknown = [] self.how = how
# FIXME: this is the simple stupid version. it doesn't actually handle # paying attention to EVR. def callback(self, ts, tag, name, evr, flags): if tag == rpm.RPMTAG_REQUIRENAME: pkgnevra = depMatch(name, evr, flags, self.grpset.hdrlist) if pkgnevra and self.grpset.hdrlist.has_key(pkgnevra): hdr = self.grpset.hdrlist[pkgnevra] else: hdr = None if hdr is not None and not hdr.isSelected(): if evr: nevr = "%s-%s" %(name, evr) else: nevr = name log("using %s to satisfy %s" %(nevra(hdr), nevr)) ts.addInstall(hdr.hdr, hdr.hdr, self.how) # hdr.select(asDependency = 1) self.added.append(nevra(hdr.hdr))
return -1
return 1
class Package: def __init__(self, hdr, method): self.hdr = hdr self.method = method self.installState = NOT_INSTALLED self.name = hdr[rpm.RPMTAG_NAME] self.filename = None self.id = self.nevra()
self.oldState = None
def __getitem__(self, item): if item == RCPFILELOCATIONTAG: return self.filename else: return self.hdr[item]
def setFilename(self, filename): self.filename = filename
def select(self, asDependency = 0): # this package may just be needed for a dependency and we want # to be able to revert to it if so (deps are selected prior to # a ts run and we then give people a chance to back out if asDependency == 1: if self.oldState is not None: print "WARNING: %s had an old state and tried to set it again. %s to %s" % (self.name, self.oldState, self.installState) else: self.oldState = self.installState
if self.installState == INSTALLED: print "selecting already installed package %s" %(self.name,) elif self.installState == TOINSTALL or self.installState == TOUPGRADE: print "selecting already selected package %s" %(self.name,) elif self.installState == NOT_INSTALLED: self.installState = TOINSTALL elif self.installState == TOREMOVE: # FIXME: is this sane? it can only be marked for removal # if it was previously installed afaics # We also lose the maybe upgrade state self.installState = INSTALLED
def unselect(self, set = None, asDependency = 0): # this package may just be needed for a dependency and we want # to be able to revert to it if so (deps are selected prior to # a ts run and we then give people a chance to back out
if asDependency == 1: if self.oldState is not None: print "WARNING: %s had an old state and tried to set it again. %s to %s" % (self.name, self.oldState, self.installState) else: self.oldState = self.installState
# if it was previously installed (which touprade also implies), # mark it for removal -- else, revert back to not installed if (self.installState == INSTALLED or self.installState == TOUPGRADE): self.installState = TOREMOVE elif self.installState == TOINSTALL: self.installState = NOT_INSTALLED elif self.installState == NOT_INSTALLED: print "Unselecting already uninstalled package %s" %(self.name,) elif self.installState == TOREMOVE: print "Unselecting %s already marked for removal" %(self.name,)
def revert(self): if self.oldState is not None: self.installState = self.oldState self.oldState = None
def isSelected(self, toInstallOnly = 0): if ((self.installState == TOINSTALL) or (self.installState == TOUPGRADE) or ((toInstallOnly == 0) and (self.installState == INSTALLED))): return 1 else: return 0
def isBeingRemoved(self): if self.installState == TOREMOVE: return 1 else: return 0
def isInstalled(self): return (self.installState == INSTALLED)
def selectForUpgrade(self): self.installState = TOUPGRADE
# this is a misnomer since we actually return the summary instead of # the description, but oh well def getDescription(self): return self.hdr[rpm.RPMTAG_SUMMARY]
def getName(self): return self.hdr[rpm.RPMTAG_NAME]
def getVersion(self): version = self.hdr[rpm.RPMTAG_VERSION] + "-" + self.hdr[rpm.RPMTAG_RELEASE] return version
def getSize(self): return self.hdr[rpm.RPMTAG_SIZE]
# FIXME: this is a quick hack to move the method into the package # so that we can install packages from multiple sources easily def getFilename(self, pkgTimer): return self.method.getFilename(self, pkgTimer)
def __repr__(self): return "%s" %(self.nevra(),)
def nevra(self): return nevra(self.hdr)
class HeaderList: def __init__(self, hdlist, method): self.hdlist = hdlist self.pkgs = {} self.pkgnames = {}
self.addHeaders(hdlist, method) self.hasFullHeaders = None
def addHeaders(self, hdlist, method): for h in hdlist: nevrastr = nevra(h)
if self.pkgs.has_key(nevrastr): log("Have more than one copy of %s, skipping" %(nevrastr,)) continue
self.addHeader(h, method)
def addHeader(self, h, method): name = h['name'] nevrastr = nevra(h)
p = Package(h, method) self.pkgs[nevrastr] = p if self.pkgnames.has_key(name): self.pkgnames[name].append( (nevrastr, h['arch']) ) else: self.pkgnames[name] = [ (nevrastr, h['arch']) ] return p
def mergeRpmDb(self, instPath = "/"): installedmethod = method.InstalledPackageMethod()
ts = rpm.TransactionSet(instPath) ts.setVSFlags(~(rpm.RPMVSF_NORSA|rpm.RPMVSF_NODSA)) ts.setFlags(~rpm.RPMTRANS_FLAG_NOMD5) mi = ts.dbMatch() for h in mi: name = h[rpm.RPMTAG_NAME] nevrastr = nevra(h)
if self.pkgs.has_key(nevrastr): self.pkgs[nevrastr].installState = INSTALLED elif self.pkgnames.has_key(name): for (pnevra, arch) in self.pkgnames[name]: # FIXME: this will work for most cases, but if we ever # start adding arches, it will break down. I kind of # go on the assumption that if arch != h['arch']: continue hdr = self.pkgs[pnevra] val = rpm.versionCompare(h, hdr.hdr) if val < 0: pass # print "have an older version installed of %s" %(name) if ALLOWUPGRADE == 1: self[name].selectForUpgrade() else: p = self.addHeader(h, installedmethod) p.installState = INSTALLED elif val > 0: p = self.addHeader(h, installedmethod) p.installState = INSTALLED
# del self.pkgs[pnevra] # self.pkgnames[name].remove( (pnevra, arch) ) #print "have a newer version installed of %s" %(name,) else: self.pkgs[pnevra].installState = INSTALLED # they're the same version, don't worry about it pass else: p = self.addHeader(h, installedmethod) p.installState = INSTALLED
def has_key(self, item): if self.pkgs.has_key(item): return 1 elif self.getBestNevra(item): return 1 return 0
def keys(self): return self.pkgnames.keys()
def values(self): return self.pkgs.values()
# this is definite crack rock, but it allows us to avoid tripling # our memory usage :( # reads an hdlist2 file and merges the header information we split out # (things like file lists) def mergeFullHeaders(self, file): if self.hasFullHeaders is not None: return fd = os.open(file, os.O_RDONLY) rpm.mergeHeaderListFromFD(self.hdlist, fd, 1000004) os.close(fd) self.hasFullHeaders = 1 def preordered(self): preordered = 1 for h in self.pkgs.values(): if h.isSelected() and h[1000003] == None: preordered = 0 return preordered
# get the best nevra for the package name. # FIXME: surely this can be made faster/less complicated # doing scoring everytime seems like it might be overkill # then again, it shouldn't be called *that* often so it might not matter # prefInstalled: prefer an installed of an older version def getBestNevra(self, item, prefArch = None, prefInstalled = 0): bestscore = 0 bestpkg = None bestinst = 0
if not self.pkgnames.has_key(item): return None
# the best nevra is going to be defined by being 1) the best match # for the primary arch (eg, x86_64 on AMD64, ppc on pSeries) and # if that fails, fall back to the canonical (which could be the same) # This will allow us to get the best package by name for both # system packages and kernel while not getting the secondary arch # glibc. if prefArch is not None: arches = (prefArch, ) elif rhpl.arch.getBaseArch() != rhpl.arch.canonArch: arches = (rhpl.arch.getBaseArch(), rhpl.arch.canonArch) else: arches = (rhpl.arch.canonArch, ) for basearch in arches: for (nevra, arch) in self.pkgnames[item]: score = rhpl.arch.archDifference(basearch, arch) if not score: continue if ((bestscore == 0) or (score < bestscore) or (prefInstalled and not bestinst and self.pkgs[nevra].isInstalled())): bestpkg = nevra bestscore = score bestinst = self.pkgs[nevra].isInstalled() if bestpkg is not None: return bestpkg return bestpkg
# FIXME: surely this can be made faster/less complicated # doing scoring everytime seems like it might be overkill # then again, it shouldn't be called *that* often so it might not matter def __getitem__(self, item): if self.pkgs.has_key(item): return self.pkgs[item]
# explict nevra not specified -- see what we can do pkg = self.getBestNevra(item)
if pkg is None: raise KeyError, "No such package %s" %(item,)
return self.pkgs[pkg]
class HeaderListFromFile (HeaderList): def __init__(self, path, method, update_method = None): hdlist = rpm.readHeaderListFromFile(path) if update_method: update_method(0.7) HeaderList.__init__(self, hdlist, method) if update_method: update_method(1.0)
# FIXME: this is magic that mostly happens to work with current # stuff. the whole hdlist + hdlist2 thing needs to be revisited # at some point path2 = "%s2" %(path,) if os.access(path2, os.O_RDONLY): fd = os.open(path2, os.O_RDONLY) rpm.mergeHeaderListFromFD(self.hdlist, fd, 1000004) os.close(fd)
class HeaderListFromFds(HeaderList): def __init__(self, fd1, fd2, method, update_method=None): hdlist = rpm.readHeaderListFromFD(fd1) if update_method: update_method(0.7) HeaderList.__init__(self, hdlist, method) if update_method: update_method(1.0)
# FIXME: this is magic that mostly happens to work with current # stuff. the whole hdlist + hdlist2 thing needs to be revisited # at some point if fd2 is not None: rpm.mergeHeaderListFromFD(self.hdlist, fd2, 1000004)
class Group: def __init__(self, grpset, xmlgrp): self.id = xmlgrp.id self.basename = xmlgrp.name
# We want to have translated name/descriptions self.name = None self.description = None for lang in getLangs(): if (self.name is None and xmlgrp.translated_name.has_key(lang)): self.name = xmlgrp.translated_name[lang] if (self.description is None and xmlgrp.translated_description.has_key(lang)): self.description = xmlgrp.translated_description[lang] # fall back to english if they're not set and try to see if the # translation is in the anaconda.po (eg, Everything) if self.name is None: self.name = _(xmlgrp.name) if self.description is None: self.description = xmlgrp.description
# obviously enough, hidden components aren't shown self.hidden = not xmlgrp.user_visible
# whether or not a group should be enabled by default. only # really matters for custom installs self.default = xmlgrp.default
# if it's a biarch group and we're not a biarch-arch, be hidden and off if xmlgrp.biarchonly and rhpl.arch.getMultiArchInfo() is None: self.hidden = 1 self.default = 0
# figure out the preferred arch. if this isn't a biarch group, # fall back to the normal picking. if its a biarch group and we # are a biarch arch, use the information we've got if xmlgrp.biarchonly and rhpl.arch.getMultiArchInfo() is not None: (comp, best, biarch) = rhpl.arch.getMultiArchInfo() pref = biarch else: pref = None
# FIXME: this is a hack to handle language support groups self.langonly = xmlgrp.langonly
# FIXME: do we really want to keep this? needed to select packages self.grpset = grpset hdrlist = grpset.hdrlist
# state self.installState = INSTALLED self.manual_state = MANUAL_NONE
# included groups (ie groups that are required if we're selected) self.groupreqs = []
found = 0 self.packages = {} for (pkg, (type, name)) in xmlgrp.packages.items(): pkgnevra = hdrlist.getBestNevra(pkg, prefArch = pref, prefInstalled = 1) if pkgnevra is None: log("%s references package %s which doesn't exist" %(self.id, pkg)) continue
self.packages[pkgnevra] = self.makePackageDict(pkgnevra, type)
if type == u"mandatory" and not hdrlist[pkgnevra].isInstalled(): log("%s not installed in group %s" %(pkgnevra, self.name)) self.installState = NOT_INSTALLED
if hdrlist[pkgnevra].isInstalled(): found = 1
# if we don't have any packages, make it hidden to avoid confusion if len(self.packages.keys()) == 0: self.hidden = 1
if found == 0 and self.installState == INSTALLED: log("setting %s to not installed" %(self.name,)) self.installState = NOT_INSTALLED
def addGroupRequires(self, grpid): if grpid not in self.groupreqs: self.groupreqs.append(grpid)
def addMetaPkg(self, metapkginfo): (type, id) = metapkginfo if id in self.packages.keys(): log("already have %s in %s" %(id, self.id)) return self.packages[id] = self.makePackageDict(id, type, isMeta = 1)
# dict of package info. nevra and type are obvious # state is one of the ON/OFF states def makePackageDict(self, pkgnevra, type, installed = 0, isMeta = 0): if type == u'mandatory': pkgtype = PKGTYPE_MANDATORY elif type == u'default': pkgtype = PKGTYPE_DEFAULT elif type == u'optional': pkgtype = PKGTYPE_OPTIONAL else: log("Invalid package type of %s for %s in %s; defaulting to " "optional" % (type, pkgnevra, self.id)) pkgtype = PKGTYPE_OPTIONAL return { "nevra": pkgnevra, "type": pkgtype, "state": installed, "meta": isMeta }
# FIXME: this doesn't seem like the right place for it, but ... :/ def selectDeps(self, pkgs, uses = 1): checked = [] while len(pkgs) > 0: tocheck = pkgs pkgs = [] for pkgnevra in tocheck: if pkgnevra in checked: continue pkg = self.grpset.hdrlist[pkgnevra]
# this is a little bit complicated. we don't want to keep # the deps in the comps file (because that gets ugly with biarch) # but we also don't want to have to resolve every time # (it's slow!). so, we cache the first time through if pkg.depsFound == 0: deps = (pkg[rpm.RPMTAG_REQUIRENAME], pkg[rpm.RPMTAG_REQUIREVERSION], pkg[rpm.RPMTAG_REQUIREFLAGS]) thisone = [] for (dep, depver, depflag) in deps: # hey wait, this is me! if ((pkg[rpm.RPMTAG_PROVIDENAME] is not None) and (dep in pkg[rpm.RPMTAG_PROVIDENAME])): continue for f in pkg.hdr.fiFromHeader(): if f[0] == dep: continue # ignore rpmlib stuff if dep.startswith("rpmlib("): continue p = depMatch(dep, depver, depflag, self.grpset.hdrlist) # don't care about self referential deps if p == pkg.nevra(): continue if p in checked or p in tocheck or p in pkgs: continue if p is None: # log("ERROR: unable to resolve dep %s" %(dep,)) continue
self.grpset.hdrlist[p].select() # FIXME: this is a hack so we can make sure the # usecount is bumped high enough for # langsupport packages self.grpset.hdrlist[p].usecount += uses - 1
pkgs.append(p) thisone.append(p) pkg.addDeps(thisone) else: deps = pkg.dependencies for dep in deps: # if we've already checked for this package, don't worry if dep in checked or dep in tocheck or dep in pkgs: continue # hmm, not in the header list. we can't do much but # hope for the best if not self.grpset.hdrlist.has_key(dep): log("Package %s requires %s which we don't have" %(tocheck, dep)) continue self.grpset.hdrlist[dep].select() pkgs.append(dep) checked.append(pkgnevra)
# FIXME: this doesn't seem like the right place for it, but ... :/ def unselectDeps(self, pkgs): checked = [] while len(pkgs) > 0: tocheck = pkgs pkgs = [] for pkgnevra in tocheck: pkg = self.grpset.hdrlist[pkgnevra]
deps = pkg.dependencies for dep in deps: # if we've already checked for this package, don't worry if dep in checked or dep in tocheck or dep in pkgs: continue # hmm, not in the header list. we can't do much but # hope for the best if not self.grpset.hdrlist.has_key(dep): log("Package %s requires %s which we don't have" %(tocheck, dep)) continue self.grpset.hdrlist[dep].unselect() pkgs.append(dep) checked.append(pkgnevra)
# forInclude is whether this group is an include from a previous # asMeta means that we should include the members of the group, # but not this one (useful for Workstation Common, etc) def select(self, forInclude = 0, selectOptional = 0): hdrlist = self.grpset.hdrlist
if self.installState == INSTALLED or self.installState == TOINSTALL: return
if not forInclude: self.manual_state = MANUAL_ON
for grpid in self.groupreqs: self.grpset.groups[grpid].select(forInclude = 1)
selected = [] for (pkgnevra, pkg) in self.packages.items(): # if it's not optional, we should turn it on if pkg["type"] == PKGTYPE_OPTIONAL and not selectOptional: continue pkg["state"] = ON if pkg["meta"] == 0: hdrlist[pkgnevra].select() selected.append(pkgnevra) # self.selectDeps([pkgnevra]) else: self.grpset.groups[pkgnevra].select(forInclude = 1)
if self.installState == INSTALLED: print "selecting already installed component %s" %(self.name,) elif self.installState == TOINSTALL: print "selecting already toinstall component %s" %(self.name,) elif self.installState == NOT_INSTALLED: self.installState = INSTALLED elif self.installState == TOREMOVE: self.installState = INSTALLED
# manual package selection def selectPackage(self, pkgnevra): pkg = self.packages[pkgnevra] if pkg["state"] in ON_STATES: return pkg["state"] = ON if pkg["meta"] == 0: self.grpset.hdrlist[pkgnevra].select() # self.selectDeps([pkgnevra]) else: self.grpset.groups[pkgnevra].select(forInclude = 1) def unselect(self, forInclude = 0): hdrlist = self.grpset.hdrlist
if not forInclude: self.manual_state = MANUAL_OFF else: # FIXME: this isn't really right for an anaconda-type install # case, but we don't want people being able to traverse includes # by removing components from redhat-config-packages afaict # (it can lead to things like base being removed which is bad ;) return
for grpid in self.groupreqs: self.grpset.groups[grpid].unselect(forInclude = 1)
selected = [] for pkg in self.packages.values(): pkgnevra = pkg["nevra"] pkg["state"] = OFF if pkg["meta"] == 0: hdrlist[pkgnevra].unselect() selected.append(pkgnevra) # self.unselectDeps([pkgnevra]) else: self.grpset.groups[pkgnevra].unselect(forInclude = 1)
if self.installState == INSTALLED: self.installState = TOREMOVE elif self.installState == TOINSTALL: self.installState = NOT_INSTALLED elif self.installState == NOT_INSTALLED: print "Unselecting already uninstalled package %s" %(self.name,) elif self.installState == TOREMOVE: print "Unselecting %s already marked for removal" %(self.name,)
def unselectPackage(self, pkgnevra): pkg = self.packages[pkgnevra] if pkg["meta"] == 0 and not self.grpset.hdrlist[pkgnevra].isSelected(): return # if pkg["state"] not in ON_STATES: # return pkg["state"] = OFF if pkg["meta"] == 0: self.grpset.hdrlist[pkgnevra].unselect() # self.unselectDeps([pkgnevra]) else: self.grpset.groups[pkgnevra].unselect(forInclude = 0)
def isSelected(self, justManual=0): if self.installState == INSTALLED or self.installState == TOINSTALL: return 1 else: return 0
def packageInfo(self, type = PKGTYPE_ALL): ret = {} for pkg in self.packages.values(): if type == PKGTYPE_ALL or (pkg["type"] & type): ret[pkg["nevra"]] = (pkg["type"], pkg["state"])
return ret
# FIXME: remove this def includesPackage(self, pkg): pkgnevra = nevra(pkg) if self.packages.has_key(pkgnevra): return 1
# make sure it's not in this group for deps tocheck = self.packages.keys() checked = [] while len(tocheck) > 0: pkgs = tocheck tocheck = [] for p in pkgs: if pkgnevra in self.grpset.hdrlist[p].dependencies: return 1 checked.append(p) for m in self.grpset.hdrlist[p].dependencies: if m not in checked and m not in tocheck: tocheck.append(m) return 0 def getDescription(self): return self.description
def getName(self): return self.name
def getSize(self): size = 0 for p in self.packageInfo(type = (PKGTYPE_MANDATORY | PKGTYPE_DEFAULT)): pkg = self.packages[p] if pkg["meta"] == 0: size += self.grpset.hdrlist[p].getSize() else: size += self.grpset.groups[p].getSize()
return size
class GroupSet: def __init__(self, compsxml, hdrlist): self.hdrlist = hdrlist self.compsxml = compsxml self.groups = {}
for xmlgrp in compsxml.groups.values(): group = Group(self, xmlgrp) self.groups[xmlgrp.id] = group
# have to do includes and metagroups in a second pass so that # we can make sure the group is defined. for xmlgrp in compsxml.groups.values(): group = self.groups[xmlgrp.id] for id in xmlgrp.groups.keys(): if not self.groups.has_key(id): log("%s references component %s which doesn't exist" %(xmlgrp.id, id)) continue group.addGroupRequires(id)
for id in xmlgrp.metapkgs.keys(): if not self.groups.has_key(id): log("%s references component %s which doesn't exist" %(xmlgrp.id, id)) continue if len(self.groups[id].packages.keys()) == 0: log("%s references component %s which doesn't have " "any packages" %(xmlgrp.id, id)) continue group.addMetaPkg(xmlgrp.metapkgs[id]) if xmlgrp.user_visible and group.hidden: group.hidden = 0
# FIXME: this used to exist for setting up provides/requires dicts # to make transaction buildup faster. now that I use the depcheck # callback, do I still need this? def setupStateDicts(self, update_method = None): if self.update_method: apply (self.update_method, (0.5,)) # figure out the installed state of our packages # FIXME: this really shouldn't be done here ts = rpm.TransactionSet("/") # screwy backwards logic ts.setVSFlags(~(rpm.RPMVSF_NORSA|rpm.RPMVSF_NODSA)) ts.setFlags(~rpm.RPMTRANS_FLAG_NOMD5)
pkgs = self.hdrlist.values() if self.update_method: incr = 0.5/len(keys) count = 0.5 for pkg in pkgs: if self.update_method: apply (self,update_method, (counter,)) counter = counter + incr
mi = ts.dbMatch('name', pkg[rpm.RPMTAG_NAME]) for h in mi: if h[rpm.RPMTAG_ARCH] == pkg[rpm.RPMTAG_ARCH]: pkg.installState = INSTALLED
def selectGroup(self, group, asMeta = 0): if self.groups.has_key(group): self.groups[group].select(asMeta = asMeta) return for grp in self.compsxml.groups.values(): if (grp.name == group) and self.groups.has_key(grp.id): self.groups[grp.id].select(asMeta = asMeta) return raise KeyError, "No such group %s" %(group,)
def size(self): size = 0 for pkg in self.hdrlist.values(): if pkg.isSelected(): size = size + (pkg[rpm.RPMTAG_SIZE])
return size
def sizeStr(self): return size_string(self.size())
def revertState(self): for pkg in self.hdrlist.values(): pkg.revert()
def groupSetFromCompsFile(filename, hdrlist, doSelect = 1, update_method = None): if filename is not None: tries = 0 while tries < 5: try: file = urllib2.urlopen(filename) except urllib2.HTTPError, e: log("HTTPError: %s occurred getting %s", filename, e) except urllib2.URLError, e: log("URLError: %s occurred getting %s", filename, e) except IOError, (errnum, msg): log("IOError %s occurred getting %s: %s", filename, errnum, str(msg)) except IOError, (errnum, msg): log("OSError %s occurred getting %s: %s", filename, errnum, str(msg)) else: break
time.sleep(5) tries = tries + 1 compsxml = rhpl.comps.Comps(file) file.close() else: compsxml = rhpl.comps.Comps()
grpset = GroupSet(compsxml, hdrlist)
if doSelect: for group in grpset.groups.values(): if group.default: group.select() return grpset
# this is a temporary way to set order of packages def orderPackageGroups(grpset): compsHierarchy = grpset.compsxml.hierarchy try: compsParents = grpset.compsxml.hierarchy.order except: compsParents = []
grpids = [] for grp in grpset.groups.values(): grpids.append(grp.id)
ignorelst = [] retlist = [] retdict = {}
langs = getLangs() for key in compsParents:
# get the translated name myname = None if not compsHierarchy.translations.has_key(key): myname = key else: for lang in langs: if compsHierarchy.translations[key].has_key(lang): myname = compsHierarchy.translations[key][lang] break if myname is None: myname = key retlist.append(myname) retdict[myname] = [] compslist = compsHierarchy[key] for grp in compslist:
if grp in grpids: thecomp = grpset.groups[grp] ignorelst.append(grp) retdict[myname].append(thecomp)
miscgrp = _("Miscellaneous") for grp in grpids: if grp in ignorelst: continue
thecomp = grpset.groups[grp] if thecomp.hidden: continue if miscgrp not in retlist: retlist.append(miscgrp) retdict[miscgrp] = [thecomp] else: retdict[miscgrp].append(thecomp) return (retlist, retdict)
if __name__ == "__main__": tree = "/mnt/redhat/test/katzj2/i386/i386/" def simpleInstallCallback(what, amount, total, h, (param)): global rpmfd if (what == rpm.RPMCALLBACK_TRANS_START): # step 6 is the bulk of the transaction set # processing time if amount == 6: pass print "Preparing to install..." if (what == rpm.RPMCALLBACK_TRANS_PROGRESS): pass if (what == rpm.RPMCALLBACK_TRANS_STOP): pass
if (what == rpm.RPMCALLBACK_INST_OPEN_FILE): print "Installing %s" %(nevra(h),) rpmfd = os.open("%s/RedHat/RPMS/%s-%s-%s.%s.rpm" %(tree, h['name'], h['version'], h['release'], h['arch']), os.O_RDONLY) return rpmfd elif (what == rpm.RPMCALLBACK_INST_PROGRESS): pass elif (what == rpm.RPMCALLBACK_INST_CLOSE_FILE): os.close (rpmfd) elif ((what == rpm.RPMCALLBACK_UNPACK_ERROR) or (what == rpm.RPMCALLBACK_CPIO_ERROR)): print "ERROR!" sys.exit(0) else: pass
def packageSort(first, second): one = first[1000002] two = second[1000002]
if one < two: return -1 elif one > two: return 1 return 0 fd = os.open(tree + "/RedHat/base/hdlist", os.O_RDONLY) hdrs = rpm.readHeaderListFromFD(fd) os.close(fd) showMem() # fd = os.open(tree + "/RedHat/base/hdlist2", os.O_RDONLY) # rpm.mergeHeaderListFromFD(hdrs, fd, 1000004) # os.close(fd) showMem() f = open(tree + "/RedHat/base/comps.xml", "r") comps = rhpl.comps.Comps(f) f.close() showMem() hdrlist = HeaderList(hdrs) hdrlist.mergeFullHeaders(tree + "/RedHat/base/hdlist2") showMem() groups = GroupSet(comps, hdrlist) showMem()
ts = rpm.TransactionSet("/tmp/testinstall") ts.setVSFlags(-1) ts.setFlags(rpm.RPMTRANS_FLAG_ANACONDA) showMem()
l = [] groups.groups["base"].select() groups.hdrlist["evolution"].select()
for hdr in groups.hdrlist.pkgs.values(): if hdr.isSelected(): l.append(hdr) print "going to install %s" %(nevra(hdr),)
depcheck = DependencyChecker(groups)
l.sort(packageSort) for h in l: ts.addInstall(h.hdr, h.hdr, "i") foo = ts.check(depcheck.callback)
print depcheck.added sys.exit(0) ts.run(simpleInstallCallback, 0)
|