* fix: address pr-bug-scan validated finding from #4213 On per-file read/size error, skip the file and continue merging instead of returning found:false; preserve first error for the all-failed case. * add tests --------- Co-authored-by: orca-bug-scan-bot <orca-bug-scan-bot@stably.ai> Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
This commit is contained in:
parent
e20845eedb
commit
eacba6654f
|
|
@ -114,6 +114,84 @@ background = #1a1a1a
|
|||
expect(result.unsupportedKeys).toEqual([])
|
||||
})
|
||||
|
||||
it('keeps successfully imported settings when a later config cannot be read', async () => {
|
||||
delete process.env.XDG_CONFIG_HOME
|
||||
const firstPath = '/Users/alice/.config/ghostty/config.ghostty'
|
||||
const unreadablePath = '/Users/alice/.config/ghostty/config'
|
||||
statMock.mockImplementation(async (p: string) => {
|
||||
if (p === firstPath || p === unreadablePath) {
|
||||
return { isFile: () => true, size: 128 }
|
||||
}
|
||||
throw Object.assign(new Error('ENOENT'), { code: 'ENOENT' })
|
||||
})
|
||||
readFileMock.mockImplementation(async (p: string) => {
|
||||
if (p === firstPath) {
|
||||
return 'font-size = 22\n'
|
||||
}
|
||||
throw new Error('EACCES')
|
||||
})
|
||||
|
||||
const result = await previewGhosttyImport(createStore())
|
||||
|
||||
expect(result).toMatchObject({
|
||||
found: true,
|
||||
configPath: firstPath,
|
||||
configPaths: [firstPath],
|
||||
diff: { terminalFontSize: 22 }
|
||||
})
|
||||
})
|
||||
|
||||
it('keeps successfully imported settings when a later config is too large', async () => {
|
||||
delete process.env.XDG_CONFIG_HOME
|
||||
const firstPath = '/Users/alice/.config/ghostty/config.ghostty'
|
||||
const oversizedPath = '/Users/alice/.config/ghostty/config'
|
||||
statMock.mockImplementation(async (p: string) => {
|
||||
if (p === firstPath) {
|
||||
return { isFile: () => true, size: 128 }
|
||||
}
|
||||
if (p === oversizedPath) {
|
||||
return { isFile: () => true, size: 1_000_001 }
|
||||
}
|
||||
throw Object.assign(new Error('ENOENT'), { code: 'ENOENT' })
|
||||
})
|
||||
readFileMock.mockResolvedValue('font-size = 22\n')
|
||||
|
||||
const result = await previewGhosttyImport(createStore())
|
||||
|
||||
expect(result).toMatchObject({
|
||||
found: true,
|
||||
configPath: firstPath,
|
||||
configPaths: [firstPath],
|
||||
diff: { terminalFontSize: 22 }
|
||||
})
|
||||
expect(readFileMock).not.toHaveBeenCalledWith(oversizedPath, 'utf-8')
|
||||
})
|
||||
|
||||
it('returns the first error when every discovered config fails to load', async () => {
|
||||
delete process.env.XDG_CONFIG_HOME
|
||||
const configPath = '/Users/alice/.config/ghostty/config.ghostty'
|
||||
let configPathStatCalls = 0
|
||||
statMock.mockImplementation(async (p: string) => {
|
||||
if (p === configPath) {
|
||||
configPathStatCalls += 1
|
||||
if (configPathStatCalls === 1) {
|
||||
return { isFile: () => true, size: 128 }
|
||||
}
|
||||
throw new Error('EACCES')
|
||||
}
|
||||
throw Object.assign(new Error('ENOENT'), { code: 'ENOENT' })
|
||||
})
|
||||
|
||||
const result = await previewGhosttyImport(createStore())
|
||||
|
||||
expect(result).toEqual({
|
||||
found: false,
|
||||
diff: {},
|
||||
unsupportedKeys: [],
|
||||
error: 'Could not read config: EACCES'
|
||||
})
|
||||
})
|
||||
|
||||
it('omits values that match current settings', async () => {
|
||||
statMock.mockImplementation(async (p: string) => {
|
||||
if (p === '/Users/alice/Library/Application Support/com.mitchellh.ghostty/config') {
|
||||
|
|
|
|||
|
|
@ -107,29 +107,37 @@ export async function previewGhosttyImport(store: Store): Promise<GhosttyImportP
|
|||
}
|
||||
|
||||
const parsed: Record<string, string | string[]> = {}
|
||||
const readPaths: string[] = []
|
||||
let firstError: string | null = null
|
||||
for (const configPath of configPaths) {
|
||||
let content: string
|
||||
try {
|
||||
const info = await stat(configPath)
|
||||
if (info.size > MAX_CONFIG_BYTES) {
|
||||
return {
|
||||
found: false,
|
||||
diff: {},
|
||||
unsupportedKeys: [],
|
||||
error: `Config file is too large to import (${info.size} bytes, limit ${MAX_CONFIG_BYTES}).`
|
||||
if (firstError === null) {
|
||||
firstError = `Config file is too large to import (${info.size} bytes, limit ${MAX_CONFIG_BYTES}).`
|
||||
}
|
||||
continue
|
||||
}
|
||||
content = await readFile(configPath, 'utf-8')
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : 'Could not read config file'
|
||||
return {
|
||||
found: false,
|
||||
diff: {},
|
||||
unsupportedKeys: [],
|
||||
error: `Could not read config: ${message}`
|
||||
if (firstError === null) {
|
||||
firstError = `Could not read config: ${message}`
|
||||
}
|
||||
continue
|
||||
}
|
||||
mergeParsedConfig(parsed, parseGhosttyConfig(content))
|
||||
readPaths.push(configPath)
|
||||
}
|
||||
|
||||
if (readPaths.length === 0) {
|
||||
return {
|
||||
found: false,
|
||||
diff: {},
|
||||
unsupportedKeys: [],
|
||||
error: firstError ?? 'Could not read config'
|
||||
}
|
||||
}
|
||||
|
||||
const themeUnsupportedKeys = await applyThemeReference(parsed)
|
||||
|
|
@ -153,8 +161,8 @@ export async function previewGhosttyImport(store: Store): Promise<GhosttyImportP
|
|||
|
||||
return {
|
||||
found: true,
|
||||
configPath: configPaths[0],
|
||||
configPaths,
|
||||
configPath: readPaths[0],
|
||||
configPaths: readPaths,
|
||||
diff: actualDiff,
|
||||
unsupportedKeys
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue