summaryrefslogtreecommitdiffstats
path: root/BuildManager/package.py
diff options
context:
space:
mode:
Diffstat (limited to 'BuildManager/package.py')
-rw-r--r--BuildManager/package.py243
1 files changed, 243 insertions, 0 deletions
diff --git a/BuildManager/package.py b/BuildManager/package.py
new file mode 100644
index 0000000..ce73333
--- /dev/null
+++ b/BuildManager/package.py
@@ -0,0 +1,243 @@
+from BuildManager import *
+from BuildManager.rpmver import rpmVersionCompare
+from UserList import UserList
+import commands
+import string
+import os
+import re
+
+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