#pragma once #include #include #include #include #include #include #include #include "config.h" struct RsyncProgress { int64_t files_transferred = 0; int64_t files_total = 0; int64_t bytes_transferred = 0; int64_t bytes_total = 0; int speed = 0; int64_t estimated_total_size = 0; double elapsed_seconds = 0; double estimated_remaining = 0; std::string current_file; std::string log_line; bool finished = false; bool error = false; std::string error_message; }; class RsyncManager { public: RsyncManager(Config& config); bool create_snapshot(const std::string& snapshot_name, const std::string& source, const std::string& dest, const std::string& link_dest = ""); bool restore_files(const std::string& snapshot_path, const std::vector& files, const std::string& restore_dest, const std::string& sudo_password); bool restore_full_snapshot(const std::string& snapshot_path, const std::string& restore_dest, const std::string& sudo_password); void cancel(); bool is_running() const { return running_; } std::function on_progress; int64_t estimate_backup_size(const std::string& source); std::string format_time_remaining(double seconds); private: Config& config_; std::atomic running_{false}; std::atomic cancel_requested_{false}; std::thread worker_; std::mutex log_mutex_; std::vector log_buffer_; std::chrono::steady_clock::time_point start_time_; std::vector build_exclude_args(); bool run_rsync(const std::vector& args); void parse_progress_line(const std::string& line, RsyncProgress& prog); };