Skip to main content

cargo_advent/functions/
generate_project.rs

1use crate::AdventResult;
2use cargo_generate::{generate, GenerateArgs, TemplatePath, Vcs};
3use lazy_static::lazy_static;
4use regex::Regex;
5use std::path::PathBuf;
6use thiserror::Error;
7use tracing::debug;
8
9#[derive(Debug, Error)]
10pub enum GenerateProjectError {
11    #[error("Target directory ({0}) does not exist.")]
12    TargetDirectoryNotExists(String),
13    #[error(
14        "Project name must match contain only letters, numbers, underscore and dash, supplied: {0}"
15    )]
16    InvalidProjectName(String),
17    #[error(transparent)]
18    GenerateError(#[from] anyhow::Error),
19}
20
21lazy_static! {
22    pub static ref PROJECT_NAME_REGEX: Regex = Regex::new(r"^[a-zA-Z0-9_-]+$").unwrap();
23}
24
25pub fn generate_project(project_name: String, path: String, template: String) -> AdventResult<()> {
26    let path_buf = PathBuf::from(&path);
27    if !path_buf.is_dir() {
28        return Err(GenerateProjectError::TargetDirectoryNotExists(path).into());
29    };
30
31    debug!(path = path, "Checked path to be valid");
32
33    if !PROJECT_NAME_REGEX.is_match(&project_name) {
34        return Err(GenerateProjectError::InvalidProjectName(project_name).into());
35    }
36
37    debug!(
38        project_name = project_name.as_str(),
39        "Project name is valid"
40    );
41
42    let generate_args = GenerateArgs {
43        name: Some(project_name.clone()),
44        vcs: Some(Vcs::Git),
45        template_path: TemplatePath {
46            git: Some(template),
47            ..TemplatePath::default()
48        },
49        destination: Some(path_buf),
50        ..GenerateArgs::default()
51    };
52
53    debug!(args=?generate_args, "Generated args");
54
55    let path = generate(generate_args).map_err(GenerateProjectError::GenerateError)?;
56
57    debug!(project_path=?path, "Generated project");
58    Ok(())
59}