bh@225: # Copyright (C) 2007, 2008, 2009 by Intevation GmbH
bh@211: # Authors:
bh@211: # Bernhard Herzog <bh@intevation.de>
bh@211: #
bh@211: # This program is free software under the GPL (>=v2)
bh@211: # Read the file COPYING coming with the software for details.
bh@211: 
bh@211: import os
bh@211: import logging
bh@211: import shutil
bh@211: import time
bh@211: 
bh@211: import treepkg.packager
bh@211: import treepkg.util
bh@211: import treepkg.subversion as subversion
bh@211: 
bh@279: from base import BaseSourcePackager, BasePackageTrack
bh@270: 
bh@211: 
bh@211: class SubversionSubset(object):
bh@211: 
bh@211:     """Manage a subversion working copy that contains a subset of a repository
bh@211: 
bh@211:     The SVN repository for the enterprise 4 l10n sources contains all
bh@211:     languages.  Only a small subset of those languages are actually
bh@211:     maintained, though.  This class provides a way to manage a working
bh@211:     copy that contains only the part that actually need to be packaged.
bh@211:     """
bh@211: 
bh@211:     def __init__(self, baseurl, localdir, subdirectories):
bh@211:         self.baseurl = baseurl
bh@211:         self.localdir = localdir
bh@211:         self.subdirectories = subdirectories
bh@211: 
bh@211:     def update_or_checkout(self, revision=None):
bh@211:         for desc in self.subdirectories:
bh@211:             if len(desc) == 2:
bh@211:                 subdir, recurse = desc
bh@211:             else:
bh@211:                 subdir = desc[0]
bh@211:                 recurse = True
bh@211:             self.update_or_checkout_subdir(subdir, revision, recurse=recurse)
bh@211: 
bh@211:     def update_or_checkout_subdir(self, subdir, revision, recurse):
bh@211:         localdir = os.path.join(self.localdir, subdir)
bh@211:         svn_url = self.baseurl + subdir
bh@211:         if os.path.exists(localdir):
bh@211:             logging.info("Updating the working copy in %r", localdir)
bh@211:             subversion.update(localdir, revision=revision, recurse=recurse)
bh@211:         else:
bh@211:             logging.info("The working copy in %r doesn't exist yet."
bh@211:                          "  Checking out from %r", localdir, svn_url)
bh@211:             subversion.checkout(svn_url, localdir, revision=revision,
bh@211:                                 recurse=recurse)
bh@211: 
bh@270:     def export(self, destdir, url=None):
bh@270:         if url is not None:
bh@270:             baseurl = url
bh@270:         else:
bh@270:             baseurl = self.localdir
bh@211:         for desc in self.subdirectories:
bh@270:             if len(desc) == 2:
bh@270:                 subdir, recurse = desc
bh@270:             else:
bh@270:                 subdir = desc[0]
bh@270:                 recurse = True
bh@270:             subversion.export(os.path.join(baseurl, subdir),
bh@270:                               os.path.join(destdir, subdir),
bh@270:                               recurse=recurse)
bh@211: 
bh@211:     def last_changed_revision(self):
bh@211:         return max([subversion.last_changed_revision(os.path.join(self.localdir,
bh@211:                                                                   desc[0]))
bh@211:                     for desc in self.subdirectories])
bh@211: 
bh@211: 
bh@211: 
bh@279: class SourcePackager(BaseSourcePackager):
bh@211: 
bh@211:     """Creates the debian source package for the l10n files
bh@211: 
bh@211:     This is a bit more complicated than for other packages.  The
bh@211:     orig.tar.gz file of the debian source package contains one .tar.bz2
bh@211:     file for every language.  Those .tar.bz files are the kde-18n-<lang>
bh@211:     files released by the KDE project.  For now, we only have the German
bh@211:     localization in the enterprise source package, so the orig.tar.gz
bh@211:     file will have the following contents:
bh@211: 
bh@211:       kde-l10n-<version>/
bh@211:       kde-l10n-<version>/kde-l10n-de-<version>.tar.bz2
bh@211: 
bh@211:     <version> is the same everywhere.
bh@211:     """
bh@211: 
bh@211:     pkg_basename = "kde-l10n"
bh@211: 
bh@211:     createtarball_script = """\
bh@211: #! /bin/bash
bh@211: set -e
bh@211: 
bh@211: apt-get --assume-yes --force-yes install %(builddeps)s
bh@211: 
bh@211: # copy the source tree to a directory that's under pbuilder control so
bh@211: # that it gets removed along with the build environment.  Otherwise we
bh@211: # end up with a directory containing files that cannot be removed by
bh@211: # treepkg
bh@211: workdir=/tmp/work
bh@211: cp -a %(basedir)s $workdir
bh@211: cd $workdir
bh@211: 
bh@211: # only handle the de subdirectory
bh@211: echo de > subdirs
bh@211: 
bh@211: # create the CMakeFiles
bh@211: ./scripts/autogen.sh
bh@211: mv de kde-l10n-de-%(version)s
bh@226: tar cjf %(tarball)s kde-l10n-de-%(version)s
bh@211: """
bh@211: 
bh@211: 
bh@211:     def __init__(self, *args, **kw):
bh@211:         super(SourcePackager, self).__init__(*args, **kw)
bh@211:         self.enterprise_version = (time.strftime("%Y%m%d", time.localtime())
bh@211:                                    + "." + str(self.revision))
bh@211: 
bh@211:     def determine_package_version(self, directory):
bh@211:         enterprise_version = self.enterprise_version
bh@211:         return self.track.version_template % locals()
bh@211: 
bh@279:     def create_l10n_de_tarball(self, pkgbasedir, pkgbaseversion):
bh@211:         logging.info("Creating kde-l10n-de tarball")
bh@211:         de_tarball = os.path.join(self.work_dir,
bh@211:                                   "kde-l10n-de-" + pkgbaseversion + ".tar.bz2")
bh@226:         # xutils-dev is needed for the revpath script used by
bh@226:         # scripts/autogen.sh
bh@211:         script = (self.createtarball_script
bh@226:                   % dict(builddeps="xutils-dev",  tarball=de_tarball,
bh@211:                          basedir=pkgbasedir, version=pkgbaseversion))
bh@211:         script_name = os.path.join(self.work_dir, "createtarball")
bh@211:         treepkg.util.writefile(script_name, script, 0755)
bh@211:         treepkg.util.ensure_directory(self.src_dir)
bh@211:         treepkg.util.ensure_directory(self.log_dir)
bh@211:         self.track.builder.run_script([script_name],
bh@211:                                       logfile=os.path.join(self.log_dir,
bh@211:                                                            "tarball_log.txt"),
bh@211:                                       bindmounts=[self.work_dir])
bh@211:         return de_tarball
bh@211: 
bh@279:     def prepare_sources_for_tarball(self, pkgbasedir, pkgbaseversion):
bh@279:         de_tarball = self.create_l10n_de_tarball(pkgbasedir, pkgbaseversion)
bh@211:         shutil.rmtree(pkgbasedir)
bh@211:         os.mkdir(pkgbasedir)
bh@211:         os.rename(de_tarball,
bh@211:                   os.path.join(pkgbasedir, os.path.basename(de_tarball)))
bh@211: 
bh@211: 
bh@211: class RevisionPackager(treepkg.packager.RevisionPackager):
bh@211: 
bh@211:     source_packager_cls = SourcePackager
bh@211: 
bh@211: 
bh@270: class PackageTrack(BasePackageTrack):
bh@211: 
bh@211:     revision_packager_cls = RevisionPackager
bh@211: 
bh@211:     def __init__(self, *args, **kw):
bh@225:         svn_url = kw["svn_url"]
bh@211:         super(PackageTrack, self).__init__(*args, **kw)
bh@225:         self.working_copy = SubversionSubset(svn_url, self.checkout_dir,
bh@211:                                              subdirectories= [("", False),
bh@211:                                                               ("de",),
bh@211:                                                               ("scripts",)])
bh@270: 
bh@270:     def export_tag(self, tag_url, to_dir):
bh@270:         logging.info("Exporting sources from %s to %r",
bh@270:                      tag_url, to_dir)
bh@270:         self.working_copy.export(to_dir, url=tag_url)