mirror of
https://github.com/stablyai/orca.git
synced 2026-10-13 08:02:52 +00:00
* 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
242 lines
10 KiB
TypeScript
242 lines
10 KiB
TypeScript
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'
|
||
)
|
||
})
|
||
})
|