use std::path::{Path, PathBuf}; #[derive(Clone, Debug, PartialEq)] pub enum VcsClient { Noop {}, Git { source: PathBuf, username: String, email: String, token: String, }, } impl VcsClient { pub fn new_noop() -> VcsClient { Self::Noop {} } pub fn new_git( path: &Path, git_username: Option>, git_email: Option>, git_token: String, ) -> anyhow::Result { if !path.to_path_buf().join(".git").exists() { anyhow::bail!("git directory not found in: {}", path.display().to_string()) } Ok(Self::Git { source: path.to_path_buf(), username: git_username .map(|u| u.into()) .unwrap_or("cuddle-please".to_string()), email: git_email .map(|e| e.into()) .unwrap_or("bot@cuddle.sh".to_string()), token: git_token, }) } pub fn checkout_branch(&self) -> anyhow::Result<()> { match self { VcsClient::Noop {} => {} VcsClient::Git { .. } => { if let Err(_e) = self.exec_git(&["branch", "-D", "cuddle-please/release"]) { tracing::debug!("failed to cleaned up local branch for force-push, this may be because it didn't exist before running this command"); } self.exec_git(&["checkout", "-b", "cuddle-please/release"])?; } } Ok(()) } fn exec_git(&self, args: &[&str]) -> anyhow::Result<()> { match self { VcsClient::Noop {} => {} VcsClient::Git { source, username, email, token, } => { let checkout_branch = std::process::Command::new("git") .current_dir(source.as_path()) .args([ "-c", &format!("http.extraHeader='Authorization: token {}'", token), "-c", "http.extraHeader='Sudo: kjuulh'", "-c", &format!("user.name={}", username), "-c", &format!("user.email={}", email), ]) .args(args) .output()?; let stdout = std::str::from_utf8(&checkout_branch.stdout)?; let stderr = std::str::from_utf8(&checkout_branch.stderr)?; tracing::debug!(stdout = stdout, stderr = stderr, "git {}", args.join(" ")); } } Ok(()) } pub fn commit_and_push(&self, version: impl Into, dry_run: bool) -> anyhow::Result<()> { match self { VcsClient::Noop {} => {} VcsClient::Git { .. } => { self.exec_git(&["add", "."])?; self.exec_git(&[ "commit", "-m", &format!("chore(release): {}", version.into()), ])?; tracing::trace!("git push -u -f origin cuddle-please/release"); if !dry_run { self.exec_git(&["push", "-u", "-f", "origin", "cuddle-please/release"])?; } } } Ok(()) } }