1 |
slords |
1.1 |
import rpm |
2 |
|
|
import rhpl.arch |
3 |
|
|
import string |
4 |
|
|
import types |
5 |
|
|
from constants import * |
6 |
|
|
|
7 |
|
|
# set DB_PRIVATE to make rpm happy |
8 |
|
|
rpm.addMacro("__dbi_cdb", "create private mpool mp_mmapsize=16Mb mp_size=1Mb") |
9 |
|
|
|
10 |
|
|
|
11 |
|
|
def dEBUG(str): |
12 |
|
|
print str |
13 |
|
|
|
14 |
|
|
def addNewPackageToUpgSet(pkgDict, pkg): |
15 |
|
|
"""Check to see if there's already a pkg by the name of pkg already |
16 |
|
|
in our dictionary. If not, add this one. If there is, see if |
17 |
|
|
this one is 'newer' or has a 'better' arch.""" |
18 |
|
|
name = pkg[rpm.RPMTAG_NAME] |
19 |
|
|
arch = pkg[rpm.RPMTAG_ARCH] |
20 |
|
|
if not pkgDict.has_key((name, arch)): |
21 |
|
|
# nope |
22 |
|
|
pkgDict[(name,arch)] = pkg |
23 |
|
|
else: |
24 |
|
|
# first check version |
25 |
|
|
val = rpm.versionCompare(pkgDict[(name,arch)], pkg) |
26 |
|
|
if val < 0: |
27 |
|
|
# we're newer, add this one |
28 |
|
|
pkgDict[(name,arch)] = pkg |
29 |
|
|
|
30 |
|
|
def comparePackageForUpgrade(updDict, h, pkg): |
31 |
|
|
val = rpm.versionCompare(h, pkg) |
32 |
|
|
if (val > 0): |
33 |
|
|
# dEBUG("found older version of %(name)s %(arch)s" % h) |
34 |
|
|
pass |
35 |
|
|
elif (val < 0): |
36 |
|
|
# dEBUG("found newer version of %(name)s %(arch)s" % h) |
37 |
|
|
# check if we already have this package in our dictionary |
38 |
|
|
addNewPackageToUpgSet(updDict, pkg) |
39 |
|
|
else: |
40 |
|
|
# dEBUG("found same verison of %(name)s %(arch)s" % h) |
41 |
|
|
pass |
42 |
|
|
|
43 |
|
|
def findBestArch(archlist): |
44 |
|
|
bestarch = None |
45 |
|
|
for availarch in archlist: |
46 |
|
|
newscore = rhpl.arch.score(availarch) |
47 |
|
|
# unsupported |
48 |
|
|
if newscore <= 0: |
49 |
|
|
continue |
50 |
|
|
# If old arch is better or same |
51 |
|
|
if bestarch and rhpl.arch.score(bestarch) <= newscore: |
52 |
|
|
continue |
53 |
|
|
|
54 |
|
|
# If we get here we're better |
55 |
|
|
bestarch = availarch |
56 |
|
|
return bestarch |
57 |
|
|
|
58 |
|
|
def getAvailPackages(hdrlist): |
59 |
|
|
# go through and figure out which packages in the header list are |
60 |
|
|
# actually applicable for our architecture |
61 |
|
|
pkgDict = {} |
62 |
|
|
nameDict = {} |
63 |
|
|
for h in hdrlist: |
64 |
|
|
score1 = rhpl.arch.score(h[rpm.RPMTAG_ARCH]) |
65 |
|
|
if (score1): |
66 |
|
|
name = h[rpm.RPMTAG_NAME] |
67 |
|
|
arch = h[rpm.RPMTAG_ARCH] |
68 |
|
|
pkgDict[(name,arch)] = h |
69 |
|
|
if nameDict.has_key(name): |
70 |
|
|
nameDict[name].append(arch) |
71 |
|
|
else: |
72 |
|
|
nameDict[name] = [ arch ] |
73 |
|
|
return (pkgDict, nameDict) |
74 |
|
|
|
75 |
|
|
def getInstalledPackages(dbPath='/'): |
76 |
|
|
pkgDict = {} |
77 |
|
|
nameDict = {} |
78 |
|
|
ts = rpm.TransactionSet(dbPath) |
79 |
|
|
ts.setVSFlags(~(rpm.RPMVSF_NORSA|rpm.RPMVSF_NODSA|rpm.RPMVSF_NOMD5)) |
80 |
|
|
mi = ts.dbMatch() |
81 |
|
|
for h in mi: |
82 |
|
|
name = h[rpm.RPMTAG_NAME] |
83 |
|
|
arch = h[rpm.RPMTAG_ARCH] |
84 |
|
|
pkgDict[(name,arch)] = h |
85 |
|
|
if nameDict.has_key(name): |
86 |
|
|
nameDict[name].append(arch) |
87 |
|
|
else: |
88 |
|
|
nameDict[name] = [ arch ] |
89 |
|
|
return (pkgDict, nameDict) |
90 |
|
|
|
91 |
|
|
def findpackageset(hdrlist, dbPath='/'): |
92 |
|
|
instDict = {} |
93 |
|
|
availDict = {} |
94 |
|
|
updDict = {} |
95 |
|
|
|
96 |
|
|
# dicts for name : [archlist] |
97 |
|
|
availNames = {} |
98 |
|
|
instNames = {} |
99 |
|
|
|
100 |
|
|
ts = rpm.TransactionSet(dbPath) |
101 |
|
|
ts.setVSFlags(~(rpm.RPMVSF_NORSA|rpm.RPMVSF_NODSA|rpm.RPMVSF_NOMD5)) |
102 |
|
|
|
103 |
|
|
(availDict, availNames) = getAvailPackages(hdrlist) |
104 |
|
|
(instDict, instNames) = getInstalledPackages(dbPath=dbPath) |
105 |
|
|
|
106 |
|
|
hdlist = availDict.values() |
107 |
|
|
|
108 |
|
|
# loop through packages and find ones which are a newer |
109 |
|
|
# version than what we have |
110 |
|
|
for ( name, arch ) in instDict.keys(): |
111 |
|
|
# See if we have a better arch than that installed |
112 |
|
|
if name in availNames.keys(): |
113 |
|
|
bestarch = findBestArch(availNames[name]) |
114 |
|
|
if not bestarch: |
115 |
|
|
continue |
116 |
|
|
if availDict.has_key((name,bestarch)): |
117 |
|
|
h = instDict[(name,arch)] |
118 |
|
|
pkg = availDict[(name,bestarch)] |
119 |
|
|
comparePackageForUpgrade(updDict, h, pkg) |
120 |
|
|
|
121 |
|
|
# handle obsoletes |
122 |
|
|
for pkg in hdlist: |
123 |
|
|
if (pkg[rpm.RPMTAG_NAME],pkg[rpm.RPMTAG_ARCH]) in updDict.keys(): |
124 |
|
|
# dEBUG("%(name)s %(arch)s is already selected" % pkg) |
125 |
|
|
continue |
126 |
|
|
|
127 |
|
|
if pkg[rpm.RPMTAG_OBSOLETENAME] is not None: |
128 |
|
|
name = pkg[rpm.RPMTAG_NAME] |
129 |
|
|
arch = pkg[rpm.RPMTAG_ARCH] |
130 |
|
|
for obs,obsver in zip(pkg[rpm.RPMTAG_OBSOLETENAME],pkg[rpm.RPMTAG_OBSOLETEVERSION]): |
131 |
|
|
mi = ts.dbMatch('name', obs) |
132 |
|
|
oevr = strToVersion(obsver) |
133 |
|
|
for h in mi: |
134 |
|
|
if not obsver: |
135 |
|
|
# unversioned obsoletes win |
136 |
|
|
addNewPackageToUpgSet(updDict, pkg) |
137 |
|
|
# dEBUG("adding %(name)s to the upgrade set for obsoletes" % pkg) |
138 |
|
|
break |
139 |
|
|
else: |
140 |
|
|
if h[rpm.RPMTAG_EPOCH] is None: |
141 |
|
|
epoch = '0' |
142 |
|
|
else: |
143 |
|
|
epoch = str(h[rpm.RPMTAG_EPOCH]) |
144 |
|
|
val = compareEVR(oevr,(epoch,h[rpm.RPMTAG_VERSION],h[rpm.RPMTAG_RELEASE])) |
145 |
|
|
if val > 0: |
146 |
|
|
# dEBUG("adding %(name)s %(version)s to the upgrade set for obsoletes" % pkg) |
147 |
|
|
updDict[(name,arch)] = pkg |
148 |
|
|
break |
149 |
|
|
|
150 |
|
|
return updDict.values() |
151 |
|
|
|
152 |
|
|
def rpmOutToStr(arg): |
153 |
|
|
if type(arg) != types.StringType: |
154 |
|
|
# and arg is not None: |
155 |
|
|
arg = str(arg) |
156 |
|
|
|
157 |
|
|
return arg |
158 |
|
|
|
159 |
|
|
def compareEVR((e1, v1, r1), (e2, v2, r2)): |
160 |
|
|
# return 1: a is newer than b |
161 |
|
|
# 0: a and b are the same version |
162 |
|
|
# -1: b is newer than a |
163 |
|
|
e1 = rpmOutToStr(e1) |
164 |
|
|
v1 = rpmOutToStr(v1) |
165 |
|
|
r1 = rpmOutToStr(r1) |
166 |
|
|
e2 = rpmOutToStr(e2) |
167 |
|
|
v2 = rpmOutToStr(v2) |
168 |
|
|
r2 = rpmOutToStr(r2) |
169 |
|
|
rc = rpm.labelCompare((e1, v1, r1), (e2, v2, r2)) |
170 |
|
|
return rc |
171 |
|
|
|
172 |
|
|
def strToVersion(str): |
173 |
|
|
"""Parse a string such as in obsoleteversion into evr. |
174 |
|
|
Gratuitously borrowed from yum str_to_version |
175 |
|
|
FIXME: should be implemented in and use rpmUtils""" |
176 |
|
|
i = string.find(str, ':') |
177 |
|
|
if i != -1: |
178 |
|
|
epoch = string.atol(str[:i]) |
179 |
|
|
else: |
180 |
|
|
epoch = '0' |
181 |
|
|
j = string.find(str, '-') |
182 |
|
|
if j != -1: |
183 |
|
|
if str[i + 1:j] == '': |
184 |
|
|
version = None |
185 |
|
|
else: version = str[i + 1:j] |
186 |
|
|
release = str[j + 1:] |
187 |
|
|
else: |
188 |
|
|
if str[i + 1:] == '': |
189 |
|
|
version = None |
190 |
|
|
else: |
191 |
|
|
version = str[i + 1:] |
192 |
|
|
release = None |
193 |
|
|
return (epoch, version, release) |
194 |
|
|
|
195 |
|
|
|
196 |
|
|
if __name__ == "__main__": |
197 |
|
|
import sys, os |
198 |
|
|
|
199 |
|
|
if len(sys.argv) < 2: |
200 |
|
|
print "Usage: %s /path/to/tree [rootpath]" %(sys.argv[0],) |
201 |
|
|
sys.exit(0) |
202 |
|
|
|
203 |
|
|
tree = sys.argv[1] |
204 |
|
|
if len(sys.argv) >= 3: |
205 |
|
|
instPath = sys.argv[2] |
206 |
|
|
else: |
207 |
|
|
instPath = "/" |
208 |
|
|
|
209 |
|
|
fd = os.open("%s/%s/base/hdlist" %(tree, productPath), os.O_RDONLY) |
210 |
|
|
hdlist = rpm.readHeaderListFromFD(fd) |
211 |
|
|
os.close(fd) |
212 |
|
|
|
213 |
|
|
|
214 |
|
|
packages = findpackageset(hdlist, instPath) |
215 |
|
|
for pkg in packages: |
216 |
|
|
print pkg[rpm.RPMTAG_NAME] |
217 |
|
|
|