[Secure-testing-commits] r16575 - lib/python
Florian Weimer
fw at alioth.debian.org
Sun Apr 24 14:06:23 UTC 2011
Author: fw
Date: 2011-04-24 14:06:14 +0000 (Sun, 24 Apr 2011)
New Revision: 16575
Modified:
lib/python/debian_support.py
Log:
debian_support.inspect_deb(): attempt add a .deb parser
Also adds debian_support.BinaryPackage class.
Modified: lib/python/debian_support.py
===================================================================
--- lib/python/debian_support.py 2011-04-23 17:52:11 UTC (rev 16574)
+++ lib/python/debian_support.py 2011-04-24 14:06:14 UTC (rev 16575)
@@ -20,6 +20,9 @@
import types
import os
import re
+import subprocess
+import tempfile
+from cStringIO import StringIO
try:
from hashlib import sha1
@@ -415,6 +418,117 @@
l.sort()
return l
+class BinaryPackage(object):
+ __slots__ = ("name", "version", "arch", "source", "source_version")
+ re_source = re.compile\
+ (r'^([a-zA-Z0-9.+-]+)(?:\s+\(([a-zA-Z0-9.+:~-]+)\))?$')
+
+ def __init__(self, data=None):
+ if data is not None:
+ self.loadtuple(data)
+
+ def loadentry(self, lines):
+ """Loads an entry from the Packages file.
+
+ LINES is a sequence of string pairs (KEY, VALUE).
+ """
+ pkg_name = None
+ pkg_version = None
+ pkg_arch = None
+ pkg_source = None
+ pkg_source_version = None
+ for (name, contents) in lines:
+ name = name.lower()
+ if name == "package":
+ pkg_name = contents
+ elif name == "version":
+ pkg_version = contents
+ elif name == "source":
+ match = self.re_source.match(contents)
+ if match is None:
+ raise SyntaxError(('package %s references '
+ + 'invalid source package %s') %
+ (pkg_name, `contents`))
+ (pkg_source, pkg_source_version) = match.groups()
+ elif name == "architecture":
+ pkg_arch = contents
+ if pkg_name is None:
+ raise SyntaxError\
+ ("package record does not contain package name")
+ if pkg_version is None:
+ raise SyntaxError\
+ ("package record for %s does not contain version"
+ % pkg_name)
+ if pkg_arch is None:
+ raise SyntaxError\
+ ("package record for %s lacks Architecture: field"
+ % pkg_name)
+ if pkg_source is None:
+ pkg_source = pkg_name
+ if pkg_source_version is None:
+ pkg_source_version = pkg_version
+ self.loadtuple((pkg_name, pkg_version, pkg_arch,
+ pkg_source, pkg_source_version))
+
+ def loadtuple(self, data):
+ self.name, self.version, self.arch, self.source, self.source_version =\
+ data
+
+ def astuple(self):
+ return (self.name, self.version, self.arch,
+ self.source, self.source_version)
+
+ def __repr__(self):
+ return "BinaryPackage(" + repr(self.astuple()) + ")"
+
+def inspect_deb(path):
+ "Extracts meta-data from a Debian package file (.deb)."
+ devnull = file("/dev/null", "r")
+ tempout = tempfile.TemporaryFile()
+ temperr = tempfile.TemporaryFile()
+ dpkg = subprocess.Popen(("dpkg", "-I", "--", path),
+ stdin=devnull,
+ stdout=tempout,
+ stderr=temperr)
+ dpkg.wait()
+ temperr.seek(0)
+ temperr = temperr.read()
+ if temperr:
+ raise IOError("unexpected dpkg output for " + repr(path) + ": "
+ + repr(temperr))
+ if dpkg.returncode <> 0:
+ raise IOError("unexpected dpkg status for " + repr(path) + ": "
+ + repr(dpkg.returncode))
+ tempout.seek(0)
+ lines = list(tempout.readlines())
+ if not lines:
+ raise IOError("empty dpkg output for " + repr(path))
+ if lines[0] <> " new debian package, version 2.0.\n":
+ raise IOError("unexpected dpkg format for " +repr(path) + ":"
+ + repr(lines[0]))
+ while lines and not lines[0].startswith(" Package: "):
+ del lines[0]
+ if not lines:
+ raise IOError("no Package: line in dpkg output for " +repr(path))
+ stripped = StringIO()
+ for line in lines:
+ if line.startswith(" "):
+ stripped.write(line[1:])
+ else:
+ break
+ stripped.seek(0)
+ pkgfile = PackageFile(path, stripped)
+ result = None
+ for pkg in pkgfile:
+ if result is None:
+ result = BinaryPackage()
+ result.loadentry(pkg)
+ else:
+ raise IOError("multiple package entries for " + repr(path))
+ if result is None:
+ raise IOError("no package entries for " + repr(path))
+ return result
+
def test():
# Version
assert Version('0') < Version('a')
More information about the Secure-testing-commits
mailing list