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 <vibe@mistral.ai>
This commit is contained in:
2026-09-16 18:38:03 -05:00
parent 2471312f05
commit 341202f87c
+42 -16
View File
@@ -189,29 +189,34 @@ pub fn default_show_toolbar() -> bool {
pub fn default_project_template() -> PathBuf { pub fn default_project_template() -> PathBuf {
// Find the bundled template relative to the executable's location // Find the bundled template relative to the executable's location
if let Ok(exe_path) = std::env::current_exe() { if let Ok(exe_path) = std::env::current_exe() {
// The templates are at the project root level, same as Cargo.toml // Walk up from the executable looking for templates/snowflake/cookiecutter.json
// binary is typically at target/release/md-manuscript or target/debug/md-manuscript // This handles various build configurations (release, debug, cargo run, installed binary)
// So we need to go up from target/release (or target/debug) to the project root let mut current = exe_path.as_path();
// Then look for templates/snowflake there loop {
let candidates = [ // Check if current/templates/snowflake/cookiecutter.json exists
// Binary in target/release/ -> project root -> templates/snowflake let candidate = current.join("templates/snowflake");
exe_path.parent().and_then(|p| p.parent()).and_then(|p| p.parent()).map(|p| p.join("templates/snowflake")), if candidate.join("cookiecutter.json").is_file() {
// Binary in target/debug/ -> project root -> templates/snowflake return candidate;
exe_path.parent().and_then(|p| p.parent()).map(|p| p.join("templates/snowflake")), }
// Binary in project root (dev) -> templates/snowflake // Try going up one level
exe_path.parent().map(|p| p.join("templates/snowflake")), match current.parent() {
// Fallback: relative to current working directory Some(parent) => current = parent,
std::env::current_dir().ok().map(|p| p.join("templates/snowflake")), None => break,
]; }
for candidate in candidates.into_iter().flatten() { }
// 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() { if candidate.join("cookiecutter.json").is_file() {
return candidate; return candidate;
} }
} }
} }
// If we can't find the bundled template, panic with a clear error // 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 // 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 /// 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 // Verify it returns a valid path that contains cookiecutter.json
assert!(path.join("cookiecutter.json").is_file(), assert!(path.join("cookiecutter.json").is_file(),
"Template path {} should contain cookiecutter.json", path.display()); "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");
} }
} }