|
1 | | -use std::ffi::{OsStr, OsString}; |
| 1 | +use std::ffi::OsStr; |
2 | 2 | use std::fs::{self, File}; |
3 | 3 | use std::io::Write; |
4 | 4 | use std::path::Path; |
5 | | -use std::{env, slice}; |
6 | 5 |
|
7 | | -use anyhow::{Context, Result}; |
| 6 | +use anyhow::Result; |
8 | 7 | use liquid::model::Object; |
9 | | -use print_util::success; |
10 | 8 | use rust_i18n::t; |
11 | 9 |
|
12 | | -use super::get_selection::{get_user_selected, UserSelected}; |
13 | | -use super::{print_util, restricted_names, warning}; |
14 | | -use crate::NewCmd; |
| 10 | +use crate::printer::warning; |
| 11 | +use crate::{git, NewCmd}; |
| 12 | + |
| 13 | +mod selection; |
| 14 | +use selection::Selected; |
15 | 15 |
|
16 | 16 | #[derive(rust_embed::RustEmbed)] |
17 | | -#[folder = "./template"] |
| 17 | +#[folder = "./templates/classic"] |
18 | 18 | struct Template; |
19 | 19 |
|
20 | | -pub fn create_project(new_cmd: &NewCmd) -> Result<()> { |
21 | | - check_name(&new_cmd.project_name)?; |
22 | | - let project_name = &new_cmd.project_name; |
23 | | - let project_path = Path::new(project_name); |
24 | | - if project_path.exists() { |
25 | | - anyhow::bail!(t!( |
26 | | - "error_project_path_exist", |
27 | | - path = project_path.to_string_lossy() |
28 | | - )) |
29 | | - } |
30 | | - |
31 | | - check_path(project_path)?; |
32 | | - let Some(config) = get_user_selected()? else { |
| 20 | +pub fn generate(new_cmd: &NewCmd) -> Result<()> { |
| 21 | + let Some(config) = selection::get_selected()? else { |
33 | 22 | anyhow::bail!("cli quit!") |
34 | 23 | }; |
35 | | - match init_git(project_path) { |
| 24 | + let project_path = Path::new(&new_cmd.project_name); |
| 25 | + match git::init_repository(project_path) { |
36 | 26 | Ok(_) => {} |
37 | 27 | Err(e) => { |
38 | 28 | warning(t!("warning_init_git", error = e).replace(r"\n", "\n")); |
39 | 29 | } |
40 | 30 | } |
41 | 31 |
|
42 | 32 | create_files(project_path, config, new_cmd)?; |
43 | | - |
44 | | - after_print_info(project_name); |
45 | 33 | Ok(()) |
46 | 34 | } |
47 | 35 |
|
48 | | -fn after_print_info(project_name: &String) { |
49 | | - println!(); // a new line |
50 | | - success(t!("create_info", project_name = project_name).replace(r"\n", "\n")); |
51 | | - success(t!("create_success").replace(r"\n", "\n")); |
52 | | - success(t!("rust_version_tip")); |
53 | | - println!(); // a new line |
54 | | -} |
55 | | - |
56 | | -pub fn create_files( |
57 | | - project_path: &Path, |
58 | | - user_selected: UserSelected, |
59 | | - new_cmd: &NewCmd, |
60 | | -) -> Result<()> { |
61 | | - let code_gen = user_selected.code_gen.to_string(); |
| 36 | +fn create_files(project_path: &Path, user_selected: Selected, new_cmd: &NewCmd) -> Result<()> { |
62 | 37 | let db_lib = user_selected.db_lib.to_string(); |
63 | 38 | let db_type = user_selected.db_type.to_string(); |
64 | 39 | let data = liquid::object!({ |
65 | 40 | "project_name": new_cmd.project_name, |
66 | | - "code_gen":code_gen, |
67 | 41 | "db_type":db_type, |
68 | 42 | "db_lib":db_lib, |
69 | 43 | "main_log_message":t!("main_log_message"), |
@@ -177,77 +151,3 @@ fn write_file(tmpl: &[u8], file_path: &Path, data: &Object) -> Result<()> { |
177 | 151 | } |
178 | 152 | Ok(()) |
179 | 153 | } |
180 | | - |
181 | | -fn check_name(name: &str) -> Result<()> { |
182 | | - restricted_names::validate_package_name(name, "package name")?; |
183 | | - |
184 | | - if restricted_names::is_keyword(name) { |
185 | | - anyhow::bail!(t!("error_is_keyword", name = name)); |
186 | | - } |
187 | | - if restricted_names::is_conflicting_artifact_name(name) { |
188 | | - warning(t!("error_is_conflicting_artifact_name", name = name).replace(r"\n", "\n")); |
189 | | - } |
190 | | - if name == "test" { |
191 | | - anyhow::bail!(t!("error_equal_test").replace(r"\n", "\n")) |
192 | | - } |
193 | | - if ["core", "std", "alloc", "proc_macro", "proc-macro"].contains(&name) { |
194 | | - warning(t!("error_part_of_standard_library", name = name,).replace(r"\n", "\n")); |
195 | | - } |
196 | | - if restricted_names::is_windows_reserved(name) { |
197 | | - if cfg!(windows) { |
198 | | - anyhow::bail!(t!("error_is_windows_reserved", name = name),); |
199 | | - } else { |
200 | | - warning(t!("warning_is_windows_reserved", name = name).replace(r"\n", "\n")); |
201 | | - } |
202 | | - } |
203 | | - if restricted_names::is_non_ascii_name(name) { |
204 | | - warning(t!("warning_is_non_ascii_name", name = name).replace(r"\n", "\n")); |
205 | | - } |
206 | | - Ok(()) |
207 | | -} |
208 | | -fn check_path(path: &Path) -> Result<()> { |
209 | | - // warn if the path contains characters that will break `env::join_paths` |
210 | | - if join_paths(slice::from_ref(&OsStr::new(path)), "").is_err() { |
211 | | - let path = path.to_string_lossy(); |
212 | | - print_util::warning(t!("warning_invalid_path", path = path)); |
213 | | - } |
214 | | - Ok(()) |
215 | | -} |
216 | | - |
217 | | -pub fn join_paths<T: AsRef<OsStr>>(paths: &[T], env: &str) -> Result<OsString> { |
218 | | - env::join_paths(paths.iter()).with_context(|| { |
219 | | - let mut message = t!("erroe_join_paths", env = env).replace(r"\n", "\n"); |
220 | | - for path in paths { |
221 | | - use std::fmt::Write; |
222 | | - write!(&mut message, "\n {:?}", Path::new(path)).unwrap(); |
223 | | - } |
224 | | - message |
225 | | - }) |
226 | | -} |
227 | | - |
228 | | -pub fn init_git(project_path: &Path) -> Result<()> { |
229 | | - if !project_path.join(".git").exists() { |
230 | | - // Temporary fix to work around bug in libgit2 when creating a |
231 | | - // directory in the root of a posix filesystem. |
232 | | - // See: https://github.com/libgit2/libgit2/issues/5130 |
233 | | - create_dir_all(project_path)?; |
234 | | - git2::Repository::init(project_path)?; |
235 | | - write_ignore_file(project_path)?; |
236 | | - } |
237 | | - Ok(()) |
238 | | -} |
239 | | - |
240 | | -fn write_ignore_file(project_path: &Path) -> Result<()> { |
241 | | - let fp_ignore = project_path.join(".gitignore"); |
242 | | - let mut fp_ignore_file = File::create(fp_ignore)?; |
243 | | - fp_ignore_file.write_all(b"/target\n/migration/target")?; |
244 | | - Ok(()) |
245 | | -} |
246 | | - |
247 | | -/// Equivalent to [`create_dir_all`] with better error messages. |
248 | | -pub fn create_dir_all(p: impl AsRef<Path>) -> Result<()> { |
249 | | - let p = p.as_ref(); |
250 | | - fs::create_dir_all(p) |
251 | | - .with_context(|| format!("failed to create directory `{}`", p.display()))?; |
252 | | - Ok(()) |
253 | | -} |
0 commit comments