Skip to content

Commit a9028b3

Browse files
committed
fix(macos): allow no-write installs with multiline TOML
1 parent 3af1d6d commit a9028b3

3 files changed

Lines changed: 106 additions & 12 deletions

File tree

macos/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
### 修复
2121

2222
- 首页建议卡片的文字节点显式跟随主题正文色,避免 Codex 浅色模式的原生文字 token 覆盖深色主题并显示成近黑色;实时验证器会在卡片可见时核对实际文字颜色。
23+
- 当前版本没有计划写入外观键时,macOS 安装不再解析或备份 `config.toml` 的 TOML 结构。包含多行 MCP `args` 或多行字符串的配置可以原样安装,旧备份的恢复流程仍保留严格检查。
2324
- 保留 Codex 原生固定顶栏的定位与层级,避免打开任务侧边面板后开关被推出主区、导致面板无法关闭。
2425
- 修复亮色背景图在 ChatGPT/Codex 暗色模式下错误生成浅色皮肤壳的问题。`appearance=auto` 现在跟随原生/系统外观,避免白字叠在浅色面板上导致界面不可读。
2526
- 修复从“设置 > 外观”返回“已安排的任务”等无输入框路由后,验证器因找不到 composer 而拒绝合法 Codex 主界面的问题。

macos/scripts/theme-config.mjs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import path from "node:path";
33
import { randomUUID } from "node:crypto";
44

55
const [mode, configPath, backupPath] = process.argv.slice(2);
6-
// Backup these keys so Restore can put them back. Do NOT force dark —
7-
// Dream Skin CSS auto-adapts to light/dark via data-dream-shell.
6+
// Non-null entries are managed settings that install must back up for Restore.
7+
// Keep these null because Dream Skin auto-adapts via data-dream-shell.
88
const settings = new Map([
99
["appearanceTheme", null],
1010
["appearanceDarkCodeThemeId", null],
@@ -229,6 +229,20 @@ async function main() {
229229
if (originalStat.isSymbolicLink() || !originalStat.isFile()) {
230230
throw new Error("Codex config must be a regular file, not a symbolic link.");
231231
}
232+
const hasPlannedSettingWrites = [...settings.values()].some((line) => line !== null);
233+
if (!hasPlannedSettingWrites) {
234+
if (mode === "install") {
235+
console.log("Left Codex appearance settings unchanged; no config backup was needed.");
236+
return;
237+
}
238+
try {
239+
await fs.access(backupPath);
240+
} catch (error) {
241+
if (error.code !== "ENOENT") throw error;
242+
console.log("No selective theme backup is available; config.toml was left unchanged.");
243+
return;
244+
}
245+
}
232246
if (content.includes('"""') || content.includes("'''")) {
233247
throw new Error("Refusing to rewrite TOML containing multiline strings.");
234248
}

macos/tests/run-tests.sh

Lines changed: 89 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -700,21 +700,59 @@ BACKUP="$TMP/theme-backup.json"
700700
/bin/cp "$CONFIG" "$TMP/original.toml"
701701
"$NODE" "$ROOT/scripts/theme-config.mjs" install "$CONFIG" "$BACKUP" >/dev/null
702702
/usr/bin/cmp -s "$CONFIG" "$TMP/original.toml"
703+
[ ! -e "$BACKUP" ]
704+
"$NODE" "$ROOT/scripts/theme-config.mjs" restore "$CONFIG" "$BACKUP" >/dev/null
705+
/usr/bin/cmp -s "$CONFIG" "$TMP/original.toml"
706+
707+
# Backups from releases that managed appearance keys must still restore through
708+
# the strict parser and disappear only after a successful round trip.
703709
"$NODE" -e '
704-
const backup = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8"));
705-
if (backup.values.appearanceTheme !== `appearanceTheme = "system"`) process.exit(1);
706-
if (backup.values.appearanceDarkCodeThemeId !== `appearanceDarkCodeThemeId = "vscode-dark"`) process.exit(1);
707-
' "$BACKUP"
710+
const fs = require("node:fs");
711+
const [file, configPath] = process.argv.slice(1);
712+
fs.writeFileSync(file, `${JSON.stringify({
713+
schemaVersion: 1,
714+
platform: "darwin",
715+
configPath,
716+
values: {
717+
appearanceTheme: `appearanceTheme = "system"`,
718+
appearanceDarkCodeThemeId: `appearanceDarkCodeThemeId = "vscode-dark"`,
719+
},
720+
}, null, 2)}\n`);
721+
' "$BACKUP" "$CONFIG"
722+
/usr/bin/printf '%s\n' \
723+
'model = "gpt-5"' \
724+
'project = "中文项目"' \
725+
'' \
726+
'[desktop]' \
727+
'appearanceTheme = "dark"' \
728+
'appearanceDarkCodeThemeId = "monokai"' \
729+
'keepMe = true' > "$CONFIG"
708730
"$NODE" "$ROOT/scripts/theme-config.mjs" restore "$CONFIG" "$BACKUP" >/dev/null
709731
/usr/bin/cmp -s "$CONFIG" "$TMP/original.toml"
732+
[ ! -e "$BACKUP" ]
733+
734+
write_null_theme_backup() {
735+
local backup="$1"
736+
local config="$2"
737+
"$NODE" -e '
738+
const fs = require("node:fs");
739+
const [file, configPath] = process.argv.slice(1);
740+
fs.writeFileSync(file, `${JSON.stringify({
741+
schemaVersion: 1,
742+
platform: "darwin",
743+
configPath,
744+
values: { appearanceTheme: null, appearanceDarkCodeThemeId: null },
745+
}, null, 2)}\n`);
746+
' "$backup" "$config"
747+
}
710748

711749
assert_theme_config_restore_rejected() {
712750
local label="$1"
713751
local config="$2"
714752
local backup="$3"
715753
/bin/cp "$config" "$config.original"
716754
if "$NODE" "$ROOT/scripts/theme-config.mjs" restore "$config" "$backup" >/dev/null 2>&1; then
717-
printf 'theme-config unexpectedly accepted invalid %s backup.\n' "$label" >&2
755+
printf 'theme-config unexpectedly accepted unsafe %s restore.\n' "$label" >&2
718756
exit 1
719757
fi
720758
/usr/bin/cmp -s "$config" "$config.original"
@@ -752,6 +790,7 @@ NO_DESKTOP_BACKUP="$TMP/theme-backup-without-desktop.json"
752790
"$NODE" "$ROOT/scripts/theme-config.mjs" install "$NO_DESKTOP_CONFIG" "$NO_DESKTOP_BACKUP" >/dev/null
753791
"$NODE" "$ROOT/scripts/theme-config.mjs" restore "$NO_DESKTOP_CONFIG" "$NO_DESKTOP_BACKUP" >/dev/null
754792
/usr/bin/cmp -s "$NO_DESKTOP_CONFIG" "$TMP/original-without-desktop.toml"
793+
[ ! -e "$NO_DESKTOP_BACKUP" ]
755794

756795
INVALID_UTF_CONFIG="$TMP/config-invalid-utf8.toml"
757796
INVALID_UTF_BACKUP="$TMP/config-invalid-utf8-backup.json"
@@ -763,6 +802,11 @@ if "$NODE" "$ROOT/scripts/theme-config.mjs" install \
763802
printf 'theme-config unexpectedly accepted invalid UTF-8.\n' >&2
764803
exit 1
765804
fi
805+
if "$NODE" "$ROOT/scripts/theme-config.mjs" restore \
806+
"$INVALID_UTF_CONFIG" "$INVALID_UTF_BACKUP" >/dev/null 2>&1; then
807+
printf 'theme-config restore unexpectedly accepted invalid UTF-8.\n' >&2
808+
exit 1
809+
fi
766810
/usr/bin/cmp -s "$INVALID_UTF_CONFIG" "$TMP/original-invalid-utf8.toml"
767811
[ ! -e "$INVALID_UTF_BACKUP" ]
768812
[ ! -e "$INVALID_UTF_CONFIG.dream-skin.lock" ]
@@ -776,11 +820,28 @@ assert_theme_config_install_rejected() {
776820
printf 'theme-config unexpectedly accepted invalid %s config.\n' "$label" >&2
777821
exit 1
778822
fi
823+
if "$NODE" "$ROOT/scripts/theme-config.mjs" restore "$config" "$backup" >/dev/null 2>&1; then
824+
printf 'theme-config restore unexpectedly accepted invalid %s config.\n' "$label" >&2
825+
exit 1
826+
fi
779827
/usr/bin/cmp -s "$config" "$config.original"
780828
[ ! -e "$backup" ]
781829
[ ! -e "$config.dream-skin.lock" ]
782830
}
783831

832+
assert_theme_config_install_noop() {
833+
local label="$1"
834+
local config="$2"
835+
local backup="$3"
836+
/bin/cp "$config" "$config.original"
837+
"$NODE" "$ROOT/scripts/theme-config.mjs" install "$config" "$backup" >/dev/null
838+
/usr/bin/cmp -s "$config" "$config.original"
839+
[ ! -e "$backup" ]
840+
"$NODE" "$ROOT/scripts/theme-config.mjs" restore "$config" "$backup" >/dev/null
841+
/usr/bin/cmp -s "$config" "$config.original"
842+
[ ! -e "$config.dream-skin.lock" ]
843+
}
844+
784845
SYMLINK_CONFIG_TARGET="$TMP/config-symlink-target.toml"
785846
SYMLINK_CONFIG_PATH="$TMP/config-symlink.toml"
786847
/usr/bin/printf '%s\n' '[desktop]' 'appearanceTheme = "system"' > "$SYMLINK_CONFIG_TARGET"
@@ -798,20 +859,37 @@ assert_theme_config_install_rejected nul "$NUL_CONFIG" "$TMP/config-nul-backup.j
798859
DUPLICATE_DESKTOP_CONFIG="$TMP/config-duplicate-desktop.toml"
799860
/usr/bin/printf '%s\n' '[desktop]' 'keep = 1' '[desktop]' 'keep = 2' \
800861
> "$DUPLICATE_DESKTOP_CONFIG"
801-
assert_theme_config_install_rejected duplicate-desktop "$DUPLICATE_DESKTOP_CONFIG" \
862+
assert_theme_config_install_noop duplicate-desktop "$DUPLICATE_DESKTOP_CONFIG" \
802863
"$TMP/config-duplicate-desktop-backup.json"
803864

804865
MULTILINE_CONFIG="$TMP/config-multiline.toml"
805866
/usr/bin/printf '%s\n' 'note = """value' 'continued"""' '[desktop]' 'keep = true' \
806867
> "$MULTILINE_CONFIG"
807-
assert_theme_config_install_rejected multiline "$MULTILINE_CONFIG" \
808-
"$TMP/config-multiline-backup.json"
868+
MULTILINE_BACKUP="$TMP/config-multiline-backup.json"
869+
assert_theme_config_install_noop multiline "$MULTILINE_CONFIG" "$MULTILINE_BACKUP"
870+
871+
PRESERVED_BACKUP="$TMP/config-preserved-backup.json"
872+
write_null_theme_backup "$PRESERVED_BACKUP" "$MULTILINE_CONFIG"
873+
/bin/cp "$PRESERVED_BACKUP" "$PRESERVED_BACKUP.original"
874+
"$NODE" "$ROOT/scripts/theme-config.mjs" install \
875+
"$MULTILINE_CONFIG" "$PRESERVED_BACKUP" >/dev/null
876+
/usr/bin/cmp -s "$PRESERVED_BACKUP" "$PRESERVED_BACKUP.original"
809877

810878
MULTILINE_ARRAY_CONFIG="$TMP/config-multiline-array.toml"
811879
/usr/bin/printf '%s\n' '[desktop]' 'rows = [' ' ["one", "two"],' ']' \
812880
'appearanceTheme = "system"' > "$MULTILINE_ARRAY_CONFIG"
813-
assert_theme_config_install_rejected multiline-array "$MULTILINE_ARRAY_CONFIG" \
814-
"$TMP/config-multiline-array-backup.json"
881+
MULTILINE_ARRAY_BACKUP="$TMP/config-multiline-array-backup.json"
882+
assert_theme_config_install_noop multiline-array \
883+
"$MULTILINE_ARRAY_CONFIG" "$MULTILINE_ARRAY_BACKUP"
884+
885+
write_null_theme_backup "$MULTILINE_BACKUP" "$MULTILINE_CONFIG"
886+
assert_theme_config_restore_rejected multiline-layout "$MULTILINE_CONFIG" \
887+
"$MULTILINE_BACKUP"
888+
/bin/rm -f "$MULTILINE_BACKUP"
889+
write_null_theme_backup "$MULTILINE_ARRAY_BACKUP" "$MULTILINE_ARRAY_CONFIG"
890+
assert_theme_config_restore_rejected multiline-array-layout \
891+
"$MULTILINE_ARRAY_CONFIG" "$MULTILINE_ARRAY_BACKUP"
892+
/bin/rm -f "$MULTILINE_ARRAY_BACKUP"
815893

816894
CRLF_CONFIG="$TMP/config-crlf.toml"
817895
CRLF_BACKUP="$TMP/config-crlf-backup.json"
@@ -821,6 +899,7 @@ CRLF_BACKUP="$TMP/config-crlf-backup.json"
821899
"$NODE" "$ROOT/scripts/theme-config.mjs" install "$CRLF_CONFIG" "$CRLF_BACKUP" >/dev/null
822900
"$NODE" "$ROOT/scripts/theme-config.mjs" restore "$CRLF_CONFIG" "$CRLF_BACKUP" >/dev/null
823901
/usr/bin/cmp -s "$CRLF_CONFIG" "$TMP/original-crlf.toml"
902+
[ ! -e "$CRLF_BACKUP" ]
824903

825904
/usr/bin/env -u HOME /bin/bash -c '. "$1/scripts/common-macos.sh"; [ -n "$HOME" ] && [ "$SKIN_VERSION" = "1.2.0" ]' _ "$ROOT"
826905
"$ROOT/scripts/doctor-macos.sh" >/dev/null

0 commit comments

Comments
 (0)