3617b7aabc
Build: fix incremental package (update_info.json SHA256, __delete__, test exclude, files/ prefix), fix bump_version for 3-segment, PYTHONUTF8 in update.bat Frontend: upload→manual redirect, LLM→cluster_overview redirect, filter UI before clustering, 地球→态势 rename, fix globe drag direction+inertia Pipeline: LLM→auto clustering+PCA, column union handling (keep extra cols, no dropping), FFT spectral analysis tool Quality: fix 24 bare except:pass patterns, enrich LLM context with TlsDB metadata, auto-save workflows with pinning, TlsDB-based column types
131 lines
3.8 KiB
Python
131 lines
3.8 KiB
Python
"""版本工具函数,在构建端(开发机)和应用端(离线机)共享
|
||
|
||
Provides version tracking and git change detection utilities.
|
||
All functions work standalone without Django imports.
|
||
"""
|
||
from pathlib import Path
|
||
import subprocess
|
||
import re
|
||
|
||
PROJECT_DIR = Path(__file__).resolve().parent.parent
|
||
VERSION_FILE = PROJECT_DIR / 'VERSION'
|
||
|
||
|
||
def get_current_version() -> str:
|
||
"""从 VERSION 文件读取当前版本"""
|
||
if VERSION_FILE.exists():
|
||
return VERSION_FILE.read_text(encoding='utf-8').strip()
|
||
return 'v0.0.0'
|
||
|
||
|
||
def set_current_version(version: str) -> None:
|
||
"""写入 VERSION 文件"""
|
||
VERSION_FILE.write_text(version.strip() + '\n', encoding='utf-8')
|
||
|
||
|
||
def get_git_tags() -> list[str]:
|
||
"""获取所有 git tag,按版本号降序排列"""
|
||
try:
|
||
result = subprocess.run(
|
||
['git', 'tag', '--sort=-version:refname'],
|
||
capture_output=True, text=True, cwd=PROJECT_DIR, timeout=30
|
||
)
|
||
return [t.strip() for t in result.stdout.strip().split('\n') if t.strip()]
|
||
except (subprocess.TimeoutExpired, FileNotFoundError):
|
||
return []
|
||
|
||
|
||
def get_latest_tag() -> str | None:
|
||
"""获取最新 git tag,如果没有则返回 None"""
|
||
tags = get_git_tags()
|
||
return tags[0] if tags else None
|
||
|
||
|
||
def get_changed_files(from_tag: str, to_ref: str = 'HEAD') -> tuple[list[str], list[str]]:
|
||
"""获取两个 git 引用之间变更的文件列表
|
||
|
||
使用 git diff --name-status 以确保能捕获删除的文件。
|
||
|
||
Args:
|
||
from_tag: 起始版本(如 'v1.0')
|
||
to_ref: 终止引用(默认 HEAD)
|
||
|
||
Returns:
|
||
(added_modified: list[str], deleted: list[str])
|
||
文件路径相对于项目根目录
|
||
"""
|
||
try:
|
||
result = subprocess.run(
|
||
['git', 'diff', '--name-status', f'{from_tag}..{to_ref}'],
|
||
capture_output=True, text=True, cwd=PROJECT_DIR, timeout=30
|
||
)
|
||
except (subprocess.TimeoutExpired, FileNotFoundError):
|
||
return [], []
|
||
|
||
added_modified: list[str] = []
|
||
deleted: list[str] = []
|
||
|
||
for line in result.stdout.strip().split('\n'):
|
||
if not line.strip():
|
||
continue
|
||
parts = line.split('\t')
|
||
if len(parts) < 2:
|
||
continue
|
||
status = parts[0]
|
||
path = parts[1]
|
||
|
||
# Handle renames: R100 file1\tfile2 → track the new name
|
||
if status.startswith('R'):
|
||
if len(parts) >= 3:
|
||
added_modified.append(parts[2]) # new name
|
||
deleted.append(parts[1]) # old name
|
||
continue
|
||
|
||
if status == 'D':
|
||
deleted.append(path)
|
||
elif status in ('A', 'M', 'C'):
|
||
added_modified.append(path)
|
||
|
||
return added_modified, deleted
|
||
|
||
|
||
def is_working_tree_clean() -> bool:
|
||
"""检查 git 工作树是否干净(无未提交变更)"""
|
||
try:
|
||
result = subprocess.run(
|
||
['git', 'diff', '--stat'],
|
||
capture_output=True, text=True, cwd=PROJECT_DIR, timeout=15
|
||
)
|
||
return result.stdout.strip() == ''
|
||
except (subprocess.TimeoutExpired, FileNotFoundError):
|
||
return False
|
||
|
||
|
||
def bump_version(current: str) -> str:
|
||
"""递增版本号
|
||
|
||
v0.0.0 → v1.0 (首次稳定版)
|
||
v1.0 → v1.1
|
||
v1.9 → v1.10
|
||
v1.1.2 → v1.1.3
|
||
v1.1.9 → v1.1.10
|
||
"""
|
||
match = re.match(r'v(\d+)\.(\d+)(?:\.(\d+))?', current)
|
||
if not match:
|
||
return 'v1.0'
|
||
major = int(match.group(1))
|
||
minor = int(match.group(2))
|
||
patch = match.group(3)
|
||
if major == 0:
|
||
return 'v1.0'
|
||
if patch is not None:
|
||
# 3-segment: increment patch
|
||
return f'v{major}.{minor}.{int(patch) + 1}'
|
||
else:
|
||
# 2-segment: increment minor
|
||
return f'v{major}.{minor + 1}'
|
||
|
||
|
||
if __name__ == '__main__':
|
||
print(bump_version('v1.1.2'))
|