2024-05-03 17:50:50 +01:00
|
|
|
use std::ops::Deref;
|
|
|
|
|
2024-05-11 19:46:20 +01:00
|
|
|
use git_next_config::BranchName;
|
2024-04-19 18:56:42 +01:00
|
|
|
use secrecy::ExposeSecret;
|
2024-04-16 22:21:55 +01:00
|
|
|
use tracing::{info, warn};
|
|
|
|
|
2024-05-11 19:46:20 +01:00
|
|
|
use super::{GitRef, RepoDetails, Repository};
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum Force {
|
|
|
|
No,
|
|
|
|
From(GitRef),
|
|
|
|
}
|
|
|
|
impl std::fmt::Display for Force {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
match self {
|
|
|
|
Self::No => write!(f, "fast-foward"),
|
|
|
|
Self::From(from) => write!(f, "force-if-from:{}", from),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-04-16 22:21:55 +01:00
|
|
|
|
2024-05-03 17:50:50 +01:00
|
|
|
// TODO: (#72) reimplement using `gix`
|
2024-05-04 19:57:50 +01:00
|
|
|
#[tracing::instrument(skip_all, fields(branch = %branch_name, to = %to_commit, force = %force))]
|
2024-04-16 22:21:55 +01:00
|
|
|
pub fn reset(
|
2024-05-09 21:53:50 +01:00
|
|
|
repository: &Repository,
|
2024-04-16 22:21:55 +01:00
|
|
|
repo_details: &RepoDetails,
|
|
|
|
branch_name: BranchName,
|
|
|
|
to_commit: GitRef,
|
|
|
|
force: Force,
|
2024-05-11 19:46:20 +01:00
|
|
|
) -> Result {
|
2024-04-19 18:56:42 +01:00
|
|
|
let origin = repo_details.origin();
|
2024-04-16 22:21:55 +01:00
|
|
|
let force = match force {
|
|
|
|
Force::No => "".to_string(),
|
|
|
|
Force::From(old_ref) => format!("--force-with-lease={branch_name}:{old_ref}"),
|
|
|
|
};
|
|
|
|
// INFO: never log the command as it contains the API token within the 'origin'
|
2024-04-19 18:56:42 +01:00
|
|
|
let command: secrecy::Secret<String> = format!(
|
|
|
|
"/usr/bin/git push {} {to_commit}:{branch_name} {force}",
|
|
|
|
origin.expose_secret()
|
|
|
|
)
|
|
|
|
.into();
|
2024-05-03 17:50:50 +01:00
|
|
|
let ctx = gix::diff::command::Context {
|
2024-05-09 21:53:50 +01:00
|
|
|
git_dir: Some(repository.deref().git_dir().to_path_buf()),
|
2024-05-03 17:50:50 +01:00
|
|
|
..Default::default()
|
|
|
|
};
|
2024-04-19 18:56:42 +01:00
|
|
|
match gix::command::prepare(command.expose_secret())
|
2024-05-03 17:50:50 +01:00
|
|
|
.with_context(ctx)
|
2024-04-16 22:21:55 +01:00
|
|
|
.with_shell_allow_argument_splitting()
|
2024-05-04 19:57:50 +01:00
|
|
|
.stdout(std::process::Stdio::null())
|
|
|
|
.stderr(std::process::Stdio::null())
|
2024-04-16 22:21:55 +01:00
|
|
|
.spawn()
|
|
|
|
{
|
|
|
|
Ok(mut child) => match child.wait() {
|
2024-05-04 19:57:50 +01:00
|
|
|
Ok(_) => {
|
|
|
|
info!("Branch updated");
|
|
|
|
Ok(())
|
|
|
|
}
|
2024-04-16 22:21:55 +01:00
|
|
|
Err(err) => {
|
|
|
|
warn!(?err, "Failed (wait)");
|
2024-05-03 17:50:50 +01:00
|
|
|
Err(BranchResetError::Push)
|
2024-04-16 22:21:55 +01:00
|
|
|
}
|
|
|
|
},
|
|
|
|
Err(err) => {
|
|
|
|
warn!(?err, "Failed (spawn)");
|
2024-05-03 17:50:50 +01:00
|
|
|
Err(BranchResetError::Push)
|
2024-04-16 22:21:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-05-11 19:46:20 +01:00
|
|
|
|
|
|
|
#[derive(Debug, derive_more::From, derive_more::Display)]
|
|
|
|
pub enum BranchResetError {
|
|
|
|
Open(Box<gix::open::Error>),
|
|
|
|
Fetch(super::fetch::Error),
|
|
|
|
Push,
|
|
|
|
}
|
|
|
|
impl std::error::Error for BranchResetError {}
|
|
|
|
|
|
|
|
pub type Result = core::result::Result<(), BranchResetError>;
|