Repository navigation
Expand file tree
/
Copy pathsync_assembly_version.py
More file actions
126 lines (106 loc) · 4.37 KB
/
Copy pathsync_assembly_version.py
File metadata and controls
126 lines (106 loc) · 4.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import codecs
import os
import re
import sys
def _read_text_preserve_bom(path: str) -> tuple[str, bool]:
raw = open(path, "rb").read()
has_bom = raw.startswith(codecs.BOM_UTF8)
text = raw.decode("utf-8-sig" if has_bom else "utf-8")
return text, has_bom
def _write_text_preserve_bom(path: str, text: str, has_bom: bool) -> None:
raw = text.encode("utf-8")
if has_bom:
raw = codecs.BOM_UTF8 + raw
with open(path, "wb") as f:
f.write(raw)
def _extract_version_from_setup_py(setup_py_path: str) -> tuple[str, str]:
text, _ = _read_text_preserve_bom(setup_py_path)
m = re.search(r"(?m)^\s*version\s*=\s*['\"]([^'\"]+)['\"]\s*$", text)
if not m:
raise RuntimeError(f"无法在 {setup_py_path} 中找到 version = 'x.y.z.w' 形式的版本号")
version = m.group(1).strip()
m_num = re.match(r"^(\d+(?:\.\d+){3})", version)
if not m_num:
raise RuntimeError(f"版本号格式不符合要求(至少包含 4 段数字): {version}")
return version, m_num.group(1)
def _sync_assembly_info(assembly_info_path: str, version: str, numeric_version: str) -> bool:
text, has_bom = _read_text_preserve_bom(assembly_info_path)
changed = False
# AssemblyVersion (must be numeric x.x.x.x)
new_text, n = re.subn(
r'(?m)^\s*\[assembly:\s*AssemblyVersion\("([^"]+)"\)\]\s*$',
f'[assembly: AssemblyVersion("{numeric_version}")]',
text,
)
if n > 0:
text = new_text
changed = True
# AssemblyFileVersion (must be numeric x.x.x.x)
new_text, n = re.subn(
r'(?m)^\s*\[assembly:\s*AssemblyFileVersion\("([^"]+)"\)\]\s*$',
f'[assembly: AssemblyFileVersion("{numeric_version}")]',
text,
)
if n > 0:
text = new_text
changed = True
# AssemblyInformationalVersion (can contain suffix like a0)
info_pat = r'(?m)^\s*\[assembly:\s*AssemblyInformationalVersion\("([^"]+)"\)\]\s*$'
if re.search(info_pat, text):
new_text, n = re.subn(
info_pat,
f'[assembly: AssemblyInformationalVersion("{version}")]',
text,
)
if n > 0:
text = new_text
changed = True
else:
newline = "\r\n" if "\r\n" in text else "\n"
insert_line = f'[assembly: AssemblyInformationalVersion("{version}")]'
# 优先插在 AssemblyFileVersion 后面;没有就插在 AssemblyVersion 后面;都没有就追加到文件末尾
if re.search(r'(?m)^\s*\[assembly:\s*AssemblyFileVersion\("([^"]+)"\)\]\s*$', text):
text = re.sub(
r'(?m)^\s*(\[assembly:\s*AssemblyFileVersion\("([^"]+)"\)\]\s*)$',
r"\1" + newline + insert_line,
text,
count=1,
)
changed = True
elif re.search(r'(?m)^\s*\[assembly:\s*AssemblyVersion\("([^"]+)"\)\]\s*$', text):
text = re.sub(
r'(?m)^\s*(\[assembly:\s*AssemblyVersion\("([^"]+)"\)\]\s*)$',
r"\1" + newline + insert_line,
text,
count=1,
)
changed = True
else:
if not text.endswith(("\n", "\r\n")):
text += newline
text += insert_line + newline
changed = True
if changed:
_write_text_preserve_bom(assembly_info_path, text, has_bom)
return changed
def main() -> int:
repo_root = os.path.dirname(os.path.abspath(__file__))
setup_py = os.path.join(repo_root, "setup.py")
assembly_infos = [
os.path.join(repo_root, "DlcvDemo", "Properties", "AssemblyInfo.cs"),
os.path.join(repo_root, "DlcvCsharpApi", "Properties", "AssemblyInfo.cs"),
]
version, numeric_version = _extract_version_from_setup_py(setup_py)
all_changed = False
for assembly_info in assembly_infos:
if not os.path.exists(assembly_info):
print(f"[sync_assembly_version] 未找到目标文件: {assembly_info}", file=sys.stderr)
return 2
changed = _sync_assembly_info(assembly_info, version, numeric_version)
all_changed = all_changed or changed
print(
f"[sync_assembly_version] {os.path.basename(os.path.dirname(assembly_info))} AssemblyInfo 版本已{'更新' if changed else '确认一致'} -> {version} (numeric: {numeric_version})"
)
return 0
if __name__ == "__main__":
raise SystemExit(main())