diff --git a/src/command.rs b/src/command.rs index a0ba558..821e599 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,4 +1,4 @@ -pub fn exec_command(command: &Vec) -> Result<(), String> { +pub fn exec_command(command: &Vec<&str>) -> Result { if command.is_empty() { return Err("Command is empty".to_string()); } @@ -15,5 +15,6 @@ pub fn exec_command(command: &Vec) -> Result<(), String> { String::from_utf8_lossy(&output.stderr) )); } - Ok(()) + let output_str = String::from_utf8_lossy(&output.stdout).to_string(); + Ok(output_str) } diff --git a/src/lib.rs b/src/lib.rs index d9839a4..d69a522 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,24 +53,32 @@ impl JobBuilder { self } - pub fn build(self) -> Job { - for source in &self.sources { - let mut cmd = self.source_zfs_command.clone(); - let mut args = vec!["list".to_string(), source.clone()]; - cmd.append(&mut args); - match command::exec_command(&cmd) { - Ok(_) => (), - Err(e) => panic!("Cannot list source dataset {}: {}", source, e), - } - println!("Source: {}", source); - } - Job { - datasets: vec!["dataset1".to_string(), "dataset2".to_string()], + pub fn build(self) -> Result { + let mut job = Job { + datasets: vec![], target: self.target, source_zfs_command: self.source_zfs_command, target_zfs_command: self.target_zfs_command, dryrun: self.dryrun, + }; + let mut datasets: Vec = vec![]; + for source in &self.sources { + let recurse = source.ends_with("/..."); + let source = source.trim_end_matches("/..."); + + let mut args = vec!["list", "-H", "-o", "name"]; + if recurse { + args.push("-r"); + } + args.push(source); + + let mut cmd = job.get_side_command(JobSide::Source); + cmd.extend(args); + let output = command::exec_command(&cmd)?; + datasets = [datasets, output.lines().map(&str::to_string).collect()].concat(); } + job.datasets = datasets; + Ok(job) } } @@ -81,3 +89,25 @@ pub struct Job { target_zfs_command: Vec, dryrun: bool, } + +enum JobSide { + Source, + Destination, +} + +impl Job { + pub fn dump(&self) { + println!("Datasets: {:?}", self.datasets); + println!("Target: {}", self.target); + println!("Source ZFS Command: {:?}", self.source_zfs_command); + println!("Target ZFS Command: {:?}", self.target_zfs_command); + println!("Dryrun: {}", self.dryrun); + } + + fn get_side_command(&self, side: JobSide) -> Vec<&str> { + match side { + JobSide::Source => self.source_zfs_command.iter().map(|s| s.as_str()).collect(), + JobSide::Destination => self.target_zfs_command.iter().map(|s| s.as_str()).collect(), + } + } +} diff --git a/src/main.rs b/src/main.rs index e5eeaee..9116479 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,10 @@ +use std::env::args; + use zfsbackup::JobBuilder; fn main() { - let job = JobBuilder::new(vec!["chonk".to_string()], "backup".to_string()).build(); + let job = JobBuilder::new(args().skip(1).collect(), "backup".to_string()) + .build() + .expect("asplode"); + job.dump() }