mirror of
https://github.com/stablyai/orca.git
synced 2026-09-30 08:03:12 +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
108 lines
3.3 KiB
TypeScript
108 lines
3.3 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
import {
|
|
clearActiveGitStatusRefBinding,
|
|
updateActiveGitStatusRefBinding,
|
|
type GitStatusRefBindingRequest,
|
|
type GitStatusRefWatchTarget
|
|
} from './worktree-git-status-ref-watch'
|
|
|
|
function makeTarget(): GitStatusRefWatchTarget {
|
|
return {
|
|
kind: 'git-common',
|
|
path: 'C:\\repo\\.git',
|
|
repos: new Map([['repo-1', { repoId: 'repo-1', repoName: 'repo', nestWorkspaces: false }]]),
|
|
gitStatusRefPaths: new Set()
|
|
}
|
|
}
|
|
|
|
describe('worktree git status ref watch binding', () => {
|
|
afterEach(() => clearActiveGitStatusRefBinding())
|
|
|
|
function request(overrides: Partial<GitStatusRefBindingRequest> = {}) {
|
|
return {
|
|
worktreeId: 'repo-1::C:\\repo',
|
|
worktreePath: 'C:\\repo',
|
|
executionHostId: 'local',
|
|
branch: 'refs/heads/feature/main',
|
|
upstreamName: 'origin/feature/main',
|
|
...overrides
|
|
}
|
|
}
|
|
|
|
it('binds a custom refspec destination exactly', async () => {
|
|
const target = makeTarget()
|
|
await updateActiveGitStatusRefBinding(
|
|
request(),
|
|
() => [target],
|
|
async () => 'refs/custom/origin/main'
|
|
)
|
|
|
|
expect([...target.gitStatusRefPaths]).toEqual(['C:/repo/.git/refs/custom/origin/main'])
|
|
})
|
|
|
|
it('does not spend the dynamic ref stat on a slash-named local upstream', async () => {
|
|
const target = makeTarget()
|
|
await updateActiveGitStatusRefBinding(
|
|
request(),
|
|
() => [target],
|
|
async () => 'refs/heads/feature/base'
|
|
)
|
|
|
|
expect(target.gitStatusRefPaths).toEqual(new Set())
|
|
})
|
|
|
|
it('keeps a slash-containing remote name exact', async () => {
|
|
const target = makeTarget()
|
|
await updateActiveGitStatusRefBinding(
|
|
request(),
|
|
() => [target],
|
|
async () => 'refs/remotes/team/fork/feature/main'
|
|
)
|
|
|
|
expect([...target.gitStatusRefPaths]).toEqual([
|
|
'C:/repo/.git/refs/remotes/team/fork/feature/main'
|
|
])
|
|
})
|
|
|
|
it('does not resolve the exact ref again on unchanged status ticks', async () => {
|
|
const target = makeTarget()
|
|
const resolve = vi.fn(async () => 'refs/remotes/origin/feature/main')
|
|
|
|
await updateActiveGitStatusRefBinding(request(), () => [target], resolve)
|
|
await updateActiveGitStatusRefBinding(request(), () => [target], resolve)
|
|
|
|
expect(resolve).toHaveBeenCalledOnce()
|
|
})
|
|
|
|
it('applies an in-flight resolution to a replacement watch', async () => {
|
|
const first = makeTarget()
|
|
const replacement = makeTarget()
|
|
let current = [first]
|
|
let finish: (ref: string) => void = () => {}
|
|
const pending = new Promise<string>((resolve) => {
|
|
finish = resolve
|
|
})
|
|
|
|
const update = updateActiveGitStatusRefBinding(
|
|
request(),
|
|
() => current,
|
|
() => pending
|
|
)
|
|
current = [replacement]
|
|
finish('refs/remotes/origin/feature/main')
|
|
await update
|
|
|
|
expect(first.gitStatusRefPaths).toEqual(new Set())
|
|
expect([...replacement.gitStatusRefPaths]).toEqual([
|
|
'C:/repo/.git/refs/remotes/origin/feature/main'
|
|
])
|
|
|
|
const latest = makeTarget()
|
|
current = [latest]
|
|
const resolve = vi.fn(async () => 'refs/remotes/origin/feature/main')
|
|
await updateActiveGitStatusRefBinding(request(), () => current, resolve)
|
|
expect(resolve).not.toHaveBeenCalled()
|
|
expect([...latest.gitStatusRefPaths]).toEqual(['C:/repo/.git/refs/remotes/origin/feature/main'])
|
|
})
|
|
})
|