guix-scheme 0.2.0

Read, edit, and generate Guix Scheme files (channels.scm, system config.scm) from Rust
Documentation
use guix_scheme::os_builder::{FsDevice, OsBuilder, OsFlavor};
use scheme_edit::Document;

fn assert_valid_scheme(out: &str) {
    Document::parse(out).unwrap_or_else(|e| panic!("output is not valid scheme: {e}\n{out}"));
}

#[test]
fn panther_efi_plain_ext4_desktop() {
    let out = OsBuilder::new(
        OsFlavor::Panther,
        "panther-box",
        "Europe/Berlin",
        "en_US.utf8",
    )
    .bootloader_efi("/boot/efi")
    .file_system("/", FsDevice::Label("root".into()), "ext4", false)
    .user("franz", "Franz", &["wheel", "netdev", "audio", "video"])
    .packages_field("%os-desktop-packages")
    .services_field("%os-desktop-services")
    .build();
    assert_valid_scheme(&out);
    assert!(out.contains("(inherit %os-base)"));
    assert!(out.contains("grub-efi-bootloader"));
    assert!(out.contains("(px system os)"));
    assert!(out.contains("%os-desktop-services"));
    assert!(out.contains("%os-desktop-packages"));
    assert!(out.contains("\"ext4\""));
    assert!(out.contains("/boot/efi"));
    assert!(!out.contains("luks-device-mapping"));
    assert!(!out.contains("mapped-devices"));
}

#[test]
fn bios_luks_headless() {
    let out = OsBuilder::new(OsFlavor::Panther, "srv", "UTC", "en_US.utf8")
        .bootloader_bios("/dev/sda")
        .luks_root("/dev/sda2", "cryptroot")
        .file_system(
            "/",
            FsDevice::Path("/dev/mapper/cryptroot".into()),
            "ext4",
            true,
        )
        .user("admin", "Admin", &["wheel"])
        .build();
    assert_valid_scheme(&out);
    assert!(out.contains("grub-bootloader"));
    assert!(!out.contains("grub-efi-bootloader"));
    assert!(out.contains("luks-device-mapping"));
    assert!(out.contains("/dev/mapper/cryptroot"));
    assert!(out.contains("(dependencies mapped-devices)"));
    assert!(!out.contains("(packages"));
    assert!(!out.contains("/boot/efi"));
}

#[test]
fn nonguix_kernel_initrd_firmware() {
    let out = OsBuilder::new(OsFlavor::Nonguix, "laptop", "Europe/Berlin", "en_US.utf8")
        .bootloader_efi("/boot/efi")
        .file_system("/", FsDevice::Label("root".into()), "ext4", false)
        .user("franz", "Franz", &["wheel"])
        .services_field("%desktop-services")
        .build();
    assert_valid_scheme(&out);
    assert!(out.contains("(kernel linux)"));
    assert!(out.contains("(initrd microcode-initrd)"));
    assert!(out.contains("(firmware (list linux-firmware))"));
    assert!(out.contains("(nongnu packages linux)"));
    assert!(out.contains("(nongnu system linux-initrd)"));
}

#[test]
fn keyboard_layout_and_uuid_device() {
    let out = OsBuilder::new(OsFlavor::Guix, "kb", "UTC", "en_US.utf8")
        .keyboard_layout("de", Some("nodeadkeys"))
        .bootloader_efi("/boot/efi")
        .file_system("/", FsDevice::Uuid("1234-ABCD".into()), "btrfs", false)
        .user("u", "U", &["wheel"])
        .build();
    assert_valid_scheme(&out);
    assert!(out.contains("(keyboard-layout (keyboard-layout \"de\" \"nodeadkeys\"))"));
    assert!(out.contains("(uuid \"1234-ABCD\")"));
}

#[test]
fn output_reparses_and_host_name_is_editable() {
    let out = OsBuilder::new(OsFlavor::Guix, "editme", "UTC", "en_US.utf8")
        .bootloader_efi("/boot/efi")
        .file_system("/", FsDevice::Label("root".into()), "ext4", false)
        .user("u", "U", &["wheel"])
        .build();
    let mut doc = Document::parse(&out).unwrap();
    let os = doc
        .forms_mut()
        .find(|n| n.head_symbol() == Some("operating-system"))
        .unwrap();
    let mut v = guix_scheme::record::RecordViewMut::new(os).unwrap();
    v.set_field("host-name", scheme_edit::string_lit("edited"));
    assert!(doc.to_string().contains("(host-name \"edited\")"));
}