Skip to main content

DevelopmentNodeEnvironment_MicrosoftVSCodeDependency_22NodeVersion_Bundle_Clean_Debug_ElectronProfile_EsbuildCompiler_Mountain/IPC/WindServiceHandlers/NativeHost/
UninstallShellCommand.rs

1//! `nativeHost:uninstallShellCommand` - remove the `land` symlink from
2//! `/usr/local/bin`. Mirrors VS Code's "Uninstall 'code' command from PATH".
3
4use std::path::PathBuf;
5
6use serde_json::Value;
7
8use crate::dev_log;
9
10const CLI_NAME:&str = "land";
11
12const SYMLINK_DIR:&str = "/usr/local/bin";
13
14pub async fn Fn(_Arguments:Vec<Value>) -> Result<Value, String> {
15	let Target = PathBuf::from(SYMLINK_DIR).join(CLI_NAME);
16
17	dev_log!("shell-cmd", "uninstallShellCommand: removing {}", Target.display());
18
19	match std::fs::remove_file(&Target) {
20		Ok(()) => {
21			dev_log!("shell-cmd", "uninstallShellCommand: removed");
22
23			Ok(Value::Bool(true))
24		},
25
26		Err(E) if E.kind() == std::io::ErrorKind::NotFound => Ok(Value::Bool(true)),
27
28		Err(E) if E.kind() == std::io::ErrorKind::PermissionDenied => {
29			#[cfg(target_os = "macos")]
30			{
31				// Pass path via env var; use AppleScript's `quoted form of` for
32				// safe shell quoting - no interpolation into script source.
33				let Status = tokio::process::Command::new("osascript")
34					.env("SH_TARGET", Target.as_os_str())
35					.args([
36						"-e",
37						"do shell script (\"rm -f \" & quoted form of (system attribute \"SH_TARGET\")) with \
38						 administrator privileges",
39					])
40					.status()
41					.await
42					.map_err(|E| format!("uninstallShellCommand: osascript failed: {E}"))?;
43
44				if Status.success() {
45					return Ok(Value::Bool(true));
46				}
47			}
48
49			Err(format!("uninstallShellCommand: permission denied"))
50		},
51
52		Err(E) => Err(format!("uninstallShellCommand: {E}")),
53	}
54}