Files
orca/src/shared/git-change-list.ts
T
Neil 328caa2160 fix(git): reduce queries and preserve data across execution hosts (#24602)
* fix(git): reduce queries and preserve data across execution hosts

* fix(ci): exercise pinned Git and serialize mobile dependency entrypoints

* fix(relay): preserve fresh diff retries after hung shared reads

* test(git): wait for fetch barrier before canceling preparation

* fix(i18n): describe index-preserving discard in every locale

* fix(git): retain clone diagnostics and allow WSL policy startup

* test(git): refresh default-base and branch-safety fixtures
2026-10-02 18:05:37 -07:00

55 lines
1.8 KiB
TypeScript

import type { GitBranchChangeEntry } from './git-diff-compare-types'
import type { GitBranchChangeStatus } from './git-status-types'
import { parseNumstat } from './git-uncommitted-line-stats'
const CHANGE_STATUS: Record<string, GitBranchChangeStatus> = {
A: 'added',
D: 'deleted',
R: 'renamed',
C: 'copied'
}
export function gitChangeListArgs(fromOid: string | null, toOid: string): string[] {
const format = ['--raw', '--numstat', '-z', '-M', '-C']
return fromOid
? ['diff', ...format, fromOid, toOid, '--']
: ['diff-tree', '--root', '--no-commit-id', '-r', ...format, toOid, '--']
}
export function parseGitChangeList(stdout: string): GitBranchChangeEntry[] {
const entries: GitBranchChangeEntry[] = []
let offset = 0
function readField(): string {
const end = stdout.indexOf('\0', offset)
if (end === -1) {
throw new Error('Incomplete Git change record')
}
const value = stdout.slice(offset, end)
offset = end + 1
return value
}
// Raw records precede numstat records; filenames are separate NUL-delimited fields.
while (stdout[offset] === ':') {
const header = readField()
const match = /^:[0-7]{6} [0-7]{6} [0-9a-f]+ [0-9a-f]+ ([A-Z])\d*$/.exec(header)
if (!match) {
throw new Error('Invalid Git change record')
}
const code = match[1] ?? ''
const firstPath = readField()
const oldPath = code === 'R' || code === 'C' ? firstPath : undefined
const path = oldPath === undefined ? firstPath : readField()
if (!path || oldPath === '') {
throw new Error('Missing Git change path')
}
entries.push({
path,
status: CHANGE_STATUS[code] ?? 'modified',
...(oldPath === undefined ? {} : { oldPath })
})
}
const statsByPath = parseNumstat(stdout.slice(offset))
return entries.map((entry) => ({ ...entry, ...statsByPath.get(entry.path) }))
}