155 lines
6.1 KiB
Python
155 lines
6.1 KiB
Python
import re
|
||
import subprocess
|
||
import os
|
||
import sys
|
||
import datetime
|
||
import io
|
||
import locale
|
||
|
||
system_encoding = locale.getpreferredencoding(False)
|
||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding=system_encoding)
|
||
|
||
# 语义化版本 https://semver.org/lang/zh-CN/spec/v2.0.0.html
|
||
default_major_version = 0 # 主版本号
|
||
defalut_minor_version = 1 # 次版本号
|
||
defalut_revision_version = 0 # 修订版本号
|
||
defalut_pre_release_version = "" # 预发行版本号
|
||
|
||
|
||
def get_version_from_file(path):
|
||
"""从项目根目录的version.txt文件中读取版本信息"""
|
||
version_file = os.path.join(path, "version.txt")
|
||
|
||
# 默认版本号
|
||
versions = {
|
||
"major_version": default_major_version,
|
||
"minor_version": defalut_minor_version,
|
||
"revision_version": defalut_revision_version,
|
||
"pre_release_version": defalut_pre_release_version
|
||
}
|
||
|
||
# 检查文件是否存在
|
||
if not os.path.exists(version_file):
|
||
# 创建默认version.txt文件
|
||
try:
|
||
with open(version_file, 'w', encoding='utf-8') as f:
|
||
f.write(f"major_version={versions['major_version']}\n")
|
||
f.write(f"minor_version={versions['minor_version']}\n")
|
||
f.write(f"revision_version={versions['revision_version']}\n")
|
||
f.write(
|
||
f"pre_release_version={versions['pre_release_version']}\n")
|
||
print(f"已在项目根目录创建默认的version.txt文件")
|
||
except Exception as e:
|
||
print(f"创建version.txt文件失败: {str(e)}")
|
||
return versions
|
||
|
||
# 读取version.txt文件
|
||
try:
|
||
with open(version_file, 'r', encoding='utf-8') as f:
|
||
for line in f:
|
||
line = line.strip()
|
||
if '=' in line:
|
||
key, value = line.split('=', 1)
|
||
key = key.strip()
|
||
value = value.strip()
|
||
|
||
if key in versions:
|
||
# 处理整数类型的版本号
|
||
if key != "pre_release_version":
|
||
try:
|
||
versions[key] = int(value)
|
||
except ValueError:
|
||
raise ValueError(
|
||
f"版本号解析错误: {key}必须是整数,当前值为'{value}'")
|
||
else:
|
||
versions[key] = value
|
||
except Exception as e:
|
||
raise Exception(f"解析version.txt文件失败: {str(e)}")
|
||
|
||
return versions
|
||
|
||
|
||
def generate_version_file(name, path, file_version, file_build_time):
|
||
if not os.path.exists(f"{path}/Core/App/AutoGen/"):
|
||
os.makedirs(f"{path}/Core/App/AutoGen/", exist_ok=True)
|
||
|
||
with open(f"{path}/Core/App/AutoGen/autogen_version.c", "w", encoding="utf-8") as f:
|
||
f.write("// 这个文件是自动生成的\n")
|
||
f.write("// 对它作任何修改都将在编译前由程序自动覆盖\n")
|
||
f.write("// 不需要修改这个文件的内容\n")
|
||
f.write("\n")
|
||
f.write(f'const char *g_name = "{name}";\n')
|
||
f.write(f'const char *g_version = "{file_version}";\n')
|
||
f.write(f'const char *g_buildTime = "{file_build_time}";\n')
|
||
|
||
|
||
def generate_version(path):
|
||
# 从version.txt获取版本信息
|
||
try:
|
||
versions = get_version_from_file(path)
|
||
major_version = versions["major_version"]
|
||
minor_version = versions["minor_version"]
|
||
revision_version = versions["revision_version"]
|
||
pre_release_version = versions["pre_release_version"]
|
||
except Exception as e:
|
||
print(f"错误: {str(e)}")
|
||
sys.exit(-1)
|
||
|
||
generated_version = f"{major_version}.{minor_version}.{revision_version}"
|
||
git_commit_id = ""
|
||
# 检查是否在Git仓库中
|
||
git_process = subprocess.run(
|
||
["git", "rev-parse"], capture_output=True, text=True, cwd=path)
|
||
if git_process.returncode == 0:
|
||
# 检查是否有未提交的更改
|
||
commit_process = subprocess.run(
|
||
["git", "status", "-s"], capture_output=True, text=True, cwd=path)
|
||
if commit_process.stdout != "":
|
||
# 有未提交的更改,获取当前commit id并加*
|
||
process = subprocess.run(
|
||
["git", "rev-parse", "--short", "HEAD"], capture_output=True, text=True, cwd=path)
|
||
git_commit_id = process.stdout.strip() + "*"
|
||
else:
|
||
# 没有未提交的更改,直接获取当前commit id
|
||
process = subprocess.run(["git", "rev-parse", "--short=8", "HEAD"], capture_output=True, text=True,
|
||
cwd=path)
|
||
git_commit_id = process.stdout.strip()
|
||
|
||
# 根据 pre_release_version 和 git_commit_id 更新版本号
|
||
if pre_release_version and git_commit_id:
|
||
generated_version += f"-{pre_release_version}+{git_commit_id}"
|
||
elif pre_release_version:
|
||
generated_version += f"-{pre_release_version}"
|
||
elif git_commit_id:
|
||
generated_version += f"+{git_commit_id}"
|
||
|
||
# https://regex101.com/r/Ly7O1x/3/
|
||
semver_regex = (
|
||
r"^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*["
|
||
r"a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>["
|
||
r"0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*|\*|.*\*))?$")
|
||
|
||
if not re.match(semver_regex, generated_version):
|
||
print(f"生成的版本号 {generated_version} 不符合语义化版本规范")
|
||
|
||
return generated_version
|
||
|
||
|
||
if __name__ == "__main__":
|
||
try:
|
||
name = sys.argv[1] if len(sys.argv) > 1 else 'McuProgram'
|
||
project_directory = sys.argv[2] if len(sys.argv) > 2 else '.'
|
||
if not os.path.isdir(project_directory):
|
||
raise Exception("Invalid project directory")
|
||
version = generate_version(project_directory)
|
||
build_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||
generate_version_file(
|
||
name, project_directory, version, build_time)
|
||
print(f"Program name: {name}")
|
||
print(f"Version: {version}")
|
||
print(f"Build time: {build_time}")
|
||
sys.exit(0)
|
||
except Exception as e:
|
||
print(e)
|
||
sys.exit(-1)
|