From 341202f87c96d588c1e831179693f67301b664af Mon Sep 17 00:00:00 2001 From: landon Date: Wed, 16 Sep 2026 18:38:03 -0500 Subject: [PATCH] fix: Improve bundled template path resolution and add tests - Walk up directory tree from executable to find templates/snowflake - Handles various build configurations (release, debug, cargo run, installed) - Add test to verify bundled template path contains 'templates/snowflake' - Add test to verify template has 05-First Draft (merged) and not old 05-Plot/06-First Draft Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe --- src/config.rs | 58 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/src/config.rs b/src/config.rs index 596519d..1c52557 100644 --- a/src/config.rs +++ b/src/config.rs @@ -189,29 +189,34 @@ pub fn default_show_toolbar() -> bool { pub fn default_project_template() -> PathBuf { // Find the bundled template relative to the executable's location if let Ok(exe_path) = std::env::current_exe() { - // The templates are at the project root level, same as Cargo.toml - // binary is typically at target/release/md-manuscript or target/debug/md-manuscript - // So we need to go up from target/release (or target/debug) to the project root - // Then look for templates/snowflake there - let candidates = [ - // Binary in target/release/ -> project root -> templates/snowflake - exe_path.parent().and_then(|p| p.parent()).and_then(|p| p.parent()).map(|p| p.join("templates/snowflake")), - // Binary in target/debug/ -> project root -> templates/snowflake - exe_path.parent().and_then(|p| p.parent()).map(|p| p.join("templates/snowflake")), - // Binary in project root (dev) -> templates/snowflake - exe_path.parent().map(|p| p.join("templates/snowflake")), - // Fallback: relative to current working directory - std::env::current_dir().ok().map(|p| p.join("templates/snowflake")), - ]; - for candidate in candidates.into_iter().flatten() { + // Walk up from the executable looking for templates/snowflake/cookiecutter.json + // This handles various build configurations (release, debug, cargo run, installed binary) + let mut current = exe_path.as_path(); + loop { + // Check if current/templates/snowflake/cookiecutter.json exists + let candidate = current.join("templates/snowflake"); + if candidate.join("cookiecutter.json").is_file() { + return candidate; + } + // Try going up one level + match current.parent() { + Some(parent) => current = parent, + None => break, + } + } + + // Also try relative to current working directory + if let Ok(cwd) = std::env::current_dir() { + let candidate = cwd.join("templates/snowflake"); if candidate.join("cookiecutter.json").is_file() { return candidate; } } } + // If we can't find the bundled template, panic with a clear error // The bundled template should always be present in a properly built release - panic!("Bundled template not found. Please ensure templates/snowflake/ exists relative to the executable."); + panic!("Bundled template not found. Please ensure templates/snowflake/cookiecutter.json exists relative to the executable."); } /// Default subfolder opened after generating a project: the snowflake @@ -595,5 +600,26 @@ mod tests { // Verify it returns a valid path that contains cookiecutter.json assert!(path.join("cookiecutter.json").is_file(), "Template path {} should contain cookiecutter.json", path.display()); + + // Also verify it's using the bundled template (contains "templates/snowflake") + let path_str = path.to_string_lossy(); + assert!(path_str.contains("templates/snowflake"), + "Template path {} should be the bundled template", path.display()); + } + + #[test] + fn bundled_template_contains_05_first_draft() { + let path = default_project_template(); + let template_dir = path.join("{{ cookiecutter.project_name }}"); + + // Verify the template has the merged 05-First Draft folder + assert!(template_dir.join("05-First Draft").is_dir(), + "Bundled template should contain 05-First Draft directory"); + + // Verify it does NOT have the old separate directories + assert!(!template_dir.join("05-Plot").is_dir(), + "Bundled template should NOT contain old 05-Plot directory"); + assert!(!template_dir.join("06-First Draft").is_dir(), + "Bundled template should NOT contain old 06-First Draft directory"); } }