diff --git a/src-tauri/src/commands/profile_commands.rs b/src-tauri/src/commands/profile_commands.rs index dd667f1..91f63dc 100644 --- a/src-tauri/src/commands/profile_commands.rs +++ b/src-tauri/src/commands/profile_commands.rs @@ -1,6 +1,6 @@ use rand::RngCore; use serde::{Deserialize, Serialize}; -use sha2::{Digest, Sha256}; +use sha2::{Digest, Sha256, Sha384}; use std::fs; use tauri::Manager; @@ -157,8 +157,8 @@ fn hex_encode(bytes: &[u8]) -> String { } /// Repair migration checksums for a profile database. -/// Deletes migration records that have mismatched checksums so they can be re-applied. -/// This fixes the "migration X was previously applied but has been modified" error. +/// Updates stored checksums to match current migration SQL, avoiding re-application +/// of destructive migrations (e.g., migration 2 which DELETEs categories/keywords). #[tauri::command] pub fn repair_migrations(app: tauri::AppHandle, db_filename: String) -> Result { let app_dir = app @@ -174,7 +174,6 @@ pub fn repair_migrations(app: tauri::AppHandle, db_filename: String) -> Result 0 FROM sqlite_master WHERE type='table' AND name='_sqlx_migrations'", @@ -187,14 +186,34 @@ pub fn repair_migrations(app: tauri::AppHandle, db_filename: String) -> Result 0) + let mut repaired = false; + for (version, sql) in migrations { + let expected_checksum = Sha384::digest(sql.as_bytes()).to_vec(); + + // Check if this migration exists with a different checksum + let needs_repair: bool = conn + .query_row( + "SELECT COUNT(*) > 0 FROM _sqlx_migrations WHERE version = ?1 AND checksum != ?2", + rusqlite::params![version, expected_checksum], + |row| row.get(0), + ) + .unwrap_or(false); + + if needs_repair { + conn.execute( + "UPDATE _sqlx_migrations SET checksum = ?1 WHERE version = ?2", + rusqlite::params![expected_checksum, version], + ) + .map_err(|e| format!("Cannot repair migration {}: {}", version, e))?; + repaired = true; + } + } + + Ok(repaired) }