Mountain/IPC/WindServiceHandlers/NativeHost/
InstallShellCommand.rs1
2use std::path::PathBuf;
9
10use serde_json::Value;
11
12use crate::dev_log;
13
14const CLI_NAME:&str = "land";
15
16const SYMLINK_DIR:&str = "/usr/local/bin";
17
18pub async fn Fn(_Arguments:Vec<Value>) -> Result<Value, String> {
19 let ExePath = std::env::current_exe().map_err(|E| format!("installShellCommand: cannot get exe path: {E}"))?;
20
21 let Target = PathBuf::from(SYMLINK_DIR).join(CLI_NAME);
22
23 dev_log!("shell-cmd", "installShellCommand: {} → {}", Target.display(), ExePath.display());
24
25 let _ = std::fs::remove_file(&Target);
27
28 match std::os::unix::fs::symlink(&ExePath, &Target) {
29 Ok(()) => {
30 dev_log!("shell-cmd", "installShellCommand: symlink created");
31
32 Ok(Value::Bool(true))
33 },
34
35 Err(E) if E.kind() == std::io::ErrorKind::PermissionDenied => {
36 #[cfg(target_os = "macos")]
38 {
39 let Status = tokio::process::Command::new("osascript")
42 .env("SH_SRC", ExePath.as_os_str())
43 .env("SH_DST", Target.as_os_str())
44 .args([
45 "-e",
46 "do shell script (\"ln -sf \" & quoted form of (system attribute \"SH_SRC\") & \" \" & quoted \
47 form of (system attribute \"SH_DST\")) with administrator privileges",
48 ])
49 .status()
50 .await
51 .map_err(|E| format!("installShellCommand: osascript failed: {E}"))?;
52
53 if Status.success() {
54 dev_log!("shell-cmd", "installShellCommand: symlink created (elevated)");
55
56 return Ok(Value::Bool(true));
57 }
58 }
59
60 Err(format!("installShellCommand: permission denied and elevation failed"))
61 },
62
63 Err(E) => Err(format!("installShellCommand: {E}")),
64 }
65}