cargo_swift/commands/
init.rs1use askama::Template;
2use std::fmt::Display;
3use std::fs::{create_dir, write};
4use std::process::Stdio;
5
6use clap::ValueEnum;
7use execute::{command, Execute};
8
9use crate::console::{run_step, Config, Result};
10use crate::lib_type::LibType;
11use crate::templating;
12
13#[derive(ValueEnum, Debug, Clone)]
14#[value()]
15pub enum Vcs {
16 Git,
17 None,
18}
19
20impl Display for Vcs {
21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22 match self {
23 Self::Git => write!(f, "git"),
24 Self::None => write!(f, "none"),
25 }
26 }
27}
28
29pub fn run(
30 crate_name: String,
31 config: Config,
32 vcs: Vcs,
33 lib_type: LibType,
34 plain: bool,
35 macro_only: bool,
36) -> Result<()> {
37 run_step(&config, "Creating Rust library package...", || {
38 create_project(&crate_name, lib_type, plain, macro_only)
39 })?;
40
41 match vcs {
42 Vcs::Git => init_git_repository(&crate_name, &config)?,
43 Vcs::None => (),
44 };
45
46 Ok(())
47}
48
49fn create_project(
50 crate_name: &str,
51 lib_type: LibType,
52 plain: bool,
53 macro_only: bool,
54) -> Result<()> {
55 let namespace = crate_name.replace('-', "_");
58 let cargo_toml_content = templating::CargoToml {
59 crate_name,
60 namespace: &namespace,
61 lib_type: lib_type.identifier(),
62 macro_only,
63 };
64 let lib_rs_content = templating::LibRs { plain, macro_only };
65 let (udl_content, build_rs_content) = if !macro_only {
66 (
67 Some(templating::LibUdl {
68 namespace: &namespace,
69 plain,
70 }),
71 Some(templating::BuildRs {}),
72 )
73 } else {
74 (None, None)
75 };
76
77 write_project_files(
78 cargo_toml_content,
79 build_rs_content,
80 lib_rs_content,
81 udl_content,
82 crate_name,
83 )?;
84
85 Ok(())
86}
87
88fn write_project_files(
89 cargo_toml: templating::CargoToml,
90 build_rs: Option<templating::BuildRs>,
91 lib_rs: templating::LibRs,
92 lib_udl: Option<templating::LibUdl>,
93 crate_name: &str,
94) -> Result<()> {
95 create_dir(crate_name).map_err(|_| "Could not create directory for crate!")?;
96
97 write(
98 format!("{}/Cargo.toml", crate_name),
99 cargo_toml.render().unwrap(),
100 )
101 .map_err(|_| "Could not write Cargo.toml!")?;
102
103 if let Some(build_rs) = build_rs {
104 write(
105 format!("{}/build.rs", crate_name),
106 build_rs.render().unwrap(),
107 )
108 .expect("Could not write build.rs!");
109 }
110
111 create_dir(format!("{}/src", crate_name)).expect("Could not create src/ directory!");
112 write(
113 format!("{}/src/lib.rs", crate_name),
114 lib_rs.render().unwrap(),
115 )
116 .map_err(|_| "Could not write src/lib.rs!")?;
117
118 if let Some(lib_udl) = lib_udl {
119 write(
120 format!("{}/src/lib.udl", crate_name),
121 lib_udl.render().unwrap(),
122 )
123 .map_err(|_| "Could not write src/lib.udl!")?;
124 }
125
126 Ok(())
127}
128
129fn init_git_repository(crate_name: &str, config: &Config) -> Result<()> {
130 let gitignore_content = include_str!("../../templates/template.gitignore");
131 write(format!("{}/.gitignore", crate_name), gitignore_content)
132 .map_err(|_| "Could not write .gitignore!")?;
133
134 let git_status_output = command!("git status")
135 .stdout(Stdio::piped())
136 .stderr(Stdio::piped())
137 .execute_output()
138 .expect("Could not run git status!");
139
140 if let Some(0) = git_status_output.status.code() {
141 return Ok(());
143 }
144
145 run_step(config, "Initializing git repository...", || {
146 create_git_repo(crate_name)
147 })?;
148
149 Ok(())
150}
151
152fn create_git_repo(crate_name: &str) -> Result<()> {
153 command!("git init")
154 .current_dir(format!("./{crate_name}"))
155 .execute_check_exit_status_code(0)
156 .map_err(|_| "Could not initialize git repository!")?;
157 command!("git checkout -b main")
158 .current_dir(format!("./{crate_name}"))
159 .execute_check_exit_status_code(0)
160 .map_err(|_| "Could not checkout branch main!")?;
161
162 Ok(())
163}