Merge branch 'master' into 'master'
Change argument parsing to use clap v3 derive syntax See merge request crystal/programs/jade!1axtloss/rework-partitioning
commit
d23b17cb2f
@ -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
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="PROJECT_FILES" />
|
||||
<option name="description" value="" />
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="CPP_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/jade.iml" filepath="$PROJECT_DIR$/.idea/jade.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,189 @@
|
||||
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,
|
||||
},
|
||||
|
||||
/// Install a graphical desktop setup
|
||||
#[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<String>,
|
||||
}
|
||||
|
||||
#[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 <password>` 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 <password>` 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 = "onyx")]
|
||||
Onyx,
|
||||
|
||||
#[clap(name = "gnome")]
|
||||
Gnome,
|
||||
|
||||
#[clap(name = "kde", aliases = ["plasma"])]
|
||||
Kde,
|
||||
|
||||
#[clap(name = "budgie")]
|
||||
Budgie,
|
||||
|
||||
#[clap(name = "cinnamon")]
|
||||
Cinnamon,
|
||||
|
||||
#[clap(name = "mate")]
|
||||
Mate,
|
||||
|
||||
#[clap(name = "xfce")]
|
||||
Xfce,
|
||||
|
||||
#[clap(name = "enlightenment")]
|
||||
Enlightenment,
|
||||
}
|
@ -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 <password>` 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 <password>` 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::<Vec<&str>>()
|
||||
.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") {
|
||||
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::create_hosts();
|
||||
}
|
||||
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::<bool>().unwrap(),
|
||||
app.value_of("password").unwrap(),
|
||||
);
|
||||
} else if let Some(app) = app.subcommand_matches("rootPass") {
|
||||
users::root_pass(app.value_of("rootPass").unwrap());
|
||||
network::set_hostname(&args.hostname);
|
||||
}
|
||||
} 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::Users { subcommand } => match subcommand {
|
||||
UsersSubcommand::NewUser(args) => {
|
||||
users::new_user(&args.username, args.hasroot, &args.password);
|
||||
}
|
||||
} 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() {
|
||||
UsersSubcommand::RootPass { password } => {
|
||||
users::root_pass(&password);
|
||||
}
|
||||
},
|
||||
Command::Nix => {
|
||||
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());
|
||||
}
|
||||
Command::Config { config } => {
|
||||
crate::internal::config::read_config(config);
|
||||
}
|
||||
Command::Desktops { desktop } => {
|
||||
desktops::install_desktop_setup(desktop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue