Skip to content

Commit

Permalink
Combine subtree and exclusions to ReadTree:iter_filtered
Browse files Browse the repository at this point in the history
  • Loading branch information
sourcefrog committed Oct 16, 2020
1 parent 684ea03 commit d7ec219
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/copy_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub fn copy_tree<ST: ReadTree, DT: WriteTree>(
progress_bar.set_phase("Copying".to_owned());
let entry_iter: Box<dyn Iterator<Item = ST::Entry>> = match &options.only_subtree {
None => Box::new(source.iter_entries()?),
Some(subtree) => source.iter_subtree_entries(subtree)?,
Some(subtree) => source.iter_filtered(subtree, &excludes::excludes_nothing())?,
};
for entry in entry_iter {
if options.print_filenames {
Expand Down
10 changes: 7 additions & 3 deletions src/live_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,15 @@ impl tree::ReadTree for LiveTree {
Ok(Box::new(Iter::new(&self.path, &self.excludes)?))
}

fn iter_subtree_entries(&self, subtree: &Apath) -> Result<Box<dyn Iterator<Item = LiveEntry>>> {
fn iter_filtered(
&self,
subtree: &Apath,
excludes: &GlobSet,
) -> Result<Box<dyn Iterator<Item = LiveEntry>>> {
// TODO: Just skip directly to the requested directory, and stop when it's done.
let subtree = subtree.to_owned();
Ok(Box::new(
self.iter_entries()?
Iter::new(&self.path, excludes)?
.filter(move |entry| subtree.is_prefix_of(entry.apath())),
))
}
Expand Down Expand Up @@ -464,7 +468,7 @@ mod tests {
let lt = LiveTree::open(tf.path()).unwrap();

let names: Vec<String> = lt
.iter_subtree_entries(&"/subdir".into())
.iter_filtered(&"/subdir".into(), &excludes::excludes_nothing())
.unwrap()
.map(|entry| entry.apath.into())
.collect();
Expand Down
17 changes: 2 additions & 15 deletions src/stored_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,19 +111,6 @@ impl ReadTree for StoredTree {
))
}

fn iter_subtree_entries(
&self,
subtree: &Apath,
) -> Result<Box<dyn Iterator<Item = IndexEntry>>> {
// TODO: Advance in the index to the requested directory, and stop immediately when it's
// done.
let subtree = subtree.to_owned();
Ok(Box::new(
self.iter_entries()?
.filter(move |entry| subtree.is_prefix_of(entry.apath())),
))
}

fn file_contents(&self, entry: &Self::Entry) -> Result<Self::R> {
Ok(self.open_stored_file(entry)?.into_read())
}
Expand Down Expand Up @@ -177,14 +164,14 @@ mod test {
}

#[test]
fn iter_subtree_entries() {
fn iter_filtered() {
let archive = Archive::open_path(Path::new("testdata/archive/v0.6.3/minimal-1/")).unwrap();
let st = archive
.open_stored_tree(BandSelectionPolicy::Latest)
.unwrap();

let names: Vec<String> = st
.iter_subtree_entries(&"/subdir".into())
.iter_filtered(&"/subdir".into(), &excludes::excludes_nothing())
.unwrap()
.map(|entry| entry.apath.into())
.collect();
Expand Down
18 changes: 11 additions & 7 deletions src/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::*;
/// Abstract Tree that may be either on the real filesystem or stored in an archive.
pub trait ReadTree {
// TODO: Perhaps hide these and just return dyn objects?
type Entry: Entry;
type Entry: Entry + 'static;
type R: std::io::Read;

/// Iterate, in apath order, all the entries in this tree.
Expand All @@ -31,14 +31,18 @@ pub trait ReadTree {
/// iterator.
fn iter_entries(&self) -> Result<Box<dyn Iterator<Item = Self::Entry>>>;

/// Iterate, in apath order, the entries from a subtree.
///
/// The provided implementation iterates and filters all entries, but implementations
/// may be able to do better.
fn iter_subtree_entries(
/// Return entries within the subtree and not excluded.
fn iter_filtered(
&self,
subtree: &Apath,
) -> Result<Box<dyn Iterator<Item = Self::Entry>>>;
excludes: &GlobSet,
) -> Result<Box<dyn Iterator<Item = Self::Entry>>> {
let subtree = subtree.to_owned();
let excludes = excludes.clone();
Ok(Box::new(self.iter_entries()?.filter(move |entry| {
subtree.is_prefix_of(entry.apath()) && !excludes.is_match(entry.apath())
})))
}

/// Read file contents as a `std::io::Read`.
// TODO: Remove this and use ReadBlocks or similar.
Expand Down

0 comments on commit d7ec219

Please sign in to comment.