[aide] impl: 子计划1 Git分支管理核心功能实现完成
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"task_id": "2025-12-17T03-13-17",
|
"task_id": "2025-12-17T03-13-17",
|
||||||
"current_phase": "impl",
|
"current_phase": "impl",
|
||||||
"current_step": 8,
|
"current_step": 9,
|
||||||
"started_at": "2025-12-17T03:13:17+08:00",
|
"started_at": "2025-12-17T03:13:17+08:00",
|
||||||
"history": [
|
"history": [
|
||||||
{
|
{
|
||||||
@@ -65,7 +65,15 @@
|
|||||||
"action": "next-part",
|
"action": "next-part",
|
||||||
"phase": "impl",
|
"phase": "impl",
|
||||||
"step": 8,
|
"step": 8,
|
||||||
"summary": "流程设计完成,开始实现子计划1:Git分支管理核心功能"
|
"summary": "流程设计完成,开始实现子计划1:Git分支管理核心功能",
|
||||||
|
"git_commit": "cf52da408315f0beb7e1d64cc37e48e35f81d8a1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2025-12-17T04:08:17+08:00",
|
||||||
|
"action": "next-step",
|
||||||
|
"phase": "impl",
|
||||||
|
"step": 9,
|
||||||
|
"summary": "子计划1 Git分支管理核心功能实现完成"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
26012
|
26989
|
||||||
368
aide-program/aide/flow/branch.py
Normal file
368
aide-program/aide/flow/branch.py
Normal file
@@ -0,0 +1,368 @@
|
|||||||
|
"""BranchManager:管理 aide flow 任务分支编号和概况文档。"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from aide.flow.errors import FlowError
|
||||||
|
from aide.flow.git import GitIntegration
|
||||||
|
from aide.flow.utils import now_iso
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class BranchInfo:
|
||||||
|
"""分支信息记录"""
|
||||||
|
number: int
|
||||||
|
branch_name: str
|
||||||
|
source_branch: str
|
||||||
|
start_commit: str
|
||||||
|
end_commit: str | None
|
||||||
|
task_id: str
|
||||||
|
task_summary: str
|
||||||
|
started_at: str
|
||||||
|
finished_at: str | None
|
||||||
|
status: str # "active", "finished", "merged-to-temp"
|
||||||
|
temp_branch: str | None = None
|
||||||
|
|
||||||
|
def to_dict(self) -> dict[str, Any]:
|
||||||
|
data: dict[str, Any] = {
|
||||||
|
"number": self.number,
|
||||||
|
"branch_name": self.branch_name,
|
||||||
|
"source_branch": self.source_branch,
|
||||||
|
"start_commit": self.start_commit,
|
||||||
|
"task_id": self.task_id,
|
||||||
|
"task_summary": self.task_summary,
|
||||||
|
"started_at": self.started_at,
|
||||||
|
"status": self.status,
|
||||||
|
}
|
||||||
|
if self.end_commit is not None:
|
||||||
|
data["end_commit"] = self.end_commit
|
||||||
|
if self.finished_at is not None:
|
||||||
|
data["finished_at"] = self.finished_at
|
||||||
|
if self.temp_branch is not None:
|
||||||
|
data["temp_branch"] = self.temp_branch
|
||||||
|
return data
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_dict(data: dict[str, Any]) -> "BranchInfo":
|
||||||
|
return BranchInfo(
|
||||||
|
number=data["number"],
|
||||||
|
branch_name=data["branch_name"],
|
||||||
|
source_branch=data["source_branch"],
|
||||||
|
start_commit=data["start_commit"],
|
||||||
|
end_commit=data.get("end_commit"),
|
||||||
|
task_id=data["task_id"],
|
||||||
|
task_summary=data["task_summary"],
|
||||||
|
started_at=data["started_at"],
|
||||||
|
finished_at=data.get("finished_at"),
|
||||||
|
status=data.get("status", "active"),
|
||||||
|
temp_branch=data.get("temp_branch"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class BranchesData:
|
||||||
|
"""分支概况数据"""
|
||||||
|
next_number: int
|
||||||
|
branches: list[BranchInfo]
|
||||||
|
|
||||||
|
def to_dict(self) -> dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"next_number": self.next_number,
|
||||||
|
"branches": [b.to_dict() for b in self.branches],
|
||||||
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_dict(data: dict[str, Any]) -> "BranchesData":
|
||||||
|
next_number = data.get("next_number", 1)
|
||||||
|
branches_raw = data.get("branches", [])
|
||||||
|
branches = [BranchInfo.from_dict(b) for b in branches_raw]
|
||||||
|
return BranchesData(next_number=next_number, branches=branches)
|
||||||
|
|
||||||
|
|
||||||
|
class BranchManager:
|
||||||
|
"""管理 aide flow 任务分支"""
|
||||||
|
|
||||||
|
def __init__(self, root: Path, git: GitIntegration):
|
||||||
|
self.root = root
|
||||||
|
self.git = git
|
||||||
|
self.aide_dir = root / ".aide"
|
||||||
|
self.branches_json = self.aide_dir / "branches.json"
|
||||||
|
self.branches_md = self.aide_dir / "branches.md"
|
||||||
|
self._data: BranchesData | None = None
|
||||||
|
self._current_branch_info: BranchInfo | None = None
|
||||||
|
|
||||||
|
def load_branches(self) -> BranchesData:
|
||||||
|
"""加载分支概况"""
|
||||||
|
if self._data is not None:
|
||||||
|
return self._data
|
||||||
|
|
||||||
|
if not self.branches_json.exists():
|
||||||
|
self._data = BranchesData(next_number=1, branches=[])
|
||||||
|
return self._data
|
||||||
|
|
||||||
|
try:
|
||||||
|
content = self.branches_json.read_text(encoding="utf-8")
|
||||||
|
data = json.loads(content)
|
||||||
|
self._data = BranchesData.from_dict(data)
|
||||||
|
return self._data
|
||||||
|
except (json.JSONDecodeError, KeyError, TypeError) as e:
|
||||||
|
raise FlowError(f"读取分支概况失败: {e}") from e
|
||||||
|
|
||||||
|
def save_branches(self) -> None:
|
||||||
|
"""保存分支概况(同时生成 JSON 和 MD)"""
|
||||||
|
if self._data is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.aide_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# 保存 JSON
|
||||||
|
json_content = json.dumps(
|
||||||
|
self._data.to_dict(),
|
||||||
|
ensure_ascii=False,
|
||||||
|
indent=2,
|
||||||
|
)
|
||||||
|
self.branches_json.write_text(json_content + "\n", encoding="utf-8")
|
||||||
|
|
||||||
|
# 生成并保存 MD
|
||||||
|
md_content = self._generate_markdown()
|
||||||
|
self.branches_md.write_text(md_content, encoding="utf-8")
|
||||||
|
|
||||||
|
def _generate_markdown(self) -> str:
|
||||||
|
"""生成 Markdown 格式的分支概况"""
|
||||||
|
if self._data is None:
|
||||||
|
return "# Git 分支概况\n\n暂无分支记录。\n"
|
||||||
|
|
||||||
|
lines = ["# Git 分支概况\n"]
|
||||||
|
|
||||||
|
if not self._data.branches:
|
||||||
|
lines.append("暂无分支记录。\n")
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
for branch in reversed(self._data.branches):
|
||||||
|
lines.append(f"## {branch.branch_name}\n")
|
||||||
|
lines.append(f"- **任务**: {branch.task_summary}")
|
||||||
|
lines.append(f"- **任务ID**: {branch.task_id}")
|
||||||
|
lines.append(f"- **源分支**: {branch.source_branch}")
|
||||||
|
lines.append(f"- **起始提交**: {branch.start_commit[:7]}")
|
||||||
|
if branch.end_commit:
|
||||||
|
lines.append(f"- **结束提交**: {branch.end_commit[:7]}")
|
||||||
|
lines.append(f"- **状态**: {branch.status}")
|
||||||
|
time_str = branch.started_at[:16].replace("T", " ")
|
||||||
|
if branch.finished_at:
|
||||||
|
time_str += f" ~ {branch.finished_at[11:16]}"
|
||||||
|
lines.append(f"- **时间**: {time_str}")
|
||||||
|
if branch.temp_branch:
|
||||||
|
lines.append(f"- **临时分支**: {branch.temp_branch}")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
def get_next_branch_number(self) -> int:
|
||||||
|
"""获取下一个分支编号"""
|
||||||
|
data = self.load_branches()
|
||||||
|
return data.next_number
|
||||||
|
|
||||||
|
def create_task_branch(
|
||||||
|
self,
|
||||||
|
task_id: str,
|
||||||
|
task_summary: str,
|
||||||
|
) -> str:
|
||||||
|
"""创建任务分支并记录信息
|
||||||
|
|
||||||
|
返回创建的分支名称
|
||||||
|
"""
|
||||||
|
self.git.ensure_repo()
|
||||||
|
data = self.load_branches()
|
||||||
|
|
||||||
|
# 确保 git 状态干净
|
||||||
|
if not self.git.is_clean():
|
||||||
|
self.git.add_all()
|
||||||
|
self.git.commit("[aide] 保存未提交的变更")
|
||||||
|
|
||||||
|
# 确保有提交历史
|
||||||
|
if not self.git.has_commits():
|
||||||
|
gitkeep = self.root / ".gitkeep"
|
||||||
|
if not gitkeep.exists():
|
||||||
|
gitkeep.touch()
|
||||||
|
self.git.add_all()
|
||||||
|
self.git.commit("[aide] 初始提交")
|
||||||
|
|
||||||
|
# 记录起始信息
|
||||||
|
source_branch = self.git.get_current_branch()
|
||||||
|
start_commit = self.git.rev_parse_head()
|
||||||
|
|
||||||
|
# 创建分支名
|
||||||
|
branch_number = data.next_number
|
||||||
|
branch_name = f"aide/{branch_number:03d}"
|
||||||
|
|
||||||
|
# 创建并切换到任务分支
|
||||||
|
self.git.checkout_new_branch(branch_name)
|
||||||
|
|
||||||
|
# 记录分支信息
|
||||||
|
branch_info = BranchInfo(
|
||||||
|
number=branch_number,
|
||||||
|
branch_name=branch_name,
|
||||||
|
source_branch=source_branch,
|
||||||
|
start_commit=start_commit,
|
||||||
|
end_commit=None,
|
||||||
|
task_id=task_id,
|
||||||
|
task_summary=task_summary,
|
||||||
|
started_at=now_iso(),
|
||||||
|
finished_at=None,
|
||||||
|
status="active",
|
||||||
|
)
|
||||||
|
|
||||||
|
# 更新数据
|
||||||
|
data.branches.append(branch_info)
|
||||||
|
data.next_number = branch_number + 1
|
||||||
|
self._data = data
|
||||||
|
self._current_branch_info = branch_info
|
||||||
|
|
||||||
|
# 保存
|
||||||
|
self.save_branches()
|
||||||
|
|
||||||
|
return branch_name
|
||||||
|
|
||||||
|
def get_active_branch_info(self) -> BranchInfo | None:
|
||||||
|
"""获取当前活跃的分支信息"""
|
||||||
|
if self._current_branch_info is not None:
|
||||||
|
return self._current_branch_info
|
||||||
|
|
||||||
|
data = self.load_branches()
|
||||||
|
current_branch = self.git.get_current_branch()
|
||||||
|
|
||||||
|
for branch in data.branches:
|
||||||
|
if branch.branch_name == current_branch and branch.status == "active":
|
||||||
|
self._current_branch_info = branch
|
||||||
|
return branch
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def record_branch_finish(
|
||||||
|
self,
|
||||||
|
status: str = "finished",
|
||||||
|
end_commit: str | None = None,
|
||||||
|
temp_branch: str | None = None,
|
||||||
|
) -> None:
|
||||||
|
"""记录分支结束信息"""
|
||||||
|
data = self.load_branches()
|
||||||
|
branch_info = self.get_active_branch_info()
|
||||||
|
|
||||||
|
if branch_info is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
# 更新分支信息
|
||||||
|
for i, branch in enumerate(data.branches):
|
||||||
|
if branch.number == branch_info.number:
|
||||||
|
data.branches[i] = BranchInfo(
|
||||||
|
number=branch.number,
|
||||||
|
branch_name=branch.branch_name,
|
||||||
|
source_branch=branch.source_branch,
|
||||||
|
start_commit=branch.start_commit,
|
||||||
|
end_commit=end_commit or self.git.rev_parse_head(),
|
||||||
|
task_id=branch.task_id,
|
||||||
|
task_summary=branch.task_summary,
|
||||||
|
started_at=branch.started_at,
|
||||||
|
finished_at=now_iso(),
|
||||||
|
status=status,
|
||||||
|
temp_branch=temp_branch,
|
||||||
|
)
|
||||||
|
break
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._current_branch_info = None
|
||||||
|
self.save_branches()
|
||||||
|
|
||||||
|
def finish_branch_merge(self, task_summary: str) -> tuple[bool, str]:
|
||||||
|
"""执行分支合并逻辑
|
||||||
|
|
||||||
|
返回 (是否成功, 消息)
|
||||||
|
"""
|
||||||
|
branch_info = self.get_active_branch_info()
|
||||||
|
|
||||||
|
if branch_info is None:
|
||||||
|
return True, "未找到活跃的任务分支,跳过合并"
|
||||||
|
|
||||||
|
source_branch = branch_info.source_branch
|
||||||
|
start_commit = branch_info.start_commit
|
||||||
|
task_branch = branch_info.branch_name
|
||||||
|
|
||||||
|
# 检查源分支是否有新提交
|
||||||
|
if self.git.has_commits_since(start_commit, source_branch):
|
||||||
|
# 源分支有新提交,使用临时分支策略
|
||||||
|
return self._merge_with_temp_branch(
|
||||||
|
branch_info=branch_info,
|
||||||
|
task_summary=task_summary,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# 正常合并流程
|
||||||
|
return self._merge_normal(
|
||||||
|
branch_info=branch_info,
|
||||||
|
task_summary=task_summary,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _merge_normal(
|
||||||
|
self,
|
||||||
|
branch_info: BranchInfo,
|
||||||
|
task_summary: str,
|
||||||
|
) -> tuple[bool, str]:
|
||||||
|
"""正常合并流程:软重置 + 压缩提交"""
|
||||||
|
source_branch = branch_info.source_branch
|
||||||
|
start_commit = branch_info.start_commit
|
||||||
|
|
||||||
|
# 切回源分支
|
||||||
|
self.git.checkout(source_branch)
|
||||||
|
|
||||||
|
# 软重置到起始提交
|
||||||
|
self.git.reset_soft(start_commit)
|
||||||
|
|
||||||
|
# 创建压缩提交
|
||||||
|
self.git.add_all()
|
||||||
|
commit_msg = f"[aide] 任务: {task_summary}"
|
||||||
|
end_commit = self.git.commit(commit_msg)
|
||||||
|
|
||||||
|
# 记录完成
|
||||||
|
self.record_branch_finish(
|
||||||
|
status="finished",
|
||||||
|
end_commit=end_commit,
|
||||||
|
)
|
||||||
|
|
||||||
|
return True, f"任务分支已合并到 {source_branch}"
|
||||||
|
|
||||||
|
def _merge_with_temp_branch(
|
||||||
|
self,
|
||||||
|
branch_info: BranchInfo,
|
||||||
|
task_summary: str,
|
||||||
|
) -> tuple[bool, str]:
|
||||||
|
"""临时分支合并策略:源分支有新提交时使用"""
|
||||||
|
start_commit = branch_info.start_commit
|
||||||
|
task_branch = branch_info.branch_name
|
||||||
|
temp_branch = f"{task_branch}-merge"
|
||||||
|
|
||||||
|
# 从起始提交检出临时分支
|
||||||
|
self.git.checkout_new_branch(temp_branch, start_commit)
|
||||||
|
|
||||||
|
# 在临时分支执行 squash 合并
|
||||||
|
self.git.merge_squash(task_branch)
|
||||||
|
|
||||||
|
# 创建提交
|
||||||
|
self.git.add_all()
|
||||||
|
commit_msg = f"[aide] 任务压缩提交: {task_summary}"
|
||||||
|
end_commit = self.git.commit(commit_msg)
|
||||||
|
|
||||||
|
# 记录完成(保留任务分支和临时分支)
|
||||||
|
self.record_branch_finish(
|
||||||
|
status="merged-to-temp",
|
||||||
|
end_commit=end_commit,
|
||||||
|
temp_branch=temp_branch,
|
||||||
|
)
|
||||||
|
|
||||||
|
return False, (
|
||||||
|
f"⚠ 源分支 {branch_info.source_branch} 有新提交\n"
|
||||||
|
f"已在临时分支 {temp_branch} 完成合并\n"
|
||||||
|
f"请手动处理后续操作"
|
||||||
|
)
|
||||||
@@ -61,6 +61,71 @@ class GitIntegration:
|
|||||||
files = [line.strip() for line in (result.stdout or "").splitlines() if line.strip()]
|
files = [line.strip() for line in (result.stdout or "").splitlines() if line.strip()]
|
||||||
return path in files
|
return path in files
|
||||||
|
|
||||||
|
# === 分支管理新增方法 ===
|
||||||
|
|
||||||
|
def get_current_branch(self) -> str:
|
||||||
|
"""获取当前分支名"""
|
||||||
|
result = self._run(["rev-parse", "--abbrev-ref", "HEAD"], check=False)
|
||||||
|
if result.returncode != 0:
|
||||||
|
raise FlowError(_format_git_error("获取当前分支失败", result))
|
||||||
|
return (result.stdout or "").strip()
|
||||||
|
|
||||||
|
def is_clean(self) -> bool:
|
||||||
|
"""检查工作目录是否干净(无未提交的变更)"""
|
||||||
|
result = self._run(["status", "--porcelain"], check=False)
|
||||||
|
if result.returncode != 0:
|
||||||
|
raise FlowError(_format_git_error("检查 git 状态失败", result))
|
||||||
|
return not (result.stdout or "").strip()
|
||||||
|
|
||||||
|
def has_commits(self) -> bool:
|
||||||
|
"""检查是否有提交历史"""
|
||||||
|
result = self._run(["rev-parse", "HEAD"], check=False)
|
||||||
|
return result.returncode == 0
|
||||||
|
|
||||||
|
def create_branch(self, name: str, start_point: str | None = None) -> None:
|
||||||
|
"""创建新分支"""
|
||||||
|
args = ["branch", name]
|
||||||
|
if start_point:
|
||||||
|
args.append(start_point)
|
||||||
|
result = self._run(args, check=False)
|
||||||
|
if result.returncode != 0:
|
||||||
|
raise FlowError(_format_git_error(f"创建分支 {name} 失败", result))
|
||||||
|
|
||||||
|
def checkout(self, branch: str) -> None:
|
||||||
|
"""切换到指定分支"""
|
||||||
|
result = self._run(["checkout", branch], check=False)
|
||||||
|
if result.returncode != 0:
|
||||||
|
raise FlowError(_format_git_error(f"切换到分支 {branch} 失败", result))
|
||||||
|
|
||||||
|
def checkout_new_branch(self, name: str, start_point: str | None = None) -> None:
|
||||||
|
"""创建并切换到新分支"""
|
||||||
|
args = ["checkout", "-b", name]
|
||||||
|
if start_point:
|
||||||
|
args.append(start_point)
|
||||||
|
result = self._run(args, check=False)
|
||||||
|
if result.returncode != 0:
|
||||||
|
raise FlowError(_format_git_error(f"创建并切换到分支 {name} 失败", result))
|
||||||
|
|
||||||
|
def has_commits_since(self, commit: str, branch: str) -> bool:
|
||||||
|
"""检查指定分支自某提交后是否有新提交"""
|
||||||
|
result = self._run(["rev-list", f"{commit}..{branch}", "--count"], check=False)
|
||||||
|
if result.returncode != 0:
|
||||||
|
raise FlowError(_format_git_error(f"检查分支 {branch} 新提交失败", result))
|
||||||
|
count = int((result.stdout or "0").strip())
|
||||||
|
return count > 0
|
||||||
|
|
||||||
|
def reset_soft(self, commit: str) -> None:
|
||||||
|
"""软重置到指定提交"""
|
||||||
|
result = self._run(["reset", "--soft", commit], check=False)
|
||||||
|
if result.returncode != 0:
|
||||||
|
raise FlowError(_format_git_error(f"软重置到 {commit} 失败", result))
|
||||||
|
|
||||||
|
def merge_squash(self, branch: str) -> None:
|
||||||
|
"""squash 合并指定分支"""
|
||||||
|
result = self._run(["merge", "--squash", branch], check=False)
|
||||||
|
if result.returncode != 0:
|
||||||
|
raise FlowError(_format_git_error(f"squash 合并分支 {branch} 失败", result))
|
||||||
|
|
||||||
def _run(self, args: list[str], check: bool) -> subprocess.CompletedProcess[str]:
|
def _run(self, args: list[str], check: bool) -> subprocess.CompletedProcess[str]:
|
||||||
return subprocess.run(
|
return subprocess.run(
|
||||||
["git", *args],
|
["git", *args],
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
from aide.core import output
|
from aide.core import output
|
||||||
from aide.core.config import ConfigManager
|
from aide.core.config import ConfigManager
|
||||||
|
from aide.flow.branch import BranchManager
|
||||||
from aide.flow.errors import FlowError
|
from aide.flow.errors import FlowError
|
||||||
from aide.flow.git import GitIntegration
|
from aide.flow.git import GitIntegration
|
||||||
from aide.flow.hooks import run_post_commit_hooks, run_pre_commit_hooks
|
from aide.flow.hooks import run_post_commit_hooks, run_pre_commit_hooks
|
||||||
@@ -23,6 +24,7 @@ class FlowTracker:
|
|||||||
self.cfg = cfg
|
self.cfg = cfg
|
||||||
self.storage = FlowStorage(root)
|
self.storage = FlowStorage(root)
|
||||||
self.git = GitIntegration(root)
|
self.git = GitIntegration(root)
|
||||||
|
self.branch_mgr = BranchManager(root, self.git)
|
||||||
|
|
||||||
def start(self, phase: str, summary: str) -> bool:
|
def start(self, phase: str, summary: str) -> bool:
|
||||||
return self._run(action="start", to_phase=phase, text=summary)
|
return self._run(action="start", to_phase=phase, text=summary)
|
||||||
@@ -61,12 +63,24 @@ class FlowTracker:
|
|||||||
assert to_phase is not None
|
assert to_phase is not None
|
||||||
validator.validate_start(to_phase)
|
validator.validate_start(to_phase)
|
||||||
self.storage.archive_existing_status()
|
self.storage.archive_existing_status()
|
||||||
|
|
||||||
|
# 创建任务分支
|
||||||
|
task_id = now_task_id()
|
||||||
|
task_branch = self.branch_mgr.create_task_branch(
|
||||||
|
task_id=task_id,
|
||||||
|
task_summary=normalized_text,
|
||||||
|
)
|
||||||
|
branch_info = self.branch_mgr.get_active_branch_info()
|
||||||
|
|
||||||
status = FlowStatus(
|
status = FlowStatus(
|
||||||
task_id=now_task_id(),
|
task_id=task_id,
|
||||||
current_phase=to_phase,
|
current_phase=to_phase,
|
||||||
current_step=0,
|
current_step=0,
|
||||||
started_at=now_iso(),
|
started_at=now_iso(),
|
||||||
history=[],
|
history=[],
|
||||||
|
source_branch=branch_info.source_branch if branch_info else None,
|
||||||
|
start_commit=branch_info.start_commit if branch_info else None,
|
||||||
|
task_branch=task_branch,
|
||||||
)
|
)
|
||||||
updated, commit_msg = self._apply_action(
|
updated, commit_msg = self._apply_action(
|
||||||
status=status,
|
status=status,
|
||||||
@@ -80,7 +94,7 @@ class FlowTracker:
|
|||||||
self.storage.save_status(updated)
|
self.storage.save_status(updated)
|
||||||
final_status = self._do_git_commit(updated, commit_msg)
|
final_status = self._do_git_commit(updated, commit_msg)
|
||||||
self.storage.save_status(final_status)
|
self.storage.save_status(final_status)
|
||||||
output.ok(f"任务开始: {to_phase}")
|
output.ok(f"任务开始: {to_phase} (分支: {task_branch})")
|
||||||
run_post_commit_hooks(to_phase=to_phase, action=action)
|
run_post_commit_hooks(to_phase=to_phase, action=action)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -94,6 +108,14 @@ class FlowTracker:
|
|||||||
if action == "next-part":
|
if action == "next-part":
|
||||||
assert to_phase is not None
|
assert to_phase is not None
|
||||||
validator.validate_next_part(current_phase, to_phase)
|
validator.validate_next_part(current_phase, to_phase)
|
||||||
|
|
||||||
|
# 如果进入 finish 环节,执行分支合并
|
||||||
|
if to_phase == "finish":
|
||||||
|
success, merge_msg = self.branch_mgr.finish_branch_merge(
|
||||||
|
task_summary=normalized_text,
|
||||||
|
)
|
||||||
|
if not success:
|
||||||
|
output.warn(merge_msg)
|
||||||
elif action == "back-part":
|
elif action == "back-part":
|
||||||
assert to_phase is not None
|
assert to_phase is not None
|
||||||
validator.validate_back_part(current_phase, to_phase)
|
validator.validate_back_part(current_phase, to_phase)
|
||||||
@@ -181,6 +203,9 @@ class FlowTracker:
|
|||||||
current_step=next_step,
|
current_step=next_step,
|
||||||
started_at=status.started_at,
|
started_at=status.started_at,
|
||||||
history=history,
|
history=history,
|
||||||
|
source_branch=status.source_branch,
|
||||||
|
start_commit=status.start_commit,
|
||||||
|
task_branch=status.task_branch,
|
||||||
)
|
)
|
||||||
return updated_status, message
|
return updated_status, message
|
||||||
|
|
||||||
@@ -207,6 +232,9 @@ class FlowTracker:
|
|||||||
current_step=status.current_step,
|
current_step=status.current_step,
|
||||||
started_at=status.started_at,
|
started_at=status.started_at,
|
||||||
history=updated_history,
|
history=updated_history,
|
||||||
|
source_branch=status.source_branch,
|
||||||
|
start_commit=status.start_commit,
|
||||||
|
task_branch=status.task_branch,
|
||||||
)
|
)
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
|||||||
@@ -54,15 +54,26 @@ class FlowStatus:
|
|||||||
current_step: int
|
current_step: int
|
||||||
started_at: str
|
started_at: str
|
||||||
history: list[HistoryEntry]
|
history: list[HistoryEntry]
|
||||||
|
# 分支管理相关字段
|
||||||
|
source_branch: str | None = None
|
||||||
|
start_commit: str | None = None
|
||||||
|
task_branch: str | None = None
|
||||||
|
|
||||||
def to_dict(self) -> dict[str, Any]:
|
def to_dict(self) -> dict[str, Any]:
|
||||||
return {
|
data: dict[str, Any] = {
|
||||||
"task_id": self.task_id,
|
"task_id": self.task_id,
|
||||||
"current_phase": self.current_phase,
|
"current_phase": self.current_phase,
|
||||||
"current_step": self.current_step,
|
"current_step": self.current_step,
|
||||||
"started_at": self.started_at,
|
"started_at": self.started_at,
|
||||||
"history": [h.to_dict() for h in self.history],
|
"history": [h.to_dict() for h in self.history],
|
||||||
}
|
}
|
||||||
|
if self.source_branch is not None:
|
||||||
|
data["source_branch"] = self.source_branch
|
||||||
|
if self.start_commit is not None:
|
||||||
|
data["start_commit"] = self.start_commit
|
||||||
|
if self.task_branch is not None:
|
||||||
|
data["task_branch"] = self.task_branch
|
||||||
|
return data
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_dict(data: dict[str, Any]) -> "FlowStatus":
|
def from_dict(data: dict[str, Any]) -> "FlowStatus":
|
||||||
@@ -84,6 +95,9 @@ class FlowStatus:
|
|||||||
current_step=current_step,
|
current_step=current_step,
|
||||||
started_at=started_at,
|
started_at=started_at,
|
||||||
history=history,
|
history=history,
|
||||||
|
source_branch=data.get("source_branch"),
|
||||||
|
start_commit=data.get("start_commit"),
|
||||||
|
task_branch=data.get("task_branch"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user