Files
orca/src/main/ipc/git-status-upstream-ref-watch-request.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

79 lines
2.7 KiB
TypeScript

import type { Store } from '../persistence'
import { resolveGitStatusUpstreamRef } from '../git/status-upstream-ref'
import { gitExecFileAsync } from '../git/runner'
import {
getSshGitProvider,
getSshGitProviderGeneration,
SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE
} from '../providers/ssh-git-dispatch'
import { resolveRegisteredWorktreePath } from './filesystem-auth'
import {
getLocalGitOptionsForRepo,
getLocalRepoForRegisteredWorktree
} from './local-worktree-runtime-options'
import { setWorktreeGitStatusRefWatch } from './worktree-base-directory-watcher'
import type { GitStatusRefBindingRequest } from './worktree-git-status-ref-watch'
export type GitStatusUpstreamRefWatchRequest = Omit<
GitStatusRefBindingRequest,
'providerGeneration'
>
const UPSTREAM_REF_RESOLUTION_TIMEOUT_MS = 15_000
function boundedSignal(signal: AbortSignal): AbortSignal {
return AbortSignal.any([signal, AbortSignal.timeout(UPSTREAM_REF_RESOLUTION_TIMEOUT_MS)])
}
export function applyGitStatusUpstreamRefWatchRequest(
store: Store,
args: GitStatusUpstreamRefWatchRequest
): Promise<void> {
const providerGeneration = args.connectionId
? getSshGitProviderGeneration(args.connectionId)
: undefined
return setWorktreeGitStatusRefWatch(
{ ...args, ...(providerGeneration !== undefined ? { providerGeneration } : {}) },
async (bindingSignal) => {
if (!args.branch || !args.upstreamName) {
return undefined
}
const signal = boundedSignal(bindingSignal)
if (args.connectionId) {
const provider = getSshGitProvider(args.connectionId)
if (!provider) {
throw new Error(SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE)
}
return resolveGitStatusUpstreamRef(
(gitArgs, cwd, requestSignal) =>
provider.exec(gitArgs, cwd, {
signal: requestSignal,
timeoutMs: UPSTREAM_REF_RESOLUTION_TIMEOUT_MS
}),
args.worktreePath,
args.branch,
args.upstreamName,
signal
)
}
const worktreePath = await resolveRegisteredWorktreePath(args.worktreePath, store)
const repo = getLocalRepoForRegisteredWorktree(store, args.worktreePath, worktreePath)
const gitOptions = getLocalGitOptionsForRepo(store, repo)
return resolveGitStatusUpstreamRef(
(gitArgs, cwd, requestSignal) =>
gitExecFileAsync(gitArgs, {
cwd,
signal: requestSignal,
timeout: UPSTREAM_REF_RESOLUTION_TIMEOUT_MS,
...(gitOptions.wslDistro ? { wslDistro: gitOptions.wslDistro } : {})
}),
worktreePath,
args.branch,
args.upstreamName,
signal
)
}
)
}