From 152551ec927e46c10b7d6682163b9403570ec01f Mon Sep 17 00:00:00 2001 From: trivernis Date: Wed, 20 Apr 2022 12:05:48 +0200 Subject: [PATCH] Change argument parsing to use clap v3 derive Signed-off-by: trivernis --- .idea/.gitignore | 8 + .idea/discord.xml | 7 + .idea/jade.iml | 11 ++ .idea/modules.xml | 8 + .idea/vcs.xml | 6 + Cargo.lock | 140 ++++++++++++++---- Cargo.toml | 4 +- src/args.rs | 188 ++++++++++++++++++++++++ src/functions/base.rs | 15 +- src/functions/desktops.rs | 289 ++++++++++++++++++++----------------- src/functions/partition.rs | 218 ++++++++++++++++------------ src/internal/config.rs | 47 +++--- src/internal/mod.rs | 4 +- src/internal/strings.rs | 2 +- src/main.rs | 253 +++++++------------------------- 15 files changed, 703 insertions(+), 497 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/discord.xml create mode 100644 .idea/jade.iml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 src/args.rs diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..d8e9561 --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/jade.iml b/.idea/jade.iml new file mode 100644 index 0000000..c254557 --- /dev/null +++ b/.idea/jade.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..9d08f4e --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index afc0079..8ff7633 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - [[package]] name = "atty" version = "0.2.14" @@ -22,6 +13,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "bitflags" version = "1.3.2" @@ -30,19 +27,55 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "clap" -version = "2.34.0" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "3124f3f75ce09e22d1410043e1e24f2ecc44fad3afe4f08408f1f7663d68da2b" dependencies = [ - "ansi_term", "atty", "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "lazy_static", "strsim", + "termcolor", "textwrap", - "unicode-width", - "vec_map", ] +[[package]] +name = "clap_derive" +version = "3.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "189ddd3b5d32a70b35e7686054371742a937b0d99128e76dde6340210e966669" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -52,6 +85,16 @@ dependencies = [ "libc", ] +[[package]] +name = "indexmap" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "itoa" version = "1.0.1" @@ -67,12 +110,48 @@ dependencies = [ "serde_json", ] +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" version = "1.0.36" @@ -130,9 +209,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" @@ -146,19 +225,19 @@ dependencies = [ ] [[package]] -name = "textwrap" -version = "0.11.0" +name = "termcolor" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ - "unicode-width", + "winapi-util", ] [[package]] -name = "unicode-width" -version = "0.1.9" +name = "textwrap" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "unicode-xid" @@ -167,10 +246,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] -name = "vec_map" -version = "0.8.2" +name = "version_check" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "winapi" @@ -188,6 +267,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 5b06c68..367f85b 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -clap = "2.34.0" +clap = {version = "3.1.10", features = ["derive"] } serde_json = "1.0.59" -serde = { version = "1.0.117", features = [ "derive" ] } \ No newline at end of file +serde = { version = "1.0.117", features = [ "derive" ] } diff --git a/src/args.rs b/src/args.rs new file mode 100644 index 0000000..99b9ae4 --- /dev/null +++ b/src/args.rs @@ -0,0 +1,188 @@ +use clap::{ArgEnum, Args, Parser, Subcommand}; +use serde::{Deserialize, Serialize}; +use std::path::PathBuf; + +#[derive(Debug, Parser)] +#[clap(name="jade", version=env!("CARGO_PKG_VERSION"), about=env!("CARGO_PKG_DESCRIPTION"), author=env!("CARGO_PKG_AUTHORS"))] +pub struct Opt { + #[clap(subcommand)] + pub command: Command, +} + +#[derive(Debug, Subcommand)] +pub enum Command { + /// Partition the install destination + #[clap(name = "partition")] + Partition(PartitionArgs), + + /// Install base packages + #[clap(name = "install-base")] + InstallBase, + + /// Generate fstab file for mounting partitions + #[clap(name = "genfstab")] + GenFstab, + + /// Setup timeshift + #[clap(name = "setup-timeshift")] + SetupTimeshift, + + /// Install the bootloader + #[clap(name = "bootloader")] + Bootloader { + #[clap(subcommand)] + subcommand: BootloaderSubcommand, + }, + + /// Set locale stuff + #[clap(name = "locale")] + Locale(LocaleArgs), + + /// Set networking stuff + #[clap(name = "networking")] + Networking(NetworkingArgs), + + /// Configure users and passwords + #[clap(name = "users")] + Users { + #[clap(subcommand)] + subcommand: UsersSubcommand, + }, + + /// Install the nix package manager + #[clap(name = "nix")] + Nix, + + /// Read jade installation config + #[clap(name = "config")] + Config { + /// The config to read + config: PathBuf, + }, + + #[clap(name = "desktops")] + Desktops { + /// The desktop setup to use + #[clap(arg_enum)] + desktop: DesktopSetup, + }, +} + +#[derive(Debug, Args)] +pub struct PartitionArgs { + /// If jade should automatically partition (mode = auto) + /// or the user manually partitioned it (mode = manual) + #[clap(arg_enum)] + pub mode: PartitionMode, + + /// The device to partition + #[clap(required_if_eq("mode", "PartitionMode::Manual"))] + pub device: PathBuf, + + /// If the install destination should be partitioned with EFI + #[clap(long)] + pub efi: bool, +} + +#[derive(Debug, ArgEnum, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Serialize, Deserialize)] +pub enum PartitionMode { + #[clap(name = "auto")] + Auto, + #[clap(name = "manual")] + Manual, +} + +#[derive(Debug, Subcommand)] +pub enum BootloaderSubcommand { + /// Install grub in efi mode + #[clap(name = "grub-efi")] + GrubEfi { + /// The directory to install the EFI bootloader to + efidir: PathBuf, + }, + + /// Install grub in legacy (BIOS) mode + #[clap(name = "grub-legacy")] + GrubLegacy { + /// The device to install the bootloader to + device: PathBuf, + }, +} + +#[derive(Debug, Args)] +pub struct LocaleArgs { + /// The keyboard layout to use + pub keyboard: String, + + /// The timezone to use + pub timezone: String, + + /// The locales to set + pub locales: Vec, +} + +#[derive(Debug, Args)] +pub struct NetworkingArgs { + /// The hostname to assign to the system + pub hostname: String, + + /// Whether ipv6 should be enabled + #[clap(long)] + pub ipv6: bool, +} + +#[derive(Debug, Subcommand)] +pub enum UsersSubcommand { + /// Create a new user + #[clap(name="new-user", aliases=&["newUser"])] + NewUser(NewUserArgs), + + /// Set the password of the root user + #[clap(name="root-password", aliases=&["root-pass", "rootPass"])] + RootPass { + /// The password to set. NOTE: Takes hashed password, use `openssl passwd -1 ` to generate the hash. + password: String, + }, +} + +#[derive(Debug, Args)] +pub struct NewUserArgs { + /// The name of the user to create + pub username: String, + + /// If the user should have root privileges + #[clap(long, aliases=&["has-root"])] + pub hasroot: bool, + + /// The password to set. NOTE: Takes hashed password, use `openssl passwd -1 ` to generate the hash. + /// When not providing a password openssl jumps into an interactive masked input mode allowing you to hide your password + /// from the terminal history. + pub password: String, +} + +#[derive(Debug, ArgEnum, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Serialize, Deserialize)] +pub enum DesktopSetup { + #[clap(name = "onxy")] + Onyx, + + #[clap(name = "gnome")] + Gnome, + + #[clap(name = "kde")] + Kde, + + #[clap(name = "budgie")] + Budgie, + + #[clap(name = "cinnamon")] + Cinnamon, + + #[clap(name = "mate")] + Mate, + + #[clap(name = "xfce")] + Xfce, + + #[clap(name = "enlightenment")] + Enlightenment, +} diff --git a/src/functions/base.rs b/src/functions/base.rs index c3ab418..a5667d2 100755 --- a/src/functions/base.rs +++ b/src/functions/base.rs @@ -1,5 +1,6 @@ use crate::internal::exec::*; use crate::internal::*; +use std::path::PathBuf; pub fn install_base_packages() { std::fs::create_dir_all("/mnt/etc").unwrap(); @@ -36,8 +37,12 @@ pub fn genfstab() { ); } -pub fn install_bootloader_efi(efidir: &str) { +pub fn install_bootloader_efi(efidir: PathBuf) { install::install(vec!["grub", "efibootmgr", "grub-btrfs"]); + if !efidir.exists() { + crash(format!("The efidir {efidir:?} doesn't exist"), 1); + } + let efidir = efidir.to_string_lossy().to_string(); exec_eval( exec_chroot( "grub-install", @@ -59,8 +64,12 @@ pub fn install_bootloader_efi(efidir: &str) { ); } -pub fn install_bootloader_legacy(device: &str) { +pub fn install_bootloader_legacy(device: PathBuf) { install::install(vec!["grub", "grub-btrfs"]); + if !device.exists() { + crash(format!("The device {device:?} does not exist"), 1); + } + let device = device.to_string_lossy().to_string(); exec_eval( exec_chroot( "grub-install", @@ -87,4 +96,4 @@ pub fn setup_timeshift() { pub fn install_homemgr() { install(vec!["nix"]); -} \ No newline at end of file +} diff --git a/src/functions/desktops.rs b/src/functions/desktops.rs index 5ba9744..5773ad5 100755 --- a/src/functions/desktops.rs +++ b/src/functions/desktops.rs @@ -1,143 +1,23 @@ +use crate::args::DesktopSetup; use crate::internal::exec::*; use crate::internal::*; -pub fn choose_pkgs(desktop_setup: &str) { - log(format!("Installing {}", desktop_setup)); - match desktop_setup.to_lowercase().as_str() { - "onyx" => { - install(vec![ - "xorg", - "onyx", - "lightdm", - "lightdm-gtk-greeter", - "lightdm-gtk-greeter-settings", - ]); - files_eval( - files::append_file( - "/mnt/etc/lightdm/lightdm.conf", - "[SeatDefaults]\ngreeter-session=lightdm-gtk-greeter\n", - ), - "Add lightdm greeter", - ); - enable_dm("lightdm"); - } - "gnome" => { - install(vec![ - "xorg", - "gnome", - "gnome-tweaks", - "chrome-gnome-shell", - "gdm", - ]); - enable_dm("gdm"); - } - "kde" => { - install(vec![ - "xorg", - "plasma", - "plasma-wayland-session", - "kde-utilities", - "kde-system", - "sddm", - ]); - enable_dm("sddm"); - } - "budgie" => { - install(vec![ - "xorg", - "budgie-desktop", - "gnome", - "lightdm", - "lightdm-gtk-greeter", - "lightdm-gtk-greeter-settings", - ]); - files_eval( - files::append_file( - "/mnt/etc/lightdm/lightdm.conf", - "[SeatDefaults]\ngreeter-session=lightdm-gtk-greeter\n", - ), - "Add lightdm greeter", - ); - enable_dm("lightdm"); - } - "cinnamon" => { - install(vec![ - "xorg", - "cinnamon", - "lightdm", - "lightdm-gtk-greeter", - "lightdm-gtk-greeter-settings", - "metacity", - "gnome-shell", - ]); - files_eval( - files::append_file( - "/mnt/etc/lightdm/lightdm.conf", - "[SeatDefaults]\ngreeter-session=lightdm-gtk-greeter\n", - ), - "Add lightdm greeter", - ); - enable_dm("lightdm"); - } - "mate" => { - install(vec![ - "xorg", - "mate", - "lightdm", - "lightdm-gtk-greeter", - "lightdm-gtk-greeter-settings", - "mate-extra", - ]); - files_eval( - files::append_file( - "/mnt/etc/lightdm/lightdm.conf", - "[SeatDefaults]\ngreeter-session=lightdm-gtk-greeter\n", - ), - "Add lightdm greeter", - ); - enable_dm("lightdm"); - } - "xfce" => { - install(vec![ - "xorg", - "xfce4", - "lightdm", - "lightdm-gtk-greeter", - "lightdm-gtk-greeter-settings", - "xfce4-goodies", - ]); - files_eval( - files::append_file( - "/mnt/etc/lightdm/lightdm.conf", - "[SeatDefaults]\ngreeter-session=lightdm-gtk-greeter\n", - ), - "Add lightdm greeter", - ); - enable_dm("lightdm"); - } - "enlightenment" => { - install(vec![ - "xorg", - "enlightenment", - "lightdm", - "lightdm-gtk-greeter", - "lightdm-gtk-greeter-settings", - "terminology", - ]); - files_eval( - files::append_file( - "/mnt/etc/lightdm/lightdm.conf", - "[SeatDefaults]\ngreeter-session=lightdm-gtk-greeter\n", - ), - "Add lightdm greeter", - ); - enable_dm("lightdm"); - } - - _ => { - crash("Unknown desktop setup".to_string(), 1); - } +pub fn install_desktop_setup(desktop_setup: DesktopSetup) { + log(format!("Installing {:?}", desktop_setup)); + match desktop_setup { + DesktopSetup::Onyx => install_onyx(), + DesktopSetup::Gnome => install_gnome(), + DesktopSetup::Kde => install_kde(), + DesktopSetup::Budgie => install_budgie(), + DesktopSetup::Cinnamon => install_cinnamon(), + DesktopSetup::Mate => install_mate(), + DesktopSetup::Xfce => install_xfce(), + DesktopSetup::Enlightenment => install_enlightenment(), } + install_networkmanager(); +} + +fn install_networkmanager() { install(vec!["networkmanager"]); exec_eval( exec_chroot( @@ -148,6 +28,143 @@ pub fn choose_pkgs(desktop_setup: &str) { ); } +fn install_enlightenment() { + install(vec![ + "xorg", + "enlightenment", + "lightdm", + "lightdm-gtk-greeter", + "lightdm-gtk-greeter-settings", + "terminology", + ]); + files_eval( + files::append_file( + "/mnt/etc/lightdm/lightdm.conf", + "[SeatDefaults]\ngreeter-session=lightdm-gtk-greeter\n", + ), + "Add lightdm greeter", + ); + enable_dm("lightdm"); +} + +fn install_xfce() { + install(vec![ + "xorg", + "xfce4", + "lightdm", + "lightdm-gtk-greeter", + "lightdm-gtk-greeter-settings", + "xfce4-goodies", + ]); + files_eval( + files::append_file( + "/mnt/etc/lightdm/lightdm.conf", + "[SeatDefaults]\ngreeter-session=lightdm-gtk-greeter\n", + ), + "Add lightdm greeter", + ); + enable_dm("lightdm"); +} + +fn install_mate() { + install(vec![ + "xorg", + "mate", + "lightdm", + "lightdm-gtk-greeter", + "lightdm-gtk-greeter-settings", + "mate-extra", + ]); + files_eval( + files::append_file( + "/mnt/etc/lightdm/lightdm.conf", + "[SeatDefaults]\ngreeter-session=lightdm-gtk-greeter\n", + ), + "Add lightdm greeter", + ); + enable_dm("lightdm"); +} + +fn install_cinnamon() { + install(vec![ + "xorg", + "cinnamon", + "lightdm", + "lightdm-gtk-greeter", + "lightdm-gtk-greeter-settings", + "metacity", + "gnome-shell", + ]); + files_eval( + files::append_file( + "/mnt/etc/lightdm/lightdm.conf", + "[SeatDefaults]\ngreeter-session=lightdm-gtk-greeter\n", + ), + "Add lightdm greeter", + ); + enable_dm("lightdm"); +} + +fn install_budgie() { + install(vec![ + "xorg", + "budgie-desktop", + "gnome", + "lightdm", + "lightdm-gtk-greeter", + "lightdm-gtk-greeter-settings", + ]); + files_eval( + files::append_file( + "/mnt/etc/lightdm/lightdm.conf", + "[SeatDefaults]\ngreeter-session=lightdm-gtk-greeter\n", + ), + "Add lightdm greeter", + ); + enable_dm("lightdm"); +} + +fn install_kde() { + install(vec![ + "xorg", + "plasma", + "plasma-wayland-session", + "kde-utilities", + "kde-system", + "sddm", + ]); + enable_dm("sddm"); +} + +fn install_gnome() { + install(vec![ + "xorg", + "gnome", + "gnome-tweaks", + "chrome-gnome-shell", + "gdm", + ]); + enable_dm("gdm"); +} + +fn install_onyx() { + install(vec![ + "xorg", + "onyx", + "lightdm", + "lightdm-gtk-greeter", + "lightdm-gtk-greeter-settings", + ]); + files_eval( + files::append_file( + "/mnt/etc/lightdm/lightdm.conf", + "[SeatDefaults]\ngreeter-session=lightdm-gtk-greeter\n", + ), + "Add lightdm greeter", + ); + enable_dm("lightdm"); +} + fn enable_dm(dm: &str) { log(format!("Enabling {}", dm)); exec_eval( diff --git a/src/functions/partition.rs b/src/functions/partition.rs index 3f07509..f7a4045 100755 --- a/src/functions/partition.rs +++ b/src/functions/partition.rs @@ -1,112 +1,134 @@ +use crate::args::PartitionMode; use crate::internal::exec::*; use crate::internal::*; +use std::path::PathBuf; -pub fn partition(device: &str, mode: &str, efi: bool) { - if mode == "manual" { - log("Manual partitioning".to_string()); - } else { - log(format!("automatically partitioning {}", device)); - if efi { - exec_eval( - exec( - "parted", - vec![ - String::from("-s"), - String::from(device), - String::from("mklabel"), - String::from("gpt"), - ], - ), - format!("create gpt label on {}", device).as_str(), - ); - exec_eval( - exec( - "parted", - vec![ - String::from("-s"), - String::from(device), - String::from("mkpart"), - String::from("fat32"), - String::from("0"), - String::from("300"), - ], - ), - "create EFI partition", - ); - exec_eval( - exec( - "parted", - vec![ - String::from("-s"), - String::from(device), - String::from("mkpart"), - String::from("btrfs"), - String::from("300"), - String::from("100%"), - ], - ), - "Create btrfs root partition", - ); - } else { - exec_eval( - exec( - "parted", - vec![ - String::from("-s"), - String::from(device), - String::from("mklabel"), - String::from("msdos"), - ], - ), - format!("Create msdos label on {}", device).as_str(), - ); - exec_eval( - exec( - "parted", - vec![ - String::from("-s"), - String::from(device), - String::from("mkpart"), - String::from("primary"), - String::from("ext4"), - String::from("1MIB"), - String::from("512MIB"), - ], - ), - "create bios boot partition", - ); - exec_eval( - exec( - "parted", - vec![ - String::from("-s"), - String::from(device), - String::from("mkpart"), - String::from("primary"), - String::from("btrfs"), - String::from("512MIB"), - String::from("100%"), - ], - ), - "create btrfs root partition", - ); +pub fn partition(device: PathBuf, mode: PartitionMode, efi: bool) { + if !device.exists() { + crash(format!("The device {device:?} doesn't exist"), 1); + } + match mode { + PartitionMode::Auto => { + log(format!("automatically partitioning {device:?}")); + if efi { + partition_with_efi(&device); + } else { + partition_no_efi(&device); + } + } + PartitionMode::Manual => { + log("Manual partitioning".to_string()); } } - if device.contains("nvme") { - part_nvme(device, efi); + if device.to_string_lossy().contains("nvme") { + part_nvme(&device, efi); } else { - part_disk(device, efi); + part_disk(&device, efi); } } -fn part_nvme(device: &str, efi: bool) { +fn partition_no_efi(device: &PathBuf) { + let device = device.to_string_lossy().to_string(); + exec_eval( + exec( + "parted", + vec![ + String::from("-s"), + String::from(&device), + String::from("mklabel"), + String::from("msdos"), + ], + ), + format!("Create msdos label on {}", device).as_str(), + ); + exec_eval( + exec( + "parted", + vec![ + String::from("-s"), + String::from(&device), + String::from("mkpart"), + String::from("primary"), + String::from("ext4"), + String::from("1MIB"), + String::from("512MIB"), + ], + ), + "create bios boot partition", + ); + exec_eval( + exec( + "parted", + vec![ + String::from("-s"), + String::from(device), + String::from("mkpart"), + String::from("primary"), + String::from("btrfs"), + String::from("512MIB"), + String::from("100%"), + ], + ), + "create btrfs root partition", + ); +} + +fn partition_with_efi(device: &PathBuf) { + let device = device.to_string_lossy().to_string(); + exec_eval( + exec( + "parted", + vec![ + String::from("-s"), + String::from(&device), + String::from("mklabel"), + String::from("gpt"), + ], + ), + format!("create gpt label on {}", &device).as_str(), + ); + exec_eval( + exec( + "parted", + vec![ + String::from("-s"), + String::from(&device), + String::from("mkpart"), + String::from("fat32"), + String::from("0"), + String::from("300"), + ], + ), + "create EFI partition", + ); + exec_eval( + exec( + "parted", + vec![ + String::from("-s"), + String::from(device), + String::from("mkpart"), + String::from("btrfs"), + String::from("300"), + String::from("100%"), + ], + ), + "Create btrfs root partition", + ); +} + +fn part_nvme(device: &PathBuf, efi: bool) { + let device = device.to_string_lossy().to_string(); if efi { exec_eval( exec("mkfs.vfat", vec![format!("{}p1", device)]), format!("format {}p1 as fat32", device).as_str(), ); exec_eval( - exec("mkfs.btrfs", vec!["-f".to_string(), format!("{}p2", device)]), + exec( + "mkfs.btrfs", + vec!["-f".to_string(), format!("{}p2", device)], + ), format!("format {}p2 as btrfs", device).as_str(), ); mount(format!("{}p2", device).as_str(), "/mnt", ""); @@ -154,7 +176,10 @@ fn part_nvme(device: &str, efi: bool) { format!("format {}p1 as ext4", device).as_str(), ); exec_eval( - exec("mkfs.btrfs", vec!["-f".to_string(), format!("{}p2", device)]), + exec( + "mkfs.btrfs", + vec!["-f".to_string(), format!("{}p2", device)], + ), format!("format {}p2 as btrfs", device).as_str(), ); mount(format!("{}p2", device).as_str(), "/mnt/", ""); @@ -195,7 +220,8 @@ fn part_nvme(device: &str, efi: bool) { } } -fn part_disk(device: &str, efi: bool) { +fn part_disk(device: &PathBuf, efi: bool) { + let device = device.to_string_lossy().to_string(); if efi { exec_eval( exec("mkfs.vfat", vec![format!("{}1", device)]), diff --git a/src/internal/config.rs b/src/internal/config.rs index 3cd2e3f..08f61a5 100755 --- a/src/internal/config.rs +++ b/src/internal/config.rs @@ -1,6 +1,8 @@ +use crate::args::{DesktopSetup, PartitionMode}; use crate::functions::*; use crate::internal::*; use serde::{Deserialize, Serialize}; +use std::path::PathBuf; #[derive(Serialize, Deserialize)] struct Config { @@ -10,7 +12,7 @@ struct Config { networking: Networking, users: Vec, rootpass: String, - desktop: String, + desktop: Option, timeshift: bool, extra_packages: Vec, } @@ -18,7 +20,7 @@ struct Config { #[derive(Serialize, Deserialize)] struct Partition { device: String, - mode: String, + mode: PartitionMode, efi: bool, } @@ -48,22 +50,17 @@ struct Users { hasroot: bool, } -pub fn read_config(configpath: &str) { - let data = std::fs::read_to_string(configpath); +pub fn read_config(configpath: PathBuf) { + let data = std::fs::read_to_string(&configpath); match &data { Ok(_) => { log(format!( - "[ \x1b[2;1;32mOK\x1b[0m ] {}", - format!("Read config file {}", configpath).as_str() + "[ \x1b[2;1;32mOK\x1b[0m ] Read config file {configpath:?}" )); } Err(e) => { crash( - format!( - "{} ERROR: {}", - format!("Read config file {}", configpath).as_str(), - e - ), + format!("Read config file {configpath:?} ERROR: {}", e), e.raw_os_error().unwrap(), ); } @@ -73,19 +70,11 @@ pub fn read_config(configpath: &str) { match &config { Ok(_) => { log(format!( - "[ \x1b[2;1;32mOK\x1b[0m ] {}", - format!("Parse config file {}", configpath).as_str() + "[ \x1b[2;1;32mOK\x1b[0m ] Parse config file {configpath:?}", )); } Err(e) => { - crash( - format!( - "{} ERROR: {}", - format!("Parse config file {}", configpath).as_str(), - e - ), - 1, - ); + crash(format!("Parse config file {configpath:?} ERROR: {}", e), 1); } } let config: Config = config.unwrap(); @@ -94,11 +83,11 @@ pub fn read_config(configpath: &str) { "Block device to use : /dev/{}", config.partition.device )); - info(format!("Partitioning mode : {}", config.partition.mode)); + info(format!("Partitioning mode : {:?}", config.partition.mode)); info(format!("Partitioning for EFI : {}", config.partition.efi)); partition::partition( - format!("/dev/{}", config.partition.device).as_str(), - config.partition.mode.as_str(), + PathBuf::from("/dev/").join(config.partition.device), + config.partition.mode, config.partition.efi, ); base::install_base_packages(); @@ -113,9 +102,9 @@ pub fn read_config(configpath: &str) { config.bootloader.location )); if config.bootloader.r#type == "grub-efi" { - base::install_bootloader_efi(config.bootloader.location.as_str()); + base::install_bootloader_efi(PathBuf::from(config.bootloader.location)); } else if config.bootloader.r#type == "grub-legacy" { - base::install_bootloader_legacy(config.bootloader.location.as_str()); + base::install_bootloader_legacy(PathBuf::from(config.bootloader.location)); } println!(); info(format!("Adding Locales : {:?}", config.locale.locale)); @@ -155,9 +144,9 @@ pub fn read_config(configpath: &str) { info(format!("Setting root password : {}", config.rootpass)); users::root_pass(config.rootpass.as_str()); println!(); - info(format!("Installing desktop : {}", config.desktop)); - if config.desktop != "none" || !config.desktop.is_empty() { - desktops::choose_pkgs(config.desktop.as_str()); + info(format!("Installing desktop : {:?}", config.desktop)); + if let Some(desktop) = &config.desktop { + desktops::install_desktop_setup(*desktop); } println!(); info(format!("Enabling timeshift : {}", config.timeshift)); diff --git a/src/internal/mod.rs b/src/internal/mod.rs index 02081a3..0a157c2 100755 --- a/src/internal/mod.rs +++ b/src/internal/mod.rs @@ -9,8 +9,8 @@ pub fn install(pkgs: Vec<&str>) { install::install(pkgs); } -pub fn crash(a: String, b: i32) { - strings::crash(a, b); +pub fn crash>(a: S, b: i32) -> ! { + strings::crash(a.as_ref().to_string(), b); } pub fn log(a: String) { diff --git a/src/internal/strings.rs b/src/internal/strings.rs index 2704632..49ae707 100755 --- a/src/internal/strings.rs +++ b/src/internal/strings.rs @@ -4,7 +4,7 @@ use std::process::exit; use std::str::FromStr; use std::time::UNIX_EPOCH; -pub fn crash(a: String, b: i32) { +pub fn crash(a: String, b: i32) -> ! { let a = if env::var("JADE_UWU").unwrap_or_else(|_| "".to_string()) == "true" { uwu!(&a) } else { diff --git a/src/main.rs b/src/main.rs index 5d08249..7eccf69 100755 --- a/src/main.rs +++ b/src/main.rs @@ -1,213 +1,62 @@ +mod args; mod functions; mod internal; +use crate::args::{BootloaderSubcommand, Command, Opt, UsersSubcommand}; use crate::functions::*; -use clap::{App, Arg, SubCommand}; +use clap::Parser; fn main() { - let app = App::new("jade") - .version(env!("CARGO_PKG_VERSION")) - .about(env!("CARGO_PKG_DESCRIPTION")) - .author(env!("CARGO_PKG_AUTHORS")) - .subcommand( - SubCommand::with_name("partition") - .about("Partition the install destination") - .arg( - Arg::with_name("mode") - .help("If jade should automatically partition (mode = auto) or the user manually partitioned it (mode = manual)") - .possible_values(&["auto", "manual"]) - .required(true), - ) - .arg( - Arg::with_name("device") - .help("The device to partition") - .required_if("mode", "auto"), - ) - .arg( - Arg::with_name("efi") - .help("If the install destination should be partitioned with EFI") - .long("efi") - .takes_value(false), - ), - ) - .subcommand( - SubCommand::with_name("install-base") - .about("Install base packages") - ) - .subcommand( - SubCommand::with_name("genfstab") - .about("Generate fstab") - ) - .subcommand( - SubCommand::with_name("setup-timeshift") - .about("Setup timeshift") - ) - .subcommand( - SubCommand::with_name("bootloader") - .about("Install bootloader") - .subcommand( - SubCommand::with_name("grub-efi") - .about("Install grub-efi") - .arg( - Arg::with_name("efidir") - .help("The directory to install the EFI bootloader to") - .required(true), - ), - ) - .subcommand( - SubCommand::with_name("grub-legacy") - .about("Install grub-legacy") - .arg( - Arg::with_name("device") - .help("The device to install the bootloader to") - .required(true), - ), - ), - ) - .subcommand( - SubCommand::with_name("locale") - .about("Set locale stuff") - .arg( - Arg::with_name("keyboard") - .help("The keyboard layout to use") - .required(true), - ) - .arg( - Arg::with_name("timezone") - .help("The timezone to use") - .required(true), - ) - .arg( - Arg::with_name("locales") - .help("The locales to set") - .multiple(true) - .index(3) - .required(true), - ), - ) - .subcommand( - SubCommand::with_name("networking") - .about("Set networking stuff") - .arg( - Arg::with_name("hostname") - .help("The hostname to use") - .required(true), - ) - .arg( - Arg::with_name("ipv6") - .help("Wether ipv6 should be enabled") - .short("i6") - .long("ipv6") - .takes_value(false), - ), - ) - .subcommand( - SubCommand::with_name("users") - .about("Configure users") - .subcommand( - SubCommand::with_name("newUser") - .about("Create a new user") - .arg( - Arg::with_name("username") - .help("The username to create") - .required(true), - ) - .arg( - Arg::with_name("hasroot") - .help("If the user should have root privileges") - .required(true), - ) - .arg( - Arg::with_name("password") - .help("The password to set. NOTE: Takes hashed password, use `openssl passwd -1 ` to generate the hash.") - .required(true), - ) - ) - .subcommand( - SubCommand::with_name("rootPass") - .about("Set the root password") - .arg( - Arg::with_name("rootPass") - .help("The password to set. NOTE: Takes hashed password, use `openssl passwd -1 ` to generate the hash._") - .required(true), - ), - ) - ) - .subcommand( - SubCommand::with_name("nix") - .about("Install nix"), - ) - .subcommand( - SubCommand::with_name("config") - .about("read a jade installation config") - .arg( - Arg::with_name("config") - .help("The config to read") - .required(true), - ), - ) - .subcommand( - SubCommand::with_name("desktops") - .about("Graphical stuff (Desktop environment and Display Manager)") - .arg( - Arg::with_name("desktopsetup") - .help("The desktop setup to use") - .required(true), - ), - ).get_matches(); - - if let Some(app) = app.subcommand_matches("partition") { - partition::partition( - app.value_of("device").unwrap(), - app.value_of("mode").unwrap(), - app.is_present("efi"), - ); - } else if let Some(app) = app.subcommand_matches("locale") { - locale::set_locale( - app.values_of("locales") - .unwrap() - .collect::>() - .join(" "), - ); - locale::set_keyboard(app.value_of("keyboard").unwrap()); - locale::set_timezone(app.value_of("timezone").unwrap()); - } else if let Some(app) = app.subcommand_matches("networking") { - if app.is_present("ipv6") { - network::create_hosts(); - network::enable_ipv6() - } else { - network::create_hosts() + let opt: Opt = Opt::parse(); + match opt.command { + Command::Partition(args) => { + partition::partition(args.device, args.mode, args.efi); + } + Command::InstallBase => { + base::install_base_packages(); + } + Command::GenFstab => { + base::genfstab(); + } + Command::SetupTimeshift => base::setup_timeshift(), + Command::Bootloader { subcommand } => match subcommand { + BootloaderSubcommand::GrubEfi { efidir } => { + base::install_bootloader_efi(efidir); + } + BootloaderSubcommand::GrubLegacy { device } => { + base::install_bootloader_legacy(device); + } + }, + Command::Locale(args) => { + locale::set_locale(args.locales.join(" ")); + locale::set_keyboard(&args.keyboard); + locale::set_timezone(&args.timezone); + } + Command::Networking(args) => { + if args.ipv6 { + network::create_hosts(); + network::enable_ipv6() + } else { + network::create_hosts(); + } + network::set_hostname(&args.hostname); + } + Command::Users { subcommand } => match subcommand { + UsersSubcommand::NewUser(args) => { + users::new_user(&args.username, args.hasroot, &args.password); + } + UsersSubcommand::RootPass { password } => { + users::root_pass(&password); + } + }, + Command::Nix => { + base::install_homemgr(); } - network::set_hostname(app.value_of("hostname").unwrap()) - } else if let Some(app) = app.subcommand_matches("users") { - if let Some(app) = app.subcommand_matches("newUser") { - users::new_user( - app.value_of("username").unwrap(), - app.value_of("hasroot").unwrap().parse::().unwrap(), - app.value_of("password").unwrap(), - ); - } else if let Some(app) = app.subcommand_matches("rootPass") { - users::root_pass(app.value_of("rootPass").unwrap()); + Command::Config { config } => { + crate::internal::config::read_config(config); } - } else if let Some(app) = app.subcommand_matches("desktops") { - desktops::choose_pkgs(app.value_of("desktopsetup").unwrap()); - } else if let Some(app) = app.subcommand_matches("bootloader") { - if let Some(app) = app.subcommand_matches("grub-efi") { - base::install_bootloader_efi(app.value_of("efidir").unwrap()); - } else if let Some(app) = app.subcommand_matches("grub-legacy") { - base::install_bootloader_legacy(app.value_of("device").unwrap()); + Command::Desktops { desktop } => { + desktops::install_desktop_setup(desktop); } - } else if app.subcommand_matches("install-base").is_some() { - base::install_base_packages(); - } else if app.subcommand_matches("genfstab").is_some() { - base::genfstab(); - } else if app.subcommand_matches("setup-timeshift").is_some() { - base::setup_timeshift(); - } else if app.subcommand_matches("nix").is_some() { - base::install_homemgr(); - } else if let Some(app) = app.subcommand_matches("config") { - crate::internal::config::read_config(app.value_of("config").unwrap()); - } else { - println!("{}", app.usage()); } }