1use anyhow::{anyhow, Result};
2use gpui2::AsyncAppContext;
3use std::path::Path;
4use util::ResultExt;
5
6// todo!()
7// actions!(cli, [Install]);
8
9pub async fn install_cli(cx: &AsyncAppContext) -> Result<()> {
10 let cli_path = cx
11 .run_on_main(|cx| cx.path_for_auxiliary_executable("cli"))?
12 .await?;
13 let link_path = Path::new("/usr/local/bin/zed");
14 let bin_dir_path = link_path.parent().unwrap();
15
16 // Don't re-create symlink if it points to the same CLI binary.
17 if smol::fs::read_link(link_path).await.ok().as_ref() == Some(&cli_path) {
18 return Ok(());
19 }
20
21 // If the symlink is not there or is outdated, first try replacing it
22 // without escalating.
23 smol::fs::remove_file(link_path).await.log_err();
24 if smol::fs::unix::symlink(&cli_path, link_path)
25 .await
26 .log_err()
27 .is_some()
28 {
29 return Ok(());
30 }
31
32 // The symlink could not be created, so use osascript with admin privileges
33 // to create it.
34 let status = smol::process::Command::new("/usr/bin/osascript")
35 .args([
36 "-e",
37 &format!(
38 "do shell script \" \
39 mkdir -p \'{}\' && \
40 ln -sf \'{}\' \'{}\' \
41 \" with administrator privileges",
42 bin_dir_path.to_string_lossy(),
43 cli_path.to_string_lossy(),
44 link_path.to_string_lossy(),
45 ),
46 ])
47 .stdout(smol::process::Stdio::inherit())
48 .stderr(smol::process::Stdio::inherit())
49 .output()
50 .await?
51 .status;
52 if status.success() {
53 Ok(())
54 } else {
55 Err(anyhow!("error running osascript"))
56 }
57}