diff --git a/src/embedded_template.rs b/src/embedded_template.rs index 0f72f0c..25872e7 100644 --- a/src/embedded_template.rs +++ b/src/embedded_template.rs @@ -27,18 +27,15 @@ impl EmbeddedTemplate { // Write Cargo.toml let cargo_toml_path = build_dir.join("Cargo.toml"); - fs::write(&cargo_toml_path, self.cargo_toml) - .context("Failed to write Cargo.toml")?; + fs::write(&cargo_toml_path, self.cargo_toml).context("Failed to write Cargo.toml")?; // Write build.rs let build_rs_path = build_dir.join("build.rs"); - fs::write(&build_rs_path, self.build_rs) - .context("Failed to write build.rs")?; + fs::write(&build_rs_path, self.build_rs).context("Failed to write build.rs")?; // Write src/main.rs let main_rs_path = src_dir.join("main.rs"); - fs::write(&main_rs_path, self.main_rs) - .context("Failed to write src/main.rs")?; + fs::write(&main_rs_path, self.main_rs).context("Failed to write src/main.rs")?; Ok(()) } diff --git a/src/executable.rs b/src/executable.rs index 128f85f..4c02f4e 100644 --- a/src/executable.rs +++ b/src/executable.rs @@ -17,68 +17,72 @@ pub fn create_self_extracting_executable( ) -> Result<()> { // Check if Rust toolchain is available if let Err(e) = RustToolchain::check_availability() { - eprintln!("\nError: {}", e); + eprintln!("\nError: {e}"); eprintln!("{}", RustToolchain::get_installation_instructions()); return Err(e); } - + let build_id = Uuid::new_v4().to_string(); - + // Create temporary directory for building let temp_dir = TempDir::new().context("Failed to create temporary directory")?; let build_dir = temp_dir.path(); - + // Copy template to build directory copy_template_to_build_dir(build_dir)?; - + // Write embedded data let zip_path = build_dir.join("embedded_data.zip"); fs::write(&zip_path, &zip_data).context("Failed to write embedded zip data")?; - + let build_id_path = build_dir.join("build_id.txt"); fs::write(&build_id_path, &build_id).context("Failed to write build ID")?; - + // Update Cargo.toml with app name update_cargo_toml(build_dir, app_name)?; - + // Build the executable build_executable(build_dir, output_path, app_name)?; - + Ok(()) } fn copy_template_to_build_dir(build_dir: &Path) -> Result<()> { // Use embedded template files instead of filesystem copy let template = EmbeddedTemplate::new(); - template.write_to_dir(build_dir) + template + .write_to_dir(build_dir) .context("Failed to write embedded template files to build directory")?; - + Ok(()) } - - fn update_cargo_toml(build_dir: &Path, app_name: &str) -> Result<()> { let cargo_toml_path = build_dir.join("Cargo.toml"); - let cargo_content = fs::read_to_string(&cargo_toml_path) - .context("Failed to read Cargo.toml")?; - + let cargo_content = + fs::read_to_string(&cargo_toml_path).context("Failed to read Cargo.toml")?; + // Replace the package name let updated_content = cargo_content.replace( r#"name = "banderole-app""#, - &format!(r#"name = "{}""#, sanitize_package_name(app_name)) + &format!(r#"name = "{}""#, sanitize_package_name(app_name)), ); - - fs::write(&cargo_toml_path, updated_content) - .context("Failed to write updated Cargo.toml")?; - + + fs::write(&cargo_toml_path, updated_content).context("Failed to write updated Cargo.toml")?; + Ok(()) } fn sanitize_package_name(name: &str) -> String { // Rust package names must be valid identifiers name.chars() - .map(|c| if c.is_alphanumeric() || c == '_' || c == '-' { c } else { '-' }) + .map(|c| { + if c.is_alphanumeric() || c == '_' || c == '-' { + c + } else { + '-' + } + }) .collect::() .trim_start_matches(|c: char| c.is_numeric() || c == '-') .to_string() @@ -87,48 +91,51 @@ fn sanitize_package_name(name: &str) -> String { fn build_executable(build_dir: &Path, output_path: &Path, app_name: &str) -> Result<()> { let current_platform = Platform::current(); let target_triple = get_target_triple(¤t_platform); - + // Ensure we have the target installed install_rust_target(&target_triple)?; - + // Build the executable let mut cmd = Command::new("cargo"); cmd.current_dir(build_dir) - .args(&["build", "--release", "--target", &target_triple]); - + .args(["build", "--release", "--target", &target_triple]); + let output = cmd.output().context("Failed to execute cargo build")?; - + if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); anyhow::bail!("Cargo build failed:\n{}", stderr); } - + // Get the sanitized package name to find the correct executable let package_name = sanitize_package_name(app_name); let executable_name = if current_platform.is_windows() { - format!("{}.exe", package_name) + format!("{package_name}.exe") } else { package_name }; - + let built_executable = build_dir .join("target") .join(&target_triple) .join("release") .join(executable_name); - + if !built_executable.exists() { - anyhow::bail!("Built executable not found at {}", built_executable.display()); + anyhow::bail!( + "Built executable not found at {}", + built_executable.display() + ); } - + // Ensure output directory exists if let Some(parent) = output_path.parent() { fs::create_dir_all(parent).context("Failed to create output directory")?; } - + fs::copy(&built_executable, output_path) .context("Failed to copy built executable to output path")?; - + // Set executable permissions on Unix systems #[cfg(unix)] { @@ -137,7 +144,7 @@ fn build_executable(build_dir: &Path, output_path: &Path, app_name: &str) -> Res perms.set_mode(0o755); fs::set_permissions(output_path, perms)?; } - + Ok(()) } @@ -155,4 +162,3 @@ fn get_target_triple(platform: &Platform) -> String { fn install_rust_target(target: &str) -> Result<()> { RustToolchain::ensure_target_installed(target) } - diff --git a/src/rust_toolchain.rs b/src/rust_toolchain.rs index 62fac39..0579734 100644 --- a/src/rust_toolchain.rs +++ b/src/rust_toolchain.rs @@ -8,9 +8,7 @@ impl RustToolchain { /// Check if Rust toolchain is available and properly configured pub fn check_availability() -> Result<()> { // Check if rustc is available - let rustc_output = Command::new("rustc") - .arg("--version") - .output(); + let rustc_output = Command::new("rustc").arg("--version").output(); match rustc_output { Ok(output) if output.status.success() => { @@ -25,9 +23,7 @@ impl RustToolchain { } // Check if cargo is available - let cargo_output = Command::new("cargo") - .arg("--version") - .output(); + let cargo_output = Command::new("cargo").arg("--version").output(); match cargo_output { Ok(output) if output.status.success() => { @@ -42,9 +38,7 @@ impl RustToolchain { } // Check if rustup is available (for target management) - let rustup_output = Command::new("rustup") - .arg("--version") - .output(); + let rustup_output = Command::new("rustup").arg("--version").output(); match rustup_output { Ok(output) if output.status.success() => { @@ -65,16 +59,16 @@ impl RustToolchain { pub fn ensure_target_installed(target: &str) -> Result<()> { // Check if target is already installed let output = Command::new("rustup") - .args(&["target", "list", "--installed"]) + .args(["target", "list", "--installed"]) .output() .context("Failed to check installed targets")?; let installed_targets = String::from_utf8_lossy(&output.stdout); if !installed_targets.contains(target) { - println!("Installing Rust target: {}", target); + println!("Installing Rust target: {target}"); let install_output = Command::new("rustup") - .args(&["target", "add", target]) + .args(["target", "add", target]) .output() .context("Failed to install Rust target")?; @@ -82,9 +76,9 @@ impl RustToolchain { let stderr = String::from_utf8_lossy(&install_output.stderr); anyhow::bail!("Failed to install target {}:\n{}", target, stderr); } - println!("Successfully installed target: {}", target); + println!("Successfully installed target: {target}"); } else { - println!("Target {} is already installed", target); + println!("Target {target} is already installed"); } Ok(()) @@ -92,8 +86,7 @@ impl RustToolchain { /// Get helpful installation instructions for the user pub fn get_installation_instructions() -> String { - format!( - r#" + r#" Rust toolchain is required to build portable executables. To install Rust: @@ -109,6 +102,6 @@ For automated installation: After installation, you can use banderole to create portable Node.js executables without requiring users to have Node.js or Rust installed. "# - ) + .to_string() } }