diff treepkg/packager.py @ 4:fee641fec94e

Separate the kolab specific parts.
author Bernhard Herzog <bh@intevation.de>
date Fri, 09 Mar 2007 12:26:01 +0100
parents e6a9f4037f68
children 96f4f58c62b5
line wrap: on
line diff
--- a/treepkg/packager.py	Thu Mar 08 20:23:28 2007 +0100
+++ b/treepkg/packager.py	Fri Mar 09 12:26:01 2007 +0100
@@ -27,56 +27,87 @@
 
 class SourcePackager(object):
 
+    # Derived classes must supply the package basename
+    pkg_basename = None
+
     def __init__(self, plant, status, work_dir, src_dir, revision):
         self.plant = plant
         self.status = status
         self.work_dir = work_dir
         self.src_dir = src_dir
         self.revision = revision
-        self.enterprise_version = (time.strftime("%Y%m%d", time.localtime()) \
-                                   + "." + str(self.revision))
-
-    def kdepim_version(self, directory):
-        """Determine the kdepim version.
-
-        The version is taken from the kdepim.lsm file in the plants
-        checkout dir.
-        """
-        return util.extract_lsm_version(os.path.join(directory, "kdepim.lsm"))
+        assert(self.pkg_basename)
 
     def determine_package_version(self, directory):
-        enterprise_version = self.enterprise_version
-        kdepimversion = self.kdepim_version(directory)
-        version_template = "%(kdepimversion)s.enterprise.0.%(enterprise_version)s"
-        return version_template % locals()
+        """Returns the version number of the new package as a string
+
+        The directory parameter is the name of the directory containing
+        the newly exported sources.  The sources were exported with the
+        export_sources method.
+
+        The default implementation simply returns the revision converted
+        to a string.
+        """
+        return str(self.revision)
 
     def export_sources(self):
+        """Export the sources from the subversion working directory
+
+        This method first exports the sources to a temporary directory
+        and then renames the directory.  The new name is of the form
+
+          <pkg_basename>-<version>
+
+        Where pkg_basename is the value of self.pkg_basename and version
+        is the return value of the determine_package_version() method.
+        """
         temp_dir = os.path.join(self.work_dir, "temp")
         self.plant.export_sources(temp_dir)
 
         pkgbaseversion = self.determine_package_version(temp_dir)
-        pkgbasedir = os.path.join(self.work_dir, "kdepim-" + pkgbaseversion)
+        pkgbasedir = os.path.join(self.work_dir,
+                                  self.pkg_basename + "-" + pkgbaseversion)
 
         os.rename(temp_dir, pkgbasedir)
         return pkgbaseversion, pkgbasedir
 
 
     def update_version_numbers(self, pkgbasedir):
-        versionstring = "(enterprise %s)" % self.enterprise_version
-        for versionfile in ["kmail/kmversion.h", "kontact/src/main.cpp",
-                            "korganizer/version.h"]:
-            filename = os.path.join(pkgbasedir, versionfile)
-            patched = re.sub("\(enterprise ([^)]*)\)", versionstring,
-                              open(filename).read())
-            f = open(filename, "w")
-            f.write(patched)
-            f.close()
+        """Updates the version numbers in the code in pkgbasedir.
+
+        The default implementation does nothing.  Derived classes should
+        override this method if necessary.
+        """
 
     def create_tarball(self, tarballname, workdir, basedir):
+        """Creates a new tarball.
+
+        Parameters:
+
+          tarballname -- the filename of the new tarball
+          workdir -- The directory into which to change before running tar.
+                     (actually this is done with GNUI tar's -C option)
+          basedir -- The basedirectory of the files that are packaged
+                     into the tarfile.  This should be a relative
+                     filename directly in workdir.
+        """
         logging.info("Creating tarball %r", tarballname)
         run.call(["tar", "czf", tarballname, "-C", workdir, basedir])
 
     def copy_debian_directory(self, pkgbasedir, pkgbaseversion, changemsg):
+        """Copies the debian directory and updates the copy's changelog
+
+        Parameter:
+          pkgbasedir -- The directory holding the unpacked source package
+          pkgbaseversion -- The version to update the changelog to
+          changemsg -- The message for the changelog
+
+        When determining the actual version for the new package, this
+        function looks at the previous version in the changelog.  If it
+        has a prefix separated from the version number by a colon this
+        prefix is prepended to the pkgbaseversion parameter.  Debian
+        uses such prefixes for the kde packages.
+        """
         debian_dir = os.path.join(pkgbasedir, "debian")
         changelog = os.path.join(debian_dir, "changelog")
 
@@ -95,6 +126,7 @@
 
 
     def create_source_package(self, pkgbasedir, origtargz):
+        """Creates a new source package from pkgbasedir and origtargz"""
         logging.info("Creating new source package")
         run.call(["dpkg-source", "-b", os.path.basename(pkgbasedir),
                   os.path.basename(origtargz)],
@@ -102,37 +134,41 @@
                  suppress_output=True,
                  env=self.plant.debian_environment())
 
+    def move_source_package(self, pkgbasename):
+        """Moves the new source package from the work_dir to the src_dir"""
+        logging.info("Moving source package to %r", self.src_dir)
+        util.ensure_directory(self.src_dir)
+        for filename in [filename for filename in os.listdir(self.work_dir)
+                                  if filename.startswith(pkgbasename)]:
+            os.rename(os.path.join(self.work_dir, filename),
+                      os.path.join(self.src_dir, filename))
+
     def package(self):
+        """Creates a source package from a subversion checkout.
+
+        After setting up the working directory, this method calls the
+        do_package method to do the actual packaging.  Afterwards the
+        work directory is removed.
+        """
         util.ensure_directory(self.work_dir)
         try:
             self.status.set("creating_source_package")
-            pkgbaseversion, pkgbasedir = self.export_sources()
-            self.update_version_numbers(pkgbasedir)
-
-            pkgbasename = "kdepim_" + pkgbaseversion
-            origtargz = os.path.join(self.work_dir,
-                                     pkgbasename + ".orig.tar.gz")
-            self.create_tarball(origtargz, self.work_dir,
-                                os.path.basename(pkgbasedir))
-
-            changemsg = ("Update to SVN enterprise branch rev. %d"
-                         % (self.revision,))
-            self.copy_debian_directory(pkgbasedir, pkgbaseversion,
-                                       changemsg)
-
-            self.create_source_package(pkgbasedir, origtargz)
-
-            logging.info("Moving source package to %r", self.src_dir)
-            util.ensure_directory(self.src_dir)
-            for filename in [filename for filename in os.listdir(self.work_dir)
-                                      if filename.startswith(pkgbasename)]:
-                os.rename(os.path.join(self.work_dir, filename),
-                          os.path.join(self.src_dir, filename))
+            self.do_package()
             self.status.set("source_package_created")
         finally:
             logging.info("Removing workdir %r", self.work_dir)
             shutil.rmtree(self.work_dir)
 
+    def do_package(self):
+        """Does the work of creating a source package
+        This method must be overriden by derived classes.
+
+        The method should do the work in self.work_dir.  When the
+        package is done, the source package files should be in
+        self.src_dir.
+        """
+        raise NotImplementedError
+
 
 class BinaryPackager(object):
 
@@ -155,6 +191,9 @@
 
 class RevisionPackager(object):
 
+    source_packager_cls = SourcePackager
+    binary_packager_cls = BinaryPackager
+
     def __init__(self, plant, revision):
         self.plant = plant
         self.revision = revision
@@ -173,19 +212,19 @@
 
     def package(self):
         try:
-            src_packager = SourcePackager(self.plant, self.status,
-                                          self.work_dir, self.src_dir,
-                                          self.revision)
+            src_packager = self.source_packager_cls(self.plant, self.status,
+                                                    self.work_dir, self.src_dir,
+                                                    self.revision)
             src_packager.package()
 
             dsc_file = self.find_dsc_file()
             if dsc_file is None:
                 raise RuntimeError("Cannot find dsc File in %r" % self.src_dir)
 
-            bin_packager = BinaryPackager(self.plant, self.status,
-                                          self.binary_dir, dsc_file,
-                                          os.path.join(self.base_dir,
-                                                       "build.log"))
+            bin_packager = self.binary_packager_cls(self.plant, self.status,
+                                                    self.binary_dir, dsc_file,
+                                                    os.path.join(self.base_dir,
+                                                                 "build.log"))
             bin_packager.package()
         except:
             self.status.set("failed", traceback.format_exc())
@@ -198,8 +237,14 @@
 
 class AssemblyLine(object):
 
+    revision_packager_cls = RevisionPackager
+
+    svn_external_subdirs = []
+
+    extra_config_desc = []
+
     def __init__(self, name, base_dir, svn_url, root_cmd, deb_email,
-                 deb_fullname):
+                 deb_fullname, packager_class="treepkg.packager"):
         self.name = name
         self.base_dir = base_dir
         self.svn_url = svn_url
@@ -219,10 +264,11 @@
                             self.pkg_dir_template % locals())
 
     def last_changed_revision(self):
-        rev1 = subversion.last_changed_revision(self.checkout_dir)
-        rev2 = subversion.last_changed_revision(os.path.join(self.checkout_dir,
-                                                             "admin"))
-        return max(rev1, rev2)
+        revisions = []
+        for directory in [self.checkout_dir] + self.svn_external_subdirs:
+            directory = os.path.join(self.checkout_dir, directory)
+            revisions.append(subversion.last_changed_revision(directory))
+        return max(revisions)
 
     def last_packaged_revision(self):
         """Returns the revision number of the highest packaged revision.
@@ -265,10 +311,11 @@
         # some versions of svn (notably version 1.4.2 shipped with etch)
         # do export externals such as the admin subdirectory.  We may
         # have to do that in an extra step.
-        admindir = os.path.join(to_dir, "admin")
-        if not os.path.isdir(admindir):
-            subversion.export(os.path.join(self.checkout_dir, "admin"),
-                              admindir)
+        for subdir in self.svn_external_subdirs:
+            absdir = os.path.join(to_dir, subdir)
+            if not os.path.isdir(absdir):
+                subversion.export(os.path.join(self.checkout_dir, subdir),
+                                  absdir)
 
     def copy_debian_directory(self, to_dir):
         logging.info("Copying debian directory to %r", to_dir)
@@ -290,11 +337,15 @@
         logging.info("Previously packaged revision was %d", previous_revision)
         if current_revision > previous_revision:
             logging.info("New revision is not packaged yet")
-            return RevisionPackager(self, current_revision)
+            return self.revision_packager_cls(self, current_revision)
         else:
             logging.info("New revision already packaged.")
 
 
+def create_packager(packager_class, **kw):
+    module = util.import_dotted_name(packager_class)
+    return module.AssemblyLine(**kw)
+
 
 class Packager(object):
 
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)