regen_derived.py
5.49 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
127
128
129
130
131
132
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
r"""
补齐 `restore_p1.py` 恢复不到的那 16 个文件。
它们不是用 Write 工具写的,因此不在会话 jsonl 的 Write/Edit 记录里:
* 12 个 Mapper 接口 —— 是当时用一句 bash 函数 `gen()` + heredoc 批量生成的
* 4 个 apibase 常量/POJO —— 是 `sed` 从老 `zteits-api` 复制改包名生成的
两种生成方式都是确定性的,本脚本按当时**一模一样**的规则重算:
* Mapper:模板取自会话里那条 `gen()` 命令,`OrgMapper.java`(它是用 Write
写的、已被 restore_p1.py 恢复)用来交叉验证模板的最终形态(含当时补的
`sed '/^\*$/d'` 去掉多余星号行)。
* apibase:直接重放当时那条 `sed -e 's/com.zteits.clouds.api.apibase/…/g'`。
输出写到 tools/recover/out/,与其他恢复产物合并后再一起拷回源码树。
"""
import os
import re
CLOUD = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
LEGACY = os.path.join(os.path.dirname(CLOUD), "zteits-clouds")
STAGE = os.path.join(CLOUD, "tools/recover/out")
SYS = "parking-module-system/src/main/java/com/zteits/parking/module/system"
API = "parking-module-api/src/main/java/com/zteits/parking/module/api/apibase"
# (包/DO 所在子包, 类名前缀, 中文描述, extra) —— 顺序与当时 gen() 的调用完全一致
# extra 是当时生成器的第 4 个参数,三个关联表被传成了 "*" / "'*'",
# 落进 javadoc 就是一行多余的星号,随后由那条 `sed '/^\*$/d'` 删掉。
# 这里如实保留 extra,再在下面用等价的 sed 逻辑清掉,才能和当时的最终文件逐字节一致
# (extra 非空的那三个**没有**空行,extra 为空的那些有——这个差异肉眼看不出来,
# 但对"恢复"来说必须还原)。
MAPPERS = [
("user", "User", "用户", ""),
("permission", "Role", "角色", ""),
("permission", "Menu", "菜单", "*"),
("permission", "UserRole", "用户和角色的关联", "'*'"),
("permission", "RoleMenu", "角色和菜单的关联", "'*'"),
("dict", "DictType", "字典类型", ""),
("dict", "DictData", "字典数据", ""),
("oauth2", "OAuth2AccessToken", "OAuth2 访问令牌", ""),
("oauth2", "OAuth2RefreshToken", "OAuth2 刷新令牌", ""),
("oauth2", "OAuth2Client", "OAuth2 客户端", ""),
("logger", "LoginLog", "登录日志", ""),
("logger", "OperateLog", "操作日志", ""),
]
MAPPER_TPL = """package com.zteits.parking.module.system.dal.mysql.{sub};
import com.zteits.parking.framework.mybatis.core.mapper.BaseMapperX;
import com.zteits.parking.module.system.dal.dataobject.{sub}.{name}DO;
import org.apache.ibatis.annotations.Mapper;
/**
* {desc} Mapper
*
* ⚠️ 每个 Mapper **必须**带 {{@link Mapper}} 注解:
* `ParkingMybatisAutoConfiguration` 用的是
* `@MapperScan(value = "${{parking.info.base-package}}", annotationClass = Mapper.class)`,
* 漏写注解不会被扫描到,报 "Invalid bound statement (not found)"。
{extra}
* @author ZIEITS
*/
@Mapper
public interface {name}Mapper extends BaseMapperX<{name}DO> {{
}}
"""
def drop_star_lines(text):
"""等价于当时的 `sed -e '/^\\*$/d' -e "/^'\\*'$/d"`:删掉整行只有 * 或 '*' 的行。"""
return "".join(
ln for ln in text.splitlines(keepends=True) if ln.rstrip("\n") not in ("*", "'*'")
)
# sed 的目标:apibase 包名整体改名
APIBASE_FILES = [
"bean/BizResult.java",
"bean/ResultBean.java",
"bean/ErrorCode.java",
"constants/ErrorType.java",
]
OLD_PKG = "com.zteits.clouds.api.apibase"
NEW_PKG = "com.zteits.parking.module.api.apibase"
def write(rel, text):
dst = os.path.join(STAGE, rel)
os.makedirs(os.path.dirname(dst), exist_ok=True)
# 保持与当时一致的 LF 结尾 + 文件末尾换行
with open(dst, "w", encoding="utf-8", newline="\n") as f:
f.write(text)
def main():
for sub, name, desc, extra in MAPPERS:
text = MAPPER_TPL.format(sub=sub, name=name, desc=desc, extra=extra)
write(f"{SYS}/dal/mysql/{sub}/{name}Mapper.java", drop_star_lines(text))
print(f"✔ 生成 {len(MAPPERS)} 个 Mapper 接口")
# apibase:老源码存在才做,否则明确报错而不是产出空文件
src_root = os.path.join(LEGACY, "zteits-api/src/main/java/com/zteits/clouds/api/apibase")
if not os.path.isdir(src_root):
raise SystemExit(f"!! 老 apibase 目录不存在:{src_root}")
for rel in APIBASE_FILES:
src = os.path.join(src_root, rel)
if not os.path.isfile(src):
raise SystemExit(f"!! 老文件不存在:{src}")
with open(src, encoding="utf-8", errors="surrogateescape") as f:
text = f.read()
text = text.replace(OLD_PKG, NEW_PKG)
write(f"{API}/{rel}", text)
print(f"✔ 由 {OLD_PKG} 重放改名生成 {len(APIBASE_FILES)} 个 apibase 文件")
# 自检:新包名生效、老包名无残留
bad = []
for rel in APIBASE_FILES:
text = open(os.path.join(STAGE, f"{API}/{rel}"), encoding="utf-8").read()
if OLD_PKG in text:
bad.append(rel)
if rel == "constants/ErrorType.java":
# 与当时那条 `grep -c '^ [A-Z_0-9]*('` 等价,用来对齐历史计数 142
n = sum(1 for ln in text.splitlines() if re.match(r"^ [A-Z_0-9]*\(", ln))
print(f" ErrorType 枚举值:{n}(当时记录为 142)")
if bad:
raise SystemExit(f"!! 仍有老包名残留:{bad}")
if __name__ == "__main__":
main()