Files
msime-windows/scripts/dev-build-version.py
T
tokisaki galaxy 43452f1ff9 build: derive a dev version string from version.txt
scripts/dev-build-version.py turns version.txt plus the head commit into
0.7.1-dev.20261019.<hash>: the -dev display string for installer names and
the native settings page, and a YYMMDD stamp for the fourth VERSIONINFO field.

apply_version.py accepts an optional fourth quad field to carry that stamp;
releases leave it at 0, so their behaviour is unchanged. The settings page's
version parser strips the -dev suffix and compares numbers, which is what
keeps the update check quiet on dev installs -- no opt-out flag needed.
2026-10-19 16:00:06 +08:00

101 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""Derive the dev-build version from version.txt.
The release owns version.txt (release-please), and dev builds must never masquerade as one.
The dev number keeps the release base for human recognition and appends a date and the short
commit: 0.7.1-dev.20261019.7fa6fb1a.
The strings go to the installer name and the settings page. The TSF DLL's VERSIONINFO quad has
four 16-bit fields, so the date compresses to YYMMDD in the fourth slot: 0.7.1.261019. yy > 79
sorts above every year this product exists, and any real release leaves that slot at 0, so a dev
DLL always reads as newer than its own base and older than the next release. The settings page's
parseVersion strips the -dev suffix and compares 0.7.1, which is why the update check stays quiet.
Windows filenames and Inno Setup accept the dots in the short hash; a detached HEAD (workflow
dispatch on a raw SHA) falls back to the first twelve hex digits.
python scripts/dev-build-version.py # all three outputs, one per line
python scripts/dev-build-version.py --display # 0.7.1-dev.20261019.7fa6fb1a
python scripts/dev-build-version.py --base # 0.7.1
python scripts/dev-build-version.py --date # 261019
"""
from __future__ import annotations
import argparse
import datetime
import re
import subprocess
import sys
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[1]
VERSION_FILE = REPO_ROOT / "version.txt"
SEMVER = re.compile(r"^(\d+)\.(\d+)\.(\d+)$")
SHORT_SHA = re.compile(r"^[0-9a-f]{7,40}$")
def read_base() -> tuple[str, str, str]:
if not VERSION_FILE.is_file():
raise SystemExit(f"error: {VERSION_FILE} is missing")
raw = VERSION_FILE.read_text(encoding="utf-8").strip()
match = SEMVER.match(raw)
if not match:
raise SystemExit(f"error: version.txt must hold MAJOR.MINOR.PATCH, got {raw!r}")
return match.groups()
def read_short_sha(explicit: str | None) -> str:
if explicit:
sha = explicit.strip().lower()
if not SHORT_SHA.match(sha):
raise SystemExit(f"error: --commit must be hex digits, got {explicit!r}")
return sha[:12]
result = subprocess.run(
["git", "rev-parse", "--short=12", "HEAD"],
cwd=REPO_ROOT,
capture_output=True,
text=True,
)
if result.returncode != 0:
raise SystemExit(f"error: cannot read the commit: {result.stderr.strip()}")
return result.stdout.strip()
def build(base: tuple[str, str, str], today: datetime.date, sha: str) -> tuple[str, str]:
major, minor, patch = base
display = f"{major}.{minor}.{patch}-dev.{today:%Y%m%d}.{sha}"
# 四段 quad 的末位放 YYMMDD:YY > 79 恒大于本产品存在的一切年份,任何正式版该位是 0,
# 所以 dev DLL 恒读作比基线新、比下一个发布旧。
date = today.strftime("%y%m%d")
quad = f"{major}.{minor}.{patch}.{date}"
return display, date
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
output = parser.add_mutually_exclusive_group()
output.add_argument("--display", action="store_true", help="print the display version only")
output.add_argument("--base", action="store_true", help="print the base version only")
output.add_argument("--date", action="store_true", help="print the YYMMDD stamp only")
parser.add_argument("--commit", metavar="SHA", help="use this short commit instead of reading git")
args = parser.parse_args()
base = read_base()
display, date = build(base, datetime.date.today(), read_short_sha(args.commit))
if args.display:
print(display)
elif args.base:
print(".".join(base))
elif args.date:
print(date)
else:
print(display)
print(date)
return 0
if __name__ == "__main__":
sys.exit(main())