1use super::*;
2
3fn validate_project_name(name: &str) -> Result<(), NewError> {
13 if name.is_empty() {
14 return Err(NewError::InvalidName(ERROR_PROJECT_NAME_EMPTY.to_string()));
15 }
16 if name.contains('/') || name.contains('\\') || name.contains(':') {
17 return Err(NewError::InvalidName(
18 ERROR_PROJECT_NAME_INVALID_CHARACTERS.to_string(),
19 ));
20 }
21 if name.starts_with('.') || name.starts_with('-') {
22 return Err(NewError::InvalidName(
23 ERROR_PROJECT_NAME_INVALID_PREFIX.to_string(),
24 ));
25 }
26 Ok(())
27}
28
29async fn check_git_available() -> Result<(), NewError> {
35 let output: Output = Command::new("git")
36 .arg(GIT_FLAG_VERSION)
37 .stdout(Stdio::null())
38 .stderr(Stdio::null())
39 .output()
40 .await
41 .map_err(|_: io::Error| NewError::GitNotFound)?;
42 if output.status.success() {
43 Ok(())
44 } else {
45 Err(NewError::GitNotFound)
46 }
47}
48
49async fn git_clone(config: &NewProjectConfig) -> Result<(), NewError> {
59 let project_path: PathBuf = PathBuf::from(&config.project_name);
60 if project_path.exists() {
61 return Err(NewError::ProjectExists(config.project_name.clone()));
62 }
63 let output: Output = Command::new("git")
64 .arg(GIT_SUBCOMMAND_CLONE)
65 .arg(&config.template_url)
66 .arg(&config.project_name)
67 .stdout(Stdio::piped())
68 .stderr(Stdio::piped())
69 .output()
70 .await
71 .map_err(NewError::IoError)?;
72 if output.status.success() {
73 Ok(())
74 } else {
75 let stderr: String = String::from_utf8_lossy(&output.stderr).to_string();
76 Err(NewError::CloneFailed(stderr))
77 }
78}
79
80pub async fn execute_new(project_name: &str) -> Result<(), NewError> {
90 validate_project_name(project_name)?;
91 check_git_available().await?;
92 let config: NewProjectConfig = NewProjectConfig::new(project_name.to_string());
93 log::info!(
94 "Creating new project '{}' from template...",
95 config.project_name
96 );
97 git_clone(&config).await?;
98 log::info!("Successfully created project '{}'", config.project_name);
99 log::info!(" cd {}", config.project_name);
100 log::info!(" cargo build");
101 Ok(())
102}