mirror of
https://github.com/CachyOS/New-Cli-Installer.git
synced 2025-02-02 22:07:13 +08:00
attempt for wrapped process log
This commit is contained in:
parent
d33c29c516
commit
bba4767fcb
@ -88,16 +88,25 @@ add_executable(${PROJECT_NAME}
|
||||
src/config.cpp src/config.hpp
|
||||
src/utils.cpp src/utils.hpp
|
||||
src/widgets.cpp src/widgets.hpp
|
||||
src/follow_process_log.hpp src/follow_process_log.cpp
|
||||
src/tui.cpp src/tui.hpp
|
||||
src/main.cpp
|
||||
)
|
||||
|
||||
add_executable(test-exec-interactive
|
||||
src/config.cpp src/config.hpp
|
||||
src/utils.cpp src/utils.hpp
|
||||
src/tui.cpp src/tui.hpp
|
||||
src/main_test.cpp
|
||||
)
|
||||
|
||||
add_executable(test-process-tailing
|
||||
src/config.cpp
|
||||
src/utils.cpp
|
||||
src/widgets.cpp src/widgets.hpp
|
||||
src/follow_process_log.hpp src/follow_process_log.cpp
|
||||
src/tui.cpp src/tui.hpp
|
||||
src/main_test.cpp
|
||||
src/test_proccess_tailing.cpp
|
||||
)
|
||||
|
||||
# Link this 'library' to use the warnings specified in CompilerWarnings.cmake
|
||||
@ -114,6 +123,7 @@ 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 nlohmann_json::nlohmann_json cpr::cpr PkgConfig::GLIBMM)
|
||||
target_link_libraries(test-exec-interactive PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::component cpr::cpr PkgConfig::GLIBMM)
|
||||
target_link_libraries(test-process-tailing PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::component cpr::cpr PkgConfig::GLIBMM)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE range-v3::range-v3)
|
||||
|
@ -47,6 +47,7 @@ src_files = files(
|
||||
'src/config.cpp', 'src/config.hpp',
|
||||
'src/utils.cpp', 'src/utils.hpp',
|
||||
'src/widgets.cpp', 'src/widgets.hpp',
|
||||
'src/follow_process_log.cpp', 'src/follow_process_log.hpp',
|
||||
'src/tui.cpp', 'src/tui.hpp',
|
||||
'src/main.cpp',
|
||||
)
|
||||
@ -115,7 +116,7 @@ executable(
|
||||
|
||||
executable(
|
||||
'test-process-tailing',
|
||||
files('src/config.cpp', 'src/widgets.cpp', 'src/tui.cpp', 'src/utils.cpp', 'src/test_proccess_tailing.cpp'),
|
||||
files('src/config.cpp', 'src/widgets.cpp', 'src/tui.cpp', 'src/utils.cpp', 'src/follow_process_log.cpp','src/test_proccess_tailing.cpp'),
|
||||
dependencies: [fmt, spdlog, ftxui, cpr, glibmm],
|
||||
include_directories: [include_directories('src')],
|
||||
install: false)
|
||||
|
69
src/follow_process_log.cpp
Normal file
69
src/follow_process_log.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
#include "follow_process_log.hpp"
|
||||
#include "subprocess.h"
|
||||
#include "utils.hpp" // for make_multiline
|
||||
#include "widgets.hpp"
|
||||
|
||||
#include <chrono> // for operator""s, chrono_literals
|
||||
#include <csignal>
|
||||
#include <string> // for string, operator<<, to_string
|
||||
#include <thread>
|
||||
|
||||
#include <ftxui/component/component.hpp> // for Renderer, Button
|
||||
#include <ftxui/component/component_options.hpp> // for ButtonOption, Inpu...
|
||||
#include <ftxui/component/event.hpp>
|
||||
#include <ftxui/component/screen_interactive.hpp> // for ScreenInteractive
|
||||
#include <ftxui/dom/elements.hpp> // for operator|, text, Element, hbox, bold, color, filler, separator, vbox, window, gauge, Fit, size, dim, EQUAL, WIDTH
|
||||
|
||||
using namespace ftxui;
|
||||
|
||||
namespace tui::detail {
|
||||
|
||||
void follow_process_log_widget(const std::vector<std::string>& vec, Decorator boxsize) noexcept {
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
bool running{true};
|
||||
std::string process_log{};
|
||||
subprocess_s child{};
|
||||
auto execute_thread = [&]() {
|
||||
while (running) {
|
||||
utils::exec_follow(vec, process_log, running, child);
|
||||
std::this_thread::sleep_for(0.05s);
|
||||
}
|
||||
};
|
||||
std::jthread t(execute_thread);
|
||||
auto screen = ScreenInteractive::Fullscreen();
|
||||
|
||||
std::jthread refresh_ui([&] {
|
||||
while (running) {
|
||||
std::this_thread::sleep_for(0.05s);
|
||||
screen.PostEvent(Event::Custom);
|
||||
}
|
||||
});
|
||||
|
||||
auto handle_exit = [&]() {
|
||||
if (child.child != 0) {
|
||||
subprocess_terminate(&child);
|
||||
subprocess_destroy(&child);
|
||||
}
|
||||
if (running) {
|
||||
running = false;
|
||||
refresh_ui.join();
|
||||
t.join();
|
||||
}
|
||||
screen.ExitLoopClosure()();
|
||||
};
|
||||
|
||||
auto button_option = ButtonOption();
|
||||
button_option.border = false;
|
||||
auto button_back = Button("Back", handle_exit, &button_option);
|
||||
auto container = Container::Horizontal({button_back});
|
||||
|
||||
auto renderer = Renderer(container, [&] {
|
||||
return tui::detail::centered_widget(container, "New CLI Installer", tui::detail::multiline_text(utils::make_multiline(process_log)) | boxsize | vscroll_indicator | yframe | flex);
|
||||
});
|
||||
|
||||
screen.Loop(renderer);
|
||||
running = false;
|
||||
}
|
||||
|
||||
} // namespace tui::detail
|
14
src/follow_process_log.hpp
Normal file
14
src/follow_process_log.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef FOLLOW_PROCESS_LOG_HPP
|
||||
#define FOLLOW_PROCESS_LOG_HPP
|
||||
|
||||
#include <string_view> // for string_view
|
||||
|
||||
#include <ftxui/dom/elements.hpp> // for size, GREATER_THAN
|
||||
|
||||
namespace tui {
|
||||
namespace detail {
|
||||
void follow_process_log_widget(const std::vector<std::string>& vec, ftxui::Decorator boxsize = size(ftxui::HEIGHT, ftxui::GREATER_THAN, 5)) noexcept;
|
||||
} // namespace detail
|
||||
} // namespace tui
|
||||
|
||||
#endif // FOLLOW_PROCESS_LOG_HPP
|
1076
src/subprocess.h
Normal file
1076
src/subprocess.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,95 +1,5 @@
|
||||
#include <cstdio>
|
||||
#include <thread>
|
||||
|
||||
#include <chrono> // for operator""s, chrono_literals
|
||||
#include <ftxui/component/component.hpp> // for Renderer, Button
|
||||
#include <ftxui/component/component_options.hpp> // for ButtonOption, Inpu...
|
||||
#include <ftxui/component/screen_interactive.hpp> // for ScreenInteractive
|
||||
#include <ftxui/dom/elements.hpp> // for operator|, text, Element, hbox, bold, color, filler, separator, vbox, window, gauge, Fit, size, dim, EQUAL, WIDTH
|
||||
#include <ftxui/screen/screen.hpp> // for Full, Screen
|
||||
#include <iostream> // for cout, endl, ostream
|
||||
#include <list> // for list, operator!=, _List_iterator, _List_iterator<>::_Self
|
||||
#include <memory> // for allocator, shared_ptr, allocator_traits<>::value_type
|
||||
#include <string> // for string, operator<<, to_string
|
||||
#include <thread> // for sleep_for
|
||||
#include <utility> // for move
|
||||
#include <vector> // for vector
|
||||
|
||||
#include <ftxui/component/captured_mouse.hpp>
|
||||
#include <ftxui/component/event.hpp>
|
||||
#include <ftxui/dom/node.hpp> // for Render
|
||||
#include <ftxui/screen/box.hpp> // for ftxui
|
||||
#include <ftxui/screen/color.hpp> // for Color, Color::Green, Color::Red, Color::RedLight
|
||||
|
||||
#include "subprocess.h"
|
||||
#include "utils.hpp"
|
||||
#include "widgets.hpp"
|
||||
|
||||
static bool running{true};
|
||||
static std::string process_log{};
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
void execute() {
|
||||
const char* const commandLine[] = {"/sbin/tail", "-f", "/tmp/smth.log", nullptr};
|
||||
struct subprocess_s process;
|
||||
int ret = -1;
|
||||
static char data[1048576 + 1] = {0};
|
||||
unsigned index = 0;
|
||||
unsigned bytes_read = 0;
|
||||
|
||||
if ((ret = subprocess_create(commandLine, subprocess_option_enable_async | subprocess_option_combined_stdout_stderr, &process)) != 0) {
|
||||
std::perror("creation failed");
|
||||
std::cerr << "creation failed with: " << ret << '\n';
|
||||
running = false;
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
bytes_read = subprocess_read_stdout(&process, data + index,
|
||||
sizeof(data) - 1 - index);
|
||||
|
||||
index += bytes_read;
|
||||
|
||||
process_log = data;
|
||||
} while (bytes_read != 0);
|
||||
|
||||
subprocess_join(&process, &ret);
|
||||
subprocess_destroy(&process);
|
||||
}
|
||||
|
||||
void execute_thread() {
|
||||
while (running) {
|
||||
execute();
|
||||
|
||||
std::this_thread::sleep_for(2s);
|
||||
}
|
||||
}
|
||||
#include "follow_process_log.hpp"
|
||||
|
||||
int main() {
|
||||
using namespace ftxui;
|
||||
std::jthread t(execute_thread);
|
||||
|
||||
auto screen = ScreenInteractive::Fullscreen();
|
||||
|
||||
std::jthread refresh_ui([&] {
|
||||
while (running) {
|
||||
std::this_thread::sleep_for(0.05s);
|
||||
screen.PostEvent(Event::Custom);
|
||||
}
|
||||
});
|
||||
|
||||
auto button_option = ButtonOption();
|
||||
button_option.border = false;
|
||||
auto button_back = Button("Back", screen.ExitLoopClosure(), &button_option);
|
||||
auto container = Container::Horizontal({button_back});
|
||||
|
||||
auto renderer = Renderer(container, [&] {
|
||||
return tui::detail::centered_widget(container, "New CLI Installer", tui::detail::multiline_text(utils::make_multiline(process_log)) | vscroll_indicator | yframe | flex);
|
||||
});
|
||||
|
||||
screen.Loop(renderer);
|
||||
running = false;
|
||||
t.join();
|
||||
refresh_ui.join();
|
||||
tui::detail::follow_process_log_widget({"/sbin/tail", "-f", "/tmp/smth.log"});
|
||||
}
|
||||
|
16
src/tui.cpp
16
src/tui.cpp
@ -30,6 +30,10 @@ namespace fs = std::filesystem;
|
||||
namespace ranges = std::ranges;
|
||||
#endif
|
||||
|
||||
#ifdef NDEVENV
|
||||
#include "follow_process_log.hpp"
|
||||
#endif
|
||||
|
||||
namespace tui {
|
||||
|
||||
// Revised to deal with partion sizes now being displayed to the user
|
||||
@ -418,10 +422,12 @@ void install_cust_pkgs() noexcept {
|
||||
const auto& hostcache = std::get<std::int32_t>(config_data["hostcache"]);
|
||||
|
||||
if (hostcache) {
|
||||
utils::exec(fmt::format("pacstrap {} {}", mountpoint, packages));
|
||||
// utils::exec(fmt::format("pacstrap {} {}", mountpoint, packages));
|
||||
detail::follow_process_log_widget({"/sbin/pacstrap", mountpoint, packages});
|
||||
return;
|
||||
}
|
||||
utils::exec(fmt::format("pacstrap -c {} {}", mountpoint, packages));
|
||||
// utils::exec(fmt::format("pacstrap -c {} {}", mountpoint, packages));
|
||||
detail::follow_process_log_widget({"/sbin/pacstrap", "-c", mountpoint, packages});
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -454,7 +460,8 @@ void install_systemd_boot() noexcept {
|
||||
const auto& uefi_mount = std::get<std::string>(config_data["UEFI_MOUNT"]);
|
||||
|
||||
utils::arch_chroot(fmt::format("bootctl --path={} install", uefi_mount));
|
||||
utils::exec(fmt::format("pacstrap {} systemd-boot-manager", mountpoint));
|
||||
// utils::exec(fmt::format("pacstrap {} systemd-boot-manager", mountpoint));
|
||||
detail::follow_process_log_widget({"/sbin/pacstrap", mountpoint, "systemd-boot-manager"});
|
||||
utils::arch_chroot("sdboot-manage gen");
|
||||
|
||||
// Check if the volume is removable. If so, dont use autodetect
|
||||
@ -603,7 +610,8 @@ void install_base() noexcept {
|
||||
spdlog::info(fmt::format("Preparing for pkgs to install: \"{}\"", packages));
|
||||
#ifdef NDEVENV
|
||||
// filter_packages
|
||||
utils::exec(fmt::format("pacstrap {} {} |& tee /tmp/pacstrap.log", mountpoint, packages));
|
||||
// utils::exec(fmt::format("pacstrap {} {} |& tee /tmp/pacstrap.log", mountpoint, packages));
|
||||
detail::follow_process_log_widget({"/sbin/pacstrap", mountpoint, packages});
|
||||
#endif
|
||||
std::ofstream{base_installed};
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "utils.hpp"
|
||||
#include "config.hpp"
|
||||
#include "definitions.hpp"
|
||||
#include "subprocess.h"
|
||||
#include "tui.hpp"
|
||||
#include "widgets.hpp"
|
||||
|
||||
@ -82,6 +83,43 @@ void arch_chroot(const std::string_view& command) noexcept {
|
||||
utils::exec(fmt::format("arch-chroot {} \"{}\"", mountpoint, command));
|
||||
}
|
||||
|
||||
void exec_follow(const std::vector<std::string>& vec, std::string& process_log, bool& running, subprocess_s& child, bool async) noexcept {
|
||||
if (!async) {
|
||||
spdlog::error("Implement me!");
|
||||
return;
|
||||
}
|
||||
subprocess_s process{};
|
||||
int32_t ret{-1};
|
||||
static std::array<char, 1048576 + 1> data{};
|
||||
uint32_t index{};
|
||||
uint32_t bytes_read{};
|
||||
|
||||
std::vector<char*> args;
|
||||
std::transform(vec.cbegin(), vec.cend(), std::back_inserter(args),
|
||||
[=](const std::string& arg) -> char* { return const_cast<char*>(arg.data()); });
|
||||
args.push_back(nullptr);
|
||||
|
||||
char** command = args.data();
|
||||
|
||||
if ((ret = subprocess_create(command, subprocess_option_enable_async | subprocess_option_combined_stdout_stderr, &process)) != 0) {
|
||||
running = false;
|
||||
return;
|
||||
}
|
||||
|
||||
child = process;
|
||||
|
||||
do {
|
||||
bytes_read = subprocess_read_stdout(&process, data.data() + index,
|
||||
sizeof(data) - 1 - index);
|
||||
|
||||
index += bytes_read;
|
||||
process_log = data.data();
|
||||
} while (bytes_read != 0);
|
||||
|
||||
subprocess_join(&process, &ret);
|
||||
subprocess_destroy(&process);
|
||||
}
|
||||
|
||||
void exec(const std::vector<std::string>& vec) noexcept {
|
||||
std::int32_t status{};
|
||||
auto pid = fork();
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define UTILS_HPP
|
||||
|
||||
#include "definitions.hpp"
|
||||
#include "subprocess.h"
|
||||
|
||||
#include <charconv> // for from_chars
|
||||
#include <string> // for string
|
||||
@ -25,6 +26,7 @@ void umount_partitions() noexcept;
|
||||
void find_partitions() noexcept;
|
||||
|
||||
void arch_chroot(const std::string_view& command) noexcept;
|
||||
void exec_follow(const std::vector<std::string>& vec, std::string& process_log, bool& running, subprocess_s& child, bool async = true) noexcept;
|
||||
void exec(const std::vector<std::string>& vec) noexcept;
|
||||
auto exec(const std::string_view& command, const bool& interactive = false) noexcept(false) -> std::string;
|
||||
[[nodiscard]] bool check_root() noexcept;
|
||||
|
Loading…
Reference in New Issue
Block a user