mirror of
https://github.com/CachyOS/New-Cli-Installer.git
synced 2025-01-23 05:52:23 +08:00
⚡ Introduce config
The config can be used to automatically install the CachyOS on the target
This commit is contained in:
parent
7fa573d83a
commit
5357735671
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,6 +13,7 @@ subprojects/ftxui
|
||||
subprojects/nlohmann_json-*
|
||||
subprojects/spdlog
|
||||
subprojects/simdjson
|
||||
subprojects/rapidjson
|
||||
subprojects/range-v3
|
||||
subprojects/packagecache
|
||||
|
||||
|
@ -48,9 +48,9 @@ CPMAddPackage(
|
||||
EXCLUDE_FROM_ALL YES
|
||||
)
|
||||
CPMAddPackage(
|
||||
NAME simdjson
|
||||
GITHUB_REPOSITORY simdjson/simdjson
|
||||
GIT_TAG fbe955e9a449c6bbeae69aacfa995795f2100791
|
||||
NAME rapidjson
|
||||
GITHUB_REPOSITORY Tencent/rapidjson
|
||||
GIT_TAG 232389d4f1012dddec4ef84861face2d2ba85709
|
||||
EXCLUDE_FROM_ALL YES
|
||||
)
|
||||
CPMAddPackage(
|
||||
@ -94,6 +94,7 @@ add_executable(${PROJECT_NAME}
|
||||
src/follow_process_log.hpp src/follow_process_log.cpp
|
||||
src/crypto.cpp src/crypto.hpp
|
||||
src/misc.cpp src/misc.hpp
|
||||
src/simple_tui.cpp src/simple_tui.hpp
|
||||
src/tui.cpp src/tui.hpp
|
||||
src/main.cpp
|
||||
)
|
||||
@ -105,6 +106,7 @@ add_executable(test-exec-interactive
|
||||
src/widgets.cpp src/widgets.hpp
|
||||
src/follow_process_log.hpp src/follow_process_log.cpp
|
||||
src/crypto.cpp src/crypto.hpp
|
||||
src/simple_tui.cpp src/simple_tui.hpp
|
||||
src/tui.cpp src/tui.hpp
|
||||
src/main_test.cpp
|
||||
)
|
||||
@ -116,6 +118,7 @@ add_executable(test-process-tailing
|
||||
src/widgets.cpp src/widgets.hpp
|
||||
src/follow_process_log.hpp src/follow_process_log.cpp
|
||||
src/crypto.cpp src/crypto.hpp
|
||||
src/simple_tui.cpp src/simple_tui.hpp
|
||||
src/tui.cpp src/tui.hpp
|
||||
src/test_proccess_tailing.cpp
|
||||
)
|
||||
@ -132,9 +135,9 @@ enable_sanitizers(project_options)
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::screen ftxui::dom ftxui::component cpr::cpr range-v3::range-v3)#simdjson::simdjson)
|
||||
target_link_libraries(test-exec-interactive PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::component cpr::cpr range-v3::range-v3)#simdjson::simdjson)
|
||||
target_link_libraries(test-process-tailing PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::component cpr::cpr)#simdjson::simdjson)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::screen ftxui::dom ftxui::component cpr::cpr range-v3::range-v3)
|
||||
target_link_libraries(test-exec-interactive PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::component cpr::cpr range-v3::range-v3)
|
||||
target_link_libraries(test-process-tailing PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::component cpr::cpr)
|
||||
|
||||
option(ENABLE_UNITY "Enable Unity builds of projects" OFF)
|
||||
if(ENABLE_UNITY)
|
||||
|
@ -36,7 +36,7 @@ endif
|
||||
spdlog = dependency('spdlog', version : ['>=1.9.2'], fallback : ['spdlog', 'spdlog_dep'])
|
||||
fmt = dependency('fmt', version : ['>=8.0.0'], fallback : ['fmt', 'fmt_dep'])
|
||||
ftxui = dependency('ftxui', modules : ['ftxui::screen', 'ftxui::dom', 'ftxui::component'], fallback : ['ftxui', 'ftxui_dep'])
|
||||
simdjson = dependency('simdjson', version : ['>=1.0.2'], fallback : ['simdjson', 'simdjson_dep'])
|
||||
rapidjson = dependency('rapidjson', version : ['>=1.1.0'], fallback : ['rapidjson', 'rapidjson_dep'])
|
||||
cpr = dependency('cpr', version : ['>=1.7.0'], fallback : ['cpr', 'cpr_dep'])
|
||||
ranges = dependency('range-v3', version : ['>=0.11.0'], fallback : ['range-v3', 'range_dep'])
|
||||
#glibmm = dependency('glibmm-2.4', version : ['>=2.56.0'])
|
||||
@ -53,6 +53,7 @@ src_files = files(
|
||||
'src/follow_process_log.cpp', 'src/follow_process_log.hpp',
|
||||
'src/crypto.cpp', 'src/crypto.hpp',
|
||||
'src/misc.cpp', 'src/misc.hpp',
|
||||
'src/simple_tui.cpp', 'src/simple_tui.hpp',
|
||||
'src/tui.cpp', 'src/tui.hpp',
|
||||
'src/main.cpp',
|
||||
)
|
||||
@ -122,7 +123,7 @@ endif
|
||||
|
||||
add_project_arguments(cc.get_supported_arguments(possible_cc_flags), language : 'cpp')
|
||||
|
||||
deps = [fmt, spdlog, ftxui, cpr, ranges]
|
||||
deps = [fmt, spdlog, ftxui, cpr, ranges, rapidjson]
|
||||
|
||||
executable(
|
||||
'cachyos-installer',
|
||||
|
13
settings.json
Normal file
13
settings.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"menus": -1,
|
||||
"fs_name": "btrfs",
|
||||
"device": "/dev/nvme0n1",
|
||||
"locale": "en_US",
|
||||
"user_name": "testuser",
|
||||
"user_pass": "test",
|
||||
"user_shell": "/bin/bash",
|
||||
"root_pass": "secure",
|
||||
"hostname": "cachyos",
|
||||
"xkbmap": "us",
|
||||
"timezone": "America/New_York"
|
||||
}
|
@ -16,6 +16,7 @@ bool Config::initialize() noexcept {
|
||||
s_config = std::make_unique<Config>();
|
||||
if (s_config) {
|
||||
s_config->m_data["hostcache"] = static_cast<std::int32_t>(!fs::exists("/run/miso/bootmnt"));
|
||||
s_config->m_data["menus"] = -1;
|
||||
|
||||
s_config->m_data["H_INIT"] = "openrc";
|
||||
s_config->m_data["SYSTEM"] = "BIOS";
|
||||
|
48
src/disk.cpp
48
src/disk.cpp
@ -1,4 +1,5 @@
|
||||
#include "disk.hpp"
|
||||
#include "config.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "widgets.hpp"
|
||||
|
||||
@ -148,7 +149,7 @@ std::string zfs_list_devs() noexcept {
|
||||
for (const auto& device : devices) {
|
||||
// add the device
|
||||
list_of_devices += fmt::format("{}\n", device);
|
||||
// now lets add any other forms of those devices
|
||||
// now let's add any other forms of those devices
|
||||
list_of_devices += utils::exec(fmt::format("find -L /dev/ -xtype l -samefile {} 2>/dev/null", device));
|
||||
}
|
||||
return list_of_devices;
|
||||
@ -164,4 +165,49 @@ std::string zfs_list_datasets(const std::string_view& type) noexcept {
|
||||
return utils::exec("zfs list -H -o name 2>/dev/null | grep \"/\"");
|
||||
}
|
||||
|
||||
// Other filesystems
|
||||
void select_filesystem(const std::string_view& file_sys) noexcept {
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
|
||||
config_data["FILESYSTEM_NAME"] = std::string{file_sys.data()};
|
||||
|
||||
if (file_sys == "btrfs") {
|
||||
config_data["FILESYSTEM"] = "mkfs.btrfs -f";
|
||||
config_data["fs_opts"] = std::vector<std::string>{"autodefrag", "compress=zlib", "compress=lzo", "compress=zstd", "compress=no", "compress-force=zlib", "compress-force=lzo", "compress-force=zstd", "discard", "noacl", "noatime", "nodatasum", "nospace_cache", "recovery", "skip_balance", "space_cache", "nossd", "ssd", "ssd_spread", "commit=120"};
|
||||
#ifdef NDEVENV
|
||||
utils::exec("modprobe btrfs");
|
||||
#endif
|
||||
} else if (file_sys == "ext2") {
|
||||
config_data["FILESYSTEM"] = "mkfs.ext2 -q";
|
||||
} else if (file_sys == "ext3") {
|
||||
config_data["FILESYSTEM"] = "mkfs.ext3 -q";
|
||||
} else if (file_sys == "ext4") {
|
||||
config_data["FILESYSTEM"] = "mkfs.ext4 -q";
|
||||
config_data["fs_opts"] = std::vector<std::string>{"data=journal", "data=writeback", "dealloc", "discard", "noacl", "noatime", "nobarrier", "nodelalloc"};
|
||||
} else if (file_sys == "f2fs") {
|
||||
config_data["FILESYSTEM"] = "mkfs.f2fs -q";
|
||||
config_data["fs_opts"] = std::vector<std::string>{"data_flush", "disable_roll_forward", "disable_ext_identify", "discard", "fastboot", "flush_merge", "inline_xattr", "inline_data", "inline_dentry", "no_heap", "noacl", "nobarrier", "noextent_cache", "noinline_data", "norecovery"};
|
||||
#ifdef NDEVENV
|
||||
utils::exec("modprobe f2fs");
|
||||
#endif
|
||||
} else if (file_sys == "jfs") {
|
||||
config_data["FILESYSTEM"] = "mkfs.jfs -q";
|
||||
config_data["fs_opts"] = std::vector<std::string>{"discard", "errors=continue", "errors=panic", "nointegrity"};
|
||||
} else if (file_sys == "nilfs2") {
|
||||
config_data["FILESYSTEM"] = "mkfs.nilfs2 -fq";
|
||||
config_data["fs_opts"] = std::vector<std::string>{"discard", "nobarrier", "errors=continue", "errors=panic", "order=relaxed", "order=strict", "norecovery"};
|
||||
} else if (file_sys == "ntfs") {
|
||||
config_data["FILESYSTEM"] = "mkfs.ntfs -q";
|
||||
} else if (file_sys == "reiserfs") {
|
||||
config_data["FILESYSTEM"] = "mkfs.reiserfs -q";
|
||||
config_data["fs_opts"] = std::vector<std::string>{"acl", "nolog", "notail", "replayonly", "user_xattr"};
|
||||
} else if (file_sys == "vfat") {
|
||||
config_data["FILESYSTEM"] = "mkfs.vfat -F32";
|
||||
} else if (file_sys == "xfs") {
|
||||
config_data["FILESYSTEM"] = "mkfs.xfs -f";
|
||||
config_data["fs_opts"] = std::vector<std::string>{"discard", "filestreams", "ikeep", "largeio", "noalign", "nobarrier", "norecovery", "noquota", "wsync"};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
@ -22,6 +22,9 @@ void zfs_create_dataset(const std::string_view& zpath, const std::string_view& z
|
||||
std::string zfs_list_devs() noexcept;
|
||||
std::string zfs_list_datasets(const std::string_view& type = "none") noexcept;
|
||||
|
||||
// Other filesystems
|
||||
void select_filesystem(const std::string_view& fs) noexcept;
|
||||
|
||||
} // namespace utils
|
||||
|
||||
#endif // DISK_HPP
|
||||
|
173
src/simple_tui.cpp
Normal file
173
src/simple_tui.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
#include "simple_tui.hpp"
|
||||
#include "config.hpp"
|
||||
#include "disk.hpp"
|
||||
#include "tui.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "widgets.hpp"
|
||||
|
||||
/* clang-format off */
|
||||
#include <cstdlib> // for setenv
|
||||
#include <sys/mount.h> // for mount
|
||||
#include <fstream> // for ofstream
|
||||
#include <algorithm> // for copy
|
||||
#include <thread> // for thread
|
||||
#include <filesystem> // for exists, is_directory
|
||||
#include <string> // for basic_string
|
||||
#include <ftxui/component/component.hpp> // for Renderer, Button
|
||||
#include <ftxui/component/screen_interactive.hpp> // for Component, ScreenI...
|
||||
#include <ftxui/dom/elements.hpp> // for operator|, size
|
||||
/* clang-format on */
|
||||
|
||||
#include <fmt/ranges.h>
|
||||
|
||||
using namespace ftxui;
|
||||
|
||||
namespace {
|
||||
// Set static list of filesystems rather than on-the-fly. Partially as most require additional flags, and
|
||||
// partially because some don't seem to be viable.
|
||||
// Set static list of filesystems rather than on-the-fly.
|
||||
void select_filesystem() noexcept {
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
// prep variables
|
||||
config_data["fs_opts"] = std::vector<std::string>{};
|
||||
|
||||
const std::vector<std::string> menu_entries = {
|
||||
"btrfs",
|
||||
"ext3",
|
||||
"ext4",
|
||||
"f2fs",
|
||||
"jfs",
|
||||
"nilfs2",
|
||||
"ntfs",
|
||||
"reiserfs",
|
||||
"vfat",
|
||||
"xfs",
|
||||
};
|
||||
|
||||
auto screen = ScreenInteractive::Fullscreen();
|
||||
std::int32_t selected{};
|
||||
bool success{};
|
||||
auto ok_callback = [&] {
|
||||
const auto& src = menu_entries[static_cast<std::size_t>(selected)];
|
||||
const auto& lines = utils::make_multiline(src, false, " ");
|
||||
const auto& file_sys = lines[0];
|
||||
utils::select_filesystem(file_sys.c_str());
|
||||
success = true;
|
||||
screen.ExitLoopClosure()();
|
||||
};
|
||||
static constexpr auto filesystem_body = "\nSelect your filesystem\n";
|
||||
const auto& content_size = size(HEIGHT, LESS_THAN, 10) | size(WIDTH, GREATER_THAN, 40);
|
||||
tui::detail::menu_widget(menu_entries, ok_callback, &selected, &screen, filesystem_body, {size(HEIGHT, LESS_THAN, 18), content_size});
|
||||
|
||||
if (!success) {
|
||||
utils::select_filesystem("btrfs");
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace tui {
|
||||
|
||||
void menu_simple() noexcept {
|
||||
// Prepare
|
||||
utils::umount_partitions();
|
||||
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
|
||||
const auto& device_info = std::get<std::string>(config_data["DEVICE"]);
|
||||
const auto& fs_name = std::get<std::string>(config_data["FILESYSTEM_NAME"]);
|
||||
const auto& mount_opts_info = std::get<std::string>(config_data["MOUNT_OPTS"]);
|
||||
|
||||
const auto& hostname = std::get<std::string>(config_data["HOSTNAME"]);
|
||||
const auto& locale = std::get<std::string>(config_data["LOCALE"]);
|
||||
const auto& xkbmap = std::get<std::string>(config_data["XKBMAP"]);
|
||||
const auto& timezone = std::get<std::string>(config_data["TIMEZONE"]);
|
||||
|
||||
const auto& user_name = std::get<std::string>(config_data["USER_NAME"]);
|
||||
const auto& user_pass = std::get<std::string>(config_data["USER_PASS"]);
|
||||
const auto& user_shell = std::get<std::string>(config_data["USER_SHELL"]);
|
||||
const auto& root_pass = std::get<std::string>(config_data["ROOT_PASS"]);
|
||||
|
||||
if (device_info.empty()) {
|
||||
tui::select_device();
|
||||
}
|
||||
tui::auto_partition(false);
|
||||
|
||||
// Target FS
|
||||
if (fs_name.empty()) {
|
||||
select_filesystem();
|
||||
} else {
|
||||
utils::select_filesystem(fs_name);
|
||||
}
|
||||
tui::mount_current_partition(true);
|
||||
/* clang-format on */
|
||||
|
||||
utils::generate_fstab("genfstab -U");
|
||||
|
||||
if (hostname.empty()) {
|
||||
tui::set_hostname();
|
||||
} else {
|
||||
utils::set_hostname(hostname);
|
||||
}
|
||||
|
||||
if (locale.empty()) {
|
||||
tui::set_locale();
|
||||
} else {
|
||||
utils::set_locale(locale);
|
||||
}
|
||||
|
||||
if (xkbmap.empty()) {
|
||||
tui::set_xkbmap();
|
||||
} else {
|
||||
utils::set_xkbmap(xkbmap);
|
||||
}
|
||||
|
||||
if (timezone.empty()) {
|
||||
tui::set_timezone();
|
||||
} else {
|
||||
utils::set_timezone(timezone);
|
||||
}
|
||||
|
||||
utils::set_hw_clock("utc");
|
||||
|
||||
if (root_pass.empty()) {
|
||||
tui::set_root_password();
|
||||
} else {
|
||||
utils::set_root_password(root_pass);
|
||||
}
|
||||
|
||||
if (user_name.empty()) {
|
||||
tui::create_new_user();
|
||||
} else {
|
||||
utils::create_new_user(user_name, user_pass, user_shell);
|
||||
}
|
||||
|
||||
fmt::print("┌{0:─^{5}}┐\n"
|
||||
"│{1: ^{5}}│\n"
|
||||
"│{2: ^{5}}│\n"
|
||||
"│{3: ^{5}}│\n"
|
||||
"│{4: ^{5}}│\n"
|
||||
"└{0:─^{5}}┘\n",
|
||||
"",
|
||||
fmt::format("Mountpoint: {}", mountpoint),
|
||||
fmt::format("Your device: {}", device_info),
|
||||
fmt::format("Filesystem: {}", fs_name),
|
||||
fmt::format("Filesystem opts: {}", mount_opts_info), 80);
|
||||
|
||||
// tui::mount_partitions();
|
||||
//
|
||||
// // Install process
|
||||
// if (!utils::check_mount()) {
|
||||
// spdlog::error("Your partitions are not mounted");
|
||||
// }
|
||||
// tui::install_base();
|
||||
// tui::install_desktop();
|
||||
// if (!utils::check_base()) {
|
||||
// spdlog::error("Base is not installed");
|
||||
// }
|
||||
// tui::install_bootloader();
|
||||
// tui::config_base_menu();
|
||||
}
|
||||
|
||||
} // namespace tui
|
8
src/simple_tui.hpp
Normal file
8
src/simple_tui.hpp
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef SIMPLE_TUI_HPP
|
||||
#define SIMPLE_TUI_HPP
|
||||
|
||||
namespace tui {
|
||||
void menu_simple() noexcept;
|
||||
} // namespace tui
|
||||
|
||||
#endif // SIMPLE_TUI_HPP
|
258
src/tui.cpp
258
src/tui.cpp
@ -5,6 +5,7 @@
|
||||
#include "disk.hpp"
|
||||
#include "drivers.hpp"
|
||||
#include "misc.hpp"
|
||||
#include "simple_tui.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "widgets.hpp"
|
||||
|
||||
@ -127,6 +128,7 @@ void generate_fstab() noexcept {
|
||||
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
|
||||
|
||||
auto screen = ScreenInteractive::Fullscreen();
|
||||
std::string fstab_cmd{};
|
||||
std::int32_t selected{};
|
||||
auto ok_callback = [&] {
|
||||
if (system_info == "BIOS" && selected == 3) {
|
||||
@ -134,36 +136,17 @@ void generate_fstab() noexcept {
|
||||
detail::msgbox_widget(FstabErr);
|
||||
return;
|
||||
}
|
||||
#ifdef NDEVENV
|
||||
const auto& src = menu_entries[static_cast<std::size_t>(selected)];
|
||||
utils::exec(fmt::format(FMT_COMPILE("{0} {1} > {1}/etc/fstab"), src, mountpoint));
|
||||
spdlog::info("Created fstab file:\n");
|
||||
utils::exec(fmt::format(FMT_COMPILE("cat {}/etc/fstab >> /tmp/cachyos-install.log"), mountpoint));
|
||||
#endif
|
||||
const auto& swap_file = fmt::format(FMT_COMPILE("{}/swapfile"), mountpoint);
|
||||
if (fs::exists(swap_file) && fs::is_regular_file(swap_file)) {
|
||||
spdlog::info("appending swapfile to the fstab..");
|
||||
#ifdef NDEVENV
|
||||
utils::exec(fmt::format(FMT_COMPILE("sed -i \"s/\\\\{0}//\" {0}/etc/fstab"), mountpoint));
|
||||
#endif
|
||||
}
|
||||
fstab_cmd = menu_entries[static_cast<std::size_t>(selected)];
|
||||
screen.ExitLoopClosure()();
|
||||
};
|
||||
/* clang-format off */
|
||||
if (fstab_cmd.empty()) { return; }
|
||||
/* clang-format on */
|
||||
|
||||
utils::generate_fstab(fstab_cmd);
|
||||
|
||||
static constexpr auto fstab_body = "\nThe FSTAB file (File System TABle) sets what storage devices\nand partitions are to be mounted, and how they are to be used.\n\nUUID (Universally Unique IDentifier) is recommended.\n\nIf no labels were set for the partitions earlier,\ndevice names will be used for the label option.\n";
|
||||
detail::menu_widget(menu_entries, ok_callback, &selected, &screen, fstab_body);
|
||||
|
||||
#ifdef NDEVENV
|
||||
// Edit fstab in case of btrfs subvolumes
|
||||
utils::exec(fmt::format(FMT_COMPILE("sed -i \"s/subvolid=.*,subvol=\\/.*,//g\" {}/etc/fstab"), mountpoint));
|
||||
|
||||
// remove any zfs datasets that are mounted by zfs
|
||||
const auto& msource_list = utils::make_multiline(utils::exec(fmt::format(FMT_COMPILE("cat {}/etc/fstab | grep \"^[a-z,A-Z]\" | {}"), mountpoint, "awk '{print $1}'")));
|
||||
for (const auto& msource : msource_list) {
|
||||
if (utils::exec(fmt::format(FMT_COMPILE("zfs list -H -o mountpoint,name | grep \"^/\" | {} | grep \"^{}$\""), "awk '{print $2}'", msource), true) == "0")
|
||||
utils::exec(fmt::format(FMT_COMPILE("sed -e \"\\|^{}[[:space:]]| s/^#*/#/\" -i {}/etc/fstab"), msource, mountpoint));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set system hostname
|
||||
@ -178,14 +161,7 @@ void set_hostname() noexcept {
|
||||
if (hostname.empty()) { return; }
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef NDEVENV
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
|
||||
utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" > {}/etc/hostname"), hostname, mountpoint));
|
||||
const auto& cmd = fmt::format(FMT_COMPILE("echo -e \"#<ip-address>\\t<hostname.domain.org>\\t<hostname>\\n127.0.0.1\\tlocalhost.localdomain\\tlocalhost\\t{0}\\n::1\\tlocalhost.localdomain\\tlocalhost\\t{0}\">{1}/etc/hosts"), hostname, mountpoint);
|
||||
utils::exec(cmd);
|
||||
#endif
|
||||
utils::set_hostname(hostname);
|
||||
}
|
||||
|
||||
// Set system language
|
||||
@ -210,33 +186,7 @@ void set_locale() noexcept {
|
||||
if (locale.empty()) { return; }
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef NDEVENV
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
|
||||
const auto& locale_config_path = fmt::format(FMT_COMPILE("{}/etc/locale.conf"), mountpoint);
|
||||
const auto& locale_gen_path = fmt::format(FMT_COMPILE("{}/etc/locale.gen"), mountpoint);
|
||||
|
||||
static constexpr auto locale_config_part = R"(LANG="{0}"
|
||||
LC_NUMERIC="{0}"
|
||||
LC_TIME="{0}"
|
||||
LC_MONETARY="{0}"
|
||||
LC_PAPER="{0}"
|
||||
LC_NAME="{0}"
|
||||
LC_ADDRESS="{0}"
|
||||
LC_TELEPHONE="{0}"
|
||||
LC_MEASUREMENT="{0}"
|
||||
LC_IDENTIFICATION="{0}"
|
||||
LC_MESSAGES="{0}")";
|
||||
|
||||
std::ofstream locale_config_file{locale_config_path};
|
||||
locale_config_file << fmt::format(locale_config_part, locale);
|
||||
|
||||
utils::exec(fmt::format(FMT_COMPILE("sed -i \"s/#{0}/{0}/\" {1}"), locale, locale_gen_path));
|
||||
|
||||
// Generate locales
|
||||
utils::arch_chroot("locale-gen", false);
|
||||
#endif
|
||||
utils::set_locale(locale);
|
||||
}
|
||||
|
||||
// Set keymap for X11
|
||||
@ -263,13 +213,7 @@ void set_xkbmap() noexcept {
|
||||
if (!success) { return; }
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef NDEVENV
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
|
||||
|
||||
utils::exec(fmt::format(FMT_COMPILE("echo -e \"Section \"\\\"InputClass\"\\\"\\nIdentifier \"\\\"system-keyboard\"\\\"\\nMatchIsKeyboard \"\\\"on\"\\\"\\nOption \"\\\"XkbLayout\"\\\" \"\\\"{0}\"\\\"\\nEndSection\" > {1}/etc/X11/xorg.conf.d/00-keyboard.conf"), xkbmap_choice, mountpoint));
|
||||
#endif
|
||||
utils::set_xkbmap(xkbmap_choice);
|
||||
}
|
||||
|
||||
void select_keymap() noexcept {
|
||||
@ -347,10 +291,8 @@ bool set_timezone() noexcept {
|
||||
if (!do_set_timezone) { return false; }
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef NDEVENV
|
||||
utils::arch_chroot(fmt::format(FMT_COMPILE("ln -sf /usr/share/zoneinfo/{}/{} /etc/localtime"), zone, subzone), false);
|
||||
#endif
|
||||
spdlog::info("Timezone is set to {}/{}", zone, subzone);
|
||||
utils::set_timezone(fmt::format(FMT_COMPILE("{}/{}"), zone, subzone));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -360,10 +302,8 @@ void set_hw_clock() noexcept {
|
||||
const std::vector<std::string> menu_entries{"utc", "localtime"};
|
||||
std::int32_t selected{};
|
||||
auto ok_callback = [&] {
|
||||
#ifdef NDEVENV
|
||||
const auto& clock_type = menu_entries[static_cast<std::size_t>(selected)];
|
||||
utils::arch_chroot(fmt::format(FMT_COMPILE("hwclock --systohc --{}"), clock_type), false);
|
||||
#endif
|
||||
utils::set_hw_clock(clock_type);
|
||||
screen.ExitLoopClosure()();
|
||||
};
|
||||
|
||||
@ -390,17 +330,7 @@ void set_root_password() noexcept {
|
||||
detail::msgbox_widget(PassErrBody);
|
||||
tui::set_root_password();
|
||||
}
|
||||
|
||||
#ifdef NDEVENV
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
|
||||
|
||||
std::error_code err{};
|
||||
utils::exec(fmt::format(FMT_COMPILE("echo -e \"{}\n{}\" > /tmp/.passwd"), pass, confirm));
|
||||
utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} passwd root < /tmp/.passwd &>/dev/null"), mountpoint));
|
||||
fs::remove("/tmp/.passwd", err);
|
||||
#endif
|
||||
utils::set_root_password(pass);
|
||||
}
|
||||
|
||||
// Create user on the system
|
||||
@ -420,12 +350,6 @@ void create_new_user() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NDEVENV
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
|
||||
#endif
|
||||
|
||||
std::string_view shell{};
|
||||
{
|
||||
static constexpr auto DefShell = "\nChoose the default shell.\n";
|
||||
@ -455,19 +379,8 @@ void create_new_user() noexcept {
|
||||
screen.ExitLoopClosure()();
|
||||
};
|
||||
detail::radiolist_widget(radiobox_list, ok_callback, &selected, &screen, {.text = shells_options_body}, {.text_size = nothing});
|
||||
|
||||
#ifdef NDEVENV
|
||||
if (selected != 1) {
|
||||
const auto& packages = fmt::format(FMT_COMPILE("cachyos-{}-config"), (selected == 0) ? "zsh" : "fish");
|
||||
const auto& hostcache = std::get<std::int32_t>(config_data["hostcache"]);
|
||||
const auto& cmd = (hostcache) ? "pacstrap" : "pacstrap -c";
|
||||
detail::follow_process_log_widget({"/bin/sh", "-c", fmt::format(FMT_COMPILE("{} {} {} |& tee /tmp/pacstrap.log"), cmd, mountpoint, packages)});
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
spdlog::info("default shell: [{}]", shell);
|
||||
|
||||
// Enter password. This step will only be reached where the loop has been skipped or broken.
|
||||
std::string pass{};
|
||||
static constexpr auto user_pass_body = "Enter password for";
|
||||
@ -497,32 +410,7 @@ void create_new_user() noexcept {
|
||||
detail::infobox_widget("\nCreating User and setting groups...\n");
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
|
||||
#ifdef NDEVENV
|
||||
// Create the user, set password, then remove temporary password file
|
||||
utils::arch_chroot("groupadd sudo", false);
|
||||
utils::arch_chroot(fmt::format(FMT_COMPILE("groupadd {}"), user), false);
|
||||
utils::arch_chroot(fmt::format(FMT_COMPILE("useradd {0} -m -g {0} -G sudo,storage,power,network,video,audio,lp,sys,input -s {1}"), user, shell), false);
|
||||
spdlog::info("add user to groups");
|
||||
|
||||
// check if user has been created
|
||||
const auto& user_check = utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} getent passwd {}"), mountpoint, user));
|
||||
if (user_check.empty()) {
|
||||
spdlog::error("User has not been created!");
|
||||
}
|
||||
std::error_code err{};
|
||||
utils::exec(fmt::format(FMT_COMPILE("echo -e \"{}\\n{}\" > /tmp/.passwd"), pass, confirm));
|
||||
const auto& ret_status = utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} passwd {} < /tmp/.passwd &>/dev/null"), mountpoint, user), true);
|
||||
spdlog::info("create user pwd: {}", ret_status);
|
||||
fs::remove("/tmp/.passwd", err);
|
||||
|
||||
// Set up basic configuration files and permissions for user
|
||||
// arch_chroot "cp /etc/skel/.bashrc /home/${USER}"
|
||||
utils::arch_chroot(fmt::format(FMT_COMPILE("chown -R {0}:{0} /home/{0}"), user), false);
|
||||
const auto& sudoers_file = fmt::format(FMT_COMPILE("{}/etc/sudoers"), mountpoint);
|
||||
if (fs::exists(sudoers_file)) {
|
||||
utils::exec(fmt::format(FMT_COMPILE("sed -i '/NOPASSWD/!s/# %sudo/%sudo/g' {}"), sudoers_file));
|
||||
}
|
||||
#endif
|
||||
utils::create_new_user(user, pass, shell);
|
||||
}
|
||||
|
||||
// Install pkgs from user input
|
||||
@ -1441,7 +1329,7 @@ void install_bootloader() noexcept {
|
||||
}
|
||||
|
||||
// BIOS and UEFI
|
||||
void auto_partition() noexcept {
|
||||
void auto_partition(bool interactive) noexcept {
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
|
||||
@ -1488,6 +1376,10 @@ void auto_partition() noexcept {
|
||||
utils::exec(fmt::format(FMT_COMPILE("parted -s {} mkpart primary ext3 513MiB 100% 2>>/tmp/cachyos-install.log &>/dev/null"), device_info));
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
if (!interactive) { return; }
|
||||
/* clang-format on */
|
||||
|
||||
// Show created partitions
|
||||
const auto& disk_list = utils::exec(fmt::format(FMT_COMPILE("lsblk {} -o NAME,TYPE,FSTYPE,SIZE"), device_info));
|
||||
detail::msgbox_widget(disk_list, size(HEIGHT, GREATER_THAN, 5));
|
||||
@ -1533,7 +1425,6 @@ bool select_device() noexcept {
|
||||
|
||||
// Set static list of filesystems rather than on-the-fly. Partially as most require additional flags, and
|
||||
// partially because some don't seem to be viable.
|
||||
// Set static list of filesystems rather than on-the-fly.
|
||||
bool select_filesystem() noexcept {
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
@ -1562,42 +1453,7 @@ bool select_filesystem() noexcept {
|
||||
const auto& src = menu_entries[static_cast<std::size_t>(selected)];
|
||||
const auto& lines = utils::make_multiline(src, false, " ");
|
||||
const auto& file_sys = lines[0];
|
||||
if (file_sys == "btrfs") {
|
||||
config_data["FILESYSTEM"] = "mkfs.btrfs -f";
|
||||
config_data["fs_opts"] = std::vector<std::string>{"autodefrag", "compress=zlib", "compress=lzo", "compress=zstd", "compress=no", "compress-force=zlib", "compress-force=lzo", "compress-force=zstd", "discard", "noacl", "noatime", "nodatasum", "nospace_cache", "recovery", "skip_balance", "space_cache", "nossd", "ssd", "ssd_spread", "commit=120"};
|
||||
#ifdef NDEVENV
|
||||
utils::exec("modprobe btrfs");
|
||||
#endif
|
||||
} else if (file_sys == "ext2") {
|
||||
config_data["FILESYSTEM"] = "mkfs.ext2 -q";
|
||||
} else if (file_sys == "ext3") {
|
||||
config_data["FILESYSTEM"] = "mkfs.ext3 -q";
|
||||
} else if (file_sys == "ext4") {
|
||||
config_data["FILESYSTEM"] = "mkfs.ext4 -q";
|
||||
config_data["fs_opts"] = std::vector<std::string>{"data=journal", "data=writeback", "dealloc", "discard", "noacl", "noatime", "nobarrier", "nodelalloc"};
|
||||
} else if (file_sys == "f2fs") {
|
||||
config_data["FILESYSTEM"] = "mkfs.f2fs -q";
|
||||
config_data["fs_opts"] = std::vector<std::string>{"data_flush", "disable_roll_forward", "disable_ext_identify", "discard", "fastboot", "flush_merge", "inline_xattr", "inline_data", "inline_dentry", "no_heap", "noacl", "nobarrier", "noextent_cache", "noinline_data", "norecovery"};
|
||||
#ifdef NDEVENV
|
||||
utils::exec("modprobe f2fs");
|
||||
#endif
|
||||
} else if (file_sys == "jfs") {
|
||||
config_data["FILESYSTEM"] = "mkfs.jfs -q";
|
||||
config_data["fs_opts"] = std::vector<std::string>{"discard", "errors=continue", "errors=panic", "nointegrity"};
|
||||
} else if (file_sys == "nilfs2") {
|
||||
config_data["FILESYSTEM"] = "mkfs.nilfs2 -fq";
|
||||
config_data["fs_opts"] = std::vector<std::string>{"discard", "nobarrier", "errors=continue", "errors=panic", "order=relaxed", "order=strict", "norecovery"};
|
||||
} else if (file_sys == "ntfs") {
|
||||
config_data["FILESYSTEM"] = "mkfs.ntfs -q";
|
||||
} else if (file_sys == "reiserfs") {
|
||||
config_data["FILESYSTEM"] = "mkfs.reiserfs -q";
|
||||
config_data["fs_opts"] = std::vector<std::string>{"acl", "nolog", "notail", "replayonly", "user_xattr"};
|
||||
} else if (file_sys == "vfat") {
|
||||
config_data["FILESYSTEM"] = "mkfs.vfat -F32";
|
||||
} else if (file_sys == "xfs") {
|
||||
config_data["FILESYSTEM"] = "mkfs.xfs -f";
|
||||
config_data["fs_opts"] = std::vector<std::string>{"discard", "filestreams", "ikeep", "largeio", "noalign", "nobarrier", "norecovery", "noquota", "wsync"};
|
||||
}
|
||||
utils::select_filesystem(file_sys.c_str());
|
||||
success = true;
|
||||
screen.ExitLoopClosure()();
|
||||
};
|
||||
@ -1625,7 +1481,7 @@ bool select_filesystem() noexcept {
|
||||
|
||||
// This subfunction allows for special mounting options to be applied for relevant fs's.
|
||||
// Separate subfunction for neatness.
|
||||
void mount_opts() noexcept {
|
||||
void mount_opts(bool force) noexcept {
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
|
||||
@ -1657,9 +1513,22 @@ void mount_opts() noexcept {
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
auto screen = ScreenInteractive::Fullscreen();
|
||||
auto& mount_opts_info = std::get<std::string>(config_data["MOUNT_OPTS"]);
|
||||
auto ok_callback = [&] {
|
||||
|
||||
// Now clean up the file
|
||||
auto cleaup_mount_opts = [](auto& opts_info) {
|
||||
opts_info = utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | sed 's/ /,/g'"), opts_info));
|
||||
opts_info = utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | sed '$s/,$//'"), opts_info));
|
||||
};
|
||||
|
||||
if (force) {
|
||||
mount_opts_info = detail::from_checklist_string(fs_opts, fs_opts_state.get());
|
||||
cleaup_mount_opts(mount_opts_info);
|
||||
return;
|
||||
}
|
||||
|
||||
auto screen = ScreenInteractive::Fullscreen();
|
||||
auto ok_callback = [&] {
|
||||
mount_opts_info = detail::from_checklist_string(fs_opts, fs_opts_state.get());
|
||||
screen.ExitLoopClosure()();
|
||||
};
|
||||
@ -1670,10 +1539,7 @@ void mount_opts() noexcept {
|
||||
|
||||
static constexpr auto mount_options_body = "\nUse [Space] to de/select the desired mount\noptions and review carefully. Please do not\nselect multiple versions of the same option.\n";
|
||||
detail::checklist_widget(fs_opts, ok_callback, fs_opts_state.get(), &screen, mount_options_body, fs_title, {content_size, nothing});
|
||||
|
||||
// Now clean up the file
|
||||
mount_opts_info = utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | sed 's/ /,/g'"), mount_opts_info));
|
||||
mount_opts_info = utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | sed '$s/,$//'"), mount_opts_info));
|
||||
cleaup_mount_opts(mount_opts_info);
|
||||
|
||||
// If mount options selected, confirm choice
|
||||
if (!mount_opts_info.empty()) {
|
||||
@ -1688,7 +1554,7 @@ void mount_opts() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
bool mount_current_partition() noexcept {
|
||||
bool mount_current_partition(bool force) noexcept {
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
|
||||
@ -1706,7 +1572,7 @@ bool mount_current_partition() noexcept {
|
||||
/* clang-format off */
|
||||
// Get mounting options for appropriate filesystems
|
||||
const auto& fs_opts = std::get<std::vector<std::string>>(config_data["fs_opts"]);
|
||||
if (!fs_opts.empty()) { mount_opts(); }
|
||||
if (!fs_opts.empty()) { mount_opts(force); }
|
||||
/* clang-format on */
|
||||
|
||||
// TODO: use libmount instead.
|
||||
@ -1723,7 +1589,10 @@ bool mount_current_partition() noexcept {
|
||||
spdlog::info("{}", mount_status);
|
||||
}
|
||||
#endif
|
||||
confirm_mount(fmt::format(FMT_COMPILE("{}{}"), mountpoint, mount_dev));
|
||||
|
||||
/* clang-format off */
|
||||
if (!force) { confirm_mount(fmt::format(FMT_COMPILE("{}{}"), mountpoint, mount_dev)); }
|
||||
/* clang-format on */
|
||||
|
||||
// Identify if mounted partition is type "crypt" (LUKS on LVM, or LUKS alone)
|
||||
if (!utils::exec(fmt::format(FMT_COMPILE("lsblk -lno TYPE {} | grep \"crypt\""), partition)).empty()) {
|
||||
@ -2828,29 +2697,20 @@ void menu_advanced() noexcept {
|
||||
detail::menu_widget(menu_entries, ok_callback, &selected, &screen);
|
||||
}
|
||||
|
||||
void menu_simple() noexcept {
|
||||
// Prepare
|
||||
utils::umount_partitions();
|
||||
if (tui::select_device()) {
|
||||
tui::create_partitions();
|
||||
}
|
||||
tui::mount_partitions();
|
||||
|
||||
// Install process
|
||||
if (!utils::check_mount()) {
|
||||
spdlog::error("Your partitions are not mounted");
|
||||
}
|
||||
tui::install_base();
|
||||
tui::install_desktop();
|
||||
if (!utils::check_base()) {
|
||||
spdlog::error("Base is not installed");
|
||||
}
|
||||
tui::install_bootloader();
|
||||
tui::config_base_menu();
|
||||
}
|
||||
|
||||
void init() noexcept {
|
||||
#if 0
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
const auto& menus = std::get<std::int32_t>(config_data["menus"]);
|
||||
utils::parse_config();
|
||||
|
||||
if (menus == 1) {
|
||||
tui::menu_simple();
|
||||
return;
|
||||
} else if (menus == 2) {
|
||||
tui::menu_advanced();
|
||||
return;
|
||||
}
|
||||
|
||||
const std::vector<std::string> menu_entries = {
|
||||
"Simple installation",
|
||||
"Advanced installation",
|
||||
@ -2878,8 +2738,6 @@ void init() noexcept {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
tui::menu_advanced();
|
||||
}
|
||||
|
||||
} // namespace tui
|
||||
|
@ -2,6 +2,15 @@
|
||||
#define TUI_HPP
|
||||
|
||||
namespace tui {
|
||||
void set_hostname() noexcept;
|
||||
void set_locale() noexcept;
|
||||
void set_xkbmap() noexcept;
|
||||
bool set_timezone() noexcept;
|
||||
void create_new_user() noexcept;
|
||||
void set_root_password() noexcept;
|
||||
void mount_opts(bool force = false) noexcept;
|
||||
bool mount_current_partition(bool force = false) noexcept;
|
||||
void auto_partition(bool interactive = true) noexcept;
|
||||
void create_partitions() noexcept;
|
||||
bool select_device() noexcept;
|
||||
void init() noexcept;
|
||||
|
232
src/utils.cpp
232
src/utils.cpp
@ -39,6 +39,9 @@
|
||||
#include <range/v3/view/split.hpp>
|
||||
#include <range/v3/view/transform.hpp>
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
#include <rapidjson/istreamwrapper.h>
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
@ -306,6 +309,160 @@ void secure_wipe() noexcept {
|
||||
#endif
|
||||
}
|
||||
|
||||
void generate_fstab(const std::string_view& fstab_cmd) noexcept {
|
||||
spdlog::info("Generating with fstab '{}'", fstab_cmd);
|
||||
|
||||
#ifdef NDEVENV
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
|
||||
utils::exec(fmt::format(FMT_COMPILE("{0} {1} > {1}/etc/fstab"), fstab_cmd, mountpoint));
|
||||
spdlog::info("Created fstab file:\n");
|
||||
utils::exec(fmt::format(FMT_COMPILE("cat {}/etc/fstab >> /tmp/cachyos-install.log"), mountpoint));
|
||||
|
||||
const auto& swap_file = fmt::format(FMT_COMPILE("{}/swapfile"), mountpoint);
|
||||
if (fs::exists(swap_file) && fs::is_regular_file(swap_file)) {
|
||||
spdlog::info("appending swapfile to the fstab..");
|
||||
utils::exec(fmt::format(FMT_COMPILE("sed -i \"s/\\\\{0}//\" {0}/etc/fstab"), mountpoint));
|
||||
}
|
||||
|
||||
// Edit fstab in case of btrfs subvolumes
|
||||
utils::exec(fmt::format(FMT_COMPILE("sed -i \"s/subvolid=.*,subvol=\\/.*,//g\" {}/etc/fstab"), mountpoint));
|
||||
|
||||
// remove any zfs datasets that are mounted by zfs
|
||||
const auto& msource_list = utils::make_multiline(utils::exec(fmt::format(FMT_COMPILE("cat {}/etc/fstab | grep \"^[a-z,A-Z]\" | {}"), mountpoint, "awk '{print $1}'")));
|
||||
for (const auto& msource : msource_list) {
|
||||
if (utils::exec(fmt::format(FMT_COMPILE("zfs list -H -o mountpoint,name | grep \"^/\" | {} | grep \"^{}$\""), "awk '{print $2}'", msource), true) == "0")
|
||||
utils::exec(fmt::format(FMT_COMPILE("sed -e \"\\|^{}[[:space:]]| s/^#*/#/\" -i {}/etc/fstab"), msource, mountpoint));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set system hostname
|
||||
void set_hostname(const std::string_view& hostname) noexcept {
|
||||
spdlog::info("Setting hostname {}", hostname);
|
||||
#ifdef NDEVENV
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
|
||||
utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" > {}/etc/hostname"), hostname, mountpoint));
|
||||
const auto& cmd = fmt::format(FMT_COMPILE("echo -e \"#<ip-address>\\t<hostname.domain.org>\\t<hostname>\\n127.0.0.1\\tlocalhost.localdomain\\tlocalhost\\t{0}\\n::1\\tlocalhost.localdomain\\tlocalhost\\t{0}\">{1}/etc/hosts"), hostname, mountpoint);
|
||||
utils::exec(cmd);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set system language
|
||||
void set_locale(const std::string_view& locale) noexcept {
|
||||
spdlog::info("Selected locale: {}", locale);
|
||||
#ifdef NDEVENV
|
||||
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
|
||||
const auto& locale_config_path = fmt::format(FMT_COMPILE("{}/etc/locale.conf"), mountpoint);
|
||||
const auto& locale_gen_path = fmt::format(FMT_COMPILE("{}/etc/locale.gen"), mountpoint);
|
||||
|
||||
static constexpr auto locale_config_part = R"(LANG="{0}"
|
||||
LC_NUMERIC="{0}"
|
||||
LC_TIME="{0}"
|
||||
LC_MONETARY="{0}"
|
||||
LC_PAPER="{0}"
|
||||
LC_NAME="{0}"
|
||||
LC_ADDRESS="{0}"
|
||||
LC_TELEPHONE="{0}"
|
||||
LC_MEASUREMENT="{0}"
|
||||
LC_IDENTIFICATION="{0}"
|
||||
LC_MESSAGES="{0}")";
|
||||
|
||||
std::ofstream locale_config_file{locale_config_path};
|
||||
locale_config_file << fmt::format(locale_config_part, locale);
|
||||
|
||||
utils::exec(fmt::format(FMT_COMPILE("sed -i \"s/#{0}/{0}/\" {1}"), locale, locale_gen_path));
|
||||
|
||||
// Generate locales
|
||||
utils::arch_chroot("locale-gen", false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_xkbmap(const std::string_view& xkbmap) noexcept {
|
||||
spdlog::info("Selected xkbmap: {}", xkbmap);
|
||||
#ifdef NDEVENV
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
|
||||
|
||||
utils::exec(fmt::format(FMT_COMPILE("echo -e \"Section \"\\\"InputClass\"\\\"\\nIdentifier \"\\\"system-keyboard\"\\\"\\nMatchIsKeyboard \"\\\"on\"\\\"\\nOption \"\\\"XkbLayout\"\\\" \"\\\"{0}\"\\\"\\nEndSection\" > {1}/etc/X11/xorg.conf.d/00-keyboard.conf"), xkbmap, mountpoint));
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_timezone(const std::string_view& timezone) noexcept {
|
||||
spdlog::info("Timezone is set to {}", timezone);
|
||||
#ifdef NDEVENV
|
||||
utils::arch_chroot(fmt::format(FMT_COMPILE("ln -sf /usr/share/zoneinfo/{} /etc/localtime"), timezone), false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_hw_clock(const std::string_view& clock_type) noexcept {
|
||||
spdlog::info("Clock type is: {}", clock_type);
|
||||
#ifdef NDEVENV
|
||||
utils::arch_chroot(fmt::format(FMT_COMPILE("hwclock --systohc --{}"), clock_type), false);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Create user on the system
|
||||
void create_new_user(const std::string_view& user, const std::string_view& password, const std::string_view& shell) noexcept {
|
||||
spdlog::info("default shell: [{}]", shell);
|
||||
|
||||
#ifdef NDEVENV
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
|
||||
|
||||
if (shell.ends_with("zsh") || shell.ends_with("fish")) {
|
||||
const auto& packages = fmt::format(FMT_COMPILE("cachyos-{}-config"), (shell.ends_with("zsh")) ? "zsh" : "fish");
|
||||
const auto& hostcache = std::get<std::int32_t>(config_data["hostcache"]);
|
||||
const auto& cmd = (hostcache) ? "pacstrap" : "pacstrap -c";
|
||||
tui::detail::follow_process_log_widget({"/bin/sh", "-c", fmt::format(FMT_COMPILE("{} {} {} |& tee /tmp/pacstrap.log"), cmd, mountpoint, packages)});
|
||||
}
|
||||
|
||||
// Create the user, set password, then remove temporary password file
|
||||
utils::arch_chroot("groupadd sudo", false);
|
||||
utils::arch_chroot(fmt::format(FMT_COMPILE("groupadd {}"), user), false);
|
||||
utils::arch_chroot(fmt::format(FMT_COMPILE("useradd {0} -m -g {0} -G sudo,storage,power,network,video,audio,lp,sys,input -s {1}"), user, shell), false);
|
||||
spdlog::info("add user to groups");
|
||||
|
||||
// check if user has been created
|
||||
const auto& user_check = utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} getent passwd {}"), mountpoint, user));
|
||||
if (user_check.empty()) {
|
||||
spdlog::error("User has not been created!");
|
||||
}
|
||||
std::error_code err{};
|
||||
utils::exec(fmt::format(FMT_COMPILE("echo -e \"{0}\\n{0}\" > /tmp/.passwd"), password));
|
||||
const auto& ret_status = utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} passwd {} < /tmp/.passwd &>/dev/null"), mountpoint, user), true);
|
||||
spdlog::info("create user pwd: {}", ret_status);
|
||||
fs::remove("/tmp/.passwd", err);
|
||||
|
||||
// Set up basic configuration files and permissions for user
|
||||
// arch_chroot "cp /etc/skel/.bashrc /home/${USER}"
|
||||
utils::arch_chroot(fmt::format(FMT_COMPILE("chown -R {0}:{0} /home/{0}"), user), false);
|
||||
const auto& sudoers_file = fmt::format(FMT_COMPILE("{}/etc/sudoers"), mountpoint);
|
||||
if (fs::exists(sudoers_file)) {
|
||||
utils::exec(fmt::format(FMT_COMPILE("sed -i '/NOPASSWD/!s/# %sudo/%sudo/g' {}"), sudoers_file));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set password for root user
|
||||
void set_root_password([[maybe_unused]] const std::string_view& password) noexcept {
|
||||
#ifdef NDEVENV
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
|
||||
|
||||
std::error_code err{};
|
||||
utils::exec(fmt::format(FMT_COMPILE("echo -e \"{0}\n{0}\" > /tmp/.passwd"), password));
|
||||
utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} passwd root < /tmp/.passwd &>/dev/null"), mountpoint));
|
||||
fs::remove("/tmp/.passwd", err);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Finds all available partitions according to type(s) specified and generates a list
|
||||
// of them. This also includes partitions on different devices.
|
||||
void find_partitions() noexcept {
|
||||
@ -751,6 +908,81 @@ vm.vfs_cache_pressure = 50
|
||||
}
|
||||
|
||||
void parse_config() noexcept {
|
||||
using namespace rapidjson;
|
||||
|
||||
// 1. Open file for reading.
|
||||
static constexpr auto file_path = "settings.json";
|
||||
std::ifstream ifs{file_path};
|
||||
if (!ifs.is_open()) {
|
||||
fmt::print(stderr, "Config not found running with defaults");
|
||||
return;
|
||||
}
|
||||
|
||||
IStreamWrapper isw{ifs};
|
||||
|
||||
// 2. Parse a JSON.
|
||||
Document doc;
|
||||
doc.ParseStream(isw);
|
||||
|
||||
// Document is a JSON value represents the root of DOM. Root can be either an object or array.
|
||||
assert(doc.IsObject());
|
||||
|
||||
assert(doc.HasMember("menus"));
|
||||
assert(doc["menus"].IsInt());
|
||||
|
||||
auto* config_instance = Config::instance();
|
||||
auto& config_data = config_instance->data();
|
||||
config_data["menus"] = doc["menus"].GetInt();
|
||||
|
||||
if (doc.HasMember("device")) {
|
||||
assert(doc["device"].IsString());
|
||||
config_data["DEVICE"] = std::string{doc["device"].GetString()};
|
||||
}
|
||||
|
||||
if (doc.HasMember("fs_name")) {
|
||||
assert(doc["fs_name"].IsString());
|
||||
config_data["FILESYSTEM_NAME"] = std::string{doc["fs_name"].GetString()};
|
||||
}
|
||||
|
||||
if (doc.HasMember("mount_opts")) {
|
||||
assert(doc["mount_opts"].IsString());
|
||||
config_data["MOUNT_OPTS"] = std::string{doc["mount_opts"].GetString()};
|
||||
}
|
||||
|
||||
if (doc.HasMember("hostname")) {
|
||||
assert(doc["hostname"].IsString());
|
||||
config_data["HOSTNAME"] = std::string{doc["hostname"].GetString()};
|
||||
}
|
||||
|
||||
if (doc.HasMember("locale")) {
|
||||
assert(doc["locale"].IsString());
|
||||
config_data["LOCALE"] = std::string{doc["locale"].GetString()};
|
||||
}
|
||||
|
||||
if (doc.HasMember("xkbmap")) {
|
||||
assert(doc["xkbmap"].IsString());
|
||||
config_data["XKBMAP"] = std::string{doc["xkbmap"].GetString()};
|
||||
}
|
||||
|
||||
if (doc.HasMember("timezone")) {
|
||||
assert(doc["timezone"].IsString());
|
||||
config_data["TIMEZONE"] = std::string{doc["timezone"].GetString()};
|
||||
}
|
||||
|
||||
if (doc.HasMember("user_name") && doc.HasMember("user_pass") && doc.HasMember("user_shell")) {
|
||||
assert(doc["user_name"].IsString());
|
||||
assert(doc["user_pass"].IsString());
|
||||
assert(doc["user_shell"].IsString());
|
||||
config_data["USER_NAME"] = std::string{doc["user_name"].GetString()};
|
||||
config_data["USER_PASS"] = std::string{doc["user_pass"].GetString()};
|
||||
config_data["USER_SHELL"] = std::string{doc["user_shell"].GetString()};
|
||||
}
|
||||
|
||||
if (doc.HasMember("root_pass")) {
|
||||
assert(doc["root_pass"].IsString());
|
||||
config_data["ROOT_PASS"] = std::string{doc["root_pass"].GetString()};
|
||||
}
|
||||
|
||||
/*
|
||||
using namespace simdjson;
|
||||
|
||||
|
@ -20,6 +20,14 @@ void clear_screen() noexcept;
|
||||
[[nodiscard]] auto make_multiline(std::vector<std::string>& multiline, bool reverse = false, const std::string_view&& delim = "\n") noexcept -> std::string;
|
||||
void inst_needed(const std::string_view& pkg) noexcept;
|
||||
void secure_wipe() noexcept;
|
||||
void generate_fstab(const std::string_view& fstab_cmd) noexcept;
|
||||
void set_hostname(const std::string_view& hostname) noexcept;
|
||||
void set_locale(const std::string_view& locale) noexcept;
|
||||
void set_xkbmap(const std::string_view& xkbmap) noexcept;
|
||||
void set_timezone(const std::string_view& timezone) noexcept;
|
||||
void set_hw_clock(const std::string_view& clock_type) noexcept;
|
||||
void create_new_user(const std::string_view& user, const std::string_view& password, const std::string_view& shell) noexcept;
|
||||
void set_root_password(const std::string_view& password) noexcept;
|
||||
[[nodiscard]] bool check_mount() noexcept;
|
||||
[[nodiscard]] bool check_base() noexcept;
|
||||
[[nodiscard]] std::string list_mounted() noexcept;
|
||||
|
4
subprojects/packagefiles/rapidjson/meson.build
Normal file
4
subprojects/packagefiles/rapidjson/meson.build
Normal file
@ -0,0 +1,4 @@
|
||||
project('rapidjson', 'cpp', version: '1.1.0', license: 'MIT')
|
||||
|
||||
rapidjson_inc = include_directories('include')
|
||||
rapidjson_dep = declare_dependency(include_directories: rapidjson_inc)
|
8
subprojects/rapidjson.wrap
Normal file
8
subprojects/rapidjson.wrap
Normal file
@ -0,0 +1,8 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/Tencent/rapidjson.git
|
||||
revision = 232389d4f1012dddec4ef84861face2d2ba85709
|
||||
|
||||
patch_directory = rapidjson
|
||||
|
||||
[provide]
|
||||
rapidjson = rapidjson_dep
|
Loading…
Reference in New Issue
Block a user