diff --git a/src/docker_client.rs b/src/docker_client.rs index 5f6c635..98975cd 100644 --- a/src/docker_client.rs +++ b/src/docker_client.rs @@ -5,16 +5,23 @@ pub struct DockerClient {} impl DockerClient { pub fn build_image( ruby_version: &str, - rails_version: &str, + maybe_rails_version: Option<&str>, user_id: Option, group_id: Option, + rebuild: bool, ) -> Command { let mut command = Command::new("docker"); command.arg("build"); + if rebuild { + command.arg("--no-cache"); + } + Self::set_build_arg(&mut command, "RUBY_VERSION", ruby_version); - Self::set_build_arg(&mut command, "RAILS_VERSION", rails_version); + if let Some(rails_version) = maybe_rails_version { + Self::set_build_arg(&mut command, "RAILS_VERSION", rails_version); + } if let Some(id) = user_id { Self::set_build_arg(&mut command, "USER_ID", &id.to_string()) @@ -25,14 +32,18 @@ impl DockerClient { command.arg("-t"); - Self::set_image_name(&mut command, ruby_version, rails_version); + Self::set_image_name(&mut command, ruby_version, maybe_rails_version); command.arg("-").stdin(Stdio::piped()); command } - pub fn run_image(ruby_version: &str, rails_version: &str, args: Vec) -> Command { + pub fn run_image( + ruby_version: &str, + rails_version: Option<&str>, + args: Vec, + ) -> Command { let mut command = Self::run(); Self::set_workdir(&mut command); @@ -42,7 +53,7 @@ impl DockerClient { command } - pub fn get_help(ruby_version: &str, rails_version: &str) -> Command { + pub fn get_help(ruby_version: &str, rails_version: Option<&str>) -> Command { let mut command = Self::run(); Self::set_image_name(&mut command, ruby_version, rails_version); @@ -76,8 +87,16 @@ impl DockerClient { .args(["-w", current_dir]); } - fn set_image_name(command: &mut Command, ruby_version: &str, rails_version: &str) { - command.arg(format!("rails-new-{}-{}", ruby_version, rails_version)); + fn set_image_name( + command: &mut Command, + ruby_version: &str, + maybe_rails_version: Option<&str>, + ) { + if let Some(rails_version) = maybe_rails_version { + command.arg(format!("rails-new-{}-{}", ruby_version, rails_version)); + } else { + command.arg(format!("rails-new-{}", ruby_version)); + } } fn set_rails_new(command: &mut Command, args: Vec) { @@ -116,7 +135,7 @@ mod tests { #[test] fn build_image() { - let command = DockerClient::build_image("3.2.3", "7.1.3", None, None); + let command = DockerClient::build_image("3.2.3", Some("7.1.3"), None, None, false); assert_eq!(command.get_program(), "docker"); @@ -139,7 +158,7 @@ mod tests { #[test] fn build_image_with_user_id() { - let command = DockerClient::build_image("3.2.3", "7.1.3", Some(1000), None); + let command = DockerClient::build_image("3.2.3", Some("7.1.3"), Some(1000), None, false); assert_eq!(command.get_program(), "docker"); @@ -164,7 +183,7 @@ mod tests { #[test] fn build_image_with_group_id() { - let command = DockerClient::build_image("3.2.3", "7.1.3", None, Some(1000)); + let command = DockerClient::build_image("3.2.3", Some("7.1.3"), None, Some(1000), false); assert_eq!(command.get_program(), "docker"); @@ -187,9 +206,75 @@ mod tests { ); } + #[test] + fn build_image_with_rebuild_flag() { + let command = DockerClient::build_image("3.2.3", Some("7.1.3"), None, None, true); + + let args: Vec<&OsStr> = command.get_args().collect(); + + assert_eq!( + args, + &[ + "build", + "--no-cache", + "--build-arg", + "RUBY_VERSION=3.2.3", + "--build-arg", + "RAILS_VERSION=7.1.3", + "-t", + "rails-new-3.2.3-7.1.3", + "-", + ] + ); + } + + #[test] + fn build_image_without_rails_version() { + let command = DockerClient::build_image("3.2.3", None, None, None, false); + + let args: Vec<&OsStr> = command.get_args().collect(); + + assert_eq!( + args, + &[ + "build", + "--build-arg", + "RUBY_VERSION=3.2.3", + "-t", + "rails-new-3.2.3", + "-", + ] + ); + } + + #[test] + fn build_image_with_both_ids() { + let command = DockerClient::build_image("3.2.3", Some("7.1.3"), Some(1000), Some(1000), false); + + let args: Vec<&OsStr> = command.get_args().collect(); + + assert_eq!( + args, + &[ + "build", + "--build-arg", + "RUBY_VERSION=3.2.3", + "--build-arg", + "RAILS_VERSION=7.1.3", + "--build-arg", + "USER_ID=1000", + "--build-arg", + "GROUP_ID=1000", + "-t", + "rails-new-3.2.3-7.1.3", + "-", + ] + ); + } + #[test] fn run_image() { - let command = DockerClient::run_image("3.2.3", "7.1.3", vec!["my_app".to_string()]); + let command = DockerClient::run_image("3.2.3", Some("7.1.3"), vec!["my_app".to_string()]); assert_eq!(command.get_program(), "docker"); @@ -216,9 +301,36 @@ mod tests { ); } + #[test] + fn run_image_without_rails_version() { + let command = DockerClient::run_image("3.2.3", None, vec!["my_app".to_string()]); + + let binding = current_dir().unwrap(); + let absolute_path = canonicalize_os_path(&binding).unwrap(); + let current_dir = absolute_path.to_str().unwrap(); + + let args: Vec<&OsStr> = command.get_args().collect(); + + assert_eq!( + args, + &[ + "run", + "--rm", + "-v", + &format!("{}:{}", current_dir, current_dir), + "-w", + current_dir, + "rails-new-3.2.3", + "rails", + "new", + "my_app", + ] + ); + } + #[test] fn get_help() { - let command = DockerClient::get_help("3.2.3", "7.1.3"); + let command = DockerClient::get_help("3.2.3", Some("7.1.3")); assert_eq!(command.get_program(), "docker"); diff --git a/src/main.rs b/src/main.rs index a753532..d32f260 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,15 +18,17 @@ fn main() { let cli = Cli::parse(); let ruby_version = cli.ruby_version; - let rails_version = cli.rails_version; + let rails_version = cli.rails_version.as_deref(); + let rebuild = cli.rebuild; // Run docker build --build-arg RUBY_VERSION=$RUBY_VERSION --build-arg RAILS_VERSION=$RAILS_VERSION -t rails-new-$RUBY_VERSION-$RAILS_VERSION // passing the content of DOCKERFILE to the command stdin let mut child = DockerClient::build_image( &ruby_version, - &rails_version, + rails_version, os_specific::get_user_id(), os_specific::get_group_id(), + rebuild, ) .spawn() .expect("Failed to execute process"); @@ -44,12 +46,12 @@ fn main() { match &cli.command { Some(Commands::RailsHelp {}) => { - command = DockerClient::get_help(&ruby_version, &rails_version) + command = DockerClient::get_help(&ruby_version, rails_version) } None => { // Run the image with docker run -v $(pwd):/$(pwd) -w $(pwd) rails-new-$RUBY_VERSION-$RAILS_VERSION rails new $@ - command = DockerClient::run_image(&ruby_version, &rails_version, cli.args) + command = DockerClient::run_image(&ruby_version, rails_version, cli.args) } } diff --git a/src/rails_new.rs b/src/rails_new.rs index bc7a27e..1c452ac 100644 --- a/src/rails_new.rs +++ b/src/rails_new.rs @@ -6,10 +6,12 @@ pub struct Cli { #[clap(trailing_var_arg = true, required = true)] /// arguments passed to `rails new` pub args: Vec, - #[clap(long, short = 'u', default_value = "3.4.1")] + #[clap(long, short = 'u', default_value = "latest")] pub ruby_version: String, - #[clap(long, short = 'r', default_value = "8.0.1")] - pub rails_version: String, + #[clap(long, short = 'r')] + pub rails_version: Option, + #[clap(long)] + pub rebuild: bool, #[command(subcommand)] pub command: Option, @@ -52,10 +54,8 @@ mod tests { let m = Cli::command().get_matches_from(vec!["rails-new", "my_app"]); let ruby_version = m.get_one::("ruby_version").unwrap(); - let rails_version = m.get_one::("rails_version").unwrap(); - assert_eq!(ruby_version, "3.4.1"); - assert_eq!(rails_version, "8.0.1"); + assert_eq!(ruby_version, "latest"); Ok(()) } @@ -73,4 +73,52 @@ mod tests { Ok(()) } + + #[test] + fn custom_ruby_version() -> Result<(), Box> { + use clap::CommandFactory; + + let m = Cli::command().get_matches_from(vec!["rails-new", "--ruby-version", "3.2.0", "my_app"]); + let ruby_version = m.get_one::("ruby_version").unwrap(); + assert_eq!(ruby_version, "3.2.0"); + + // Test short form + let m = Cli::command().get_matches_from(vec!["rails-new", "-u", "3.2.0", "my_app"]); + let ruby_version = m.get_one::("ruby_version").unwrap(); + assert_eq!(ruby_version, "3.2.0"); + + Ok(()) + } + + #[test] + fn rails_version_flag() -> Result<(), Box> { + use clap::CommandFactory; + + let m = Cli::command().get_matches_from(vec!["rails-new", "--rails-version", "7.1.0", "my_app"]); + let rails_version = m.get_one::("rails_version").unwrap(); + assert_eq!(rails_version, "7.1.0"); + + // Test short form + let m = Cli::command().get_matches_from(vec!["rails-new", "-r", "7.1.0", "my_app"]); + let rails_version = m.get_one::("rails_version").unwrap(); + assert_eq!(rails_version, "7.1.0"); + + Ok(()) + } + + #[test] + fn rebuild_flag() -> Result<(), Box> { + use clap::CommandFactory; + + let m = Cli::command().get_matches_from(vec!["rails-new", "--rebuild", "my_app"]); + let rebuild = m.get_flag("rebuild"); + assert!(rebuild); + + // Test default value (false) + let m = Cli::command().get_matches_from(vec!["rails-new", "my_app"]); + let rebuild = m.get_flag("rebuild"); + assert!(!rebuild); + + Ok(()) + } }