use crate::cli::UI;
use anyhow::{bail, Result};
use git2::StatusOptions;
use std::path::Path;
pub fn execute(
path: &Path,
force: bool,
directories: bool,
dry_run: bool,
remove_ignored: bool,
ui: &UI,
) -> Result<()> {
if !force && !dry_run {
bail!(
"clean requires -f (force) or -n (dry-run).\n\
Use securegit clean -f to remove untracked files."
);
}
let repo = crate::ops::open_repo(path)?;
let mut opts = StatusOptions::new();
opts.include_untracked(true)
.recurse_untracked_dirs(true)
.exclude_submodules(true);
opts.include_ignored(remove_ignored);
let statuses = repo.statuses(Some(&mut opts))?;
let mut removed = 0;
for entry in statuses.iter() {
let dominated = entry.status();
let is_untracked = dominated.contains(git2::Status::WT_NEW);
let is_ignored = dominated.contains(git2::Status::IGNORED);
if !is_untracked && !is_ignored {
continue;
}
if is_ignored && !remove_ignored {
continue;
}
let file_path = entry.path().unwrap_or("");
let full = path.join(file_path);
if full.is_dir() && !directories {
continue;
}
if dry_run {
ui.list_item(format!("Would remove {}", file_path));
} else if full.is_dir() {
std::fs::remove_dir_all(&full)?;
ui.success(format!("Removing {}/", file_path));
} else if full.exists() {
std::fs::remove_file(&full)?;
ui.success(format!("Removing {}", file_path));
}
removed += 1;
}
if removed == 0 {
ui.info("Nothing to clean");
}
Ok(())
}