cargo_swift/commands/
init.rs

1use 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 manifest = Manifest::from_str(include_str!("../../Cargo.toml")).unwrap();
56    // let cargo_swift_version = manifest.package().version();
57    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        // Already in a git repository
142        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}