File size: 2,798 Bytes
064bfd6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | import { stat } from 'fs/promises'
import { homedir } from 'os'
import { join } from 'path'
import { getGlobalConfig, saveGlobalConfig } from './config.js'
import { execFileNoThrow } from './execFileNoThrow.js'
import { logError } from './log.js'
export function markTerminalSetupInProgress(backupPath: string): void {
saveGlobalConfig(current => ({
...current,
appleTerminalSetupInProgress: true,
appleTerminalBackupPath: backupPath,
}))
}
export function markTerminalSetupComplete(): void {
saveGlobalConfig(current => ({
...current,
appleTerminalSetupInProgress: false,
}))
}
function getTerminalRecoveryInfo(): {
inProgress: boolean
backupPath: string | null
} {
const config = getGlobalConfig()
return {
inProgress: config.appleTerminalSetupInProgress ?? false,
backupPath: config.appleTerminalBackupPath || null,
}
}
export function getTerminalPlistPath(): string {
return join(homedir(), 'Library', 'Preferences', 'com.apple.Terminal.plist')
}
export async function backupTerminalPreferences(): Promise<string | null> {
const terminalPlistPath = getTerminalPlistPath()
const backupPath = `${terminalPlistPath}.bak`
try {
const { code } = await execFileNoThrow('defaults', [
'export',
'com.apple.Terminal',
terminalPlistPath,
])
if (code !== 0) {
return null
}
try {
await stat(terminalPlistPath)
} catch {
return null
}
await execFileNoThrow('defaults', [
'export',
'com.apple.Terminal',
backupPath,
])
markTerminalSetupInProgress(backupPath)
return backupPath
} catch (error) {
logError(error)
return null
}
}
type RestoreResult =
| {
status: 'restored' | 'no_backup'
}
| {
status: 'failed'
backupPath: string
}
export async function checkAndRestoreTerminalBackup(): Promise<RestoreResult> {
const { inProgress, backupPath } = getTerminalRecoveryInfo()
if (!inProgress) {
return { status: 'no_backup' }
}
if (!backupPath) {
markTerminalSetupComplete()
return { status: 'no_backup' }
}
try {
await stat(backupPath)
} catch {
markTerminalSetupComplete()
return { status: 'no_backup' }
}
try {
const { code } = await execFileNoThrow('defaults', [
'import',
'com.apple.Terminal',
backupPath,
])
if (code !== 0) {
return { status: 'failed', backupPath }
}
await execFileNoThrow('killall', ['cfprefsd'])
markTerminalSetupComplete()
return { status: 'restored' }
} catch (restoreError) {
logError(
new Error(
`Failed to restore Terminal.app settings with: ${restoreError}`,
),
)
markTerminalSetupComplete()
return { status: 'failed', backupPath }
}
}
|