[Treepkg-commits] r8 - in trunk: test treepkg
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Mon Sep 10 19:13:33 CEST 2007
Author: bh
Date: 2007-09-10 19:13:33 +0200 (Mon, 10 Sep 2007)
New Revision: 8
Added:
trunk/test/filesupport.py
trunk/test/mocksudopbuilder.py
trunk/test/test_packager.py
Modified:
trunk/treepkg/packager.py
Log:
Make BinaryPackager remove all files that do not belong to the binary
package from the pkg/<rev>/binary directory after pbuilder finished.
Also, add tests for this and some corresponding test support code.
Added: trunk/test/filesupport.py
===================================================================
--- trunk/test/filesupport.py 2007-08-31 17:07:18 UTC (rev 7)
+++ trunk/test/filesupport.py 2007-09-10 17:13:33 UTC (rev 8)
@@ -0,0 +1,92 @@
+# Copyright (C) 2007 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Support code for the test cases"""
+
+import os
+import shutil
+from treepkg.util import writefile
+
+
+def create_temp_dir():
+ """Create a temporary directory for the test-suite and return its name.
+
+ The temporary directory is always called temp and is created in the
+ directory where the support module is located.
+
+ If the temp directory already exists, just return the name.
+ """
+ name = os.path.abspath(os.path.join(os.path.dirname(__file__), "temp"))
+
+ # if the directory already exists, we're done
+ if os.path.isdir(name):
+ return name
+
+ # create the directory
+ os.mkdir(name)
+ return name
+
+
+class FileTestMixin:
+
+ """Mixin class for tests that use files in the temporary directory
+ """
+
+ def temp_file_name(self, basename, remove=False):
+ """Returns the full name of the file named basename in the temp. dir.
+ If the remove parameter is true, the file is removed if already exists.
+ """
+ filename = os.path.join(create_temp_dir(), basename)
+ if remove and os.path.exists(filename):
+ os.remove(filename)
+ return filename
+
+ def create_temp_file(self, basename, contents, mode = None):
+ """Creates a file in the temp directory with the given contents.
+ The optional parameter mode should either be None (the default)
+ or an int specifying the file permissions (same format as the
+ second parameter of os.chmod). The method returns the absolute
+ name of the created file.
+ """
+ filename = self.temp_file_name(basename)
+ file = open(filename, "w")
+ file.write(contents)
+ file.close()
+ if mode is not None:
+ os.chmod(filename, mode)
+ return filename
+
+ def create_temp_dir(self, basename, remove=True):
+ """Creates the directory basename in the temporary directory.
+ If the optional parameter remove is true (the default), the
+ directory and all its contents are deleted with shutil.rmtree.
+ The method returns the absolute name of the created directory.
+ """
+ dirname = os.path.join(create_temp_dir(), basename)
+ if remove and os.path.exists(dirname):
+ shutil.rmtree(dirname)
+ os.mkdir(dirname)
+ return dirname
+
+ def create_files(self, directory, filedesc):
+ """Creates a hieararchy of directories and files in directory.
+ The filedesc parameter should be a sequence of (name, contents)
+ pairs. Each pair describes one entry of the directory. If
+ contents is an instance of list, the entry is a subdirectory and
+ the contents is a list in the same format as filedesc and passed
+ recursively to the create_files method. If contents is a
+ string, the new directory entry is a normal file and contents is
+ the contents of the file.
+ """
+ for name, contents in filedesc:
+ if isinstance(contents, list):
+ # a list as contents indicates a directory
+ newdir = os.path.join(directory, name)
+ os.mkdir(newdir)
+ self.create_files(newdir, contents)
+ else:
+ writefile(os.path.join(directory, name), contents)
Property changes on: trunk/test/filesupport.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native
Added: trunk/test/mocksudopbuilder.py
===================================================================
--- trunk/test/mocksudopbuilder.py 2007-08-31 17:07:18 UTC (rev 7)
+++ trunk/test/mocksudopbuilder.py 2007-09-10 17:13:33 UTC (rev 8)
@@ -0,0 +1,150 @@
+#! /usr/bin/env python
+# Copyright (C) 2007 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""
+Mock sudo that mimics some aspects of sudo pbuilder invocations for test cases
+"""
+
+import sys
+import os
+import shutil
+import tempfile
+import re
+
+from optparse import OptionParser
+
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir))
+
+from treepkg.util import extract_value_for_key, writefile
+from treepkg.run import call
+from treepkg.cmdexpand import cmdexpand
+
+
+def parse_command_line(args):
+ if len(args) < 2:
+ raise RuntimeError("mocksudopbuilder must be called with at least"
+ " two parameters")
+ if args[0] != "/usr/sbin/pbuilder":
+ raise RuntimeError("mocksudopbuilder must be called with"
+ " /usr/sbin/pbuilder as first argument")
+
+ cmd = args[1]
+ if cmd != "build":
+ raise RuntimeError("mocksudopbuilder only supports the pbuilder build"
+ " command")
+
+ args = args[2:]
+
+ parser = OptionParser()
+ parser.add_option("--configfile")
+ parser.add_option("--logfile")
+ parser.add_option("--buildresult")
+
+ opts, rest = parser.parse_args(args)
+ return opts, rest
+
+
+class DSC(object):
+
+ def __init__(self, filename):
+ self.filename = os.path.abspath(filename)
+ self.parse_dsc_file()
+
+ def parse_dsc_file(self):
+ lines = open(self.filename).readlines()
+
+ self.source_package = extract_value_for_key(lines, "Source:")
+
+ raw_binaries = extract_value_for_key(lines, "Binary:")
+ self.binaries = [name.strip() for name in raw_binaries.split(",")]
+
+ version = extract_value_for_key(lines, "Version:")
+ match = re.match(r"\d+:", version)
+ if match:
+ version = version[match.end(0):]
+ self.version = version
+ match = re.search("-([^-]+)$", version)
+ if match:
+ self.base_version = version[:match.start(0)]
+ self.revision = match.group(1)
+ else:
+ self.base_version = version
+ self.revision = ""
+
+ self.files = []
+ for i in range(len(lines) - 1, -1, -1):
+ line = lines[i]
+ if line[0] != " ":
+ break
+ self.files.append(line.split()[-1])
+
+def unpack_source_pkg(dsc):
+ tempdir = tempfile.mkdtemp()
+ call(cmdexpand("dpkg-source -x $filename", filename=dsc.filename),
+ cwd=tempdir, stdout=sys.stdout)
+ return os.path.join(tempdir, dsc.source_package + "-" + dsc.base_version)
+
+def parse_debian_control(filename):
+ packages = []
+ lines = [line.strip() for line in open(filename).readlines()]
+ while lines:
+ try:
+ empty_line = lines.index("")
+ except ValueError:
+ empty_line = len(lines)
+ paragraph = lines[:empty_line]
+ lines = lines[empty_line + 1:]
+
+ package_name = extract_value_for_key(paragraph, "Package:")
+ arch = extract_value_for_key(paragraph, "Architecture:")
+ if package_name is not None:
+ packages.append((package_name, arch))
+ return packages
+
+def create_binary_results(buildresult, dsc, packages):
+ for name, arch in packages:
+ if arch == "any":
+ arch = "i386"
+ writefile(os.path.join(buildresult,
+ "%s_%s_%s.deb" % (name, dsc.version, arch)),
+ "")
+
+ basename = os.path.splitext(os.path.basename(dsc.filename))[0]
+ writefile(os.path.join(buildresult, basename + "_i386.changes"), "")
+
+def create_source_results(buildresult, dsc):
+ dscdir = os.path.dirname(dsc.filename)
+ shutil.copy(dsc.filename, buildresult)
+ for name in dsc.files:
+ shutil.copy(os.path.join(dscdir, name), buildresult)
+
+def mock_pbuilder_build(opts, dscfilename):
+ dsc = DSC(dscfilename)
+ print "unpacking source package"
+ unpacked_dir = unpack_source_pkg(dsc)
+ try:
+ packages = parse_debian_control(os.path.join(unpacked_dir, "debian",
+ "control"))
+ create_binary_results(opts.buildresult, dsc, packages)
+ create_source_results(opts.buildresult, dsc)
+ finally:
+ print "removing tempdir", repr(os.path.dirname(unpacked_dir))
+ shutil.rmtree(os.path.dirname(unpacked_dir))
+
+def main():
+ opts, rest = parse_command_line(sys.argv[1:])
+ for optname in ["buildresult"]:
+ if getattr(opts, optname) is None:
+ raise RuntimeError("Missing required option %r" % optname)
+ if len(rest) != 1:
+ raise RuntimeError("Missing required argument for .dsc file")
+ if opts.logfile:
+ sys.stdout = open(opts.logfile, "w", 1)
+ mock_pbuilder_build(opts, rest[0])
+
+main()
Property changes on: trunk/test/mocksudopbuilder.py
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native
Added: trunk/test/test_packager.py
===================================================================
--- trunk/test/test_packager.py 2007-08-31 17:07:18 UTC (rev 7)
+++ trunk/test/test_packager.py 2007-09-10 17:13:33 UTC (rev 8)
@@ -0,0 +1,132 @@
+# Copyright (C) 2007 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Tests for treepkg.packager"""
+
+import sys
+import os
+import unittest
+
+from treepkg.run import call
+from treepkg.cmdexpand import cmdexpand
+from treepkg.util import writefile
+from treepkg.packager import PackagerGroup
+import treepkg.subversion as subversion
+import treepkg
+
+from filesupport import FileTestMixin
+
+
+def create_svn_repository(directory):
+ baseurl = "file://" + directory
+ call(cmdexpand("svnadmin create --fs-type fsfs $directory",
+ **locals()))
+ call(cmdexpand("svn mkdir -q -m 'create directory structure'"
+ " $baseurl/trunk",
+ **locals()))
+ return baseurl
+
+def add_svn_files(workingcopy, filedesc, commitmsg):
+ for name, contents in filedesc:
+ writefile(os.path.join(workingcopy, name), contents)
+ call(cmdexpand("svn add -q $name", **locals()),
+ cwd=workingcopy)
+ call(cmdexpand("svn commit -q -m $commitmsg", **locals()),
+ cwd=workingcopy)
+
+
+class SourcePackager(treepkg.packager.SourcePackager):
+
+ pkg_basename = "testpkg"
+
+ def do_package(self):
+ pkgbaseversion, pkgbasedir = self.export_sources()
+
+ pkgbasename = self.pkg_basename + "_" + 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 rev. %d" % (self.revision,))
+ self.copy_debian_directory(pkgbasedir, pkgbaseversion,
+ changemsg)
+
+ self.create_source_package(pkgbasedir, origtargz)
+ self.move_source_package(pkgbasename)
+
+
+class RevisionPackager(treepkg.packager.RevisionPackager):
+
+ source_packager_cls = SourcePackager
+
+
+class PackageTrack(treepkg.packager.PackageTrack):
+
+ revision_packager_cls = RevisionPackager
+
+
+class TestPackager(unittest.TestCase, FileTestMixin):
+
+ initial_files = [
+ ("README", "and miles to go before I sleep"),
+ ]
+
+ debian_files = [
+ ("debian",
+ [("control", """\
+Source: testpkg
+Priority: optional
+Maintainer: TreePKG <treepkg at example.com>
+Standards-Version: 3.7.2
+
+Package: testpkg
+Architecture: all
+Description: Test package for treepkg testsGerman (de) internationalized (i18n) files for KDE
+ This package contains the German internationalized (i18n) files for
+ all KDE core applications.
+"""),
+ ("changelog", """\
+testpkg (0-0) unstable; urgency=low
+
+ * Initial version
+
+ -- TreePKG <treepkg at example.com> Thu, 8 Mar 2007 18:34:39 +0100
+"""),
+ ("rules", "binary: echo binary")])]
+
+ def setUp(self):
+ self.svndir = self.create_temp_dir(self.id() + "-svn")
+ self.svnworkdir = self.create_temp_dir(self.id() + "-svnwork")
+ self.trackdir = self.create_temp_dir(self.id() + "-track")
+ self.create_files(self.trackdir, self.debian_files)
+
+ def test(self):
+ baseurl = create_svn_repository(self.svndir)
+ svn_url = baseurl + "/trunk"
+ subversion.checkout(svn_url, self.svnworkdir)
+ add_svn_files(self.svnworkdir, self.initial_files,
+ "Initial version")
+ rootcmd = os.path.join(os.path.dirname(__file__), os.pardir, "test",
+ "mocksudopbuilder.py")
+ track = PackageTrack(name="testpkg", base_dir=self.trackdir,
+ svn_url=svn_url, pbuilderrc="",
+ root_cmd=[sys.executable, rootcmd],
+ deb_email="treepkg at example.com",
+ deb_fullname="treepkg tester")
+ group = PackagerGroup([track], 1)
+ group.check_package_tracks()
+
+ # Now check the source and binary package files
+ pkgdir = os.path.join(self.trackdir, "pkg", "2-1")
+ self.assertEquals(sorted(os.listdir(os.path.join(pkgdir, "src"))),
+ ["testpkg_2-kk1.diff.gz",
+ "testpkg_2-kk1.dsc",
+ "testpkg_2.orig.tar.gz"])
+ self.assertEquals(sorted(os.listdir(os.path.join(pkgdir, "binary"))),
+ ["testpkg_2-kk1_all.deb",
+ "testpkg_2-kk1_i386.changes"])
Property changes on: trunk/test/test_packager.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native
Modified: trunk/treepkg/packager.py
===================================================================
--- trunk/treepkg/packager.py 2007-08-31 17:07:18 UTC (rev 7)
+++ trunk/treepkg/packager.py 2007-09-10 17:13:33 UTC (rev 8)
@@ -195,6 +195,11 @@
logfile=self.logfile, bindir=self.binary_dir,
dsc=self.dsc_file),
suppress_output=True)
+ # remove the source package files put into the binary directory
+ # by pbuilder
+ for filename in os.listdir(self.binary_dir):
+ if os.path.splitext(filename)[1] not in (".deb", ".changes"):
+ os.remove(os.path.join(self.binary_dir, filename))
self.status.binary_package_created()
More information about the Treepkg-commits
mailing list