Skip to content

Commit

Permalink
feat: interactive project initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
Procrat committed Nov 30, 2022
1 parent e3fb067 commit 898c264
Show file tree
Hide file tree
Showing 6 changed files with 323 additions and 210 deletions.
42 changes: 42 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cargo-shuttle/Cargo.toml
Expand Up @@ -18,6 +18,7 @@ clap = { version = "3.2.17", features = ["derive", "env"] }
clap_complete = "3.2.5"
crossbeam-channel = "0.5.6"
crossterm = "0.25.0"
dialoguer = { version = "0.10.2", features = ["fuzzy-select"] }
dirs = "4.0.0"
flate2 = "1.0.24"
futures = "0.3.23"
Expand Down
95 changes: 94 additions & 1 deletion cargo-shuttle/src/args.rs
Expand Up @@ -10,6 +10,8 @@ use clap_complete::Shell;
use shuttle_common::project::ProjectName;
use uuid::Uuid;

use crate::init::Framework;

#[derive(Parser)]
#[clap(
version,
Expand Down Expand Up @@ -113,7 +115,7 @@ pub enum ProjectCommand {
Status,
}

#[derive(Parser)]
#[derive(Parser, Clone, Debug)]
pub struct LoginArgs {
/// api key for the shuttle platform
#[clap(long)]
Expand Down Expand Up @@ -173,6 +175,11 @@ pub struct InitArgs {
/// Initialize with thruster framework
#[clap(long, conflicts_with_all = &["axum", "rocket", "tide", "tower", "poem", "warp", "salvo", "serenity"])]
pub thruster: bool,
/// Whether to create the environment for this project on Shuttle
#[clap(long)]
pub new: bool,
#[clap(flatten)]
pub login_args: LoginArgs,
/// Path to initialize a new shuttle project
#[clap(
parse(try_from_os_str = parse_init_path),
Expand All @@ -181,6 +188,32 @@ pub struct InitArgs {
pub path: PathBuf,
}

impl InitArgs {
pub fn framework(&self) -> Option<Framework> {
if self.axum {
Some(Framework::Axum)
} else if self.rocket {
Some(Framework::Rocket)
} else if self.tide {
Some(Framework::Tide)
} else if self.tower {
Some(Framework::Tower)
} else if self.poem {
Some(Framework::Poem)
} else if self.salvo {
Some(Framework::Salvo)
} else if self.serenity {
Some(Framework::Serenity)
} else if self.warp {
Some(Framework::Warp)
} else if self.thruster {
Some(Framework::Thruster)
} else {
None
}
}
}

// Helper function to parse and return the absolute path
fn parse_path(path: &OsStr) -> Result<PathBuf, io::Error> {
canonicalize(path).map_err(|e| {
Expand All @@ -198,3 +231,63 @@ fn parse_init_path(path: &OsStr) -> Result<PathBuf, io::Error> {

parse_path(path)
}

#[cfg(test)]
mod tests {
use super::*;

fn init_args_factory(framework: &str) -> InitArgs {
let mut init_args = InitArgs {
axum: false,
rocket: false,
tide: false,
tower: false,
poem: false,
salvo: false,
serenity: false,
warp: false,
thruster: false,
new: false,
login_args: LoginArgs { api_key: None },
path: PathBuf::new(),
};

match framework {
"axum" => init_args.axum = true,
"rocket" => init_args.rocket = true,
"tide" => init_args.tide = true,
"tower" => init_args.tower = true,
"poem" => init_args.poem = true,
"salvo" => init_args.salvo = true,
"serenity" => init_args.serenity = true,
"warp" => init_args.warp = true,
"thruster" => init_args.thruster = true,
_ => unreachable!(),
}

init_args
}

#[test]
fn test_init_args_framework() {
let framework_strs = vec![
"axum", "rocket", "tide", "tower", "poem", "salvo", "serenity", "warp", "thruster",
];
let frameworks: Vec<Framework> = vec![
Framework::Axum,
Framework::Rocket,
Framework::Tide,
Framework::Tower,
Framework::Poem,
Framework::Salvo,
Framework::Serenity,
Framework::Warp,
Framework::Thruster,
];

for (framework_str, expected_framework) in framework_strs.into_iter().zip(frameworks) {
let framework = init_args_factory(framework_str).framework();
assert_eq!(framework, Some(expected_framework));
}
}
}

0 comments on commit 898c264

Please sign in to comment.