mirror of
https://github.com/stablyai/orca.git
synced 2026-10-23 16:03:49 +00:00
* 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
77 lines
2.3 KiB
TypeScript
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
|
|
}
|
|
}
|