bh@84: #! /usr/bin/env python bh@171: # Copyright (C) 2007, 2008 by Intevation GmbH bh@84: # Authors: bh@84: # Bernhard Herzog bh@84: # bh@84: # This program is free software under the GPL (>=v2) bh@84: # Read the file COPYING coming with the software for details. bh@84: bh@84: """ bh@84: Mock sudo that mimics some aspects of sudo pbuilder invocations for test cases bh@84: """ bh@84: bh@84: import sys bh@84: import os bh@84: import shutil bh@84: import tempfile bh@84: import re bh@84: bh@84: from optparse import OptionParser bh@84: bh@84: sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir)) bh@84: bh@84: from treepkg.util import extract_value_for_key, writefile bh@84: from treepkg.run import call bh@84: from treepkg.cmdexpand import cmdexpand bh@84: bh@84: bh@84: def parse_command_line(args): bh@84: if len(args) < 2: bh@84: raise RuntimeError("mocksudopbuilder must be called with at least" bh@84: " two parameters") bh@84: if args[0] != "/usr/sbin/pbuilder": bh@84: raise RuntimeError("mocksudopbuilder must be called with" bh@84: " /usr/sbin/pbuilder as first argument") bh@84: bh@84: cmd = args[1] bh@84: if cmd != "build": bh@84: raise RuntimeError("mocksudopbuilder only supports the pbuilder build" bh@84: " command") bh@84: bh@84: args = args[2:] bh@84: bh@84: parser = OptionParser() bh@84: parser.add_option("--configfile") bh@84: parser.add_option("--logfile") bh@84: parser.add_option("--buildresult") bh@171: parser.add_option("--debbuildopts") bh@84: bh@84: opts, rest = parser.parse_args(args) bh@84: return opts, rest bh@84: bh@84: bh@84: class DSC(object): bh@84: bh@84: def __init__(self, filename): bh@84: self.filename = os.path.abspath(filename) bh@84: self.parse_dsc_file() bh@84: bh@84: def parse_dsc_file(self): bh@84: lines = open(self.filename).readlines() bh@84: bh@84: self.source_package = extract_value_for_key(lines, "Source:") bh@84: bh@84: raw_binaries = extract_value_for_key(lines, "Binary:") bh@84: self.binaries = [name.strip() for name in raw_binaries.split(",")] bh@84: bh@84: version = extract_value_for_key(lines, "Version:") bh@84: match = re.match(r"\d+:", version) bh@84: if match: bh@84: version = version[match.end(0):] bh@84: self.version = version bh@84: match = re.search("-([^-]+)$", version) bh@84: if match: bh@84: self.base_version = version[:match.start(0)] bh@84: self.revision = match.group(1) bh@84: else: bh@84: self.base_version = version bh@84: self.revision = "" bh@84: bh@84: self.files = [] bh@84: for i in range(len(lines) - 1, -1, -1): bh@84: line = lines[i] bh@84: if line[0] != " ": bh@84: break bh@84: self.files.append(line.split()[-1]) bh@84: bh@84: def unpack_source_pkg(dsc): bh@84: tempdir = tempfile.mkdtemp() bh@84: call(cmdexpand("dpkg-source -x $filename", filename=dsc.filename), bh@84: cwd=tempdir, stdout=sys.stdout) bh@84: return os.path.join(tempdir, dsc.source_package + "-" + dsc.base_version) bh@84: bh@84: def parse_debian_control(filename): bh@84: packages = [] bh@84: lines = [line.strip() for line in open(filename).readlines()] bh@84: while lines: bh@84: try: bh@84: empty_line = lines.index("") bh@84: except ValueError: bh@84: empty_line = len(lines) bh@84: paragraph = lines[:empty_line] bh@84: lines = lines[empty_line + 1:] bh@84: bh@84: package_name = extract_value_for_key(paragraph, "Package:") bh@84: arch = extract_value_for_key(paragraph, "Architecture:") bh@84: if package_name is not None: bh@84: packages.append((package_name, arch)) bh@84: return packages bh@84: bh@84: def create_binary_results(buildresult, dsc, packages): bh@84: for name, arch in packages: bh@84: if arch == "any": bh@84: arch = "i386" bh@84: writefile(os.path.join(buildresult, bh@84: "%s_%s_%s.deb" % (name, dsc.version, arch)), bh@84: "") bh@84: bh@84: basename = os.path.splitext(os.path.basename(dsc.filename))[0] bh@84: writefile(os.path.join(buildresult, basename + "_i386.changes"), "") bh@84: bh@84: def create_source_results(buildresult, dsc): bh@84: dscdir = os.path.dirname(dsc.filename) bh@84: shutil.copy(dsc.filename, buildresult) bh@84: for name in dsc.files: bh@84: shutil.copy(os.path.join(dscdir, name), buildresult) bh@84: bh@84: def mock_pbuilder_build(opts, dscfilename): bh@84: dsc = DSC(dscfilename) bh@84: print "unpacking source package" bh@84: unpacked_dir = unpack_source_pkg(dsc) bh@84: try: bh@84: packages = parse_debian_control(os.path.join(unpacked_dir, "debian", bh@84: "control")) bh@84: create_binary_results(opts.buildresult, dsc, packages) bh@84: create_source_results(opts.buildresult, dsc) bh@84: finally: bh@84: print "removing tempdir", repr(os.path.dirname(unpacked_dir)) bh@84: shutil.rmtree(os.path.dirname(unpacked_dir)) bh@84: bh@84: def main(): bh@84: opts, rest = parse_command_line(sys.argv[1:]) bh@84: for optname in ["buildresult"]: bh@84: if getattr(opts, optname) is None: bh@84: raise RuntimeError("Missing required option %r" % optname) bh@84: if len(rest) != 1: bh@84: raise RuntimeError("Missing required argument for .dsc file") bh@84: if opts.logfile: bh@84: sys.stdout = open(opts.logfile, "w", 1) bh@84: mock_pbuilder_build(opts, rest[0]) bh@84: bh@84: main()