use std::collections::BTreeSet;
use std::path::{Path, PathBuf};
use log::debug;
use crate::errors::{GrabError, GrabResult};
pub(crate) fn generate_indented_tree(files: &[PathBuf], base_path: &Path) -> GrabResult<String> {
debug!("Generating tree relative to {:?}", base_path);
let mut tree_output = String::new();
let mut relative_paths = BTreeSet::new();
for file_path in files {
let rel_path =
file_path
.strip_prefix(base_path)
.map_err(|_e| GrabError::PathStripError {
prefix: base_path.to_path_buf(),
path: file_path.clone(),
})?;
relative_paths.insert(rel_path.to_path_buf());
let mut current = rel_path;
while let Some(parent) = current.parent() {
if parent.as_os_str().is_empty() {
break; }
relative_paths.insert(parent.to_path_buf());
current = parent;
}
}
for rel_path in relative_paths {
let depth = rel_path.components().count();
let indent = " ".repeat(depth.saturating_sub(1));
if let Some(name) = rel_path.file_name() {
let abs_path = base_path.join(&rel_path);
let is_dir = abs_path.is_dir();
tree_output.push_str(&format!(
"{}- {}{}\n",
indent,
name.to_string_lossy(),
if is_dir { "/" } else { "" }
));
} else {
debug!(
"Skipping empty path component in tree generation: {:?}",
rel_path
);
}
}
Ok(tree_output)
}