Skip to content

Commit 134a20c

Browse files
userwsp1911
authored andcommitted
fix(process): hide console windows for spawned git/cmd subprocesses
Route git/cmd/editor/bitfun.exe subprocess spawns through the upstream native process_manager helper (create_command / create_tokio_command), which applies CREATE_NO_WINDOW on Windows, preventing the flash of a console window that previously accompanied spawned git/cmd subprocesses from the CLI dispatch runner, desktop dispatch host, and workspace auto-index. Reuses bitfun_services_core::process_manager and the bitfun_core::util::process_manager re-export (TUI boundary compliant); zero new dependencies, zero Cargo.toml changes. Test: cargo check --jobs 4 -p bitfun-services-integrations --features workspace-search --all-targets && cargo check --jobs 4 -p bitfun-cli --all-targets && cargo check --jobs 4 -p bitfun-desktop --all-targets (expected green) AI: lightly tested
1 parent b993edb commit 134a20c

6 files changed

Lines changed: 15 additions & 13 deletions

File tree

src/apps/cli/src/dispatch/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ mod worker;
66
mod workspace;
77

88
use std::path::{Path, PathBuf};
9-
use std::process::Command;
109

1110
use anyhow::{anyhow, bail, Context, Result};
1211
use bitfun_core::infrastructure::ai::AIClientFactory;
1312
use bitfun_core::service::config::{AuthConfig, GlobalConfig};
1413
use bitfun_core::service::git::trust;
14+
use bitfun_services_core::process_manager;
1515
use serde::de::DeserializeOwned;
1616

1717
use protocol::{
@@ -853,7 +853,7 @@ fn classify_repository_probe(result: Result<GitProbeOutput, GitProbeOutput>) ->
853853
/// below matches Git's English prose, and a localized host would otherwise make
854854
/// an ownership rejection unrecognizable.
855855
fn git_probe(workspace: &Path, args: &[&str]) -> Result<GitProbeOutput, GitProbeOutput> {
856-
let output = Command::new("git")
856+
let output = process_manager::create_command("git")
857857
.env("LC_ALL", "C")
858858
.arg("-C")
859859
.arg(workspace)

src/apps/cli/src/dispatch/workspace.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use std::time::{Duration, Instant};
2020
use anyhow::{bail, Context, Result};
2121
use base64::Engine as _;
2222
use bitfun_services_core::dispatch_workspace::sha256_file;
23+
use bitfun_services_core::process_manager;
2324
use serde::{Deserialize, Serialize};
2425
use sha2::{Digest, Sha256};
2526

@@ -1573,7 +1574,7 @@ fn commit_exists(repo: &Path, commit: &str) -> Result<bool> {
15731574
}
15741575

15751576
fn git_command(dir: &Path) -> Command {
1576-
let mut command = Command::new("git");
1577+
let mut command = process_manager::create_command("git");
15771578
command
15781579
.current_dir(dir)
15791580
// A detached dispatch worker has nobody to answer a credential or

src/apps/cli/src/modes/chat/external_editor.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ fn editor_process(
208208
command: &EditorCommand,
209209
path: &std::path::Path,
210210
) -> Result<Command, EditorRunError> {
211-
let mut process = Command::new(&command.program);
211+
let mut process = bitfun_core::util::process_manager::create_command(&command.program);
212212
process.args(&command.args).arg(path);
213213
Ok(process)
214214
}
@@ -235,15 +235,15 @@ fn editor_process(
235235
}
236236
values.push(quote_windows_batch_value(path.as_os_str())?);
237237
let command_line = values.join(" ");
238-
let mut process = Command::new("cmd.exe");
238+
let mut process = bitfun_core::util::process_manager::create_command("cmd.exe");
239239
process.args(["/d", "/v:off", "/s", "/c"]);
240240
// cmd.exe requires an extra outer quote pair when the command itself
241241
// begins with a quoted executable path. raw_arg is intentional here:
242242
// Rust's argv quoting does not escape cmd metacharacters.
243243
process.raw_arg(format!("\"{command_line}\""));
244244
Ok(process)
245245
} else {
246-
let mut process = Command::new(&command.program);
246+
let mut process = bitfun_core::util::process_manager::create_command(&command.program);
247247
process.args(&command.args).arg(path);
248248
Ok(process)
249249
}

src/apps/cli/src/modes/exec/verification.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,11 @@ pub(super) async fn run_verifier(
6363
retries_used: u32,
6464
) -> VerifyOutcome {
6565
let mut process = if cfg!(windows) {
66-
let mut process = tokio::process::Command::new("cmd");
66+
let mut process = bitfun_services_core::process_manager::create_tokio_command("cmd");
6767
process.arg("/C").arg(command);
6868
process
6969
} else {
70-
let mut process = tokio::process::Command::new("sh");
70+
let mut process = bitfun_services_core::process_manager::create_tokio_command("sh");
7171
process.arg("-c").arg(command);
7272
process
7373
};

src/apps/desktop/src/api/dispatch_host.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use std::time::Duration;
1010
use anyhow::{anyhow, Context};
1111
use serde_json::Value;
1212
use tokio::io::AsyncWriteExt;
13-
use tokio::process::Command;
1413

1514
const TARGET_COMMAND_TIMEOUT: Duration = Duration::from_secs(110);
1615
const MAX_TARGET_RESPONSE_BYTES: usize = 4 * 1024 * 1024;
@@ -53,7 +52,7 @@ fn target_cli_verb(command: &str) -> Option<&'static str> {
5352

5453
async fn invoke_cli(executable: &Path, verb: &str, args: Value) -> anyhow::Result<Value> {
5554
let request = serde_json::to_vec(&args).context("serialize target dispatch request")?;
56-
let mut child = Command::new(executable)
55+
let mut child = bitfun_core::util::process_manager::create_tokio_command(executable)
5756
.arg("dispatch")
5857
.arg(verb)
5958
.stdin(std::process::Stdio::piped())

src/crates/services/services-integrations/src/workspace_search/auto_index.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use std::path::{Path, PathBuf};
2+
#[cfg(test)]
23
use std::process::Command;
34

5+
use bitfun_services_core::process_manager;
46
use tokio::task::spawn_blocking;
57

68
pub(crate) const DEFAULT_AUTO_INDEX_MIN_FILES: usize = 2_000;
@@ -99,7 +101,7 @@ fn git_ls_files_indexable_count(
99101
policy: AutoIndexPolicy,
100102
carried: usize,
101103
) -> Result<usize, String> {
102-
let output = Command::new("git")
104+
let output = process_manager::create_command("git")
103105
.arg("ls-files")
104106
.args(selectors)
105107
.arg("-z")
@@ -128,7 +130,7 @@ fn git_ls_files_indexable_count(
128130
}
129131

130132
fn git_worktree_root(repo_root: &Path) -> Result<PathBuf, String> {
131-
let output = Command::new("git")
133+
let output = process_manager::create_command("git")
132134
.args(["rev-parse", "--show-toplevel"])
133135
.current_dir(repo_root)
134136
.output()
@@ -146,7 +148,7 @@ fn git_worktree_root(repo_root: &Path) -> Result<PathBuf, String> {
146148
}
147149
let worktree_root = dunce::canonicalize(root)
148150
.map_err(|error| format!("cannot canonicalize Git worktree root: {error}"))?;
149-
let head = Command::new("git")
151+
let head = process_manager::create_command("git")
150152
.args(["rev-parse", "--verify", "HEAD^{commit}"])
151153
.current_dir(&worktree_root)
152154
.output()

0 commit comments

Comments
 (0)