use std::fs;
use std::path::Path;
use crate::{
cmd,
util::{self, CommandExt as _},
};
use eyre::{Result, WrapErr, bail};
use owo_colors::OwoColorize;
pub fn run(repo: &util::Repo, msg_file: &str) -> Result<()> {
let msg_path = Path::new(msg_file);
if !msg_path
.try_exists()
.wrap_err("Failed to check file existence")?
{
bail!("File does not exist: {}", msg_path.display().red().bold());
}
let Some(branch_name) = repo.current_branch().name() else {
log::debug!("Could not determine branch name (detached head?). Skipping.");
return Ok(());
};
if !repo.is_managed(branch_name)? {
log::warn!("Branch {} is not managed. Skipping.", branch_name.yellow());
return Ok(());
}
let msg_content = fs::read_to_string(msg_path).wrap_err("Failed to read msg file")?;
if msg_content
.lines()
.next()
.is_some_and(|l| l.starts_with("squash! "))
{
return Ok(());
}
let input_data = {
let committer_ident = cmd!("git var GIT_COMMITTER_IDENT").checked_output()?;
let committer_ident = String::from_utf8_lossy(committer_ident.stdout.as_slice())
.trim()
.to_string();
let refhash = repo
.head_id()
.map(|h| h.to_string())
.unwrap_or_else(|_| gix::ObjectId::empty_tree(repo.object_hash()).to_string());
format!("{}\n{}\n{}", committer_ident, refhash, msg_content)
};
let object_id = gix::diff::object::compute_hash(
repo.object_hash(),
gix::object::Kind::Blob,
input_data.as_bytes(),
)
.wrap_err("Failed to compute hash")?;
let random_hash = object_id.to_string();
let output = cmd!("git interpret-trailers --parse", msg_file).checked_output()?;
let trailers = String::from_utf8_lossy(&output.stdout);
let re = crate::re!(r"^gherrit-pr-id: .*");
if trailers.lines().any(|line| re.is_match(line)) {
return Ok(());
}
cmd!(
"git interpret-trailers --in-place --where start --if-exists doNothing --trailer",
"gherrit-pr-id: G{random_hash}",
msg_file
)
.success()?;
Ok(())
}