rpm: add version parsing functions to pkg policy
authorMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Mon, 23 Apr 2012 09:51:08 +0000 (12:51 +0300)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Tue, 7 Jan 2014 14:21:28 +0000 (16:21 +0200)
Adds functions for version string generation and parsing. These are
intended for parsing version strings taken e.g. from rpm filename or
changelogs.

Also, take these new version parsing functions into use in the rpm gbp
scripts.

Signed-off-by: Markus Lehtonen <markus.lehtonen@linux.intel.com>
Signed-off-by: Ed Bartosh <eduard.bartosh@intel.com>
gbp/rpm/git.py
gbp/rpm/policy.py
gbp/scripts/buildpackage_rpm.py
gbp/scripts/import_orig_rpm.py
gbp/scripts/import_srpm.py
gbp/scripts/pq_rpm.py

index dac555cff05056794b7ed0f32239d105c4dfb007..55a412b381c39f26293bfc34b53669d200fe5d6f 100644 (file)
@@ -19,6 +19,7 @@ import re
 
 from gbp.git import GitRepository, GitRepositoryError
 from gbp.pkg.pristinetar import PristineTar
+from gbp.rpm.policy import RpmPkgPolicy
 
 class RpmGitRepository(GitRepository):
     """A git repository that holds the source of an RPM package"""
@@ -35,8 +36,10 @@ class RpmGitRepository(GitRepository):
 
         @param format: tag pattern
         @type format: C{str}
-        @param version: rpm version number
-        @type version: C{str}
+        @param version: rpm version components ('epoch', 'upstreamversion', 'release',...)
+        @type version: C{dict} of C{str}
+        @param vendor: distribution vendor
+        @type vendor: C{str}
         @return: sha1 of the commit the tag references to
         """
         tag = self.version_to_tag(format, version, vendor)
@@ -47,30 +50,41 @@ class RpmGitRepository(GitRepository):
 
     @staticmethod
     def version_to_tag(format, version, vendor="vendor"):
-        """Generate a tag from a given format and a version
+        """
+        Generate a tag from a given format and a version
+
+        @param format: tag pattern
+        @type format: C{str}
+        @param version: rpm version components ('epoch', 'upstreamversion', 'release',...)
+        @type version: C{dict} of C{str}
+        @param vendor: distribution vendor
+        @type vendor: C{str}
+        @return: version tag
 
-        >>> RpmGitRepository.version_to_tag("packaging/%(version)s", "0:0~0")
+        >>> RpmGitRepository.version_to_tag("packaging/%(version)s", dict(epoch='0', upstreamversion='0~0'))
         'packaging/0%0_0'
-        >>> RpmGitRepository.version_to_tag("%(vendor)s/v%(version)s", "1.0", "myvendor")
-        'myvendor/v1.0'
+        >>> RpmGitRepository.version_to_tag("%(vendor)s/v%(version)s", dict(upstreamversion='1.0', release='2'), "myvendor")
+        'myvendor/v1.0-2'
         """
-        return format % dict(version=RpmGitRepository._sanitize_version(version),
-                             vendor=vendor)
+        version_tag = format % dict(version,
+                                    version=RpmPkgPolicy.compose_full_version(version),
+                                    vendor=vendor)
+        return RpmGitRepository._sanitize_tag(version_tag)
 
     @staticmethod
-    def _sanitize_version(version):
+    def _sanitize_tag(tag):
         """sanitize a version so git accepts it as a tag
 
-        >>> RpmGitRepository._sanitize_version("0.0.0")
+        >>> RpmGitRepository._sanitize_tag("0.0.0")
         '0.0.0'
-        >>> RpmGitRepository._sanitize_version("0.0~0")
+        >>> RpmGitRepository._sanitize_tag("0.0~0")
         '0.0_0'
-        >>> RpmGitRepository._sanitize_version("0:0.0")
+        >>> RpmGitRepository._sanitize_tag("0:0.0")
         '0%0.0'
-        >>> RpmGitRepository._sanitize_version("0%0~0")
+        >>> RpmGitRepository._sanitize_tag("0%0~0")
         '0%0_0'
         """
-        return version.replace('~', '_').replace(':', '%')
+        return tag.replace('~', '_').replace(':', '%')
 
     @property
     def pristine_tar_branch(self):
index e61a4972b31cd4731dd22ab03d4e28d17d530eb9..9fbf5632f517f54dba0c2c4e28997a86d0d6cfbb 100644 (file)
@@ -67,3 +67,73 @@ class RpmPkgPolicy(PkgPolicy):
             return True
         return False
 
+    @classmethod
+    def split_full_version(cls, version):
+        """
+        Parse full version string and split it into individual "version
+        components", i.e. upstreamversion, epoch and release
+
+        @param version: full version of a package
+        @type version: C{str}
+        @return: individual version components
+        @rtype: C{dict}
+
+        >>> RpmPkgPolicy.split_full_version("1")
+        {'release': None, 'epoch': None, 'upstreamversion': '1'}
+        >>> RpmPkgPolicy.split_full_version("1.2.3-5.3")
+        {'release': '5.3', 'epoch': None, 'upstreamversion': '1.2.3'}
+        >>> RpmPkgPolicy.split_full_version("3:1.2.3")
+        {'release': None, 'epoch': '3', 'upstreamversion': '1.2.3'}
+        >>> RpmPkgPolicy.split_full_version("3:1-0")
+        {'release': '0', 'epoch': '3', 'upstreamversion': '1'}
+        """
+        epoch = None
+        upstreamversion = None
+        release = None
+
+        e_vr = version.split(":", 1)
+        if len(e_vr) == 1:
+            v_r = e_vr[0].split("-", 1)
+        else:
+            epoch = e_vr[0]
+            v_r = e_vr[1].split("-", 1)
+        upstreamversion = v_r[0]
+        if len(v_r) > 1:
+            release = v_r[1]
+
+        return {'epoch': epoch,
+                'upstreamversion': upstreamversion,
+                'release': release}
+
+    @classmethod
+    def compose_full_version(cls, evr):
+        """
+        Compose a full version string from individual "version components",
+        i.e. epoch, version and release
+
+        @param evr: dict of version components
+        @type evr: C{dict} of C{str}
+        @return: full version
+        @rtype: C{str}
+
+        >>> RpmPkgPolicy.compose_full_version({'epoch': '', 'upstreamversion': '1.0'})
+        '1.0'
+        >>> RpmPkgPolicy.compose_full_version({'epoch': '2', 'upstreamversion': '1.0', 'release': None})
+        '2:1.0'
+        >>> RpmPkgPolicy.compose_full_version({'epoch': None, 'upstreamversion': '1', 'release': '0'})
+        '1-0'
+        >>> RpmPkgPolicy.compose_full_version({'epoch': '2', 'upstreamversion': '1.0', 'release': '2.3'})
+        '2:1.0-2.3'
+        >>> RpmPkgPolicy.compose_full_version({'epoch': '2', 'upstreamversion': '', 'release': '2.3'})
+        """
+        if 'upstreamversion' in evr and evr['upstreamversion']:
+            version = ""
+            if 'epoch' in evr and evr['epoch']:
+                version += "%s:" % evr['epoch']
+            version += evr['upstreamversion']
+            if 'release' in evr and evr['release']:
+                version += "-%s" % evr['release']
+            if version:
+                return version
+        return None
+
index 8f97bd8bd6ae681cc51e87274e8bb4f899a99a31..4994559220dc8ac94fb5dd30ae5b3b9d295d5ac1 100755 (executable)
@@ -147,7 +147,7 @@ def pristine_tar_build_orig(repo, orig_file, output_dir, options):
 def get_upstream_tree(repo, spec, options):
     """Determine the upstream tree from the given options"""
     if options.upstream_tree.upper() == 'TAG':
-        upstream_tree = repo.version_to_tag(options.upstream_tag, spec.version, vendor="Upstream")
+        upstream_tree = repo.version_to_tag(options.upstream_tag, dict(upstreamversion=spec.version), "Upstream")
     elif options.upstream_tree.upper() == 'BRANCH':
         if not repo.has_branch(options.upstream_branch):
             raise GbpError("%s is not a valid branch" % options.upstream_branch)
@@ -472,7 +472,7 @@ def main(argv):
         # Tag (note: tags the exported version)
         if options.tag or options.tag_only:
             gbp.log.info("Tagging %s" % spec.version)
-            tag = repo.version_to_tag(options.packaging_tag, spec.version, vendor=options.vendor)
+            tag = repo.version_to_tag(options.packaging_tag, dict(upstreamversion=spec.version), options.vendor)
             if options.retag and repo.has_tag(tag):
                 repo.delete_tag(tag)
             repo.create_tag(name=tag, msg="%s release %s" % (options.vendor, spec.version),
index 7dad3bc80cef5a0e9f90c03909a6579bb7c0d46a..44368de05bd572f695d5f431d8df56ac9f40171f 100755 (executable)
@@ -266,7 +266,7 @@ def main(argv):
                 gbp.log.info("Pristine-tar: commiting %s" % pristine_orig)
                 repo.pristine_tar.commit(pristine_orig, options.upstream_branch)
 
-            tag = repo.version_to_tag(options.upstream_tag, version, vendor="Upstream")
+            tag = repo.version_to_tag(options.upstream_tag, dict(upstreamversion=version), "Upstream")
             repo.create_tag(name=tag,
                             msg="Upstream version %s" % version,
                             commit=commit,
index 50a04d042b27d42aab8b6c2a470bfbfef0d2fe1c..a3f40b4e296b31a25086e2003d7ad8b87d651716 100755 (executable)
@@ -32,6 +32,7 @@ import urllib2
 import gbp.command_wrappers as gbpc
 from gbp.rpm import (parse_srpm, SrcRpmFile, SpecFile, guess_spec, NoSpecError,
                      parse_spec, RpmUpstreamSource)
+from gbp.rpm.policy import RpmPkgPolicy
 from gbp.rpm.git import (RpmGitRepository, GitRepositoryError)
 from gbp.git.modifier import GitModifier
 from gbp.config import GbpOptionParserRpm, GbpOptionGroup, no_upstream_branch_msg
@@ -87,8 +88,8 @@ def committer_from_author(author, options):
 def move_tag_stamp(repo, format, version, vendor):
     "Move tag out of the way appending the current timestamp"
     old = repo.version_to_tag(format, version, vendor)
-    timestamped = "%s~%s" % (version, int(time.time()))
-    new = repo.version_to_tag(format, timestamped, vendor)
+    new = repo.version_to_tag('%s~%d' % (format, int(time.time())),
+                              version, vendor)
     repo.move_tag(old, new)
 
 
@@ -193,7 +194,7 @@ def main(argv):
                     spec = parse_spec(pkg)
 
                 pkgname = spec.name
-                pkgver = "%s-%s" % (spec.version, spec.release)
+                pkgver = dict(upstreamversion=spec.version, release=spec.release)
                 upstream_version = spec.version
                 packager = spec.packager
                 unpacked = True
@@ -202,7 +203,7 @@ def main(argv):
                 dirs['src'] = os.path.abspath(os.path.dirname(pkg))
                 src = parse_srpm(srpm)
                 pkgname = src.name
-                pkgver = src.version
+                pkgver = dict(upstreamversion=src.version)
                 upstream_version = src.upstream_version
                 packager = src.packager
                 unpacked = False
@@ -268,12 +269,12 @@ def main(argv):
                 upstream = None
 
             format = [(options.upstream_tag, "Upstream"), (options.packaging_tag, options.vendor)][options.native]
-            tag = repo.version_to_tag(format[0], upstream_version, options.vendor)
+            tag = repo.version_to_tag(format[0], dict(upstreamversion=upstream_version), options.vendor)
 
             if repo.find_version(options.packaging_tag, pkgver, options.vendor):
-                gbp.log.warn("Version %s already imported." % pkgver)
+                gbp.log.warn("Version %s already imported." % RpmPkgPolicy.compose_full_version(pkgver))
                 if options.allow_same_version:
-                    gbp.log.info("Moving tag of version '%s' since import forced" % pkgver)
+                    gbp.log.info("Moving tag of version '%s' since import forced" % RpmPkgPolicy.compose_full_version(pkgver))
                     move_tag_stamp(repo, options.packaging_tag, pkgver, options.vendor)
                 else:
                     raise SkipImport
@@ -295,7 +296,7 @@ def main(argv):
 
             # Import upstream sources
             if upstream:
-                upstream_commit = repo.find_version(format[0], upstream_version, options.vendor)
+                upstream_commit = repo.find_version(format[0], dict(upstreamversion=upstream_version), options.vendor)
                 if not upstream_commit:
                     gbp.log.info("Tag %s not found, importing %s tarball" % (tag, format[1]))
 
@@ -342,7 +343,7 @@ def main(argv):
                         raise GbpError
 
                 tag = repo.version_to_tag(options.packaging_tag, pkgver, options.vendor)
-                msg = "%s release %s" % (options.vendor, pkgver)
+                msg = "%s release %s" % (options.vendor, RpmPkgPolicy.compose_full_version(pkgver))
 
                 if options.orphan_packaging or not upstream:
                     parents = []
@@ -411,7 +412,7 @@ def main(argv):
             gbpc.RemoveTree(dirs[d])()
 
     if not ret and not skipped:
-        gbp.log.info("Version '%s' imported under '%s'" % (pkgver, pkgname))
+        gbp.log.info("Version '%s' imported under '%s'" % (RpmPkgPolicy.compose_full_version(pkgver), pkgname))
     return ret
 
 if __name__ == '__main__':
index 9077ea96de4f28123b04f46dd81d2afc04621d9c..ff70c49f8d0d3866efc2f417f096bf766360d879 100755 (executable)
@@ -142,7 +142,7 @@ def export_patches(repo, branch, options):
         raise GbpError, "Can't parse spec"
 
     # Find upstream version
-    upstream_commit = repo.find_version(options.upstream_tag, spec.version, vendor="Upstream")
+    upstream_commit = repo.find_version(options.upstream_tag, dict(upstreamversion=spec.version), "Upstream")
     if not upstream_commit:
         raise GbpError, ("Couldn't find upstream version %s. Don't know on what base to import." % spec.version)
 
@@ -233,7 +233,7 @@ def import_spec_patches(repo, branch, options):
         raise GbpError, "Can't parse spec"
 
     # Find upstream version
-    commit = repo.find_version(options.upstream_tag, spec.version, vendor="Upstream")
+    commit = repo.find_version(options.upstream_tag, dict(upstreamversion=spec.version), "Upstream")
     if commit:
         commits=[commit]
     else:
@@ -295,7 +295,7 @@ def rebase_pq(repo, branch, options):
         raise GbpError, "Can't parse spec"
 
     # Find upstream version
-    upstream_commit = repo.find_version(options.upstream_tag, spec.version, vendor="Upstream")
+    upstream_commit = repo.find_version(options.upstream_tag, dict(upstreamversion=spec.version), "Upstream")
     if not upstream_commit:
         raise GbpError, ("Couldn't find upstream version %s. Don't know on what base to import." % spec.version)