use std::io::{self, Write};
use std::time::Duration;
fn read_line_with_timeout(prompt: &str, timeout: Duration) -> io::Result<Option<String>> {
print!("{}", prompt);
io::stdout().flush()?;
let (tx, rx) = std::sync::mpsc::channel();
std::thread::spawn(move || {
let mut input = String::new();
if io::stdin().read_line(&mut input).is_ok() {
let _ = tx.send(input.trim().to_string());
}
});
match rx.recv_timeout(timeout) {
Ok(val) => Ok(Some(val)),
Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {
println!("\nPrompt timed out. Operation cancelled.");
Ok(None)
}
Err(_) => Err(io::Error::new(io::ErrorKind::Other, "Channel closed")),
}
}
pub fn run_clean_history(repo_path: &str) -> io::Result<()> {
println!("Warning: This action will permanently delete all previous commit history.");
let confirm1 = read_line_with_timeout(
"Are you sure you want to proceed? [y/N] ",
Duration::from_secs(15),
)?;
if confirm1.is_none() {
return Ok(());
}
let confirm1 = confirm1.unwrap();
if !confirm1.eq_ignore_ascii_case("y") {
println!("Operation cancelled.");
return Ok(());
}
println!("\nWarning: The force push will fail if your remote branch is protected.");
println!("Please verify branch protection is disabled here:");
println!(
"https://gitlab.com/{}/-/settings/repository#js-protected-branches-settings",
repo_path
);
let confirm2 = read_line_with_timeout(
"Have you disabled protection for your current branch? [y/N] ",
Duration::from_secs(15),
)?;
if confirm2.is_none() {
return Ok(());
}
let confirm2 = confirm2.unwrap();
if !confirm2.eq_ignore_ascii_case("y") {
println!("Operation cancelled. Please disable branch protection and try again.");
return Ok(());
}
println!("Resetting repository history...");
let branch_output = std::process::Command::new("chezmoi")
.args(&["git", "--", "branch", "--show-current"])
.output()?;
let mut branch = String::from_utf8_lossy(&branch_output.stdout)
.trim()
.to_string();
if branch.is_empty() {
branch = "main".to_string();
}
std::process::Command::new("chezmoi")
.args(&["git", "--", "checkout", "--orphan", "temp_branch"])
.status()?;
std::process::Command::new("chezmoi")
.args(&["git", "--", "add", "-A"])
.status()?;
std::process::Command::new("chezmoi")
.args(&[
"git",
"--",
"commit",
"-m",
"chore: reset repository history",
])
.status()?;
std::process::Command::new("chezmoi")
.args(&["git", "--", "branch", "-D", &branch])
.status()?;
std::process::Command::new("chezmoi")
.args(&["git", "--", "branch", "-m", &branch])
.status()?;
println!("Force pushing to remote...");
std::process::Command::new("chezmoi")
.args(&["git", "--", "push", "-f", "-u", "origin", &branch])
.status()?;
println!("Cleaning local garbage...");
std::process::Command::new("chezmoi")
.args(&["git", "--", "reflog", "expire", "--expire=now", "--all"])
.status()?;
std::process::Command::new("chezmoi")
.args(&["git", "--", "gc", "--prune=now", "--aggressive"])
.status()?;
println!("History cleaned successfully.");
Ok(())
}