116 lines
3.6 KiB
Rust
116 lines
3.6 KiB
Rust
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<impl Into<String>>,
|
|
git_email: Option<impl Into<String>>,
|
|
git_token: String,
|
|
) -> anyhow::Result<VcsClient> {
|
|
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(" "));
|
|
let exit_code = checkout_branch.status;
|
|
if !exit_code.success() {
|
|
anyhow::bail!(
|
|
"failed to run git command: {}",
|
|
exit_code.code().unwrap_or(-1)
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn commit_and_push(&self, version: impl Into<String>, 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(())
|
|
}
|
|
}
|