diff options
author | Lars Wirzenius <liw@liw.fi> | 2020-11-23 07:57:57 +0200 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2020-11-23 09:32:50 +0200 |
commit | eeabe321112af8fcef1b4c1be7728684f9a7a9aa (patch) | |
tree | 0722e5c3aeaac36987227bf5ee99c6a1e288cdeb /src/cmd | |
parent | 7194cdfb105b1b835dc2a4ff3bbfc1823f170243 (diff) | |
download | obnam2-eeabe321112af8fcef1b4c1be7728684f9a7a9aa.tar.gz |
feat: progress reporting to backups and restores
Diffstat (limited to 'src/cmd')
-rw-r--r-- | src/cmd/backup.rs | 33 | ||||
-rw-r--r-- | src/cmd/restore.rs | 23 |
2 files changed, 51 insertions, 5 deletions
diff --git a/src/cmd/backup.rs b/src/cmd/backup.rs index 926b2b1..8f195eb 100644 --- a/src/cmd/backup.rs +++ b/src/cmd/backup.rs @@ -1,9 +1,12 @@ use crate::client::{BackupClient, ClientConfig}; use crate::fsiter::FsIterator; use crate::generation::Generation; +use indicatif::{ProgressBar, ProgressStyle}; use std::path::Path; use tempfile::NamedTempFile; +const GUESS_FILE_COUNT: u64 = 0; + pub fn backup(config: &Path, buffer_size: usize) -> anyhow::Result<()> { let config = ClientConfig::read_config(config)?; let client = BackupClient::new(&config.server_url)?; @@ -21,10 +24,21 @@ pub fn backup(config: &Path, buffer_size: usize) -> anyhow::Result<()> { // 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)?; - gen.insert_iter(FsIterator::new(&config.root).map(|entry| match entry { - Err(err) => Err(err), - Ok(entry) => client.upload_filesystem_entry(entry, buffer_size), + let progress = create_progress_bar(GUESS_FILE_COUNT); + progress.enable_steady_tick(100); + gen.insert_iter(FsIterator::new(&config.root).map(|entry| { + progress.inc(1); + match entry { + Err(err) => Err(err), + Ok(entry) => { + progress.set_message(&format!("{}", entry.path().display())); + client.upload_filesystem_entry(entry, buffer_size) + } + } }))?; + progress.set_length(gen.file_count()); + progress.finish(); + println!("file count: {}", gen.file_count()); } // Upload the SQLite file, i.e., the named temporary file, which @@ -37,3 +51,16 @@ pub fn backup(config: &Path, buffer_size: usize) -> anyhow::Result<()> { Ok(()) } + +fn create_progress_bar(file_count: u64) -> ProgressBar { + let progress = ProgressBar::new(file_count); + let parts = vec![ + "{wide_bar}", + "elapsed: {elapsed}", + "files: {pos}/{len}", + "current: {wide_msg}", + "{spinner}", + ]; + progress.set_style(ProgressStyle::default_bar().template(&parts.join("\n"))); + progress +} diff --git a/src/cmd/restore.rs b/src/cmd/restore.rs index 0051d20..f2724c9 100644 --- a/src/cmd/restore.rs +++ b/src/cmd/restore.rs @@ -2,6 +2,7 @@ use crate::client::BackupClient; use crate::client::ClientConfig; use crate::fsentry::{FilesystemEntry, FilesystemKind}; use crate::generation::Generation; +use indicatif::{ProgressBar, ProgressStyle}; use log::{debug, info}; use std::fs::File; use std::io::prelude::*; @@ -35,9 +36,12 @@ pub fn restore(config: &Path, gen_id: &str, to: &Path) -> anyhow::Result<()> { info!("downloaded generation to {}", dbname.display()); let gen = Generation::open(&dbname)?; + println!("file count: {}", gen.file_count()); + let progress = create_progress_bar(gen.file_count()); for (fileid, entry) in gen.files()? { - restore_generation(&client, &gen, fileid, entry, &to)?; + restore_generation(&client, &gen, fileid, entry, &to, &progress)?; } + progress.finish(); // Delete the temporary file. std::fs::remove_file(&dbname)?; @@ -67,8 +71,10 @@ fn restore_generation( fileid: u64, entry: FilesystemEntry, to: &Path, + progress: &ProgressBar, ) -> anyhow::Result<()> { - println!("restoring {}:{}", fileid, entry.path().display()); + progress.set_message(&format!("{}", entry.path().display())); + progress.inc(1); let path = if entry.path().is_absolute() { entry.path().strip_prefix("/")? @@ -112,3 +118,16 @@ fn restore_regular( debug!("restored regular {}", path.display()); Ok(()) } + +fn create_progress_bar(file_count: u64) -> ProgressBar { + let progress = ProgressBar::new(file_count); + let parts = vec![ + "{wide_bar}", + "elapsed: {elapsed}", + "files: {pos}/{len}", + "current: {wide_msg}", + "{spinner}", + ]; + progress.set_style(ProgressStyle::default_bar().template(&parts.join("\n"))); + progress +} |