[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