attempt for wrapped process log

This commit is contained in:
Vladislav Nepogodin 2021-12-27 03:04:03 +04:00
parent d33c29c516
commit bba4767fcb
No known key found for this signature in database
GPG Key ID: B62C3D10C54D5DA9
9 changed files with 1226 additions and 98 deletions

View File

@ -88,16 +88,25 @@ add_executable(${PROJECT_NAME}
src/config.cpp src/config.hpp src/config.cpp src/config.hpp
src/utils.cpp src/utils.hpp src/utils.cpp src/utils.hpp
src/widgets.cpp src/widgets.hpp src/widgets.cpp src/widgets.hpp
src/follow_process_log.hpp src/follow_process_log.cpp
src/tui.cpp src/tui.hpp src/tui.cpp src/tui.hpp
src/main.cpp src/main.cpp
) )
add_executable(test-exec-interactive 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/config.cpp
src/utils.cpp src/utils.cpp
src/widgets.cpp src/widgets.hpp src/widgets.cpp src/widgets.hpp
src/follow_process_log.hpp src/follow_process_log.cpp
src/tui.cpp src/tui.hpp 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 # 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(${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-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") if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
target_link_libraries(${PROJECT_NAME} PRIVATE range-v3::range-v3) target_link_libraries(${PROJECT_NAME} PRIVATE range-v3::range-v3)

View File

@ -47,6 +47,7 @@ src_files = files(
'src/config.cpp', 'src/config.hpp', 'src/config.cpp', 'src/config.hpp',
'src/utils.cpp', 'src/utils.hpp', 'src/utils.cpp', 'src/utils.hpp',
'src/widgets.cpp', 'src/widgets.hpp', 'src/widgets.cpp', 'src/widgets.hpp',
'src/follow_process_log.cpp', 'src/follow_process_log.hpp',
'src/tui.cpp', 'src/tui.hpp', 'src/tui.cpp', 'src/tui.hpp',
'src/main.cpp', 'src/main.cpp',
) )
@ -115,7 +116,7 @@ executable(
executable( executable(
'test-process-tailing', '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], dependencies: [fmt, spdlog, ftxui, cpr, glibmm],
include_directories: [include_directories('src')], include_directories: [include_directories('src')],
install: false) install: false)

View 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

View 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

File diff suppressed because it is too large Load Diff

View File

@ -1,95 +1,5 @@
#include <cstdio> #include "follow_process_log.hpp"
#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);
}
}
int main() { int main() {
using namespace ftxui; tui::detail::follow_process_log_widget({"/sbin/tail", "-f", "/tmp/smth.log"});
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();
} }

View File

@ -30,6 +30,10 @@ namespace fs = std::filesystem;
namespace ranges = std::ranges; namespace ranges = std::ranges;
#endif #endif
#ifdef NDEVENV
#include "follow_process_log.hpp"
#endif
namespace tui { namespace tui {
// Revised to deal with partion sizes now being displayed to the user // 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"]); const auto& hostcache = std::get<std::int32_t>(config_data["hostcache"]);
if (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; 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 #endif
} }
@ -454,7 +460,8 @@ void install_systemd_boot() noexcept {
const auto& uefi_mount = std::get<std::string>(config_data["UEFI_MOUNT"]); const auto& uefi_mount = std::get<std::string>(config_data["UEFI_MOUNT"]);
utils::arch_chroot(fmt::format("bootctl --path={} install", 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"); utils::arch_chroot("sdboot-manage gen");
// Check if the volume is removable. If so, dont use autodetect // 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)); spdlog::info(fmt::format("Preparing for pkgs to install: \"{}\"", packages));
#ifdef NDEVENV #ifdef NDEVENV
// filter_packages // 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 #endif
std::ofstream{base_installed}; std::ofstream{base_installed};
} }

View File

@ -1,6 +1,7 @@
#include "utils.hpp" #include "utils.hpp"
#include "config.hpp" #include "config.hpp"
#include "definitions.hpp" #include "definitions.hpp"
#include "subprocess.h"
#include "tui.hpp" #include "tui.hpp"
#include "widgets.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)); 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 { void exec(const std::vector<std::string>& vec) noexcept {
std::int32_t status{}; std::int32_t status{};
auto pid = fork(); auto pid = fork();

View File

@ -2,6 +2,7 @@
#define UTILS_HPP #define UTILS_HPP
#include "definitions.hpp" #include "definitions.hpp"
#include "subprocess.h"
#include <charconv> // for from_chars #include <charconv> // for from_chars
#include <string> // for string #include <string> // for string
@ -25,6 +26,7 @@ void umount_partitions() noexcept;
void find_partitions() noexcept; void find_partitions() noexcept;
void arch_chroot(const std::string_view& command) 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; void exec(const std::vector<std::string>& vec) noexcept;
auto exec(const std::string_view& command, const bool& interactive = false) noexcept(false) -> std::string; auto exec(const std::string_view& command, const bool& interactive = false) noexcept(false) -> std::string;
[[nodiscard]] bool check_root() noexcept; [[nodiscard]] bool check_root() noexcept;