mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Add bump_version.py
This commit is contained in:
17
utils/CHANGES_template
Normal file
17
utils/CHANGES_template
Normal file
@@ -0,0 +1,17 @@
|
||||
Release x.y.z (in development)
|
||||
==============================
|
||||
|
||||
Incompatible changes
|
||||
--------------------
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
Features added
|
||||
--------------
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
Testing
|
||||
--------
|
||||
170
utils/bump_vesion.py
Executable file
170
utils/bump_vesion.py
Executable file
@@ -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()
|
||||
@@ -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`
|
||||
|
||||
Reference in New Issue
Block a user