diff options
author | Lars Wirzenius <liw@liw.fi> | 2020-12-11 17:41:42 +0200 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2020-12-11 18:12:46 +0200 |
commit | 4d810f49298cce32ee0165b144af1917588c2de7 (patch) | |
tree | a1b51a323f89a80eeded6032f906fce1bb197bf6 | |
parent | c2df16bb3644fc270a3f5ce7e048d509de0e4b51 (diff) | |
download | obnam2-4d810f49298cce32ee0165b144af1917588c2de7.tar.gz |
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.
-rw-r--r-- | src/fsentry.rs | 5 | ||||
-rw-r--r-- | 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<u8> = 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( |