[Treepkg-commits] r272 - branches/scratchbox/treepkg
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Thu Apr 15 12:07:20 CEST 2010
Author: bricks
Date: 2010-04-15 12:07:18 +0200 (Thu, 15 Apr 2010)
New Revision: 272
Added:
branches/scratchbox/treepkg/sbuilder.py
Modified:
branches/scratchbox/treepkg/builder.py
Log:
added sbdmock builder stub
merged trunk changes
Modified: branches/scratchbox/treepkg/builder.py
===================================================================
--- branches/scratchbox/treepkg/builder.py 2010-04-14 14:54:14 UTC (rev 271)
+++ branches/scratchbox/treepkg/builder.py 2010-04-15 10:07:18 UTC (rev 272)
@@ -179,13 +179,22 @@
args.extend(["--bindmounts", mount])
for pkg in extra_packages:
args.extend(["--extrapackages", pkg])
- run.call(cmdexpand("@rootcmd /usr/sbin/pbuilder build"
- " --configfile $pbuilderrc @args"
- " --debbuildopts -b $dsc",
- rootcmd=self.root_cmd, pbuilderrc=self.pbuilderrc,
- dsc=dsc_file, args=args),
- suppress_output=True,
- extra_env=extra_env)
+ try:
+ run.call(cmdexpand("@rootcmd /usr/sbin/pbuilder build"
+ " --configfile $pbuilderrc @args"
+ " --debbuildopts -b $dsc",
+ rootcmd=self.root_cmd, pbuilderrc=self.pbuilderrc,
+ dsc=dsc_file, args=args),
+ suppress_output=True,
+ extra_env=extra_env)
+ except:
+ if logfile is not None and os.path.exists(logfile):
+ run.call(cmdexpand("gzip -9 $logfile", logfile=logfile))
+ raise
+ else:
+ if logfile is not None and os.path.exists(logfile):
+ run.call(cmdexpand("gzip -9 $logfile", logfile=logfile))
+
if logfile is not None and os.path.exists(logfile):
run.call(cmdexpand("gzip -9 $logfile", logfile=logfile))
# remove the source package files put into the binary directory
Added: branches/scratchbox/treepkg/sbuilder.py
===================================================================
--- branches/scratchbox/treepkg/sbuilder.py 2010-04-14 14:54:14 UTC (rev 271)
+++ branches/scratchbox/treepkg/sbuilder.py 2010-04-15 10:07:18 UTC (rev 272)
@@ -0,0 +1,265 @@
+# Copyright (C) 2020 by Intevation GmbH
+# Authors:
+# Bjoern Ricks <bjoern.ricks at 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 tempfile
+
+import util
+import run
+from cmdexpand import cmdexpand
+
+
+class SbdmockBuilder(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=%(basetgz_dir)s/base.tgz
+BUILDPLACE=%(build_dir)s
+USEPROC=yes
+USEDEVPTS=yes
+BUILDRESULT=%(result_dir)s
+DISTRIBUTION=%(distribution)s
+APTCACHE=%(aptcache_dir)s
+APTCACHEHARDLINK=yes
+REMOVEPACKAGES=lilo
+MIRRORSITE="%(mirrorsite)s"
+OTHERMIRROR="%(othermirror)s"
+BINDMOUNTS="%(extra_pkg_dir)s"
+PKGNAME_LOGFILE=yes
+'''
+
+ basetgz_dir = util.filenameproperty("base")
+ build_dir = util.filenameproperty("build")
+ result_dir = util.filenameproperty("result")
+ aptcache_dir = util.filenameproperty("aptcache")
+ extra_pkg_dir = util.filenameproperty("extra-pkg")
+
+ def __init__(self, builderconfig, root_cmd, release_signing_keyid=None):
+ """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.builderconfig = builderconfig
+ self.root_cmd = root_cmd
+ self.release_signing_keyid = release_signing_keyid
+ self.base_dir = os.path.dirname(self.builderconfig)
+
+ 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 attr in ["basetgz_dir", "build_dir", "result_dir", "aptcache_dir",
+ "extra_pkg_dir"]:
+ directory = getattr(self, attr)
+ replacements[attr] = directory
+ print "creating directory:", repr(directory)
+ util.ensure_directory(directory)
+
+ # build OTHERMIRROR value. We always include the extra-pkg dir.
+ othermirror = "deb file://%(extra_pkg_dir)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"
+ self.update_extra_pkg_dir()
+
+ # 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 update_extra_pkg_dir(self):
+ run.call(cmdexpand("apt-ftparchive packages ."),
+ stdout=open(os.path.join(self.extra_pkg_dir, "Packages"), "w"),
+ cwd=self.extra_pkg_dir)
+ release_filename = os.path.join(self.extra_pkg_dir, "Release")
+ run.call(cmdexpand("apt-ftparchive release ."),
+ stdout=open(release_filename, "w"), cwd=self.extra_pkg_dir)
+ # handle signatures. remove any existing signature because it
+ # will be invalid now.
+ signature = release_filename + ".gpg"
+ try:
+ os.remove(signature)
+ except OSError:
+ pass
+ if self.release_signing_keyid:
+ run.call(cmdexpand("gpg --detach-sign --armor --local-user=$keyid"
+ " -o $sig $release",
+ keyid=self.release_signing_keyid,
+ sig=release_filename + ".gpg",
+ release=release_filename)),
+
+ def update(self, suppress_output=True, log_info=True):
+ """Runs pbuilder update on this pbuilder instance"""
+ if log_info:
+ 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=suppress_output)
+
+ def add_apt_key(self, keyid):
+ """Runs apt-key add in the chroot"""
+ # Creates a temporary file in extra_pkg_dir (because that's
+ # bind-mounted by default) with a script that adds the desired
+ # key. The exported key is included in the script file so that
+ # only one file has to be created
+ script = tempfile.NamedTemporaryFile(dir=self.extra_pkg_dir)
+ try:
+ script.write("#! /bin/sh\n")
+ script.write("apt-key add $0\n")
+ script.write("exit\n\n")
+ script.flush()
+ run.call(cmdexpand("gpg --export --armor $keyid", **locals()),
+ stdout=script.fileno())
+ self.run_script([script.name], logfile=None, save_after_exec=True)
+ finally:
+ script.close()
+
+ def build(self, dsc_file, binary_dir=None, logfile=None, 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
+ """
+ args = []
+ if logfile is not None:
+ args.extend(["--logfile", logfile])
+ if binary_dir is not None:
+ args.extend(["--buildresult", binary_dir])
+ util.ensure_directory(binary_dir)
+ 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"
+ " --debbuildopts -b $dsc",
+ rootcmd=self.root_cmd, pbuilderrc=self.pbuilderrc,
+ dsc=dsc_file, args=args),
+ suppress_output=True,
+ extra_env=extra_env)
+ if logfile is not None and os.path.exists(logfile):
+ run.call(cmdexpand("gzip -9 $logfile", logfile=logfile))
+ # remove the source package files put into the binary directory
+ # by pbuilder
+ if binary_dir is not None:
+ 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, subdirectory="auto"):
+ """Adds binary packages to the extra-pkg directory.
+ The filenames parameter should be sequence of absolute
+ filenames. The files named will be copied to a subdirectory of
+ the extra-pkg directory which is assumed to reside in the same
+ directory as the pbuilderrc. The subdirectory is specified with
+ the subdirectory parameter and defaults to 'auto'. 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.
+ """
+ target_dir = os.path.join(self.extra_pkg_dir, subdirectory)
+ util.ensure_directory(target_dir)
+ for filename in filenames:
+ logging.info("Copying %s into %s", filename, target_dir)
+ shutil.copy(filename, target_dir)
+
+ logging.info("Running apt-ftparchive in %s", self.extra_pkg_dir)
+ self.update_extra_pkg_dir()
+
+ self.update(suppress_output=True, log_info=True)
+
+ def run_script(self, script, logfile, bindmounts=(), save_after_exec=False):
+ """Execute a script in pbuilder's chroot environment
+ Parameters:
+ script -- A list of strings with the command line to invoke 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)
+ save_after_exec -- Boolean indicating whether the chroot
+ environment should be copied back so that
+ modifications are available in subsequent
+ uses of the pbuilder instance.
+ """
+ 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])
+ if save_after_exec:
+ args.append("--save-after-exec")
+
+ 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)
+
+ def login(self, bindmounts=(), save_after_login=False):
+ """Start an interactive shell in the pbuilder environment"""
+ args = []
+ for mount in bindmounts:
+ args.extend(["--bindmounts", mount])
+ if save_after_login:
+ args.extend(["--save-after-login"])
+ run.call(cmdexpand("@rootcmd /usr/sbin/pbuilder login"
+ " --configfile $pbuilderrc @args",
+ rootcmd=self.root_cmd, pbuilderrc=self.pbuilderrc,
+ args=args),
+ suppress_output=False)
More information about the Treepkg-commits
mailing list