// Unit: self-installing pgv3-git-shell launcher (same-account userland SSH).
import test from 'brittle'
import { promises as fs } from '#node:fs'
import os from '#node:os'
import { join } from '#node:path'
import { ensureGitShellLauncher } from '../lib/auth/ssh-setup.js'
test('ensureGitShellLauncher: writes an exec shim, mode 0755, idempotent', async (t) => {
const dir = await fs.mkdtemp(join(os.tmpdir(), 'pgv3-launcher-'))
const launcher = join(dir, 'bin', 'pgv3-git-shell')
const out = await ensureGitShellLauncher(launcher, { runtime: '/usr/bin/bare', script: '/opt/app/bin/pgv3-git-shell.js' })
t.is(out.launcherPath, launcher)
const body = await fs.readFile(launcher, 'utf8')
t.ok(body.startsWith('#!/bin/sh'), 'shebang')
t.ok(body.includes('exec "/usr/bin/bare" "/opt/app/bin/pgv3-git-shell.js" "$@"'), 'execs runtime on script, args passed')
t.is((await fs.stat(launcher)).mode & 0o777, 0o755, 'executable 0755')
// idempotent — second call with same inputs leaves content identical
const before = await fs.stat(launcher)
await new Promise((r) => setTimeout(r, 5))
await ensureGitShellLauncher(launcher, { runtime: '/usr/bin/bare', script: '/opt/app/bin/pgv3-git-shell.js' })
t.is(await fs.readFile(launcher, 'utf8'), body, 'content unchanged')
t.is((await fs.stat(launcher)).mtimeMs, before.mtimeMs, 'not rewritten when unchanged')
// rewrites when the runtime/script path moves (a redeploy)
await ensureGitShellLauncher(launcher, { runtime: '/usr/bin/bare', script: '/opt/app-v2/bin/pgv3-git-shell.js' })
t.ok((await fs.readFile(launcher, 'utf8')).includes('/opt/app-v2/'), 'updated path on change')
await fs.rm(dir, { recursive: true, force: true })
})
test('ensureGitShellLauncher: validates inputs', async (t) => {
await t.exception(() => ensureGitShellLauncher('', { runtime: 'r', script: 's' }), /requires/)
await t.exception(() => ensureGitShellLauncher('/x', { runtime: 'r' }), /requires/)
await t.exception(() => ensureGitShellLauncher('/x', { runtime: 'r\n"evil', script: 's' }), /invalid runtime/)
})