diff --git a/Cargo.lock b/Cargo.lock index 11adf8028fd72..34db11c4a5674 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5504,6 +5504,7 @@ dependencies = [ "log", "lsp", "node_runtime", + "process", "project", "regex", "rope", @@ -5784,6 +5785,7 @@ dependencies = [ "lsp-types", "parking_lot", "postage", + "process", "release_channel", "serde", "serde_json", @@ -6226,6 +6228,7 @@ dependencies = [ "async-trait", "futures 0.3.28", "log", + "process", "semver", "serde", "serde_json", @@ -7372,6 +7375,7 @@ dependencies = [ "postage", "prettier", "pretty_assertions", + "process", "rand 0.8.5", "regex", "release_channel", diff --git a/crates/extension/src/extension_builder.rs b/crates/extension/src/extension_builder.rs index f242d54a684bb..41e1df9cafd5a 100644 --- a/crates/extension/src/extension_builder.rs +++ b/crates/extension/src/extension_builder.rs @@ -118,18 +118,14 @@ impl ExtensionBuilder { let cargo_toml: CargoToml = toml::from_str(&cargo_toml_content)?; log::info!("compiling rust extension {}", extension_dir.display()); - let mut process = process::Process::new("cargo"); - process + let output = process::Process::new("cargo") .args(["build", "--target", RUST_TARGET]) .args(options.release.then_some("--release")) .arg("--target-dir") .arg(extension_dir.join("target")) - .current_dir(&extension_dir); - let output = process + .current_dir(&extension_dir) .output() - .standard() .context("failed to run `cargo`")?; - if !output.status.success() { bail!( "failed to build extension {}", @@ -210,8 +206,7 @@ impl ExtensionBuilder { let scanner_path = src_path.join("scanner.c"); log::info!("compiling {grammar_name} parser"); - let mut process = process::Process::new(&clang_path); - process + let clang_output = process::Process::new(&clang_path) .args(["-fPIC", "-shared", "-Os"]) .arg(format!("-Wl,--export=tree_sitter_{grammar_name}")) .arg("-o") @@ -219,8 +214,9 @@ impl ExtensionBuilder { .arg("-I") .arg(&src_path) .arg(&parser_path) - .args(scanner_path.exists().then_some(scanner_path)); - let clang_output = process.output().standard().context("failed to run clang")?; + .args(scanner_path.exists().then_some(scanner_path)) + .output() + .context("failed to run clang")?; if !clang_output.status.success() { bail!( "failed to compile {} parser with clang: {}", @@ -236,13 +232,11 @@ impl ExtensionBuilder { let git_dir = directory.join(".git"); if directory.exists() { - let mut process = process::Process::new("git"); - process + let remotes_output = process::Process::new("git") .arg("--git-dir") .arg(&git_dir) - .args(["remote", "-v"]); - let remotes_output = process.output().standard()?; - + .args(["remote", "-v"]) + .output()?; let has_remote = remotes_output.status.success() && String::from_utf8_lossy(&remotes_output.stdout) .lines() @@ -261,10 +255,10 @@ impl ExtensionBuilder { fs::create_dir_all(&directory).with_context(|| { format!("failed to create grammar directory {}", directory.display(),) })?; - let mut process = process::Process::new("git"); - process.arg("init").current_dir(&directory); - let init_output = process.output().standard()?; - + let init_output = process::Process::new("git") + .arg("init") + .current_dir(&directory) + .output()?; if !init_output.status.success() { bail!( "failed to run `git init` in directory '{}'", @@ -272,16 +266,12 @@ impl ExtensionBuilder { ); } - let mut process = process::Process::new("git"); - process + let remote_add_output = process::Process::new("git") .arg("--git-dir") .arg(&git_dir) - .args(["remote", "add", "origin", url]); - let remote_add_output = process + .args(["remote", "add", "origin", url]) .output() - .standard() .context("failed to execute `git remote add`")?; - if !remote_add_output.status.success() { bail!( "failed to add remote {url} for git repository {}", @@ -290,27 +280,20 @@ impl ExtensionBuilder { } } - let mut process = process::Process::new("git"); - process + let fetch_output = process::Process::new("git") .arg("--git-dir") .arg(&git_dir) - .args(["fetch", "--depth", "1", "origin", &rev]); - let fetch_output = process + .args(["fetch", "--depth", "1", "origin", &rev]) .output() - .standard() .context("failed to execute `git fetch`")?; - let mut process = process::Process::new("git"); - process + let checkout_output = process::Process::new("git") .arg("--git-dir") .arg(&git_dir) .args(["checkout", &rev]) - .current_dir(&directory); - let checkout_output = process + .current_dir(&directory) .output() - .standard() .context("failed to execute `git checkout`")?; - if !checkout_output.status.success() { if !fetch_output.status.success() { bail!( @@ -331,10 +314,11 @@ impl ExtensionBuilder { } fn install_rust_wasm_target_if_needed(&self) -> Result<()> { - let mut process = process::Process::new("rustc"); - process.arg("--print").arg("sysroot"); - let rustc_output = process.output().standard().context("failed to run rustc")?; - + let rustc_output = process::Process::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .context("failed to run rustc")?; if !rustc_output.status.success() { bail!( "failed to retrieve rust sysroot: {}", @@ -347,16 +331,12 @@ impl ExtensionBuilder { return Ok(()); } - let mut process = process::Process::new("rustup"); - process + let output = process::Process::new("rustup") .args(["target", "add", RUST_TARGET]) .stderr(Stdio::inherit()) - .stdout(Stdio::inherit()); - let output = process + .stdout(Stdio::inherit()) .output() - .standard() .context("failed to run `rustup target add`")?; - if !output.status.success() { bail!("failed to install the `{RUST_TARGET}` target"); } diff --git a/crates/extension/src/wasm_host/wit/since_v0_0_6.rs b/crates/extension/src/wasm_host/wit/since_v0_0_6.rs index 7d3c7b638023c..aa749d5e33e43 100644 --- a/crates/extension/src/wasm_host/wit/since_v0_0_6.rs +++ b/crates/extension/src/wasm_host/wit/since_v0_0_6.rs @@ -344,7 +344,7 @@ impl ExtensionImports for WasmState { futures::pin_mut!(body); self.host.fs.create_file_with(&zip_path, body).await?; - let unzip_status = std::process::Command::new("unzip") + let unzip_status = process::Process::new("unzip") .current_dir(&extension_work_dir) .arg("-d") .arg(&destination_path) diff --git a/crates/git/src/blame.rs b/crates/git/src/blame.rs index 52e28e0a73a3e..a1b953a25642c 100644 --- a/crates/git/src/blame.rs +++ b/crates/git/src/blame.rs @@ -14,9 +14,6 @@ use time::OffsetDateTime; use time::UtcOffset; use url::Url; -#[cfg(windows)] -use process::WindowsCommandExt; - pub use git2 as libgit; #[derive(Debug, Clone, Default)] @@ -92,11 +89,10 @@ fn run_git_blame( .stderr(Stdio::piped()); #[cfg(windows)] - child.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0); + child.windows_creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0); let child = child .spawn() - .standard() .map_err(|e| anyhow!("Failed to start git blame process: {}", e))?; let mut stdin = child diff --git a/crates/git/src/commit.rs b/crates/git/src/commit.rs index 9d18575bf00b6..c70b968e33904 100644 --- a/crates/git/src/commit.rs +++ b/crates/git/src/commit.rs @@ -3,9 +3,6 @@ use anyhow::{anyhow, Result}; use collections::HashMap; use std::path::Path; -#[cfg(windows)] -use process::WindowsCommandExt; - pub fn get_messages(working_directory: &Path, shas: &[Oid]) -> Result> { const MARKER: &'static str = ""; @@ -19,11 +16,10 @@ pub fn get_messages(working_directory: &Path, shas: &[Oid]) -> Result Option { } let pkgid = String::from_utf8( - std::process::Command::new("cargo") + process::Process::new("cargo") .current_dir(package_directory) .arg("pkgid") .output() diff --git a/crates/lsp/Cargo.toml b/crates/lsp/Cargo.toml index e685ddf5a26dc..64d5b446c9c0d 100644 --- a/crates/lsp/Cargo.toml +++ b/crates/lsp/Cargo.toml @@ -24,6 +24,7 @@ gpui.workspace = true log.workspace = true lsp-types = { git = "https://github.com/zed-industries/lsp-types", branch = "updated-completion-list-item-defaults" } parking_lot.workspace = true +process.workspace = true postage.workspace = true serde.workspace = true serde_json.workspace = true diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index 65294974e7d17..9db6c240a4a55 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -13,12 +13,9 @@ use serde_json::{json, value::RawValue, Value}; use smol::{ channel, io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader}, - process::{self, Child}, + process::Child, }; -#[cfg(target_os = "windows")] -use smol::process::windows::CommandExt; - use std::{ ffi::OsString, fmt, @@ -259,18 +256,17 @@ impl LanguageServer { &binary.arguments ); - let mut command = process::Command::new(&binary.path); + let mut command = process::Process::new(&binary.path); command .current_dir(working_dir) .args(binary.arguments) .envs(binary.env.unwrap_or_default()) .stdin(Stdio::piped()) .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .kill_on_drop(true); + .stderr(Stdio::piped()); #[cfg(windows)] - command.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0); - let mut server = command.spawn()?; + command.windows_creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0); + let mut server = command.spawn_async(true)?; let stdin = server.stdin.take().unwrap(); let stdout = server.stdout.take().unwrap(); diff --git a/crates/node_runtime/Cargo.toml b/crates/node_runtime/Cargo.toml index 1097f85f38954..fec24dc925310 100644 --- a/crates/node_runtime/Cargo.toml +++ b/crates/node_runtime/Cargo.toml @@ -19,6 +19,7 @@ async-tar.workspace = true async-trait.workspace = true futures.workspace = true log.workspace = true +process.workspace = true semver.workspace = true serde.workspace = true serde_json.workspace = true diff --git a/crates/process/src/output.rs b/crates/process/src/output.rs deleted file mode 100644 index 0c57c39730e67..0000000000000 --- a/crates/process/src/output.rs +++ /dev/null @@ -1,65 +0,0 @@ -use smol::prelude::Future; -use std::io::Result; - -pub enum Child { - Standard(Result), - Smol(Result), -} - -impl Child { - pub fn standard(self) -> Result { - match self { - Self::Standard(inner) => inner, - _ => panic!("Cannot get smol child from Child::Standard"), - } - } - - pub fn smol(self) -> Result { - match self { - Self::Smol(inner) => inner, - _ => panic!("Cannot get standard child from Child::Smol"), - } - } -} - -pub enum Output { - Standard(Result), - Smol(Box>>), -} - -impl Output { - pub fn standard(self) -> Result { - match self { - Self::Standard(inner) => inner, - _ => panic!("Cannot get smol output from Output::Standard"), - } - } - - pub fn smol(self) -> Box>> { - match self { - Self::Smol(inner) => inner, - _ => panic!("Cannot get standard output from Output::Smol"), - } - } -} - -pub enum ExitStatus { - Standard(Result), - Smol(Box>>), -} - -impl ExitStatus { - pub fn standard(self) -> Result { - match self { - Self::Standard(inner) => inner, - _ => panic!("Cannot get smol exit status from ExitStatus::Standard"), - } - } - - pub fn smol(self) -> Box>> { - match self { - Self::Smol(inner) => inner, - _ => panic!("Cannot get standard exit status from ExitStatus::Smol"), - } - } -} diff --git a/crates/process/src/process.rs b/crates/process/src/process.rs index 5adef6e6b07a5..3c16c6d2aa2f4 100644 --- a/crates/process/src/process.rs +++ b/crates/process/src/process.rs @@ -1,60 +1,58 @@ +use std::collections::HashMap; use std::ffi::{OsStr, OsString}; +use std::io::Result; use std::path::{Path, PathBuf}; -use std::process::{Command, CommandEnvs, Stdio}; - -pub mod output; +use std::process::Stdio; #[cfg(windows)] use std::os::windows::process::CommandExt; -use output::{Child, ExitStatus, Output}; - -#[cfg(windows)] -pub trait WindowsCommandExt { - fn creation_flags(&mut self, flags: u32) -> &mut Process; - fn raw_arg>(&mut self, text_to_append_as_is: S) -> &mut Process; -} - pub struct Process { - process: std::process::Command, - - program: OsString, + program: PathBuf, working_dir: Option, - args: Vec, + args: Vec<(OsString, bool)>, + + stdin: Option, + stdout: Option, + stderr: Option, - use_pty: bool, - is_async: bool, + envs: HashMap, + cleared_env: bool, + removed_envs: Vec, + + flatpak_use_pty: bool, + #[cfg(windows)] + windows_creation_flags: u32, } impl Process { - pub fn new>(program: S) -> Self { + pub fn new>(program: P) -> Self { Self { - #[cfg(feature = "flatpak")] - process: Command::new("/app/bin/host-spawn"), - #[cfg(not(feature = "flatpak"))] - process: Command::new(&program), - - program: program.as_ref().into(), + program: program.as_ref().to_path_buf(), working_dir: None, args: Vec::new(), - use_pty: false, - is_async: false, + stdin: None, + stdout: None, + stderr: None, + + envs: HashMap::new(), + cleared_env: false, + removed_envs: Vec::new(), + + flatpak_use_pty: false, + #[cfg(windows)] + windows_creation_flags: 0, } } pub fn flatpak_use_pty(&mut self) -> &mut Self { - self.use_pty = true; - self - } - - pub fn make_async(&mut self) -> &mut Self { - self.is_async = true; + self.flatpak_use_pty = true; self } pub fn arg>(&mut self, arg: S) -> &mut Self { - self.args.push(arg.as_ref().into()); + self.args.push((arg.as_ref().to_os_string(), false)); self } @@ -71,7 +69,8 @@ impl Process { } pub fn env, V: AsRef>(&mut self, key: K, val: V) -> &mut Self { - self.process.env(key, val); + self.envs + .insert(key.as_ref().to_os_string(), val.as_ref().to_os_string()); self } @@ -79,146 +78,191 @@ impl Process { &mut self, vars: I, ) -> &mut Self { - self.process.envs(vars); + for (k, v) in vars { + self.env(k, v); + } self } - pub fn env_remove>(&mut self, key: K) -> &mut Self { - self.process.env_remove(key); + pub fn env_remove>(&mut self, key: S) -> &mut Self { + self.envs.remove(key.as_ref()); + self.removed_envs.push(key.as_ref().to_os_string()); self } pub fn env_clear(&mut self) -> &mut Self { - self.process.env_clear(); + self.cleared_env = true; + self.envs.clear(); self } pub fn stdin>(&mut self, cfg: T) -> &mut Self { - self.process.stdin(cfg); + self.stdin = Some(cfg.into()); self } pub fn stdout>(&mut self, cfg: T) -> &mut Self { - self.process.stdout(cfg); + self.stdout = Some(cfg.into()); self } pub fn stderr>(&mut self, cfg: T) -> &mut Self { - self.process.stderr(cfg); + self.stderr = Some(cfg.into()); self } - pub fn spawn(mut self) -> Child { - self.process.args(self.get_actual_args()); - if let Some(working_dir) = &self.working_dir { - self.process.current_dir(working_dir); - } + pub fn spawn(&mut self) -> Result { + self.make_command().spawn() + } - if self.is_async { - Child::Smol(smol::process::Command::from(self.process).spawn()) - } else { - Child::Standard(self.process.spawn()) - } + pub fn output(&mut self) -> Result { + self.make_command().output() } - pub fn output(mut self) -> Output { - self.process.args(self.get_actual_args()); - if let Some(working_dir) = &self.working_dir { - self.process.current_dir(working_dir); - } + pub fn status(&mut self) -> Result { + self.make_command().status() + } - if self.is_async { - Output::Smol(Box::new( - smol::process::Command::from(self.process).output(), - )) - } else { - Output::Standard(self.process.output()) - } + pub fn spawn_async(&mut self, kill_on_drop: bool) -> Result { + self.make_async_command(kill_on_drop).spawn() } - pub fn status(mut self) -> ExitStatus { - self.process.args(self.get_actual_args()); - if let Some(working_dir) = &self.working_dir { - self.process.current_dir(working_dir); - } + pub fn output_async( + &mut self, + kill_on_drop: bool, + ) -> impl std::future::Future> { + self.make_async_command(kill_on_drop).output() + } - if self.is_async { - ExitStatus::Smol(Box::new( - smol::process::Command::from(self.process).status(), - )) - } else { - ExitStatus::Standard(self.process.status()) - } + pub fn status_async( + &mut self, + kill_on_drop: bool, + ) -> impl std::future::Future> { + self.make_async_command(kill_on_drop).status() } - pub fn get_program(&self) -> &OsStr { + pub fn get_program(&self) -> &PathBuf { &self.program } - pub fn get_args(&self) -> &[OsString] { - &self.args + pub fn get_args(&self) -> Vec { + self.args + .iter() + .map(|(arg, _)| arg.clone()) + .collect::>() } - pub fn get_envs(&self) -> CommandEnvs<'_> { - self.process.get_envs() + pub fn get_envs(&self) -> &HashMap { + &self.envs } - pub fn get_actual_program(&self) -> &OsStr { - self.process.get_program() + #[cfg(windows)] + pub fn windows_creation_flags(&mut self, flags: u32) -> &mut Self { + self.windows_creation_flags |= flags; + self } - pub fn get_actual_args(&self) -> Vec { - #[cfg(feature = "flatpak")] - let mut args = self.flatpak_args(); + pub fn windows_raw_arg>(&mut self, raw_text: S) -> &mut Self { + self.args.push((raw_text.as_ref().to_os_string(), true)); + self + } + pub fn get_actual_program(&self) -> PathBuf { + #[cfg(feature = "flatpak")] + return ::from_str("/app/bin/host-spawn").unwrap(); #[cfg(not(feature = "flatpak"))] - let mut args = Vec::new(); + return self.program.clone(); + } - for arg in &self.args { - args.push(arg.clone()); - } - args + pub fn get_actual_args(&mut self) -> Vec { + let command = self.make_command_common(true); + command + .get_args() + .map(|arg| arg.to_str().unwrap().to_string()) + .collect() } - #[cfg(feature = "flatpak")] - fn flatpak_args(&self) -> Vec { - let env_keys = self - .process - .get_envs() - .map(|(k, _)| k.to_str().unwrap().to_string()) - .chain(std::env::vars().map(|(k, _)| k)) - .collect::>() - .join(","); - - let mut flatpak_args = Vec::new(); - - flatpak_args.push(if self.use_pty { - "-pty".into() - } else { - "-no-pty".into() - }); - if !env_keys.is_empty() { - flatpak_args.push("-env".into()); - flatpak_args.push(env_keys.into()); + fn make_command_common(&mut self, only_args: bool) -> std::process::Command { + let env = self + .envs + .clone() + .into_iter() + .chain( + std::env::vars() + .map(|(key, val)| (OsString::from(key), OsString::from(val))) + .filter(|(key, _)| !self.removed_envs.contains(key) && !self.cleared_env), + ) + .collect::>(); + + #[cfg(not(feature = "flatpak"))] + let mut command = std::process::Command::new(&self.program); + #[cfg(feature = "flatpak")] + let mut command = { + let mut command = std::process::Command::new("/app/bin/host-spawn"); + if let Some(working_directory) = &self.working_dir { + command.arg("-directory").arg(working_directory); + } + if !env.is_empty() { + command.arg("-env").arg( + env.iter() + .map(|(key, _)| key.clone()) + .collect::>() + .join(&OsString::from(",")), + ); + } + command.arg(if self.flatpak_use_pty { + "-pty" + } else { + "-no-pty" + }); + command.arg(self.program.as_os_str()); + command + }; + + if !only_args { + command.env_clear().envs(env); + if let Some(working_directory) = &self.working_dir { + command.current_dir(working_directory); + } } - if let Some(working_dir) = &self.working_dir { - flatpak_args.push("-directory".into()); - flatpak_args.push(working_dir.into()); + + for (arg, is_raw) in &self.args { + if *is_raw { + #[cfg(windows)] + command.raw_arg(arg); + } else { + command.arg(arg); + } } - flatpak_args.push(self.program.clone()); - flatpak_args + command } -} -#[cfg(windows)] -impl WindowsCommandExt for Process { - fn creation_flags(&mut self, flags: u32) -> &mut Self { - self.process.creation_flags(flags); - self + fn make_command(&mut self) -> std::process::Command { + let mut command = self.make_command_common(false); + if self.stdin.is_some() { + command.stdin(self.stdin.take().unwrap()); // smol::process::Command::from doesn't work with stdin et al + } + if self.stdout.is_some() { + command.stdout(self.stdout.take().unwrap()); + } + if self.stderr.is_some() { + command.stderr(self.stderr.take().unwrap()); + } + command } - fn raw_arg>(&mut self, raw_text: S) -> &mut Self { - self.process.raw_arg(raw_text); - self + fn make_async_command(&mut self, kill_on_drop: bool) -> smol::process::Command { + let mut command = smol::process::Command::from(self.make_command_common(false)); + if self.stdin.is_some() { + command.stdin(self.stdin.take().unwrap()); // smol::process::Command::from doesn't work with stdin et al + } + if self.stdout.is_some() { + command.stdout(self.stdout.take().unwrap()); + } + if self.stderr.is_some() { + command.stderr(self.stderr.take().unwrap()); + } + command.kill_on_drop(kill_on_drop); + command } } diff --git a/crates/project/Cargo.toml b/crates/project/Cargo.toml index 30766a7b6feb9..64c0f3c7ac249 100644 --- a/crates/project/Cargo.toml +++ b/crates/project/Cargo.toml @@ -45,6 +45,7 @@ node_runtime.workspace = true parking_lot.workspace = true postage.workspace = true prettier.workspace = true +process.workspace = true worktree.workspace = true rand.workspace = true regex.workspace = true diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 6113ea8e92b41..6072d7d36e994 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -3850,14 +3850,13 @@ impl Project { // A lack of test binary counts as a failure let process = installation_test_binary.and_then(|binary| { - smol::process::Command::new(&binary.path) + process::Process::new(&binary.path) .current_dir(&binary.path) .args(binary.arguments) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::inherit()) - .kill_on_drop(true) - .spawn() + .spawn_async(true) .ok() }); @@ -4896,7 +4895,7 @@ impl Project { if let Some(working_dir_path) = working_dir_path { let mut child = - smol::process::Command::new(command) + process::Process::new(command) .args(arguments.iter().map(|arg| { arg.replace("{buffer_path}", &buffer_abs_path.to_string_lossy()) })) @@ -4904,7 +4903,7 @@ impl Project { .stdin(smol::process::Stdio::piped()) .stdout(smol::process::Stdio::piped()) .stderr(smol::process::Stdio::piped()) - .spawn()?; + .spawn_async(false)?; let stdin = child .stdin .as_mut() @@ -10651,9 +10650,9 @@ async fn load_shell_environment(dir: &Path) -> Result> { additional_command.unwrap_or("") ); - let output = smol::process::Command::new(&shell) + let output = process::Process::new(&shell) .args(["-i", "-c", &command]) - .output() + .output_async(false) .await .context("failed to spawn login shell to source login environment variables")?; diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index dc4954f1a3c33..2533ec6d2be64 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -331,21 +331,17 @@ impl TerminalBuilder { Shell::WithArguments { program, args } => (Some(program), args), }; - let mut process = + let mut command = process::Process::new(shell_command.clone().unwrap_or("".to_string())); - process.flatpak_use_pty().envs(&env).args(additional_args); + command.flatpak_use_pty().envs(&env).args(additional_args); alacritty_terminal::tty::Options { shell: if shell_command.is_none() { None } else { Some(alacritty_terminal::tty::Shell::new( - process.get_actual_program().to_str().unwrap().to_string(), - process - .get_actual_args() - .iter() - .map(|arg| arg.to_str().unwrap().to_string()) - .collect(), + command.get_actual_program().to_str().unwrap().to_string(), + command.get_actual_args(), )) }, working_directory: working_directory.clone(), @@ -1557,10 +1553,11 @@ impl EventEmitter for Terminal {} #[cfg(feature = "flatpak")] fn flatpak_get_user_shell() -> Option { - let mut process = process::Process::new("getent"); - process.arg("passwd").arg(std::env::var("USER").unwrap()); - - match process.output().standard() { + match process::Process::new("getent") + .arg("passwd") + .arg(std::env::var("USER").unwrap()) + .output() + { Ok(output) => match String::from_utf8(output.stdout) { Ok(output) => output.trim().split(':').last().map(|str| str.to_string()), Err(_) => None, diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index d591b0525d80d..e471653430c54 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -37,7 +37,6 @@ use settings::{ default_settings, handle_settings_file_changes, watch_config_file, Settings, SettingsStore, }; use simplelog::ConfigBuilder; -use smol::process::Command; use std::{ env, ffi::OsStr, @@ -1008,9 +1007,9 @@ async fn load_login_shell_environment() -> Result<()> { shell_cmd_prefix.as_deref().unwrap_or("") ); - let output = Command::new(&shell) + let output = process::Process::new(&shell) .args(["-l", "-i", "-c", &shell_cmd]) - .output() + .output_async(false) .await .context("failed to spawn login shell to source login environment variables")?; if !output.status.success() {