|
|
@ -10,6 +10,7 @@ import subprocess |
|
|
|
import traceback |
|
|
|
import unittest |
|
|
|
import random |
|
|
|
from cStringIO import StringIO |
|
|
|
|
|
|
|
|
|
|
|
def main(args=sys.argv[1:]): |
|
|
@ -34,7 +35,9 @@ def main(args=sys.argv[1:]): |
|
|
|
# Top-level flow: |
|
|
|
def main_logged(release, releaseprev): |
|
|
|
verify_releaseprev_tag(releaseprev) |
|
|
|
verify_git_clean_master() |
|
|
|
initialize_git(release) |
|
|
|
patch_version_in_files(release, releaseprev) |
|
|
|
|
|
|
|
raise NotImplementedError(main_logged) |
|
|
|
|
|
|
|
|
|
|
@ -81,7 +84,7 @@ def verify_releaseprev_tag(releaseprev): |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
def verify_git_clean_master(): |
|
|
|
def initialize_git(release): |
|
|
|
junk = sh_out('git', 'status', '--porcelain') |
|
|
|
if junk.strip(): |
|
|
|
raise SystemExit('There are uncommitted changes:\n' + junk) |
|
|
@ -94,8 +97,18 @@ def verify_git_clean_master(): |
|
|
|
), |
|
|
|
) |
|
|
|
|
|
|
|
out = sh_out('git', 'pull', '--ff-only') |
|
|
|
logging.debug('+ git pull --ff-only\n%s', out) |
|
|
|
logging.info('Pulling to latest master.') |
|
|
|
sh_out_logged('git', 'pull', '--ff-only') |
|
|
|
|
|
|
|
branch = 'release-' + release.vtext |
|
|
|
logging.info('Creating release branch: %r', branch) |
|
|
|
sh_out_logged('git', 'checkout', '-b', branch) |
|
|
|
return branch |
|
|
|
|
|
|
|
|
|
|
|
def patch_version_in_files(release, releaseprev): |
|
|
|
patch_README(release, releaseprev) |
|
|
|
patch_clientversion_h(release, releaseprev) |
|
|
|
|
|
|
|
|
|
|
|
# Helper code: |
|
|
@ -106,6 +119,36 @@ def chdir_to_repo(repo): |
|
|
|
os.chdir(repo) |
|
|
|
|
|
|
|
|
|
|
|
def patch_README(release, releaseprev): |
|
|
|
with PathPatcher('README.md') as (inf, outf): |
|
|
|
firstline = inf.readline() |
|
|
|
assert firstline == 'Zcash {}\n'.format(releaseprev.novtext), \ |
|
|
|
repr(firstline) |
|
|
|
|
|
|
|
outf.write('Zcash {}\n'.format(release.novtext)) |
|
|
|
outf.write(inf.read()) |
|
|
|
|
|
|
|
|
|
|
|
def patch_clientversion_h(release, releaseprev): |
|
|
|
rgx = re.compile( |
|
|
|
r'^(#define CLIENT_VERSION_(MAJOR|MINOR|REVISION|BUILD)) \d+$' |
|
|
|
) |
|
|
|
with PathPatcher('src/clientversion.h') as (inf, outf): |
|
|
|
for line in inf: |
|
|
|
m = rgx.match(line) |
|
|
|
if m: |
|
|
|
prefix, label = m.groups() |
|
|
|
repl = { |
|
|
|
'MAJOR': release.major, |
|
|
|
'MINOR': release.minor, |
|
|
|
'REVISION': release.patch, |
|
|
|
'BUILD': release.build, |
|
|
|
}[label] |
|
|
|
outf.write('{} {}\n'.format(prefix, repl)) |
|
|
|
else: |
|
|
|
outf.write(line) |
|
|
|
|
|
|
|
|
|
|
|
def initialize_logging(): |
|
|
|
TIME_FMT = '%Y-%m-%dT%H:%M:%S' |
|
|
|
logname = './zcash-make-release.{}.log'.format(time.strftime(TIME_FMT)) |
|
|
@ -134,6 +177,12 @@ def sh_out(*args): |
|
|
|
return subprocess.check_output(args) |
|
|
|
|
|
|
|
|
|
|
|
def sh_out_logged(*args): |
|
|
|
out = sh_out(*args) |
|
|
|
logging.debug('Output:\n%s', out) |
|
|
|
return out |
|
|
|
|
|
|
|
|
|
|
|
class Version (object): |
|
|
|
'''A release version.''' |
|
|
|
|
|
|
@ -175,12 +224,22 @@ class Version (object): |
|
|
|
self.betarc = betarc |
|
|
|
self.hotfix = hotfix |
|
|
|
|
|
|
|
self.vtext = 'v{}.{}.{}'.format(major, minor, patch) |
|
|
|
if hotfix is not None: |
|
|
|
self.vtext += '-{}{}'.format( |
|
|
|
'' if betarc is None else betarc, |
|
|
|
hotfix, |
|
|
|
) |
|
|
|
self.novtext = '{}.{}.{}'.format(major, minor, patch) |
|
|
|
|
|
|
|
if hotfix is None: |
|
|
|
self.build = 50 |
|
|
|
else: |
|
|
|
assert hotfix > 0, hotfix |
|
|
|
if betarc is None: |
|
|
|
assert hotfix < 50, hotfix |
|
|
|
self.build = 50 + hotfix |
|
|
|
self.novtext += '-{}'.format(hotfix) |
|
|
|
else: |
|
|
|
assert hotfix < 26, hotfix |
|
|
|
self.novtext += '-{}{}'.format(betarc, hotfix) |
|
|
|
self.build = {'beta': 0, 'rc': 25}[betarc] + hotfix - 1 |
|
|
|
|
|
|
|
self.vtext = 'v' + self.novtext |
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
return '<Version {}>'.format(self.vtext) |
|
|
@ -203,26 +262,49 @@ class Version (object): |
|
|
|
return cmp(self._sort_tup(), other._sort_tup()) |
|
|
|
|
|
|
|
|
|
|
|
class PathPatcher (object): |
|
|
|
def __init__(self, path): |
|
|
|
self._path = path |
|
|
|
|
|
|
|
def __enter__(self): |
|
|
|
logging.info('Patching %r', self._path) |
|
|
|
self._inf = file(self._path, 'r') |
|
|
|
self._outf = StringIO() |
|
|
|
return (self._inf, self._outf) |
|
|
|
|
|
|
|
def __exit__(self, et, ev, tb): |
|
|
|
if (et, ev, tb) == (None, None, None): |
|
|
|
self._inf.close() |
|
|
|
with file(self._path, 'w') as f: |
|
|
|
f.write(self._outf.getvalue()) |
|
|
|
|
|
|
|
|
|
|
|
# Unit Tests |
|
|
|
class TestVersion (unittest.TestCase): |
|
|
|
ValidVersions = [ |
|
|
|
ValidVersionsAndBuilds = [ |
|
|
|
# These are taken from: git tag --list | grep '^v1' |
|
|
|
'v1.0.0-beta1', |
|
|
|
'v1.0.0-beta2', |
|
|
|
'v1.0.0-rc1', |
|
|
|
'v1.0.0-rc2', |
|
|
|
'v1.0.0-rc3', |
|
|
|
'v1.0.0-rc4', |
|
|
|
'v1.0.0', |
|
|
|
'v1.0.1', |
|
|
|
'v1.0.2', |
|
|
|
'v1.0.3', |
|
|
|
'v1.0.4', |
|
|
|
'v1.0.5', |
|
|
|
'v1.0.6', |
|
|
|
'v1.0.7-1', |
|
|
|
'v1.0.8', |
|
|
|
'v1.0.8-1', |
|
|
|
('v1.0.0-beta1', 0), |
|
|
|
('v1.0.0-beta2', 1), |
|
|
|
('v1.0.0-rc1', 25), |
|
|
|
('v1.0.0-rc2', 26), |
|
|
|
('v1.0.0-rc3', 27), |
|
|
|
('v1.0.0-rc4', 28), |
|
|
|
('v1.0.0', 50), |
|
|
|
('v1.0.1', 50), |
|
|
|
('v1.0.2', 50), |
|
|
|
('v1.0.3', 50), |
|
|
|
('v1.0.4', 50), |
|
|
|
('v1.0.5', 50), |
|
|
|
('v1.0.6', 50), |
|
|
|
('v1.0.7-1', 51), |
|
|
|
('v1.0.8', 50), |
|
|
|
('v1.0.8-1', 51), |
|
|
|
] |
|
|
|
|
|
|
|
ValidVersions = [ |
|
|
|
v |
|
|
|
for (v, _) |
|
|
|
in ValidVersionsAndBuilds |
|
|
|
] |
|
|
|
|
|
|
|
def test_arg_parse_and_vtext_identity(self): |
|
|
@ -259,6 +341,11 @@ class TestVersion (unittest.TestCase): |
|
|
|
vec.sort() |
|
|
|
self.assertEqual(vec, expected) |
|
|
|
|
|
|
|
def test_build_nums(self): |
|
|
|
for (text, expected) in self.ValidVersionsAndBuilds: |
|
|
|
version = Version.parse_arg(text) |
|
|
|
self.assertEqual(version.build, expected) |
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
if len(sys.argv) == 2 and sys.argv[1] == '--help': |
|
|
|