main.rs

 1use clap::Parser;
 2use remote_server::Commands;
 3use std::io::Write as _;
 4use std::path::PathBuf;
 5
 6#[derive(Parser)]
 7#[command(disable_version_flag = true)]
 8struct Cli {
 9    #[command(subcommand)]
10    command: Option<Commands>,
11    /// Used for SSH/Git password authentication, to remove the need for netcat as a dependency,
12    /// by having Zed act like netcat communicating over a Unix socket.
13    #[arg(long, hide = true)]
14    askpass: Option<String>,
15    /// Used for recording minidumps on crashes by having the server run a separate
16    /// process communicating over a socket.
17    #[arg(long, hide = true)]
18    crash_handler: Option<PathBuf>,
19    /// Used for loading the environment from the project.
20    #[arg(long, hide = true)]
21    printenv: bool,
22}
23
24fn main() -> anyhow::Result<()> {
25    let cli = Cli::parse();
26
27    if let Some(socket_path) = &cli.askpass {
28        askpass::main(socket_path);
29        return Ok(());
30    }
31
32    if let Some(socket) = &cli.crash_handler {
33        crashes::crash_server(socket.as_path());
34        return Ok(());
35    }
36
37    if cli.printenv {
38        util::shell_env::print_env();
39        return Ok(());
40    }
41
42    #[cfg(not(windows))]
43    if let Some(command) = cli.command {
44        use remote_server::unix::ExecuteProxyError;
45
46        let res = remote_server::run(command);
47        if let Err(e) = &res
48            && let Some(e) = e.downcast_ref::<ExecuteProxyError>()
49        {
50            std::io::stderr().write_fmt(format_args!("{e:#}\n")).ok();
51            // It is important for us to report the proxy spawn exit code here
52            // instead of the generic 1 that result returns
53            // The client reads the exit code to determine if the server process has died when trying to reconnect
54            // signaling that it needs to try spawning a new server
55            std::process::exit(e.to_exit_code());
56        }
57        res
58    } else {
59        std::io::stderr()
60            .write_all(b"usage: remote <run|proxy|version>\n")
61            .ok();
62        std::process::exit(1);
63    }
64
65    #[cfg(windows)]
66    if let Some(_) = cli.command {
67        std::io::stderr()
68            .write_all(b"run is not supported on Windows\n")
69            .ok();
70        std::process::exit(2);
71    } else {
72        std::io::stderr()
73            .write_all(b"usage: remote <run|proxy|version>\n")
74            .ok();
75        std::process::exit(1);
76    }
77}