use std::path::Path;
use anyhow::Context;
pub fn data_dir() -> anyhow::Result<std::path::PathBuf> {
let home =
dirs::home_dir().ok_or_else(|| anyhow::anyhow!("Could not determine home directory"))?;
let data_dir = home.join(".texforge");
std::fs::create_dir_all(&data_dir)?;
Ok(data_dir)
}
pub fn templates_dir() -> anyhow::Result<std::path::PathBuf> {
let dir = data_dir()?.join("templates");
std::fs::create_dir_all(&dir)?;
Ok(dir)
}
pub fn find_tex_files(root: &Path) -> anyhow::Result<Vec<std::path::PathBuf>> {
let mut files = Vec::new();
let build_dir = root.join("build");
for entry in walkdir::WalkDir::new(root)
.follow_links(true)
.into_iter()
.filter_map(|e| e.ok())
{
let path = entry.path();
if path.starts_with(&build_dir) {
continue;
}
if entry.file_type().is_file() {
if let Some(ext) = path.extension() {
if ext == "tex" {
files.push(path.to_path_buf());
}
}
}
}
Ok(files)
}
pub fn mirror_assets(root: &Path, build_dir: &Path) -> anyhow::Result<()> {
for entry in std::fs::read_dir(root)? {
let entry = entry?;
let path = entry.path();
let name = entry.file_name();
let name_str = name.to_string_lossy();
if name_str.starts_with('.') || path == build_dir {
continue;
}
let dest = build_dir.join(&name);
if path.is_dir() {
if dest.exists() || dest.symlink_metadata().is_ok() {
continue;
}
link_or_copy_dir(&path, &dest)?;
} else if path.is_file() {
let ext = path.extension().and_then(|e| e.to_str()).unwrap_or("");
if ext != "tex" && !dest.exists() {
std::fs::copy(&path, &dest)?;
}
}
}
Ok(())
}
#[cfg(unix)]
fn link_or_copy_dir(src: &Path, dest: &Path) -> anyhow::Result<()> {
let target = std::path::Path::new("..").join(src.file_name().unwrap());
std::os::unix::fs::symlink(&target, dest).with_context(|| {
format!(
"Failed to symlink {} -> {}",
dest.display(),
target.display()
)
})
}
#[cfg(not(unix))]
fn link_or_copy_dir(src: &Path, dest: &Path) -> anyhow::Result<()> {
std::fs::create_dir_all(dest)?;
for entry in walkdir::WalkDir::new(src)
.into_iter()
.filter_map(|e| e.ok())
{
let rel = entry.path().strip_prefix(src).unwrap();
let target = dest.join(rel);
if entry.file_type().is_dir() {
std::fs::create_dir_all(&target)?;
} else {
std::fs::copy(entry.path(), &target)?;
}
}
Ok(())
}