use anyhow::Context as _;
use std::path::Path;
const POLY_CONFIG_RELATIVE: &str = "poly.toml";
const STALE_SNIPPET_HOOK_RUN: &str = "alef snippets check --strict --cache off";
pub(crate) fn migrate_poly_toml_drop_snippet_hook(base_dir: &Path) -> anyhow::Result<bool> {
let path = base_dir.join(POLY_CONFIG_RELATIVE);
let Ok(existing) = std::fs::read_to_string(&path) else {
return Ok(false);
};
let Ok(mut doc) = existing.parse::<toml_edit::DocumentMut>() else {
return Ok(false);
};
let commands = doc
.as_table_mut()
.get_mut("hooks")
.and_then(toml_edit::Item::as_table_mut)
.and_then(|hooks| hooks.get_mut("pre-commit"))
.and_then(toml_edit::Item::as_table_mut)
.and_then(|pre_commit| pre_commit.get_mut("commands"))
.and_then(toml_edit::Item::as_table_mut);
let Some(commands) = commands else {
return Ok(false);
};
let is_stale_snippet_hook = commands
.get("alef-snippets")
.and_then(toml_edit::Item::as_table)
.is_some_and(|hook| {
hook.get("run").and_then(toml_edit::Item::as_str) == Some(STALE_SNIPPET_HOOK_RUN)
&& hook.get("workspace").and_then(toml_edit::Item::as_bool) == Some(true)
});
if !is_stale_snippet_hook {
return Ok(false);
}
commands.remove("alef-snippets");
let parent = path.parent().context("poly.toml path has no parent directory")?;
let mut temporary = tempfile::NamedTempFile::new_in(parent)
.with_context(|| format!("failed to create temporary file in {}", parent.display()))?;
std::io::Write::write_all(&mut temporary, doc.to_string().as_bytes())
.with_context(|| format!("failed to write temporary file for {}", path.display()))?;
temporary
.persist(&path)
.map_err(|error| error.error)
.with_context(|| format!("failed to replace {}", path.display()))?;
tracing::info!(
path = %path.display(),
"repaired pre-existing poly.toml: removed the retracted alef-snippets pre-commit hook"
);
Ok(true)
}