From 5960cfe430c744759f8cac155aed7e5a0ef49c29 Mon Sep 17 00:00:00 2001 From: Joakim Hulthe Date: Tue, 8 Sep 2026 22:50:39 +0200 Subject: [PATCH] Clean up smelly code in inject.rs --- src/build.rs | 5 ++--- src/inject.rs | 53 +++++++++++++++++---------------------------------- 2 files changed, 20 insertions(+), 38 deletions(-) diff --git a/src/build.rs b/src/build.rs index 881eaa9..189b9dc 100644 --- a/src/build.rs +++ b/src/build.rs @@ -76,9 +76,8 @@ fn build_inner( ) -> Result<()> { let config = inject::inspect_config(image)?; let command = cmd.unwrap_or_else(|| inject::infer_command(&config)); - let env = inject::env(&config); - let working_dir = inject::working_dir(&config); - let exec_script = inject::build_exec_script(&command, &env, working_dir); + let exec_script = + inject::build_exec_script(&command, &config.env, config.working_dir.as_deref()); inject::inject(mount_path, &exec_script)?; println!("Injected /slim/ (init + exec)"); diff --git a/src/inject.rs b/src/inject.rs index 7fbc152..ea3ea0b 100644 --- a/src/inject.rs +++ b/src/inject.rs @@ -3,6 +3,7 @@ use anyhow::{Context, Result, anyhow}; use serde::Deserialize; +use std::fmt::Write as _; use std::fs; use std::path::Path; @@ -14,13 +15,13 @@ const SLIM_INIT: &str = include_str!("scripts/slim-init.sh"); #[serde(rename_all = "PascalCase")] pub struct Config { #[serde(default)] - cmd: Option>, + pub cmd: Vec, #[serde(default)] - entrypoint: Option>, + pub entrypoint: Vec, #[serde(default)] - env: Option>, + pub env: Vec, #[serde(default)] - working_dir: Option, + pub working_dir: Option, } pub fn inspect_config(image: &str) -> Result { @@ -42,40 +43,21 @@ pub fn inspect_config(image: &str) -> Result { /// Concatenates ENTRYPOINT + CMD (Docker semantics). If neither is present, /// falls back to `/bin/sh`. pub fn infer_command(config: &Config) -> String { - let entrypoint = config.entrypoint.as_deref().filter(|e| !e.is_empty()); - let cmd = config.cmd.as_deref().filter(|c| !c.is_empty()); + let parts = config.entrypoint.iter().chain(config.cmd.iter()); + let parts: Vec<_> = parts.map(|s| s.as_str()).collect(); - let parts: Vec = match (entrypoint, cmd) { - (Some(ep), Some(c)) => { - let mut parts = ep.to_vec(); - parts.extend(c.iter().cloned()); - parts - } - (Some(ep), None) => ep.to_vec(), - (None, Some(c)) => c.to_vec(), - (None, None) => vec!["/bin/sh".to_string()], - }; - - if parts.len() == 3 && (parts[0] == "/bin/sh" || parts[0] == "sh") && parts[1] == "-c" { - parts[2].clone() - } else { - shell_join(&parts) + match &parts[..] { + [] => "/bin/sh".into(), + ["/bin/sh" | "sh", "-c", cmd] => cmd.to_string(), + _ => shell_join(&parts), } } -pub fn env(config: &Config) -> Vec { - config.env.clone().unwrap_or_default() -} - -pub fn working_dir(config: &Config) -> Option<&str> { - config.working_dir.as_deref() -} - fn shell_escape(s: &str) -> String { format!("'{}'", s.replace('\'', "'\\''")) } -fn shell_join(parts: &[String]) -> String { +fn shell_join(parts: &[&str]) -> String { parts .iter() .map(|p| shell_escape(p)) @@ -87,18 +69,19 @@ fn shell_join(parts: &[String]) -> String { pub fn build_exec_script(command: &str, env: &[String], working_dir: Option<&str>) -> String { let mut lines = String::from("#!/bin/sh\n"); if let Some(dir) = working_dir.filter(|d| !d.is_empty()) { - lines.push_str(&format!("cd {} 2>/dev/null\n", shell_escape(dir))); + _ = writeln!(&mut lines, "cd {} 2>/dev/null", shell_escape(dir)); } for var in env { if let Some((key, val)) = var.split_once('=') { - lines.push_str(&format!( - "export {}={}\n", + _ = writeln!( + &mut lines, + "export {}={}", shell_escape(key), shell_escape(val) - )); + ); } } - lines.push_str(&format!("exec /bin/sh -c {}\n", shell_escape(command))); + _ = writeln!(&mut lines, "exec /bin/sh -c {}", shell_escape(command)); lines }