Use osascript to escalate privileges and copy the CLI to /usr/local/bin

This commit is contained in:
Antonio Scandurra 2022-04-20 10:22:20 +02:00
parent 0d9a0e2cbe
commit b3f2b7a92c

View File

@ -4,7 +4,7 @@ pub mod settings_file;
#[cfg(any(test, feature = "test-support"))]
pub mod test;
use anyhow::Context;
use anyhow::{anyhow, Context, Result};
use breadcrumbs::Breadcrumbs;
use chat_panel::ChatPanel;
pub use client;
@ -16,7 +16,7 @@ use gpui::{
actions,
geometry::vector::vec2f,
platform::{WindowBounds, WindowOptions},
ModelHandle, ViewContext,
AsyncAppContext, ModelHandle, ViewContext,
};
use lazy_static::lazy_static;
pub use lsp;
@ -26,7 +26,10 @@ use project_panel::ProjectPanel;
use search::{BufferSearchBar, ProjectSearchBar};
use serde_json::to_string_pretty;
use settings::Settings;
use std::{path::PathBuf, sync::Arc};
use std::{
path::{Path, PathBuf},
sync::Arc,
};
use util::ResultExt;
pub use workspace;
use workspace::{AppState, Workspace, WorkspaceParams};
@ -69,25 +72,8 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut gpui::MutableAppContext) {
});
});
cx.add_global_action(move |_: &InstallCommandLineTool, cx| {
cx.spawn(|cx| async move {
log::info!("installing command line launcher");
let cli_path = cx
.platform()
.path_for_auxiliary_executable("cli")
.log_err()?;
let link_path = "/opt/homebrew/bin/zed";
smol::fs::unix::symlink(cli_path.as_path(), link_path)
.await
.context("failed to install cli symlink")
.log_err()?;
log::info!(
"created symlink {} -> {}",
link_path,
cli_path.to_string_lossy()
);
Some(())
})
.detach();
cx.spawn(|cx| async move { install_cli(&cx).await.context("error creating CLI symlink") })
.detach_and_log_err(cx);
});
cx.add_action({
let app_state = app_state.clone();
@ -253,6 +239,54 @@ fn quit(_: &Quit, cx: &mut gpui::MutableAppContext) {
cx.platform().quit();
}
async fn install_cli(cx: &AsyncAppContext) -> Result<()> {
let cli_path = cx.platform().path_for_auxiliary_executable("cli")?;
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("osascript")
.args([
"-e",
&dbg!(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"))
}
}
#[cfg(test)]
mod tests {
use super::*;