Skip to main content

game_manager_lib/database/backup/
auto.rs

1//! Módulo com a lógica de update automático
2
3use crate::database::backup::export_queries::fetch_backup_data;
4use crate::database::backup::models::BackupData;
5use crate::database::{self, AppState};
6use crate::errors::AppError;
7use chrono::Utc;
8use std::fs;
9use std::path::PathBuf;
10use tauri::{AppHandle, Manager};
11
12pub fn backup_if_major_update(
13    app: &AppHandle,
14    previous_version: &str,
15    current_version: &str,
16) -> Result<Option<PathBuf>, AppError> {
17    // Parse das versões
18    let parse_version = |v: &str| -> (u32, u32, u32) {
19        let parts: Vec<&str> = v.split('.').collect();
20        let major = parts.first().and_then(|s| s.parse().ok()).unwrap_or(0);
21        let minor = parts.get(1).and_then(|s| s.parse().ok()).unwrap_or(0);
22        let patch = parts.get(2).and_then(|s| s.parse().ok()).unwrap_or(0);
23        (major, minor, patch)
24    };
25
26    let (prev_major, _, _) = parse_version(previous_version);
27    let (curr_major, _, _) = parse_version(current_version);
28
29    // Se versão major mudou, faz backup
30    if prev_major != curr_major && prev_major > 0 {
31        tracing::info!(
32            "Mudança de versão major detectada: v{} -> v{}",
33            previous_version,
34            current_version
35        );
36        let backup_path = backup_before_update(app, previous_version)?;
37        Ok(Some(backup_path))
38    } else {
39        Ok(None)
40    }
41}
42
43/// Cria backup automático antes de atualização de versão
44///
45/// Chamado automaticamente quando detecta mudança de versão major
46pub fn backup_before_update(app: &AppHandle, previous_version: &str) -> Result<PathBuf, AppError> {
47    tracing::info!("Criando backup automático antes da atualização...");
48
49    let app_data_dir = app
50        .path()
51        .app_data_dir()
52        .map_err(|e| AppError::IoError(format!("Falha ao obter app_data_dir: {}", e)))?;
53
54    let backups_dir = app_data_dir.join("backups");
55    fs::create_dir_all(&backups_dir)?;
56
57    // Nome do backup com timestamp e versão anterior
58    let timestamp = chrono::Local::now().format("%Y%m%d_%H%M%S");
59    let backup_filename = format!("auto_backup_v{}_{}.json", previous_version, timestamp);
60    let backup_path = backups_dir.join(backup_filename);
61
62    // Reutiliza a função auxiliar de fetch
63    let state: tauri::State<AppState> = app.state();
64    let (
65        games,
66        game_details,
67        wishlist_game,
68        game_extras,
69        system_requirements,
70        game_data_paths,
71        schema_version,
72    ) = fetch_backup_data(&state)?;
73
74    let backup = BackupData {
75        version: schema_version,
76        app_version: previous_version.to_string(),
77        date: chrono::Local::now().to_rfc3339(),
78        games,
79        game_details,
80        wishlist_game,
81        game_extras,
82        system_requirements,
83        game_data_paths,
84    };
85
86    let json = serde_json::to_string_pretty(&backup)?;
87    fs::write(&backup_path, json)?;
88
89    // Atualiza timestamp do último backup automático
90    let cache_conn = state.cache_db.lock().map_err(|_| AppError::MutexError)?;
91    let now = Utc::now().to_rfc3339();
92    database::configs::set_config(&cache_conn, "last_auto_backup_at", &now)?;
93
94    tracing::info!("Backup automático criado: {:?}", backup_path);
95    Ok(backup_path)
96}