Files
orca/src/shared/git-worktree-admin.test.ts
T
Neil 62451920ed fix(git): preserve SSH review context and worktree ownership (#24945)
* fix(git): preserve SSH arguments and guard background writes

* test(terminal): settle fish fixture startup readiness

* fix(git): preserve bare UNC SSH paths

* fix(git): unescape shell operators in Windows SSH paths

* test(runtime): settle removal writes before fixture cleanup

* test(git): skip optional OpenSSH probe when unavailable

* perf(git): skip equal-tip reads and bound relay discovery

* test(processes): ratchet the removed relay Git spawn

* test(shells): wait for initial zsh output before sending input

* Fix SSH review context and recover Git maintenance cleanup safely

* Keep relay Git compatibility fixtures outside shared client projects

* Fence superseded maintenance and preserve mixed-version session search

* test: model Git child termination and search catalogs

* test: retain catalog authority over history flags
2026-10-03 05:24:35 -07:00

242 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { mkdir, mkdtemp, rename, rm, symlink, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import path from 'node:path'
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
import { resolveGitCommonDirectory } from './git-common-directory'
import {
annotateWorktreeLocksFromAdmin,
findLinkedWorktreeGitDirectory,
isBranchReservedByWorktreeOperation
} from './git-worktree-admin'
import type { GitWorktreeInfo } from './worktree/types'
import { isWorktreeCreatePreparation } from './worktree/create-preparation'
let root = ''
let repo = ''
let common = ''
let linked = ''
let admin = ''
const preparationReason = 'orca-create-preparation:v1:12345:lease'
function rows(): GitWorktreeInfo[] {
return [
{ path: repo, branch: 'refs/heads/main', head: 'abc', isBare: false, isMainWorktree: true },
{ path: linked, branch: '', head: 'abc', isBare: false, isMainWorktree: false }
]
}
beforeEach(async () => {
root = await mkdtemp(path.join(tmpdir(), 'orca-admin-safety-'))
repo = path.join(root, 'repo')
common = path.join(repo, '.git')
linked = path.join(root, '.orca-preparing', 'checkout')
admin = path.join(common, 'worktrees', 'checkout')
await mkdir(admin, { recursive: true })
await mkdir(linked, { recursive: true })
await writeFile(path.join(common, 'HEAD'), 'ref: refs/heads/main\n')
await writeFile(path.join(admin, 'gitdir'), `${path.join(linked, '.git')}\n`)
await writeFile(path.join(admin, 'commondir'), '../..\n')
await writeFile(path.join(linked, '.git'), `gitdir: ${admin}\r\n`)
})
afterEach(async () => {
await rm(root, { recursive: true, force: true })
})
describe('owning-host worktree administrative reads', () => {
it('finds one exact linked registration after its checkout disappears', async () => {
await rm(linked, { recursive: true })
await expect(findLinkedWorktreeGitDirectory(repo, linked)).resolves.toBe(admin)
await expect(findLinkedWorktreeGitDirectory(repo, `${linked}-other`)).resolves.toBeNull()
await expect(findLinkedWorktreeGitDirectory(repo, repo)).resolves.toBeNull()
await writeFile(
path.join(admin, 'gitdir'),
`${path.relative(admin, path.join(linked, '.git'))}\n`
)
await expect(findLinkedWorktreeGitDirectory(repo, linked)).resolves.toBe(admin)
})
it('rejects duplicate registrations instead of choosing an owner marker', async () => {
const duplicate = path.join(common, 'worktrees', 'duplicate')
await mkdir(duplicate)
await writeFile(path.join(duplicate, 'gitdir'), `${path.join(linked, '.git')}\n`)
await expect(findLinkedWorktreeGitDirectory(repo, linked)).rejects.toThrow(
'Cannot verify linked worktree administration'
)
})
it('rejects a backlink to a file other than the checkout gitfile', async () => {
await writeFile(path.join(admin, 'gitdir'), `${path.join(linked, 'other')}\n`)
await expect(findLinkedWorktreeGitDirectory(repo, linked)).rejects.toThrow(
'Cannot verify linked worktree administration'
)
})
it.runIf(process.platform !== 'win32')(
'rejects administrative directories redirected outside the common directory',
async () => {
const outside = path.join(root, 'outside-administration')
const worktrees = path.join(common, 'worktrees')
await rename(worktrees, outside)
await symlink(outside, worktrees)
await expect(findLinkedWorktreeGitDirectory(repo, linked)).rejects.toThrow(
'Cannot verify linked worktree administration'
)
}
)
it.runIf(process.platform !== 'win32')('rejects symlinked backlink files', async () => {
const outside = path.join(root, 'outside-backlink')
await writeFile(outside, `${path.join(linked, '.git')}\n`)
await rm(path.join(admin, 'gitdir'))
await symlink(outside, path.join(admin, 'gitdir'))
await expect(findLinkedWorktreeGitDirectory(repo, linked)).rejects.toThrow(
'Cannot verify linked worktree administration'
)
})
it.runIf(process.platform !== 'win32')(
'rejects symlink administrative entries instead of overlooking duplicates',
async () => {
await symlink(admin, path.join(common, 'worktrees', 'duplicate-link'))
await expect(findLinkedWorktreeGitDirectory(repo, linked)).rejects.toThrow(
'Cannot verify linked worktree administration'
)
}
)
it('resolves normal, linked, separate-git-dir and bare layouts without subprocesses', async () => {
await expect(resolveGitCommonDirectory(repo)).resolves.toBe(common)
await expect(resolveGitCommonDirectory(linked)).resolves.toBe(common)
await expect(resolveGitCommonDirectory(common)).resolves.toBe(common)
const separate = path.join(root, 'separate')
await mkdir(separate)
await writeFile(path.join(separate, '.git'), 'gitdir: ../repo/.git\r\n')
await expect(resolveGitCommonDirectory(separate)).resolves.toBe(common)
})
it('recovers exact preparation reasons even when the checkout directory is missing', async () => {
await writeFile(path.join(admin, 'locked'), `${preparationReason}\n`)
await rm(linked, { recursive: true })
const annotated = await annotateWorktreeLocksFromAdmin(repo, rows())
expect(annotated[1]).toMatchObject({ locked: true, lockReason: preparationReason })
expect(isWorktreeCreatePreparation(annotated[1])).toBe(true)
})
it('keeps empty and foreign locks without claiming preparations by path shape', async () => {
await writeFile(path.join(admin, 'locked'), '')
const empty = await annotateWorktreeLocksFromAdmin(repo, rows())
expect(empty[1].locked).toBe(true)
expect(isWorktreeCreatePreparation(empty[1])).toBe(false)
await writeFile(path.join(admin, 'locked'), 'user session\n')
const foreign = await annotateWorktreeLocksFromAdmin(repo, rows())
expect(foreign[1]).toMatchObject({ locked: true, lockReason: 'user session' })
expect(isWorktreeCreatePreparation(foreign[1])).toBe(false)
})
it('does not treat an unreadable marker as an unlocked authoritative registration', async () => {
await mkdir(path.join(admin, 'locked'))
await expect(annotateWorktreeLocksFromAdmin(repo, rows())).rejects.toThrow()
})
it('does not cache a replaced lock reason or another repository’s metadata', async () => {
await writeFile(path.join(admin, 'locked'), `${preparationReason}\n`)
expect((await annotateWorktreeLocksFromAdmin(repo, rows()))[1].lockReason).toBe(
preparationReason
)
await writeFile(path.join(admin, 'locked'), 'replacement\n')
expect((await annotateWorktreeLocksFromAdmin(repo, rows()))[1].lockReason).toBe('replacement')
const other = path.join(root, 'other')
await mkdir(path.join(other, '.git'), { recursive: true })
await writeFile(path.join(other, '.git', 'HEAD'), 'ref: refs/heads/main\n')
const otherRows = rows().map((row) => (row.isMainWorktree ? { ...row, path: other } : row))
expect((await annotateWorktreeLocksFromAdmin(other, otherRows))[1].locked).toBeUndefined()
})
it.each(['rebase-merge/head-name', 'rebase-apply/head-name', 'BISECT_START'])(
'checks detached main worktrees as well as linked ones: %s',
async (marker) => {
const file = path.join(common, ...marker.split('/'))
await mkdir(path.dirname(file), { recursive: true })
await writeFile(file, 'refs/heads/feature\n')
const detachedMain = rows().map((row) => (row.isMainWorktree ? { ...row, branch: '' } : row))
await expect(
isBranchReservedByWorktreeOperation(repo, 'feature', detachedMain)
).resolves.toBe(true)
await expect(isBranchReservedByWorktreeOperation(repo, 'other', detachedMain)).resolves.toBe(
false
)
}
)
it('fails closed when a detached registration cannot be associated with admin metadata', async () => {
await rm(path.join(admin, 'gitdir'))
await expect(isBranchReservedByWorktreeOperation(repo, 'feature', rows())).rejects.toThrow(
'Cannot verify worktree branch usage'
)
})
it.each([40, 64])(
'protects auxiliary rebase refs with %i-character OIDs on attached worktrees',
async (length) => {
await mkdir(path.join(admin, 'rebase-merge'))
const before = 'a'.repeat(length)
const after = '0'.repeat(length)
await writeFile(
path.join(admin, 'rebase-merge', 'update-refs'),
`refs/heads/other\r\n${before}\r\n${after}\r\nrefs/heads/feature\r\n${before}\r\n${after}\r\n`
)
const attached = rows().map((row) => ({ ...row, branch: 'refs/heads/main' }))
await expect(isBranchReservedByWorktreeOperation(repo, 'feature', attached)).resolves.toBe(
true
)
await expect(isBranchReservedByWorktreeOperation(repo, 'unreserved', attached)).resolves.toBe(
false
)
}
)
it('checks update-refs in the main worktree and compares only ref-name fields', async () => {
await mkdir(path.join(common, 'rebase-merge'))
await writeFile(
path.join(common, 'rebase-merge', 'update-refs'),
`refs/heads/feature\n${'a'.repeat(40)}\n${'0'.repeat(40)}\n`
)
await expect(isBranchReservedByWorktreeOperation(repo, 'feature', rows())).resolves.toBe(true)
await expect(isBranchReservedByWorktreeOperation(repo, 'a'.repeat(40), rows())).resolves.toBe(
false
)
})
it.each([
`refs/heads/feature\n${'a'.repeat(40)}\n`,
`refs/heads/feature\n${'a'.repeat(40)}\n${'g'.repeat(40)}\n`,
`refs/heads/feature\n${'a'.repeat(40)}\n${'0'.repeat(64)}\n`,
`refs/heads/feature\n${'a'.repeat(40)}\n${'0'.repeat(40)}\ninvalid\n`
])('fails closed on malformed update-refs records: %s', async (contents) => {
await mkdir(path.join(admin, 'rebase-merge'))
await writeFile(path.join(admin, 'rebase-merge', 'update-refs'), contents)
await expect(isBranchReservedByWorktreeOperation(repo, 'feature', rows())).rejects.toThrow(
'Cannot verify rebase update-refs branch usage'
)
})
it('fails closed when update-refs cannot be read', async () => {
await mkdir(path.join(admin, 'rebase-merge', 'update-refs'), { recursive: true })
await expect(isBranchReservedByWorktreeOperation(repo, 'feature', rows())).rejects.toThrow()
})
it('propagates cancellation during administrative reads', async () => {
const signal = AbortSignal.abort(new Error('cancelled'))
await expect(annotateWorktreeLocksFromAdmin(repo, rows(), { signal })).rejects.toThrow(
'cancelled'
)
await expect(
isBranchReservedByWorktreeOperation(repo, 'feature', rows(), { signal })
).rejects.toThrow('cancelled')
await expect(findLinkedWorktreeGitDirectory(repo, linked, { signal })).rejects.toThrow(
'cancelled'
)
})
})