🐛 fix(vscode): 摘修复列表与角标认 cherry-pick -x 尾注,解过冲突的复制品不再重复显示
解过冲突的 cherry-pick 复制品补丁内容已变,按文件指纹对不上,列表和角标 都把它当没摘。现在额外扫发布分支独有提交的说明,`(cherry picked from commit <sha>)` 尾注命中的来源提交直接判已摘,列表过滤与 rev-list 计数同步扣掉。 Claude-Session: https://claude.ai/code/session_018HDxMmNDyfLa3bMTUctBzt
This commit is contained in:
1 parent
e99aed15c2
commit
df0660cff7
4 files changed
+42
-9
No files matched your search
@@ -162,12 +162,23 @@ export async function getReleaseStatus(o: { cwd: string, devBranch: string, pref
|
||||
const current = pickCurrentRelease(o.prefix, await remoteBranchNames(o.cwd, o.prefix))
|
||||
if (!current)
|
||||
return base
|
||||
const count = await mustGit(
|
||||
const shas = await mustGit(
|
||||
o.cwd,
|
||||
['rev-list', '--count', '--right-only', '--cherry-pick', '--no-merges', unreleasedRange(current, o.devBranch)],
|
||||
['rev-list', '--right-only', '--cherry-pick', '--no-merges', unreleasedRange(current, o.devBranch)],
|
||||
'统计未发布提交失败',
|
||||
)
|
||||
return { devBranch: o.devBranch, current, unreleased: Number(count) }
|
||||
const picked = await cherryPickedSources(o.cwd, `origin/${o.devBranch}..origin/${current}`)
|
||||
const unreleased = shas.split('\n').filter(sha => sha && !picked.has(sha)).length
|
||||
return { devBranch: o.devBranch, current, unreleased }
|
||||
}
|
||||
|
||||
/**
|
||||
* `cherry-pick -x` 在提交说明末尾留的来源提交号。解过冲突的复制品补丁内容已经变了,
|
||||
* 指纹对不上,只剩这条线索能认出它摘过。
|
||||
*/
|
||||
async function cherryPickedSources(cwd: string, range: string): Promise<Set<string>> {
|
||||
const bodies = await mustGit(cwd, ['log', '--no-merges', '--format=%b', range], '读取发布分支提交说明失败')
|
||||
return new Set(Array.from(bodies.matchAll(/\(cherry picked from commit ([0-9a-f]{40})\)/g), m => m[1]))
|
||||
}
|
||||
|
||||
/** 新→旧;不 fetch,调用方自己决定何时刷新远端 */
|
||||
@@ -276,20 +287,24 @@ export async function listUnreleasedCommits(o: { cwd: string, devBranch: string,
|
||||
)
|
||||
if (!out)
|
||||
return []
|
||||
const releaseOnly = `origin/${o.devBranch}..origin/${o.current}`
|
||||
const picked = await cherryPickedSources(o.cwd, releaseOnly)
|
||||
const commits = out.split('\x1E').flatMap((chunk) => {
|
||||
const trimmed = chunk.replace(/^\n+/, '').trimEnd()
|
||||
if (!trimmed)
|
||||
return []
|
||||
const [sha, subject, author, date, body = ''] = trimmed.split('\0')
|
||||
return [{ sha, subject, author, date, body: body.trim() }]
|
||||
return picked.has(sha) ? [] : [{ sha, subject, author, date, body: body.trim() }]
|
||||
})
|
||||
if (commits.length === 0)
|
||||
return []
|
||||
const perCommit = await fileChangeKeysByCommit(o.cwd, ['--right-only', '--cherry-pick', unreleasedRange(o.current, o.devBranch)])
|
||||
const files = new Set<string>()
|
||||
for (const keys of perCommit.values()) {
|
||||
for (const key of keys)
|
||||
for (const c of commits) {
|
||||
for (const key of perCommit.get(c.sha) ?? [])
|
||||
files.add(key.slice(0, key.indexOf('\0')))
|
||||
}
|
||||
const onRelease = await fileChangeKeysByCommit(o.cwd, [`origin/${o.devBranch}..origin/${o.current}`], files)
|
||||
const onRelease = await fileChangeKeysByCommit(o.cwd, [releaseOnly], files)
|
||||
const released = new Set<string>()
|
||||
for (const keys of onRelease.values()) {
|
||||
for (const key of keys)
|
||||
|
||||
Reference in new issue
Block a user