use xx::file::display_path;
use crate::file;
use crate::git::Git;
#[derive(Debug, clap::Args)]
#[clap(verbatim_doc_comment, visible_alias = "pre-commit", after_long_help = AFTER_LONG_HELP)]
pub struct GitPreCommit {
#[clap(long, short, default_value = "pre-commit")]
task: String,
#[clap(long, short)]
write: bool,
#[clap(long, default_value = "pre-commit")]
hook: String,
}
impl GitPreCommit {
pub async fn run(self) -> eyre::Result<()> {
let output = self.generate();
if self.write {
let path = Git::get_root()?.join(".git/hooks").join(&self.hook);
if path.exists() {
let old_path = path.with_extension("old");
miseprintln!(
"Moving existing hook to {:?}",
old_path.file_name().unwrap()
);
file::rename(&path, path.with_extension("old"))?;
}
file::write(&path, &output)?;
file::make_executable(&path)?;
miseprintln!("Wrote to {}", display_path(&path));
} else {
miseprintln!("{output}");
}
Ok(())
}
fn generate(&self) -> String {
let task = &self.task;
format!(
r#"#!/bin/sh
STAGED="$(git diff-index --cached --name-only -z HEAD | xargs -0)"
export STAGED
export MISE_PRE_COMMIT=1
exec mise run {task}
"#
)
}
}
static AFTER_LONG_HELP: &str = color_print::cstr!(
r#"<bold><underline>Examples:</underline></bold>
$ <bold>mise generate git-pre-commit --write --task=pre-commit</bold>
$ <bold>git commit -m "feat: add new feature"</bold> <dim># runs `mise run pre-commit`</dim>
"#
);