mdmg/commands/
generate.rs

1use crate::markdown::parse;
2use crate::scaffold_executor::{DryRunScaffoldExecutor, FSScaffoldExecutor, ScaffoldExecutor};
3use crate::template::{render, MdmgCtx};
4use crate::template_repository::{FSTemplateRepository, TemplateRepository};
5use crate::Result;
6
7use std::env::current_dir;
8use std::sync::Arc;
9
10pub struct GenerateCommandImpl;
11
12impl GenerateCommandImpl {
13    pub fn new() -> Self {
14        GenerateCommandImpl
15    }
16}
17
18trait Dependencies {
19    fn template_repository(&self) -> Arc<dyn TemplateRepository>;
20}
21
22impl Dependencies for GenerateCommandImpl {
23    fn template_repository(&self) -> Arc<dyn TemplateRepository> {
24        let current_dir = current_dir().expect("failed fetch current dir");
25        Arc::new(FSTemplateRepository::new(current_dir.join(".mdmg")))
26    }
27}
28
29pub trait GenerateCommand {
30    fn run(&self, plan_name: String, component_name: String, dry_run: bool) -> Result<()>;
31}
32
33impl GenerateCommand for GenerateCommandImpl {
34    fn run(&self, plan_name: String, component_name: String, dry_run: bool) -> Result<()> {
35        let template = self.template_repository().resolve(plan_name)?;
36        let render_ctx = MdmgCtx::new(component_name);
37        if let Ok(scaffolds) = parse(render(template, &render_ctx)?) {
38            for scaffold in scaffolds.iter() {
39                match dry_run {
40                    true => DryRunScaffoldExecutor::new().execute(scaffold)?,
41                    false => FSScaffoldExecutor::new().execute(scaffold)?,
42                };
43            }
44        };
45        Ok(())
46    }
47}
48
49#[cfg(not(tarpaulin_include))]
50#[cfg(test)]
51mod tests {
52    use std::fs::{remove_file, write};
53    use std::path::Path;
54
55    use super::*;
56
57    fn setup_template() {
58        assert!(write(
59            ".mdmg/example.md",
60            "
61          ## test.md
62
63          ```
64          hello
65          ```
66        "
67        )
68        .is_ok());
69    }
70
71    fn terradown_template() {
72        let path = Path::new(".mdmg/example.md");
73
74        assert!(remove_file(path).is_ok());
75        assert!(remove_file("test.md").is_ok());
76    }
77
78    #[test]
79    #[cfg_attr(not(feature = "fs-test"), ignore)]
80    pub fn generate_command_run_is_file_delete() {
81        setup_template();
82        let command = GenerateCommandImpl::new();
83        let actual = command.run("example".to_string(), "foo".to_string(), false);
84
85        assert!(actual.is_ok());
86        terradown_template();
87    }
88}