1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
|
from BuildManager import *
from BuildManager.rpmver import rpmVersionCompare
from UserList import UserList
import commands
import string
import os
import re
class BuildManagerFileError(Error): pass
class BuildManagerPackageError(Error): pass
try:
import rpm
except ImportError:
rpm = None
__all__ = ["Package", "PackageList"]
def subst(s, vars):
def _subst(match, vars=vars):
name = match.group(1)
return str(vars[name])
try:
return re.sub(r'\$([a-zA-Z]+)', _subst, s)
except KeyError, var:
raise Error, "variable $%s not declared" % var
class Package:
def __init__(self, file, log=None):
self._package = None
ext = self._filename_extension(file)
if not ext:
raise Error, "unknown file extension of "+file
if not globals().has_key("_package_"+ext):
raise Error, "unknown package extension of "+file
self._package = globals()["_package_"+ext](file, log)
def __getattr__(self, name):
return getattr(self._package, name)
def _filename_extension(self, filename):
try:
dotpos = filename.rindex(".")
except ValueError:
pass
else:
return filename[dotpos+1:]
class _package:
def __init__(self, file, log):
self.file = file
self.absfile = os.path.abspath(file)
self.type = None
self.name = None
self.version = None
self.release = None
self.epoch = None
self.spec = None
self.builddir = None
self.log = log or "$builddir/SPECS/log.$name"
self._init()
def __cmp__(self, pkg):
rc = cmp(self.name, pkg.name)
if rc: return rc
return rpmVersionCompare(self.epoch, self.version, self.release,
pkg.epoch, pkg.version, pkg.release)
def _expand_log(self):
substdict = {"builddir":self.builddir,
"name":self.name,
"version":self.version,
"release":self.release}
self.log = subst(self.log, substdict)
class _package_spec(_package):
def _rpm_vars(self, str, vars):
end = -1
ret = []
while 1:
start = string.find(str, "%{", end+1)
if start == -1:
ret.append(str[end+1:])
break
ret.append(str[end+1:start])
end = string.find(str, "}", start)
if end == -1:
ret.append(str[start:])
break
varname = str[start+2:end]
if vars.has_key(varname):
ret.append(vars[varname])
else:
ret.append(str[start:end+1])
return string.join(ret,"")
def _init(self):
self.spec = self.absfile
self.builddir = os.path.dirname(os.path.dirname(self.absfile))
ret = os.system("mkdir -p %s/{SOURCES,SPECS,BUILD,SRPMS,RPMS,BUILDROOT}" % self.builddir)
try:
f = open(self.spec,"r")
except IOError, e:
raise BuildManagerFileError, \
"couldn't open spec file %s" % self.absfile
defines = {}
for line in f.readlines():
lowerline = string.lower(line)
if not self.name and lowerline[:5] == "name:":
self.name = self._rpm_vars(string.strip(line[5:]), defines)
elif not self.version and lowerline[:8] == "version:":
self.version = self._rpm_vars(string.strip(line[8:]), defines)
elif not self.release and lowerline[:8] == "release:":
self.release = self._rpm_vars(string.strip(line[8:]), defines)
elif lowerline[:7] == "%define":
token = string.split(line[7:])
if len(token) == 2:
defines[token[0]] = self._rpm_vars(token[1], defines)
if self.name and self.version and self.release:
break
else:
raise Error, "spec file %s doesn't define name, " \
"version or release" % self.file
self.type = "spec"
self._expand_log()
class _package_rpm(_package):
def _init(self):
if not rpm:
cmd = "rpm -qp --queryformat='%%{NAME} %%{EPOCH} %%{VERSION} %%{RELEASE} %%{SOURCERPM}' %s"%self.file
status, output = commands.getstatusoutput(cmd)
if status != 0:
raise BuildManagerPackageError, \
"error querying rpm file %s" % self.file
else:
tokens = string.split(output, " ")
if len(tokens) != 5:
raise Error, \
"unexpected output querying rpm file %s: %s" % \
(self.file, output)
else:
self.name, self.epoch, self.version, self.release, srpm = tokens
if self.epoch == "(none)":
self.epoch = None
if srpm != "(none)":
self.type = "rpm"
else:
self.type = "srpm"
else:
# Boost up query if rpm module is available
file = open(self.file)
if hasattr(rpm, "headerFromPackage"):
h = rpm.headerFromPackage(file.fileno())[0]
else:
ts = rpm.TransactionSet()
h = ts.hdrFromFdno(file.fileno())
file.close()
self.name = h[rpm.RPMTAG_NAME]
self.epoch = h[rpm.RPMTAG_EPOCH]
self.version = h[rpm.RPMTAG_VERSION]
self.release = h[rpm.RPMTAG_RELEASE]
if h[rpm.RPMTAG_SOURCERPM]:
self.type = "rpm"
else:
self.type = "srpm"
def unpack(self, unpackdir):
if self.type == "srpm":
self.builddir = self._builddir_create(unpackdir)
if self.builddir:
self._expand_log()
return self._install_srpm()
def _builddir_create(self, unpackdir):
unpackdir = os.path.abspath(unpackdir)
builddir = "%s/%s-%s-%s-topdir" % (unpackdir, self.name, self.version, self.release)
ret = os.system("mkdir -p %s/{SOURCES,SPECS,BUILD,SRPMS,RPMS,BUILDROOT}" % builddir)
if ret != 0:
raise BuildManagerPackageError, \
"error creating builddir at %s" % builddir
else:
return builddir
def _install_srpm(self):
cmd = "rpm -i --define '_topdir %s' %s &> %s"%(self.builddir,self.file,self.log)
status, output = commands.getstatusoutput(cmd)
if status != 0:
raise Error, "error installing package "+self.file
else:
spec = self.builddir+"/SPECS/"+self.name+".spec"
if not os.path.isfile(spec):
listdir = os.listdir(self.builddir+"/SPECS")
for file in listdir[:]:
if file[-5:] != ".spec":
listdir.remove(file)
if len(listdir) != 1:
raise Error, "can't guess spec file for "+self.file
else:
self.spec = self.builddir+"/SPECS/"+listdir[0]
return 1
else:
self.spec = spec
return 1
class PackageList(UserList):
def has_lt(self, pkg):
for mypkg in self.data:
if mypkg.name == pkg.name \
and mypkg.type == pkg.type \
and mypkg < pkg:
return 1
return 0
def has_le(self, pkg):
for mypkg in self.data:
if mypkg.name == pkg.name \
and mypkg.type == pkg.type \
and mypkg <= pkg:
return 1
return 0
def has_eq(self, pkg):
for mypkg in self.data:
if mypkg.name == pkg.name \
and mypkg.type == pkg.type \
and mypkg == pkg:
return 1
return 0
def has_ge(self, pkg):
for mypkg in self.data:
if mypkg.name == pkg.name \
and mypkg.type == pkg.type \
and mypkg >= pkg:
return 1
return 0
def has_gt(self, pkg):
for mypkg in self.data:
if mypkg.name == pkg.name \
and mypkg.type == pkg.type \
and mypkg > pkg:
return 1
return 0
# vim:ts=4:sw=4:et
|