✨ feat(vscode): 摘修复按 PR 分组框选,可搜作者和标题

This commit is contained in:
cruldra committed 2026-09-01 17:27:27 +08:00
1 parent 0031851df3
commit 3e3750c494
9 files changed
+353 -42

No files matched your search

+26 -35
View File
@@ -12,6 +12,7 @@ import {
cherryPickToRelease,
cutRelease,
getReleaseStatus,
groupCommitsByPr,
listReleaseBranches,
listUnreleasedCommits,
todayReleaseBranch,
@@ -85,10 +86,8 @@ export function handleReleaseCut(panel: KanbanWebviewPanel): Promise<void> {
})
}
interface CommitPickItem { label: string, description: string, sha: string }
export function handleReleaseCherryPick(panel: KanbanWebviewPanel): Promise<void> {
return runReleaseAction(panel, async () => {
export async function handleReleaseCherryPick(panel: KanbanWebviewPanel): Promise<void> {
try {
const root = requireRoot()
const s = getSettings(panel.context)
const status = await getReleaseStatus({ cwd: root, devBranch: s.devBranch, prefix: s.releaseBranchPrefix })
@@ -102,44 +101,36 @@ export function handleReleaseCherryPick(panel: KanbanWebviewPanel): Promise<void
toast(panel, 'info', '没有待摘的提交')
return
}
const picked = await pickCommits(current, commits.map(c => ({
label: c.subject,
description: `${c.sha.slice(0, 7)} · ${c.author} · ${c.date}`,
sha: c.sha,
})))
if (!picked || picked.length === 0)
panel.postMessage({ type: 'release/pick-show', branch: current, groups: groupCommitsByPr(commits) })
}
catch (err) {
toast(panel, 'error', err instanceof Error ? err.message : String(err), { dismissOnTimer: 10_000 })
}
}
export function handleReleaseCherryPickConfirm(panel: KanbanWebviewPanel, shas: string[]): Promise<void> {
return runReleaseAction(panel, async () => {
if (shas.length === 0)
return
// 列表是 git log 顺序(新→旧),cherry-pick 要按时间顺序(旧→新)
const root = requireRoot()
const s = getSettings(panel.context)
const status = await getReleaseStatus({ cwd: root, devBranch: s.devBranch, prefix: s.releaseBranchPrefix })
if (status.unavailable)
throw new Error(status.unavailable)
const current = status.current
if (!current)
throw new Error('尚无发布分支,先切新发布')
const commits = await listUnreleasedCommits({ cwd: root, devBranch: s.devBranch, current })
const order = new Map(commits.map((c, i) => [c.sha, i]))
const shas = [...picked].sort((a, b) => (order.get(b.sha) ?? 0) - (order.get(a.sha) ?? 0)).map(p => p.sha)
const spinner = toast(panel, 'info', `正在摘 ${shas.length} 个提交到 ${current}…`, { spinner: true, dismissOnTimer: 0 })
const ordered = [...shas].sort((a, b) => (order.get(b) ?? 0) - (order.get(a) ?? 0))
const spinner = toast(panel, 'info', `正在摘 ${ordered.length} 个提交到 ${current}…`, { spinner: true, dismissOnTimer: 0 })
try {
await cherryPickToRelease({ cwd: root, branch: current, shas })
await cherryPickToRelease({ cwd: root, branch: current, shas: ordered })
}
finally {
dismiss(panel, spinner)
}
toast(panel, 'success', `已摘 ${shas.length} 个提交到 ${current}`)
})
}
/** 多选 QuickPick;用户按 Esc 返回 undefined */
function pickCommits(current: string, items: CommitPickItem[]): Promise<CommitPickItem[] | undefined> {
return new Promise((resolve) => {
const qp = window.createQuickPick<CommitPickItem>()
qp.canSelectMany = true
qp.title = `摘修复到 ${current}`
qp.placeholder = '勾选要摘到发布分支的提交'
qp.items = items
qp.onDidAccept(() => {
resolve([...qp.selectedItems])
qp.hide()
})
qp.onDidHide(() => {
resolve(undefined)
qp.dispose()
})
qp.show()
toast(panel, 'success', `已摘 ${ordered.length} 个提交到 ${current}`)
})
}