diff --git a/settings.json b/settings.json index 6610837..4e00b34 100644 --- a/settings.json +++ b/settings.json @@ -12,5 +12,6 @@ "timezone": "America/New_York", "kernel": "linux-cachyos", "desktop": "kde", - "bootloader": "systemd-boot" + "bootloader": "systemd-boot", + "drivers_type": "free" } diff --git a/src/config.cpp b/src/config.cpp index 3df035a..ab6fd9d 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -40,6 +40,7 @@ bool Config::initialize() noexcept { // Installation s_config->m_data["GRAPHIC_CARD"] = ""; + s_config->m_data["DRIVERS_TYPE"] = "free"; } return s_config.get(); diff --git a/src/disk.cpp b/src/disk.cpp index cbae706..5165309 100644 --- a/src/disk.cpp +++ b/src/disk.cpp @@ -17,7 +17,7 @@ namespace fs = std::filesystem; namespace utils { -void btrfs_create_subvols([[maybe_unused]] const disk_part& disk, const std::string_view& mode) noexcept { +void btrfs_create_subvols([[maybe_unused]] const disk_part& disk, const std::string_view& mode, bool ignore_note) noexcept { /* clang-format off */ if (mode.empty()) { return; } /* clang-format on */ @@ -62,11 +62,13 @@ void btrfs_create_subvols([[maybe_unused]] const disk_part& disk, const std::str } return; } - static constexpr auto content = "\nThis creates subvolumes:\n@ for /,\n@home for /home,\n@cache for /var/cache.\n"; - const auto& do_create = tui::detail::yesno_widget(content, size(ftxui::HEIGHT, ftxui::LESS_THAN, 15) | size(ftxui::WIDTH, ftxui::LESS_THAN, 75)); - /* clang-format off */ - if (!do_create) { return; } - /* clang-format on */ + if (!ignore_note) { + static constexpr auto content = "\nThis creates subvolumes:\n@ for /,\n@home for /home,\n@cache for /var/cache.\n"; + const auto& do_create = tui::detail::yesno_widget(content, size(ftxui::HEIGHT, ftxui::LESS_THAN, 15) | size(ftxui::WIDTH, ftxui::LESS_THAN, 75)); + /* clang-format off */ + if (!do_create) { return; } + /* clang-format on */ + } // Create subvolumes automatically const auto& saved_path = fs::current_path(); @@ -83,6 +85,8 @@ void btrfs_create_subvols([[maybe_unused]] const disk_part& disk, const std::str fs::create_directories("/mnt/var/cache"); utils::exec(fmt::format(FMT_COMPILE("mount -o {},subvol=@home \"{}\" /mnt/home"), disk.mount_opts, disk.root)); utils::exec(fmt::format(FMT_COMPILE("mount -o {},subvol=@cache \"{}\" /mnt/var/cache"), disk.mount_opts, disk.root)); +#else + spdlog::info("Do we ignore note? {}", ignore_note); #endif } diff --git a/src/disk.hpp b/src/disk.hpp index 88b15bb..dc60df5 100644 --- a/src/disk.hpp +++ b/src/disk.hpp @@ -13,7 +13,7 @@ struct disk_part { const std::string_view mount_opts{}; }; -void btrfs_create_subvols(const disk_part& disk, const std::string_view& mode) noexcept; +void btrfs_create_subvols(const disk_part& disk, const std::string_view& mode, bool ignore_note = false) noexcept; void mount_existing_subvols(const disk_part& disk) noexcept; std::vector lvm_show_vg() noexcept; diff --git a/src/simple_tui.cpp b/src/simple_tui.cpp index 9bdf9b8..4995bcb 100644 --- a/src/simple_tui.cpp +++ b/src/simple_tui.cpp @@ -33,15 +33,9 @@ void select_filesystem() noexcept { config_data["fs_opts"] = std::vector{}; const std::vector menu_entries = { - "btrfs", - "ext3", "ext4", + "btrfs", "f2fs", - "jfs", - "nilfs2", - "ntfs", - "reiserfs", - "vfat", "xfs", }; @@ -64,6 +58,33 @@ void select_filesystem() noexcept { utils::select_filesystem("btrfs"); } } + +void make_esp(const auto& part_name) noexcept { + auto* config_instance = Config::instance(); + auto& config_data = config_instance->data(); + const auto& sys_info = std::get(config_data["SYSTEM"]); + + /* clang-format off */ + if (sys_info != "UEFI") { return; } + /* clang-format on */ + + auto& partition = std::get(config_data["PARTITION"]); + partition = part_name; + config_data["UEFI_MOUNT"] = "/boot"; + config_data["UEFI_PART"] = partition; + + spdlog::debug("Formating boot partition with fat/vfat!"); +#ifdef NDEVENV + const auto& mountpoint_info = std::get(config_data["MOUNTPOINT"]); + const auto& uefi_mount = std::get(config_data["UEFI_MOUNT"]); + const auto& path_formatted = fmt::format(FMT_COMPILE("{}{}"), mountpoint_info, uefi_mount); + + utils::exec(fmt::format(FMT_COMPILE("mkfs.vfat -F32 {} &>/dev/null"), partition)); + utils::exec(fmt::format(FMT_COMPILE("mkdir -p {}"), path_formatted)); + utils::exec(fmt::format(FMT_COMPILE("mount {} {}"), partition, path_formatted)); +#endif +} + } // namespace namespace tui { @@ -89,15 +110,71 @@ void menu_simple() noexcept { const auto& user_shell = std::get(config_data["USER_SHELL"]); const auto& root_pass = std::get(config_data["ROOT_PASS"]); - const auto& kernel = std::get(config_data["KERNEL"]); - const auto& desktop = std::get(config_data["DE"]); - const auto& bootloader = std::get(config_data["BOOTLOADER"]); + const auto& kernel = std::get(config_data["KERNEL"]); + const auto& desktop = std::get(config_data["DE"]); + const auto& bootloader = std::get(config_data["BOOTLOADER"]); + const auto& drivers_type = std::get(config_data["DRIVERS_TYPE"]); if (device_info.empty()) { tui::select_device(); } + tui::auto_partition(false); + // LVM Detection. If detected, activate. + tui::lvm_detect(); + + // Ensure partitions are unmounted (i.e. where mounted previously) + config_data["INCLUDE_PART"] = "part\\|lvm\\|crypt"; + utils::umount_partitions(); + + // We need to remount the zfs filesystems that have defined mountpoints already + utils::exec("zfs mount -aO &>/dev/null"); + + // Get list of available partitions + utils::find_partitions(); + + // Filter out partitions that have already been mounted and partitions that just contain crypt or zfs devices + auto ignore_part = utils::list_mounted(); + ignore_part += utils::zfs_list_devs(); + ignore_part += utils::list_containing_crypt(); + + std::vector> parts{}; + + const auto& partitions = std::get>(config_data["PARTITIONS"]); + for (const auto& partition : partitions) { + /* clang-format off */ + if (!partition.starts_with(device_info)) { continue; } + /* clang-format on */ + const auto& partition_stat = utils::make_multiline(partition, false, " "); + const auto& part_name = partition_stat[0]; + const auto& part_size = partition_stat[1]; + + if (part_size == "512M") { + make_esp(part_name); + utils::get_cryptroot(); + utils::get_cryptboot(); + spdlog::info("boot partition: name={}", part_name); + continue; + } + + const auto& size_end_pos = std::find_if(part_size.begin(), part_size.end(), [](auto&& ch) { return std::isalpha(ch); }); + const auto& number_len = std::distance(part_size.begin(), size_end_pos); + const std::string_view number_str{part_size.data(), static_cast(number_len)}; + const std::string_view unit{part_size.data() + number_len, part_size.size() - static_cast(number_len)}; + + const double number = utils::to_floating(number_str); + const auto& converted_num = utils::convert_unit(number, unit); + parts.push_back(std::pair{part_name, converted_num}); + } + + const auto& root_part = std::max_element(parts.begin(), parts.end(), [](auto&& lhs, auto&& rhs) { return lhs.second < rhs.second; })->first; + config_data["PARTITION"] = root_part; + config_data["ROOT_PART"] = root_part; + + // Reset the mountpoint variable, in case this is the second time through this menu and old state is still around + config_data["MOUNT"] = ""; + // Target FS if (fs_name.empty()) { select_filesystem(); @@ -105,7 +182,20 @@ void menu_simple() noexcept { utils::select_filesystem(fs_name); } tui::mount_current_partition(true); - /* clang-format on */ + + // If the root partition is btrfs, offer to create subvolumes + if (utils::exec(fmt::format(FMT_COMPILE("findmnt -no FSTYPE \"{}\""), mountpoint)) == "btrfs") { + // Check if there are subvolumes already on the btrfs partition + const auto& subvolumes = fmt::format(FMT_COMPILE("btrfs subvolume list \"{}\""), mountpoint); + const auto& subvolumes_count = utils::exec(fmt::format(FMT_COMPILE("{} | wc -l"), subvolumes)); + const auto& lines_count = utils::to_int(subvolumes_count.data()); + if (lines_count > 1) { + // Pre-existing subvolumes and user wants to mount them + utils::mount_existing_subvols({root_part, root_part}); + } else { + utils::btrfs_create_subvols({.root = root_part, .mount_opts = mount_opts_info}, "automatic", true); + } + } utils::generate_fstab("genfstab -U"); @@ -159,12 +249,6 @@ void menu_simple() noexcept { fmt::format("Filesystem: {}", fs_name), fmt::format("Filesystem opts: {}", mount_opts_info), 80); - // tui::mount_partitions(); - // - // if (!utils::check_mount()) { - // spdlog::error("Your partitions are not mounted"); - // } - // Install process if (kernel.empty()) { tui::install_base(); @@ -184,20 +268,22 @@ void menu_simple() noexcept { } #ifdef NDEVENV - utils::arch_chroot("mhwd -a pci free 0300"); + utils::arch_chroot(fmt::format(FMT_COMPILE("mhwd -a pci {} 0300"), drivers_type)); std::ofstream{fmt::format(FMT_COMPILE("{}/.video_installed"), mountpoint)}; #endif tui::exit_done(); - fmt::print("┌{0:─^{4}}┐\n" - "│{1: ^{4}}│\n" - "│{2: ^{4}}│\n" - "│{3: ^{4}}│\n" - "└{0:─^{4}}┘\n", + fmt::print("┌{0:─^{5}}┐\n" + "│{1: ^{5}}│\n" + "│{2: ^{5}}│\n" + "│{3: ^{5}}│\n" + "│{4: ^{5}}│\n" + "└{0:─^{5}}┘\n", "", fmt::format("Kernel: {}", kernel), fmt::format("Desktop: {}", desktop), + fmt::format("Drivers type: {}", drivers_type), fmt::format("Bootloader: {}", bootloader), 80); } diff --git a/src/tui.cpp b/src/tui.cpp index 36d3d4f..55a17b3 100644 --- a/src/tui.cpp +++ b/src/tui.cpp @@ -650,7 +650,7 @@ void install_desktop() noexcept { #endif // Prep variables - const std::vector available_des{"kde", "cutefish", "xfce", "sway", "wayfire", "i3wm", "openbox", "bspwm", "Kofuku edition"}; + const std::vector available_des{"kde", "cutefish", "xfce", "sway", "wayfire", "i3wm", "gnome", "openbox", "bspwm", "Kofuku edition", "lxqt"}; auto screen = ScreenInteractive::Fullscreen(); std::string desktop_env{}; @@ -852,27 +852,19 @@ void auto_partition(bool interactive) noexcept { const auto& device_info = std::get(config_data["DEVICE"]); [[maybe_unused]] const auto& system_info = std::get(config_data["SYSTEM"]); +#ifdef NDEVENV // Find existing partitions (if any) to remove const auto& parts = utils::exec(fmt::format(FMT_COMPILE("parted -s {} print | {}"), device_info, "awk '/^ / {print $1}'")); const auto& del_parts = utils::make_multiline(parts); for (const auto& del_part : del_parts) { -#ifdef NDEVENV utils::exec(fmt::format(FMT_COMPILE("parted -s {} rm {} 2>>/tmp/cachyos-install.log &>/dev/null"), device_info, del_part)); -#else - spdlog::debug("{}", del_part); -#endif } // Clear disk -#ifdef NDEVENV utils::exec(fmt::format(FMT_COMPILE("dd if=/dev/zero of=\"{}\" bs=512 count=1 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); utils::exec(fmt::format(FMT_COMPILE("wipefs -af \"{}\" 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); utils::exec(fmt::format(FMT_COMPILE("sgdisk -Zo \"{}\" 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); -#else - spdlog::debug("Clearing disk..."); -#endif -#ifdef NDEVENV // Identify the partition table const auto& part_table = utils::exec(fmt::format(FMT_COMPILE("parted -s {} print 2>/dev/null | grep -i 'partition table' | {}"), device_info, "awk '{print $3}'")); @@ -1088,7 +1080,7 @@ bool mount_current_partition(bool force) noexcept { /* clang-format off */ // Get mounting options for appropriate filesystems const auto& fs_opts = std::get>(config_data["fs_opts"]); - if (!fs_opts.empty()) { mount_opts(force); } + if (!fs_opts.empty()) { tui::mount_opts(force); } /* clang-format on */ // TODO: use libmount instead. @@ -1756,7 +1748,7 @@ void mount_partitions() noexcept { // Extra check if root is on LUKS or lvm // get_cryptroot // echo "$LUKS_DEV" > /tmp/.luks_dev - // If the root partition is btrfs, offer to create subvolumus + // If the root partition is btrfs, offer to create subvolumes if (utils::exec(fmt::format(FMT_COMPILE("findmnt -no FSTYPE \"{}\""), mountpoint_info)) == "btrfs") { // Check if there are subvolumes already on the btrfs partition const auto& subvolumes = fmt::format(FMT_COMPILE("btrfs subvolume list \"{}\""), mountpoint_info); diff --git a/src/tui.hpp b/src/tui.hpp index 4e320c8..4cabc24 100644 --- a/src/tui.hpp +++ b/src/tui.hpp @@ -3,7 +3,6 @@ namespace tui { bool exit_done() noexcept; - void set_hostname() noexcept; void set_locale() noexcept; void set_xkbmap() noexcept; @@ -11,6 +10,7 @@ bool set_timezone() noexcept; void create_new_user() noexcept; void set_root_password() noexcept; void mount_opts(bool force = false) noexcept; +void lvm_detect() noexcept; bool mount_current_partition(bool force = false) noexcept; void auto_partition(bool interactive = true) noexcept; void create_partitions() noexcept; diff --git a/src/utils.cpp b/src/utils.cpp index 7454f02..f7db06f 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -536,8 +536,8 @@ auto get_pkglist_base(const std::string_view& packages) noexcept -> std::vector< pkg_list.insert(pkg_list.cend(), {"zfs-utils", "linux-cachyos-zfs"}); } pkg_list.insert(pkg_list.cend(), {"amd-ucode", "intel-ucode"}); - pkg_list.insert(pkg_list.cend(), {"base", "base-devel", "zsh", "mhwd-cachyos", "vim", "wget", "micro", "nano", "networkmanager"}); - pkg_list.insert(pkg_list.cend(), {"cachyos", "cachyos-keyring", "cachyos-mirrorlist", "cachyos-v3-mirrorlist", "cachyos-hello", "cachyos-hooks", "cachyos-settings", "cachyos-rate-mirrors", "cachy-browser"}); + pkg_list.insert(pkg_list.cend(), {"base", "base-devel", "zsh", "mhwd-cachyos", "mhwd-nvidia-390xx", "nerd-fonts-meslo", "vim", "wget", "micro", "nano", "networkmanager", "alacritty", "btop"}); + pkg_list.insert(pkg_list.cend(), {"cachyos-keyring", "cachyos-mirrorlist", "cachyos-v3-mirrorlist", "cachyos-hello", "cachyos-hooks", "cachyos-settings", "cachyos-kernel-manager", "cachyos-rate-mirrors", "cachy-browser"}); return pkg_list; } @@ -546,14 +546,16 @@ auto get_pkglist_desktop(const std::string_view& desktop_env) noexcept -> std::v std::vector pkg_list{}; constexpr std::string_view kde{"kde"}; - constexpr std::string_view sway{"sway"}; - constexpr std::string_view i3wm{"i3wm"}; - constexpr std::string_view xfce{"xfce"}; constexpr std::string_view cutefish{"cutefish"}; + constexpr std::string_view xfce{"xfce"}; + constexpr std::string_view sway{"sway"}; constexpr std::string_view wayfire{"wayfire"}; + constexpr std::string_view i3wm{"i3wm"}; + constexpr std::string_view gnome{"gnome"}; constexpr std::string_view openbox{"openbox"}; constexpr std::string_view bspwm{"bspwm"}; constexpr std::string_view kofuku{"Kofuku edition"}; + constexpr std::string_view lxqt{"lxqt"}; bool needed_xorg{}; auto found = ranges::search(desktop_env, i3wm); @@ -563,15 +565,15 @@ auto get_pkglist_desktop(const std::string_view& desktop_env) noexcept -> std::v } found = ranges::search(desktop_env, sway); if (!found.empty()) { - pkg_list.insert(pkg_list.cend(), {"sway", "waybar"}); + pkg_list.insert(pkg_list.cend(), {"sway", "waybar", "wl-clipboard", "egl-wayland", "waybar", "wayland-protocols", "wofi", "ly", "xorg-xhost", "xorg-xwayland"}); } found = ranges::search(desktop_env, kde); if (!found.empty()) { /* clang-format off */ - static constexpr std::array to_be_inserted{"plasma-desktop", "plasma-framework", "plasma-nm", "plasma-pa", "plasma-workspace", + static constexpr std::array to_be_inserted{"ark", "audiocd-kio", "egl-wayland", "plasma-desktop", "plasma-framework", "plasma-nm", "plasma-pa", "plasma-workspace", "plasma-integration", "plasma-firewall", "plasma-browser-integration", "plasma-systemmonitor", "plasma-thunderbolt", - "konsole", "kate", "dolphin", "sddm", "sddm-kcm", "plasma", "plasma-wayland-protocols", "plasma-wayland-session", - "gamemode", "lib32-gamemode", "ksysguard", "pamac-aur", "octopi", "cachyos-kde-settings"}; + "konsole", "kate", "dolphin", "kscreen", "kde-gtk-config", "sddm", "sddm-kcm", "plasma", "plasma-wayland-protocols", "plasma-wayland-session", + "ksysguard", "pamac-aur", "octopi", "cachyos-kde-settings", "xsettingsd"}; /* clang-format on */ pkg_list.insert(pkg_list.end(), std::move_iterator(to_be_inserted.begin()), std::move_iterator(to_be_inserted.end())); @@ -586,9 +588,21 @@ auto get_pkglist_desktop(const std::string_view& desktop_env) noexcept -> std::v std::move_iterator(to_be_inserted.end())); needed_xorg = true; } + found = ranges::search(desktop_env, gnome); + if (!found.empty()) { + /* clang-format off */ + static constexpr std::array to_be_inserted{"adwaita-icon-theme", "cachyos-gnome-settings", "eog", "evince", "file-roller", "gdm", "gedit", "gnome-calculator", + "gnome-control-center", "gnome-disk-utility", "gnome-keyring", "gnome-nettool", "gnome-power-manager", "gnome-screenshot", "gnome-shell", "gnome-terminal", + "gnome-themes-extra", "gnome-tweaks", "gnome-usage", "gvfs", "gvfs-afc", "gvfs-gphoto2", "gvfs-mtp", "gvfs-nfs", "gvfs-smb", "nautilus", + "nautilus-sendto", "sushi", "totem", "xdg-user-dirs-gtk"}; + /* clang-format on */ + pkg_list.insert(pkg_list.end(), std::move_iterator(to_be_inserted.begin()), + std::move_iterator(to_be_inserted.end())); + needed_xorg = true; + } found = ranges::search(desktop_env, cutefish); if (!found.empty()) { - pkg_list.insert(pkg_list.cend(), {"cutefish"}); + pkg_list.insert(pkg_list.cend(), {"fishui", "cutefish", "sddm"}); needed_xorg = true; } found = ranges::search(desktop_env, wayfire); @@ -597,7 +611,19 @@ auto get_pkglist_desktop(const std::string_view& desktop_env) noexcept -> std::v } found = ranges::search(desktop_env, openbox); if (!found.empty()) { - pkg_list.insert(pkg_list.cend(), {"openbox", "obconf"}); + /* clang-format off */ + static constexpr std::array to_be_inserted{"openbox", "obconf", "acpi", "arandr", "archlinux-xdg-menu", "dex", "dmenu", "dunst", "feh", "gtk-engine-murrine", + "gvfs", "gvfs-afc", "gvfs-gphoto2", "gvfs-mtp", "gvfs-nfs", "gvfs-smb", "jgmenu", "jq", "lightdm", "lightdm-slick-greeter", "lxappearance-gtk3", "mpv", "network-manager-applet", + "nitrogen", "pasystray", "cachyos-picom-config", "polkit-gnome", "rofi", "scrot", "slock", "sysstat", "thunar", "thunar-archive-plugin", "thunar-media-tags-plugin", "thunar-volman", + "tint2", "ttf-nerd-fonts-symbols", "tumbler", "xbindkeys", "xcursor-neutral", "xdg-user-dirs-gtk", "xed", "xfce4-terminal"}; + /* clang-format on */ + pkg_list.insert(pkg_list.end(), std::move_iterator(to_be_inserted.begin()), + std::move_iterator(to_be_inserted.end())); + needed_xorg = true; + } + found = ranges::search(desktop_env, lxqt); + if (!found.empty()) { + pkg_list.insert(pkg_list.cend(), {"audiocd-kio", "baka-mplayer", "breeze", "breeze-gtk", "featherpad", "gvfs", "gvfs-mtp", "kio-fuse", "libstatgrab", "libsysstat", "lm_sensors", "lxqt", "lxqt-archiver", "network-manager-applet", "oxygen-icons", "pavucontrol-qt", "print-manager", "qt5-translations", "sddm", "xdg-utils", "xscreensaver", "xsettingsd"}); needed_xorg = true; } found = ranges::search(desktop_env, bspwm); @@ -1596,6 +1622,19 @@ void parse_config() noexcept { assert(doc["bootloader"].IsString()); config_data["BOOTLOADER"] = std::string{doc["bootloader"].GetString()}; } + + std::string drivers_type{"free"}; + if (doc.HasMember("drivers_type")) { + assert(doc["drivers_type"].IsString()); + drivers_type = doc["drivers_type"].GetString(); + + if (drivers_type != "nonfree" && drivers_type != "free") { + spdlog::error("Unknown value: {}!", drivers_type); + drivers_type = "free"; + } + } + + config_data["DRIVERS_TYPE"] = drivers_type; } void setup_luks_keyfile() noexcept { diff --git a/src/utils.hpp b/src/utils.hpp index f4471de..7bbf6a6 100644 --- a/src/utils.hpp +++ b/src/utils.hpp @@ -80,6 +80,27 @@ inline T to_int(const std::string_view& str) { return result; } +template ::value>> +inline T to_floating(const std::string_view& str) { + T result = 0; + std::from_chars(str.data(), str.data() + str.size(), result); + return result; +} + +// convert number, unit to bytes +constexpr inline double convert_unit(const double number, const std::string_view& unit) { + if (unit == "KB" || unit == "K") { // assuming KiB not KB + return number * 1024; + } else if (unit == "MB" || unit == "M") { + return number * 1024 * 1024; + } else if (unit == "GB" || unit == "G") { + return number * 1024 * 1024 * 1024; + } + // for "bytes" + return number; +} + } // namespace utils #endif // UTILS_HPP