1use anyhow::{anyhow, Context, Result};
2use log::{debug, warn};
3use std::path::PathBuf;
4use std::process::Command;
5
6pub fn is_git_repo() -> bool {
8 Command::new("git")
9 .args(["rev-parse", "--is-inside-work-tree"])
10 .output()
11 .map(|output| output.status.success())
12 .unwrap_or(false)
13}
14
15pub fn commit_changes(files: &[PathBuf], message: &str) -> Result<()> {
17 if !is_git_repo() {
18 warn!("Not a git repository, skipping commit");
19 return Ok(());
20 }
21
22 for file in files {
24 debug!("Staging file: {}", file.display());
25
26 let status = Command::new("git")
27 .args(["add", &file.to_string_lossy()])
28 .status()
29 .context("Failed to run git add command")?;
30
31 if !status.success() {
32 return Err(anyhow!(
33 "Failed to add file to git staging area: {}",
34 file.display()
35 ));
36 }
37 }
38
39 debug!("Committing with message: {}", message);
41
42 let status = Command::new("git")
43 .args(["commit", "-m", message])
44 .status()
45 .context("Failed to run git commit command")?;
46
47 if !status.success() {
48 return Err(anyhow!("Git commit failed"));
49 }
50
51 Ok(())
52}
53
54pub fn tag_exists(tag: &str) -> Result<bool> {
56 if !is_git_repo() {
57 warn!("Not a git repository, assuming tag doesn't exist");
58 return Ok(false);
59 }
60
61 let output = Command::new("git")
62 .args(["tag", "-l", tag])
63 .output()
64 .context("Failed to run git tag command")?;
65
66 Ok(!output.stdout.is_empty())
67}
68
69pub fn create_tag(tag: &str, force: bool) -> Result<()> {
71 if !is_git_repo() {
72 warn!("Not a git repository, skipping tag creation");
73 return Ok(());
74 }
75
76 let mut args = vec!["tag"];
77
78 if force {
79 args.push("-f");
80 }
81
82 args.push(tag);
83
84 debug!("Creating git tag: {}", tag);
85
86 let status = Command::new("git")
87 .args(&args)
88 .status()
89 .context("Failed to run git tag command")?;
90
91 if !status.success() {
92 return Err(anyhow!("Failed to create git tag: {}", tag));
93 }
94
95 Ok(())
96}