source: soft/build_system/build_system/bm/tags/2.1/BuildManager/package.py @ 1

Last change on this file since 1 was 1, checked in by fasma, 12 years ago

Initial Import from Mandriva's soft revision 224062 and package revision 45733

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