Compare commits

...

10 Commits

Author SHA1 Message Date
everyone 7582f98e46
wip 2023-11-11 13:37:47 -08:00
everyone 8c7ca74363
wip 2023-11-10 22:49:33 -08:00
everyone 22966cd7bd
wip 2023-11-10 19:18:57 -08:00
everyone 3c156d580d
wip 2023-11-10 19:02:57 -08:00
everyone 89a201acd0
refactor cmd macro 2023-11-09 15:37:53 -08:00
everyone 96737ddcc1
fix cmd macro for capital letters 2023-11-08 19:42:00 -08:00
everyone 433fc1af7d
fix cmd macro misinterpreting quoted strings 2023-11-08 19:10:52 -08:00
everyone 336939581d
fix btrfs mkswapfile using wrong command 2023-11-08 18:53:17 -08:00
everyone b87e7d0bda
remove duplicate swap_size variable 2023-11-08 18:50:40 -08:00
everyone c406d4fd08
wip 2023-11-08 18:43:07 -08:00
13 changed files with 599 additions and 1 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
**/target

View File

@ -1 +1,6 @@
{}
{
"editor.formatOnSave": true,
"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer"
}
}

3
Untitled-1.sh Normal file
View File

@ -0,0 +1,3 @@
#!/bin/env bash
sw

34
archlinux/install.sh Executable file
View File

@ -0,0 +1,34 @@
#!/bin/env bash
prompt() {
variable=$1
prompt=$2
read -p "> " "${variable?}"
}
invert() {
value=$1
((value ^= 1))
echo $value
}
is_uefi=0
if [[ $(cat /sys/firmware/efi/fw_platform_size) -eq 64 ]]; then
is_uefi=1
fi
mapfile -t devices < <(lsblk --paths --output NAME --noheadings --nodeps)
mapfile -t devices_sizes < <(lsblk --paths --output SIZE --noheadings --nodeps)
paste <(printf "%s\n" "${!devices[@]}") <(printf "%s\n" "${devices[@]}") <(printf "%s\n" "${devices_sizes[@]}")
echo "Which device do you want to be main root drive?"
prompt root_drive
echo "Which device do you want to be used for home? use q to skip and use root drive."
prompt home_drive
echo $root_drive - $home_drive

View File

@ -0,0 +1,3 @@
{
"recommendations": []
}

45
archlinux/install/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,45 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug executable 'install'",
"cargo": {
"args": [
"build",
"--bin=install",
"--package=install"
],
"filter": {
"name": "install",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in executable 'install'",
"cargo": {
"args": [
"test",
"--no-run",
"--bin=install",
"--package=install"
],
"filter": {
"name": "install",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}

View File

@ -0,0 +1,6 @@
{
"editor.formatOnSave": true,
"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer"
}
}

110
archlinux/install/Cargo.lock generated Normal file
View File

@ -0,0 +1,110 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "bitflags"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cli"
version = "0.1.0"
dependencies = [
"nix",
"quote",
"strum",
]
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "libc"
version = "0.2.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
[[package]]
name = "nix"
version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
dependencies = [
"bitflags",
"cfg-if",
"libc",
]
[[package]]
name = "proc-macro2"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustversion"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
[[package]]
name = "strum"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn",
]
[[package]]
name = "syn"
version = "2.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"

View File

@ -0,0 +1,6 @@
[workspace]
resolver = "2"
members = [
# "cmd",
"cli"
]

View File

@ -0,0 +1,12 @@
[package]
name = "cli"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
strum = { version = "0.25.0", features = ["derive"] }
quote = "*"
nix = { version = "0.27.1", features = ["user"] }
# cmd = {path = "../cmd"}

View File

@ -0,0 +1,293 @@
#![allow(dead_code, unused_macros)]
use std::{
net::{Shutdown, TcpStream},
process::Stdio,
};
type Disks = Vec<Vec<String>>;
macro_rules! count_tts {
() => { 0 };
($odd:tt $($a:tt $b:tt)*) => { (count_tts!($($a)*) << 1) | 1 };
($($a:tt $even:tt)*) => { count_tts!($($a)*) << 1 };
}
macro_rules! read {
($type:ty, $($prompts:literal),+) => {{
use std::io::{stdout, stdin, Write};
let r#type = match stringify!($type) {
"bool" => "Boolean",
"usize" => "Integer",
"String" => "String",
_=> panic!("\nunkown type {}", stringify!($type))
};
loop {
let mut result = String::new();
$(println!("\n{}", $prompts);)*
print!("> ");
let _ = stdout().flush();
stdin()
.read_line(&mut result)
.expect("Did not enter a correct string");
if let Some('\n') = result.chars().next_back() {
result.pop();
}
let results = result.parse::<$type>();
match results {
Ok(v) => break v,
Err(_) => println!("\nInput does not match expected type: {}.", r#type),
}
}
}};
}
/// Currently does not work for standalone long dash
macro_rules! cmd {
(@command $token:tt) => {
stringify!($token).replace(" - ", "-")
};
(@args $($token:tt)+) => {{
let args = [$(stringify!($token)),+];
let mut prv_val: &'static str = "";
args.iter()
.map(|token| {
let mut results: Option<String> = None;
if (prv_val != "-" || prv_val != "--") && *token != "-" {
results = Some(format!("{}", token.replace('"', "")));
}
if prv_val == "-" && *token != "-" {
results = Some(format!("-{}", *token));
}
if prv_val == "--" && *token != "-" {
results = Some(format!("--{}", *token));
}
prv_val = if prv_val == "-" && *token == "-" {
"--"
} else {
token
};
match results {
Some(val) => val,
None => String::from(""),
}
})
.filter(|item| !item.is_empty())
.collect::<Vec<String>>()
}};
($command:expr) => {{
let command = cmd!(@command $command);
std::process::Command::new(command)
}};
($command:expr => $($args:tt)+) => {{
let command = cmd!(@command $command);
#[allow(unused_mut,)]
let mut args = cmd!(@args $($args) *);
std::process::Command::new(command).args(args)
}};
}
fn is_online() -> bool {
let archlinux_org = "95.217.163.246:80";
let ping = TcpStream::connect(archlinux_org);
match ping {
Ok(val) => {
let _ = val.shutdown(Shutdown::Both);
true
}
Err(_) => panic!("Connect to a network then rerun script"),
}
}
fn is_uefi() -> bool {
let bit = std::fs::read_to_string("/sys/firmware/efi/fw_platform_size");
match bit {
Ok(_) => true,
_ => false,
}
}
fn get_disks() -> Disks {
let process = std::process::Command::new("lsblk")
.args([
"--paths",
"--output",
"NAME,SIZE",
"--noheadings",
"--nodeps",
])
.output();
let output = String::from_utf8(process.unwrap().stdout)
.unwrap()
.trim()
.to_owned();
output
.split("\n")
.map(|disk| {
disk.split_whitespace()
.map(|value| value.to_owned())
.collect()
})
.collect()
}
fn print_disks(disks: &Disks) {
for (i, disk) in disks.iter().enumerate() {
println!("{}\t{}\t{}", i, disk[0], disk[1]);
}
}
#[derive(strum::AsRefStr)]
enum DiskLabel {
GPT,
MBR,
}
fn fdisk(dev: &String, label: DiskLabel, partitions: Vec<&'static str>) {
let label = format!("label: {}", label.as_ref());
let mut process = std::process::Command::new("sfdisk")
// .arg("--quiet")
.arg(dev)
.stdin(Stdio::piped())
.spawn()
.expect("Command failed to spawn");
std::process::Command::new("echo")
.arg([label, partitions.join("\n")].join("\n"))
.stdout(process.stdin.take().unwrap()) // Converted into a Stdio here
.spawn()
.expect("failed echo command");
let _ = process.wait();
}
fn mkfs_fat(dev: &String, part_num: i32, size: i32, label: &'static str) {
let _ = std::process::Command::new("mkfs.fat")
.args(["-n", label])
.args(["-F", &size.to_string()])
.arg(format!("{}{}", dev, part_num))
.spawn()
.unwrap()
.wait()
.expect("Command failed to spawn");
}
fn mkfs_btrfs(dev: &String, part_num: i32, label: &'static str) {
let _ = std::process::Command::new("mkfs.btrfs")
.args(["--label", label])
.arg("-f")
.arg(format!("{}{}", dev, part_num))
.spawn()
.unwrap()
.wait()
.expect("Command failed to spawn");
}
fn mount(dev: &String, part_num: i32, path: &'static str, options: Option<Vec<&'static str>>) {
let _ = std::process::Command::new("mount")
.arg("--mkdir")
.args(match options {
Some(opts) => vec!["--options".to_string(), opts.join(",")],
None => vec![],
})
.arg(format!("{dev}{part_num}"))
.arg(path)
.spawn()
.unwrap()
.wait()
.expect("Command failed to spawn");
}
fn main() {
if !nix::unistd::getuid().is_root() {
panic!("Script must be ran as root")
}
is_online();
let _is_uefi = is_uefi();
let disks = get_disks();
// Get info from user.
print_disks(&disks);
let root = read!(usize, "Which device do you want to be root drive?");
let mut fmt_home = false;
let home = if read!(
bool,
"Do you want to store home on another drive? (true|false)"
) {
let home = read!(usize, "Which device do you want to be home drive");
fmt_home = read!(bool, "Do you want to format home? (true|false)");
home
} else {
root
};
let swap = read!(bool, "Do you want a swap space? (true|false)");
let swap_size = if swap {
read!(
String,
"Swap size. Default is 2g. (accepting k/m/g/e/p suffix)"
)
} else {
String::from("2g")
};
// Act on user info.
// -- format disks and mkfs
{
let boot = ",+1G,C12A7328-F81F-11D2-BA4B-00A0C93EC93B";
let part_root = ",";
fdisk(&disks[root][0], DiskLabel::GPT, vec![boot, part_root]);
mkfs_fat(&disks[root][0], 1, 32, "boot");
mkfs_btrfs(&disks[root][0], 2, "root");
};
if fmt_home {
fdisk(&disks[home][0], DiskLabel::GPT, vec![","]);
mkfs_btrfs(&disks[home][0], 1, "home");
}
// -- mount partitions
mount(&disks[root][0], 2, "/mnt", None);
mount(&disks[root][0], 1, "/mnt/boot", None);
if swap {
_ = cmd! {btrfs => subvolume create "/mnt/swap"}
.spawn()
.unwrap()
.wait();
_ = cmd! {btrfs => filesystem mkswapfile --uuid clear "/mnt/swap/file"}
.args(["--size", &swap_size])
.spawn()
.unwrap()
.wait();
_ = cmd! {swapon => "/mnt/swap/file"}.spawn().unwrap().wait();
}
// Installation
// -- Sort mirrors
_ = cmd! {reflector => --save "/etc/pacman.d/mirrorlist" --sort rate --threads 24}
.spawn()
.unwrap()
.wait();
// -- Install essential packages
_ = cmd! {pacstrap => -K "/mnt" base "linux-zen" "linux-firmware" micro}
.spawn()
.unwrap()
.wait();
// Configure the system
// -- Fstab
let fstab = cmd! {genfstab => -U "/mnt"}.output().unwrap();
let _ = std::fs::write("/mnt/etc/fstab", fstab.stdout);
// -- Chroot
let chroot = "#!/bin/env bash\nln -sf /usr/share/zoneinfo/America/Los_Angeles /etc/localtime\n\nhwclock --systohc\n\nsed -i 's/#en_US\\./en_US./' /etc/locale.gen\n\nlocale-gen\n\necho \"LANG=en_US.UTF-8\" >>/etc/locale.conf\n\necho \"zesktop\" >>/etc/hostname\n\nsed -i 's/#COMPRESSION=\"zstd\"/COMPRESSION=\"zstd\"/' /etc/mkinitcpio.conf\n\nprintf \"[Match]\\n\" >>/etc/systemd/network/20-ethernet.network\nprintf \"Name=en*\\n\" >>/etc/systemd/network/20-ethernet.network\nprintf \"Name=eth*\\n\" >>/etc/systemd/network/20-ethernet.network\nprintf \"\\n\" >>/etc/systemd/network/20-ethernet.network\nprintf \"[Network]\\n\" >>/etc/systemd/network/20-ethernet.network\nprintf \"DHCP=yes\\n\" >>/etc/systemd/network/20-ethernet.network\n\necho \"password\npassword\" | passwd\n";
_ = std::fs::write("/mnt/chroot.bash", chroot);
let _ = cmd! {arch-chroot => "/mnt" bash -c "chmod +x /chroot.bash; /chroot.bash"}
.spawn()
.unwrap()
.wait();
}

View File

@ -0,0 +1,15 @@
[package]
name = "cmd"
version = "0.1.0"
edition = "2021"
[lib]
name = "cmd"
path = "src/lib.rs"
proc-macro = true
[dependencies]
syn = { version = "*", features = ["extra-traits"] }
quote = "*"
proc-macro2 = "*"
r3bl_rs_utils = "*"

View File

@ -0,0 +1,65 @@
use proc_macro::TokenStream;
use syn::parse::{Parse, ParseStream, Result};
use syn::{parse_macro_input, Ident};
/// Parses the following syntax, which aligns with the input of the real
/// `lazy_static` crate.
///
/// lazy_static! {
/// $VISIBILITY static ref $NAME: $TYPE = $EXPR;
/// }
///
/// For example:
///
/// lazy_static! {
/// static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
/// }
struct LazyStatic {
command: Ident,
}
impl Parse for LazyStatic {
fn parse(input: ParseStream) -> Result<Self> {
dbg!(input);
let command: Ident = input.parse()?;
// input.parse::<Token![Ident]>()?;
// let args: Expr = input.parse()?;
// input.parse::<Token![>]>()?;
// let replacement: Ident = input.parse()?;
// input.parse::<Token![,]>()?;
Ok(LazyStatic { command })
}
}
#[proc_macro]
pub fn cmd(input: TokenStream) -> TokenStream {
let LazyStatic { command: _ } = parse_macro_input!(input);
// let expanded = quote! {
// #visibility struct #name;
// impl std::ops::Deref for #name {
// type Target = #ty;
// fn deref(&self) -> &#ty {
// #assert_sync
// #assert_sized
// static ONCE: std::sync::Once = std::sync::Once::new();
// static mut VALUE: *mut #ty = 0 as *mut #ty;
// }
// }
// };
todo!();
// TokenStream::from(expanded)
}
// use proc_macro::TokenStream;
// use quote::quote;
// #[proc_macro]
// pub fn cmd(input: TokenStream) -> TokenStream {
// dbg!(input);
// todo!()
// }