✨ feat(vscode): 手动删除 worktree 时连同 feature 分支一起删(本地+远程)

抽出共享 cleanupFeatureBranch(handlers/branchCleanup.ts):受保护分支跳过、
远程走 gitea API、本地强删(git branch -D),全程 best-effort 只记日志。
「拖到完成」的分支清理改为复用它(71 行 → 12 行);handleDeleteWorktree 在
删完 worktree 目录后同样调用它,确认框与完成提示带上分支名。

放在 handlers 层而非 git/branchSync.ts:后者刻意不依赖 vscode(有单测覆盖
deleteLocalBranch),本函数需 logger(→vscode)+ gitea API。
This commit is contained in:
cruldra committed 2026-07-08 19:05:48 +08:00
1 parent 045e203590
commit f39e61aa7f
3 files changed
+108 -71

No files matched your search

+25 -5
View File
@@ -14,6 +14,7 @@ import {
import { logger } from '../../logging/logger'
import { getSettings } from '../../settings/store'
import { makeNonce } from '../KanbanPanel'
import { cleanupFeatureBranch } from './branchCleanup'
/**
* Open the worktree directory in a **new** VS Code window. The Boolean
@@ -59,8 +60,10 @@ export async function handleOpenWorktree(panel: KanbanWebviewPanel, relPath: str
}
/**
* Confirm + 递归强删 worktree 目录(removeWorktreeDir),然后清掉 state JSON 里的
* `worktreePath`/`branch` 并刷新看板。删除失败(如权限、护栏拦截)把错误弹给用户。
* Confirm + 递归强删 worktree 目录(removeWorktreeDir)→ 清掉 state JSON 里的
* `worktreePath`/`branch` → 连同该工单的 feature 分支一起删(本地 + 远程,best-effort)
* → 刷新看板。目录删除失败(权限 / 护栏拦截)把错误弹给用户;分支清理失败只记日志、
* 不阻断——与「拖到完成」的清理行为一致。
*/
export async function handleDeleteWorktree(panel: KanbanWebviewPanel, issueNumber: number, relPath: string): Promise<void> {
const workspaceRoot = workspace.workspaceFolders?.[0]?.uri.fsPath
@@ -68,8 +71,11 @@ export async function handleDeleteWorktree(panel: KanbanWebviewPanel, issueNumbe
void window.showErrorMessage('请先打开一个工作区文件夹')
return
}
// 先读分支名:确认框要提示「连分支一起删」,删完目录后也据此清分支。
const state = await panel.readIssueState(issueNumber)
const branch = typeof state.branch === 'string' ? state.branch : ''
const choice = await window.showWarningMessage(
`确认删除 worktree ${relPath}?`,
branch ? `确认删除 worktree ${relPath} 及其分支 ${branch}?` : `确认删除 worktree ${relPath}?`,
{ modal: true },
'删除',
)
@@ -85,7 +91,7 @@ export async function handleDeleteWorktree(panel: KanbanWebviewPanel, issueNumbe
await dispatchWorktreeHook(panel, 'pre-remove', {
workspaceRoot,
worktreePath: abs,
branch: '',
branch,
issueNumber,
mainBranch: settingsForHook.devBranch || 'main',
customScriptPath: settingsForHook.worktreePreRemoveScript,
@@ -110,6 +116,20 @@ export async function handleDeleteWorktree(panel: KanbanWebviewPanel, issueNumbe
console.warn('[superpowers] failed to clear worktree state JSON:', err)
}
// 连同 feature 分支一起删(本地 + 远程,best-effort)。受保护分支跳过、缺 token 只删本地,
// 逻辑与「拖到完成」共用同一个 cleanupFeatureBranch。
const remote = await detectRepo(workspaceRoot)
const token = remote ? await getToken(panel.context, remote.host) : undefined
await cleanupFeatureBranch({
workspaceRoot,
branch,
issueNumber,
devBranch: settingsForHook.devBranch,
autoBuildBranch: settingsForHook.autoBuildBranch,
remote: remote ? { host: remote.host, owner: remote.owner, repo: remote.repo } : undefined,
token,
})
panel.postMessage({
type: 'issue/patch',
issueNumber,
@@ -119,7 +139,7 @@ export async function handleDeleteWorktree(panel: KanbanWebviewPanel, issueNumbe
worktreeExists: false,
},
})
void window.showInformationMessage(`已删除 worktree #${issueNumber}`)
void window.showInformationMessage(`已删除 worktree #${issueNumber}${branch ? `(含分支 ${branch})` : ''}`)
}
/**