From c8c49db5e4a9c4564f7bded449d5b84002f28590 Mon Sep 17 00:00:00 2001 From: refcell Date: Wed, 18 Oct 2023 15:56:41 -0400 Subject: [PATCH] v0.1.2 --- Cargo.toml | 2 +- src/bins.rs | 27 +++++++++++++++++++++++--- src/cli.rs | 20 ++++++++++---------- src/lib.rs | 1 + src/libs.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/root.rs | 48 ++++++++++++++++++++++++----------------------- src/utils.rs | 18 ++++++++++++++++++ 7 files changed, 131 insertions(+), 38 deletions(-) create mode 100644 src/utils.rs diff --git a/Cargo.toml b/Cargo.toml index aa4d2f3..8255cde 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "amble" description = "First class, scalable rust project generator with batteries included." -version = "0.1.1" +version = "0.1.2" edition = "2021" license = "MIT" authors = ["refcell"] diff --git a/src/bins.rs b/src/bins.rs index 437a386..b09a73c 100644 --- a/src/bins.rs +++ b/src/bins.rs @@ -20,6 +20,13 @@ pub(crate) fn create( let src_path_buf = project_path_buf.join("src"); let main_rs_path_buf = project_path_buf.join("src").join("main.rs"); + if !dry { + tracing::debug!("Creating bin directory at {:?}", dir); + std::fs::create_dir_all(dir)?; + } + tree.as_deref_mut() + .map(|t| t.begin_child("bin".to_string())); + if !dry { tracing::debug!("Creating crate directory at {:?}", project_path_buf); std::fs::create_dir_all(&project_path_buf)?; @@ -54,7 +61,8 @@ pub(crate) fn create( .map(|t| t.add_empty_child("main.rs".to_string())); tree.as_deref_mut().map(|t| t.end_child()); // <- src/ - tree.map(|t| t.end_child()); // <- / + tree.as_deref_mut().map(|t| t.end_child()); // <- / + tree.map(|t| t.end_child()); // <- bin/ Ok(()) } @@ -75,17 +83,30 @@ mod tests { let project_path = bin_path_buf.join(project_name); create(&bin_path_buf, project_name, false, None).unwrap(); - // Check that the project directory was created. assert!(project_path.exists()); assert!(project_path.join("src").exists()); assert!(project_path.join("src").join("main.rs").exists()); assert!(project_path.join("Cargo.toml").exists()); - // Check that the contents of the main.rs file are correct. let mut main_rs = File::open(project_path.join("src").join("main.rs")).unwrap(); let mut main_rs_contents = String::new(); main_rs.read_to_string(&mut main_rs_contents).unwrap(); let expected_contents = "fn main() {\n println!(\"Hello World!\");\n}\n"; assert_eq!(main_rs_contents, expected_contents); } + + #[test] + fn test_create_dry_run() { + let dir = tempdir().unwrap(); + let dir_path_buf = dir.path().to_path_buf(); + let bin_path_buf = dir_path_buf.join("bin"); + let project_name = "example"; + let project_path = bin_path_buf.join(project_name); + create(&bin_path_buf, project_name, true, None).unwrap(); + + assert!(!project_path.exists()); + assert!(!project_path.join("src").exists()); + assert!(!project_path.join("src").join("main.rs").exists()); + assert!(!project_path.join("Cargo.toml").exists()); + } } diff --git a/src/cli.rs b/src/cli.rs index afad77d..6761f3b 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -13,20 +13,20 @@ pub struct Args { /// Dry run mode. /// If this flag is provided, the cli will no execute commands, /// printing the directories and files that would be created instead. - #[arg(long, short)] + #[arg(long)] dry_run: bool, /// The project name. /// This will be used for the binary application name. #[arg(long, short, default_value = "example")] - project_name: String, + name: String, /// The path to the project directory. /// By default, the current working directory is used. /// If any rust artifacts are detected in the specified /// or unspecified directory, an error will be thrown. #[arg(long, short, default_value = ".")] - project_dir: String, + dir: String, } /// CLI Entrypoint. @@ -34,22 +34,22 @@ pub fn run() -> Result<()> { let Args { v, dry_run, - project_name, - project_dir, + name, + dir, } = Args::parse(); crate::telemetry::init_tracing_subscriber(v)?; - let mut builder = TreeBuilder::new(project_dir.clone()); - let project_dir_path = std::path::Path::new(&project_dir); + let mut builder = TreeBuilder::new(dir.clone()); + let project_dir_path = std::path::Path::new(&dir); std::fs::create_dir_all(project_dir_path)?; - // todo: check if rust artifacts in the project directory. + crate::utils::check_artifacts(project_dir_path, dry_run)?; - crate::root::create(project_dir_path, &project_name, dry_run, Some(&mut builder))?; + crate::root::create(project_dir_path, &name, dry_run, Some(&mut builder))?; crate::bins::create( &project_dir_path.join("bin"), - &project_name, + &name, dry_run, Some(&mut builder), )?; diff --git a/src/lib.rs b/src/lib.rs index be11a0a..2221967 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,3 +20,4 @@ pub(crate) mod bins; pub(crate) mod libs; pub(crate) mod root; pub(crate) mod telemetry; +pub(crate) mod utils; diff --git a/src/libs.rs b/src/libs.rs index 04f4f56..98124b2 100644 --- a/src/libs.rs +++ b/src/libs.rs @@ -20,6 +20,13 @@ pub(crate) fn create( let cargo_toml_path_buf = lib_path_buf.join("Cargo.toml"); let lib_rs_path_buf = lib_path_buf.join("src").join("lib.rs"); + if !dry { + tracing::debug!("Creating crates directory at {:?}", dir); + std::fs::create_dir_all(dir)?; + } + tree.as_deref_mut() + .map(|t| t.begin_child("crates".to_string())); + if !dry { tracing::debug!("Creating crate directory at {:?}", lib_path_buf); std::fs::create_dir_all(&lib_path_buf)?; @@ -54,7 +61,51 @@ pub(crate) fn create( .map(|t| t.add_empty_child("main.rs".to_string())); tree.as_deref_mut().map(|t| t.end_child()); // <- src/ - tree.map(|t| t.end_child()); // <- / + tree.as_deref_mut().map(|t| t.end_child()); // <- / + tree.map(|t| t.end_child()); // <- crates Ok(()) } + +#[cfg(test)] +mod tests { + use super::*; + use std::fs::File; + use std::io::Read; + use tempfile::tempdir; + + #[test] + fn test_create() { + let dir = tempdir().unwrap(); + let dir_path_buf = dir.path().to_path_buf(); + let crates_path_buf = dir_path_buf.join("crates"); + let project_name = "example"; + let project_path = crates_path_buf.join(project_name); + create(&crates_path_buf, project_name, false, None).unwrap(); + + assert!(project_path.exists()); + assert!(project_path.join("src").exists()); + assert!(project_path.join("src").join("lib.rs").exists()); + assert!(project_path.join("Cargo.toml").exists()); + + let mut lib_rs = File::open(project_path.join("src").join("lib.rs")).unwrap(); + let mut lib_rs_contents = String::new(); + lib_rs.read_to_string(&mut lib_rs_contents).unwrap(); + assert!(lib_rs_contents.len() > 0); + } + + #[test] + fn test_create_dry_run() { + let dir = tempdir().unwrap(); + let dir_path_buf = dir.path().to_path_buf(); + let crates_path_buf = dir_path_buf.join("crates"); + let project_name = "example"; + let project_path = crates_path_buf.join(project_name); + create(&crates_path_buf, project_name, true, None).unwrap(); + + assert!(!project_path.exists()); + assert!(!project_path.join("src").exists()); + assert!(!project_path.join("src").join("lib.rs").exists()); + assert!(!project_path.join("Cargo.toml").exists()); + } +} diff --git a/src/root.rs b/src/root.rs index 007a562..59d82b2 100644 --- a/src/root.rs +++ b/src/root.rs @@ -11,40 +11,42 @@ pub(crate) fn create( dir: &Path, name: impl AsRef + std::fmt::Display, dry: bool, - mut tree: Option<&mut TreeBuilder>, + tree: Option<&mut TreeBuilder>, ) -> Result<()> { tracing::info!("Creating top level workspace artifacts for {}", name); - let cargo_toml_path_buf = dir.join("Cargo.toml"); - let crates_dir_path_buf = dir.join("crates"); - let bin_dir_path_buf = dir.join("bin"); - if !dry { tracing::debug!( "Creating crate Cargo.toml file as {:?}", - cargo_toml_path_buf + dir.join("Cargo.toml") ); - let mut cargo_toml = std::fs::File::create(&cargo_toml_path_buf)?; + let mut cargo_toml = std::fs::File::create(dir.join("Cargo.toml"))?; cargo_toml.write_all(include_bytes!("../templates/Cargo.toml"))?; } - tree.as_deref_mut() - .map(|t| t.add_empty_child("Cargo.toml".to_string())); + tree.map(|t| t.add_empty_child("Cargo.toml".to_string())); - if !dry { - tracing::debug!("Creating crates directory at {:?}", crates_dir_path_buf); - std::fs::create_dir_all(&crates_dir_path_buf)?; - } - tree.as_deref_mut() - .map(|t| t.add_empty_child("crates".to_string())); + Ok(()) +} - if !dry { - tracing::debug!("Creating crates directory at {:?}", bin_dir_path_buf); - std::fs::create_dir_all(&bin_dir_path_buf)?; +#[cfg(test)] +mod tests { + use super::*; + use tempfile::tempdir; + + #[test] + fn test_create() { + let dir = tempdir().unwrap(); + let dir_path_buf = dir.path().to_path_buf(); + create(&dir_path_buf, "example", false, None).unwrap(); + assert!(dir_path_buf.exists()); + assert!(dir_path_buf.join("Cargo.toml").exists()); } - tree.map(|t| t.add_empty_child("bin".to_string())); - - // tree.as_deref_mut().map(|t| t.end_child()); // <- src/ - // tree.as_deref_mut().map(|t| t.end_child()); // <- / - Ok(()) + #[test] + fn test_create_dry_run() { + let dir = tempdir().unwrap(); + let dir_path_buf = dir.path().to_path_buf(); + create(&dir_path_buf, "example", true, None).unwrap(); + assert!(!dir_path_buf.join("Cargo.toml").exists()); + } } diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..98b1987 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,18 @@ +use std::path::Path; + +use eyre::Result; +use tracing::instrument; + +/// Checks if rust artifacts are present in the given directory. +/// If `dry_run` is enabled, this method will not error if rust +/// artifacts are found. +#[instrument(name = "utils", skip(dir, dry_run))] +pub(crate) fn check_artifacts(dir: &Path, dry_run: bool) -> Result<()> { + if dry_run { + return Ok(()); + } + if dir.join("Cargo.toml").exists() { + eyre::bail!("Rust artifacts detected in the project directory"); + } + Ok(()) +}