use crate::cli::UI;
use crate::core::SanitizeConfig;
use crate::git::GitSanitizer;
use anyhow::Result;
use std::path::PathBuf;
pub async fn execute(path: PathBuf, dry_run: bool, backup: bool, ui: &UI) -> Result<()> {
ui.header("Sanitization");
ui.blank();
let git_dir = if path.ends_with(".git") {
path.clone()
} else {
path.join(".git")
};
if !git_dir.exists() {
anyhow::bail!("Not a git repository: {}", path.display());
}
ui.field("Repository", path.display());
ui.field("Git dir", git_dir.display());
ui.blank();
if dry_run {
ui.warning("DRY RUN - No changes will be made");
ui.blank();
}
if backup && !dry_run {
let backup_path = git_dir.with_extension("git.bak");
ui.info(format!("Creating backup: {}", backup_path.display()));
copy_dir_recursive(&git_dir, &backup_path)?;
ui.success(format!("Backup created: {}", backup_path.display()));
}
let sanitizer = GitSanitizer::new(SanitizeConfig::default());
if !dry_run {
let report = sanitizer.sanitize(&git_dir)?;
ui.result_banner(
true,
"Sanitization complete",
&[
("Hooks removed", report.removed_hooks.len().to_string()),
(
"Config keys removed",
report.removed_config_keys.len().to_string(),
),
(
"Config sections removed",
report.removed_config_sections.len().to_string(),
),
],
);
if !report.warnings.is_empty() {
ui.section("Warnings:");
for warning in &report.warnings {
ui.warning(warning);
}
}
} else {
ui.info(format!("Would sanitize: {}", git_dir.display()));
}
ui.blank();
Ok(())
}
fn copy_dir_recursive(src: &std::path::Path, dst: &std::path::Path) -> anyhow::Result<()> {
std::fs::create_dir_all(dst)?;
for entry in walkdir::WalkDir::new(src)
.into_iter()
.filter_map(|e| e.ok())
{
let rel = entry
.path()
.strip_prefix(src)
.map_err(|e| anyhow::anyhow!("Failed to compute relative path: {}", e))?;
let target = dst.join(rel);
if entry.file_type().is_dir() {
std::fs::create_dir_all(&target)?;
} else {
std::fs::copy(entry.path(), &target)?;
}
}
Ok(())
}