use anyhow::Context; use std::{fs, path::Path}; pub fn find_unique_file(dir_path: &str, suffix: &str) -> anyhow::Result { let mut matching_files = Vec::new(); for entry in fs::read_dir(dir_path).with_context(|| format!("Failed to read directory: {}", dir_path))? { let entry = entry.with_context(|| "Failed to read directory entry")?; let path = entry.path(); if path.is_file() && path .file_name() .and_then(|name| name.to_str()) .map(|name| name.ends_with(suffix)) .unwrap_or(false) { matching_files.push(path); } } match matching_files.len() { 0 => Err(anyhow::anyhow!("No file found ending with '{}'", suffix)) .with_context(|| format!("In directory: {}", dir_path)), 1 => Ok(matching_files[0].to_string_lossy().into_owned()), _ => Err(anyhow::anyhow!( "Multiple files found ending with '{}'", suffix )) .with_context(|| format!("In directory: {}", dir_path)), } } pub fn path_prefix(out: &str) -> anyhow::Result { let out_path = Path::new(&out); let out_dir = out_path .parent() .ok_or_else(|| anyhow::anyhow!("Can't parse the dir of {}", out_path.display()))?; let name = out_path .file_name() .and_then(|name| name.to_str()) .ok_or_else(|| anyhow::anyhow!("Can't parse the file name of {}", out_path.display()))?; let stem = name .split_once('.') .map(|(stem, _)| stem) .ok_or_else(|| anyhow::anyhow!("Can't parse the file stem of {}", name))?; Ok(format!("{}/{stem}", out_dir.display())) } pub fn force_or_not(path: &str, force: bool) -> anyhow::Result<()> { let path = Path::new(path); let mut output_exists = path.exists(); if force && output_exists { fs::remove_dir_all( path.parent() .context(format!("Can't parse the parent dir of {}", path.display()))?, )?; output_exists = false; } if output_exists { anyhow::bail!("{} already exists.", path.display()) } Ok(()) }