bricks@349: # Copyright (C) 2007 - 2010 by Intevation GmbH
bh@271: # Authors:
bh@271: # Bernhard Herzog <bh@intevation.de>
bricks@349: # Bjoern Ricks <bjoern.ricks@intevation.de>
bh@271: #
bh@271: # This program is free software under the GPL (>=v2)
bh@271: # Read the file COPYING coming with the software for details.
bh@271: 
bh@314: """Base classes for all kde entperprise packagers"""
bh@271: 
bh@286: import re
bh@271: import time
bh@271: import logging
bh@271: 
bh@271: import treepkg.packager
bh@286: import treepkg.subversion as subversion
bricks@511: import treepkg.git as git
bh@271: 
bh@271: 
bh@314: class SourcePackager(treepkg.packager.SourcePackager):
bh@275: 
bh@271:     def __init__(self, *args, **kw):
bh@314:         super(SourcePackager, self).__init__(*args, **kw)
bh@283:         self.enterprise_version = (self.parent.pkg_date + "."
bh@283:                                    + str(self.revision))
bh@271: 
bh@271:     def determine_package_version(self, directory):
bh@271:         enterprise_version = self.enterprise_version
bricks@494:         return super(SourcePackager, self).determine_package_version(
bricks@494:                 directory, locals())
bh@271: 
bh@276:     def prepare_sources_for_tarball(self, pkgbasedir, pkgbaseversion):
bh@271:         self.update_version_numbers(pkgbasedir)
bh@271: 
bh@274:     def update_version_numbers(self, pkgbasedir):
bh@274:         """Updates the version numbers in the code in pkgbasedir.
bh@274:         The default implementation does nothing.  Derived classes should
bh@274:         override this method if necessary.
bh@274:         """
bh@271: 
bricks@381:     def get_change_msg(self):
bricks@381:         return self.changemsg_template % dict(revision=self.revision,
bricks@381:                                      pkg_date=self.parent.pkg_date,
bricks@381:                                      rules_revision=self.parent.rules_revision)
bh@271: 
bh@314: class RevisionPackager(treepkg.packager.RevisionPackager):
bh@283: 
bh@314:     source_packager_cls = SourcePackager
bh@301: 
bh@283:     def __init__(self, *args, **kw):
bh@283:         self.pkg_date = kw.pop("pkg_date",
bh@283:                                time.strftime("%Y%m%d", time.localtime()))
bh@314:         super(RevisionPackager, self).__init__(*args, **kw)
bh@283: 
bh@283: 
bh@314: class PackageTrack(treepkg.packager.PackageTrack):
bh@271: 
bh@314:     revision_packager_cls = RevisionPackager
bh@309: 
bh@314:     extra_config_desc = [("tags_url", str, ""),
bh@271:                          ("tags_pattern", str, ""),
bricks@349:                          ("tags_subdir", str, ""),
bricks@511:                          ("tags_scm_type", str, scm_type),
bricks@511:                          ("tags_rules_url", str, None),
bricks@511:                          ("tags_rules_pattern", str, None),
bricks@511:                          ("tags_rules_subdir", str, ""),
bricks@511:                          ("tags_rules_scm_type", str, rules_scm_type)]
bh@271: 
bh@271:     def __init__(self, *args, **kw):
bh@271:         tags_url = kw.pop("tags_url")
bh@271:         tags_pattern = kw.pop("tags_pattern")
bh@271:         tags_subdir = kw.pop("tags_subdir")
bricks@511:         tags_rules_url = kw.pop("tags_rules_url")
bricks@511:         tags_rules_pattern = kw.pop("tags_rules_pattern", tags_pattern)
bricks@349:         tags_rules_subdir = kw.pop("tags_rules_subdir")
bh@314:         super(PackageTrack, self).__init__(*args, **kw)
bricks@511:         if tags_scm_type == "git":
bricks@511:             self.tag_detector = git.TagDetector(tags_url, tags_pattern)
bricks@511:         elif tags_scm_type == "svn":
bricks@511:             self.tag_detector = subversion.TagDetector(tags_url, tags_pattern,
bh@286:                                                    tags_subdir)
bricks@511:         else:
bricks@511:             raise packager.PackageError("Unknown scm type \"%s\" for tag" \
bricks@511:                     " sources set" % tags_scm_type)
bricks@511:         if tags_rules_scm_type == "git":
bricks@511:             self.tag_rules_detector = git.TagDetector(tags_rules_url,
bricks@511:                     tags_rules_pattern)
bricks@511:         elif tags_rules_scm_type == "svn":
bricks@511:             self.tag_rules_detector = subversion.TagDetector(tags_rules_url,
bricks@511:                     tags_rules_pattern, tags_rules_subdir)
bricks@511:         else:
bricks@511:             raise packager.PackageError("Unknown scm type \"%s\" for tag" \
bricks@511:                     " rules set" % tags_rules_scm_type)
bricks@355:         self.found_tag_rules = False
bricks@511:         if tags_rules_url:
bricks@355:             self.found_tag_rules = True
bh@271: 
bh@271:     def packager_for_new_revision(self):
bh@271:         logging.info("Checking tags")
bh@271:         self.tag_url = None
bricks@355:         self.use_tag_rules = self.found_tag_rules
bh@271:         tag_url, tag_revision = self.tag_detector.newest_tag_revision()
bricks@349:         tag_rules_url, tag_rules_revision = self.tag_rules_detector.newest_tag_revision()
bh@271:         logging.info("Found: %s: %s", tag_url, tag_revision)
bricks@355:         logging.info("Found rules: %s: %s", tag_rules_url, tag_rules_revision)
bricks@349:         if self.use_tag_rules and tag_rules_url is None:
bricks@355:             self.use_tag_rules = False # maybe it's better to raise an exception
bh@271:         if tag_url is not None:
bricks@349:             if not self.use_tag_rules:
bricks@349:                 tag_rules_revision = self.rules_working_copy.last_changed_revision()
bricks@349:             revision = (tag_revision, tag_rules_revision)
bh@271:             logging.info("New revision is %s", revision)
bh@271:             if revision not in self.get_revision_numbers():
bh@271:                 logging.info("Revision %s has not been packaged yet",
bh@271:                              revision)
bh@271:                 self.tag_url = tag_url
bh@280:                 self.tag_revision = tag_revision
bricks@349:                 self.tag_rules_url = tag_rules_url
bricks@349:                 self.tag_rules_revision = tag_rules_revision
bh@286:                 tag_date, tag_change_count = self.tag_pkg_parameters(tag_url)
bh@293:                 pkg_revision = (self.pkg_revision_template
aheinecke@337:                                 % dict(pkg_revision=tag_change_count,
aheinecke@337:                                        rules_revision=revision[1]))
bh@286:                 return self.revision_packager_cls(self, tag=tag_url,
bh@286:                                                   pkg_revision=pkg_revision,
bh@286:                                                   pkg_date=tag_date,
bh@286:                                                   *revision)
bh@271:             else:
bh@271:                 logging.info("Revision %s has already been packaged.",
bh@271:                              revision)
bricks@357: 
bricks@357:         # tag has been built -> build trunk
bricks@357:         # don't use rules from tags for trunk
bricks@354:         self.use_tag_rules = False
bh@314:         return super(PackageTrack, self).packager_for_new_revision()
bh@271: 
bh@271:     def export_sources(self, to_dir):
bh@271:         if self.tag_url is not None:
bh@314:             logging.info("Exporting sources for tarball from %r to %r",
bh@314:                          self.tag_url, to_dir)
bh@314:             self.working_copy.export_tag(self.tag_url, to_dir,
bh@314:                                          revision=self.tag_revision)
bh@271:         else:
bh@314:             super(PackageTrack, self).export_sources(to_dir)
bh@286: 
bricks@349:     def copy_debian_directory(self, to_dir):
bricks@349:         if self.use_tag_rules:
bricks@349:             logging.info("Exporting debian package description from %s to %s",
bricks@349:                     self.tag_rules_url, to_dir)
bricks@349:             self.rules_working_copy.export_tag(self.tag_rules_url, to_dir)
bricks@349:         else:
bricks@349:             super(PackageTrack, self).copy_debian_directory(to_dir)
bricks@349: 
bh@286:     def tag_pkg_parameters(self, tag_url):
bh@286:         match = re.search(r"/enterprise[^.]*\.[^.]*\."
bh@286:                           r"(?P<date>[0-9]{8})\.(?P<baserev>[0-9]+)/",
bh@286:                           tag_url)
bh@286:         if match:
bh@286:             date = match.group("date")
bricks@350:             baserev = match.group("baserev")
bh@286:             xml_log = subversion.log_xml(tag_url, baserev)
bh@286:             revisions = subversion.extract_tag_revisions(xml_log)
bh@286:             tag_change_count = len(revisions)
bh@286:             return (date, tag_change_count)
bh@286:         else:
bh@286:             raise RuntimeError("Cannot determine tag parameters from %r"
bh@286:                                % tag_url)