summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakeshi KOMIYA <i.tkomiya@gmail.com>2017-01-21 19:45:09 +0900
committerTakeshi KOMIYA <i.tkomiya@gmail.com>2017-01-21 19:45:35 +0900
commit3f17bebecbd5bef6d7425a17e813090cff295730 (patch)
treeb6fbb948a2759d6d8d75c3670719574f17ecec86
parent765b00fc306c25c3bb1a16e1ea7c046f759f251e (diff)
downloadsphinx-git-3f17bebecbd5bef6d7425a17e813090cff295730.tar.gz
Add bump_version.py
-rw-r--r--utils/CHANGES_template17
-rwxr-xr-xutils/bump_vesion.py170
-rw-r--r--utils/release-checklist7
3 files changed, 191 insertions, 3 deletions
diff --git a/utils/CHANGES_template b/utils/CHANGES_template
new file mode 100644
index 000000000..344a49eae
--- /dev/null
+++ b/utils/CHANGES_template
@@ -0,0 +1,17 @@
+Release x.y.z (in development)
+==============================
+
+Incompatible changes
+--------------------
+
+Deprecated
+----------
+
+Features added
+--------------
+
+Bugs fixed
+----------
+
+Testing
+--------
diff --git a/utils/bump_vesion.py b/utils/bump_vesion.py
new file mode 100755
index 000000000..617c33c0c
--- /dev/null
+++ b/utils/bump_vesion.py
@@ -0,0 +1,170 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+
+import os
+import re
+import sys
+from datetime import datetime
+from contextlib import contextmanager
+
+script_dir = os.path.dirname(__file__)
+package_dir = os.path.abspath(os.path.join(script_dir, '..'))
+
+RELEASE_TYPE = {'a': 'alpha', 'b': 'beta'}
+
+
+def stringify_version(version_info):
+ if version_info[2] == 0:
+ return '.'.join(str(v) for v in version_info[:2])
+ else:
+ return '.'.join(str(v) for v in version_info[:3])
+
+
+def bump_version(path, version_info):
+ version = stringify_version(version_info)
+ release = version
+ if version_info[3] != 'final':
+ version += '+'
+
+ with open(path, 'r+') as f:
+ body = f.read()
+ body = re.sub("(?<=__version__ = ')[^']+", version, body)
+ body = re.sub("(?<=__released__ = ')[^']+", release, body)
+ body = re.sub("(?<=version_info = )\(.*\)", str(version_info), body)
+
+ f.seek(0)
+ f.truncate(0)
+ f.write(body)
+
+
+def parse_version(version):
+ matched = re.search('^(\d+)\.(\d+)$', version)
+ if matched:
+ major, minor = matched.groups()
+ return (int(major), int(minor), 0, 'final', 0)
+
+ matched = re.search('^(\d+)\.(\d+)\.(\d+)$', version)
+ if matched:
+ major, minor, rev = matched.groups()
+ return (int(major), int(minor), int(rev), 'final', 0)
+
+ matched = re.search('^(\d+)\.(\d+)\s*(a|b|alpha|beta)(\d+)$', version)
+ if matched:
+ major, minor, typ, relver = matched.groups()
+ release = RELEASE_TYPE.get(typ, typ)
+ return (int(major), int(minor), 0, release, int(relver))
+
+ matched = re.search('^(\d+)\.(\d+)\.(\d+)\s*(a|b|alpha|beta)(\d+)$', version)
+ if matched:
+ major, minor, rev, typ, relver = matched.groups()
+ release = RELEASE_TYPE.get(typ, typ)
+ return (int(major), int(minor), int(rev), release, int(relver))
+
+ raise RuntimeError('Unknown vesion: %s' % version)
+
+
+class Skip(Exception):
+ pass
+
+
+@contextmanager
+def processing(message):
+ try:
+ print(message + ' ... ', end='')
+ yield
+ except Skip as exc:
+ print('skip: %s' % exc)
+ except:
+ print('error')
+ raise
+ else:
+ print('done')
+
+
+class Changes(object):
+ def __init__(self, path):
+ self.path = path
+ self.fetch_version()
+
+ def fetch_version(self):
+ with open(self.path) as f:
+ version = f.readline().strip()
+ matched = re.search('^Release (.*) \((.*)\)$', version)
+ if matched is None:
+ raise RuntimeError('Unknown CHANGES format: %s' % version)
+
+ self.version, self.release_date = matched.groups()
+ self.version_info = parse_version(self.version)
+ if self.release_date == 'in development':
+ self.in_development = True
+ else:
+ self.in_development = False
+
+ def finalize_release_date(self):
+ release_date = datetime.now().strftime('%b %d, %Y')
+ heading = 'Release %s (released %s)' % (self.version, release_date)
+
+ with open(self.path, 'r+') as f:
+ f.readline() # skip first two lines
+ f.readline()
+ body = f.read()
+
+ f.seek(0)
+ f.truncate(0)
+ f.write(heading + '\n')
+ f.write('=' * len(heading) + '\n')
+ f.write(body)
+
+ def add_release(self, version_info):
+ if version_info[-2:] in (('beta', 0), ('final', 0)):
+ version = stringify_version(version_info)
+ else:
+ reltype = version_info[3]
+ version = '%s %s%s' % (stringify_version(version_info),
+ RELEASE_TYPE.get(reltype, reltype),
+ version_info[4] or '')
+ heading = 'Release %s (in development)' % version
+
+ with open(os.path.join(script_dir, 'CHANGES_template')) as f:
+ f.readline() # skip first two lines
+ f.readline()
+ tmpl = f.read()
+
+ with open(self.path, 'r+') as f:
+ body = f.read()
+
+ f.seek(0)
+ f.truncate(0)
+ f.write(heading + '\n')
+ f.write('=' * len(heading) + '\n')
+ f.write(tmpl)
+ f.write('\n')
+ f.write(body)
+
+
+def main():
+ if len(sys.argv) != 2:
+ print("bump_version.py [version]")
+ return -1
+
+ version_info = parse_version(sys.argv[-1])
+
+ with processing("Rewriting sphinx/__init__.py"):
+ bump_version(os.path.join(package_dir, 'sphinx/__init__.py'), version_info)
+
+ with processing('Rewriting CHANGES'):
+ changes = Changes(os.path.join(package_dir, 'CHANGES'))
+ if changes.version_info == version_info:
+ if changes.in_development:
+ changes.finalize_release_date()
+ else:
+ raise Skip('version not changed')
+ else:
+ if changes.in_development:
+ print('WARNING: last version is not released yet: %s' % changes.version)
+ changes.add_release(version_info)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/utils/release-checklist b/utils/release-checklist
index c4c9f48bf..610ab9d19 100644
--- a/utils/release-checklist
+++ b/utils/release-checklist
@@ -9,8 +9,8 @@ Release checklist
* Run `(cd sphinx/locale; tx pull -a -f)`
* Run `python setup.py compile_catalog`
-* Update version info in sphinx/__init__.py
-* Update release date in CHANGES
+* `python utils/bump_version.py x.y.z`
+* Check diff by `git diff`
* `git commit -am 'Bump to x.y.z final'`
* `make clean`
* `python setup.py compile_grammar`
@@ -21,7 +21,8 @@ Release checklist
* `git push origin stable --tags`
* open https://readthedocs.org/dashboard/sphinx/versions/ and enable the released version
* Add new version/milestone to tracker categories
-* Update version info, add new CHANGES entry for next version
+* `python utils/bump_version.py a.b.cb0` (ex. 1.5.3b0)
+* Check diff by `git diff`
* `git commit -am 'Bump version'`
* `git push origin stable`
* `git checkout master`