Cargo.lock 🔗
@@ -3929,6 +3929,17 @@ dependencies = [
"util",
]
+[[package]]
+name = "install_cli2"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "gpui2",
+ "log",
+ "smol",
+ "util",
+]
+
[[package]]
name = "instant"
version = "0.1.12"
Antonio Scandurra , Mikayla , and Kirill created
Co-authored-by: Mikayla <mikayla@zed.dev>
Co-Authored-By: Kirill <kirill@zed.dev>
Cargo.lock | 11 +++++
Cargo.toml | 1
crates/gpui2/src/app.rs | 5 ++
crates/install_cli2/Cargo.toml | 18 ++++++++
crates/install_cli2/src/install_cli2.rs | 57 +++++++++++++++++++++++++++
5 files changed, 92 insertions(+)
@@ -3929,6 +3929,17 @@ dependencies = [
"util",
]
+[[package]]
+name = "install_cli2"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "gpui2",
+ "log",
+ "smol",
+ "util",
+]
+
[[package]]
name = "instant"
version = "0.1.12"
@@ -46,6 +46,7 @@ members = [
"crates/gpui2",
"crates/gpui2_macros",
"crates/install_cli",
+ "crates/install_cli2",
"crates/journal",
"crates/language",
"crates/language2",
@@ -30,6 +30,7 @@ use std::{
marker::PhantomData,
mem,
ops::{Deref, DerefMut},
+ path::PathBuf,
sync::{atomic::Ordering::SeqCst, Arc, Weak},
time::Duration,
};
@@ -722,6 +723,10 @@ where
pub fn open_url(&self, url: &str) {
self.platform().open_url(url);
}
+
+ pub fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf> {
+ self.platform().path_for_auxiliary_executable(name)
+ }
}
impl MainThread<AppContext> {
@@ -0,0 +1,18 @@
+[package]
+name = "install_cli2"
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[lib]
+path = "src/install_cli2.rs"
+
+[features]
+test-support = []
+
+[dependencies]
+smol.workspace = true
+anyhow.workspace = true
+log.workspace = true
+gpui2 = { path = "../gpui2" }
+util = { path = "../util" }
@@ -0,0 +1,57 @@
+use anyhow::{anyhow, Result};
+use gpui2::AsyncAppContext;
+use std::path::Path;
+use util::ResultExt;
+
+// todo!()
+// actions!(cli, [Install]);
+
+pub async fn install_cli(cx: &AsyncAppContext) -> Result<()> {
+ let cli_path = cx
+ .run_on_main(|cx| cx.path_for_auxiliary_executable("cli"))?
+ .await?;
+ let link_path = Path::new("/usr/local/bin/zed");
+ let bin_dir_path = link_path.parent().unwrap();
+
+ // Don't re-create symlink if it points to the same CLI binary.
+ if smol::fs::read_link(link_path).await.ok().as_ref() == Some(&cli_path) {
+ return Ok(());
+ }
+
+ // If the symlink is not there or is outdated, first try replacing it
+ // without escalating.
+ smol::fs::remove_file(link_path).await.log_err();
+ if smol::fs::unix::symlink(&cli_path, link_path)
+ .await
+ .log_err()
+ .is_some()
+ {
+ return Ok(());
+ }
+
+ // The symlink could not be created, so use osascript with admin privileges
+ // to create it.
+ let status = smol::process::Command::new("/usr/bin/osascript")
+ .args([
+ "-e",
+ &format!(
+ "do shell script \" \
+ mkdir -p \'{}\' && \
+ ln -sf \'{}\' \'{}\' \
+ \" with administrator privileges",
+ bin_dir_path.to_string_lossy(),
+ cli_path.to_string_lossy(),
+ link_path.to_string_lossy(),
+ ),
+ ])
+ .stdout(smol::process::Stdio::inherit())
+ .stderr(smol::process::Stdio::inherit())
+ .output()
+ .await?
+ .status;
+ if status.success() {
+ Ok(())
+ } else {
+ Err(anyhow!("error running osascript"))
+ }
+}