Mercurial > treepkg > treepkg
view treepkg/builder.py @ 171:c0ea6cbb0fd2
Add "--debbuildopts -b" to "pbuilder build" command line to stop
pbuilder from creating a source package. The .changes would otherwise
contain references to that new source package instead of the one we
passed to pbuilder. The checksums for the two source packages would be
different so the .changes file would not match the source package that
treepkg produces.
author | Bernhard Herzog <bh@intevation.de> |
---|---|
date | Mon, 23 Jun 2008 16:12:01 +0000 |
parents | bfcb2bbf9a52 |
children | 97435e92411a |
line wrap: on
line source
# Copyright (C) 2007, 2008 by Intevation GmbH # Authors: # Bernhard Herzog <bh@intevation.de> # # This program is free software under the GPL (>=v2) # Read the file COPYING coming with the software for details. """Build binary packages from source packages""" import sys import os import shutil import logging import util import run from cmdexpand import cmdexpand class PBuilder(object): """Represents a way to run and manage a specific pbuilder instance""" pbuilderrc_template = '''\ # This file was automatically generated by initpbuilder.py. # for the possible settings see "man pbuilderrc" BASETGZ=%(basedir)s/base.tgz BUILDPLACE=%(builddir)s USEPROC=yes USEDEVPTS=yes BUILDRESULT=%(resultdir)s DISTRIBUTION=%(distribution)s APTCACHE=%(basedir)s/aptcache APTCACHEHARDLINK=yes REMOVEPACKAGES=lilo MIRRORSITE="%(mirrorsite)s" OTHERMIRROR="%(othermirror)s" BINDMOUNTS="%(extra-pkgdir)s" PKGNAME_LOGFILE=yes ''' def __init__(self, pbuilderrc, root_cmd): """Initialize the PBuilder instance with the configuration file. The root_cmd parameter should be a list with a command that can be used to get root permissions to run pbuilder. It may be an empty list if no command is needed. It's a list so that commands with several shell-words can be used without having to worry about quoting. """ self.pbuilderrc = pbuilderrc self.root_cmd = root_cmd def init_pbuilder(self, distribution, mirrorsite, extramirrors): """Initializes the pbuilder instance""" if not os.path.isabs(self.pbuilderrc): print >>sys.stderr, "pbuilderrc must be an absolute filename" sys.exit(1) if os.path.exists(self.pbuilderrc): print >>sys.stderr, ("pbuilderrc %r already exists." % self.pbuilderrc) sys.exit(1) basedir = os.path.dirname(self.pbuilderrc) replacements = dict(basedir=basedir, distribution=distribution, mirrorsite=mirrorsite) # create the pbuilder directories. basedir is created implicitly by # creating its subdirectories. for subdir in ["base", "build", "result", "aptcache", "extra-pkg"]: directory = os.path.join(basedir, subdir) replacements[subdir + "dir"] = directory print "creating directory:", repr(directory) util.ensure_directory(directory) # build OTHERMIRROR value. We always include the extra-pkg dir. othermirror = "deb file://%(extra-pkgdir)s ./" % replacements if extramirrors: othermirror += " | " + extramirrors replacements["othermirror"] = othermirror # create the pbuilderrcfile print "creating pbuilderrc:", repr(self.pbuilderrc) util.writefile(self.pbuilderrc, self.pbuilderrc_template % replacements) # turn the extra-pkg directory into a proper deb archive print "turning the extra-pkg dir into a debian archive" extra_pkgdir = replacements["extra-pkgdir"] run.call(cmdexpand("apt-ftparchive packages ."), stdout=open(os.path.join(extra_pkgdir, "Packages"), "w"), cwd=extra_pkgdir) # create the base.tgz chroot print "running pbuilder create" run.call(cmdexpand("@root_cmd pbuilder create --configfile $pbuilderrc", root_cmd=self.root_cmd, pbuilderrc=self.pbuilderrc)) def build(self, dsc_file, binary_dir, logfile, bindmounts=(), extra_packages=(), extra_env=None): """Build a binary packager from a source package Parameters: dsc_file -- name of the debian .dsc file of the source package binary_dir -- name of the directory to receive the binary packages logfile -- name of the logfile of the build bindmounts -- Sequence of directory names that should be bind-mounted in the pbuilder chroot environment extra_packages -- Extra packages to install extra_env -- mapping with extra environment variables to set when runing the pbuilder process. If pbuilder is started via sudo, make sure that sudo does not remove these variables when it starts pbuilder """ util.ensure_directory(binary_dir) args = [] for mount in bindmounts: args.extend(["--bindmounts", mount]) for pkg in extra_packages: args.extend(["--extrapackages", pkg]) run.call(cmdexpand("@rootcmd /usr/sbin/pbuilder build" " --configfile $pbuilderrc @args" " --logfile $logfile --buildresult $bindir" " --debbuildopts -b $dsc", rootcmd=self.root_cmd, pbuilderrc=self.pbuilderrc, logfile=logfile, bindir=binary_dir, dsc=dsc_file, args=args), suppress_output=True, extra_env=extra_env) # remove the source package files put into the binary directory # by pbuilder for filename in os.listdir(binary_dir): if os.path.splitext(filename)[1] not in (".deb", ".changes"): os.remove(os.path.join(binary_dir, filename)) def add_binaries_to_extra_pkg(self, filenames): """Adds binary packages to the extra-pkg directory. The filenames parameter should be sequence of absolute filenames. The files named will be copied to the extra-pkg directory which is assumed to reside in the same directory as the pbuilderrc. Afterwards, the method generates a Packages file in the directory and runs pbuilder update. All of this assumes that pbuilder was set up the way bin/initpbuilder.py does. """ extrapkg_dir = os.path.join(os.path.dirname(self.pbuilderrc), "extra-pkg") for filename in filenames: logging.info("Copying %s into %s", filename, extrapkg_dir) shutil.copy(filename, extrapkg_dir) logging.info("Running apt-ftparchive in %s", extrapkg_dir) run.call(cmdexpand("apt-ftparchive packages ."), stdout=open(os.path.join(extrapkg_dir, "Packages"), "w"), cwd=extrapkg_dir) logging.info("Running pbuilder update for %s", self.pbuilderrc) run.call(cmdexpand("@rootcmd /usr/sbin/pbuilder update" " --configfile $pbuilderrc", rootcmd=self.root_cmd, pbuilderrc=self.pbuilderrc), suppress_output=True) def run_script(self, script, logfile, bindmounts=()): """Execute a script in pbuilder's chroot environment Parameters: script -- The filename of the script logfile -- name of the logfile of the build bindmounts -- Sequence of directory names that should be bind-mounted in the pbuilder chroot environment (optional) """ logging.info("Running pbuilder execute on %s", script) args = [] if logfile: args.extend(["--logfile", logfile]) # create the logfile. This makes sure that it is owned by # the user the tree packager is running as and not root, as # would be the case when it is created indirectly by # pbuilder open(logfile, "w").close() for mount in bindmounts: args.extend(["--bindmounts", mount]) run.call(cmdexpand("@rootcmd /usr/sbin/pbuilder execute" " --configfile $pbuilderrc @args $script", rootcmd=self.root_cmd, pbuilderrc=self.pbuilderrc, args=args, script=script), suppress_output=False)