#!/usr/bin/env python3 ######################################################################## # Generates a new release. ######################################################################## import sys import re import subprocess import io import os import fileinput if sys.version_info < (3, 0): sys.stdout.write("Sorry, requires Python 3.x or better\n") sys.exit(1) def colored(r, g, b, text): return f"\033[38;2;{r};{g};{b}m{text} \033[38;2;255;255;255m" def extractnumbers(s): return tuple(map(int, re.findall(r"(\d+)\.(\d+)\.(\d+)", str(s))[0])) def toversionstring(major, minor, rev): return f"{major}.{minor}.{rev}" print("Calling git rev-parse --abbrev-ref HEAD") pipe = subprocess.Popen( ["git", "rev-parse", "--abbrev-ref", "HEAD"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) branchresult = pipe.communicate()[0].decode().strip() if branchresult != "main": print( colored( 255, 0, 0, f"We recommend that you release on main, you are on '{branchresult}'", ) ) ret = subprocess.call(["git", "remote", "update"]) if ret != 0: sys.exit(ret) print("Calling git log HEAD.. --oneline") pipe = subprocess.Popen( ["git", "log", "HEAD..", "--oneline"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) uptodateresult = pipe.communicate()[0].decode().strip() if len(uptodateresult) != 0: print(uptodateresult) sys.exit(-1) pipe = subprocess.Popen( ["git", "rev-parse", "--show-toplevel"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) maindir = pipe.communicate()[0].decode().strip() scriptlocation = os.path.dirname(os.path.abspath(__file__)) print(f"repository: {maindir}") pipe = subprocess.Popen( ["git", "describe", "--abbrev=0", "--tags"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) versionresult = pipe.communicate()[0].decode().strip() print(f"last version: {versionresult}") try: currentv = extractnumbers(versionresult) except: currentv = [0, 0, 0] if len(sys.argv) != 2: nextv = (currentv[0], currentv[1], currentv[2] + 1) print(f"please specify version number, e.g. {toversionstring(*nextv)}") sys.exit(-1) try: newversion = extractnumbers(sys.argv[1]) print(newversion) except: print(f"can't parse version number {sys.argv[1]}") sys.exit(-1) print("checking that new version is valid") if newversion[0] != currentv[0]: assert newversion[0] == currentv[0] + 1 assert newversion[1] == 0 assert newversion[2] == 0 elif newversion[1] != currentv[1]: assert newversion[1] == currentv[1] + 1 assert newversion[2] == 0 else: assert newversion[2] == currentv[2] + 1 atleastminor = (currentv[0] != newversion[0]) or (currentv[1] != newversion[1]) newmajorversionstring = str(newversion[0]) newminorversionstring = str(newversion[1]) newpatchversionstring = str(newversion[2]) newversionstring = f"{newversion[0]}.{newversion[1]}.{newversion[2]}" cmakefile = f"{maindir}{os.sep}CMakeLists.txt" for line in fileinput.input(cmakefile, inplace=1, backup=".bak"): line = re.sub( r"project\(fast_float VERSION \d+\.\d+\.\d+ LANGUAGES CXX\)", f"project(fast_float VERSION {newversionstring} LANGUAGES CXX)", line.rstrip(), ) print(line) print(f"modified {cmakefile}, a backup was made") versionfilerel = f"{os.sep}include{os.sep}fast_float{os.sep}float_common.h" versionfile = f"{maindir}{versionfilerel}" for line in fileinput.input(versionfile, inplace=1, backup=".bak"): line = re.sub( r"#define FASTFLOAT_VERSION_MAJOR \d+", f"#define FASTFLOAT_VERSION_MAJOR {newmajorversionstring}", line.rstrip(), ) line = re.sub( r"#define FASTFLOAT_VERSION_MINOR \d+", f"#define FASTFLOAT_VERSION_MINOR {newminorversionstring}", line.rstrip(), ) line = re.sub( r"#define FASTFLOAT_VERSION_PATCH \d+", f"#define FASTFLOAT_VERSION_PATCH {newpatchversionstring}", line.rstrip(), ) print(line) print(f"{versionfile} modified") readmefile = f"{maindir}{os.sep}README.md" for line in fileinput.input(readmefile, inplace=1, backup=".bak"): line = re.sub( r"https://github.com/fastfloat/fast_float/releases/download/v(\d+\.\d+\.\d+)/fast_float.h", f"https://github.com/fastfloat/fast_float/releases/download/v{newversionstring}/fast_float.h", line.rstrip(), ) line = re.sub( r"GIT_TAG tags/v(\d+\.\d+\.\d+)", f"GIT_TAG tags/v{newversionstring}", line.rstrip(), ) line = re.sub( r"GIT_TAG v(\d+\.\d+\.\d+)\)", f"GIT_TAG v{newversionstring})", line.rstrip() ) print(line) print(f"modified {readmefile}, a backup was made") print("running amalgamate.py") with open(f"{maindir}{os.sep}fast_float.h", "w") as outfile: cp = subprocess.run( [f"python3", f"{maindir}{os.sep}script{os.sep}amalgamate.py"], stdout=outfile ) if cp.returncode != 0: print("Failed to run amalgamate") else: print("amalgamate.py ran successfully") print(f"You should upload {maindir}{os.sep}fast_float.h") print("Please run the tests before issuing a release.\n") print( f'to issue release, enter\n git commit -a && git push && git tag -a v{toversionstring(*newversion)} -m "version {toversionstring(*newversion)}" && git push --tags\n' )