1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use crate::config::{AnswerConfigError, CatalogError};
use crate::system::SystemError;
use crate::source::SourceError;
use crate::ArchetypeError;
use std::path::PathBuf;
use std::fmt::{Display, Formatter};
use std::error::Error;

#[derive(Debug, thiserror::Error)]
pub enum ArchetectError {
    #[error("Error in answer file `{path}`: {source}")]
    AnswerConfigError { path: String, source: AnswerConfigError },
    #[error(transparent)]
    ArchetypeError(#[from] ArchetypeError),
    #[error(transparent)]
    RenderError(#[from] RenderError),
    #[error(transparent)]
    SystemError(#[from] SystemError),
    #[error(transparent)]
    SourceError(#[from] SourceError),
    #[error(transparent)]
    CatalogError(#[from] CatalogError),
    #[error(transparent)]
    IoError(#[from] std::io::Error),
    #[error("Headless mode requires answers to be supplied for all variables, but no answer was supplied for the `{0}` \
    variable.")]
    HeadlessMissingAnswer(String),
    #[error("Headless mode attempted to use the default value for the `{identifier}` variable, however, {message}")]
    HeadlessInvalidDefault { identifier: String, default: String, message: String },
}

#[derive(Debug, thiserror::Error)]
pub enum RenderError {
    InvalidPathCharacters {
        path: PathBuf,
    },
    PathRenderError {
        path: PathBuf,
        source: crate::vendor::tera::Error,
    },
    FileRenderError {
        path: PathBuf,
        source: crate::vendor::tera::Error,
    },
    FileRenderIOError {
        path: PathBuf,
        source: std::io::Error,
    },
    StringRenderError {
        string: String,
        source: crate::vendor::tera::Error,
    },
    IOError {
        #[from]
        source: std::io::Error,
    },
}

impl Display for RenderError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            RenderError::InvalidPathCharacters { path } => {
                write!(f, "Invalid characters in path template `{:?}`", path)
            }
            RenderError::PathRenderError { path, source } => {
                write!(f, "Unable to render path `{:?}`: {}", path, extract_tera_message(source))
            }
            RenderError::FileRenderError { path, source } => {
                write!(f, "Unable to render file `{:?}`: {}", path, extract_tera_message(source))
            }
            RenderError::FileRenderIOError { path, source} => {
                write!(f, "Unable to render file `{:?}`: {}", path, source)
            }
            RenderError::StringRenderError { string, source } => {
                write!(f, "Unable to render string `{}`: {}", string, extract_tera_message(source))
            }
            RenderError::IOError { source } => {
                write!(f, "Rendering IO Error: {}", source)
            }
        }
    }
}

fn extract_tera_message(error: &crate::vendor::tera::Error) -> String {
    match error.source() {
        None => format!("{}", error),
        Some(source) => format!("{}", source)
    }
}