mirror of
https://github.com/stablyai/orca.git
synced 2026-11-03 10:37:35 +00:00
* [comment audit] Shorten daemon, hook, and emulator comments [skip ci] * [comment audit] Shorten VM, conversation, SQLite, and theme-import comments [skip ci] * [comment audit] Tighten Git execution and source-control comment contracts [skip ci] * [comment audit] Clarify repository probes and maintenance comments [skip ci] * [comment audit] Shorten status, diff-cache, and checkout comments [skip ci] * [comment audit] Clarify worktree lifecycle and WSL routing comments [skip ci] * [comment audit] Shorten forge identity and review-refresh comments [skip ci] * [comment audit] Tighten hosted-review client comment contracts [skip ci] * [comment audit] Clarify GitLab compatibility and review comments [skip ci] * [comment audit] Tighten hook ownership and watchdog rationale [skip ci] * [comment audit] Condense host and integration compatibility comments [skip ci] * [comment audit] Clarify IPC authority and remote-routing rationale [skip ci] * [comment audit] Finalize file-import and containment comment cleanup * [comment audit] Fix stale Jira type imports blocking full CI --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
227 lines
8.4 KiB
TypeScript
227 lines
8.4 KiB
TypeScript
import { access, chmod, mkdir, mkdtemp, rm, symlink, writeFile } from 'node:fs/promises'
|
|
import { tmpdir } from 'node:os'
|
|
import path from 'node:path'
|
|
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
|
|
import { isCommandOnLocalPath, listLocalCommandPaths } from './command-path-resolver'
|
|
|
|
describe('isCommandOnLocalPath', () => {
|
|
it('returns false for an empty command', async () => {
|
|
await expect(isCommandOnLocalPath('')).resolves.toBe(false)
|
|
})
|
|
|
|
// POSIX semantics: executable bit + absolute-only + symlink follow.
|
|
describe.skipIf(process.platform === 'win32')('posix', () => {
|
|
let dir = ''
|
|
beforeAll(async () => {
|
|
dir = await mkdtemp(path.join(tmpdir(), 'cmd-resolver-posix-'))
|
|
await writeFile(path.join(dir, 'runme'), '#!/bin/sh\n')
|
|
await chmod(path.join(dir, 'runme'), 0o755)
|
|
await writeFile(path.join(dir, 'plain'), 'not executable\n')
|
|
await chmod(path.join(dir, 'plain'), 0o644)
|
|
await mkdir(path.join(dir, 'adir'))
|
|
await symlink(path.join(dir, 'runme'), path.join(dir, 'linkme'))
|
|
})
|
|
afterAll(async () => {
|
|
await rm(dir, { recursive: true, force: true })
|
|
})
|
|
|
|
it('finds an executable file on PATH', async () => {
|
|
await expect(
|
|
isCommandOnLocalPath('runme', { platform: 'linux', env: { PATH: dir } })
|
|
).resolves.toBe(true)
|
|
})
|
|
|
|
it('rejects a non-executable file on PATH', async () => {
|
|
await expect(
|
|
isCommandOnLocalPath('plain', { platform: 'linux', env: { PATH: dir } })
|
|
).resolves.toBe(false)
|
|
})
|
|
|
|
it('rejects a directory whose name matches the command', async () => {
|
|
await expect(
|
|
isCommandOnLocalPath('adir', { platform: 'linux', env: { PATH: dir } })
|
|
).resolves.toBe(false)
|
|
})
|
|
|
|
it('follows a symlink to an executable', async () => {
|
|
await expect(
|
|
isCommandOnLocalPath('linkme', { platform: 'linux', env: { PATH: dir } })
|
|
).resolves.toBe(true)
|
|
})
|
|
|
|
it('returns false when PATH is empty', async () => {
|
|
await expect(
|
|
isCommandOnLocalPath('runme', { platform: 'linux', env: { PATH: '' } })
|
|
).resolves.toBe(false)
|
|
})
|
|
|
|
it('resolves an absolute command path directly', async () => {
|
|
await expect(
|
|
isCommandOnLocalPath(path.join(dir, 'runme'), { platform: 'linux', env: { PATH: '' } })
|
|
).resolves.toBe(true)
|
|
})
|
|
|
|
it('rejects a match reached via a relative PATH entry (absolute-only gate)', async () => {
|
|
await expect(
|
|
isCommandOnLocalPath('runme', { platform: 'linux', env: { PATH: '.' }, cwd: dir })
|
|
).resolves.toBe(false)
|
|
})
|
|
})
|
|
|
|
// Win32 semantics tested cross-platform via the explicit `platform` option:
|
|
// PATHEXT resolution + case-insensitive `Path` key.
|
|
describe('win32 (synthetic)', () => {
|
|
let dir = ''
|
|
beforeAll(async () => {
|
|
dir = await mkdtemp(path.join(tmpdir(), 'cmd-resolver-win32-'))
|
|
// Match PATHEXT case in fixtures; real Windows handles filename case while Linux test filesystems do not.
|
|
await writeFile(path.join(dir, 'tool.CMD'), '@echo off\n')
|
|
})
|
|
afterAll(async () => {
|
|
await rm(dir, { recursive: true, force: true })
|
|
})
|
|
|
|
it('resolves a bare command via PATHEXT using the case-insensitive Path key', async () => {
|
|
await expect(
|
|
isCommandOnLocalPath('tool', {
|
|
platform: 'win32',
|
|
env: { Path: dir, PATHEXT: '.COM;.EXE;.CMD;.BAT' }
|
|
})
|
|
).resolves.toBe(true)
|
|
})
|
|
|
|
it('returns false when PATHEXT excludes the only available extension', async () => {
|
|
await expect(
|
|
isCommandOnLocalPath('tool', {
|
|
platform: 'win32',
|
|
env: { Path: dir, PATHEXT: '.EXE;.COM' }
|
|
})
|
|
).resolves.toBe(false)
|
|
})
|
|
|
|
it('matches an exact name with extension already present', async () => {
|
|
await expect(
|
|
isCommandOnLocalPath('tool.CMD', {
|
|
platform: 'win32',
|
|
env: { Path: dir, PATHEXT: '.EXE' }
|
|
})
|
|
).resolves.toBe(true)
|
|
})
|
|
})
|
|
|
|
// Executable-but-broken shims can shadow working binaries; retain later PATH candidates (#22975).
|
|
describe.skipIf(process.platform === 'win32')('listLocalCommandPaths', () => {
|
|
let front = ''
|
|
let middle = ''
|
|
let back = ''
|
|
|
|
async function executable(dir: string, name: string, body: string): Promise<void> {
|
|
await writeFile(path.join(dir, name), body)
|
|
await chmod(path.join(dir, name), 0o755)
|
|
}
|
|
|
|
beforeAll(async () => {
|
|
front = await mkdtemp(path.join(tmpdir(), 'cmd-list-front-'))
|
|
middle = await mkdtemp(path.join(tmpdir(), 'cmd-list-middle-'))
|
|
back = await mkdtemp(path.join(tmpdir(), 'cmd-list-back-'))
|
|
await executable(front, 'gh', '#!/usr/bin/env bash\nexec /nope/asdf exec "gh" "$@"\n')
|
|
await executable(back, 'gh', "#!/bin/sh\nprintf 'gh version 2.98.0\\n'\n")
|
|
await writeFile(path.join(middle, 'gh'), 'not executable\n')
|
|
await chmod(path.join(middle, 'gh'), 0o644)
|
|
await mkdir(path.join(middle, 'glab'))
|
|
await executable(back, 'glab', '#!/bin/sh\n')
|
|
})
|
|
|
|
afterAll(async () => {
|
|
await rm(front, { recursive: true, force: true })
|
|
await rm(middle, { recursive: true, force: true })
|
|
await rm(back, { recursive: true, force: true })
|
|
})
|
|
|
|
it('returns every match in PATH order, shim first', async () => {
|
|
await expect(
|
|
listLocalCommandPaths('gh', {
|
|
platform: 'linux',
|
|
env: { PATH: `${front}:${middle}:${back}` }
|
|
})
|
|
).resolves.toEqual([path.posix.join(front, 'gh'), path.posix.join(back, 'gh')])
|
|
})
|
|
|
|
it('follows PATH order rather than which copy runs', async () => {
|
|
await expect(
|
|
listLocalCommandPaths('gh', { platform: 'linux', env: { PATH: `${back}:${front}` } })
|
|
).resolves.toEqual([path.posix.join(back, 'gh'), path.posix.join(front, 'gh')])
|
|
})
|
|
|
|
it('skips a directory that matches the command name and keeps scanning', async () => {
|
|
await expect(
|
|
listLocalCommandPaths('glab', {
|
|
platform: 'linux',
|
|
env: { PATH: `${middle}:${front}:${back}` }
|
|
})
|
|
).resolves.toEqual([path.posix.join(back, 'glab')])
|
|
})
|
|
|
|
it('returns an empty list when PATH holds no absolute match', async () => {
|
|
await expect(
|
|
listLocalCommandPaths('gh', { platform: 'linux', env: { PATH: '' } })
|
|
).resolves.toEqual([])
|
|
})
|
|
|
|
it('applies the absolute-only gate to the whole list, not just the winner', async () => {
|
|
await expect(
|
|
listLocalCommandPaths('gh', {
|
|
platform: 'linux',
|
|
env: { PATH: `.${path.delimiter}${front}` }
|
|
})
|
|
).resolves.toEqual([path.posix.join(front, 'gh')])
|
|
})
|
|
|
|
it('drops a relative match the filesystem would otherwise find', async () => {
|
|
// Ensure this relative PATH entry actually reaches a fixture before asserting the absolute-only filter.
|
|
const relative = path.relative(process.cwd(), back)
|
|
await expect(access(path.join(relative, 'gh'))).resolves.toBeUndefined()
|
|
await expect(
|
|
listLocalCommandPaths('gh', { platform: 'linux', env: { PATH: relative } })
|
|
).resolves.toEqual([])
|
|
})
|
|
|
|
it('lists a PATH entry that repeats only once', async () => {
|
|
// Duplicate PATH directories must not probe doomed shims repeatedly.
|
|
await expect(
|
|
listLocalCommandPaths('gh', {
|
|
platform: 'linux',
|
|
env: { PATH: `${back}:${front}:${back}` }
|
|
})
|
|
).resolves.toEqual([path.posix.join(back, 'gh'), path.posix.join(front, 'gh')])
|
|
})
|
|
|
|
it('returns an empty list for an empty command', async () => {
|
|
await expect(listLocalCommandPaths('')).resolves.toEqual([])
|
|
})
|
|
|
|
it('resolves an absolute command path directly', async () => {
|
|
await expect(
|
|
listLocalCommandPaths(path.join(front, 'gh'), { platform: 'linux', env: { PATH: '' } })
|
|
).resolves.toEqual([`${front}/gh`])
|
|
})
|
|
|
|
it('lists every PATHEXT permutation on win32, in resolver order', async () => {
|
|
const dir = await mkdtemp(path.join(tmpdir(), 'cmd-list-win32-'))
|
|
try {
|
|
await writeFile(path.join(dir, 'tool.CMD'), '@echo off\n')
|
|
await writeFile(path.join(dir, 'tool.EXE'), '')
|
|
await expect(
|
|
listLocalCommandPaths('tool', {
|
|
platform: 'win32',
|
|
env: { Path: dir, PATHEXT: '.CMD;.EXE' },
|
|
cwd: dir
|
|
})
|
|
).resolves.toEqual([`${dir}/tool.CMD`, `${dir}/tool.EXE`])
|
|
} finally {
|
|
await rm(dir, { recursive: true, force: true })
|
|
}
|
|
})
|
|
})
|
|
})
|