nyxi-installer/src/main.rs
2025-04-11 21:36:21 -06:00

308 lines
8.5 KiB
Rust

use std::io;
use std::io::Write;
use std::fs::File;
use std::process::{Command, Stdio};
use std::path::Path;
use sys_metrics::disks;
use rsfdisk::fdisk::Fdisk;
use rsfdisk::core::partition_table::PartitionTableKind;
use rsfdisk::core::partition::{Guid, Partition, PartitionKind};
use nix::mount::{mount, MsFlags};
use curl::easy::Easy;
fn format_drive(drive_name: &str) -> rsfdisk::Result<()> {
let mut disk = Fdisk::builder()
.assign_device(drive_name)
.enable_read_write()
.wipe_device_metadata()
.build()?;
disk.partition_table_create(PartitionTableKind::GPT)?;
let partition_type = PartitionKind::builder()
.guid(Guid::EfiSystem)
.build()?;
let boot = Partition::builder()
.partition_type(partition_type)
.name("EFI")
//Assuming 512 bytes per sector, 2_097_152 sectors <=> 1 GiB.
.size_in_sectors(2_097_152)
.build()?;
let _ = disk.partition_add(boot)?;
let partition_type = PartitionKind::builder()
.guid(Guid::LinuxRootx86_64)
.build()?;
let root = Partition::builder()
.partition_type(partition_type)
.name("Root")
// Flash drive testing
.size_in_sectors(121_634_816)
// Internal drive testing
// .size_in_sectors(499_033_071_61)
// replace static int with a variable
.build()?;
let _ = disk.partition_add(root)?;
disk.partition_table_write_to_disk()?;
Ok(())
}
fn format_partitions() {
let _efi_partition = Command::new("mkfs.fat")
.arg("-F32")
.arg("-n")
.arg("EFI")
// replace static path with a variable
.arg("/dev/sda1")
.output()
.expect("Failed to partition boot partition as FAT32");
let _root_partition = Command::new("mkfs.ext4")
// replace static path with a variable
.arg("/dev/sda2")
.output()
.expect("Failed to partition root partition as ext4");
}
fn mount_root() {
// replace static path with a variable
let root_source = Some(Path::new("/dev/sda2"));
let root_target = Path::new("/mnt");
mount(
root_source,
root_target,
Some("ext4"),
MsFlags::empty(),
None::<&[u8]>,
)
.expect("Failed to mount root partition");
// Deletes the boot directory
// Shouldn't be needed with a blank drive
// So just for testing
let _delete_boot_directory = Command::new("rm")
.arg("-r")
.arg("/mnt/boot")
.output()
.expect("Failed to delete boot directory");
// Creates the boot directory in /mnt/boot
let _create_boot_directory = Command::new("mkdir")
.arg("/mnt/boot")
.output()
.expect("Failed to create boot directory");
}
fn mount_boot() {
// replace static path with a variable
let boot_source = Some(Path::new("/dev/sda1"));
let boot_target = Path::new("/mnt/boot");
mount(
boot_source,
boot_target,
Some("vfat"),
MsFlags::empty(),
None::<&[u8]>,
)
.expect("Failed to mount boot partition");
println!("");
}
fn grab_flake() {
let mut easy = Easy::new();
easy.url("https://gitlab.com/ahoneybun/nix-configs/-/raw/rust-rewrite/flake.nix").unwrap();
let mut file = File::create("flake.nix").unwrap();
{
let mut transfer = easy.transfer();
transfer.write_function(|data| {
file.write_all(data).unwrap();
Ok(data.len())
}).unwrap();
transfer.perform().unwrap();
}
}
fn grab_config() {
let mut easy = Easy::new();
easy.url("https://gitlab.com/ahoneybun/nix-configs/-/raw/rust-rewrite/configuration.nix").unwrap();
let mut file = File::create("configuration.nix").unwrap();
{
let mut transfer = easy.transfer();
transfer.write_function(|data| {
file.write_all(data).unwrap();
Ok(data.len())
}).unwrap();
transfer.perform().unwrap();
}
}
fn grab_home() {
let mut easy = Easy::new();
easy.url("https://gitlab.com/ahoneybun/nix-configs/-/raw/rust-rewrite/home.nix").unwrap();
let mut file = File::create("home.nix").unwrap();
{
let mut transfer = easy.transfer();
transfer.write_function(|data| {
file.write_all(data).unwrap();
Ok(data.len())
}).unwrap();
transfer.perform().unwrap();
}
}
fn grab_gnome(){
let mut gnome_config = Easy::new();
gnome_config.url("https://gitlab.com/ahoneybun/nix-configs/-/raw/main/desktops/gnome.nix").unwrap();
let mut config_file = File::create("gnome.nix").unwrap();
{
let mut transfer = gnome_config.transfer();
transfer.write_function(|data| {
config_file.write_all(data).unwrap();
Ok(data.len())
}).unwrap();
transfer.perform().unwrap();
}
}
fn main() {
println!("--------------------------------------");
println!("| Welcome to the Nyxi Installer 2.0! |");
println!("--------------------------------------");
println!("");
println!("Availble disks for installation:");
println!("---------------------------------");
println!("");
match disks::get_physical_ioblocks() {
Ok(disk_list) => {
for disk in disk_list {
println!("Disk: {}", disk.device_name);
}
}
Err(_e) => println!("{}",_e),
}
let mut drive_name = String::new();
println!("");
println!("Use the full drive path such as /dev/nvme0n1 or /dev/sda");
println!("");
println!("Which drive do we want to use for this installation?: {}", drive_name);
io::stdin()
.read_line(&mut drive_name)
.expect("Failed to read line");
let drive_name = drive_name.trim();
// Partitioning the selected drive
let _ = format_drive(drive_name);
// Formatting the partitions
format_partitions();
// Mounting the partitions
mount_root();
mount_boot();
// Download nix files
grab_flake();
grab_config();
grab_home();
grab_gnome();
let _nixos_gen_config = Command::new("nixos-generate-config")
.arg("--root")
.arg("/mnt")
.output()
.expect("Failed to execute command");
// Copies the nix files to /mnt/etc/nixos/
let _nix_copy = Command::new("mv")
.args(["flake.nix", "configration.nix", "home.nix"])
.arg("/mnt/etc/nixos")
.output()
.expect("Failed to copy nix files over");
// Host selection
loop {
println!("");
println!("Host selection:");
println!("---------------");
println!("");
println!("1. Lemur Pro 13 (Garrus)");
println!("2. Device 2");
println!("3. Quit");
println!("");
println!("Enter your host for installation:");
let mut choice = String::new();
io::stdin().read_line(&mut choice).unwrap();
match choice.trim() {
"1" => {
let mut garrus_config = Easy::new();
garrus_config.url("https://gitlab.com/ahoneybun/nix-configs/-/raw/main/hosts/x86_64/garrus/configuration.nix").unwrap();
let mut config_file = File::create("garrus.nix").unwrap();
{
let mut transfer = garrus_config.transfer();
transfer.write_function(|data| {
config_file.write_all(data).unwrap();
Ok(data.len())
}).unwrap();
transfer.perform().unwrap();
}
// Copies the system nix files to /mnt/etc/nixos/
let _garrus_nix_copy = Command::new("cp")
.args(["garrus.nix", "gnome.nix"])
.arg("/mnt/etc/nixos")
.output()
.expect("Failed to copy nix files over");
let mut nixos_install = Command::new("nixos-install")
.arg("--flake")
.arg("/mnt/etc/nixos#garrus")
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.spawn()
.unwrap();
let install_status = nixos_install.wait();
println!("Exited with status {:?}", install_status);
break
}
"2" => {
println!("Nix the world!");
},
"3" => {
println!("Goodbye!");
break;
},
_ => println!("Invalid choice, try again."),
}
}
}