diff options
Diffstat (limited to 'src/integration/targets.rs')
| -rw-r--r-- | src/integration/targets.rs | 98 |
1 files changed, 63 insertions, 35 deletions
diff --git a/src/integration/targets.rs b/src/integration/targets.rs index cab8f7ee..6cb90c18 100644 --- a/src/integration/targets.rs +++ b/src/integration/targets.rs @@ -19,6 +19,7 @@ use super::config_edit::{ remove_direct_hook_commands, remove_flat_command_hook, remove_hermes_plugin_enabled, remove_hook_commands, remove_kimi_config_block, remove_simple_command_hook, }; +use super::config_file::{check_config_targets, write_config}; use super::env::{ antigravity_cli_dir, claude_dir, codex_dir, copilot_dir, cursor_dir, devin_dir, droid_dir, grok_dir, hermes_dir, hermes_plugin_dir, kilo_dir, kimi_dir, letta_dir, mastracode_dir, @@ -122,6 +123,7 @@ pub(crate) fn remove_legacy_pi_extension_from_omp_dir(dir: &Path) -> io::Result< pub(crate) fn install_claude() -> io::Result<ClaudeInstallPaths> { let dir = claude_dir()?; + check_config_targets(&dir, &["settings.json"])?; if !dir.is_dir() { return Err(io::Error::other(format!( "claude directory not found at {}. install claude code first", @@ -146,7 +148,7 @@ pub(crate) fn install_claude() -> io::Result<ClaudeInstallPaths> { remove_legacy_bash_hook_file(&hook_path)?; if updated_settings != existing_settings { - fs::write(&settings_path, updated_settings)?; + write_config(&settings_path, updated_settings)?; } Ok(ClaudeInstallPaths { @@ -157,6 +159,7 @@ pub(crate) fn install_claude() -> io::Result<ClaudeInstallPaths> { pub(crate) fn install_codex() -> io::Result<CodexInstallPaths> { let dir = codex_dir()?; + check_config_targets(&dir, &["hooks.json", "config.toml"])?; if !dir.is_dir() { return Err(io::Error::other(format!( "codex config directory not found at {}. install codex first", @@ -198,7 +201,7 @@ pub(crate) fn install_codex() -> io::Result<CodexInstallPaths> { )?; remove_legacy_bash_hook_file(&hook_path)?; - fs::write(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; + write_config(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; let config_path = dir.join("config.toml"); let existing_config = if config_path.is_file() { @@ -208,7 +211,7 @@ pub(crate) fn install_codex() -> io::Result<CodexInstallPaths> { }; let new_config = build_codex_config_with_hooks(&existing_config); if new_config != existing_config { - fs::write(&config_path, new_config)?; + write_config(&config_path, new_config)?; } Ok(CodexInstallPaths { @@ -220,6 +223,7 @@ pub(crate) fn install_codex() -> io::Result<CodexInstallPaths> { pub(crate) fn install_kimi() -> io::Result<KimiInstallPaths> { let dir = kimi_dir()?; + check_config_targets(&dir, &["config.toml"])?; if !dir.is_dir() { return Err(io::Error::other(format!( "kimi code config directory not found at {}. install kimi code first", @@ -242,7 +246,7 @@ pub(crate) fn install_kimi() -> io::Result<KimiInstallPaths> { }; let new_config = build_kimi_config_with_hooks(&existing_config, &hook_path); if new_config != existing_config { - fs::write(&config_path, new_config)?; + write_config(&config_path, new_config)?; } remove_legacy_bash_hook_file(&hook_path)?; @@ -254,6 +258,7 @@ pub(crate) fn install_kimi() -> io::Result<KimiInstallPaths> { pub(crate) fn install_copilot() -> io::Result<CopilotInstallPaths> { let dir = copilot_dir()?; + check_config_targets(&dir, &["settings.json"])?; if !dir.is_dir() { return Err(io::Error::other(format!( "copilot config directory not found at {}. install github copilot cli first", @@ -298,7 +303,7 @@ pub(crate) fn install_copilot() -> io::Result<CopilotInstallPaths> { } remove_legacy_bash_hook_file(&hook_path)?; - fs::write(&settings_path, serde_json::to_string_pretty(&settings)?)?; + write_config(&settings_path, serde_json::to_string_pretty(&settings)?)?; Ok(CopilotInstallPaths { hook_path, @@ -308,6 +313,7 @@ pub(crate) fn install_copilot() -> io::Result<CopilotInstallPaths> { pub(crate) fn install_devin() -> io::Result<DevinInstallPaths> { let dir = devin_dir()?; + check_config_targets(&dir, &["config.json"])?; if !dir.is_dir() { return Err(io::Error::other(format!( "devin config directory not found at {}. install devin cli first", @@ -354,7 +360,7 @@ pub(crate) fn install_devin() -> io::Result<DevinInstallPaths> { } remove_legacy_bash_hook_file(&hook_path)?; - fs::write(&settings_path, serde_json::to_string_pretty(&settings)?)?; + write_config(&settings_path, serde_json::to_string_pretty(&settings)?)?; Ok(DevinInstallPaths { hook_path, @@ -364,6 +370,7 @@ pub(crate) fn install_devin() -> io::Result<DevinInstallPaths> { pub(crate) fn install_droid() -> io::Result<DroidInstallPaths> { let dir = droid_dir()?; + check_config_targets(&dir, &["settings.json", "hooks.json"])?; if !dir.is_dir() { return Err(io::Error::other(format!( "droid config directory not found at {}. install droid first", @@ -414,7 +421,7 @@ pub(crate) fn install_droid() -> io::Result<DroidInstallPaths> { } remove_legacy_bash_hook_file(&hook_path)?; - fs::write(&settings_path, serde_json::to_string_pretty(&settings)?)?; + write_config(&settings_path, serde_json::to_string_pretty(&settings)?)?; let hooks_path = dir.join("hooks.json"); let mut updated_legacy_hooks = false; @@ -440,7 +447,7 @@ pub(crate) fn install_droid() -> io::Result<DroidInstallPaths> { } } if updated_legacy_hooks { - fs::write(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; + write_config(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; } } @@ -454,6 +461,7 @@ pub(crate) fn install_droid() -> io::Result<DroidInstallPaths> { pub(crate) fn install_opencode() -> io::Result<OpenCodeInstallPaths> { let dir = opencode_dir()?; + check_config_targets(&dir, &["tui.jsonc", "cli.json"])?; if !dir.is_dir() { return Err(io::Error::other(format!( "opencode config directory not found at {}. install opencode first", @@ -507,6 +515,7 @@ pub(crate) fn install_kilo() -> io::Result<KiloInstallPaths> { pub(crate) fn install_hermes() -> io::Result<HermesInstallPaths> { let dir = hermes_dir()?; + check_config_targets(&dir, &["config.yaml"])?; if !dir.is_dir() { return Err(io::Error::other(format!( "hermes config directory not found at {}. install hermes agent first", @@ -533,7 +542,7 @@ pub(crate) fn install_hermes() -> io::Result<HermesInstallPaths> { }; let new_config = ensure_hermes_plugin_enabled(&existing_config); if new_config != existing_config { - fs::write(&config_path, new_config)?; + write_config(&config_path, new_config)?; } Ok(HermesInstallPaths { @@ -563,8 +572,10 @@ pub(crate) fn uninstall_omp() -> io::Result<OmpUninstallResult> { } pub(crate) fn uninstall_claude() -> io::Result<ClaudeUninstallResult> { - let hook_path = claude_dir()?.join("hooks").join(CLAUDE_HOOK_INSTALL_NAME); - let settings_path = claude_dir()?.join("settings.json"); + let dir = claude_dir()?; + check_config_targets(&dir, &["settings.json"])?; + let hook_path = dir.join("hooks").join(CLAUDE_HOOK_INSTALL_NAME); + let settings_path = dir.join("settings.json"); let mut updated_settings = false; if settings_path.is_file() { @@ -573,7 +584,7 @@ pub(crate) fn uninstall_claude() -> io::Result<ClaudeUninstallResult> { uninstall_claude_settings(&existing_settings, &settings_path, &hook_path)?; updated_settings = new_settings != existing_settings; if updated_settings { - fs::write(&settings_path, new_settings)?; + write_config(&settings_path, new_settings)?; } } @@ -590,6 +601,7 @@ pub(crate) fn uninstall_claude() -> io::Result<ClaudeUninstallResult> { pub(crate) fn uninstall_codex() -> io::Result<CodexUninstallResult> { let codex_dir = codex_dir()?; + check_config_targets(&codex_dir, &["hooks.json"])?; let hook_path = codex_dir.join(CODEX_HOOK_INSTALL_NAME); let hooks_path = codex_dir.join("hooks.json"); let config_path = codex_dir.join("config.toml"); @@ -620,7 +632,7 @@ pub(crate) fn uninstall_codex() -> io::Result<CodexUninstallResult> { } if updated_hooks { - fs::write(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; + write_config(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; } } @@ -638,6 +650,7 @@ pub(crate) fn uninstall_codex() -> io::Result<CodexUninstallResult> { pub(crate) fn uninstall_kimi() -> io::Result<KimiUninstallResult> { let kimi_dir = kimi_dir()?; + check_config_targets(&kimi_dir, &["config.toml"])?; let hook_path = kimi_dir.join("hooks").join(KIMI_HOOK_INSTALL_NAME); let config_path = kimi_dir.join("config.toml"); let mut updated_config = false; @@ -646,7 +659,7 @@ pub(crate) fn uninstall_kimi() -> io::Result<KimiUninstallResult> { let existing_config = fs::read_to_string(&config_path)?; let new_config = remove_kimi_config_block(&existing_config); if new_config != existing_config { - fs::write(&config_path, new_config)?; + write_config(&config_path, new_config)?; updated_config = true; } } @@ -664,6 +677,7 @@ pub(crate) fn uninstall_kimi() -> io::Result<KimiUninstallResult> { pub(crate) fn uninstall_copilot() -> io::Result<CopilotUninstallResult> { let copilot_dir = copilot_dir()?; + check_config_targets(&copilot_dir, &["settings.json"])?; let hook_path = copilot_dir.join("hooks").join(COPILOT_HOOK_INSTALL_NAME); let settings_path = copilot_dir.join("settings.json"); let mut updated_settings = false; @@ -692,7 +706,7 @@ pub(crate) fn uninstall_copilot() -> io::Result<CopilotUninstallResult> { } if updated_settings { - fs::write(&settings_path, serde_json::to_string_pretty(&settings)?)?; + write_config(&settings_path, serde_json::to_string_pretty(&settings)?)?; } } @@ -709,6 +723,7 @@ pub(crate) fn uninstall_copilot() -> io::Result<CopilotUninstallResult> { pub(crate) fn uninstall_devin() -> io::Result<DevinUninstallResult> { let devin_dir = devin_dir()?; + check_config_targets(&devin_dir, &["config.json"])?; let hook_path = devin_dir.join(DEVIN_HOOK_INSTALL_NAME); let settings_path = devin_dir.join("config.json"); let mut updated_settings = false; @@ -737,7 +752,7 @@ pub(crate) fn uninstall_devin() -> io::Result<DevinUninstallResult> { } if updated_settings { - fs::write(&settings_path, serde_json::to_string_pretty(&settings)?)?; + write_config(&settings_path, serde_json::to_string_pretty(&settings)?)?; } } @@ -754,6 +769,7 @@ pub(crate) fn uninstall_devin() -> io::Result<DevinUninstallResult> { pub(crate) fn uninstall_droid() -> io::Result<DroidUninstallResult> { let droid_dir = droid_dir()?; + check_config_targets(&droid_dir, &["settings.json", "hooks.json"])?; let hook_path = droid_dir.join("hooks").join(DROID_HOOK_INSTALL_NAME); let hooks_path = droid_dir.join("hooks.json"); let settings_path = droid_dir.join("settings.json"); @@ -781,7 +797,7 @@ pub(crate) fn uninstall_droid() -> io::Result<DroidUninstallResult> { } if updated_hooks { - fs::write(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; + write_config(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; } } @@ -809,7 +825,7 @@ pub(crate) fn uninstall_droid() -> io::Result<DroidUninstallResult> { } if updated_settings { - fs::write(&settings_path, serde_json::to_string_pretty(&settings)?)?; + write_config(&settings_path, serde_json::to_string_pretty(&settings)?)?; } } @@ -828,6 +844,7 @@ pub(crate) fn uninstall_droid() -> io::Result<DroidUninstallResult> { pub(crate) fn uninstall_opencode() -> io::Result<OpenCodeUninstallResult> { let dir = opencode_dir()?; + check_config_targets(&dir, &["tui.jsonc", "cli.json"])?; let tui_config_path = tui_config_path(&dir); let plugin_path = dir.join("plugins").join(OPENCODE_PLUGIN_INSTALL_NAME); let tui_plugin_path = dir.join(OPENCODE_TUI_PLUGIN_INSTALL_NAME); @@ -883,6 +900,7 @@ pub(crate) fn uninstall_kilo() -> io::Result<KiloUninstallResult> { pub(crate) fn uninstall_hermes() -> io::Result<HermesUninstallResult> { let dir = hermes_dir()?; + check_config_targets(&dir, &["config.yaml"])?; let plugin_dir = hermes_plugin_dir()?; let config_path = dir.join("config.yaml"); @@ -892,7 +910,7 @@ pub(crate) fn uninstall_hermes() -> io::Result<HermesUninstallResult> { let existing_config = fs::read_to_string(&config_path)?; let new_config = remove_hermes_plugin_enabled(&existing_config); if new_config != existing_config { - fs::write(&config_path, new_config)?; + write_config(&config_path, new_config)?; updated_config = true; } } @@ -907,6 +925,7 @@ pub(crate) fn uninstall_hermes() -> io::Result<HermesUninstallResult> { pub(crate) fn install_qodercli() -> io::Result<QodercliInstallPaths> { let dir = qodercli_dir()?; + check_config_targets(&dir, &["settings.json"])?; if !dir.is_dir() { return Err(io::Error::other(format!( "qodercli config directory not found at {}. install qodercli first", @@ -961,7 +980,7 @@ pub(crate) fn install_qodercli() -> io::Result<QodercliInstallPaths> { } remove_legacy_bash_hook_file(&hook_path)?; - fs::write(&settings_path, serde_json::to_string_pretty(&settings)?)?; + write_config(&settings_path, serde_json::to_string_pretty(&settings)?)?; Ok(QodercliInstallPaths { hook_path, @@ -971,6 +990,7 @@ pub(crate) fn install_qodercli() -> io::Result<QodercliInstallPaths> { pub(crate) fn install_qwen() -> io::Result<QwenInstallPaths> { let dir = qwen_dir()?; + check_config_targets(&dir, &["settings.json"])?; if !dir.is_dir() { return Err(io::Error::other(format!( "qwen code config directory not found at {}. install qwen code first", @@ -1014,7 +1034,7 @@ pub(crate) fn install_qwen() -> io::Result<QwenInstallPaths> { )?; } - fs::write(&settings_path, serde_json::to_string_pretty(&settings)?)?; + write_config(&settings_path, serde_json::to_string_pretty(&settings)?)?; Ok(QwenInstallPaths { hook_path, @@ -1225,6 +1245,7 @@ pub(crate) fn install_letta() -> io::Result<LettaInstallPaths> { pub(crate) fn install_cursor() -> io::Result<CursorInstallPaths> { let dir = cursor_dir()?; + check_config_targets(&dir, &["hooks.json"])?; if !dir.is_dir() { return Err(io::Error::other(format!( "cursor config directory not found at {}. install cursor agent cli first", @@ -1271,7 +1292,7 @@ pub(crate) fn install_cursor() -> io::Result<CursorInstallPaths> { remove_simple_command_hook(hooks, "sessionEnd", &session_command)?; ensure_simple_command_hook(hooks, "sessionStart", session_command)?; - fs::write(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; + write_config(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; Ok(CursorInstallPaths { hook_path, @@ -1280,10 +1301,10 @@ pub(crate) fn install_cursor() -> io::Result<CursorInstallPaths> { } pub(crate) fn uninstall_qodercli() -> io::Result<QodercliUninstallResult> { - let hook_path = qodercli_dir()? - .join("hooks") - .join(QODERCLI_HOOK_INSTALL_NAME); - let settings_path = qodercli_dir()?.join("settings.json"); + let dir = qodercli_dir()?; + check_config_targets(&dir, &["settings.json"])?; + let hook_path = dir.join("hooks").join(QODERCLI_HOOK_INSTALL_NAME); + let settings_path = dir.join("settings.json"); let mut updated_settings = false; if settings_path.is_file() { @@ -1310,7 +1331,7 @@ pub(crate) fn uninstall_qodercli() -> io::Result<QodercliUninstallResult> { } if updated_settings { - fs::write(&settings_path, serde_json::to_string_pretty(&settings)?)?; + write_config(&settings_path, serde_json::to_string_pretty(&settings)?)?; } } @@ -1326,8 +1347,10 @@ pub(crate) fn uninstall_qodercli() -> io::Result<QodercliUninstallResult> { } pub(crate) fn uninstall_qwen() -> io::Result<QwenUninstallResult> { - let hook_path = qwen_dir()?.join("hooks").join(QWEN_HOOK_INSTALL_NAME); - let settings_path = qwen_dir()?.join("settings.json"); + let dir = qwen_dir()?; + check_config_targets(&dir, &["settings.json"])?; + let hook_path = dir.join("hooks").join(QWEN_HOOK_INSTALL_NAME); + let settings_path = dir.join("settings.json"); let mut updated_settings = false; if settings_path.is_file() { @@ -1351,7 +1374,7 @@ pub(crate) fn uninstall_qwen() -> io::Result<QwenUninstallResult> { } if updated_settings { - fs::write(&settings_path, serde_json::to_string_pretty(&settings)?)?; + write_config(&settings_path, serde_json::to_string_pretty(&settings)?)?; } } @@ -1407,6 +1430,7 @@ pub(crate) fn uninstall_letta() -> io::Result<LettaUninstallResult> { pub(crate) fn uninstall_cursor() -> io::Result<CursorUninstallResult> { let cursor_home = cursor_dir()?; + check_config_targets(&cursor_home, &["hooks.json"])?; let hook_path = cursor_home.join(CURSOR_HOOK_INSTALL_NAME); let hooks_path = cursor_home.join("hooks.json"); let mut updated_hooks = false; @@ -1436,7 +1460,7 @@ pub(crate) fn uninstall_cursor() -> io::Result<CursorUninstallResult> { } if updated_hooks { - fs::write(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; + write_config(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; } } @@ -1463,6 +1487,7 @@ pub(crate) fn mastracode_hook_command(hook_path: &Path, action: &str) -> String pub(crate) fn install_mastracode() -> io::Result<MastracodeInstallPaths> { let mastracode_home = mastracode_dir()?; + check_config_targets(&mastracode_home, &["hooks.json"])?; let hook_dir = mastracode_home.join("hooks"); fs::create_dir_all(&hook_dir)?; @@ -1500,7 +1525,7 @@ pub(crate) fn install_mastracode() -> io::Result<MastracodeInstallPaths> { )?; } - fs::write(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; + write_config(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; Ok(MastracodeInstallPaths { hook_path, @@ -1510,6 +1535,7 @@ pub(crate) fn install_mastracode() -> io::Result<MastracodeInstallPaths> { pub(crate) fn uninstall_mastracode() -> io::Result<MastracodeUninstallResult> { let mastracode_home = mastracode_dir()?; + check_config_targets(&mastracode_home, &["hooks.json"])?; let hook_path = mastracode_home .join("hooks") .join(MASTRACODE_HOOK_INSTALL_NAME); @@ -1542,7 +1568,7 @@ pub(crate) fn uninstall_mastracode() -> io::Result<MastracodeUninstallResult> { } if updated_hooks { - fs::write(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; + write_config(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; } } @@ -1558,6 +1584,7 @@ pub(crate) fn uninstall_mastracode() -> io::Result<MastracodeUninstallResult> { pub(crate) fn install_antigravity_cli() -> io::Result<AntigravityCliInstallPaths> { let dir = antigravity_cli_dir()?; + check_config_targets(&dir, &["hooks.json"])?; if !dir.is_dir() { return Err(io::Error::other(format!( "antigravity cli config directory not found at {}. install antigravity cli first", @@ -1595,7 +1622,7 @@ pub(crate) fn install_antigravity_cli() -> io::Result<AntigravityCliInstallPaths antigravity_cli_hook_block(&hook_path), ); - fs::write(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; + write_config(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; Ok(AntigravityCliInstallPaths { hook_path, @@ -1633,6 +1660,7 @@ fn antigravity_cli_hook_block(hook_path: &Path) -> Value { pub(crate) fn uninstall_antigravity_cli() -> io::Result<AntigravityCliUninstallResult> { let dir = antigravity_cli_dir()?; + check_config_targets(&dir, &["hooks.json"])?; let hook_path = dir.join("hooks").join(ANTIGRAVITY_CLI_HOOK_INSTALL_NAME); let hooks_path = dir.join("hooks.json"); let mut updated_hooks = false; @@ -1653,7 +1681,7 @@ pub(crate) fn uninstall_antigravity_cli() -> io::Result<AntigravityCliUninstallR updated_hooks = hooks.remove(ANTIGRAVITY_CLI_HOOK_BLOCK_NAME).is_some(); if updated_hooks { - fs::write(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; + write_config(&hooks_path, serde_json::to_string_pretty(&hooks_file)?)?; } } |
