diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-16 21:23:53 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-16 21:23:53 +0300 |
| commit | 616d1dd8125ece4a9102b231864cb4fc4b761497 (patch) | |
| tree | 24647750130d05dcf4a0a262a1976b6bdd0fcee8 /src | |
| parent | 76a4e3ccb0958ff54badfa65ba4d224d6b0c29a1 (diff) | |
fix(windows): suppress noninteractive process windows
refs #1468
Diffstat (limited to 'src')
| -rw-r--r-- | src/detect/manifest_update.rs | 6 | ||||
| -rw-r--r-- | src/main.rs | 1 | ||||
| -rw-r--r-- | src/noninteractive_process.rs | 12 | ||||
| -rw-r--r-- | src/plugin_command.rs | 27 | ||||
| -rw-r--r-- | src/remote/unix.rs | 4 | ||||
| -rw-r--r-- | src/update.rs | 6 | ||||
| -rw-r--r-- | src/workspace/git/discovery.rs | 2 | ||||
| -rw-r--r-- | src/workspace/git/status.rs | 2 |
8 files changed, 46 insertions, 14 deletions
diff --git a/src/detect/manifest_update.rs b/src/detect/manifest_update.rs index 02efa3bc..8c5fc339 100644 --- a/src/detect/manifest_update.rs +++ b/src/detect/manifest_update.rs @@ -4,7 +4,7 @@ use std::{ fmt, fs, io::{Read, Write}, path::{Path, PathBuf}, - process::{Command, Stdio}, + process::Stdio, time::{SystemTime, UNIX_EPOCH}, }; @@ -470,9 +470,7 @@ fn catalog_url() -> String { fn fetch_text(url: &str) -> Result<String, String> { let max_fetch_bytes = MAX_FETCH_BYTES.to_string(); - let mut command = Command::new("curl"); - crate::platform::configure_background_command(&mut command); - let mut child = command + let mut child = crate::noninteractive_process::curl_command() .args([ "-sfL", "--retry", diff --git a/src/main.rs b/src/main.rs index c48951c6..d7746f57 100644 --- a/src/main.rs +++ b/src/main.rs @@ -74,6 +74,7 @@ mod kitty_graphics; mod layout; mod logging; mod metadata_tokens; +mod noninteractive_process; mod pane; mod persist; mod platform; diff --git a/src/noninteractive_process.rs b/src/noninteractive_process.rs new file mode 100644 index 00000000..98198dce --- /dev/null +++ b/src/noninteractive_process.rs @@ -0,0 +1,12 @@ +use std::{ffi::OsStr, process::Command}; + +/// Builds a subprocess whose stdio is controlled by the caller and which never opens a Windows console. +pub(crate) fn command(program: impl AsRef<OsStr>) -> Command { + let mut command = Command::new(program); + crate::platform::configure_background_command(&mut command); + command +} + +pub(crate) fn curl_command() -> Command { + command("curl") +} diff --git a/src/plugin_command.rs b/src/plugin_command.rs index ba0a1422..a0f71894 100644 --- a/src/plugin_command.rs +++ b/src/plugin_command.rs @@ -12,7 +12,7 @@ pub(crate) fn command_for_argv(program: &str, args: &[String]) -> Command { #[cfg(not(windows))] fn command_for_program(program: &str) -> Command { - Command::new(program) + crate::noninteractive_process::command(program) } #[cfg(windows)] @@ -29,11 +29,11 @@ fn command_for_program(program: &str) -> Command { { let shell = std::env::var_os("ComSpec").unwrap_or_else(|| r"C:\Windows\System32\cmd.exe".into()); - let mut command = Command::new(shell); + let mut command = crate::noninteractive_process::command(shell); command.arg("/d").arg("/c").arg(command_program); command } else { - Command::new(command_program) + crate::noninteractive_process::command(command_program) } } @@ -126,4 +126,25 @@ mod tests { assert!(!is_windows_batch_file_name("node.exe")); assert!(!is_windows_batch_file_name("node")); } + + #[cfg(windows)] + #[test] + fn windows_batch_command_captures_output() { + let path = std::env::temp_dir().join(format!( + "herdr-plugin-command-output-{}.cmd", + std::process::id() + )); + std::fs::write(&path, "@echo off\r\necho plugin-%1\r\n").expect("write batch fixture"); + + let output = command_for_argv(&path.display().to_string(), &["ready".to_string()]) + .output() + .expect("run batch fixture"); + let _ = std::fs::remove_file(&path); + + assert!(output.status.success(), "{output:?}"); + assert_eq!( + String::from_utf8_lossy(&output.stdout).trim(), + "plugin-ready" + ); + } } diff --git a/src/remote/unix.rs b/src/remote/unix.rs index 7544585f..40e8bb45 100644 --- a/src/remote/unix.rs +++ b/src/remote/unix.rs @@ -1449,7 +1449,7 @@ fn download_release_asset(platform: &RemotePlatform) -> io::Result<InstallSource let dir = private_download_dir(&asset_key)?; let path = dir.join("herdr.tmp"); - let status = Command::new("curl") + let status = crate::noninteractive_process::curl_command() .args(["-sfL", "--max-time", "120", "-o"]) .arg(&path) .arg(&asset.url) @@ -1473,7 +1473,7 @@ fn download_release_asset(platform: &RemotePlatform) -> io::Result<InstallSource } fn fetch_remote_manifest(url: &str) -> io::Result<Vec<u8>> { - let output = Command::new("curl") + let output = crate::noninteractive_process::curl_command() .args([ "-sfL", "--retry", diff --git a/src/update.rs b/src/update.rs index 8ef77840..eac917bf 100644 --- a/src/update.rs +++ b/src/update.rs @@ -294,7 +294,7 @@ fn fetch_json_manifest<T>(url: &str) -> Result<T, String> where T: serde::de::DeserializeOwned, { - let output = Command::new("curl") + let output = crate::noninteractive_process::curl_command() .args([ "-sfL", "--retry", @@ -508,7 +508,7 @@ fn homebrew_update_from_formula_json( fn check_homebrew_latest() -> Result<Option<Version>, String> { let current = Version::current(); - let output = Command::new("curl") + let output = crate::noninteractive_process::curl_command() .args([ "-sfL", "--retry", @@ -571,7 +571,7 @@ fn download_update(release: &ReleaseInfo) -> Result<DownloadedUpdate, String> { let tmp_path = parent.join(format!(".herdr-update-{}.tmp", std::process::id())); // Download the exact asset URL (pinned to the release we checked) - let status = Command::new("curl") + let status = crate::noninteractive_process::curl_command() .args(["-sfL", "--max-time", "120", "-o"]) .arg(&tmp_path) .arg(&release.download_url) diff --git a/src/workspace/git/discovery.rs b/src/workspace/git/discovery.rs index 9aa351b2..4edfcbc2 100644 --- a/src/workspace/git/discovery.rs +++ b/src/workspace/git/discovery.rs @@ -216,7 +216,7 @@ fn strip_git_config_comment(value: &str) -> &str { } fn git_trimmed_stdout(repo_root: &Path, args: &[&str]) -> Option<String> { - let output = std::process::Command::new("git") + let output = crate::noninteractive_process::command("git") .arg("-C") .arg(repo_root) .args(args) diff --git a/src/workspace/git/status.rs b/src/workspace/git/status.rs index 024ffdde..d9c3123a 100644 --- a/src/workspace/git/status.rs +++ b/src/workspace/git/status.rs @@ -218,7 +218,7 @@ fn git_ahead_behind_between( upstream_oid: &str, ) -> Option<(usize, usize)> { let range = format!("{head_oid}...{upstream_oid}"); - let output = std::process::Command::new("git") + let output = crate::noninteractive_process::command("git") .arg("-C") .arg(cwd) .args(["rev-list", "--left-right", "--count", &range]) |
