Mountain/IPC/WindServiceHandlers/Git/
Shared.rs1#![allow(non_snake_case, dead_code)]
2
3use std::{
14 collections::HashMap,
15 path::PathBuf,
16 sync::{Mutex, OnceLock},
17};
18
19use serde_json::Value;
20use tokio::process::Command;
21
22use crate::dev_log;
23
24pub fn RunningProcesses() -> &'static Mutex<HashMap<String, u32>> {
25 static SLOT:OnceLock<Mutex<HashMap<String, u32>>> = OnceLock::new();
26 SLOT.get_or_init(|| Mutex::new(HashMap::new()))
27}
28
29pub fn RegisterPid(OperationId:&str, Pid:u32) {
30 if OperationId.is_empty() {
31 return;
32 }
33 if let Ok(mut Map) = RunningProcesses().lock() {
34 Map.insert(OperationId.to_string(), Pid);
35 }
36}
37
38pub fn ClearPid(OperationId:&str) {
39 if OperationId.is_empty() {
40 return;
41 }
42 if let Ok(mut Map) = RunningProcesses().lock() {
43 Map.remove(OperationId);
44 }
45}
46
47pub fn TakePid(OperationId:&str) -> Option<u32> {
48 if OperationId.is_empty() {
49 return None;
50 }
51 RunningProcesses().lock().ok().and_then(|mut M| M.remove(OperationId))
52}
53
54pub fn ResolveCwd(Raw:&str) -> PathBuf {
55 if Raw.is_empty() {
56 std::env::current_dir().unwrap_or_default()
57 } else {
58 PathBuf::from(Raw)
59 }
60}
61
62pub async fn RunGit(OperationId:&str, Args:&[String], Cwd:Option<&str>) -> Result<(i32, String, String), String> {
63 dev_log!(
64 "git",
65 "[Git] exec-begin op={} cwd={} Arguments=[{}]",
66 OperationId,
67 Cwd.unwrap_or("<inherit>"),
68 Args.join(" ")
69 );
70
71 let WorkingDir = Cwd
72 .map(ResolveCwd)
73 .unwrap_or_else(|| std::env::current_dir().unwrap_or_default());
74
75 let mut Spawn = Command::new("git");
76 Spawn.args(Args).current_dir(&WorkingDir).kill_on_drop(true);
77
78 let Child = Spawn.spawn().map_err(|Error| {
79 dev_log!(
80 "git",
81 "[Git] exec-spawn-fail op={} Arguments=[{}] error={}",
82 OperationId,
83 Args.join(" "),
84 Error
85 );
86 format!("git spawn failed: {}", Error)
87 })?;
88
89 if let Some(Pid) = Child.id() {
90 RegisterPid(OperationId, Pid);
91 }
92
93 let Output = Child.wait_with_output().await.map_err(|Error| {
94 ClearPid(OperationId);
95 format!("git wait failed: {}", Error)
96 })?;
97
98 ClearPid(OperationId);
99
100 let ExitCode = Output.status.code().unwrap_or(-1);
101 let Stdout = String::from_utf8_lossy(&Output.stdout).into_owned();
102 let Stderr = String::from_utf8_lossy(&Output.stderr).into_owned();
103
104 dev_log!(
105 "git",
106 "[Git] exec-done op={} Arguments=[{}] exit={} stdout={}B stderr={}B",
107 OperationId,
108 Args.join(" "),
109 ExitCode,
110 Stdout.len(),
111 Stderr.len()
112 );
113
114 Ok((ExitCode, Stdout, Stderr))
115}
116
117pub fn AsStringArray(Value:&Value) -> Vec<String> {
118 Value
119 .as_array()
120 .map(|Arr| Arr.iter().filter_map(|V| V.as_str().map(str::to_string)).collect())
121 .unwrap_or_default()
122}
123
124pub fn Generated() -> String { uuid::Uuid::new_v4().to_string() }