Hi folks.
I've "hacked" together a small patch the last few days to basically
convert yum-builddep to always use specfiles for build dep resolution.
It does so by extracting the specfile from srpms to a temporary file and
uses that then to generate the build dependencies.
The advantage here is obviously that this way yum-builddep would become
arch agnostic and the year old problem of srpms actually being binary
rpms would be solved.
Currently this is still an early "work in progress" patch and definitely
needs quite a bit more cleanup, but if the approach looks sounds let me
know and i'll finish up the patch.
Thanks & regards, Phil
--
Philipp Knirsch | Tel.: +49-711-96437-470
Manager Core Services | Fax.: +49-711-96437-111
Red Hat GmbH | Email: Phil Knirsch <[email protected]>
Wankelstrasse 5 | Web: http://www.redhat.com/
D-70563 Stuttgart, Germany
--- yum-builddep.bak 2013-04-26 14:59:43.823086250 +0200
+++ yum-builddep 2013-05-03 17:18:04.991484165 +0200
@@ -26,8 +26,76 @@
import rpmUtils
import rpm
+import os
+import rpmUtils.miscutils
+import tempfile
+
rhn_source_repos = True
+class CPIOFile:
+ """ Read ASCII CPIO files. """
+ def __init__(self, fd):
+ self.fd = fd # filedescriptor
+ self.lastfilesize = 0 # Length of "current" file data
+ self.readsize = 0 # Number of bytes read from "current" file data
+
+ def getNextEntry(self):
+ """Read next header and contents, return (file name, file data length),
+ or (None, None) at EOF.
+
+ Metadata is discarded. Raise IOError."""
+
+ self.readsize = 0
+ # Do padding if necessary for nexty entry
+ self.fd.read((4 - (self.lastfilesize % 4)) % 4)
+ # The cpio header contains 8 byte hex numbers with the following
+ # content: magic, inode, mode, uid, gid, nlink, mtime, filesize,
+ # devMajor, devMinor, rdevMajor, rdevMinor, namesize, checksum.
+ data = self.fd.read(110)
+ # CPIO ASCII hex, expanded device numbers (070702 with CRC)
+ if data[0:6] not in ["070701", "070702"]:
+ raise IOError, "Bad magic reading CPIO headers %s" % data[0:6]
+ # Read filename and padding.
+ filenamesize = int(data[94:102], 16)
+ filename = self.fd.read(filenamesize).rstrip("\x00")
+ self.fd.read((4 - ((110 + filenamesize) % 4)) % 4)
+ if filename == "TRAILER!!!": # end of archive detection
+ return (None, None)
+ # Adjust filename, so that it matches the way the rpm header has
+ # filenames stored. This code used to be:
+ # 'filename = "/" + os.path.normpath("./" + filename)'
+ if filename[:2] == "./":
+ filename = filename[1:]
+ if filename[:1] != "/":
+ filename = "%s%s" % ("/", filename)
+ if filename[-1:] == "/" and len(filename) > 1:
+ filename = filename[:-1]
+ # Read file contents.
+ self.lastfilesize = int(data[54:62], 16)
+ return (filename, self.lastfilesize)
+
+ def read(self, size):
+ """Return up to size bytes of file data.
+
+ Raise IOError."""
+
+ if size > self.lastfilesize - self.readsize:
+ size = self.lastfilesize - self.readsize
+ self.readsize += size
+ return self.fd.read(size)
+
+ def skipToNextFile(self):
+ """Skip current file data.
+
+ Raise IOError."""
+ size = self.lastfilesize - self.readsize
+ data = "1"
+ while size > 0 and data:
+ data = self.read(min(size, 65536))
+ size -= len(data)
+ if size > 0:
+ raise IOError, "Unexpected EOF from CPIO archive"
+
# Copied from yumdownloader (need a yum-utils python module ;)
# This is to fix Bug 469
# To convert from a pkg to a source pkg, we have a problem in that all we have
@@ -165,6 +233,29 @@
self.logger.error("Error: %s" % e)
sys.exit(1)
+ def get_specfile_from_srpm(self, srpm):
+ input = os.open(srpm, os.O_RDONLY)
+ output1 = tempfile.NamedTemporaryFile()
+ output2 = tempfile.NamedTemporaryFile()
+ rpmUtils.miscutils.rpm2cpio(fdno = input, out = output1)
+ output1.seek(0)
+ cpio = CPIOFile(output1)
+
+ (fname, flen) = cpio.getNextEntry()
+ while fname != None and flen != None:
+ if not fname.endswith(".spec"):
+ while flen > 65536:
+ cpio.read(65536)
+ flen = flen - 65536
+ cpio.read(flen)
+ else:
+ output2.write(cpio.read(flen))
+ output2.seek(0)
+ return output2
+ (fname, flen) = cpio.getNextEntry()
+ return None
+
+
# go through each of the pkgs, figure out what they are/where they are
# if they are not a local package then run
# Setup source repos
@@ -194,7 +285,7 @@
elif arg.endswith('.src'):
srcnames.append(arg)
elif specworks and arg.endswith('.spec'):
- specnames.append(arg)
+ specnames.append((arg, arg))
else:
srcnames.append(arg)
@@ -220,25 +311,31 @@
toActOn = self.bestPackagesFromList(toActOn, 'src')
for srpm in toActOn:
- self.logger.info('Getting requirements for %s' % srpm)
- self.install_deps(srpm.requiresList())
+ try:
+ specfile = self.get_specfile_from_srpm(srpm.localpath)
+ except Exception, e:
+ self.logger.error("Error: Could not open %s .\n" % srpm)
+ self.logger.error(e)
+ sys.exit(1)
+ if specfile == None:
+ self.logger.error("Can't extract specfile from srpm: %s\n" % srpm)
+ sys.exit(1)
+ specnames.append((srpm.localpath, specfile.name))
- for name in specnames:
+ for (name, fname) in specnames:
try:
- spec = rpm.spec(name)
+ spec = rpm.spec(fname)
except ValueError:
- self.logger.error("Bad spec: %s" % name)
+ self.logger.error("Bad spec: %s" % os.path.basename(name))
continue
buildreqs = []
for d in rpm.ds(spec.sourceHeader, 'requires'):
buildreqs.append(d.DNEVR()[2:])
- self.logger.info('Getting requirements for %s' % name)
+ self.logger.info('Getting requirements for %s' % os.path.basename(name))
self.install_deps(buildreqs)
if __name__ == '__main__':
setup_locale()
util = YumBuildDep()
-
-
_______________________________________________
Yum-devel mailing list
[email protected]
http://lists.baseurl.org/mailman/listinfo/yum-devel