Mountain/IPC/WindServiceHandlers/Git/Shared/
RunGit.rs1use std::time::Duration;
5
6use tokio::process::Command;
7
8use crate::dev_log;
9
10const GIT_EXEC_TIMEOUT:Duration = Duration::from_secs(30);
18
19pub async fn Fn(OperationId:&str, Args:&[String], Cwd:Option<&str>) -> Result<(i32, String, String), String> {
20 dev_log!(
21 "git",
22 "[Git] exec-begin op={} cwd={} Arguments=[{}]",
23 OperationId,
24 Cwd.unwrap_or("<inherit>"),
25 Args.join(" ")
26 );
27
28 let WorkingDir = Cwd
29 .map(super::ResolveCwd::Fn)
30 .unwrap_or_else(|| std::env::current_dir().unwrap_or_default());
31
32 let mut Spawn = Command::new("git");
33
34 Spawn.args(Args).current_dir(&WorkingDir).kill_on_drop(true);
35
36 let Child = Spawn.spawn().map_err(|Error| {
37 dev_log!(
38 "git",
39 "[Git] exec-spawn-fail op={} Arguments=[{}] error={}",
40 OperationId,
41 Args.join(" "),
42 Error
43 );
44 format!("git spawn failed: {}", Error)
45 })?;
46
47 if let Some(Pid) = Child.id() {
48 super::RegisterPid::Fn(OperationId, Pid);
49 }
50
51 let WaitFuture = Child.wait_with_output();
52
53 let Output = match tokio::time::timeout(GIT_EXEC_TIMEOUT, WaitFuture).await {
54 Ok(WaitResult) => {
55 WaitResult.map_err(|Error| {
56 super::ClearPid::Fn(OperationId);
57 format!("git wait failed: {}", Error)
58 })?
59 },
60 Err(_) => {
61 let _ = super::TakePid::Fn(OperationId);
66
67 dev_log!(
68 "git",
69 "warn: [Git] exec-timeout op={} Arguments=[{}] after {}s - subprocess killed",
70 OperationId,
71 Args.join(" "),
72 GIT_EXEC_TIMEOUT.as_secs()
73 );
74
75 return Err(format!(
76 "git exec timed out after {}s: git {}",
77 GIT_EXEC_TIMEOUT.as_secs(),
78 Args.join(" ")
79 ));
80 },
81 };
82
83 super::ClearPid::Fn(OperationId);
84
85 let ExitCode = Output.status.code().unwrap_or(-1);
86
87 let Stdout = String::from_utf8_lossy(&Output.stdout).into_owned();
88
89 let Stderr = String::from_utf8_lossy(&Output.stderr).into_owned();
90
91 dev_log!(
92 "git",
93 "[Git] exec-done op={} Arguments=[{}] exit={} stdout={}B stderr={}B",
94 OperationId,
95 Args.join(" "),
96 ExitCode,
97 Stdout.len(),
98 Stderr.len()
99 );
100
101 Ok((ExitCode, Stdout, Stderr))
102}