1use {
5 super::commit_info::commit_info,
6 crate::{
7 core::state::commit::{CommitInfo, ConventionalCommitMessage},
8 fail,
9 },
10 eyre::Result,
11 std::process::Command,
12};
13
14pub fn commit(ccm: &ConventionalCommitMessage, cwd: Option<&str>) -> Result<CommitInfo> {
19 let message = ccm.raw_commit();
20 let cwd = cwd.unwrap_or("./");
21
22 let output = Command::new("git")
23 .arg("commit")
24 .arg("-m")
25 .arg(message)
26 .current_dir(cwd)
27 .output()
28 .expect("Failed to execute git commit");
29
30 if output.status.success() {
32 let commit_out = String::from_utf8_lossy(&output.stdout).to_string();
33 let (hash, _) = parse_commit_output(&commit_out)?;
34
35 commit_info(&hash, Some(cwd))
37 } else {
38 fail!("{}", String::from_utf8_lossy(&output.stderr).to_string())
39 }
40}
41
42fn parse_commit_output(commit_out: &str) -> Result<(String, String)> {
45 for line in commit_out.lines() {
46 if line.starts_with('[') {
47 let parts: Vec<&str> = line.split_whitespace().collect();
48 if parts.len() >= 3 {
49 let branch = parts[0][1..].to_string();
50 let hash = parts[1].trim_end_matches(']').to_string();
51 return Ok((hash, branch));
52 }
53 }
54 }
55
56 fail!("Failed to parse commit output")
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn test_output_parsing() {
65 let output = [
66 "[master e63e7aa] the first line of the message!",
67 " 1 file changed, 0 insertions(+), 0 deletions(-)",
68 " create mode 100644 wqeqwex.txt",
69 ]
70 .join("\n");
71
72 let (hash, branch) = parse_commit_output(&output).unwrap();
73 assert_eq!(hash, "e63e7aa");
74 assert_eq!(branch, "master");
75 }
76}