use std::collections::BTreeMap;
use std::fs;
use std::path::{Path, PathBuf};
pub use frame_cli::{NewOptions, generate};
use std::sync::atomic::{AtomicU64, Ordering};
static SEQUENCE: AtomicU64 = AtomicU64::new(0);
pub struct TestDirectory(PathBuf);
impl TestDirectory {
pub fn new(label: &str) -> Result<Self, std::io::Error> {
let sequence = SEQUENCE.fetch_add(1, Ordering::Relaxed);
let path = std::env::temp_dir().join(format!(
"frame-cli-{label}-{}-{sequence}",
std::process::id()
));
remove_if_present(&path)?;
fs::create_dir_all(&path)?;
Ok(Self(path))
}
pub fn path(&self) -> &Path {
&self.0
}
}
impl Drop for TestDirectory {
fn drop(&mut self) {
if let Err(error) = remove_if_present(&self.0) {
eprintln!("failed to remove {}: {error}", self.0.display());
}
}
}
pub fn options(parent: &Path, name: &str) -> NewOptions {
NewOptions {
name: name.to_owned(),
target_parent: parent.to_path_buf(),
}
}
pub fn generated_files(root: &Path) -> Result<BTreeMap<PathBuf, Vec<u8>>, std::io::Error> {
let mut files = BTreeMap::new();
collect_files(root, root, &mut files)?;
Ok(files)
}
fn collect_files(
root: &Path,
directory: &Path,
files: &mut BTreeMap<PathBuf, Vec<u8>>,
) -> Result<(), std::io::Error> {
let mut entries = fs::read_dir(directory)?.collect::<Result<Vec<_>, _>>()?;
entries.sort_by_key(std::fs::DirEntry::file_name);
for entry in entries {
let path = entry.path();
let is_page_dist = path.file_name().is_some_and(|name| name == "dist")
&& path
.parent()
.and_then(Path::file_name)
.is_some_and(|name| name == "page");
if (path.file_name().is_some_and(|name| {
name == "target" || name == "build" || name == "node_modules" || name == "dist"
}) && !is_page_dist)
|| path.file_name().is_some_and(|name| {
name == "Cargo.lock" || name == "manifest.toml" || name == "package-lock.json"
})
{
continue;
}
if path.is_dir() {
collect_files(root, &path, files)?;
} else {
let relative = path
.strip_prefix(root)
.map_err(std::io::Error::other)?
.to_path_buf();
files.insert(relative, fs::read(path)?);
}
}
Ok(())
}
pub fn remove_if_present(path: &Path) -> Result<(), std::io::Error> {
match fs::remove_dir_all(path) {
Ok(()) => Ok(()),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(()),
Err(error) => Err(error),
}
}