Allow cli to accept --dev-server-token (#10944)

Conrad Irwin created

Release Notes:

- N/A

Change summary

Cargo.lock                      |  1 +
crates/cli/src/main.rs          | 28 ++++++++++++++++++++++++++--
crates/headless/Cargo.toml      |  1 +
crates/headless/src/headless.rs |  7 +++++--
4 files changed, 33 insertions(+), 4 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -4724,6 +4724,7 @@ dependencies = [
  "project",
  "rpc",
  "settings",
+ "shellexpand",
  "util",
 ]
 

crates/cli/src/main.rs 🔗

@@ -36,6 +36,9 @@ struct Args {
     /// Custom Zed.app path
     #[arg(short, long)]
     bundle_path: Option<PathBuf>,
+    /// Run zed in dev-server mode
+    #[arg(long)]
+    dev_server_token: Option<String>,
 }
 
 fn parse_path_with_position(
@@ -67,6 +70,10 @@ fn main() -> Result<()> {
 
     let bundle = Bundle::detect(args.bundle_path.as_deref()).context("Bundle detection")?;
 
+    if let Some(dev_server_token) = args.dev_server_token {
+        return bundle.spawn(vec!["--dev-server-token".into(), dev_server_token]);
+    }
+
     if args.version {
         println!("{}", bundle.zed_version_string());
         return Ok(());
@@ -169,6 +176,10 @@ mod linux {
             unimplemented!()
         }
 
+        pub fn spawn(&self, _args: Vec<String>) -> anyhow::Result<()> {
+            unimplemented!()
+        }
+
         pub fn zed_version_string(&self) -> String {
             unimplemented!()
         }
@@ -202,6 +213,10 @@ mod windows {
             unimplemented!()
         }
 
+        pub fn spawn(&self, _args: Vec<String>) -> anyhow::Result<()> {
+            unimplemented!()
+        }
+
         pub fn zed_version_string(&self) -> String {
             unimplemented!()
         }
@@ -217,7 +232,7 @@ mod mac_os {
         url::{CFURLCreateWithBytes, CFURL},
     };
     use core_services::{kLSLaunchDefaults, LSLaunchURLSpec, LSOpenFromURLSpec, TCFType};
-    use std::{fs, path::Path, ptr};
+    use std::{fs, path::Path, process::Command, ptr};
 
     use cli::{CliRequest, CliResponse, IpcHandshake, FORCE_CLI_MODE_ENV_VAR_NAME};
     use ipc_channel::ipc::{IpcOneShotServer, IpcReceiver, IpcSender};
@@ -278,6 +293,15 @@ mod mac_os {
             }
         }
 
+        pub fn spawn(&self, args: Vec<String>) -> Result<()> {
+            let path = match self {
+                Self::App { app_bundle, .. } => app_bundle.join("Contents/MacOS/zed"),
+                Self::LocalPath { executable, .. } => executable.clone(),
+            };
+            Command::new(path).args(args).status()?;
+            Ok(())
+        }
+
         pub fn launch(&self) -> anyhow::Result<(IpcSender<CliRequest>, IpcReceiver<CliResponse>)> {
             let (server, server_name) =
                 IpcOneShotServer::<IpcHandshake>::new().context("Handshake before Zed spawn")?;
@@ -358,12 +382,12 @@ mod mac_os {
             )
         }
     }
+
     pub(super) fn spawn_channel_cli(
         channel: release_channel::ReleaseChannel,
         leftover_args: Vec<String>,
     ) -> Result<()> {
         use anyhow::bail;
-        use std::process::Command;
 
         let app_id_prompt = format!("id of app \"{}\"", channel.display_name());
         let app_id_output = Command::new("osascript")

crates/headless/Cargo.toml 🔗

@@ -26,6 +26,7 @@ project.workspace = true
 fs.workspace = true
 futures.workspace = true
 settings.workspace = true
+shellexpand.workspace = true
 postage.workspace = true
 
 [dev-dependencies]

crates/headless/src/headless.rs 🔗

@@ -180,7 +180,8 @@ impl DevServer {
         _: Arc<Client>,
         cx: AsyncAppContext,
     ) -> Result<proto::Ack> {
-        let path = std::path::Path::new(&envelope.payload.path);
+        let expanded = shellexpand::tilde(&envelope.payload.path).to_string();
+        let path = std::path::Path::new(&expanded);
         let fs = cx.read_model(&this, |this, _| this.app_state.fs.clone())?;
 
         let path_exists = fs.is_dir(path).await;
@@ -232,9 +233,11 @@ impl DevServer {
             (this.client.clone(), project)
         })?;
 
+        let path = shellexpand::tilde(&remote_project.path).to_string();
+
         project
             .update(cx, |project, cx| {
-                project.find_or_create_local_worktree(&remote_project.path, true, cx)
+                project.find_or_create_local_worktree(&path, true, cx)
             })?
             .await?;