mirror of
https://github.com/stablyai/orca.git
synced 2026-10-28 16:02:55 +00:00
119 lines
4.7 KiB
TypeScript
119 lines
4.7 KiB
TypeScript
import { chmodSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'
|
|
import { mkdtemp, rm } from 'node:fs/promises'
|
|
import { tmpdir } from 'node:os'
|
|
import { join } from 'node:path'
|
|
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
vi.mock('electron', () => ({
|
|
app: { isPackaged: true }
|
|
}))
|
|
|
|
import { ensureLinuxTerminalOrcaCliShimDir } from './linux-terminal-orca-cli-shim'
|
|
|
|
const created: string[] = []
|
|
|
|
async function makeFixture(): Promise<{ userDataPath: string; resourcesPath: string }> {
|
|
const root = await mkdtemp(join(tmpdir(), 'orca-terminal-cli-shim-'))
|
|
created.push(root)
|
|
const resourcesPath = join(root, 'resources')
|
|
// The bundled orca-ide launcher must exist for the shim to be written.
|
|
mkdirSync(join(resourcesPath, 'bin'), { recursive: true })
|
|
writeFileSync(join(resourcesPath, 'bin', 'orca-ide'), '#!/usr/bin/env bash\n', 'utf8')
|
|
return { userDataPath: join(root, 'user-data'), resourcesPath }
|
|
}
|
|
|
|
afterEach(async () => {
|
|
await Promise.all(created.splice(0).map((dir) => rm(dir, { recursive: true, force: true })))
|
|
})
|
|
|
|
describe('ensureLinuxTerminalOrcaCliShimDir', () => {
|
|
it('writes an executable bare-orca shim that execs the bundled orca-ide launcher', async () => {
|
|
const { userDataPath, resourcesPath } = await makeFixture()
|
|
|
|
const shimDir = ensureLinuxTerminalOrcaCliShimDir({
|
|
userDataPath,
|
|
resourcesPath,
|
|
appImagePath: null
|
|
})
|
|
|
|
expect(shimDir).toBe(join(userDataPath, 'linux-orca-cli-shim'))
|
|
const content = readFileSync(join(shimDir!, 'orca'), 'utf8')
|
|
// Single-quoted so a resources path with shell metacharacters can't break out.
|
|
expect(content).toContain(`exec '${join(resourcesPath, 'bin', 'orca-ide')}' "$@"`)
|
|
const mode = statSync(join(shimDir!, 'orca')).mode & 0o777
|
|
expect(mode & 0o111).not.toBe(0)
|
|
})
|
|
|
|
it('memoizes per userDataPath and re-asserts the exec bit for a stale shim', async () => {
|
|
const { userDataPath, resourcesPath } = await makeFixture()
|
|
const options = { userDataPath, resourcesPath, appImagePath: null }
|
|
|
|
const first = ensureLinuxTerminalOrcaCliShimDir(options)
|
|
expect(first).not.toBeNull()
|
|
const shimPath = join(first!, 'orca')
|
|
chmodSync(shimPath, 0o644)
|
|
|
|
// A distinct userData path is not memoized, so ensure runs again and heals
|
|
// the exec bit lost above only when it actually processes that path.
|
|
const second = ensureLinuxTerminalOrcaCliShimDir(options)
|
|
expect(second).toBe(first)
|
|
|
|
const root = await mkdtemp(join(tmpdir(), 'orca-terminal-cli-shim-2-'))
|
|
created.push(root)
|
|
const otherUserData = join(root, 'user-data')
|
|
mkdirSync(join(otherUserData, 'linux-orca-cli-shim'), { recursive: true })
|
|
writeFileSync(join(otherUserData, 'linux-orca-cli-shim', 'orca'), 'stale contents', 'utf8')
|
|
chmodSync(join(otherUserData, 'linux-orca-cli-shim', 'orca'), 0o644)
|
|
|
|
const healed = ensureLinuxTerminalOrcaCliShimDir({
|
|
userDataPath: otherUserData,
|
|
resourcesPath,
|
|
appImagePath: null
|
|
})
|
|
expect(healed).not.toBeNull()
|
|
const healedPath = join(healed!, 'orca')
|
|
expect(readFileSync(healedPath, 'utf8')).toContain('orca-ide')
|
|
expect(statSync(healedPath).mode & 0o111).not.toBe(0)
|
|
})
|
|
|
|
it('execs the stable AppImage (not the ephemeral mount) when running from an AppImage', async () => {
|
|
const { userDataPath, resourcesPath } = await makeFixture()
|
|
const appImagePath = join(userDataPath, 'Applications', 'Orca.AppImage')
|
|
|
|
const shimDir = ensureLinuxTerminalOrcaCliShimDir({
|
|
userDataPath,
|
|
resourcesPath,
|
|
appImagePath
|
|
})
|
|
|
|
const content = readFileSync(join(shimDir!, 'orca'), 'utf8')
|
|
expect(content).toContain(appImagePath)
|
|
expect(content).not.toContain(resourcesPath)
|
|
})
|
|
|
|
it('returns null (and does not memoize) when the bundled launcher is missing', async () => {
|
|
const root = await mkdtemp(join(tmpdir(), 'orca-terminal-cli-shim-missing-'))
|
|
created.push(root)
|
|
const userDataPath = join(root, 'user-data')
|
|
|
|
const missing = ensureLinuxTerminalOrcaCliShimDir({
|
|
userDataPath,
|
|
resourcesPath: join(root, 'resources'),
|
|
appImagePath: null
|
|
})
|
|
expect(missing).toBeNull()
|
|
|
|
// Once the launcher exists (e.g. later probe with real resources), the same
|
|
// userData path succeeds — proving failures are not cached.
|
|
const resourcesPath = join(root, 'resources')
|
|
mkdirSync(join(resourcesPath, 'bin'), { recursive: true })
|
|
writeFileSync(join(resourcesPath, 'bin', 'orca-ide'), '#!/usr/bin/env bash\n', 'utf8')
|
|
const recovered = ensureLinuxTerminalOrcaCliShimDir({
|
|
userDataPath,
|
|
resourcesPath,
|
|
appImagePath: null
|
|
})
|
|
expect(recovered).toBe(join(userDataPath, 'linux-orca-cli-shim'))
|
|
})
|
|
})
|