feat(v0.2): 完善量化研究与二次开发能力

This commit is contained in:
shy3130
2026-08-13 20:16:02 +08:00
parent 57eb641275
commit 8fe5dac7bd
105 changed files with 4974 additions and 678 deletions
+121
View File
@@ -0,0 +1,121 @@
#!/usr/bin/env python3
"""Read-only Git overlap and conflict preview for secondary-development branches."""
from __future__ import annotations
import argparse
import subprocess
import sys
from pathlib import Path
def _git(root: Path, *args: str, check: bool = True) -> subprocess.CompletedProcess[str]:
result = subprocess.run(
["git", *args],
cwd=root,
capture_output=True,
text=True,
check=False,
)
if check and result.returncode != 0:
detail = (result.stderr or result.stdout).strip()
raise RuntimeError(detail or f"git {' '.join(args)} failed")
return result
def _lines(result: subprocess.CompletedProcess[str]) -> set[str]:
return {line.strip() for line in result.stdout.splitlines() if line.strip()}
def _resolve_repo(path: Path) -> Path:
result = _git(path, "rev-parse", "--show-toplevel")
return Path(result.stdout.strip()).resolve()
def _resolve_commit(root: Path, ref: str) -> str:
return _git(root, "rev-parse", "--verify", f"{ref}^{{commit}}").stdout.strip()
def _merge_tree_conflicts(root: Path, base: str, current: str, target: str) -> list[str]:
result = _git(root, "merge-tree", base, current, target)
lines = result.stdout.splitlines()
conflicts: list[str] = []
current_path: str | None = None
current_conflicted = False
for line in [*lines, ""]:
if line in {"changed in both", "added in both", "removed in both"}:
if current_path and current_conflicted:
conflicts.append(current_path)
current_path = None
current_conflicted = False
continue
parts = line.strip().split()
if current_path is None and len(parts) >= 4 and parts[0] in {"base", "our", "their"}:
current_path = parts[-1]
if line.startswith("+<<<<<<< ") or line.startswith("+=======") or line.startswith("+>>>>>>> "):
current_conflicted = True
if current_path and current_conflicted:
conflicts.append(current_path)
return sorted(set(conflicts))
def _print_paths(title: str, paths: list[str]) -> None:
print(f"\n{title}: {len(paths)}")
for path in paths:
print(f" - {path}")
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(
description="只读检查当前二开分支升级到目标 Git ref 时的源码重叠与文本冲突",
)
parser.add_argument("target", help="目标 Tag/分支/commit, 例如 v0.3.1")
parser.add_argument(
"--repo",
type=Path,
default=Path.cwd(),
help="仓库路径, 默认当前目录",
)
args = parser.parse_args(argv)
try:
root = _resolve_repo(args.repo.resolve())
current = _resolve_commit(root, "HEAD")
target = _resolve_commit(root, args.target)
base = _git(root, "merge-base", current, target).stdout.strip()
if not base:
raise RuntimeError("当前分支与目标版本没有共同基线")
current_paths = _lines(_git(root, "diff", "--name-only", f"{base}..{current}"))
target_paths = _lines(_git(root, "diff", "--name-only", f"{base}..{target}"))
overlap = sorted(current_paths & target_paths)
conflicts = _merge_tree_conflicts(root, base, current, target)
dirty = sorted(_lines(_git(root, "status", "--short")))
print("Tick Stock Panel 二开升级预检")
print(f"仓库: {root}")
print(f"当前: {current[:12]}")
print(f"目标: {args.target} ({target[:12]})")
print(f"共同基线: {base[:12]}")
print(f"当前分支修改文件: {len(current_paths)}")
print(f"目标版本修改文件: {len(target_paths)}")
_print_paths("双方修改的同一文件", overlap)
_print_paths("Git 三方预演识别的文本冲突", conflicts)
if dirty:
print(f"\n未提交工作区条目: {len(dirty)}")
print(" 注意: 未提交内容不会进入 Git 三方预演, 请先提交到临时分支后再复检。")
if conflicts:
print("\n结论: 需要人工解决文本冲突并执行完整回归。")
return 2
if overlap:
print("\n结论: Git 未发现文本冲突, 但重叠文件需要检查语义兼容和测试。")
return 0
print("\n结论: 未发现源码重叠; 仍需执行目标版本的验证矩阵。")
return 0
except (OSError, RuntimeError) as exc:
print(f"升级预检失败: {exc}", file=sys.stderr)
return 1
if __name__ == "__main__":
raise SystemExit(main())