Skip to main content

ralph_workflow/checkpoint/git_capture/
io.rs

1// checkpoint/git_capture/io.rs — boundary module for git capture operations.
2// File stem is `io` — recognized as boundary module by forbid_io_effects lint.
3
4use crate::ProcessExecutor;
5
6pub fn git_head_oid(executor: &dyn ProcessExecutor) -> Option<String> {
7    executor
8        .execute("git", &["rev-parse", "HEAD"], &[], None)
9        .ok()
10        .filter(|output| output.status.success())
11        .map(|output| output.stdout.trim().to_string())
12}
13
14pub fn git_branch_name(executor: &dyn ProcessExecutor) -> Option<String> {
15    executor
16        .execute("git", &["rev-parse", "--abbrev-ref", "HEAD"], &[], None)
17        .ok()
18        .filter(|output| output.status.success())
19        .map(|output| output.stdout.trim().to_string())
20        .filter(|branch| !branch.is_empty() && branch != "HEAD")
21}
22
23pub fn git_status(executor: &dyn ProcessExecutor) -> Option<String> {
24    executor
25        .execute("git", &["status", "--porcelain"], &[], None)
26        .ok()
27        .filter(|output| output.status.success())
28        .map(|output| output.stdout.trim().to_string())
29        .filter(|status| !status.is_empty())
30}
31
32pub fn git_modified_files(executor: &dyn ProcessExecutor) -> Option<Vec<String>> {
33    let diff_output = executor
34        .execute("git", &["diff", "--name-only"], &[], None)
35        .ok()
36        .filter(|output| output.status.success())
37        .map(|output| output.stdout)?;
38
39    let modified_files: Vec<String> = diff_output
40        .lines()
41        .map(|line| line.trim().to_string())
42        .filter(|line| !line.is_empty())
43        .collect();
44
45    (!modified_files.is_empty()).then_some(modified_files)
46}