cargo_advent/functions/
generate_project.rs1use 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}