Remove netcat dependency (#28920)

Closes #28813
Closes #27749

Release Notes:

- Removed the need to have openbsd `netcat` (`nc`) installed on your
system in order to enter passwords for `git` or `ssh` (remote
development). If you previously installed `netcat` specifically for Zed,
you may uninstall it.
This commit is contained in:
Ben Kunkle 2025-04-16 19:46:36 -04:00 committed by GitHub
parent 63b4b60b79
commit cbb6c221b3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 72 additions and 22 deletions

3
Cargo.lock generated
View File

@ -448,7 +448,6 @@ dependencies = [
"smol",
"tempfile",
"util",
"which 6.0.3",
"workspace-hack",
]
@ -11752,6 +11751,7 @@ name = "remote_server"
version = "0.1.0"
dependencies = [
"anyhow",
"askpass",
"async-watch",
"backtrace",
"cargo_toml",
@ -18204,6 +18204,7 @@ dependencies = [
"agent",
"anyhow",
"ashpd",
"askpass",
"assets",
"assistant",
"assistant_context_editor",

View File

@ -18,5 +18,4 @@ gpui.workspace = true
smol.workspace = true
tempfile.workspace = true
util.workspace = true
which.workspace = true
workspace-hack.workspace = true

View File

@ -72,6 +72,8 @@ impl AskPassSession {
let (askpass_opened_tx, askpass_opened_rx) = oneshot::channel::<()>();
let listener =
UnixListener::bind(&askpass_socket).context("failed to create askpass socket")?;
let zed_path = std::env::current_exe()
.context("Failed to figure out current executable path for use in askpass")?;
let (askpass_kill_master_tx, askpass_kill_master_rx) = oneshot::channel::<()>();
let mut kill_tx = Some(askpass_kill_master_tx);
@ -110,21 +112,10 @@ impl AskPassSession {
drop(temp_dir)
});
anyhow::ensure!(
which::which("nc").is_ok(),
"Cannot find `nc` command (netcat), which is required to connect over SSH."
);
// Create an askpass script that communicates back to this process.
let askpass_script = format!(
"{shebang}\n{print_args} | {nc} -U {askpass_socket} 2> /dev/null \n",
// on macOS `brew install netcat` provides the GNU netcat implementation
// which does not support -U.
nc = if cfg!(target_os = "macos") {
"/usr/bin/nc"
} else {
"nc"
},
"{shebang}\n{print_args} | {zed_exe} --askpass={askpass_socket} 2> /dev/null \n",
zed_exe = zed_path.display(),
askpass_socket = askpass_socket.display(),
print_args = "printf '%s\\0' \"$@\"",
shebang = "#!/bin/sh",
@ -170,6 +161,51 @@ impl AskPassSession {
}
}
/// The main function for when Zed is running in netcat mode for use in askpass.
/// Called from both the remote server binary and the zed binary in their respective main functions.
#[cfg(unix)]
pub fn main(socket: &str) {
use std::io::{self, Read, Write};
use std::os::unix::net::UnixStream;
use std::process::exit;
let mut stream = match UnixStream::connect(socket) {
Ok(stream) => stream,
Err(err) => {
eprintln!("Error connecting to socket {}: {}", socket, err);
exit(1);
}
};
let mut buffer = Vec::new();
if let Err(err) = io::stdin().read_to_end(&mut buffer) {
eprintln!("Error reading from stdin: {}", err);
exit(1);
}
if buffer.last() != Some(&b'\0') {
buffer.push(b'\0');
}
if let Err(err) = stream.write_all(&buffer) {
eprintln!("Error writing to socket: {}", err);
exit(1);
}
let mut response = Vec::new();
if let Err(err) = stream.read_to_end(&mut response) {
eprintln!("Error reading from socket: {}", err);
exit(1);
}
if let Err(err) = io::stdout().write_all(&response) {
eprintln!("Error writing to stdout: {}", err);
exit(1);
}
}
#[cfg(not(unix))]
pub fn main(_socket: &str) {}
#[cfg(not(unix))]
pub struct AskPassSession {
path: PathBuf,

View File

@ -23,6 +23,7 @@ test-support = ["fs/test-support"]
[dependencies]
anyhow.workspace = true
askpass.workspace = true
async-watch.workspace = true
backtrace = "0.3"
chrono.workspace = true

View File

@ -8,6 +8,10 @@ use std::path::PathBuf;
struct Cli {
#[command(subcommand)]
command: Option<Commands>,
/// Used for SSH/Git password authentication, to remove the need for netcat as a dependency,
/// by having Zed act like netcat communicating over a Unix socket.
#[arg(long, hide = true)]
askpass: Option<String>,
}
#[derive(Subcommand)]
@ -46,6 +50,11 @@ fn main() {
let cli = Cli::parse();
if let Some(socket_path) = &cli.askpass {
askpass::main(socket_path);
return;
}
let result = match cli.command {
Some(Commands::Run {
log_file,

View File

@ -18,6 +18,7 @@ path = "src/main.rs"
activity_indicator.workspace = true
agent.workspace = true
anyhow.workspace = true
askpass.workspace = true
assets.workspace = true
assistant.workspace = true
assistant_context_editor.workspace = true

View File

@ -180,6 +180,11 @@ fn main() {
let args = Args::parse();
if let Some(socket) = &args.askpass {
askpass::main(socket);
return;
}
// Set custom data directory.
if let Some(dir) = &args.user_data_dir {
paths::set_custom_data_dir(dir);
@ -1002,6 +1007,11 @@ struct Args {
#[arg(long)]
system_specs: bool,
/// Used for SSH/Git password authentication, to remove the need for netcat as a dependency,
/// by having Zed act like netcat communicating over a Unix socket.
#[arg(long, hide = true)]
askpass: Option<String>,
/// Run zed in the foreground, only used on Windows, to match the behavior of the behavior on macOS.
#[arg(long)]
#[cfg(target_os = "windows")]

View File

@ -38,7 +38,6 @@ if [[ -n $apt ]]; then
cmake
clang
jq
netcat-openbsd
git
curl
gettext-base
@ -88,14 +87,12 @@ if [[ -n $dnf ]] || [[ -n $yum ]]; then
tar
)
# perl used for building openssl-sys crate. See: https://docs.rs/openssl/latest/openssl/
# openbsd-netcat is unavailable in RHEL8/9 (and nmap-ncat doesn't support sockets)
if grep -qP '^ID="?(fedora)' /etc/os-release; then
deps+=(
perl-FindBin
perl-IPC-Cmd
perl-File-Compare
perl-File-Copy
netcat
mold
)
elif grep -qP '^ID="?(rhel|rocky|alma|centos|ol)' /etc/os-release; then
@ -152,7 +149,6 @@ if [[ -n $zyp ]]; then
libzstd-devel
make
mold
netcat-openbsd
openssl-devel
sqlite3-devel
tar
@ -179,7 +175,6 @@ if [[ -n $pacman ]]; then
libgit2
libxcb
libxkbcommon-x11
openbsd-netcat
openssl
zstd
pkgconf
@ -209,7 +204,6 @@ if [[ -n $xbps ]]; then
libxcb-devel
libxkbcommon-devel
libzstd-devel
openbsd-netcat
openssl-devel
wayland-devel
vulkan-loader
@ -234,7 +228,6 @@ if [[ -n $emerge ]]; then
media-libs/alsa-lib
media-libs/fontconfig
media-libs/vulkan-loader
net-analyzer/openbsd-netcat
x11-libs/libxcb
x11-libs/libxkbcommon
sys-devel/mold