windows: Set CREATE_NO_WINDOW for commands (#18447)

- Closes: #18371

Release Notes:

- N/A
This commit is contained in:
张小白 2024-11-21 08:52:38 +08:00 committed by GitHub
parent 49ed932c1f
commit 95ace03706
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 122 additions and 174 deletions

9
Cargo.lock generated
View file

@ -4030,6 +4030,7 @@ dependencies = [
"serde_json", "serde_json",
"settings", "settings",
"smol", "smol",
"util",
] ]
[[package]] [[package]]
@ -4115,6 +4116,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"toml 0.8.19", "toml 0.8.19",
"util",
"wasm-encoder 0.215.0", "wasm-encoder 0.215.0",
"wasmparser 0.215.0", "wasmparser 0.215.0",
"wit-component", "wit-component",
@ -4936,7 +4938,6 @@ dependencies = [
"unindent", "unindent",
"url", "url",
"util", "util",
"windows 0.58.0",
] ]
[[package]] [[package]]
@ -6951,7 +6952,6 @@ dependencies = [
"serde_json", "serde_json",
"smol", "smol",
"util", "util",
"windows 0.58.0",
] ]
[[package]] [[package]]
@ -7490,7 +7490,6 @@ dependencies = [
"util", "util",
"walkdir", "walkdir",
"which 6.0.3", "which 6.0.3",
"windows 0.58.0",
] ]
[[package]] [[package]]
@ -9179,7 +9178,6 @@ dependencies = [
"url", "url",
"util", "util",
"which 6.0.3", "which 6.0.3",
"windows 0.58.0",
"worktree", "worktree",
] ]
@ -9941,7 +9939,6 @@ dependencies = [
"ui", "ui",
"util", "util",
"uuid", "uuid",
"windows 0.58.0",
"workspace", "workspace",
] ]
@ -11829,7 +11826,6 @@ dependencies = [
"ui", "ui",
"unicode-segmentation", "unicode-segmentation",
"util", "util",
"windows 0.58.0",
] ]
[[package]] [[package]]
@ -13548,6 +13544,7 @@ dependencies = [
"rust-embed", "rust-embed",
"serde", "serde",
"serde_json", "serde_json",
"smol",
"take-until", "take-until",
"tempfile", "tempfile",
"tendril", "tendril",

View file

@ -9,7 +9,7 @@ use serde_json::{value::RawValue, Value};
use smol::{ use smol::{
channel, channel,
io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, io::{AsyncBufReadExt, AsyncWriteExt, BufReader},
process::{self, Child}, process::Child,
}; };
use std::{ use std::{
fmt, fmt,
@ -152,7 +152,7 @@ impl Client {
&binary.args &binary.args
); );
let mut command = process::Command::new(&binary.executable); let mut command = util::command::new_smol_command(&binary.executable);
command command
.args(&binary.args) .args(&binary.args)
.envs(binary.env.unwrap_or_default()) .envs(binary.env.unwrap_or_default())

View file

@ -30,9 +30,10 @@ languages.workspace = true
node_runtime.workspace = true node_runtime.workspace = true
open_ai.workspace = true open_ai.workspace = true
project.workspace = true project.workspace = true
reqwest_client.workspace = true
semantic_index.workspace = true semantic_index.workspace = true
serde.workspace = true serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
settings.workspace = true settings.workspace = true
smol.workspace = true smol.workspace = true
reqwest_client.workspace = true util.workspace = true

View file

@ -27,7 +27,7 @@ use std::time::Duration;
use std::{ use std::{
fs, fs,
path::Path, path::Path,
process::{exit, Command, Stdio}, process::{exit, Stdio},
sync::{ sync::{
atomic::{AtomicUsize, Ordering::SeqCst}, atomic::{AtomicUsize, Ordering::SeqCst},
Arc, Arc,
@ -667,7 +667,7 @@ async fn fetch_eval_repo(
return; return;
} }
if !repo_dir.join(".git").exists() { if !repo_dir.join(".git").exists() {
let init_output = Command::new("git") let init_output = util::command::new_std_command("git")
.current_dir(&repo_dir) .current_dir(&repo_dir)
.args(&["init"]) .args(&["init"])
.output() .output()
@ -682,13 +682,13 @@ async fn fetch_eval_repo(
} }
} }
let url = format!("https://github.com/{}.git", repo); let url = format!("https://github.com/{}.git", repo);
Command::new("git") util::command::new_std_command("git")
.current_dir(&repo_dir) .current_dir(&repo_dir)
.args(&["remote", "add", "-f", "origin", &url]) .args(&["remote", "add", "-f", "origin", &url])
.stdin(Stdio::null()) .stdin(Stdio::null())
.output() .output()
.unwrap(); .unwrap();
let fetch_output = Command::new("git") let fetch_output = util::command::new_std_command("git")
.current_dir(&repo_dir) .current_dir(&repo_dir)
.args(&["fetch", "--depth", "1", "origin", &sha]) .args(&["fetch", "--depth", "1", "origin", &sha])
.stdin(Stdio::null()) .stdin(Stdio::null())
@ -703,7 +703,7 @@ async fn fetch_eval_repo(
); );
return; return;
} }
let checkout_output = Command::new("git") let checkout_output = util::command::new_std_command("git")
.current_dir(&repo_dir) .current_dir(&repo_dir)
.args(&["checkout", &sha]) .args(&["checkout", &sha])
.output() .output()

View file

@ -28,6 +28,7 @@ semantic_version.workspace = true
serde.workspace = true serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
toml.workspace = true toml.workspace = true
util.workspace = true
wasm-encoder.workspace = true wasm-encoder.workspace = true
wasmparser.workspace = true wasmparser.workspace = true
wit-component.workspace = true wit-component.workspace = true

View file

@ -11,7 +11,7 @@ use serde::Deserialize;
use std::{ use std::{
env, fs, mem, env, fs, mem,
path::{Path, PathBuf}, path::{Path, PathBuf},
process::{Command, Stdio}, process::Stdio,
sync::Arc, sync::Arc,
}; };
use wasm_encoder::{ComponentSectionId, Encode as _, RawSection, Section as _}; use wasm_encoder::{ComponentSectionId, Encode as _, RawSection, Section as _};
@ -130,7 +130,7 @@ impl ExtensionBuilder {
"compiling Rust crate for extension {}", "compiling Rust crate for extension {}",
extension_dir.display() extension_dir.display()
); );
let output = Command::new("cargo") let output = util::command::new_std_command("cargo")
.args(["build", "--target", RUST_TARGET]) .args(["build", "--target", RUST_TARGET])
.args(options.release.then_some("--release")) .args(options.release.then_some("--release"))
.arg("--target-dir") .arg("--target-dir")
@ -237,7 +237,7 @@ impl ExtensionBuilder {
let scanner_path = src_path.join("scanner.c"); let scanner_path = src_path.join("scanner.c");
log::info!("compiling {grammar_name} parser"); log::info!("compiling {grammar_name} parser");
let clang_output = Command::new(&clang_path) let clang_output = util::command::new_std_command(&clang_path)
.args(["-fPIC", "-shared", "-Os"]) .args(["-fPIC", "-shared", "-Os"])
.arg(format!("-Wl,--export=tree_sitter_{grammar_name}")) .arg(format!("-Wl,--export=tree_sitter_{grammar_name}"))
.arg("-o") .arg("-o")
@ -264,7 +264,7 @@ impl ExtensionBuilder {
let git_dir = directory.join(".git"); let git_dir = directory.join(".git");
if directory.exists() { if directory.exists() {
let remotes_output = Command::new("git") let remotes_output = util::command::new_std_command("git")
.arg("--git-dir") .arg("--git-dir")
.arg(&git_dir) .arg(&git_dir)
.args(["remote", "-v"]) .args(["remote", "-v"])
@ -287,7 +287,7 @@ impl ExtensionBuilder {
fs::create_dir_all(directory).with_context(|| { fs::create_dir_all(directory).with_context(|| {
format!("failed to create grammar directory {}", directory.display(),) format!("failed to create grammar directory {}", directory.display(),)
})?; })?;
let init_output = Command::new("git") let init_output = util::command::new_std_command("git")
.arg("init") .arg("init")
.current_dir(directory) .current_dir(directory)
.output()?; .output()?;
@ -298,7 +298,7 @@ impl ExtensionBuilder {
); );
} }
let remote_add_output = Command::new("git") let remote_add_output = util::command::new_std_command("git")
.arg("--git-dir") .arg("--git-dir")
.arg(&git_dir) .arg(&git_dir)
.args(["remote", "add", "origin", url]) .args(["remote", "add", "origin", url])
@ -312,14 +312,14 @@ impl ExtensionBuilder {
} }
} }
let fetch_output = Command::new("git") let fetch_output = util::command::new_std_command("git")
.arg("--git-dir") .arg("--git-dir")
.arg(&git_dir) .arg(&git_dir)
.args(["fetch", "--depth", "1", "origin", rev]) .args(["fetch", "--depth", "1", "origin", rev])
.output() .output()
.context("failed to execute `git fetch`")?; .context("failed to execute `git fetch`")?;
let checkout_output = Command::new("git") let checkout_output = util::command::new_std_command("git")
.arg("--git-dir") .arg("--git-dir")
.arg(&git_dir) .arg(&git_dir)
.args(["checkout", rev]) .args(["checkout", rev])
@ -346,7 +346,7 @@ impl ExtensionBuilder {
} }
fn install_rust_wasm_target_if_needed(&self) -> Result<()> { fn install_rust_wasm_target_if_needed(&self) -> Result<()> {
let rustc_output = Command::new("rustc") let rustc_output = util::command::new_std_command("rustc")
.arg("--print") .arg("--print")
.arg("sysroot") .arg("sysroot")
.output() .output()
@ -363,7 +363,7 @@ impl ExtensionBuilder {
return Ok(()); return Ok(());
} }
let output = Command::new("rustup") let output = util::command::new_std_command("rustup")
.args(["target", "add", RUST_TARGET]) .args(["target", "add", RUST_TARGET])
.stderr(Stdio::piped()) .stderr(Stdio::piped())
.stdout(Stdio::inherit()) .stdout(Stdio::inherit())

View file

@ -31,10 +31,6 @@ time.workspace = true
url.workspace = true url.workspace = true
util.workspace = true util.workspace = true
[target.'cfg(target_os = "windows")'.dependencies]
windows.workspace = true
[dev-dependencies] [dev-dependencies]
unindent.workspace = true unindent.workspace = true
serde_json.workspace = true serde_json.workspace = true

View file

@ -4,7 +4,7 @@ use anyhow::{anyhow, Context, Result};
use collections::{HashMap, HashSet}; use collections::{HashMap, HashSet};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::io::Write; use std::io::Write;
use std::process::{Command, Stdio}; use std::process::Stdio;
use std::sync::Arc; use std::sync::Arc;
use std::{ops::Range, path::Path}; use std::{ops::Range, path::Path};
use text::Rope; use text::Rope;
@ -80,9 +80,7 @@ fn run_git_blame(
path: &Path, path: &Path,
contents: &Rope, contents: &Rope,
) -> Result<String> { ) -> Result<String> {
let mut child = Command::new(git_binary); let child = util::command::new_std_command(git_binary)
child
.current_dir(working_directory) .current_dir(working_directory)
.arg("blame") .arg("blame")
.arg("--incremental") .arg("--incremental")
@ -91,15 +89,7 @@ fn run_git_blame(
.arg(path.as_os_str()) .arg(path.as_os_str())
.stdin(Stdio::piped()) .stdin(Stdio::piped())
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()); .stderr(Stdio::piped())
#[cfg(windows)]
{
use std::os::windows::process::CommandExt;
child.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0);
}
let child = child
.spawn() .spawn()
.map_err(|e| anyhow!("Failed to start git blame process: {}", e))?; .map_err(|e| anyhow!("Failed to start git blame process: {}", e))?;

View file

@ -2,10 +2,6 @@ use crate::Oid;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use collections::HashMap; use collections::HashMap;
use std::path::Path; use std::path::Path;
use std::process::Command;
#[cfg(windows)]
use std::os::windows::process::CommandExt;
pub fn get_messages(working_directory: &Path, shas: &[Oid]) -> Result<HashMap<Oid, String>> { pub fn get_messages(working_directory: &Path, shas: &[Oid]) -> Result<HashMap<Oid, String>> {
if shas.is_empty() { if shas.is_empty() {
@ -14,19 +10,12 @@ pub fn get_messages(working_directory: &Path, shas: &[Oid]) -> Result<HashMap<Oi
const MARKER: &str = "<MARKER>"; const MARKER: &str = "<MARKER>";
let mut command = Command::new("git"); let output = util::command::new_std_command("git")
command
.current_dir(working_directory) .current_dir(working_directory)
.arg("show") .arg("show")
.arg("-s") .arg("-s")
.arg(format!("--format=%B{}", MARKER)) .arg(format!("--format=%B{}", MARKER))
.args(shas.iter().map(ToString::to_string)); .args(shas.iter().map(ToString::to_string))
#[cfg(windows)]
command.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0);
let output = command
.output() .output()
.map_err(|e| anyhow!("Failed to start git blame process: {}", e))?; .map_err(|e| anyhow!("Failed to start git blame process: {}", e))?;

View file

@ -2,7 +2,7 @@ use crate::repository::{GitFileStatus, RepoPath};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use std::{ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
process::{Command, Stdio}, process::Stdio,
sync::Arc, sync::Arc,
}; };
@ -17,9 +17,7 @@ impl GitStatus {
working_directory: &Path, working_directory: &Path,
path_prefixes: &[PathBuf], path_prefixes: &[PathBuf],
) -> Result<Self> { ) -> Result<Self> {
let mut child = Command::new(git_binary); let child = util::command::new_std_command(git_binary)
child
.current_dir(working_directory) .current_dir(working_directory)
.args([ .args([
"--no-optional-locks", "--no-optional-locks",
@ -37,15 +35,7 @@ impl GitStatus {
})) }))
.stdin(Stdio::null()) .stdin(Stdio::null())
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()); .stderr(Stdio::piped())
#[cfg(windows)]
{
use std::os::windows::process::CommandExt;
child.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0);
}
let child = child
.spawn() .spawn()
.map_err(|e| anyhow!("Failed to start git status process: {}", e))?; .map_err(|e| anyhow!("Failed to start git status process: {}", e))?;

View file

@ -292,7 +292,7 @@ impl Platform for WindowsPlatform {
pid, pid,
app_path.display(), app_path.display(),
); );
let restart_process = std::process::Command::new("powershell.exe") let restart_process = util::command::new_std_command("powershell.exe")
.arg("-command") .arg("-command")
.arg(script) .arg(script)
.spawn(); .spawn();

View file

@ -29,7 +29,7 @@ load-grammars = [
"tree-sitter-rust", "tree-sitter-rust",
"tree-sitter-typescript", "tree-sitter-typescript",
"tree-sitter-yaml", "tree-sitter-yaml",
"tree-sitter" "tree-sitter",
] ]
[dependencies] [dependencies]

View file

@ -85,7 +85,7 @@ impl super::LspAdapter for CLspAdapter {
} }
futures::io::copy(response.body_mut(), &mut file).await?; futures::io::copy(response.body_mut(), &mut file).await?;
let unzip_status = smol::process::Command::new("unzip") let unzip_status = util::command::new_smol_command("unzip")
.current_dir(&container_dir) .current_dir(&container_dir)
.arg(&zip_path) .arg(&zip_path)
.output() .output()

View file

@ -8,7 +8,7 @@ pub use language::*;
use lsp::{LanguageServerBinary, LanguageServerName}; use lsp::{LanguageServerBinary, LanguageServerName};
use regex::Regex; use regex::Regex;
use serde_json::json; use serde_json::json;
use smol::{fs, process}; use smol::fs;
use std::{ use std::{
any::Any, any::Any,
borrow::Cow, borrow::Cow,
@ -138,8 +138,8 @@ impl super::LspAdapter for GoLspAdapter {
let gobin_dir = container_dir.join("gobin"); let gobin_dir = container_dir.join("gobin");
fs::create_dir_all(&gobin_dir).await?; fs::create_dir_all(&gobin_dir).await?;
let go = delegate.which("go".as_ref()).await.unwrap_or("go".into());
let install_output = process::Command::new(go) let install_output = util::command::new_smol_command("go")
.env("GO111MODULE", "on") .env("GO111MODULE", "on")
.env("GOBIN", &gobin_dir) .env("GOBIN", &gobin_dir)
.args(["install", "golang.org/x/tools/gopls@latest"]) .args(["install", "golang.org/x/tools/gopls@latest"])
@ -157,7 +157,7 @@ impl super::LspAdapter for GoLspAdapter {
} }
let installed_binary_path = gobin_dir.join("gopls"); let installed_binary_path = gobin_dir.join("gopls");
let version_output = process::Command::new(&installed_binary_path) let version_output = util::command::new_smol_command(&installed_binary_path)
.arg("version") .arg("version")
.output() .output()
.await .await

View file

@ -19,7 +19,7 @@ use pet_core::python_environment::PythonEnvironmentKind;
use pet_core::Configuration; use pet_core::Configuration;
use project::lsp_store::language_server_settings; use project::lsp_store::language_server_settings;
use serde_json::{json, Value}; use serde_json::{json, Value};
use smol::{lock::OnceCell, process::Command}; use smol::lock::OnceCell;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::str::FromStr; use std::str::FromStr;
@ -698,7 +698,7 @@ impl PyLspAdapter {
let mut path = PathBuf::from(work_dir.as_ref()); let mut path = PathBuf::from(work_dir.as_ref());
path.push("pylsp-venv"); path.push("pylsp-venv");
if !path.exists() { if !path.exists() {
Command::new(python_path) util::command::new_smol_command(python_path)
.arg("-m") .arg("-m")
.arg("venv") .arg("venv")
.arg("pylsp-venv") .arg("pylsp-venv")
@ -779,7 +779,7 @@ impl LspAdapter for PyLspAdapter {
let venv = self.base_venv(delegate).await.map_err(|e| anyhow!(e))?; let venv = self.base_venv(delegate).await.map_err(|e| anyhow!(e))?;
let pip_path = venv.join("bin").join("pip3"); let pip_path = venv.join("bin").join("pip3");
ensure!( ensure!(
Command::new(pip_path.as_path()) util::command::new_smol_command(pip_path.as_path())
.arg("install") .arg("install")
.arg("python-lsp-server") .arg("python-lsp-server")
.output() .output()
@ -789,7 +789,7 @@ impl LspAdapter for PyLspAdapter {
"python-lsp-server installation failed" "python-lsp-server installation failed"
); );
ensure!( ensure!(
Command::new(pip_path.as_path()) util::command::new_smol_command(pip_path.as_path())
.arg("install") .arg("install")
.arg("python-lsp-server[all]") .arg("python-lsp-server[all]")
.output() .output()
@ -799,7 +799,7 @@ impl LspAdapter for PyLspAdapter {
"python-lsp-server[all] installation failed" "python-lsp-server[all] installation failed"
); );
ensure!( ensure!(
Command::new(pip_path) util::command::new_smol_command(pip_path)
.arg("install") .arg("install")
.arg("pylsp-mypy") .arg("pylsp-mypy")
.output() .output()

View file

@ -14,8 +14,7 @@ use std::{
any::Any, any::Any,
borrow::Cow, borrow::Cow,
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::Arc, sync::{Arc, LazyLock},
sync::LazyLock,
}; };
use task::{TaskTemplate, TaskTemplates, TaskVariables, VariableName}; use task::{TaskTemplate, TaskTemplates, TaskVariables, VariableName};
use util::{fs::remove_matching, maybe, ResultExt}; use util::{fs::remove_matching, maybe, ResultExt};
@ -639,7 +638,7 @@ fn package_name_and_bin_name_from_abs_path(
abs_path: &Path, abs_path: &Path,
project_env: Option<&HashMap<String, String>>, project_env: Option<&HashMap<String, String>>,
) -> Option<(String, String)> { ) -> Option<(String, String)> {
let mut command = std::process::Command::new("cargo"); let mut command = util::command::new_std_command("cargo");
if let Some(envs) = project_env { if let Some(envs) = project_env {
command.envs(envs); command.envs(envs);
} }
@ -685,11 +684,10 @@ fn human_readable_package_name(
package_directory: &Path, package_directory: &Path,
project_env: Option<&HashMap<String, String>>, project_env: Option<&HashMap<String, String>>,
) -> Option<String> { ) -> Option<String> {
let mut command = std::process::Command::new("cargo"); let mut command = util::command::new_std_command("cargo");
if let Some(envs) = project_env { if let Some(envs) = project_env {
command.envs(envs); command.envs(envs);
} }
let pkgid = String::from_utf8( let pkgid = String::from_utf8(
command command
.current_dir(package_directory) .current_dir(package_directory)

View file

@ -32,9 +32,6 @@ smol.workspace = true
util.workspace = true util.workspace = true
release_channel.workspace = true release_channel.workspace = true
[target.'cfg(windows)'.dependencies]
windows.workspace = true
[dev-dependencies] [dev-dependencies]
async-pipe.workspace = true async-pipe.workspace = true
ctor.workspace = true ctor.workspace = true

View file

@ -19,12 +19,9 @@ use serde_json::{json, value::RawValue, Value};
use smol::{ use smol::{
channel, channel,
io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, io::{AsyncBufReadExt, AsyncWriteExt, BufReader},
process::{self, Child}, process::Child,
}; };
#[cfg(target_os = "windows")]
use smol::process::windows::CommandExt;
use std::{ use std::{
ffi::{OsStr, OsString}, ffi::{OsStr, OsString},
fmt, fmt,
@ -346,23 +343,21 @@ impl LanguageServer {
&binary.arguments &binary.arguments
); );
let mut command = process::Command::new(&binary.path); let mut server = util::command::new_smol_command(&binary.path)
command
.current_dir(working_dir) .current_dir(working_dir)
.args(&binary.arguments) .args(&binary.arguments)
.envs(binary.env.unwrap_or_default()) .envs(binary.env.unwrap_or_default())
.stdin(Stdio::piped()) .stdin(Stdio::piped())
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()) .stderr(Stdio::piped())
.kill_on_drop(true); .kill_on_drop(true)
#[cfg(windows)] .spawn()
command.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0); .with_context(|| {
let mut server = command.spawn().with_context(|| { format!(
format!( "failed to spawn command. path: {:?}, working directory: {:?}, args: {:?}",
"failed to spawn command. path: {:?}, working directory: {:?}, args: {:?}", binary.path, working_dir, &binary.arguments
binary.path, working_dir, &binary.arguments )
) })?;
})?;
let stdin = server.stdin.take().unwrap(); let stdin = server.stdin.take().unwrap();
let stdout = server.stdout.take().unwrap(); let stdout = server.stdout.take().unwrap();

View file

@ -37,7 +37,6 @@ which.workspace = true
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
async-std = { version = "1.12.0", features = ["unstable"] } async-std = { version = "1.12.0", features = ["unstable"] }
windows.workspace = true
[dev-dependencies] [dev-dependencies]
tempfile.workspace = true tempfile.workspace = true

View file

@ -9,7 +9,7 @@ use http_client::{HttpClient, Uri};
use semver::Version; use semver::Version;
use serde::Deserialize; use serde::Deserialize;
use smol::io::BufReader; use smol::io::BufReader;
use smol::{fs, lock::Mutex, process::Command}; use smol::{fs, lock::Mutex};
use std::ffi::OsString; use std::ffi::OsString;
use std::io; use std::io;
use std::process::{Output, Stdio}; use std::process::{Output, Stdio};
@ -20,9 +20,6 @@ use std::{
}; };
use util::ResultExt; use util::ResultExt;
#[cfg(windows)]
use smol::process::windows::CommandExt;
#[derive(Clone, Debug, Default, Eq, PartialEq)] #[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct NodeBinaryOptions { pub struct NodeBinaryOptions {
pub allow_path_lookup: bool, pub allow_path_lookup: bool,
@ -315,9 +312,7 @@ impl ManagedNodeRuntime {
let node_binary = node_dir.join(Self::NODE_PATH); let node_binary = node_dir.join(Self::NODE_PATH);
let npm_file = node_dir.join(Self::NPM_PATH); let npm_file = node_dir.join(Self::NPM_PATH);
let mut command = Command::new(&node_binary); let result = util::command::new_smol_command(&node_binary)
command
.env_clear() .env_clear()
.arg(npm_file) .arg(npm_file)
.arg("--version") .arg("--version")
@ -326,12 +321,9 @@ impl ManagedNodeRuntime {
.stderr(Stdio::null()) .stderr(Stdio::null())
.args(["--cache".into(), node_dir.join("cache")]) .args(["--cache".into(), node_dir.join("cache")])
.args(["--userconfig".into(), node_dir.join("blank_user_npmrc")]) .args(["--userconfig".into(), node_dir.join("blank_user_npmrc")])
.args(["--globalconfig".into(), node_dir.join("blank_global_npmrc")]); .args(["--globalconfig".into(), node_dir.join("blank_global_npmrc")])
.status()
#[cfg(windows)] .await;
command.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0);
let result = command.status().await;
let valid = matches!(result, Ok(status) if status.success()); let valid = matches!(result, Ok(status) if status.success());
if !valid { if !valid {
@ -412,7 +404,7 @@ impl NodeRuntimeTrait for ManagedNodeRuntime {
return Err(anyhow!("missing npm file")); return Err(anyhow!("missing npm file"));
} }
let mut command = Command::new(node_binary); let mut command = util::command::new_smol_command(node_binary);
command.env_clear(); command.env_clear();
command.env("PATH", env_path); command.env("PATH", env_path);
command.arg(npm_file).arg(subcommand); command.arg(npm_file).arg(subcommand);
@ -473,7 +465,7 @@ pub struct SystemNodeRuntime {
impl SystemNodeRuntime { impl SystemNodeRuntime {
const MIN_VERSION: semver::Version = Version::new(18, 0, 0); const MIN_VERSION: semver::Version = Version::new(18, 0, 0);
async fn new(node: PathBuf, npm: PathBuf) -> Result<Box<dyn NodeRuntimeTrait>> { async fn new(node: PathBuf, npm: PathBuf) -> Result<Box<dyn NodeRuntimeTrait>> {
let output = Command::new(&node) let output = util::command::new_smol_command(&node)
.arg("--version") .arg("--version")
.output() .output()
.await .await
@ -543,7 +535,7 @@ impl NodeRuntimeTrait for SystemNodeRuntime {
subcommand: &str, subcommand: &str,
args: &[&str], args: &[&str],
) -> anyhow::Result<Output> { ) -> anyhow::Result<Output> {
let mut command = Command::new(self.npm.clone()); let mut command = util::command::new_smol_command(self.npm.clone());
command command
.env_clear() .env_clear()
.env("PATH", std::env::var_os("PATH").unwrap_or_default()) .env("PATH", std::env::var_os("PATH").unwrap_or_default())
@ -639,7 +631,11 @@ impl NodeRuntimeTrait for UnavailableNodeRuntime {
} }
} }
fn configure_npm_command(command: &mut Command, directory: Option<&Path>, proxy: Option<&Uri>) { fn configure_npm_command(
command: &mut smol::process::Command,
directory: Option<&Path>,
proxy: Option<&Uri>,
) {
if let Some(directory) = directory { if let Some(directory) = directory {
command.current_dir(directory); command.current_dir(directory);
command.args(["--prefix".into(), directory.to_path_buf()]); command.args(["--prefix".into(), directory.to_path_buf()]);
@ -674,6 +670,5 @@ fn configure_npm_command(command: &mut Command, directory: Option<&Path>, proxy:
{ {
command.env("ComSpec", val); command.env("ComSpec", val);
} }
command.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0);
} }
} }

View file

@ -73,9 +73,6 @@ url.workspace = true
which.workspace = true which.workspace = true
fancy-regex.workspace = true fancy-regex.workspace = true
[target.'cfg(target_os = "windows")'.dependencies]
windows.workspace = true
[dev-dependencies] [dev-dependencies]
client = { workspace = true, features = ["test-support"] } client = { workspace = true, features = ["test-support"] }
collections = { workspace = true, features = ["test-support"] } collections = { workspace = true, features = ["test-support"] }

View file

@ -611,12 +611,7 @@ impl LocalLspStore {
Some(worktree_path) Some(worktree_path)
})?; })?;
let mut child = smol::process::Command::new(command); let mut child = util::command::new_smol_command(command);
#[cfg(target_os = "windows")]
{
use smol::process::windows::CommandExt;
child.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0);
}
if let Some(buffer_env) = buffer.env.as_ref() { if let Some(buffer_env) = buffer.env.as_ref() {
child.envs(buffer_env); child.envs(buffer_env);
@ -7935,7 +7930,7 @@ impl LspAdapterDelegate for LocalLspAdapterDelegate {
}; };
let env = self.shell_env().await; let env = self.shell_env().await;
let output = smol::process::Command::new(&npm) let output = util::command::new_smol_command(&npm)
.args(["root", "-g"]) .args(["root", "-g"])
.envs(env) .envs(env)
.current_dir(local_package_directory) .current_dir(local_package_directory)
@ -7969,7 +7964,7 @@ impl LspAdapterDelegate for LocalLspAdapterDelegate {
async fn try_exec(&self, command: LanguageServerBinary) -> Result<()> { async fn try_exec(&self, command: LanguageServerBinary) -> Result<()> {
let working_dir = self.worktree_root_path(); let working_dir = self.worktree_root_path();
let output = smol::process::Command::new(&command.path) let output = util::command::new_smol_command(&command.path)
.args(command.arguments) .args(command.arguments)
.envs(command.env.clone().unwrap_or_default()) .envs(command.env.clone().unwrap_or_default())
.current_dir(working_dir) .current_dir(working_dir)

View file

@ -255,7 +255,7 @@ impl SshSocket {
// and passes -l as an argument to sh, not to ls. // and passes -l as an argument to sh, not to ls.
// You need to do it like this: $ ssh host "sh -c 'ls -l /tmp'" // You need to do it like this: $ ssh host "sh -c 'ls -l /tmp'"
fn ssh_command(&self, program: &str, args: &[&str]) -> process::Command { fn ssh_command(&self, program: &str, args: &[&str]) -> process::Command {
let mut command = process::Command::new("ssh"); let mut command = util::command::new_smol_command("ssh");
let to_run = iter::once(&program) let to_run = iter::once(&program)
.chain(args.iter()) .chain(args.iter())
.map(|token| { .map(|token| {
@ -1224,7 +1224,7 @@ trait RemoteConnection: Send + Sync {
struct SshRemoteConnection { struct SshRemoteConnection {
socket: SshSocket, socket: SshSocket,
master_process: Mutex<Option<process::Child>>, master_process: Mutex<Option<Child>>,
remote_binary_path: Option<PathBuf>, remote_binary_path: Option<PathBuf>,
_temp_dir: TempDir, _temp_dir: TempDir,
} }
@ -1258,7 +1258,7 @@ impl RemoteConnection for SshRemoteConnection {
dest_path: PathBuf, dest_path: PathBuf,
cx: &AppContext, cx: &AppContext,
) -> Task<Result<()>> { ) -> Task<Result<()>> {
let mut command = process::Command::new("scp"); let mut command = util::command::new_smol_command("scp");
let output = self let output = self
.socket .socket
.ssh_options(&mut command) .ssh_options(&mut command)
@ -1910,7 +1910,7 @@ impl SshRemoteConnection {
async fn upload_file(&self, src_path: &Path, dest_path: &Path) -> Result<()> { async fn upload_file(&self, src_path: &Path, dest_path: &Path) -> Result<()> {
log::debug!("uploading file {:?} to {:?}", src_path, dest_path); log::debug!("uploading file {:?} to {:?}", src_path, dest_path);
let mut command = process::Command::new("scp"); let mut command = util::command::new_smol_command("scp");
let output = self let output = self
.socket .socket
.ssh_options(&mut command) .ssh_options(&mut command)

View file

@ -49,9 +49,6 @@ uuid.workspace = true
workspace.workspace = true workspace.workspace = true
picker.workspace = true picker.workspace = true
[target.'cfg(target_os = "windows")'.dependencies]
windows.workspace = true
[dev-dependencies] [dev-dependencies]
editor = { workspace = true, features = ["test-support"] } editor = { workspace = true, features = ["test-support"] }
env_logger.workspace = true env_logger.workspace = true

View file

@ -16,7 +16,6 @@ pub use remote_kernels::*;
use anyhow::Result; use anyhow::Result;
use runtimelib::{ExecutionState, JupyterKernelspec, JupyterMessage, KernelInfoReply}; use runtimelib::{ExecutionState, JupyterKernelspec, JupyterMessage, KernelInfoReply};
use smol::process::Command;
use ui::SharedString; use ui::SharedString;
pub type JupyterMessageChannel = stream::SelectAll<Receiver<JupyterMessage>>; pub type JupyterMessageChannel = stream::SelectAll<Receiver<JupyterMessage>>;
@ -85,7 +84,7 @@ pub fn python_env_kernel_specifications(
let python_path = toolchain.path.to_string(); let python_path = toolchain.path.to_string();
// Check if ipykernel is installed // Check if ipykernel is installed
let ipykernel_check = Command::new(&python_path) let ipykernel_check = util::command::new_smol_command(&python_path)
.args(&["-c", "import ipykernel"]) .args(&["-c", "import ipykernel"])
.output() .output()
.await; .await;

View file

@ -48,7 +48,7 @@ impl LocalKernelSpecification {
self.name self.name
); );
let mut cmd = Command::new(&argv[0]); let mut cmd = util::command::new_smol_command(&argv[0]);
for arg in &argv[1..] { for arg in &argv[1..] {
if arg == "{connection_file}" { if arg == "{connection_file}" {
@ -62,12 +62,6 @@ impl LocalKernelSpecification {
cmd.envs(env); cmd.envs(env);
} }
#[cfg(windows)]
{
use smol::process::windows::CommandExt;
cmd.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0);
}
Ok(cmd) Ok(cmd)
} }
} }
@ -350,17 +344,11 @@ pub async fn local_kernel_specifications(fs: Arc<dyn Fs>) -> Result<Vec<LocalKer
} }
// Search for kernels inside the base python environment // Search for kernels inside the base python environment
let mut command = Command::new("python"); let command = util::command::new_smol_command("python")
command.arg("-c"); .arg("-c")
command.arg("import sys; print(sys.prefix)"); .arg("import sys; print(sys.prefix)")
.output()
#[cfg(windows)] .await;
{
use smol::process::windows::CommandExt;
command.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0);
}
let command = command.output().await;
if let Ok(command) = command { if let Ok(command) = command {
if command.status.success() { if command.status.success() {

View file

@ -32,9 +32,6 @@ ui.workspace = true
unicode-segmentation.workspace = true unicode-segmentation.workspace = true
util.workspace = true util.workspace = true
[target.'cfg(target_os = "windows")'.dependencies]
windows.workspace = true
[dev-dependencies] [dev-dependencies]
editor = { workspace = true, features = ["test-support"] } editor = { workspace = true, features = ["test-support"] }
env_logger.workspace = true env_logger.workspace = true

View file

@ -21,7 +21,7 @@ use serde::{Deserialize, Serialize};
use settings::SettingsStore; use settings::SettingsStore;
use smol::{ use smol::{
io::AsyncWriteExt, io::AsyncWriteExt,
process::{Child, ChildStdin, ChildStdout, Command}, process::{Child, ChildStdin, ChildStdout},
}; };
use std::{path::PathBuf, process::Stdio, sync::Arc}; use std::{path::PathBuf, process::Stdio, sync::Arc};
use ui::prelude::*; use ui::prelude::*;
@ -269,21 +269,14 @@ impl SupermavenAgent {
client: Arc<Client>, client: Arc<Client>,
cx: &mut ModelContext<Supermaven>, cx: &mut ModelContext<Supermaven>,
) -> Result<Self> { ) -> Result<Self> {
let mut process = Command::new(&binary_path); let mut process = util::command::new_smol_command(&binary_path)
process
.arg("stdio") .arg("stdio")
.stdin(Stdio::piped()) .stdin(Stdio::piped())
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()) .stderr(Stdio::piped())
.kill_on_drop(true); .kill_on_drop(true)
.spawn()
#[cfg(target_os = "windows")] .context("failed to start the binary")?;
{
use smol::process::windows::CommandExt;
process.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0);
}
let mut process = process.spawn().context("failed to start the binary")?;
let stdin = process let stdin = process
.stdin .stdin

View file

@ -30,6 +30,7 @@ regex.workspace = true
rust-embed.workspace = true rust-embed.workspace = true
serde.workspace = true serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
smol.workspace = true
take-until = "0.2.0" take-until = "0.2.0"
tempfile = { workspace = true, optional = true } tempfile = { workspace = true, optional = true }
unicase.workspace = true unicase.workspace = true

View file

@ -0,0 +1,32 @@
use std::ffi::OsStr;
#[cfg(target_os = "windows")]
const CREATE_NO_WINDOW: u32 = 0x0800_0000_u32;
#[cfg(target_os = "windows")]
pub fn new_std_command(program: impl AsRef<OsStr>) -> std::process::Command {
use std::os::windows::process::CommandExt;
let mut command = std::process::Command::new(program);
command.creation_flags(CREATE_NO_WINDOW);
command
}
#[cfg(not(target_os = "windows"))]
pub fn new_std_command(program: impl AsRef<OsStr>) -> std::process::Command {
std::process::Command::new(program)
}
#[cfg(target_os = "windows")]
pub fn new_smol_command(program: impl AsRef<OsStr>) -> smol::process::Command {
use smol::process::windows::CommandExt;
let mut command = smol::process::Command::new(program);
command.creation_flags(CREATE_NO_WINDOW);
command
}
#[cfg(not(target_os = "windows"))]
pub fn new_smol_command(program: impl AsRef<OsStr>) -> smol::process::Command {
smol::process::Command::new(program)
}

View file

@ -1,4 +1,5 @@
pub mod arc_cow; pub mod arc_cow;
pub mod command;
pub mod fs; pub mod fs;
pub mod paths; pub mod paths;
pub mod serde; pub mod serde;