From 619b0471182daf42615558a4449b3156541944f8 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 27 Dec 2020 15:08:50 +0200 Subject: refactor: rename Generation to NascentGeneration New name is more descriptive. --- src/cmd/backup.rs | 4 ++-- src/cmd/restore.rs | 8 ++++---- src/generation.rs | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cmd/backup.rs b/src/cmd/backup.rs index 2a294f5..c9b7fc5 100644 --- a/src/cmd/backup.rs +++ b/src/cmd/backup.rs @@ -1,6 +1,6 @@ use crate::client::{BackupClient, ClientConfig}; use crate::fsiter::FsIterator; -use crate::generation::Generation; +use crate::generation::NascentGeneration; use indicatif::{ProgressBar, ProgressStyle}; use log::info; use tempfile::NamedTempFile; @@ -22,7 +22,7 @@ pub fn backup(config: &ClientConfig, buffer_size: usize) -> anyhow::Result<()> { // Create the SQLite database using the named temporary file. // The fetching is in its own block so that the file handles // get closed and data flushed to disk. - let mut gen = Generation::create(&dbname)?; + let mut gen = NascentGeneration::create(&dbname)?; let progress = create_progress_bar(GUESS_FILE_COUNT, true); progress.enable_steady_tick(100); gen.insert_iter(FsIterator::new(&config.root).map(|entry| { diff --git a/src/cmd/restore.rs b/src/cmd/restore.rs index da654fd..dd7ed41 100644 --- a/src/cmd/restore.rs +++ b/src/cmd/restore.rs @@ -1,7 +1,7 @@ use crate::client::BackupClient; use crate::client::ClientConfig; use crate::fsentry::{FilesystemEntry, FilesystemKind}; -use crate::generation::Generation; +use crate::generation::NascentGeneration; use indicatif::{ProgressBar, ProgressStyle}; use libc::{fchmod, futimens, timespec}; use log::{debug, error, info}; @@ -37,7 +37,7 @@ pub fn restore(config: &ClientConfig, gen_id: &str, to: &Path) -> anyhow::Result } info!("downloaded generation to {}", dbname.display()); - let gen = Generation::open(&dbname)?; + let gen = NascentGeneration::open(&dbname)?; info!("restore file count: {}", gen.file_count()); let progress = create_progress_bar(gen.file_count(), true); for (fileid, entry) in gen.files()? { @@ -74,7 +74,7 @@ struct Opt { fn restore_generation( client: &BackupClient, - gen: &Generation, + gen: &NascentGeneration, fileid: u64, entry: &FilesystemEntry, to: &Path, @@ -123,7 +123,7 @@ fn restored_path(entry: &FilesystemEntry, to: &Path) -> anyhow::Result fn restore_regular( client: &BackupClient, - gen: &Generation, + gen: &NascentGeneration, path: &Path, fileid: u64, entry: &FilesystemEntry, diff --git a/src/generation.rs b/src/generation.rs index 875221f..32b1e73 100644 --- a/src/generation.rs +++ b/src/generation.rs @@ -4,12 +4,12 @@ use rusqlite::{params, Connection, OpenFlags, Row, Transaction}; use std::path::Path; /// A backup generation. -pub struct Generation { +pub struct NascentGeneration { conn: Connection, fileno: u64, } -impl Generation { +impl NascentGeneration { pub fn create

(filename: P) -> anyhow::Result where P: AsRef, @@ -136,14 +136,14 @@ fn find_max_fileno(conn: &Connection) -> anyhow::Result { #[cfg(test)] mod test { - use super::Generation; + use super::NascentGeneration; use tempfile::NamedTempFile; #[test] fn empty() { let filename = NamedTempFile::new().unwrap().path().to_path_buf(); { - let mut _gen = Generation::create(&filename).unwrap(); + let mut _gen = NascentGeneration::create(&filename).unwrap(); // _gen is dropped here; the connection is close; the file // should not be removed. } -- cgit v1.2.1 From 48639d00710cf945cff7298cf927efc7275364e2 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 27 Dec 2020 15:18:10 +0200 Subject: add FinishedGeneration --- src/generation.rs | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/generation.rs b/src/generation.rs index 32b1e73..fdfd7f1 100644 --- a/src/generation.rs +++ b/src/generation.rs @@ -3,7 +3,11 @@ use crate::fsentry::FilesystemEntry; use rusqlite::{params, Connection, OpenFlags, Row, Transaction}; use std::path::Path; -/// A backup generation. +/// A nascent backup generation. +/// +/// A nascent generation is one that is being prepared. It isn't +/// finished yet, and it's not actually on the server, yet, or not +/// completely. It can't be restored. pub struct NascentGeneration { conn: Connection, fileno: u64, @@ -150,3 +154,28 @@ mod test { assert!(filename.exists()); } } + +/// A finished generation. +/// +/// A generation is finished when it's on the server. It can be restored. +pub struct FinishedGeneration { + id: ChunkId, + ended: String, +} + +impl FinishedGeneration { + pub fn new(id: ChunkId, ended: &str) -> Self { + Self { + id: id.clone(), + ended: ended.to_string(), + } + } + + pub fn id(&self) -> ChunkId { + self.id.clone() + } + + pub fn ended(&self) -> &str { + &self.ended + } +} -- cgit v1.2.1 From c492bc19aaf404ab4115b8d7f06eff81a6480b4e Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Wed, 30 Dec 2020 13:33:57 +0200 Subject: feat! store and show timestamp for each backup generation This changes the output format of "obnam list". --- Cargo.toml | 1 + src/client.rs | 17 ++++++++++++++--- src/cmd/list.rs | 6 ++++-- src/generation.rs | 5 +++-- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a8e404b..e8bbd91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] anyhow = "1" bytes = "0.5" +chrono = "0.4" indicatif = "0.15" libc = "0.2" log = "0.4" diff --git a/src/client.rs b/src/client.rs index 3149ec5..adca373 100644 --- a/src/client.rs +++ b/src/client.rs @@ -5,6 +5,8 @@ use crate::chunker::Chunker; use crate::chunkid::ChunkId; use crate::chunkmeta::ChunkMeta; use crate::fsentry::{FilesystemEntry, FilesystemKind}; +use crate::generation::FinishedGeneration; +use chrono::{DateTime, Local}; use log::{debug, error, info, trace}; use reqwest::blocking::Client; use serde::Deserialize; @@ -73,7 +75,7 @@ impl BackupClient { let ids = self.read_file(filename.to_path_buf(), size)?; let gen = GenerationChunk::new(ids); let data = gen.to_data_chunk()?; - let meta = ChunkMeta::new_generation(&sha256(data.data()), "timestamp"); + let meta = ChunkMeta::new_generation(&sha256(data.data()), ¤t_timestamp()); let gen_id = self.upload_gen_chunk(meta, gen)?; Ok(gen_id) } @@ -179,7 +181,7 @@ impl BackupClient { Ok(chunk_ids) } - pub fn list_generations(&self) -> anyhow::Result> { + pub fn list_generations(&self) -> anyhow::Result> { let url = format!("{}?generation=true", &self.chunks_url()); trace!("list_generations: url={:?}", url); let req = self.client.get(&url).build()?; @@ -189,7 +191,11 @@ impl BackupClient { debug!("list_generationgs: body={:?}", body); let map: HashMap = serde_yaml::from_slice(&body)?; debug!("list_generations: map={:?}", map); - Ok(map.keys().into_iter().map(|key| key.into()).collect()) + let finished = map + .iter() + .map(|(id, meta)| FinishedGeneration::new(id, meta.ended().map_or("", |s| s))) + .collect(); + Ok(finished) } pub fn fetch_chunk(&self, chunk_id: &ChunkId) -> anyhow::Result { @@ -222,3 +228,8 @@ impl BackupClient { Ok(gen) } } + +fn current_timestamp() -> String { + let now: DateTime = Local::now(); + format!("{}", now.format("%Y-%m-%d %H:%M:%S %z")) +} diff --git a/src/cmd/list.rs b/src/cmd/list.rs index 6c48244..70aa0a7 100644 --- a/src/cmd/list.rs +++ b/src/cmd/list.rs @@ -3,8 +3,10 @@ use crate::client::{BackupClient, ClientConfig}; pub fn list(config: &ClientConfig) -> anyhow::Result<()> { let client = BackupClient::new(&config.server_url)?; - for gen_id in client.list_generations()? { - println!("{}", gen_id); + let mut generations = client.list_generations()?; + generations.sort_by_cached_key(|gen| gen.ended().to_string()); + for finished in generations { + println!("{} {}", finished.id(), finished.ended()); } Ok(()) diff --git a/src/generation.rs b/src/generation.rs index fdfd7f1..dc9bf0c 100644 --- a/src/generation.rs +++ b/src/generation.rs @@ -164,9 +164,10 @@ pub struct FinishedGeneration { } impl FinishedGeneration { - pub fn new(id: ChunkId, ended: &str) -> Self { + pub fn new(id: &str, ended: &str) -> Self { + let id = id.parse().unwrap(); // this never fails Self { - id: id.clone(), + id, ended: ended.to_string(), } } -- cgit v1.2.1