Skip to main content

cargo_faasta/
init.rs

1use clap::Args;
2use std::error::Error;
3use std::path::Path;
4use std::{env, fs, io};
5
6/// CLI arguments for the `init` command
7#[derive(Args, Debug)]
8pub struct NewArgs {
9    /// The name of the package to create
10    pub package_name: String,
11}
12
13pub const HTTP_CARGO_TOML: &str = include_str!("../template/notCargo.toml");
14pub const HTTP_LIB_RS: &str = include_str!("../template/lib.rs");
15pub fn handle_new(args: &NewArgs) -> Result<(), Box<dyn Error>> {
16    dbg!(&args);
17    let current_dir = env::current_dir()?;
18    let new_project_dir = current_dir.join(&args.package_name);
19
20    if new_project_dir.exists() && !args.package_name.is_empty() {
21        return Err(format!("Directory '{}' already exists", args.package_name).into());
22    }
23    if new_project_dir.join("Cargo.toml").exists() {
24        return Err(format!(
25            "Cargo.toml already exists in '{}'",
26            new_project_dir.display()
27        )
28        .into());
29    }
30    fs::create_dir_all(new_project_dir.join("src"))?;
31    let pkg_name = if args.package_name.is_empty() {
32        "axum_serverless"
33    } else {
34        &*args.package_name
35    };
36
37    write_files(&new_project_dir, HTTP_CARGO_TOML, HTTP_LIB_RS, pkg_name)?;
38
39    println!(
40        "Successfully created new Axum project '{}' at '{}'",
41        args.package_name,
42        new_project_dir.display()
43    );
44    Ok(())
45}
46
47/// Writes the embedded Cargo.toml & main.rs to disk,
48/// updating the `[package] name` in Cargo.toml to `package_name`.
49fn write_files(
50    project_dir: &Path,
51    cargo_toml_str: &str,
52    main_rs_str: &str,
53    package_name: &str,
54) -> io::Result<()> {
55    // 1. Write Cargo.toml
56    // EVENT_PATHS
57
58    let cargo_toml_path = project_dir.join("Cargo.toml");
59    let updated_cargo_toml = rewrite_package_name(cargo_toml_str, package_name);
60    fs::write(cargo_toml_path, updated_cargo_toml)?;
61
62    // 2. Write src/lib.rs
63    let main_rs_path = project_dir.join("src").join("lib.rs");
64    fs::write(main_rs_path, main_rs_str)?;
65
66    Ok(())
67}
68
69/// Replaces the line `name = "whatever"` inside `[package]` with the user-provided `package_name`.
70fn rewrite_package_name(toml_input: &str, package_name: &str) -> String {
71    let mut in_package = false;
72    let mut output = String::new();
73
74    for line in toml_input.lines() {
75        let trimmed = line.trim_start();
76        if trimmed.starts_with("[package]") {
77            in_package = true;
78            output.push_str(line);
79            output.push('\n');
80            continue;
81        }
82
83        if in_package && trimmed.starts_with("name =") {
84            output.push_str(&format!("name = \"{package_name}\"\n"));
85            in_package = false; // Only replace once
86            continue;
87        }
88
89        output.push_str(line);
90        output.push('\n');
91    }
92
93    output
94}