use std::fs;
use std::path::Path;
use std::time::UNIX_EPOCH;
use rusqlite::{Connection, Error as SqliteError};
use crate::config::UblxPaths;
use crate::engine::db_ops::consts::{UblxDbCategory, UblxDbStatements};
use crate::integrations::zahir_metadata_name_from_indexed_file;
use crate::utils::snapshot_rel_path_buf;
fn mtime_ns_from_meta(meta: &fs::Metadata) -> i64 {
meta.modified()
.ok()
.and_then(|t| t.duration_since(UNIX_EPOCH).ok())
.and_then(|d| i64::try_from(d.as_nanos()).ok())
.unwrap_or(0)
}
pub fn delete_snapshot_row(db_path: &Path, rel_path: &str) -> Result<(), anyhow::Error> {
if !db_path.exists() {
return Ok(());
}
let conn = Connection::open(db_path)?;
conn.execute(UblxDbStatements::DELETE_SNAPSHOT_ROW, [rel_path])?;
Ok(())
}
pub fn rename_snapshot_row(
db_path: &Path,
dir_to_ublx: &Path,
ublx_paths: Option<&UblxPaths>,
old_rel: &str,
new_rel: &str,
) -> Result<(), anyhow::Error> {
if !db_path.exists() {
return Ok(());
}
let full_new = dir_to_ublx.join(snapshot_rel_path_buf(new_rel));
let meta = fs::metadata(&full_new)?;
let mtime_ns = mtime_ns_from_meta(&meta);
let size_i = if meta.is_dir() {
0_i64
} else {
i64::try_from(meta.len()).unwrap_or(i64::MAX)
};
let hint = zahir_metadata_name_from_indexed_file(&full_new, new_rel);
let category = UblxDbCategory::get_category_for_path(&full_new, ublx_paths, hint.as_deref());
let conn = Connection::open(db_path)?;
let zahir_json: String = match conn.query_row(
"SELECT COALESCE(zahir_json, '') FROM snapshot WHERE path = ?1",
[old_rel],
|row| row.get::<_, String>(0),
) {
Ok(s) => s,
Err(SqliteError::QueryReturnedNoRows) => return Ok(()),
Err(e) => return Err(e.into()),
};
conn.execute(
UblxDbStatements::UPDATE_SNAPSHOT_RENAME_IN_PLACE,
rusqlite::params![
new_rel,
mtime_ns,
size_i,
Option::<Vec<u8>>::None,
category,
zahir_json,
old_rel,
],
)?;
Ok(())
}