mirror of
https://github.com/stablyai/orca.git
synced 2026-10-03 08:02:12 +00:00
fix(linux): accept extracted AppImage runtimes with APPDIR only
This commit is contained in:
@@ -11,7 +11,7 @@ import { tmpdir } from 'node:os'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import {
|
||||
hasAppImageRuntimeEnvironment,
|
||||
hasAppImagePathEnvironment,
|
||||
resolveAppImageRuntimeIdentity
|
||||
} from './appimage-runtime-identity'
|
||||
|
||||
@@ -231,10 +231,10 @@ describe.skipIf(process.platform === 'win32')('resolveAppImageRuntimeIdentity',
|
||||
})
|
||||
})
|
||||
|
||||
describe('hasAppImageRuntimeEnvironment', () => {
|
||||
it('detects either AppImage runtime variable', () => {
|
||||
expect(hasAppImageRuntimeEnvironment({ APPIMAGE: '/tmp/Orca.AppImage' })).toBe(true)
|
||||
expect(hasAppImageRuntimeEnvironment({ APPDIR: '/tmp/.mount_Orca123' })).toBe(true)
|
||||
expect(hasAppImageRuntimeEnvironment({ APPIMAGE: '', APPDIR: '' })).toBe(false)
|
||||
describe('hasAppImagePathEnvironment', () => {
|
||||
it('requires the AppImage file path before treating the runtime as verifiable', () => {
|
||||
expect(hasAppImagePathEnvironment({ APPIMAGE: '/tmp/Orca.AppImage' })).toBe(true)
|
||||
expect(hasAppImagePathEnvironment({ APPDIR: '/tmp/.mount_Orca123' })).toBe(false)
|
||||
expect(hasAppImagePathEnvironment({ APPIMAGE: '', APPDIR: '/tmp/.mount_Orca123' })).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -143,10 +143,9 @@ function hasAppImagePackageEvidence(runtimeRoot: string, resourcesPath: string):
|
||||
}
|
||||
}
|
||||
|
||||
export function hasAppImageRuntimeEnvironment(
|
||||
environment: NodeJS.ProcessEnv = process.env
|
||||
): boolean {
|
||||
return Boolean(environment.APPIMAGE || environment.APPDIR)
|
||||
/** Returns whether the process inherited an AppImage file path to validate. */
|
||||
export function hasAppImagePathEnvironment(environment: NodeJS.ProcessEnv = process.env): boolean {
|
||||
return Boolean(environment.APPIMAGE)
|
||||
}
|
||||
|
||||
export function resolveAppImageRuntimeIdentity(
|
||||
|
||||
@@ -4,7 +4,7 @@ import { basename, dirname, join } from 'node:path'
|
||||
import { getAppEnvironment } from '../../shared/app-environment'
|
||||
import type { CliInstallStatus } from '../../shared/cli-install-types'
|
||||
import {
|
||||
hasAppImageRuntimeEnvironment,
|
||||
hasAppImagePathEnvironment,
|
||||
resolveAppImageRuntimeIdentity
|
||||
} from '../appimage-runtime-identity'
|
||||
import {
|
||||
@@ -106,7 +106,7 @@ export abstract class CliInstallLocation {
|
||||
this.platform === 'linux' &&
|
||||
this.isPackaged &&
|
||||
!hasExplicitAppImagePath &&
|
||||
hasAppImageRuntimeEnvironment() &&
|
||||
hasAppImagePathEnvironment() &&
|
||||
!runtimeAppImageIdentity
|
||||
this.appImagePath =
|
||||
this.platform === 'linux' && this.isPackaged
|
||||
|
||||
@@ -70,6 +70,38 @@ function installerOptions(fixture: Fixture) {
|
||||
}
|
||||
|
||||
describe.skipIf(process.platform === 'win32')('AppImage CLI ownership', () => {
|
||||
it('uses the mounted bundled launcher when only APPDIR is inherited', async () => {
|
||||
const fixture = await makeFixture()
|
||||
const resourcesPath = join(fixture.root, 'mounted', 'resources')
|
||||
const launcherPath = join(resourcesPath, 'bin', 'orca-ide')
|
||||
await mkdir(dirname(launcherPath), { recursive: true })
|
||||
await writeFile(launcherPath, '#!/usr/bin/env bash\n', { mode: 0o755 })
|
||||
vi.stubEnv('APPIMAGE', '')
|
||||
vi.stubEnv('APPDIR', dirname(resourcesPath))
|
||||
|
||||
const installer = new CliInstaller({
|
||||
platform: 'linux',
|
||||
isPackaged: true,
|
||||
userDataPath: join(fixture.root, 'user-data'),
|
||||
resourcesPath,
|
||||
execPath: join(dirname(resourcesPath), 'orca-ide'),
|
||||
appPath: join(resourcesPath, 'app.asar'),
|
||||
homePath: join(fixture.root, 'home'),
|
||||
processPathEnv: fixture.commandDirectory,
|
||||
commandPathOverride: fixture.commandPath
|
||||
})
|
||||
|
||||
await expect(installer.getStatus()).resolves.toMatchObject({
|
||||
state: 'not_installed',
|
||||
launcherPath
|
||||
})
|
||||
await expect(installer.install()).resolves.toMatchObject({
|
||||
state: 'installed',
|
||||
launcherPath
|
||||
})
|
||||
await expect(readlink(fixture.commandPath)).resolves.toBe(launcherPath)
|
||||
})
|
||||
|
||||
it('ignores inherited APPIMAGE without the matching runtime identity', async () => {
|
||||
const fixture = await makeFixture()
|
||||
const resourcesPath = join(fixture.root, 'installed', 'resources')
|
||||
|
||||
@@ -72,6 +72,7 @@ async function makeFixture(): Promise<{ homePath: string; resourcesPath: string
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
vi.unstubAllEnvs()
|
||||
filePublicationFailures.link = 0
|
||||
filePublicationFailures.replaceBeforeRename = ''
|
||||
registrationLock.completed = null
|
||||
@@ -81,6 +82,17 @@ afterEach(async () => {
|
||||
})
|
||||
|
||||
describe('installLinuxBareOrcaDispatcher', () => {
|
||||
it('uses the mounted bundled launcher when only APPDIR is inherited', async () => {
|
||||
const { homePath, resourcesPath } = await makeFixture()
|
||||
vi.stubEnv('APPIMAGE', '')
|
||||
vi.stubEnv('APPDIR', resourcesPath)
|
||||
|
||||
const result = await installLinuxBareOrcaDispatcher({ resourcesPath, homePath })
|
||||
|
||||
expect(result.state).toBe('installed')
|
||||
expect(result.target).toBe(join(resourcesPath, 'bin', 'orca-ide'))
|
||||
})
|
||||
|
||||
it('writes an executable bare-orca dispatcher that execs the bundled orca-ide launcher', async () => {
|
||||
const { homePath, resourcesPath } = await makeFixture()
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { copyFile, link, lstat, mkdir, readFile, rename, unlink, writeFile } fro
|
||||
import { homedir } from 'node:os'
|
||||
import { dirname, join } from 'node:path'
|
||||
import {
|
||||
hasAppImageRuntimeEnvironment,
|
||||
hasAppImagePathEnvironment,
|
||||
resolveAppImageRuntimeIdentity
|
||||
} from '../appimage-runtime-identity'
|
||||
import {
|
||||
@@ -89,7 +89,7 @@ async function resolveStableLauncherPath(
|
||||
): Promise<string | null> {
|
||||
const hasExplicitAppImagePath = Object.hasOwn(options, 'appImagePath')
|
||||
const runtimeIdentity = resolveAppImageRuntimeIdentity({ resourcesPath: options.resourcesPath })
|
||||
if (!hasExplicitAppImagePath && hasAppImageRuntimeEnvironment() && !runtimeIdentity) {
|
||||
if (!hasExplicitAppImagePath && hasAppImagePathEnvironment() && !runtimeIdentity) {
|
||||
return null
|
||||
}
|
||||
const appImagePath = hasExplicitAppImagePath
|
||||
|
||||
@@ -26,10 +26,24 @@ async function makeFixture(): Promise<{ userDataPath: string; resourcesPath: str
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
vi.unstubAllEnvs()
|
||||
await Promise.all(created.splice(0).map((dir) => rm(dir, { recursive: true, force: true })))
|
||||
})
|
||||
|
||||
describe('ensureLinuxTerminalOrcaCliShimDir', () => {
|
||||
it('uses the mounted bundled launcher when only APPDIR is inherited', async () => {
|
||||
const { userDataPath, resourcesPath } = await makeFixture()
|
||||
vi.stubEnv('APPIMAGE', '')
|
||||
vi.stubEnv('APPDIR', resourcesPath)
|
||||
|
||||
const shimDir = ensureLinuxTerminalOrcaCliShimDir({ userDataPath, resourcesPath })
|
||||
|
||||
expect(shimDir).toBe(join(userDataPath, 'linux-orca-cli-shim'))
|
||||
expect(readFileSync(join(shimDir!, 'orca'), 'utf8')).toContain(
|
||||
`exec '${join(resourcesPath, 'bin', 'orca-ide')}' "$@"`
|
||||
)
|
||||
})
|
||||
|
||||
it('writes an executable bare-orca shim that execs the bundled orca-ide launcher', async () => {
|
||||
const { userDataPath, resourcesPath } = await makeFixture()
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
} from 'node:fs'
|
||||
import { dirname, join, resolve } from 'node:path'
|
||||
import {
|
||||
hasAppImageRuntimeEnvironment,
|
||||
hasAppImagePathEnvironment,
|
||||
resolveAppImageRuntimeIdentity
|
||||
} from '../appimage-runtime-identity'
|
||||
import {
|
||||
@@ -50,7 +50,7 @@ export function ensureLinuxTerminalOrcaCliShimDir(
|
||||
options.resourcesPath === undefined ? process.resourcesPath : options.resourcesPath
|
||||
const hasExplicitAppImagePath = Object.hasOwn(options, 'appImagePath')
|
||||
const runtimeIdentity = resolveAppImageRuntimeIdentity({ resourcesPath })
|
||||
if (!hasExplicitAppImagePath && hasAppImageRuntimeEnvironment() && !runtimeIdentity) {
|
||||
if (!hasExplicitAppImagePath && hasAppImagePathEnvironment() && !runtimeIdentity) {
|
||||
return null
|
||||
}
|
||||
const appImagePath = hasExplicitAppImagePath
|
||||
|
||||
Reference in New Issue
Block a user