#!/usr/bin/python2.2 import sys import os import os.path import rpm import string # set up rpm dependency whiteouts import whiteout # FIXME: we really want this information somewhere, but not in the pkgorder # file itself. from rhpl.log import log from anaconda_log import anaconda_log anaconda_log.open("/dev/null") log.handler = anaconda_log rpmFD = None import comps def cmpHeaderByName(h1, h2): n1 = string.lower(h1['name']) n2 = string.lower(h2['name']) if n1 < n2: return -1 elif n1 == n2: return 0; return 1 # returns 1 if comp is in the parent chain for subcomp def isParent(comp, subcomp): if not subcomp: return 0 if subcomp.parent == comp: return 1 return isParent(comp, comp.parent) # turns on a whole comp chain def selectComp(comp): comp.select() if comp.parent: selectComp(comp.parent) # set PKGORDER_DEBUG to get rpm debugging if os.environ.has_key("PKGORDER_DEBUG"): rpm.setVerbosity(rpm.RPMLOG_DEBUG) if len(sys.argv) != 3: print "pkgorder " sys.exit(1) arch = sys.argv[2] distDir = os.path.normpath(sys.argv[1]) if not os.path.isdir(distDir): print "error: %s is not a directory" % distDir sys.exit(1) disc1Dir = distDir + "-disc1" disc1SrcDir = distDir + "-srpms" disc2Dir = distDir + "-disc2" # pull in the hdlist f = distDir + "/RedHat/base/hdlist" try: hdlist = comps.HeaderListFromFile(f, noscore = 1) hdlist.mergeFullHeaders(distDir + "/RedHat/base/hdlist2") except rpm.error: print "Failed to read header list", f sys.exit(1) # and read the comps file comps = comps.ComponentSet("file://%s/RedHat/base/comps.xml" %(distDir,), hdlist, arch = arch, matchAllLang = 0) # work out the order we'd like to install everything in pkgOrder = [] pkgHash = {} # We always want all the kernels-.* in our package list, except for a few for package in hdlist.keys(): if (package.startswith("kernel") and not package.startswith("kernel-doc") and not package.startswith("kernel-source") and not package.startswith("kernel-debug")): hdlist[package].selected = 1 pkgOrder.append(hdlist[package].h) pkgHash[hdlist[package].h] = None # Tier 1 language packages get priority. tier1langs = ("en:en_US:de:de_DE:es:es_ES:fr:fr_FR:it:it_IT:ja:ja_JP:" "ko:ko_KR:zh:zh_CN:zh_TW:pt:pt_BR:en_GB:en_CA") # Form a dictionary of _all_ the components, even sub comps compsDict = {} subComps = {} for h in hdlist.keys(): hdlist[h].selected = 0 for comp in hdlist[h].comps: compsDict[comp.name] = comp # make a list of all the names of all the components. allComps = compsDict.values() # go through all our toplevel components and add children to it. for comp in comps: compsDict[comp.name] = comp subComps[comp] = [] for c in allComps: if isParent(comp, c): subComps[comp].append(c) #print subComps #print compsDict # FIXME: this is a hack to get things we want to be first on the CDs earlier # in a more perfect world, we'd read the installclasses to do this complist = ["Core", "Base", "Text-based Internet", "Web Server", "Windows File Server", "Printing Support", "Dialup Networking Support", "Server Configuration Tools", "Administration Tools"] # now let's pull in all of workstation common if comps.has_key("Workstation Common"): comp = comps["Workstation Common"] complist.append("Workstation Common") for name in comp.includes: if name not in complist: complist.append(name) # a couple more that make sense to have early complist.extend(["GNOME Desktop Environment", "Emacs", "Development Tools", "Development Libraries", "X Software Development", "GNOME Software Development", "KDE Desktop Environment", "KDE Software Development"]) latelangs = [] for name in comps: if comp.name in complist: continue if ((comp.lang is not None) and (string.find(tier1langs, comp.lang) == -1)): latelangs.append(comp.name) else: complist.append(comp.name) complist.extend(latelangs) # for each comp, staring with base, list the packages # in alphabetical order. for name in complist: if not comps.has_key(name): continue comp = comps[name] list = [] # don't update the hdlist selection state yet, we're going to do # a lot of toggling here. comps.freeze() # make sure all the components are off for n in compsDict.values(): n.unselect () # turn on this component, and anything that this component needs # to have on in order to be on. selectComp(comp) if comp.conditionalKey: selectComp(comps[comp.conditionalKey]) # Do the same for each subcomponent for c in subComps[comp]: selectComp(c) if c.conditionalKey: selectComp(compsDict[c.conditionalKey]) # update the hdlist selection states comps.thaw() # append what got turned on to our order. for p in hdlist.selected(): list.append(p.h) list.sort(cmpHeaderByName) for item in list: if not pkgHash.has_key (item): pkgOrder.append(item) pkgHash[item] = None # add all of the packages that haven't been added yet. list = [] for p in hdlist.packages.values(): if not pkgHash.has_key (p.h): list.append(p.h) list.sort(cmpHeaderByName) for item in list: pkgOrder.append(item) # Now set up rpm to run the transaction deporder testpath = '/tmp/pkgorder-' + str (os.getpid ()) os.system ("mkdir -p " + testpath + "/var/lib/rpm") ts = rpm.TransactionSet(testpath) ts.setVSFlags(~(rpm.RPMVSF_NORSA|rpm.RPMVSF_NODSA)) ts.setFlags(rpm.RPMTRANS_FLAG_NOMD5|rpm.RPMTRANS_FLAG_ANACONDA) for h in pkgOrder: #print "in:", h[1000000] ts.addInstall(h, h, 'i') pkgOrder = [] # we have to run ts.check() before ts.order() now to set up the # alIndex. ts.check() ts.order() # Get the order back out... try: pkgOrder = ts.getKeys() except AttributeError: print "you don't have the latest RPM!" sys.exit(1) # print the results. for p in pkgOrder: print "%s-%s-%s" % (p['name'], p['version'], p['release'])