aheinecke@322: # Copyright (C) 2007, 2008, 2010 by Intevation GmbH aheinecke@322: # Authors: aheinecke@322: # Bernhard Herzog aheinecke@322: # Modified for CE Andre Heinecke aheinecke@322: # aheinecke@322: # This program is free software under the GPL (>=v2) aheinecke@322: # Read the file COPYING coming with the software for details. aheinecke@322: aheinecke@322: """Base classes for all gnupg for Windows CE packagers""" aheinecke@322: aheinecke@322: import os aheinecke@322: import re aheinecke@322: import inspect aheinecke@322: import new aheinecke@322: aheinecke@322: import treepkg.util aheinecke@322: import treepkg.packager aheinecke@322: import treepkg.run as run aheinecke@322: from treepkg.cmdexpand import cmdexpand aheinecke@322: aheinecke@322: aheinecke@322: class BaseSourcePackager(treepkg.packager.SourcePackager): aheinecke@322: aheinecke@322: def orig_source_version(self, directory): aheinecke@322: """Determines the version from the configure.ac file in directory""" aheinecke@322: filename = os.path.join(directory, "configure.ac") aheinecke@322: for line in open(filename): aheinecke@322: aheinecke@322: # Matches lines like aheinecke@322: # m4_define(my_version, [1.1.7]) aheinecke@322: # used by most of the gnupg packages aheinecke@322: match = re.match(r"m4_define\(\[?my_version\]?, \[([^]]+)\]\)", aheinecke@322: line) aheinecke@322: if match: aheinecke@322: return match.group(1) aheinecke@322: aheinecke@322: # Matches lines like. aheinecke@322: # AC_INIT(pinentry, 0.7.6-cvs, [gnupg-devel@gnupg.org]) aheinecke@322: # pinentry is the GnuPG package that actually needs this aheinecke@322: match = re.match(r"AC_INIT\([a-zA-Z_]+, ([0-9.]+)", line) aheinecke@322: if match: aheinecke@322: return match.group(1) aheinecke@322: aheinecke@322: raise RuntimeError("Could not determine the version number from %s" aheinecke@322: % filename) aheinecke@322: aheinecke@322: def determine_package_version(self, directory): aheinecke@549: """ Returns a Git package Name """ aheinecke@549: date = run.capture_output(cmdexpand("/bin/sh -c \" git log --date=iso \ aheinecke@549: -n 1 | grep Date \ aheinecke@549: | awk \'{print $$2}\'\""), aheinecke@549: cwd=directory) aheinecke@549: time = run.capture_output(cmdexpand("/bin/sh -c \" git log --date=iso \ aheinecke@549: -n 1 | grep Date \ aheinecke@549: | awk \'{print $$3}\'\""), aheinecke@549: cwd=directory) aheinecke@549: date = date.replace('-','') aheinecke@549: time = time.replace(':','') aheinecke@549: return "%s~%s%s.git%s" % (self.orig_source_version(directory), aheinecke@549: date[:8], time[:4], self.revision[:7]) aheinecke@549: aheinecke@322: def sign_package(self): aheinecke@322: return None aheinecke@322: aheinecke@322: def do_package(self): aheinecke@322: pkgbaseversion, pkgbasedir = self.export_sources() aheinecke@322: aheinecke@322: run.call(cmdexpand("/bin/sh autogen.sh"), cwd=pkgbasedir, aheinecke@322: suppress_output=True) aheinecke@322: orig_version = self.orig_source_version(pkgbasedir) aheinecke@322: aheinecke@322: # patch the version number in the newly generated configure aheinecke@322: # file. autogen.sh normally determines it from svn, but here it aheinecke@322: # ran on a copy that did not include the .svn subdirectories and aheinecke@322: # thus could not find the svn revision. aheinecke@322: treepkg.util.replace_in_file(os.path.join(pkgbasedir, "configure"), aheinecke@549: re.escape(orig_version) + "-git0", aheinecke@549: orig_version + "-git%s" % self.revision) aheinecke@322: aheinecke@322: pkgbasename = self.pkg_basename + "_" + pkgbaseversion aheinecke@322: origtargz = os.path.join(self.work_dir, aheinecke@322: pkgbasename + ".orig.tar.gz") aheinecke@322: self.create_tarball(origtargz, self.work_dir, aheinecke@322: os.path.basename(pkgbasedir)) aheinecke@322: aheinecke@549: changemsg = ("Update to GIT rev. %s" % (self.revision,)) aheinecke@322: self.copy_debian_directory(pkgbasedir, pkgbaseversion, aheinecke@322: changemsg) aheinecke@322: aheinecke@322: self.create_source_package(pkgbasedir, origtargz) aheinecke@322: self.move_source_package(pkgbasename) aheinecke@322: aheinecke@322: class SmartSourcePackager(BaseSourcePackager): aheinecke@322: aheinecke@322: """SourcePackager that uses pbuilder to create the source tarball. aheinecke@322: aheinecke@322: We try to create source tarballs that are as close to the tarballs aheinecke@322: created by the upstream maintainers as possible. For the gnupg aheinecke@322: software this means we need to run 'make dist' in a configured SVN aheinecke@322: working copy with some additional software installed like autoconf aheinecke@322: and texinfo. We want to avoid running code from a working copy aheinecke@322: outside of the pbuilder environment and having to install recipe aheinecke@322: specific additional software packages in the treepkg host system. aheinecke@322: Therefore we create the source tarball using 'pbuilder execute' with aheinecke@322: a script. aheinecke@322: """ aheinecke@322: aheinecke@322: createtarball_script = """\ aheinecke@322: #! /bin/bash aheinecke@322: set -e aheinecke@322: apt-get --assume-yes --force-yes install %(builddeps)s aheinecke@322: aheinecke@322: # copy the source tree to a directory that's under pbuilder control so aheinecke@322: # that it gets removed along with the build environment. Otherwise we aheinecke@322: # end up with a directory containing files that cannot be removed by aheinecke@322: # treepkg aheinecke@322: workdir=/tmp/work aheinecke@322: cp -a %(basedir)s $workdir aheinecke@322: cd $workdir aheinecke@322: aheinecke@322: export MINGWPATH=/opt/mingw32ce aheinecke@322: export INCLUDE=$MINGWPATH/arm-mingw32ce/include:$MINGWPATH/include:\ aheinecke@322: /home/builder/wce-build/install/include:$INCLUDE aheinecke@322: export LIB=$MINGWPATH/arm-mingw32ce/lib:$MINGWPATH/lib:\ aheinecke@322: /home/builder/wce-build/install/lib:$LIB aheinecke@322: export PATH=:$PATH:$MINGWPATH/bin:$MINGWPATH/arm-mingw32ce/bin:\ aheinecke@322: $MINGWPATH/libexec/gcc/arm-mingw32ce/4.4.0: aheinecke@373: export w32ce_root=/opt/mingw32ce aheinecke@549: export w32root=/opt/mingw32ce aheinecke@322: aheinecke@373: ./autogen.sh --build-w32ce aheinecke@322: aheinecke@322: # revert autoconf changes, so that the original Makefile.am ends up in aheinecke@322: # the tarball aheinecke@322: mv Makefile.am.orig Makefile.am aheinecke@322: aheinecke@322: %(make_dist_command)s aheinecke@322: mv *.tar.gz %(origtargz)s aheinecke@322: """ aheinecke@322: def __init__(self, *args): aheinecke@322: super(SmartSourcePackager, self).__init__(*args) aheinecke@322: self.pkgbasename = None aheinecke@322: self.pkgbaseversion = None aheinecke@322: self.origtargz = None aheinecke@322: aheinecke@322: def copy_workingcopy(self, dest): aheinecke@322: treepkg.util.copytree(self.track.checkout_dir, dest) aheinecke@322: aheinecke@322: def create_original_tarball(self): aheinecke@322: copied_working_copy = os.path.join(self.work_dir, "copied_working_copy") aheinecke@322: self.copy_workingcopy(copied_working_copy) aheinecke@322: aheinecke@322: self.pkgbaseversion = \ aheinecke@322: self.determine_package_version(copied_working_copy) aheinecke@322: self.pkgbasename = self.pkg_basename + "_" + self.pkgbaseversion aheinecke@322: self.origtargz = os.path.join(self.work_dir, aheinecke@322: self.pkgbasename + ".orig.tar.gz") aheinecke@322: aheinecke@373: # tweak automake settings so that make dist produces a tar.gz not aheinecke@373: # a tar.bz2 aheinecke@373: run.call(cmdexpand("/bin/sh -c \"cp Makefile.am Makefile.am.orig\""), aheinecke@373: cwd=copied_working_copy,suppress_output=True) aheinecke@373: run.call(cmdexpand("/bin/sh -c \"sed -e '/AUTOMAKE_OPTIONS/ \ aheinecke@373: s/[a-zA-Z0-9-]*dist[a-zA-Z0-9-]*//g' \ aheinecke@373: Makefile.am.orig > Makefile.am\""), cwd=copied_working_copy, aheinecke@373: suppress_output=True) aheinecke@373: aheinecke@373: run.call(cmdexpand("/bin/sh autogen.sh"), cwd=copied_working_copy, aheinecke@373: suppress_output=True) aheinecke@373: orig_version = self.orig_source_version(copied_working_copy) aheinecke@373: treepkg.util.replace_in_file(os.path.join(copied_working_copy, aheinecke@373: "configure"), aheinecke@549: re.escape(orig_version) + "-git0", aheinecke@549: orig_version + "-git%s" % self.revision) aheinecke@373: aheinecke@322: script = (self.createtarball_script aheinecke@322: % dict(builddeps=" ".join(self.track.dependencies_required() aheinecke@322: | self.tarball_dependencies), aheinecke@322: basedir=copied_working_copy, aheinecke@322: origtargz=self.origtargz, aheinecke@322: make_dist_command=self.make_dist_command)) aheinecke@322: script_name = os.path.join(self.work_dir, "createtarball") aheinecke@322: treepkg.util.writefile(script_name, script, 0755) aheinecke@322: aheinecke@322: treepkg.util.ensure_directory(self.src_dir) aheinecke@322: treepkg.util.ensure_directory(self.log_dir) aheinecke@322: self.track.builder.run_script([script_name], aheinecke@322: logfile=os.path.join(self.log_dir, aheinecke@322: "tarball_log.txt"), aheinecke@322: bindmounts=[self.work_dir, self.src_dir]) aheinecke@322: aheinecke@322: def create_orig_dir(self): aheinecke@322: """Unpacks the tarball created by create_original_tarball into work_dir aheinecke@322: """ aheinecke@322: unpack_dir = os.path.join(self.work_dir, "unpack") aheinecke@322: treepkg.util.ensure_directory(unpack_dir) aheinecke@322: run.call(cmdexpand("tar xzf $origtargz -C $unpack_dir", aheinecke@322: unpack_dir=unpack_dir, origtargz=self.origtargz)) aheinecke@322: unpacked_files = treepkg.util.listdir_abs(unpack_dir) aheinecke@322: if len(unpacked_files) != 1: aheinecke@322: raise RuntimeError("%s should have extracted to a single directory", aheinecke@322: origtargz) aheinecke@322: unpacked_dir = unpacked_files[0] aheinecke@322: aheinecke@322: orig_dir = os.path.join(self.work_dir, os.path.basename(unpacked_dir)) aheinecke@322: os.rename(unpacked_dir, orig_dir) aheinecke@322: return orig_dir aheinecke@322: aheinecke@322: def do_package(self): aheinecke@322: self.create_original_tarball() aheinecke@322: orig_dir = self.create_orig_dir() aheinecke@322: aheinecke@549: changemsg = ("Update to GIT rev. %s" % (self.revision,)) aheinecke@322: self.copy_debian_directory(orig_dir, self.pkgbaseversion, changemsg) aheinecke@322: aheinecke@322: self.create_source_package(orig_dir, self.origtargz) aheinecke@322: self.move_source_package(self.pkgbasename) aheinecke@322: aheinecke@322: aheinecke@322: def define_gnupg_packager(pkg_basename, aheinecke@322: tarball_dependencies=("autoconf", "automake", aheinecke@322: "texinfo", "subversion"), aheinecke@373: make_dist_command="make dist"): aheinecke@322: """Create a SourcePackager for a GnuPG package in the caller's globals(). aheinecke@322: This is a helper function for the modules in the recipe.gnupg package. aheinecke@322: """ aheinecke@322: base_class = BaseSourcePackager aheinecke@322: class_attributes = dict(pkg_basename=pkg_basename) aheinecke@322: if tarball_dependencies is not None: aheinecke@322: base_class = SmartSourcePackager aheinecke@322: class_attributes["tarball_dependencies"] = set(tarball_dependencies) aheinecke@322: if make_dist_command is not None: aheinecke@322: base_class = SmartSourcePackager aheinecke@322: class_attributes["make_dist_command"] = make_dist_command aheinecke@322: aheinecke@322: caller_globals = inspect.currentframe().f_back.f_globals aheinecke@322: caller_globals["SourcePackager"] = new.classobj("SourcePackager", aheinecke@322: (base_class,), aheinecke@322: class_attributes)