feat(all): Add loging
This commit is contained in:
1 parent
25080e3cca
commit
dfa7c463ac
10 files changed
+108
-45
No files matched your search
+14
@@ -6,6 +6,13 @@ use eframe::egui;
|
|||||||
use egui::{FontData, FontDefinitions, FontFamily};
|
use egui::{FontData, FontDefinitions, FontFamily};
|
||||||
|
|
||||||
fn main() -> Result<(), eframe::Error> {
|
fn main() -> Result<(), eframe::Error> {
|
||||||
|
// Инициализация логгера
|
||||||
|
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
|
||||||
|
.format_timestamp_millis()
|
||||||
|
.init();
|
||||||
|
|
||||||
|
log::info!("Запуск Rclone UI Manager");
|
||||||
|
|
||||||
let viewport = egui::ViewportBuilder::default()
|
let viewport = egui::ViewportBuilder::default()
|
||||||
.with_inner_size([1200.0, 800.0])
|
.with_inner_size([1200.0, 800.0])
|
||||||
.with_min_inner_size([800.0, 600.0])
|
.with_min_inner_size([800.0, 600.0])
|
||||||
@@ -20,11 +27,15 @@ fn main() -> Result<(), eframe::Error> {
|
|||||||
"Rclone UI Manager",
|
"Rclone UI Manager",
|
||||||
options,
|
options,
|
||||||
Box::new(|cc| {
|
Box::new(|cc| {
|
||||||
|
log::debug!("Инициализация шрифтов");
|
||||||
let mut fonts = FontDefinitions::default();
|
let mut fonts = FontDefinitions::default();
|
||||||
|
|
||||||
if let Ok(font_data) = std::fs::read("assets/fonts/Sans.otf") {
|
if let Ok(font_data) = std::fs::read("assets/fonts/Sans.otf") {
|
||||||
fonts.font_data.insert("sans".to_owned(), FontData::from_owned(font_data));
|
fonts.font_data.insert("sans".to_owned(), FontData::from_owned(font_data));
|
||||||
fonts.families.entry(FontFamily::Proportional).or_default().insert(0, "sans".to_owned());
|
fonts.families.entry(FontFamily::Proportional).or_default().insert(0, "sans".to_owned());
|
||||||
|
log::debug!("Загружен шрифт Sans.otf");
|
||||||
|
} else {
|
||||||
|
log::warn!("Не найден файл шрифта assets/fonts/Sans.otf");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(emoji_data) = std::fs::read("assets/fonts/NotoColorEmoji.ttf") {
|
if let Ok(emoji_data) = std::fs::read("assets/fonts/NotoColorEmoji.ttf") {
|
||||||
@@ -33,6 +44,9 @@ fn main() -> Result<(), eframe::Error> {
|
|||||||
if !prop.contains(&"emoji".to_owned()) {
|
if !prop.contains(&"emoji".to_owned()) {
|
||||||
prop.push("emoji".to_owned());
|
prop.push("emoji".to_owned());
|
||||||
}
|
}
|
||||||
|
log::debug!("Загружен шрифт NotoColorEmoji.ttf");
|
||||||
|
} else {
|
||||||
|
log::warn!("Не найден файл шрифта assets/fonts/NotoColorEmoji.ttf");
|
||||||
}
|
}
|
||||||
|
|
||||||
cc.egui_ctx.set_fonts(fonts);
|
cc.egui_ctx.set_fonts(fonts);
|
||||||
|
|||||||
+1
-19
@@ -24,25 +24,7 @@ pub struct FileInfo {
|
|||||||
pub modified: Option<String>,
|
pub modified: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileInfo {
|
pub mod fileinfo;
|
||||||
pub fn format_size(&self) -> String {
|
|
||||||
let bytes = self.size;
|
|
||||||
if bytes < 1024 {
|
|
||||||
format!("{} B", bytes)
|
|
||||||
} else if bytes < 1024 * 1024 {
|
|
||||||
format!("{:.1} KB", bytes as f64 / 1024.0)
|
|
||||||
} else if bytes < 1024 * 1024 * 1024 {
|
|
||||||
format!("{:.1} MB", bytes as f64 / (1024.0 * 1024.0))
|
|
||||||
} else {
|
|
||||||
format!("{:.2} GB", bytes as f64 / (1024.0 * 1024.0 * 1024.0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn icon(&self) -> &'static str {
|
|
||||||
if self.is_dir { "📁" } else { "📄" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod files;
|
pub mod files;
|
||||||
|
|
||||||
/// === Модуль для операций синхронизации ===
|
/// === Модуль для операций синхронизации ===
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
use super::*;
|
|
||||||
use crate::rclone_install::RcloneApp;
|
use crate::rclone_install::RcloneApp;
|
||||||
use serde_json::Value;
|
|
||||||
|
|
||||||
/// Проверить разницу между двумя директориями
|
/// Проверить разницу между двумя директориями
|
||||||
pub fn diff(app: &RcloneApp, source: &str, dest: &str) -> Result<Vec<String>, String> {
|
pub fn diff(app: &RcloneApp, source: &str, dest: &str) -> Result<Vec<String>, String> {
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
use super::*;
|
||||||
|
impl FileInfo {
|
||||||
|
pub fn format_size(&self) -> String {
|
||||||
|
let bytes = self.size;
|
||||||
|
if bytes < 1024 {
|
||||||
|
format!("{} B", bytes)
|
||||||
|
} else if bytes < 1024 * 1024 {
|
||||||
|
format!("{:.1} KB", bytes as f64 / 1024.0)
|
||||||
|
} else if bytes < 1024 * 1024 * 1024 {
|
||||||
|
format!("{:.1} MB", bytes as f64 / (1024.0 * 1024.0))
|
||||||
|
} else {
|
||||||
|
format!("{:.2} GB", bytes as f64 / (1024.0 * 1024.0 * 1024.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn icon(&self) -> &'static str {
|
||||||
|
if self.is_dir { "📁" } else { "📄" }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
use super::*;
|
|
||||||
use crate::rclone_install::RcloneApp;
|
use crate::rclone_install::RcloneApp;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
|
|
||||||
use std::fs;
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
pub fn list_directory(path: &str) -> Result<Vec<FileInfo>, String> {
|
pub fn list_directory(path: &str) -> Result<Vec<FileInfo>, String> {
|
||||||
let p = if path.is_empty() {
|
let p = if path.is_empty() {
|
||||||
if cfg!(windows) { PathBuf::from("C:\\") } else { PathBuf::from("/") }
|
if cfg!(windows) {
|
||||||
|
PathBuf::from("C:\\")
|
||||||
|
} else {
|
||||||
|
PathBuf::from("/")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
PathBuf::from(path)
|
PathBuf::from(path)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use serde_json::Value;
|
|||||||
|
|
||||||
/// Получить список всех удаленных хранилищ
|
/// Получить список всех удаленных хранилищ
|
||||||
pub fn list(app: &RcloneApp) -> Result<Vec<Remote>, String> {
|
pub fn list(app: &RcloneApp) -> Result<Vec<Remote>, String> {
|
||||||
|
log::debug!("Получение списка удаленных хранилищ");
|
||||||
let output = app.run_command(&["listremotes"])?;
|
let output = app.run_command(&["listremotes"])?;
|
||||||
|
|
||||||
let mut remotes = Vec::new();
|
let mut remotes = Vec::new();
|
||||||
@@ -14,6 +15,7 @@ pub fn list(app: &RcloneApp) -> Result<Vec<Remote>, String> {
|
|||||||
if let Ok(config) = get_config(app, name) {
|
if let Ok(config) = get_config(app, name) {
|
||||||
remotes.push(config);
|
remotes.push(config);
|
||||||
} else {
|
} else {
|
||||||
|
log::warn!("Не удалось получить конфигурацию для remote '{}'", name);
|
||||||
// Если не удалось получить конфиг, добавляем базовую информацию
|
// Если не удалось получить конфиг, добавляем базовую информацию
|
||||||
remotes.push(Remote {
|
remotes.push(Remote {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
@@ -24,11 +26,13 @@ pub fn list(app: &RcloneApp) -> Result<Vec<Remote>, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log::info!("Найдено {} удаленных хранилищ", remotes.len());
|
||||||
Ok(remotes)
|
Ok(remotes)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Получить конфигурацию конкретного remote
|
/// Получить конфигурацию конкретного remote
|
||||||
pub fn get_config(app: &RcloneApp, remote_name: &str) -> Result<Remote, String> {
|
pub fn get_config(app: &RcloneApp, remote_name: &str) -> Result<Remote, String> {
|
||||||
|
log::debug!("Получение конфигурации для remote: {}", remote_name);
|
||||||
let output = app.run_command(&["config", "dump"])?;
|
let output = app.run_command(&["config", "dump"])?;
|
||||||
|
|
||||||
let configs: Value = serde_json::from_str(&output)
|
let configs: Value = serde_json::from_str(&output)
|
||||||
@@ -54,13 +58,16 @@ pub fn get_config(app: &RcloneApp, remote_name: &str) -> Result<Remote, String>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log::debug!("Получена конфигурация для {} типа {}", remote_name, r#type);
|
||||||
Ok(Remote {
|
Ok(Remote {
|
||||||
name: remote_name.to_string(),
|
name: remote_name.to_string(),
|
||||||
r#type,
|
r#type,
|
||||||
config: config_map,
|
config: config_map,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Remote '{}' не найден", remote_name))
|
let error_msg = format!("Remote '{}' не найден", remote_name);
|
||||||
|
log::error!("{}", error_msg);
|
||||||
|
Err(error_msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,6 +78,7 @@ pub fn create(
|
|||||||
r#type: &str,
|
r#type: &str,
|
||||||
config: &HashMap<String, String>,
|
config: &HashMap<String, String>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
|
log::info!("Создание нового remote: {} типа {}", name, r#type);
|
||||||
let mut args = vec!["config", "create", name, r#type];
|
let mut args = vec!["config", "create", name, r#type];
|
||||||
|
|
||||||
for (key, value) in config {
|
for (key, value) in config {
|
||||||
@@ -79,11 +87,13 @@ pub fn create(
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.run_command(&args)?;
|
app.run_command(&args)?;
|
||||||
|
log::info!("Remote {} успешно создан", name);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Обновить конфигурацию remote
|
/// Обновить конфигурацию remote
|
||||||
pub fn update(app: &RcloneApp, name: &str, config: &HashMap<String, String>) -> Result<(), String> {
|
pub fn update(app: &RcloneApp, name: &str, config: &HashMap<String, String>) -> Result<(), String> {
|
||||||
|
log::info!("Обновление конфигурации remote: {}", name);
|
||||||
let mut args = vec!["config", "update", name];
|
let mut args = vec!["config", "update", name];
|
||||||
|
|
||||||
for (key, value) in config {
|
for (key, value) in config {
|
||||||
@@ -92,24 +102,33 @@ pub fn update(app: &RcloneApp, name: &str, config: &HashMap<String, String>) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.run_command(&args)?;
|
app.run_command(&args)?;
|
||||||
|
log::info!("Конфигурация remote {} успешно обновлена", name);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Удалить remote
|
/// Удалить remote
|
||||||
pub fn delete(app: &RcloneApp, name: &str) -> Result<(), String> {
|
pub fn delete(app: &RcloneApp, name: &str) -> Result<(), String> {
|
||||||
|
log::info!("Удаление remote: {}", name);
|
||||||
app.run_command(&["config", "delete", name])?;
|
app.run_command(&["config", "delete", name])?;
|
||||||
|
log::info!("Remote {} успешно удален", name);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Проверить доступность remote
|
/// Проверить доступность remote
|
||||||
pub fn check(app: &RcloneApp, remote_name: &str) -> Result<bool, String> {
|
pub fn check(app: &RcloneApp, remote_name: &str) -> Result<bool, String> {
|
||||||
|
log::debug!("Проверка доступности remote: {}", remote_name);
|
||||||
let result = app.run_command(&["lsd", remote_name, "--max-depth", "1"]);
|
let result = app.run_command(&["lsd", remote_name, "--max-depth", "1"]);
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => Ok(true),
|
Ok(_) => {
|
||||||
|
log::debug!("Remote {} доступен", remote_name);
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if e.contains("directory not found") {
|
if e.contains("directory not found") {
|
||||||
|
log::warn!("Remote {} существует, но пуст", remote_name);
|
||||||
Ok(true) // Remote существует, но пустой
|
Ok(true) // Remote существует, но пустой
|
||||||
} else {
|
} else {
|
||||||
|
log::error!("Ошибка доступа к remote {}: {}", remote_name, e);
|
||||||
Err(e)
|
Err(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::rclone_install::RcloneApp;
|
use crate::rclone_install::RcloneApp;
|
||||||
use serde_json::Value;
|
|
||||||
|
|
||||||
/// Скопировать файлы/директории
|
/// Скопировать файлы/директории
|
||||||
pub fn copy(
|
pub fn copy(
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
use flate2::read::GzDecoder;
|
|
||||||
use reqwest;
|
use reqwest;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use tar::Archive;
|
|
||||||
use tokio;
|
|
||||||
|
|
||||||
use super::RcloneApp;
|
use super::RcloneApp;
|
||||||
|
|
||||||
impl RcloneApp {
|
impl RcloneApp {
|
||||||
pub async fn new() -> Result<Self, Box<dyn std::error::Error>> {
|
pub async fn new() -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
|
log::info!("Инициализация RcloneApp");
|
||||||
|
|
||||||
// Сначала проверяем системный rclone
|
// Сначала проверяем системный rclone
|
||||||
if let Some(system_rclone) = Self::check_system_rclone() {
|
if let Some(system_rclone) = Self::check_system_rclone() {
|
||||||
println!("Найден системный rclone: {:?}", system_rclone);
|
log::info!("Найден системный rclone: {:?}", system_rclone);
|
||||||
return Ok(Self {
|
return Ok(Self {
|
||||||
rclone_path: system_rclone,
|
rclone_path: system_rclone,
|
||||||
using_system_rclone: true,
|
using_system_rclone: true,
|
||||||
@@ -32,7 +31,7 @@ impl RcloneApp {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if rclone_path.exists() {
|
if rclone_path.exists() {
|
||||||
println!("Найден rclone в директории приложения: {:?}", rclone_path);
|
log::info!("Найден rclone в директории приложения: {:?}", rclone_path);
|
||||||
return Ok(Self {
|
return Ok(Self {
|
||||||
rclone_path,
|
rclone_path,
|
||||||
using_system_rclone: false,
|
using_system_rclone: false,
|
||||||
@@ -40,12 +39,13 @@ impl RcloneApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Если ничего не найдено - устанавливаем
|
// Если ничего не найдено - устанавливаем
|
||||||
println!("rclone не найден. Начинаю установку...");
|
log::warn!("rclone не найден. Начинаю установку...");
|
||||||
Self::install_latest_rclone().await
|
Self::install_latest_rclone().await
|
||||||
}
|
}
|
||||||
|
|
||||||
// Публичный конструктор для тестов и создания экземпляра с заданными параметрами
|
// Публичный конструктор для тестов и создания экземпляра с заданными параметрами
|
||||||
pub fn new_with_path(rclone_path: PathBuf, using_system_rclone: bool) -> Self {
|
pub fn new_with_path(rclone_path: PathBuf, using_system_rclone: bool) -> Self {
|
||||||
|
log::debug!("Создание RcloneApp с путем {:?}, системный: {}", rclone_path, using_system_rclone);
|
||||||
Self {
|
Self {
|
||||||
rclone_path,
|
rclone_path,
|
||||||
using_system_rclone,
|
using_system_rclone,
|
||||||
@@ -63,30 +63,36 @@ impl RcloneApp {
|
|||||||
|
|
||||||
// Сеттеры
|
// Сеттеры
|
||||||
pub fn set_rclone_path(&mut self, path: PathBuf) {
|
pub fn set_rclone_path(&mut self, path: PathBuf) {
|
||||||
|
log::debug!("Изменение пути rclone с {:?} на {:?}", self.rclone_path, path);
|
||||||
self.rclone_path = path;
|
self.rclone_path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_using_system_rclone(&mut self, value: bool) {
|
pub fn set_using_system_rclone(&mut self, value: bool) {
|
||||||
|
log::debug!("Изменение флага using_system_rclone с {} на {}", self.using_system_rclone, value);
|
||||||
self.using_system_rclone = value;
|
self.using_system_rclone = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_system_rclone() -> Option<PathBuf> {
|
pub fn check_system_rclone() -> Option<PathBuf> {
|
||||||
|
log::debug!("Проверка системного rclone");
|
||||||
if let Ok(path) = which::which("rclone") {
|
if let Ok(path) = which::which("rclone") {
|
||||||
|
log::debug!("Найден системный rclone по пути: {:?}", path);
|
||||||
return Some(path);
|
return Some(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
{
|
{
|
||||||
if let Ok(path) = which::which("rclone.exe") {
|
if let Ok(path) = which::which("rclone.exe") {
|
||||||
|
log::debug!("Найден системный rclone.exe по пути: {:?}", path);
|
||||||
return Some(path);
|
return Some(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log::debug!("Системный rclone не найден");
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn install_latest_rclone() -> Result<Self, Box<dyn std::error::Error>> {
|
async fn install_latest_rclone() -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
println!("Начинаю установку последней версии rclone...");
|
log::info!("Начинаю установку последней версии rclone...");
|
||||||
|
|
||||||
// Определяем ОС и архитектуру
|
// Определяем ОС и архитектуру
|
||||||
let os = if cfg!(target_os = "linux") {
|
let os = if cfg!(target_os = "linux") {
|
||||||
@@ -109,8 +115,12 @@ impl RcloneApp {
|
|||||||
return Err("Неподдерживаемая архитектура".into());
|
return Err("Неподдерживаемая архитектура".into());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
log::info!("ОС: {}, архитектура: {}", os, arch);
|
||||||
|
|
||||||
// Получаем информацию о последнем релизе
|
// Получаем информацию о последнем релизе
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
|
log::debug!("Запрос последней версии rclone с GitHub API");
|
||||||
|
|
||||||
let latest_release: serde_json::Value = client
|
let latest_release: serde_json::Value = client
|
||||||
.get("https://api.github.com/repos/rclone/rclone/releases/latest")
|
.get("https://api.github.com/repos/rclone/rclone/releases/latest")
|
||||||
.header("User-Agent", "rclone-ui-installer")
|
.header("User-Agent", "rclone-ui-installer")
|
||||||
@@ -124,27 +134,33 @@ impl RcloneApp {
|
|||||||
.ok_or("Не удалось получить версию")?
|
.ok_or("Не удалось получить версию")?
|
||||||
.trim_start_matches('v');
|
.trim_start_matches('v');
|
||||||
|
|
||||||
|
log::info!("Найдена последняя версия rclone: {}", version);
|
||||||
|
|
||||||
// Формируем URL для скачивания
|
// Формируем URL для скачивания
|
||||||
let download_url = format!(
|
let download_url = format!(
|
||||||
"https://github.com/rclone/rclone/releases/download/v{}/rclone-v{}-{}-{}.zip",
|
"https://github.com/rclone/rclone/releases/download/v{}/rclone-v{}-{}-{}.zip",
|
||||||
version, version, os, arch
|
version, version, os, arch
|
||||||
);
|
);
|
||||||
|
|
||||||
println!("Скачиваю rclone версии {} с: {}", version, download_url);
|
log::info!("Скачиваю rclone с: {}", download_url);
|
||||||
|
|
||||||
// Скачиваем архив
|
// Скачиваем архив
|
||||||
let response = client.get(&download_url).send().await?;
|
let response = client.get(&download_url).send().await?;
|
||||||
if !response.status().is_success() {
|
if !response.status().is_success() {
|
||||||
return Err(format!("Ошибка скачивания: HTTP {}", response.status()).into());
|
let error_msg = format!("Ошибка скачивания: HTTP {}", response.status());
|
||||||
|
log::error!("{}", error_msg);
|
||||||
|
return Err(error_msg.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let bytes = response.bytes().await?;
|
let bytes = response.bytes().await?;
|
||||||
|
log::info!("Архив скачан, размер: {} байт", bytes.len());
|
||||||
|
|
||||||
// Создаем директорию приложения
|
// Создаем директорию приложения
|
||||||
let app_dir = dirs::data_dir()
|
let app_dir = dirs::data_dir()
|
||||||
.ok_or("Не удалось найти папку для данных")?
|
.ok_or("Не удалось найти папку для данных")?
|
||||||
.join("rclone-ui");
|
.join("rclone-ui");
|
||||||
fs::create_dir_all(&app_dir)?;
|
fs::create_dir_all(&app_dir)?;
|
||||||
|
log::debug!("Директория приложения: {:?}", app_dir);
|
||||||
|
|
||||||
// Определяем имя исполняемого файла
|
// Определяем имя исполняемого файла
|
||||||
let rclone_filename = if cfg!(windows) {
|
let rclone_filename = if cfg!(windows) {
|
||||||
@@ -165,16 +181,18 @@ impl RcloneApp {
|
|||||||
let file_name = file.name().to_string();
|
let file_name = file.name().to_string();
|
||||||
|
|
||||||
if file_name.ends_with("rclone") || file_name.ends_with("rclone.exe") {
|
if file_name.ends_with("rclone") || file_name.ends_with("rclone.exe") {
|
||||||
|
log::debug!("Найден исполняемый файл в архиве: {}", file_name);
|
||||||
let mut contents = Vec::new();
|
let mut contents = Vec::new();
|
||||||
std::io::copy(&mut file, &mut contents)?;
|
std::io::copy(&mut file, &mut contents)?;
|
||||||
fs::write(&rclone_path, contents)?;
|
fs::write(&rclone_path, contents)?;
|
||||||
extracted = true;
|
extracted = true;
|
||||||
println!("Найден и распакован: {}", file_name);
|
log::info!("Распакован: {} в {:?}", file_name, rclone_path);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !extracted {
|
if !extracted {
|
||||||
|
log::error!("Не удалось найти исполняемый файл rclone в архиве");
|
||||||
return Err("Не удалось найти исполняемый файл rclone в архиве".into());
|
return Err("Не удалось найти исполняемый файл rclone в архиве".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,9 +203,10 @@ impl RcloneApp {
|
|||||||
let mut perms = fs::metadata(&rclone_path)?.permissions();
|
let mut perms = fs::metadata(&rclone_path)?.permissions();
|
||||||
perms.set_mode(0o755);
|
perms.set_mode(0o755);
|
||||||
fs::set_permissions(&rclone_path, perms)?;
|
fs::set_permissions(&rclone_path, perms)?;
|
||||||
|
log::debug!("Установлены права на выполнение для {:?}", rclone_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("rclone успешно установлен в {:?}", rclone_path);
|
log::info!("rclone успешно установлен в {:?}", rclone_path);
|
||||||
|
|
||||||
// Проверяем установку
|
// Проверяем установку
|
||||||
let output = Command::new(&rclone_path)
|
let output = Command::new(&rclone_path)
|
||||||
@@ -197,7 +216,9 @@ impl RcloneApp {
|
|||||||
|
|
||||||
if output.status.success() {
|
if output.status.success() {
|
||||||
let version_output = String::from_utf8_lossy(&output.stdout);
|
let version_output = String::from_utf8_lossy(&output.stdout);
|
||||||
println!("Установленная версия rclone:\n{}", version_output);
|
log::info!("Установленная версия rclone:\n{}", version_output);
|
||||||
|
} else {
|
||||||
|
log::warn!("Не удалось проверить версию установленного rclone");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@@ -207,19 +228,29 @@ impl RcloneApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_command(&self, args: &[&str]) -> Result<String, String> {
|
pub fn run_command(&self, args: &[&str]) -> Result<String, String> {
|
||||||
|
log::debug!("Выполнение команды rclone: {} {:?}", self.rclone_path.display(), args);
|
||||||
|
|
||||||
let output = Command::new(&self.rclone_path)
|
let output = Command::new(&self.rclone_path)
|
||||||
.args(args)
|
.args(args)
|
||||||
.output()
|
.output()
|
||||||
.map_err(|e| format!("Ошибка запуска: {}", e))?;
|
.map_err(|e| {
|
||||||
|
log::error!("Ошибка запуска rclone: {}", e);
|
||||||
|
format!("Ошибка запуска: {}", e)
|
||||||
|
})?;
|
||||||
|
|
||||||
if output.status.success() {
|
if output.status.success() {
|
||||||
Ok(String::from_utf8_lossy(&output.stdout).to_string())
|
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
|
||||||
|
log::debug!("Команда выполнена успешно, вывод: {} байт", stdout.len());
|
||||||
|
Ok(stdout)
|
||||||
} else {
|
} else {
|
||||||
Err(String::from_utf8_lossy(&output.stderr).to_string())
|
let stderr = String::from_utf8_lossy(&output.stderr).to_string();
|
||||||
|
log::error!("Ошибка выполнения команды: {}", stderr);
|
||||||
|
Err(stderr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn version(&self) -> Result<String, String> {
|
pub fn version(&self) -> Result<String, String> {
|
||||||
|
log::debug!("Получение версии rclone");
|
||||||
self.run_command(&["version"])
|
self.run_command(&["version"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
use super::RcloneApp;
|
use super::RcloneApp;
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
use std::env;
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user