diff --git a/src/main.rs b/src/main.rs index de78ed4..964fd59 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ use std::io::IsTerminal; use std::sync::mpsc::channel; use std::thread; use zfsbackup::job::JobBuilder; -use zfsbackup::progress::{Progressor, log, terminal}; +use zfsbackup::progress::{Progressor, curt, log, terminal}; #[derive(Parser)] #[command(version, about, long_about = None)] @@ -29,6 +29,9 @@ struct Args { #[arg(short, long)] retain: Option, + #[arg(short, long)] + progressor: Option, + datasets: Vec, } @@ -49,10 +52,23 @@ fn main() -> Result<(), Box> { } let (tx, rx) = channel(); - let mut pr: Box = if std::io::stdout().is_terminal() { - Box::new(terminal::Progressor::new(rx)) - } else { - Box::new(log::Progressor::new(rx)) + let mut pr: Box = match args.progressor { + Some(name) => match name.as_str() { + "curt" => Box::new(curt::Progressor::new(rx)), + "terminal" => Box::new(terminal::Progressor::new(rx)), + "log" => Box::new(log::Progressor::new(rx)), + _ => { + eprintln!("progressor {} not found, defaulting to 'log'", name); + Box::new(log::Progressor::new(rx)) + } + }, + None => { + if std::io::stdout().is_terminal() { + Box::new(terminal::Progressor::new(rx)) + } else { + Box::new(log::Progressor::new(rx)) + } + } }; let handle = thread::spawn(move || pr.run()); builder = builder.sender(tx); diff --git a/src/progress/curt.rs b/src/progress/curt.rs new file mode 100644 index 0000000..c5b9cea --- /dev/null +++ b/src/progress/curt.rs @@ -0,0 +1,84 @@ +use super::{BackupEvent, human_bytes}; +use std::io::Write; +use std::sync::mpsc::Receiver; + +pub struct Progressor { + receiver: Receiver, + source: String, +} + +impl super::Progressor for Progressor { + fn run(&mut self) { + while let Ok(event) = self.receiver.recv() { + match event { + BackupEvent::Estimate(_) => {} + BackupEvent::FullBackupStart { + source, + dest: _, + index: _, + total: _, + } => { + self.source = source; + print!("{}\r", self.source); + } + BackupEvent::IncrementalBackupStart { + source, + dest: _, + index: _, + total: _, + } => { + self.source = source; + print!("{}\r", self.source); + } + BackupEvent::SnapshotCreate(_) => {} + BackupEvent::SnapshotDelete(_) => {} + BackupEvent::BytesTransferred { + bytes, + estimated_total, + } => { + match estimated_total { + Some(total) => { + let percent: f64 = if total > 0 { + bytes as f64 / total as f64 + } else { + 0.0 + }; + + print!("\x1b[2K{}: {:>3.0}%\r", self.source, percent * 100.0,); + } + None => { + print!( + "\x1b[2K{}: {} transferred\r", + self.source, + human_bytes(bytes as f64) + ); + } + } + std::io::stdout().flush().ok(); + } + BackupEvent::SendComplete(bytes) => { + print!( + "\x1b[2K{}: send complete ({})\r", + self.source, + human_bytes(bytes as f64) + ); + } + BackupEvent::DatasetComplete(_) => { + println!("\x1b[2K{}: complete", self.source); + } + BackupEvent::DryrunComplete(_) => { + println!("\x1b[2K{}: complete", self.source); + } + } + } + } +} + +impl Progressor { + pub fn new(receiver: Receiver) -> Self { + Self { + receiver, + source: String::new(), + } + } +} diff --git a/src/progress/mod.rs b/src/progress/mod.rs index e6f64a6..8db9fd3 100644 --- a/src/progress/mod.rs +++ b/src/progress/mod.rs @@ -1,3 +1,4 @@ +pub mod curt; pub mod filter; pub mod log; mod rate;