Merge pull request #2247 from code-yeongyu/fix/pr-1977-doctor-paths
fix(doctor): quote cache paths and respect release channel tags
This commit is contained in:
18
src/cli/doctor/checks/system-loaded-version.test.ts
Normal file
18
src/cli/doctor/checks/system-loaded-version.test.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { describe, expect, it } from "bun:test"
|
||||
|
||||
import { getSuggestedInstallTag } from "./system-loaded-version"
|
||||
|
||||
describe("system loaded version", () => {
|
||||
describe("getSuggestedInstallTag", () => {
|
||||
it("returns prerelease channel when current version is prerelease", () => {
|
||||
//#given
|
||||
const currentVersion = "3.2.0-beta.4"
|
||||
|
||||
//#when
|
||||
const installTag = getSuggestedInstallTag(currentVersion)
|
||||
|
||||
//#then
|
||||
expect(installTag).toBe("beta")
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -77,3 +77,7 @@ export async function getLatestPluginVersion(currentVersion: string | null): Pro
|
||||
const channel = extractChannel(currentVersion)
|
||||
return getLatestVersion(channel)
|
||||
}
|
||||
|
||||
export function getSuggestedInstallTag(currentVersion: string | null): string {
|
||||
return extractChannel(currentVersion)
|
||||
}
|
||||
|
||||
104
src/cli/doctor/checks/system.test.ts
Normal file
104
src/cli/doctor/checks/system.test.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import { beforeEach, describe, expect, it, mock } from "bun:test"
|
||||
|
||||
const mockFindOpenCodeBinary = mock(async () => ({ path: "/usr/local/bin/opencode" }))
|
||||
const mockGetOpenCodeVersion = mock(async () => "1.0.200")
|
||||
const mockCompareVersions = mock(() => true)
|
||||
const mockGetPluginInfo = mock(() => ({
|
||||
registered: true,
|
||||
entry: "oh-my-opencode",
|
||||
isPinned: false,
|
||||
pinnedVersion: null,
|
||||
configPath: null,
|
||||
isLocalDev: false,
|
||||
}))
|
||||
const mockGetLoadedPluginVersion = mock(() => ({
|
||||
cacheDir: "/Users/test/Library/Caches/opencode with spaces",
|
||||
cachePackagePath: "/tmp/package.json",
|
||||
installedPackagePath: "/tmp/node_modules/oh-my-opencode/package.json",
|
||||
expectedVersion: "3.0.0",
|
||||
loadedVersion: "3.1.0",
|
||||
}))
|
||||
const mockGetLatestPluginVersion = mock(async () => null)
|
||||
|
||||
mock.module("./system-binary", () => ({
|
||||
findOpenCodeBinary: mockFindOpenCodeBinary,
|
||||
getOpenCodeVersion: mockGetOpenCodeVersion,
|
||||
compareVersions: mockCompareVersions,
|
||||
}))
|
||||
|
||||
mock.module("./system-plugin", () => ({
|
||||
getPluginInfo: mockGetPluginInfo,
|
||||
}))
|
||||
|
||||
mock.module("./system-loaded-version", () => ({
|
||||
getLoadedPluginVersion: mockGetLoadedPluginVersion,
|
||||
getLatestPluginVersion: mockGetLatestPluginVersion,
|
||||
}))
|
||||
|
||||
const { checkSystem } = await import("./system?test")
|
||||
|
||||
describe("system check", () => {
|
||||
beforeEach(() => {
|
||||
mockFindOpenCodeBinary.mockReset()
|
||||
mockGetOpenCodeVersion.mockReset()
|
||||
mockCompareVersions.mockReset()
|
||||
mockGetPluginInfo.mockReset()
|
||||
mockGetLoadedPluginVersion.mockReset()
|
||||
mockGetLatestPluginVersion.mockReset()
|
||||
|
||||
mockFindOpenCodeBinary.mockResolvedValue({ path: "/usr/local/bin/opencode" })
|
||||
mockGetOpenCodeVersion.mockResolvedValue("1.0.200")
|
||||
mockCompareVersions.mockReturnValue(true)
|
||||
mockGetPluginInfo.mockReturnValue({
|
||||
registered: true,
|
||||
entry: "oh-my-opencode",
|
||||
isPinned: false,
|
||||
pinnedVersion: null,
|
||||
configPath: null,
|
||||
isLocalDev: false,
|
||||
})
|
||||
mockGetLoadedPluginVersion.mockReturnValue({
|
||||
cacheDir: "/Users/test/Library/Caches/opencode with spaces",
|
||||
cachePackagePath: "/tmp/package.json",
|
||||
installedPackagePath: "/tmp/node_modules/oh-my-opencode/package.json",
|
||||
expectedVersion: "3.0.0",
|
||||
loadedVersion: "3.1.0",
|
||||
})
|
||||
mockGetLatestPluginVersion.mockResolvedValue(null)
|
||||
})
|
||||
|
||||
describe("#given cache directory contains spaces", () => {
|
||||
it("uses a quoted cache directory in mismatch fix command", async () => {
|
||||
//#when
|
||||
const result = await checkSystem()
|
||||
|
||||
//#then
|
||||
const mismatchIssue = result.issues.find((issue) => issue.title === "Loaded plugin version mismatch")
|
||||
expect(mismatchIssue?.fix).toBe('Reinstall: cd "/Users/test/Library/Caches/opencode with spaces" && bun install')
|
||||
})
|
||||
|
||||
it("uses the loaded version channel for update fix command", async () => {
|
||||
//#given
|
||||
mockGetLoadedPluginVersion.mockReturnValue({
|
||||
cacheDir: "/Users/test/Library/Caches/opencode with spaces",
|
||||
cachePackagePath: "/tmp/package.json",
|
||||
installedPackagePath: "/tmp/node_modules/oh-my-opencode/package.json",
|
||||
expectedVersion: "3.0.0-canary.1",
|
||||
loadedVersion: "3.0.0-canary.1",
|
||||
})
|
||||
mockGetLatestPluginVersion.mockResolvedValue("3.0.0-canary.2")
|
||||
mockCompareVersions.mockImplementation((leftVersion: string, rightVersion: string) => {
|
||||
return !(leftVersion === "3.0.0-canary.1" && rightVersion === "3.0.0-canary.2")
|
||||
})
|
||||
|
||||
//#when
|
||||
const result = await checkSystem()
|
||||
|
||||
//#then
|
||||
const outdatedIssue = result.issues.find((issue) => issue.title === "Loaded plugin is outdated")
|
||||
expect(outdatedIssue?.fix).toBe(
|
||||
'Update: cd "/Users/test/Library/Caches/opencode with spaces" && bun add oh-my-opencode@canary'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -4,7 +4,7 @@ import { MIN_OPENCODE_VERSION, CHECK_IDS, CHECK_NAMES } from "../constants"
|
||||
import type { CheckResult, DoctorIssue, SystemInfo } from "../types"
|
||||
import { findOpenCodeBinary, getOpenCodeVersion, compareVersions } from "./system-binary"
|
||||
import { getPluginInfo } from "./system-plugin"
|
||||
import { getLatestPluginVersion, getLoadedPluginVersion } from "./system-loaded-version"
|
||||
import { getLatestPluginVersion, getLoadedPluginVersion, getSuggestedInstallTag } from "./system-loaded-version"
|
||||
import { parseJsonc } from "../../../shared"
|
||||
|
||||
function isConfigValid(configPath: string | null): boolean {
|
||||
@@ -54,6 +54,7 @@ export async function checkSystem(): Promise<CheckResult> {
|
||||
const [systemInfo, pluginInfo] = await Promise.all([gatherSystemInfo(), Promise.resolve(getPluginInfo())])
|
||||
const loadedInfo = getLoadedPluginVersion()
|
||||
const latestVersion = await getLatestPluginVersion(systemInfo.loadedVersion)
|
||||
const installTag = getSuggestedInstallTag(systemInfo.loadedVersion)
|
||||
const issues: DoctorIssue[] = []
|
||||
|
||||
if (!systemInfo.opencodePath) {
|
||||
@@ -93,7 +94,7 @@ export async function checkSystem(): Promise<CheckResult> {
|
||||
issues.push({
|
||||
title: "Loaded plugin version mismatch",
|
||||
description: `Cache expects ${loadedInfo.expectedVersion} but loaded ${loadedInfo.loadedVersion}.`,
|
||||
fix: `Reinstall: cd ${loadedInfo.cacheDir} && bun install`,
|
||||
fix: `Reinstall: cd "${loadedInfo.cacheDir}" && bun install`,
|
||||
severity: "warning",
|
||||
affects: ["plugin loading"],
|
||||
})
|
||||
@@ -107,7 +108,7 @@ export async function checkSystem(): Promise<CheckResult> {
|
||||
issues.push({
|
||||
title: "Loaded plugin is outdated",
|
||||
description: `Loaded ${systemInfo.loadedVersion}, latest ${latestVersion}.`,
|
||||
fix: `Update: cd ${loadedInfo.cacheDir} && bun add oh-my-opencode@latest`,
|
||||
fix: `Update: cd "${loadedInfo.cacheDir}" && bun add oh-my-opencode@${installTag}`,
|
||||
severity: "warning",
|
||||
affects: ["plugin features"],
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user