use clap::Args;
use log::{debug, info, warn};
use std::error::Error;
use std::{fs, io};
use crate::MultiProgressContainer;
use crate::cli::GlobalOptions;
use crate::project::Project;
use crate::{
COMPLETED_CACHE_FILE_NAME, DATA_DIRECTORY_NAME, DIRECTORY_CACHE_FILE_NAME,
SUBMITTED_CACHE_FILE_NAME,
};
#[derive(Args, Debug)]
pub struct Arguments {
#[command(flatten)]
selection: Option<Selection>,
#[arg(long, display_order = 0)]
force: bool,
}
#[derive(Args, Debug)]
#[group(multiple = true)]
pub struct Selection {
#[arg(long, display_order = 0)]
directory: bool,
#[arg(long, display_order = 0)]
submitted: bool,
#[arg(long, display_order = 0)]
completed: bool,
}
pub fn clean(
options: &GlobalOptions,
args: &Arguments,
multi_progress: &mut MultiProgressContainer,
) -> Result<(), Box<dyn Error>> {
debug!("Cleaning cache files.");
let mut project = Project::open(options.io_threads, &options.cluster, multi_progress)?;
project.close(multi_progress)?;
let selection = args.selection.as_ref().unwrap_or(&Selection {
directory: true,
submitted: true,
completed: true,
});
let num_submitted = project.state().num_submitted();
if num_submitted > 0 {
let force_needed = selection.completed || selection.submitted;
if force_needed {
warn!("There are {num_submitted} directories with submitted jobs.");
}
if selection.submitted {
warn!("The submitted cache is not recoverable. Row may resubmit running jobs.");
}
if selection.completed {
warn!("These jobs may add to the completed cache after it is cleaned.");
}
if force_needed && !args.force {
warn!("You should wait for these jobs to complete.");
return Err(Box::new(crate::Error::ForceCleanNeeded));
}
}
let data_directory = project.workflow().root.join(DATA_DIRECTORY_NAME);
if selection.submitted {
let path = data_directory.join(SUBMITTED_CACHE_FILE_NAME);
info!("Removing '{}'.", path.display());
if let Err(error) = fs::remove_file(&path) {
match error.kind() {
io::ErrorKind::NotFound => (),
_ => return Err(Box::new(crate::Error::FileRemove(path.clone(), error))),
}
}
}
if selection.completed {
let path = data_directory.join(COMPLETED_CACHE_FILE_NAME);
info!("Removing '{}'.", path.display());
if let Err(error) = fs::remove_file(&path) {
match error.kind() {
io::ErrorKind::NotFound => (),
_ => return Err(Box::new(crate::Error::FileRemove(path.clone(), error))),
}
}
}
if selection.directory {
let path = data_directory.join(DIRECTORY_CACHE_FILE_NAME);
info!("Removing '{}'.", path.display());
if let Err(error) = fs::remove_file(&path) {
match error.kind() {
io::ErrorKind::NotFound => (),
_ => return Err(Box::new(crate::Error::FileRemove(path.clone(), error))),
}
}
}
Ok(())
}