perf(git): read the porcelain worktree mode instead of probing conflicted paths

Every porcelain-v2 `u` record already carries `mW`, the working-tree mode Git
stat'ed for that row: `000000` means the conflicted path is absent. Reading it
replaces the per-conflict `fs.access`, so the bounded-concurrency resolver, its
`= 8` cap, and the order/error-precedence invariant are unnecessary rather than
cheaper. `access()` stays only as a fallback for a malformed `mW`, so
`parseUnmergedEntry` keeps its signature and neither status-read.ts nor the
relay loop changes.

Also corrects two fixtures that encoded `mW=100644` for a file that does not
exist, which real Git never emits.
This commit is contained in:
Neil
2026-09-03 20:40:04 -07:00
parent 482f8aa4b4
commit 104f44222e
5 changed files with 90 additions and 260 deletions
+3 -27
View File
@@ -18,10 +18,7 @@ import { findExistingWorktreeSymlinkPaths } from '../worktree-symlink-detection'
import type { GetStatusOptions } from './get-status-options'
import { statusReadLeaseOwner } from './git-read-cache-invalidation'
import { detectConflictOperation } from './git-conflict-operation'
import {
parseUnmergedEntry,
resolveUnmergedStatusRecords
} from '../../../shared/git-status-conflict-entries'
import { parseUnmergedEntry } from '../../../shared/git-status-conflict-entries'
import { getEffectiveUpstreamStatusCacheKey } from './effective-upstream-status-cache'
import {
getShortBranchName,
@@ -179,37 +176,16 @@ async function runGetStatus(
// Why: git runs in the distro and answers in its namespace; the working-tree probes below run here.
const hostWorktreePath = resolveWorktreeHostPath(worktreePath, options) ?? worktreePath
// Why: a record only pushes one entry, so the cap can never break before index `limit`; prefetching
// exactly that prefix keeps the probe count identical to a serial read on a truncated status.
const resolvableUnmergedEnd = didHitLimit
? Math.min(parser.statusRecords.length, limit)
: parser.statusRecords.length
// Why: skip the prefetch entirely for the conflict-free poll so the common path allocates nothing extra.
const resolvedUnmerged =
parser.unmergedLines.length > 0
? await resolveUnmergedStatusRecords(
hostWorktreePath,
parser.statusRecords,
resolvableUnmergedEnd
)
: undefined
// Why: resolve deferred conflicts in Git's output order so the cap cannot hide
// an early conflict behind ordinary rows that appeared later in the stream.
for (const [index, record] of parser.statusRecords.entries()) {
for (const record of parser.statusRecords) {
if (didHitLimit && entries.length >= limit) {
break
}
if (record.type === 'entry') {
entries.push(record.entry)
} else {
const prefetched = resolvedUnmerged?.[index]
if (prefetched?.ok === false) {
throw prefetched.error
}
const unmergedEntry = prefetched
? prefetched.entry
: await parseUnmergedEntry(hostWorktreePath, record.line)
const unmergedEntry = await parseUnmergedEntry(hostWorktreePath, record.line)
if (unmergedEntry) {
entries.push(unmergedEntry)
}