Files
orca/src/main/ipc/worktree-git-common-entry-snapshot.ts
T
Brennan Benson de64337c26 fix(worktree-watcher): refresh status after external pushes (#12361)
* fix(worktree-watcher): surface external push -u through the git-common watch

An external-shell 'git push -u' writes only the common .git/config (plus
refs/remotes/<remote>/<branch>), both invisible to the git-common event
filter, so the Checks panel stayed on 'No upstream configured' until the
renderer safety poll. Classify the common config and remote-tracking refs
as status-tier signals, poll config alongside the other primary-checkout
metadata files, and keep FETCH_HEAD/reflog/ref-lock churn ignored.

* fix(worktree-watcher): refresh after subsequent pushes
2026-08-05 11:26:13 -07:00

77 lines
2.3 KiB
TypeScript

import { stat } from 'node:fs/promises'
import { join } from 'node:path'
const STRUCTURAL_METADATA_FILES = ['HEAD', 'gitdir', 'locked', 'config.worktree']
const INDEX_FILE = 'index'
const HEAD_LOG_FILE = join('logs', 'HEAD')
function statSignature(value: { mtimeMs: number; ctimeMs: number; ino: number }): string {
return `${value.mtimeMs}:${value.ctimeMs}:${value.ino}`
}
export async function gitCommonDirectorySignature(path: string): Promise<string> {
try {
const value = await stat(path)
return `${statSignature(value)}:${value.size}`
} catch {
return 'missing'
}
}
export async function gitCommonFileSignature(path: string): Promise<string | null> {
try {
const value = await stat(path)
return value.isFile() ? `${statSignature(value)}:${value.size}` : null
} catch {
return null
}
}
export type GitCommonEntrySnapshot = {
dirSignature: string
structuralSignatures: Map<string, string>
indexSignature: string | null
headLogSignature: string | null
}
export async function snapshotGitCommonEntry(
entryPath: string,
previous: GitCommonEntrySnapshot | undefined,
forceFullScan: boolean
): Promise<GitCommonEntrySnapshot> {
// Structural leaves change in place every tick; only index uses the entry-dir gate.
const structuralSignatures = new Map<string, string>()
const [nextDirSignature, headLogSignature] = await Promise.all([
gitCommonDirectorySignature(entryPath),
gitCommonFileSignature(join(entryPath, HEAD_LOG_FILE)),
Promise.all(
STRUCTURAL_METADATA_FILES.map(async (name) => {
const signature = await gitCommonFileSignature(join(entryPath, name))
if (signature !== null) {
structuralSignatures.set(name, signature)
}
})
)
])
if (nextDirSignature === 'missing') {
return (
previous ?? {
dirSignature: nextDirSignature,
structuralSignatures,
indexSignature: null,
headLogSignature
}
)
}
const shouldReadIndex = forceFullScan || !previous || previous.dirSignature !== nextDirSignature
const indexSignature = shouldReadIndex
? await gitCommonFileSignature(join(entryPath, INDEX_FILE))
: previous.indexSignature
return {
dirSignature: nextDirSignature,
structuralSignatures,
indexSignature,
headLogSignature
}
}