cuddle_please_misc/
git_client.rs1use std::path::{Path, PathBuf};
2
3#[derive(Clone, Debug, PartialEq)]
4pub enum VcsClient {
5 Noop {},
6 Git {
7 source: PathBuf,
8 username: String,
9 email: String,
10 },
11}
12
13impl VcsClient {
14 pub fn new_noop() -> VcsClient {
15 Self::Noop {}
16 }
17
18 pub fn new_git(
19 path: &Path,
20 git_username: Option<impl Into<String>>,
21 git_email: Option<impl Into<String>>,
22 ) -> anyhow::Result<VcsClient> {
23 if !path.to_path_buf().join(".git").exists() {
24 anyhow::bail!("git directory not found in: {}", path.display().to_string())
25 }
26
27 Ok(Self::Git {
28 source: path.to_path_buf(),
29 username: git_username
30 .map(|u| u.into())
31 .unwrap_or("cuddle-please".to_string()),
32 email: git_email
33 .map(|e| e.into())
34 .unwrap_or("bot@cuddle.sh".to_string()),
35 })
36 }
37
38 pub fn checkout_branch(&self) -> anyhow::Result<()> {
39 match self {
40 VcsClient::Noop {} => {}
41 VcsClient::Git { .. } => {
42 if let Err(_e) = self.exec_git(&["branch", "-D", "cuddle-please/release"]) {
43 tracing::debug!("failed to cleaned up local branch for force-push, this may be because it didn't exist before running this command");
44 }
45 self.exec_git(&["checkout", "-b", "cuddle-please/release"])?;
46 }
47 }
48
49 Ok(())
50 }
51
52 fn exec_git(&self, args: &[&str]) -> anyhow::Result<()> {
53 match self {
54 VcsClient::Noop {} => {}
55 VcsClient::Git {
56 source,
57 username,
58 email,
59 } => {
60 let checkout_branch = std::process::Command::new("git")
61 .current_dir(source.as_path())
62 .args(&[
63 "-c",
64 &format!("user.name={}", username),
65 "-c",
66 &format!("user.email={}", email),
67 ])
68 .args(args)
69 .output()?;
70
71 let stdout = std::str::from_utf8(&checkout_branch.stdout)?;
72 let stderr = std::str::from_utf8(&checkout_branch.stderr)?;
73 tracing::debug!(stdout = stdout, stderr = stderr, "git {}", args.join(" "));
74 }
75 }
76
77 Ok(())
78 }
79
80 pub fn commit_and_push(&self, version: impl Into<String>, dry_run: bool) -> anyhow::Result<()> {
81 match self {
82 VcsClient::Noop {} => {}
83 VcsClient::Git { .. } => {
84 self.exec_git(&["add", "."])?;
85 self.exec_git(&[
86 "commit",
87 "-m",
88 &format!("chore(release): {}", version.into()),
89 ])?;
90
91 tracing::trace!("git push -u -f origin cuddle-please/release");
92 if !dry_run {
93 self.exec_git(&["push", "-u", "-f", "origin", "cuddle-please/release"])?;
94 }
95 }
96 }
97
98 Ok(())
99 }
100}