diff --git a/src/args.rs b/src/args.rs index 52e8c8d..34b51ca 100644 --- a/src/args.rs +++ b/src/args.rs @@ -8,12 +8,14 @@ pub fn get_args() -> clap::ArgMatches { .about("Create a new installation medium ISO") .arg(arg!(--without_gui "Create ISO with just terminal")) .arg(arg!(--kb_layout "Create ISO with this keyboard layout")) - .arg(arg!(--kb_variant "Create ISO with this keyboard layout variant")), + .arg(arg!(--kb_variant "Create ISO with this keyboard layout variant")) + .arg(arg!(--install "Create ISO which automatically installs upon boot.")) ) .subcommand( command!() .name("install") .about("Install a system according to configuration") + .arg(arg!(-f --force "Install without confirming config")) .arg(arg!([config] "Config file").required(true)), ) .subcommand( diff --git a/src/create_iso.rs b/src/create_iso.rs index 3bdbd4b..b3a7da2 100644 --- a/src/create_iso.rs +++ b/src/create_iso.rs @@ -1,4 +1,6 @@ -use crate::{install::uncomment_tag, is_root, linux::run_command, print_status}; +use yansi::{Color, Paint}; + +use crate::{expect_yes, install::uncomment_tag, is_root, linux::run_command, print_status}; /// Build the `kxkbrc` file for the given `layout` and `variant pub fn build_kxkbrc(layout: &str, variant: Option<&str>) -> String { @@ -11,24 +13,42 @@ pub fn build_kxkbrc(layout: &str, variant: Option<&str>) -> String { res } -pub fn create_iso(without_gui: bool, kb_layout: &str, kb_variant: Option<&str>) { +pub fn create_iso( + without_gui: bool, + kb_layout: &str, + kb_variant: Option<&str>, + install: Option<&String>, +) { if !is_root() { eprintln!("Error: You need root to create an ISO"); std::process::exit(1); } + if install.is_some() { + println!( + "{} The --install option will create an ISO file which immidiately upon boot installs the selected config.", + "WARNING:".paint(Color::Yellow) + ); + print!("{}", "DISCLAIMER: I know that this could be dangerous and I myself am ultimately responsible for any damages [yes/no]: ".paint(Color::Red)); + expect_yes(); + } + if !std::fs::exists("./iso").unwrap() { let cmd = vec!["git", "clone", "https://git.hydrar.de/navos/iso"]; run_command(&cmd, None, false); } - if without_gui { + if without_gui || install.is_some() { std::fs::remove_file("./iso/airootfs/etc/systemd/system/display-manager.service").unwrap(); } else { print_status("Adding GUI packages"); uncomment_tag("#gui: ", "./iso/packages.x86_64"); } + if let Some(install_conf) = install { + setup_auto_install(&install_conf); + } + print_status("Setting keyboard layout"); std::fs::create_dir_all("./iso/airootfs/etc/skel/.config").unwrap(); std::fs::write( @@ -53,3 +73,13 @@ pub fn create_iso(without_gui: bool, kb_layout: &str, kb_variant: Option<&str>) std::fs::remove_dir_all("./work").unwrap(); } + +pub fn setup_auto_install(conf: &str) { + print_status("Setting up automatic install upon boot"); + std::fs::copy(conf, "./iso/airootfs/root/config.toml").unwrap(); + std::fs::write( + "./iso/airootfs/root/.zshrc", + "navinstall install --force /root/config.toml;sleep 30;reboot\n", + ) + .unwrap(); +} diff --git a/src/main.rs b/src/main.rs index da97f49..fae07a6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,8 +39,9 @@ fn main() { let kb_layout: &String = iso_args.get_one("kb_layout").unwrap_or(&kb_layout_default); let kb_variant: Option<&str> = iso_args.get_one("kb_variant").map(|x: &String| x.as_str()); + let auto_install_config: Option<&String> = iso_args.get_one("install"); - create_iso(without_gui, kb_layout, kb_variant); + create_iso(without_gui, kb_layout, kb_variant, auto_install_config); std::process::exit(0); } Some(("create-tar", _)) => { @@ -79,6 +80,7 @@ fn main() { } let config_file: &String = install_args.get_one("config").unwrap(); + let force = install_args.get_flag("force"); let config_content = std::fs::read_to_string(config_file); let conf: InstallConfig = match config_content { @@ -99,19 +101,10 @@ fn main() { } }; - print_config(&conf); - print!("Do you want to proceed with this configuration? (yes/no) "); - - let mut input = String::new(); - std::io::stdout().flush().expect("Error flushing stdout."); - std::io::stdin() - .read_line(&mut input) - .expect("Error reading input."); - let input = input.trim().to_lowercase(); - - if input != "yes" { - println!("Installation aborted."); - std::process::exit(0); + if !force { + print_config(&conf); + print!("Do you want to proceed with this configuration? (yes/no) "); + expect_yes(); } // Run the @@ -120,3 +113,18 @@ fn main() { _ => {} } } + +/// Read user input and exit if the input is not "yes" +pub fn expect_yes() { + let mut input = String::new(); + std::io::stdout().flush().expect("Error flushing stdout."); + std::io::stdin() + .read_line(&mut input) + .expect("Error reading input."); + let input = input.trim().to_lowercase(); + + if input != "yes" { + println!("Installation aborted."); + std::process::exit(0); + } +}