summaryrefslogtreecommitdiff
path: root/extra/release/bump_version.py
diff options
context:
space:
mode:
Diffstat (limited to 'extra/release/bump_version.py')
-rwxr-xr-xextra/release/bump_version.py166
1 files changed, 166 insertions, 0 deletions
diff --git a/extra/release/bump_version.py b/extra/release/bump_version.py
new file mode 100755
index 00000000..02d8727c
--- /dev/null
+++ b/extra/release/bump_version.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python
+
+from __future__ import absolute_import
+from __future__ import with_statement
+
+import errno
+import os
+import re
+import sys
+import subprocess
+
+from contextlib import contextmanager
+from tempfile import NamedTemporaryFile
+
+rq = lambda s: s.strip("\"'")
+
+
+def cmd(*args):
+ return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0]
+
+
+@contextmanager
+def no_enoent():
+ try:
+ yield
+ except OSError, exc:
+ if exc.errno != errno.ENOENT:
+ raise
+
+
+class StringVersion(object):
+
+ def decode(self, s):
+ s = rq(s)
+ text = ""
+ major, minor, release = s.split(".")
+ if not release.isdigit():
+ pos = release.index(re.split("\d+", release)[1][0])
+ release, text = release[:pos], release[pos:]
+ return int(major), int(minor), int(release), text
+
+ def encode(self, v):
+ return ".".join(map(str, v[:3])) + v[3]
+to_str = StringVersion().encode
+from_str = StringVersion().decode
+
+
+class TupleVersion(object):
+
+ def decode(self, s):
+ v = list(map(rq, s.split(", ")))
+ return (tuple(map(int, v[0:3])) +
+ tuple(["".join(v[3:])]))
+
+ def encode(self, v):
+ v = list(v)
+
+ def quote(lit):
+ if isinstance(lit, basestring):
+ return '"%s"' % (lit, )
+ return str(lit)
+
+ if not v[-1]:
+ v.pop()
+ return ", ".join(map(quote, v))
+
+
+class VersionFile(object):
+
+ def __init__(self, filename):
+ self.filename = filename
+ self._kept = None
+
+ def _as_orig(self, version):
+ return self.wb % {"version": self.type.encode(version),
+ "kept": self._kept}
+
+ def write(self, version):
+ pattern = self.regex
+ with no_enoent():
+ with NamedTemporaryFile() as dest:
+ with open(self.filename) as orig:
+ for line in orig:
+ if pattern.match(line):
+ dest.write(self._as_orig(version))
+ else:
+ dest.write(line)
+ os.rename(dest.name, self.filename)
+
+ def parse(self):
+ pattern = self.regex
+ gpos = 0
+ with open(self.filename) as fh:
+ for line in fh:
+ m = pattern.match(line)
+ if m:
+ if "?P<keep>" in pattern.pattern:
+ self._kept, gpos = m.groupdict()["keep"], 1
+ return self.type.decode(m.groups()[gpos])
+
+
+class PyVersion(VersionFile):
+ regex = re.compile(r'^VERSION\s*=\s*\((.+?)\)')
+ wb = "VERSION = (%(version)s)\n"
+ type = TupleVersion()
+
+
+class SphinxVersion(VersionFile):
+ regex = re.compile(r'^:[Vv]ersion:\s*(.+?)$')
+ wb = ':Version: %(version)s\n'
+ type = StringVersion()
+
+
+class CPPVersion(VersionFile):
+ regex = re.compile(r'^\#\s*define\s*(?P<keep>\w*)VERSION\s+(.+)')
+ wb = '#define %(kept)sVERSION "%(version)s"\n'
+ type = StringVersion()
+
+
+_filetype_to_type = {"py": PyVersion,
+ "rst": SphinxVersion,
+ "c": CPPVersion,
+ "h": CPPVersion}
+
+def filetype_to_type(filename):
+ _, _, suffix = filename.rpartition(".")
+ return _filetype_to_type[suffix](filename)
+
+
+def bump(*files, **kwargs):
+ version = kwargs.get("version")
+ files = [filetype_to_type(f) for f in files]
+ versions = [v.parse() for v in files]
+ current = list(reversed(sorted(versions)))[0] # find highest
+
+ if version:
+ next = from_str(version)
+ else:
+ major, minor, release, text = current
+ if text:
+ raise Exception("Can't bump alpha releases")
+ next = (major, minor, release + 1, text)
+
+ print("Bump version from %s -> %s" % (to_str(current), to_str(next)))
+
+ for v in files:
+ print(" writing %r..." % (v.filename, ))
+ v.write(next)
+
+ print(cmd("git", "commit", "-m", "Bumps version to %s" % (to_str(next), ),
+ *[f.filename for f in files]))
+ print(cmd("git", "tag", "v%s" % (to_str(next), )))
+
+
+def main(argv=sys.argv, version=None):
+ if not len(argv) > 1:
+ print("Usage: distdir [docfile] -- <custom version>")
+ sys.exit(0)
+ if "--" in argv:
+ c = argv.index('--')
+ version = argv[c + 1]
+ argv = argv[:c]
+ bump(*argv[1:], version=version)
+
+if __name__ == "__main__":
+ main()