feat: 添加归档系统和销售系统基础
- 新增Archive相关资源和预制体 - 新增SalesSystem销售系统基础 - 添加火山美术资源文件夹 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
+346
@@ -0,0 +1,346 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Split Commit Tool - 交互式拆分未提交变更为多个原子提交
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
# 配置
|
||||
PROTECTED_BRANCHES = ['main', 'master', 'release/', 'hotfix/']
|
||||
REPO_ROOT = Path(__file__).parent.absolute()
|
||||
os.chdir(REPO_ROOT)
|
||||
|
||||
def run_command(cmd, capture_output=True):
|
||||
"""执行Git命令"""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
shell=True,
|
||||
capture_output=capture_output,
|
||||
text=True,
|
||||
encoding='utf-8'
|
||||
)
|
||||
return result.returncode == 0, result.stdout, result.stderr
|
||||
except Exception as e:
|
||||
return False, "", str(e)
|
||||
|
||||
def is_protected_branch(branch_name):
|
||||
"""检查是否为保护分支"""
|
||||
for protected in PROTECTED_BRANCHES:
|
||||
if protected.endswith('/') and branch_name.startswith(protected):
|
||||
return True
|
||||
if branch_name == protected:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_current_branch():
|
||||
"""获取当前分支"""
|
||||
success, stdout, stderr = run_command("git branch --show-current")
|
||||
return stdout.strip() if success else ""
|
||||
|
||||
def analyze_changes():
|
||||
"""分析变更"""
|
||||
print("=" * 60)
|
||||
print("步骤 1: 分析变更")
|
||||
print("=" * 60)
|
||||
|
||||
# git status
|
||||
print("\n[git status]")
|
||||
success, stdout, stderr = run_command("git status")
|
||||
print(stdout or stderr)
|
||||
|
||||
# git diff --stat
|
||||
print("\n[git diff --stat]")
|
||||
success, stdout, stderr = run_command("git diff --stat")
|
||||
print(stdout or stderr)
|
||||
|
||||
return True
|
||||
|
||||
def create_commit(msg):
|
||||
"""使用msg.txt创建提交(避免中文乱码)"""
|
||||
msg_file = REPO_ROOT / "msg.txt"
|
||||
try:
|
||||
with open(msg_file, 'w', encoding='utf-8') as f:
|
||||
f.write(msg)
|
||||
f.write("\n\nCo-Authored-By: Claude Code <noreply@anthropic.com>\n")
|
||||
|
||||
success, stdout, stderr = run_command("git commit -F msg.txt")
|
||||
if not success:
|
||||
print(f"❌ 提交失败: {stderr}")
|
||||
return False
|
||||
|
||||
print(f"✅ 提交成功: {msg}")
|
||||
return True
|
||||
finally:
|
||||
if msg_file.exists():
|
||||
msg_file.unlink()
|
||||
|
||||
def commit_all_changes():
|
||||
"""一次性提交所有变更"""
|
||||
print("\n" + "=" * 60)
|
||||
print("一次性提交所有变更")
|
||||
print("=" * 60)
|
||||
|
||||
# 处理删除的文件
|
||||
run_command("git ls-files --deleted -z | xargs -0 git rm", capture_output=False)
|
||||
|
||||
# 添加所有变更
|
||||
run_command("git add -A", capture_output=False)
|
||||
|
||||
# 创建提交
|
||||
create_commit("chore: 批量提交变更")
|
||||
|
||||
# 显示提交历史
|
||||
print("\n[提交历史]")
|
||||
run_command("git log --oneline -5", capture_output=False)
|
||||
|
||||
def interactive_split():
|
||||
"""交互式拆分提交"""
|
||||
print("\n" + "=" * 60)
|
||||
print("步骤 2: 分组变更")
|
||||
print("=" * 60)
|
||||
|
||||
# 获取所有变更
|
||||
success, status_output, _ = run_command("git status --short")
|
||||
if not success:
|
||||
print("❌ 无法获取变更状态")
|
||||
return False
|
||||
|
||||
# 分析变更类型
|
||||
staged_files = []
|
||||
modified_files = []
|
||||
deleted_files = []
|
||||
untracked_files = []
|
||||
|
||||
for line in status_output.strip().split('\n'):
|
||||
if not line:
|
||||
continue
|
||||
|
||||
status = line[:2]
|
||||
file_path = line[3:]
|
||||
|
||||
if status == 'M ':
|
||||
staged_files.append(file_path)
|
||||
elif status == ' M':
|
||||
modified_files.append(file_path)
|
||||
elif status == 'D ':
|
||||
deleted_files.append(file_path)
|
||||
elif status == ' D':
|
||||
deleted_files.append(file_path)
|
||||
elif status == '??':
|
||||
untracked_files.append(file_path)
|
||||
elif status == 'MM':
|
||||
staged_files.append(file_path)
|
||||
modified_files.append(file_path)
|
||||
|
||||
# 显示分组建议
|
||||
groups = []
|
||||
print("\n[变更分组方案]")
|
||||
|
||||
order = 1
|
||||
|
||||
# 删除文件
|
||||
if deleted_files:
|
||||
groups.append({
|
||||
'order': order,
|
||||
'files': deleted_files,
|
||||
'message': '删除旧文件',
|
||||
'type': 'delete'
|
||||
})
|
||||
print(f"{order}. 删除 {len(deleted_files)} 个文件")
|
||||
for f in deleted_files[:3]:
|
||||
print(f" - {f}")
|
||||
if len(deleted_files) > 3:
|
||||
print(f" ... 还有 {len(deleted_files) - 3} 个文件")
|
||||
order += 1
|
||||
|
||||
# 修改的meta文件
|
||||
meta_files = [f for f in modified_files if f.endswith('.meta')]
|
||||
if meta_files:
|
||||
groups.append({
|
||||
'order': order,
|
||||
'files': meta_files,
|
||||
'message': '更新.meta文件',
|
||||
'type': 'meta'
|
||||
})
|
||||
print(f"{order}. 修改 {len(meta_files)} 个.meta文件")
|
||||
for f in meta_files[:3]:
|
||||
print(f" - {f}")
|
||||
if len(meta_files) > 3:
|
||||
print(f" ... 还有 {len(meta_files) - 3} 个文件")
|
||||
order += 1
|
||||
|
||||
# 场景文件
|
||||
scene_files = [f for f in modified_files if f.endswith('.unity')]
|
||||
if scene_files:
|
||||
groups.append({
|
||||
'order': order,
|
||||
'files': scene_files,
|
||||
'message': '更新场景',
|
||||
'type': 'scene'
|
||||
})
|
||||
print(f"{order}. 修改 {len(scene_files)} 个场景文件")
|
||||
for f in scene_files:
|
||||
print(f" - {f}")
|
||||
order += 1
|
||||
|
||||
# 脚本文件
|
||||
script_files = [f for f in modified_files if f.endswith('.cs')]
|
||||
if script_files:
|
||||
for script_file in script_files:
|
||||
groups.append({
|
||||
'order': order,
|
||||
'files': [script_file],
|
||||
'message': f'更新脚本: {Path(script_file).name}',
|
||||
'type': 'script'
|
||||
})
|
||||
print(f"{order}. 修改脚本: {script_file}")
|
||||
order += 1
|
||||
|
||||
# 未跟踪文件
|
||||
if untracked_files:
|
||||
groups.append({
|
||||
'order': order,
|
||||
'files': untracked_files,
|
||||
'message': '添加新文件',
|
||||
'type': 'untracked'
|
||||
})
|
||||
print(f"{order}. 添加 {len(untracked_files)} 个新文件")
|
||||
for f in untracked_files[:3]:
|
||||
print(f" - {f}")
|
||||
if len(untracked_files) > 3:
|
||||
print(f" ... 还有 {len(untracked_files) - 3} 个文件")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("步骤 3: 确认拆分方案")
|
||||
print("=" * 60)
|
||||
|
||||
choice = input("\n是否开始拆分? [1] 开始拆分 [2] 取消拆分 [3] 自定义分组: ")
|
||||
|
||||
if choice == '2':
|
||||
print("\n已取消拆分")
|
||||
return False
|
||||
|
||||
if choice == '3':
|
||||
print("\n自定义分组功能暂未实现,请使用自动分组")
|
||||
return False
|
||||
|
||||
# 开始拆分
|
||||
print("\n" + "=" * 60)
|
||||
print("步骤 4: 执行拆分")
|
||||
print("=" * 60)
|
||||
|
||||
for group in groups:
|
||||
print(f"\n>>> 处理第 {group['order']} 组")
|
||||
|
||||
# 根据类型执行不同的git操作
|
||||
if group['type'] == 'delete':
|
||||
# 删除文件
|
||||
for file_path in group['files']:
|
||||
run_command(f'git rm "{file_path}"', capture_output=False)
|
||||
elif group['type'] == 'untracked':
|
||||
# 添加新文件
|
||||
run_command('git add -A', capture_output=False)
|
||||
else:
|
||||
# 修改文件
|
||||
for file_path in group['files']:
|
||||
run_command(f'git add "{file_path}"', capture_output=False)
|
||||
|
||||
# 创建提交
|
||||
success = create_commit(group['message'])
|
||||
if not success:
|
||||
print(f"❌ 第 {group['order']} 组提交失败,拆分中止")
|
||||
return False
|
||||
|
||||
input("\n按回车继续下一组...")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("步骤 5: 完成")
|
||||
print("=" * 60)
|
||||
|
||||
print("\n[提交历史]")
|
||||
success, stdout, _ = run_command("git log --oneline -" + str(len(groups)))
|
||||
print(stdout)
|
||||
|
||||
print(f"\n✅ 拆分完成!共创建 {len(groups)} 个原子提交")
|
||||
return True
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
print("=" * 60)
|
||||
print("Split Commit - 交互式拆分提交工具")
|
||||
print("=" * 60)
|
||||
|
||||
# 检查保护分支
|
||||
current_branch = get_current_branch()
|
||||
print(f"\n当前分支: {current_branch}")
|
||||
|
||||
if is_protected_branch(current_branch):
|
||||
print("\n❌ 当前为保护分支,无法直接拆分")
|
||||
print("\n选项:")
|
||||
print("[1] 创建新分支再拆分 (推荐)")
|
||||
print("[2] 压成单commit并移到新分支")
|
||||
print("[3] 取消")
|
||||
|
||||
choice = input("\n请选择: ")
|
||||
|
||||
if choice == '1':
|
||||
branch_name = input("请输入新分支名: ")
|
||||
if not branch_name:
|
||||
print("❌ 分支名不能为空")
|
||||
return
|
||||
|
||||
print("\n执行:")
|
||||
print("1. git stash push --include-untracked")
|
||||
print(f"2. git checkout -b {branch_name}")
|
||||
print("3. git stash pop")
|
||||
|
||||
confirm = input("\n确认执行?(y/n): ")
|
||||
if confirm.lower() == 'y':
|
||||
run_command("git stash push --include-untracked", capture_output=False)
|
||||
run_command(f"git checkout -b {branch_name}", capture_output=False)
|
||||
run_command("git stash pop", capture_output=False)
|
||||
print(f"\n✅ 已切换到新分支: {branch_name}")
|
||||
print("请重新运行此工具进行拆分")
|
||||
|
||||
elif choice == '2':
|
||||
print("\n功能暂未实现")
|
||||
|
||||
return
|
||||
|
||||
# 非保护分支,继续拆分流程
|
||||
print("\n✅ 非保护分支,可以进行拆分")
|
||||
|
||||
# 分析变更
|
||||
if not analyze_changes():
|
||||
return
|
||||
|
||||
# 选择模式
|
||||
print("\n" + "=" * 60)
|
||||
print("选择拆分模式:")
|
||||
print("=" * 60)
|
||||
print("[1] 交互式拆分 (推荐)")
|
||||
print("[2] 一次性提交所有变更")
|
||||
|
||||
mode = input("\n请选择: ")
|
||||
|
||||
if mode == '1':
|
||||
interactive_split()
|
||||
elif mode == '2':
|
||||
commit_all_changes()
|
||||
else:
|
||||
print("❌ 无效选择")
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n已取消操作")
|
||||
sys.exit(0)
|
||||
except Exception as e:
|
||||
print(f"\n❌ 发生错误: {e}")
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user