changeset 344:f06f707d9fda

merged branches/scratchbox into trunk #### IMPORTANT FOR ALL TREEPKGS ##### pbuilderrc config variable name changed to builderconfig
author Bjoern Ricks <bricks@intevation.de>
date Fri, 23 Apr 2010 07:43:29 +0000
parents c0808837fc64
children 27eccce96949
files bin/initbuilder.py bin/initpbuilder.py bin/treepkgbuilder.py demo.cfg recipes/kde/maemo/__init__.py recipes/kde/maemo/generic.py test/test_builder.py test/test_listpackages.py test/test_notifications.py test/test_packager.py test/test_readconfig.py treepkg/builder.py treepkg/packager.py treepkg/readconfig.py treepkg/sbuilder.py treepkg/util.py
diffstat 15 files changed, 478 insertions(+), 128 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/initbuilder.py	Fri Apr 23 07:43:29 2010 +0000
@@ -0,0 +1,55 @@
+#! /usr/bin/python
+# Copyright (C) 2007, 2008, 2009 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.
+
+"""Script to initialize the builder environment for the tree packager
+
+The script assumes that the config file for the tree packager already
+contains the builder settings.  Also, this script assumes that there is
+only one builder setting for all packagers.
+"""
+
+import sys
+
+import treepkgcmd
+from treepkg.options import create_parser
+from treepkg.packager import create_package_track, PackagerGroup
+from treepkg.readconfig import read_config
+
+
+def parse_commandline():
+    parser = create_parser()
+    parser.set_defaults(distribution="etch")
+    parser.add_option("--mirrorsite",
+                      help=("The debian mirror site"
+                            " (pbuilder MIRRORSITE setting).  Required."))
+    parser.add_option("--othermirror",
+                      help=("Extra contents of the OTHERMIRROR setting."
+                            " See the pbuilder documentation for the format."))
+    parser.add_option("--distribution",
+                      help=("The debian distribution for the pbuilder chroot."
+                            " Default is etch."))
+    return parser.parse_args()
+
+
+def main():
+    options, args = parse_commandline()
+
+    if options.mirrorsite is None:
+        print >>sys.stderr, "Missing required option --mirrorsite"
+        sys.exit(1)
+
+    treepkg_opts, packager_opts = read_config(options.config_file)
+    group = PackagerGroup([create_package_track(**opts)
+                           for opts in packager_opts],
+                          **treepkg_opts)
+    track = group.get_package_tracks()[0]
+    track.builder.init_builder(distribution=options.distribution,
+                                mirrorsite=options.mirrorsite,
+                                extramirrors=options.othermirror)
+
+main()
--- a/bin/initpbuilder.py	Thu Apr 22 19:25:02 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-#! /usr/bin/python
-# Copyright (C) 2007, 2008, 2009 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.
-
-"""Script to initialize the pbuilder environment for the tree packager
-
-The script assumes that the config file for the tree packager already
-contains the pbuilder settings.  Also, this script assumes that there is
-only one pbuilder setting for all packagers.
-"""
-
-import sys
-
-import treepkgcmd
-from treepkg.options import create_parser
-from treepkg.packager import create_package_track, PackagerGroup
-from treepkg.readconfig import read_config
-
-
-def parse_commandline():
-    parser = create_parser()
-    parser.set_defaults(distribution="etch")
-    parser.add_option("--mirrorsite",
-                      help=("The debian mirror site"
-                            " (pbuilder MIRRORSITE setting).  Required."))
-    parser.add_option("--othermirror",
-                      help=("Extra contents of the OTHERMIRROR setting."
-                            " See the pbuilder documentation for the format."))
-    parser.add_option("--distribution",
-                      help=("The debian distribution for the pbuilder chroot."
-                            " Default is etch."))
-    return parser.parse_args()
-
-
-def main():
-    options, args = parse_commandline()
-
-    if options.mirrorsite is None:
-        print >>sys.stderr, "Missing required option --mirrorsite"
-        sys.exit(1)
-
-    treepkg_opts, packager_opts = read_config(options.config_file)
-    group = PackagerGroup([create_package_track(**opts)
-                           for opts in packager_opts],
-                          **treepkg_opts)
-    track = group.get_package_tracks()[0]
-    track.builder.init_pbuilder(distribution=options.distribution,
-                                mirrorsite=options.mirrorsite,
-                                extramirrors=options.othermirror)
-
-main()
--- a/bin/treepkgbuilder.py	Thu Apr 22 19:25:02 2010 +0000
+++ b/bin/treepkgbuilder.py	Fri Apr 23 07:43:29 2010 +0000
@@ -76,7 +76,7 @@
 
     def run(self):
         builder = self.get_builder()
-        builder.init_pbuilder(distribution=self.opts.distribution,
+        builder.init_builder(distribution=self.opts.distribution,
                               mirrorsite=self.opts.mirrorsite,
                               extramirrors=self.opts.othermirror)
 
--- a/demo.cfg	Thu Apr 22 19:25:02 2010 +0000
+++ b/demo.cfg	Fri Apr 23 07:43:29 2010 +0000
@@ -26,12 +26,12 @@
 # specific values
 root_cmd: sudo
 
-# The pbuilder config file to use.  It should be an absolute filename.
+# The builder config file to use.  It should be an absolute filename.
 # The script initpbuilder.py can create it and the rest of the pbuilder
 # files and directories.  You can override this in the pkg_ sections for
-# individual packagers if necessary.  You will have to adapt pbuilder
+# individual packagers if necessary.  You will have to adapt e.g. pbuilder
 # yourself, then, though.
-pbuilderrc: %(treepkg_dir)s/pbuilder/pbuilderrc
+builderconfig: %(treepkg_dir)s/pbuilder/pbuilderrc
 
 
 # Email address and name to use as the packager in the debian packages.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/recipes/kde/maemo/generic.py	Fri Apr 23 07:43:29 2010 +0000
@@ -0,0 +1,131 @@
+# Copyright (C) 2007, 2008, 2009, 2010 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh@intevation.de>
+# Bjoern Ricks <bjoern.ricks@intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Base classes for all kde maemo packagers"""
+
+import re
+import time
+import logging
+
+import treepkg.packager
+import treepkg.subversion as subversion
+import treepkg.sbuilder
+
+
+class SourcePackager(treepkg.packager.SourcePackager):
+
+    def __init__(self, *args, **kw):
+        super(SourcePackager, self).__init__(*args, **kw)
+        self.enterprise_version = (self.parent.pkg_date + "."
+                                   + str(self.revision))
+        self.maemo_version =  "%s.%s" % (self.revision,
+                              self.parent.pkg_date)
+
+    def determine_package_version(self, directory):
+        enterprise_version = self.enterprise_version
+        maemo_version = self.maemo_version
+        revision = self.revision
+        rules_revision = self.parent.rules_revision
+        pkg_revision = self.parent.pkg_revision
+        pkg_date = self.parent.pkg_date
+    
+        return self.track.version_template % locals()
+
+    def prepare_sources_for_tarball(self, pkgbasedir, pkgbaseversion):
+        self.update_version_numbers(pkgbasedir)
+
+    def update_version_numbers(self, pkgbasedir):
+        """Updates the version numbers in the code in pkgbasedir.
+        The default implementation does nothing.  Derived classes should
+        override this method if necessary.
+        """
+
+    def get_change_msg(self):
+        return self.changemsg_template % dict(revision=self.revision,
+                                     pkg_date=self.parent.pkg_date,
+                                     rules_revision=self.parent.rules_revision)
+
+
+class RevisionPackager(treepkg.packager.RevisionPackager):
+
+    source_packager_cls = SourcePackager
+
+    def __init__(self, *args, **kw):
+        self.pkg_date = kw.pop("pkg_date",
+                               time.strftime("%Y%m%d", time.localtime()))
+        super(RevisionPackager, self).__init__(*args, **kw)
+
+
+class PackageTrack(treepkg.packager.PackageTrack):
+
+    revision_packager_cls = RevisionPackager
+    builder_cls = treepkg.sbuilder.SbdmockBuilder
+
+    extra_config_desc = [("tags_url", str, ""),
+                         ("tags_pattern", str, ""),
+                         ("tags_subdir", str, "")]
+
+    def __init__(self, *args, **kw):
+        tags_url = kw.pop("tags_url")
+        tags_pattern = kw.pop("tags_pattern")
+        tags_subdir = kw.pop("tags_subdir")
+        super(PackageTrack, self).__init__(*args, **kw)
+        self.tag_detector = subversion.TagDetector(tags_url, tags_pattern,
+                                                   tags_subdir)
+
+    def packager_for_new_revision(self):
+        logging.info("Checking tags")
+        self.tag_url = None
+        tag_url, tag_revision = self.tag_detector.newest_tag_revision()
+        logging.info("Found: %s: %s", tag_url, tag_revision)
+        if tag_url is not None:
+            revision = (tag_revision,
+                        self.rules_working_copy.last_changed_revision())
+            logging.info("New revision is %s", revision)
+            if revision not in self.get_revision_numbers():
+                logging.info("Revision %s has not been packaged yet",
+                             revision)
+                self.tag_url = tag_url
+                self.tag_revision = tag_revision
+                tag_date, tag_change_count = self.tag_pkg_parameters(tag_url)
+                pkg_revision = (self.pkg_revision_template
+                                % dict(pkg_revision=tag_change_count))
+                return self.revision_packager_cls(self, tag=tag_url,
+                                                  pkg_revision=pkg_revision,
+                                                  pkg_date=tag_date,
+                                                  *revision)
+            else:
+                logging.info("Revision %s has already been packaged.",
+                             revision)
+
+        return super(PackageTrack, self).packager_for_new_revision()
+
+    def export_sources(self, to_dir):
+        if self.tag_url is not None:
+            logging.info("Exporting sources for tarball from %r to %r",
+                         self.tag_url, to_dir)
+            self.working_copy.export_tag(self.tag_url, to_dir,
+                                         revision=self.tag_revision)
+        else:
+            super(PackageTrack, self).export_sources(to_dir)
+
+    def tag_pkg_parameters(self, tag_url):
+        match = re.search(r"/enterprise[^.]*\.[^.]*\."
+                          r"(?P<date>[0-9]{8})\.(?P<baserev>[0-9]+)/",
+                          tag_url)
+        if match:
+            date = match.group("date")
+            baserev = match.group("baserev")
+            xml_log = subversion.log_xml(tag_url, baserev)
+            revisions = subversion.extract_tag_revisions(xml_log)
+            tag_change_count = len(revisions)
+            return (date, tag_change_count)
+        else:
+            raise RuntimeError("Cannot determine tag parameters from %r"
+                               % tag_url)
+
--- a/test/test_builder.py	Thu Apr 22 19:25:02 2010 +0000
+++ b/test/test_builder.py	Fri Apr 23 07:43:29 2010 +0000
@@ -44,14 +44,14 @@
 class TestPBuilder(PBuilderTests):
 
     def test_init_pbuilder(self):
-        """Tests the PBuilder.init_pbuilder method."""
+        """Tests the PBuilder.init_builder method."""
         basedir = self.create_temp_dir("pbuilder")
         pbuilderrc = os.path.join(basedir, "pbuilderrc")
         builder = PBuilder(pbuilderrc, self.root_command)
         old_stdout = sys.stdout
         sys.stdout = captured_stdout = StringIO.StringIO()
         try:
-            builder.init_pbuilder(distribution="etch",
+            builder.init_builder(distribution="etch",
                                   mirrorsite="http://example.com/debian",
                                   extramirrors=None)
         finally:
@@ -62,7 +62,7 @@
                                            "aptcache", "extra-pkg"]
                    if not os.path.isdir(os.path.join(basedir, dirname))]
         if missing:
-            self.fail("init_pbuilder did not create these directories: %s"
+            self.fail("init_builder did not create these directories: %s"
                       % " ".join(missing))
 
         # check the pbuilderrc.  This test is a little too strict
@@ -104,7 +104,7 @@
                           % dict(basedir_repr=repr(basedir)[1:-1]))
 
     def test_init_pbuilder_run_twice(self):
-        """Tests whether PBuilder.init_pbuilder prints an error when run twice.
+        """Tests whether PBuilder.init_builder prints an error when run twice.
         """
         basedir = self.create_temp_dir("pbuilder")
 
@@ -114,7 +114,7 @@
         old_stdout = sys.stdout
         sys.stdout = captured_stdout = StringIO.StringIO()
         try:
-            builder.init_pbuilder(distribution="etch",
+            builder.init_builder(distribution="etch",
                                   mirrorsite="http://example.com/debian",
                                   extramirrors=None)
         finally:
@@ -127,7 +127,7 @@
         sys.stderr = captured_stderr = StringIO.StringIO()
         try:
             try:
-                builder.init_pbuilder(distribution="etch",
+                builder.init_builder(distribution="etch",
                                       mirrorsite="http://example.com/debian",
                                       extramirrors=None)
             except SystemExit, exc:
--- a/test/test_listpackages.py	Thu Apr 22 19:25:02 2010 +0000
+++ b/test/test_listpackages.py	Fri Apr 23 07:43:29 2010 +0000
@@ -64,7 +64,7 @@
 [DEFAULT]
 tracks_dir: %(tracksdir)s
 root_cmd: true
-pbuilderrc:
+builderconfig:
 deb_email: packager@example.com
 deb_fullname: Sample Packager
 pkg_revision_template: treepkg%%%%(pkg_revision)s
--- a/test/test_notifications.py	Thu Apr 22 19:25:02 2010 +0000
+++ b/test/test_notifications.py	Fri Apr 23 07:43:29 2010 +0000
@@ -21,7 +21,7 @@
 [DEFAULT]
 tracks_dir: %(tracksdir)s
 root_cmd: true
-pbuilderrc:
+builderconfig:
 deb_email: packager@example.com
 deb_fullname: Sample Packager
 pkg_revision_template: treepkg%%%%(pkg_revision)d
--- a/test/test_packager.py	Thu Apr 22 19:25:02 2010 +0000
+++ b/test/test_packager.py	Fri Apr 23 07:43:29 2010 +0000
@@ -111,7 +111,7 @@
         rootcmd = os.path.join(os.path.dirname(__file__), os.pardir, "test",
                                "mocksudopbuilder.py")
         track = PackageTrack(name="testpkg", base_dir=self.trackdir,
-                             svn_url=self.svn_url, pbuilderrc="",
+                             svn_url=self.svn_url, builderconfig="",
                              root_cmd=[sys.executable, rootcmd],
                              deb_email="treepkg@example.com",
                              deb_fullname="treepkg tester",
@@ -388,7 +388,7 @@
         defaults = dict(base_dir="/home/builder/tracks/" + name,
                         svn_url="svn://example.com",
                         root_cmd=["false"],
-                        pbuilderrc="/home/builder/pbuilderrc",
+                        builderconfig="/home/builder/pbuilderrc",
                         deb_email="treepkg@example.com", deb_fullname="treepkg",
                         handle_dependencies=handle_dependencies)
         super(PackageTrackWithDependencies,
--- a/test/test_readconfig.py	Thu Apr 22 19:25:02 2010 +0000
+++ b/test/test_readconfig.py	Fri Apr 23 07:43:29 2010 +0000
@@ -25,7 +25,7 @@
 tracks_dir: %(treepkg_dir)s/tracks
 root_cmd: sudo
 pbuilder_dir: %(treepkg_dir)s/pbuilder
-pbuilderrc: %(pbuilder_dir)s/pbuilderrc
+builderconfig: %(pbuilder_dir)s/pbuilderrc
 deb_email: treepkg@example.com
 deb_fullname: TreePKG
 pkg_revision_template: treepkg%%(pkg_revision)s
@@ -95,7 +95,7 @@
                  pkg_revision_template="treepkg%(pkg_revision)s",
                  handle_dependencies=False,
                  packager_class="readconfig_test.extraargs",
-                 pbuilderrc="/home/builder/mill/pbuilder/pbuilderrc",
+                 builderconfig="/home/builder/mill/pbuilder/pbuilderrc",
                  # pkg_basename is passed as an empty string by default.
                  # The PackageTrack an empty pkg_basename it with the
                  # value of name
@@ -122,7 +122,7 @@
                  pkg_revision_template="treepkg%(pkg_revision)s",
                  handle_dependencies=True,
                  packager_class="readconfig_test.simple",
-                 pbuilderrc="/home/builder/mill/pbuilder/pbuilderrc",
+                 builderconfig="/home/builder/mill/pbuilder/pbuilderrc",
                  pkg_basename="simple1",
                  root_cmd=['sudo'],
                  signing_key_id="abcd1234",
--- a/treepkg/builder.py	Thu Apr 22 19:25:02 2010 +0000
+++ b/treepkg/builder.py	Fri Apr 23 07:43:29 2010 +0000
@@ -17,8 +17,62 @@
 import run
 from cmdexpand import cmdexpand
 
+class Builder:
+    
+    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")
+    
+    """ Parent class for all Builders """
+    def __init__(self):
+        pass
 
-class PBuilder(object):
+    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 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)
+
+class PBuilder(Builder):
 
     """Represents a way to run and manage a specific pbuilder instance"""
 
@@ -41,12 +95,6 @@
 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, pbuilderrc, 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
@@ -60,7 +108,7 @@
         self.release_signing_keyid = release_signing_keyid
         self.base_dir = os.path.dirname(self.pbuilderrc)
 
-    def init_pbuilder(self, distribution, mirrorsite, extramirrors):
+    def init_builder(self, distribution, mirrorsite, extramirrors):
         """Initializes the pbuilder instance"""
         if not os.path.isabs(self.pbuilderrc):
             print >>sys.stderr, "pbuilderrc must be an absolute filename"
@@ -104,27 +152,6 @@
         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:
@@ -195,6 +222,8 @@
             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
         # by pbuilder
         if binary_dir is not None:
@@ -202,27 +231,6 @@
                 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
--- a/treepkg/packager.py	Thu Apr 22 19:25:02 2010 +0000
+++ b/treepkg/packager.py	Fri Apr 23 07:43:29 2010 +0000
@@ -171,7 +171,11 @@
 
     def sign_package(self):
         """Signs the .dsc file created buy the instance"""
-        self.track.sign_file(util.listdir_abs(self.src_dir, "*.dsc")[0])
+        src_files = util.listdir_abs(self.src_dir, "*.dsc")
+        if not src_files:
+            raise RuntimeError("Could not find .dsc file in source"
+                  " directory %s" % self.src_dir)
+        self.track.sign_file(src_files[0])
 
     def package(self):
         """Creates a source package from a subversion checkout.
@@ -203,13 +207,15 @@
         self.create_tarball(origtargz, self.work_dir,
                             os.path.basename(pkgbasedir))
 
-        changemsg = self.changemsg_template % dict(revision=self.revision)
+        changemsg = self.get_change_msg()
         self.copy_debian_directory(pkgbasedir, pkgbaseversion,
                                    changemsg)
 
         self.create_source_package(pkgbasedir, origtargz)
         self.move_source_package(pkgbasename)
 
+    def get_change_msg(self):
+        return self.changemsg_template % dict(revision=self.revision)
 
 class BinaryPackager(object):
 
@@ -235,7 +241,10 @@
 
     def sign_package(self):
         """Signs the .changes file created buy the instance"""
-        self.track.sign_file(util.listdir_abs(self.binary_dir, "*.changes")[0])
+        dirs = util.listdir_abs(self.binary_dir, "*.changes")
+        if not dirs:
+            raise RuntimeError("Cannot find changes File in %r" % self.binary_dir)
+        self.track.sign_file(dirs[0])
 
 
 class RevisionPackager(object):
@@ -342,11 +351,13 @@
 
     revision_packager_cls = RevisionPackager
 
+    builder_cls = PBuilder
+
     svn_external_subdirs = []
 
     extra_config_desc = []
 
-    def __init__(self, name, base_dir, root_cmd, pbuilderrc, deb_email,
+    def __init__(self, name, base_dir, root_cmd, builderconfig, deb_email,
                  deb_fullname, svn_url="", packager_class="treepkg.packager",
                  version_template="%(revision)s",
                  pkg_revision_template="treepkg%(pkg_revision)s",
@@ -360,7 +371,7 @@
         self.pkg_basename = pkg_basename
         self.changelog_msg_template = changelog_msg_template
         self.base_dir = base_dir
-        self.builder = PBuilder(pbuilderrc, root_cmd,
+        self.builder = self.builder_cls(builderconfig, root_cmd,
                                 release_signing_keyid=signing_key_id)
         self.deb_email = deb_email
         self.deb_fullname = deb_fullname
--- a/treepkg/readconfig.py	Thu Apr 22 19:25:02 2010 +0000
+++ b/treepkg/readconfig.py	Fri Apr 23 07:43:29 2010 +0000
@@ -69,7 +69,7 @@
     ("svn_subset", convert_subversion_subset, ""),
     ("svn_externals", shlex.split, ""),
     ("rules_svn_url", str, ""), "packager_class",
-    ("root_cmd", shlex.split, "sudo"), "pbuilderrc",
+    ("root_cmd", shlex.split, "sudo"), "builderconfig",
     "deb_email", "deb_fullname", ("deb_build_options", str, ""),
     ("version_template", str, "%(revision)s"),
     "pkg_revision_template", ("pkg_basename", str, ""),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/treepkg/sbuilder.py	Fri Apr 23 07:43:29 2010 +0000
@@ -0,0 +1,195 @@
+# Copyright (C) 2010 by Intevation GmbH
+# Authors:
+# Bjoern Ricks <bjoern.ricks@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
+import builder
+from cmdexpand import cmdexpand
+
+
+class SbdmockBuilder(builder.Builder):
+
+    """Represents a way to run and manage a specific sbdmock instance
+    to build binary for Maemo within scratchbox environment"""
+
+    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 Builder instance with the configuration file.
+        The root_cmd parameter should be a list with a command that can
+        be used to get root permissions.  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.
+        """
+        if not os.path.exists(builderconfig):
+            raise RuntimeError("Config file %s for sbdmock does not exist.",
+                  builderconfig)
+
+        if not os.path.isabs(builderconfig):
+            raise RuntimeError("Config file %s must be an absolute filename.",
+                  builderconfig)
+
+        self.builderconfig = builderconfig
+        self.root_cmd = root_cmd
+        self.release_signing_keyid = release_signing_keyid
+        self.base_dir = os.path.dirname(self.builderconfig)
+        self.mounted_dirs = []
+
+    def init_builder(self, distribution, mirrorsite, extramirrors):
+        """Initializes the builder instance"""
+
+        basedir = os.path.dirname(self.builderconfig)
+        replacements = dict(basedir=basedir,
+                            distribution=distribution,
+                            mirrorsite=mirrorsite)
+
+        # create the builder directories.  basedir is created implicitly by
+        # creating its subdirectories.
+        for attr in ["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
+
+        # 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()
+
+    def update(self, suppress_output=True, log_info=True):
+        """Runs nothing"""
+        if log_info:
+            logging.info("Update of apt cache is done on every start. skipping ...")
+
+    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 builder chroot
+                         environment
+           extra_packages -- Extra packages to install
+           extra_env -- mapping with extra environment variables to set
+                        when runing the builder process.  If builder
+                        is started via sudo, make sure that sudo does
+                        not remove these variables when it starts
+                        builder
+        """
+        args = []
+        if logfile is not None:
+	    logdir = os.path.dirname(logfile)
+            args.extend(["--buildlog=%s" % logfile])
+            args.extend(["--logdir=%s" % logdir])
+        if binary_dir is not None:
+            args.extend(["--resultdir=%s" % binary_dir])
+            util.ensure_directory(binary_dir)
+        if bindmounts:
+            self.mount(bindmounts)
+#        for pkg in extra_packages:
+#            args.extend(["--extrapackages", pkg])
+        
+	logging.info("Mointing extra-pkg apt repository")
+                
+        self.mount([self.extra_pkg_dir])
+
+        logging.info("Starting build process with sbdmock ...")
+
+
+        cmd = cmdexpand("/usr/bin/sbdmock --cleanbuilddir"
+                           " --config=$builderconfig"
+#                           " --dbo=" # aren't build options setable in treepkg.cfg?
+                           " -u -b $dsc @args",
+                           builderconfig=self.builderconfig,
+                           dsc=dsc_file, args=args)
+        logging.debug("sbdmock cmd: %s" % cmd)
+        
+        try:
+            run.call(cmd, suppress_output=True, extra_env=extra_env)
+
+            # remove the source package files put into the binary directory
+            # by pbuilder (BR: not sure if this is necessary for sbdmock)
+            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))
+        finally:
+            # compress logfile
+            if logfile is not None and os.path.exists(logfile):
+                run.call(cmdexpand("gzip -9 $logfile", logfile=logfile))
+            # remove all mounted directories
+            self.umount_all()
+
+    def run_script(self, script, logfile, bindmounts=(), save_after_exec=False):
+        """Execute a script in builder'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 builder 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 builder instance.
+        """
+        logging.error("It isn't possible to run scripts withon sbdmock.")
+
+    def login(self, bindmounts=(), save_after_login=False):
+        """Start an interactive shell in the builder 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)
+
+    def mount(self, bindmounts):
+        for mount in bindmounts:
+            mount_dir = "/scratchbox/users/%s/%s" % (util.getuser(), mount)
+            util.ensure_directory(mount_dir)
+            logging.info("Mounting %s to %s" % (mount, mount_dir))
+            run.call(cmdexpand("@rootcmd mount --bind $mount $mountdir", rootcmd=self.root_cmd, mount=mount, mountdir=mount_dir))
+
+            #add mountpoint to a variable to for unmounting later
+            self.mounted_dirs.append(mount_dir)
+
+    def umount(self, mounts):
+        for mount in mounts:
+            logging.info("Unmounting %s" % mount)
+            run.call(cmdexpand("@rootcmd umount $dir", rootcmd=self.root_cmd, dir=mount))
+            self.mounted_dirs.remove(mount)
+
+    def umount_all(self):
+        mounts = self.mounted_dirs[:]
+        self.umount(mounts)
--- a/treepkg/util.py	Thu Apr 22 19:25:02 2010 +0000
+++ b/treepkg/util.py	Fri Apr 23 07:43:29 2010 +0000
@@ -12,6 +12,7 @@
 import tempfile
 import shutil
 import fnmatch
+import pwd
 
 import run
 
@@ -151,3 +152,7 @@
     def get(self):
         return os.path.join(getattr(self, dir_attr), filename)
     return property(get)
+
+def getuser():
+    """Returns the login name of the current user owning the proccess"""
+    return pwd.getpwuid(os.getuid())[0]
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)