Skip to main content

camel_cli/template/
embedded.rs

1use include_dir::{Dir, DirEntry, include_dir};
2
3use super::{TemplateContext, TemplateFile, TemplateProvider};
4
5static BASIC_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates/basic");
6
7pub struct EmbeddedTemplate {
8    name: &'static str,
9    dir: &'static Dir<'static>,
10}
11
12impl EmbeddedTemplate {
13    pub fn basic() -> Self {
14        Self {
15            name: "basic",
16            dir: &BASIC_DIR,
17        }
18    }
19}
20
21fn collect_files(
22    dir: &Dir<'_>,
23    files: &mut Vec<TemplateFile>,
24) -> Result<(), Box<dyn std::error::Error>> {
25    for entry in dir.entries() {
26        match entry {
27            DirEntry::Dir(subdir) => {
28                collect_files(subdir, files)?;
29            }
30            DirEntry::File(f) => {
31                let path = f.path().to_str().unwrap_or("");
32                if path.starts_with("Camel.toml.") || path == "README.md.tpl" {
33                    continue;
34                }
35                let content = f
36                    .contents_utf8()
37                    .ok_or_else(|| format!("file is not valid UTF-8: {path}"))?;
38                files.push(TemplateFile {
39                    path: path.to_string(),
40                    content: content.to_string(),
41                });
42            }
43        }
44    }
45    Ok(())
46}
47
48impl TemplateProvider for EmbeddedTemplate {
49    fn name(&self) -> &str {
50        self.name
51    }
52
53    fn files(
54        &self,
55        ctx: &TemplateContext,
56    ) -> Result<Vec<TemplateFile>, Box<dyn std::error::Error>> {
57        let mut files = Vec::new();
58
59        let camel_toml_name = match ctx.profile_layout {
60            super::ProfileLayout::Simple => "Camel.toml.simple",
61            super::ProfileLayout::Env => "Camel.toml.env",
62        };
63        let camel_content = self
64            .dir
65            .get_file(camel_toml_name)
66            .ok_or_else(|| format!("{camel_toml_name} template not found"))?
67            .contents_utf8()
68            .ok_or_else(|| format!("{camel_toml_name} template is not valid UTF-8"))?;
69        files.push(TemplateFile {
70            path: "Camel.toml".to_string(),
71            content: camel_content.to_string(),
72        });
73
74        collect_files(self.dir, &mut files)?;
75
76        let readme_template = self
77            .dir
78            .get_file("README.md.tpl")
79            .ok_or("README.md.tpl not found")?
80            .contents_utf8()
81            .ok_or("README.md.tpl is not valid UTF-8")?;
82        // Use only the final directory name for the README title
83        let display_name = std::path::Path::new(&ctx.project_name)
84            .file_name()
85            .and_then(|n| n.to_str())
86            .unwrap_or(&ctx.project_name);
87        files.push(TemplateFile {
88            path: "README.md".to_string(),
89            content: readme_template.replace("<name>", display_name),
90        });
91
92        Ok(files)
93    }
94}