diff options
| author | Bryan Newbold <bnewbold@robocracy.org> | 2017-11-24 18:45:37 -0800 | 
|---|---|---|
| committer | Bryan Newbold <bnewbold@robocracy.org> | 2017-11-24 18:45:37 -0800 | 
| commit | 9ca88a1ecdad6c492e1d07f7fff77e199a5fefd0 (patch) | |
| tree | 8ab695c63102700402eb7984d0099457cfd5a407 /src | |
| parent | 23a1fa44e8f69dedf23ea1e713a02b5112f9413a (diff) | |
| download | geniza-9ca88a1ecdad6c492e1d07f7fff77e199a5fefd0.tar.gz geniza-9ca88a1ecdad6c492e1d07f7fff77e199a5fefd0.zip | |
import/export drive directories
Diffstat (limited to 'src')
| -rw-r--r-- | src/bin/geniza-drive.rs | 31 | ||||
| -rw-r--r-- | src/drive.rs | 85 | 
2 files changed, 116 insertions, 0 deletions
| diff --git a/src/bin/geniza-drive.rs b/src/bin/geniza-drive.rs index d402539..42e06e2 100644 --- a/src/bin/geniza-drive.rs +++ b/src/bin/geniza-drive.rs @@ -52,6 +52,18 @@ fn run() -> Result<()> {                  .arg_from_usage("--target <path> 'path to save the file to (if not same name)'")          )          .subcommand( +            SubCommand::with_name("import-dir") +                .about("Adds a directory (recursively) to the dat") +                .arg_from_usage("<DIR> 'directory to add'") +                .arg_from_usage("--target <path> 'path to import the file to (if not top level)'") +        ) +        .subcommand( +            SubCommand::with_name("export-dir") +                .about("Copies a directory (recursively) from dat archive to local disk") +                .arg_from_usage("<DIR> 'directory to export'") +                .arg_from_usage("--target <path> 'path to save the directory to (if not same name)'") +        ) +        .subcommand(              SubCommand::with_name("log")                  .about("History of additions/deletions from this dat")          ) @@ -122,6 +134,25 @@ fn run() -> Result<()> {              };              drive.export_file(&path, &fpath)?;          } +        ("import-dir", Some(subm)) => { +            let path = Path::new(subm.value_of("DIR").unwrap()); +            let mut drive = DatDrive::open(dir, true)?; +            let fpath = match subm.value_of("target") { +                None => Path::new("/").join(path.file_name().unwrap()), +                Some(p) => Path::new("/").join(p) +            }; +            drive.import_dir(&path, &fpath)?; + +        } +        ("export-dir", Some(subm)) => { +            let path = Path::new(subm.value_of("DIR").unwrap()); +            let mut drive = DatDrive::open(dir, true)?; +            let fpath = match subm.value_of("target") { +                None => Path::new("/").join(path.file_name().unwrap()), +                Some(p) => Path::new("/").join(p) +            }; +            drive.export_dir(&path, &fpath)?; +        }          ("log", Some(_subm)) => {              let mut drive = DatDrive::open(dir, false)?;              for entry in drive.history(0) { diff --git a/src/drive.rs b/src/drive.rs index a4e6cf9..360555b 100644 --- a/src/drive.rs +++ b/src/drive.rs @@ -464,6 +464,56 @@ impl<'a> DatDrive {          Ok(())      } +    /// Copies Stat metadata and all content from a directory (recursively) from the "real" +    /// filesystem into the DatDrive. +    /// On success, returns version number including all the added files. +    pub fn import_dir<P: AsRef<Path>, Q: AsRef<Path>>(&mut self, source: P, dest: Q) -> Result<u64> { +        let source = source.as_ref(); +        let dest = dest.as_ref(); +        // TODO: check that dest doesn't exist (or is directory) +        let nearest = self.get_nearest(dest)?; +        if let Some(nearest) = nearest { +            if nearest.path == dest { +                bail!("destination already exists (as a file)"); +            } +        } +        let mut ret = self.entry_count()?; +        if source.is_dir() { +            for entry in read_dir(source)? { +                let entry = entry?; +                let path = entry.path(); +                let fname = path.file_name().unwrap().to_owned(); +                if fname.to_str() == Some(".dat") { +                    // Don't import yourself! +                    continue +                } +                if path.is_dir() { +                    ret = self.import_dir(path, dest.join(fname))?; +                } else { +                    ret = self.import_file(path, dest.join(fname))?; +                } +            } +        } else { +            bail!("Source path wasn't a directory"); +        } +        Ok(ret) +    } + +    /// Copies a file from the drive to the "real" filesystem, preserving Stat metadata. +    pub fn export_dir<P: AsRef<Path>, Q: AsRef<Path>>(&mut self, source: P, dest: Q) -> Result<()> { +        let source = source.as_ref(); +        let dest = dest.as_ref(); +        // TODO: this collect() is inefficient; read doesn't mutate, so shouldn't really need a +        // mutable borrow +        let path_list: Vec<Result<DriveEntry>> = self.read_dir_recursive(source).collect(); +        for entry in path_list { +            let path = entry?.path.to_owned(); +            let out_path = dest.join(path.strip_prefix(source).unwrap()); +            self.export_file(path, out_path)?; +        } +        Ok(()) +    } +      pub fn read_file_bytes<P: AsRef<Path>>(&mut self, path: P) -> Result<Vec<u8>> {          let de = self.get_file_entry(path.as_ref())?;          if let Some(entry) = de { @@ -703,6 +753,41 @@ fn test_dd_export_file() {  }  #[test] +fn test_dd_import_dir() { + +    use tempdir::TempDir; +    use env_logger; +    env_logger::init().unwrap(); +    let tmp_dir = TempDir::new("geniza-test").unwrap(); +    let mut dd = DatDrive::create(tmp_dir.path()).unwrap(); + +    dd.import_dir("test-data/dat/tree/Animalia/", "/").unwrap(); + +    assert_eq!(dd.read_dir("/").count(), 0); +    assert_eq!(dd.read_dir_recursive("/").count(), 2); + +    dd.import_file("test-data/dat/alphabet/a", "/a").unwrap(); +    assert!(dd.import_dir("test-data/dat/tree/Animalia/", "/a/").is_err()); + +} + +#[test] +fn test_dd_export_dir() { + +    use tempdir::TempDir; +    //use env_logger; +    //env_logger::init().unwrap(); +    let tmp_dir = TempDir::new("geniza-test").unwrap(); +    let mut dd = DatDrive::create(tmp_dir.path()).unwrap(); + +    dd.import_dir("test-data/dat/tree/Animalia/", "/").unwrap(); + +    dd.export_dir("/", tmp_dir.path()).unwrap(); +    dd.export_dir("/Chordata/Mammalia/Carnivora/Caniformia/", tmp_dir.path()).unwrap(); +    //assert!(dd.export_dir("/Fruit/", tmp_dir.path()).is_err()); +} + +#[test]  fn test_dd_remove_file() {      use tempdir::TempDir; | 
