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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use std::ffi::OsString;
use std::path::PathBuf;
use std::process::Command;
use std::{env, fs};
use anyhow::Result;
use crate::commands::validate_worker_name;
use crate::settings::toml::{Manifest, Site, TargetType};
use crate::{commands, install};
pub fn generate(
name: &str,
template: &str,
target_type: Option<TargetType>,
site: bool,
) -> Result<()> {
validate_worker_name(name)?;
let new_name = if directory_exists(name).unwrap_or(true) {
match generate_name(name) {
Ok(val) => val,
Err(_) => {
log::debug!(
"Failed to auto-increment name for a new worker project, using '{}'",
name
);
String::from(name)
}
}
} else {
String::from(name)
};
log::info!("Generating a new worker project with name '{}'", new_name);
run_generate(&new_name, template)?;
let config_path = PathBuf::from("./").join(&new_name);
let generated_site = if site {
Some(Site::new("./public"))
} else {
None
};
Manifest::generate(new_name, target_type, &config_path, generated_site)?;
Ok(())
}
pub fn run_generate(name: &str, template: &str) -> Result<()> {
let binary_path = install::install_cargo_generate()?;
let args = ["generate", "--git", template, "--name", name, "--force"];
let command = command(binary_path, &args);
let command_name = format!("{:?}", command);
commands::run(command, &command_name)
}
fn generate_name(name: &str) -> Result<String> {
let mut num = 1;
let entry_names = read_current_dir()?;
let mut new_name = construct_name(name, num);
while entry_names.contains(&OsString::from(&new_name)) {
num += 1;
new_name = construct_name(name, num);
}
Ok(new_name)
}
fn read_current_dir() -> Result<Vec<OsString>> {
let current_dir = env::current_dir()?;
let mut entry_names = Vec::new();
for entry in fs::read_dir(current_dir)? {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
entry_names.push(entry.file_name());
}
}
Ok(entry_names)
}
fn directory_exists(dirname: &str) -> Result<bool> {
let entry_names = read_current_dir()?;
Ok(entry_names.contains(&OsString::from(dirname)))
}
fn construct_name(name: &str, num: i32) -> String {
format!("{}-{}", name, num)
}
fn command(binary_path: PathBuf, args: &[&str]) -> Command {
let mut c = if cfg!(target_os = "windows") {
let mut c = Command::new("cmd");
c.arg("/C");
c.arg(binary_path);
c
} else {
Command::new(binary_path)
};
c.args(args);
c
}