Files
security-ai-edge/utils/version_control.py

257 lines
8.9 KiB
Python
Raw Normal View History

2026-01-29 18:33:12 +08:00
"""
版本控制模块
记录代码更新历史包括更新时间内容修改人及影响范围
"""
import os
import json
import logging
from datetime import datetime
from typing import Any, Dict, List, Optional
from pathlib import Path
logger = logging.getLogger(__name__)
class VersionControl:
"""版本控制管理类"""
def __init__(self, changelog_path: str = "./CHANGELOG.md"):
self.changelog_path = changelog_path
self.current_version = "1.0.0"
self._init_changelog()
def _init_changelog(self):
"""初始化CHANGELOG文件"""
if not os.path.exists(self.changelog_path):
self._create_initial_changelog()
def _create_initial_changelog(self):
"""创建初始CHANGELOG"""
header = f"""# CHANGELOG - Edge_Inference_Service
## 版本更新记录
### v{self.current_version}
**更新时间**: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
**更新类型**: 初始化
**更新人员**: 系统
**影响范围**: 项目初始化
- 项目初始化创建
- 搭建基础目录结构
- 实现核心配置模块
- 实现工具类模块
---
*Generated by Edge_Inference_Service Version Control System*
"""
os.makedirs(os.path.dirname(self.changelog_path), exist_ok=True)
with open(self.changelog_path, 'w', encoding='utf-8') as f:
f.write(header)
logger.info(f"CHANGELOG文件已创建: {self.changelog_path}")
def record_update(
self,
version: str,
update_type: str,
description: str,
updated_by: str = "系统",
affected_items: Optional[List[str]] = None,
details: Optional[Dict[str, Any]] = None
):
"""
记录代码更新
Args:
version: 版本号
update_type: 更新类型 (新增/修改/修复/优化)
description: 更新描述
updated_by: 更新人员
affected_items: 影响范围列表
details: 详细信息字典
"""
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
affected = affected_items or []
entry = f"""
### v{version}
**更新时间**: {timestamp}
**更新类型**: {update_type}
**更新人员**: {updated_by}
**影响范围**: {', '.join(affected) if affected else '全局'}
- {description}
"""
if details:
details_str = json.dumps(details, ensure_ascii=False, indent=2)
entry += f"\n<details>\n<summary>详细信息</summary>\n\n```json\n{details_str}\n```\n</details>\n"
entry += "\n---"
try:
with open(self.changelog_path, 'r', encoding='utf-8') as f:
content = f.read()
insert_pos = content.find("\n## 版本更新记录")
if insert_pos == -1:
insert_pos = content.find("## 版本更新记录")
if insert_pos != -1:
insert_pos = content.find("\n", insert_pos)
new_content = content[:insert_pos] + entry + content[insert_pos:]
else:
new_content = content + entry
with open(self.changelog_path, 'w', encoding='utf-8') as f:
f.write(new_content)
self.current_version = version
logger.info(f"版本更新记录已添加: v{version}")
except Exception as e:
logger.error(f"记录版本更新失败: {e}")
def record_feature_addition(self, feature_name: str, module: str, description: str, updated_by: str = "系统"):
"""记录功能新增"""
version = self._bump_version("minor")
self.record_update(
version=version,
update_type="新增",
description=f"新增{module}模块: {feature_name}",
updated_by=updated_by,
affected_items=[module],
details={"feature": feature_name, "module": module, "description": description}
)
def record_bug_fix(self, bug_description: str, module: str, fix_method: str, updated_by: str = "系统"):
"""记录Bug修复"""
version = self._bump_version("patch")
self.record_update(
version=version,
update_type="修复",
description=f"修复{module}模块Bug: {bug_description}",
updated_by=updated_by,
affected_items=[module],
details={"bug": bug_description, "module": module, "fix_method": fix_method}
)
def record_optimization(self, optimization_type: str, module: str, improvement: str, updated_by: str = "系统"):
"""记录性能优化"""
version = self._bump_version("patch")
self.record_update(
version=version,
update_type="优化",
description=f"优化{module}模块{optimization_type}: {improvement}",
updated_by=updated_by,
affected_items=[module],
details={"type": optimization_type, "module": module, "improvement": improvement}
)
def record_refactoring(self, module: str, reason: str, changes: List[str], updated_by: str = "系统"):
"""记录代码重构"""
version = self._bump_version("minor")
self.record_update(
version=version,
update_type="重构",
description=f"重构{module}模块",
updated_by=updated_by,
affected_items=[module],
details={"module": module, "reason": reason, "changes": changes}
)
def _bump_version(self, bump_type: str) -> str:
"""版本号递增"""
parts = self.current_version.split(".")
major, minor, patch = int(parts[0]), int(parts[1]), int(parts[2])
if bump_type == "major":
major += 1
minor = 0
patch = 0
elif bump_type == "minor":
minor += 1
patch = 0
else: # patch
patch += 1
new_version = f"{major}.{minor}.{patch}"
return new_version
def get_changelog_content(self) -> str:
"""获取CHANGELOG内容"""
try:
if os.path.exists(self.changelog_path):
with open(self.changelog_path, 'r', encoding='utf-8') as f:
return f.read()
except Exception as e:
logger.error(f"读取CHANGELOG失败: {e}")
return ""
def get_version_history(self) -> List[Dict[str, Any]]:
"""获取版本历史"""
content = self.get_changelog_content()
versions = []
lines = content.split("\n")
current_version = None
for line in lines:
if line.startswith("### v"):
current_version = {
"version": line.replace("### v", "").strip(),
"timestamp": "",
"update_type": "",
"updated_by": "",
"affected_items": [],
"description": "",
}
versions.append(current_version)
elif current_version is not None:
if line.startswith("**更新时间**:"):
current_version["timestamp"] = line.split(":", 1)[1].strip()
elif line.startswith("**更新类型**:"):
current_version["update_type"] = line.split(":", 1)[1].strip()
elif line.startswith("**更新人员**:"):
current_version["updated_by"] = line.split(":", 1)[1].strip()
elif line.startswith("**影响范围**:"):
current_version["affected_items"] = [x.strip() for x in line.split(":", 1)[1].split(",")]
elif line.startswith("- ") and not line.startswith("- 详情"):
current_version["description"] = line.replace("- ", "").strip()
return versions
def export_version_report(self, output_path: str = "./version_report.json"):
"""导出版本报告"""
history = self.get_version_history()
report = {
"project": "Edge_Inference_Service",
"current_version": self.current_version,
"total_versions": len(history),
"version_history": history,
"generated_at": datetime.now().isoformat(),
}
try:
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(report, f, ensure_ascii=False, indent=2)
logger.info(f"版本报告已导出: {output_path}")
except Exception as e:
logger.error(f"导出版本报告失败: {e}")
_version_control_instance = None
def get_version_control() -> VersionControl:
"""获取版本控制单例"""
global _version_control_instance
if _version_control_instance is None:
_version_control_instance = VersionControl()
return _version_control_instance