From 4d810f49298cce32ee0165b144af1917588c2de7 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Fri, 11 Dec 2020 17:41:42 +0200 Subject: feat! store file metadata as JSON This avoids having to add extra columns when we add more metadata support. This may be worth re-thinking later, once things stabilize. --- src/fsentry.rs | 5 +++-- src/generation.rs | 35 +++++++++++------------------------ 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/src/fsentry.rs b/src/fsentry.rs index 97274ed..ca73ef6 100644 --- a/src/fsentry.rs +++ b/src/fsentry.rs @@ -1,3 +1,4 @@ +use serde::{Deserialize, Serialize}; use std::path::{Path, PathBuf}; /// A file system entry. @@ -9,7 +10,7 @@ use std::path::{Path, PathBuf}; /// /// This is everything Obnam cares about each file system object, when /// making a backup. -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct FilesystemEntry { kind: FilesystemKind, path: PathBuf, @@ -54,7 +55,7 @@ impl FilesystemEntry { } /// Different types of file system entries. -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] pub enum FilesystemKind { Regular, Directory, diff --git a/src/generation.rs b/src/generation.rs index a2a2cdb..875221f 100644 --- a/src/generation.rs +++ b/src/generation.rs @@ -1,11 +1,7 @@ -use crate::fsentry::{FilesystemEntry, FilesystemKind}; -use std::ffi::OsStr; -use std::os::unix::ffi::OsStrExt; -//use crate::fsiter::FsIterator; use crate::chunkid::ChunkId; +use crate::fsentry::FilesystemEntry; use rusqlite::{params, Connection, OpenFlags, Row, Transaction}; -use std::os::unix::ffi::OsStringExt; -use std::path::{Path, PathBuf}; +use std::path::Path; /// A backup generation. pub struct Generation { @@ -21,7 +17,7 @@ impl Generation { let flags = OpenFlags::SQLITE_OPEN_CREATE | OpenFlags::SQLITE_OPEN_READ_WRITE; let conn = Connection::open_with_flags(filename, flags)?; conn.execute( - "CREATE TABLE files (fileno INTEGER PRIMARY KEY, path BLOB, kind INTEGER, len INTEGER)", + "CREATE TABLE files (fileno INTEGER PRIMARY KEY, json TEXT)", params![], )?; conn.execute( @@ -75,7 +71,8 @@ impl Generation { let iter = stmt.query_map(params![], |row| row_to_entry(row))?; let mut files: Vec<(u64, FilesystemEntry)> = vec![]; for x in iter { - let (fileno, entry) = x?; + let (fileno, json) = x?; + let entry = serde_json::from_str(&json)?; files.push((fileno, entry)); } Ok(files) @@ -96,19 +93,11 @@ impl Generation { } } -fn row_to_entry(row: &Row) -> rusqlite::Result<(u64, FilesystemEntry)> { +fn row_to_entry(row: &Row) -> rusqlite::Result<(u64, String)> { let fileno: i64 = row.get(row.column_index("fileno")?)?; let fileno = fileno as u64; - let path: Vec = row.get(row.column_index("path")?)?; - let path: &OsStr = OsStrExt::from_bytes(&path); - let path: PathBuf = PathBuf::from(path); - let kind = row.get(row.column_index("kind")?)?; - let kind = FilesystemKind::from_code(kind).unwrap(); - let entry = match kind { - FilesystemKind::Regular => FilesystemEntry::regular(path, 0), - FilesystemKind::Directory => FilesystemEntry::directory(path), - }; - Ok((fileno, entry)) + let json: String = row.get(row.column_index("json")?)?; + Ok((fileno, json)) } fn insert_one( @@ -117,13 +106,11 @@ fn insert_one( fileno: u64, ids: &[ChunkId], ) -> anyhow::Result<()> { - let path = e.path().as_os_str().to_os_string().into_vec(); - let kind = e.kind().as_code(); - let len = e.len() as i64; let fileno = fileno as i64; + let json = serde_json::to_string(&e)?; t.execute( - "INSERT INTO files (fileno, path, kind, len) VALUES (?1, ?2, ?3, ?4)", - params![fileno, path, kind, len], + "INSERT INTO files (fileno, json) VALUES (?1, ?2)", + params![fileno, &json], )?; for id in ids { t.execute( -- cgit v1.2.1