Skip to content

Commit

Permalink
copy-tracking: extract next_impl from next in diff iter/stream
Browse files Browse the repository at this point in the history
  • Loading branch information
fowles committed Aug 11, 2024
1 parent 34b0f87 commit 0349d9e
Showing 1 changed file with 61 additions and 50 deletions.
111 changes: 61 additions & 50 deletions lib/src/merged_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,52 +663,8 @@ impl<'matcher> TreeDiffIterator<'matcher> {
Ok(Merge::resolved(Tree::empty(store.clone(), dir.to_owned())))
}
}
}

impl TreeDiffDirItem {
fn from_trees(
dir: &RepoPath,
trees1: &Merge<Tree>,
trees2: &Merge<Tree>,
matcher: &dyn Matcher,
) -> Self {
let mut entries = vec![];
for (name, before, after) in merged_tree_entry_diff(trees1, trees2) {
let path = dir.join(name);
let before = before.to_merge();
let after = after.to_merge();
let tree_before = before.is_tree();
let tree_after = after.is_tree();
// Check if trees and files match, but only if either side is a tree or a file
// (don't query the matcher unnecessarily).
let tree_matches = (tree_before || tree_after) && !matcher.visit(&path).is_nothing();
let file_matches = (!tree_before || !tree_after) && matcher.matches(&path);

// Replace trees or files that don't match by `Merge::absent()`
let before = if (tree_before && tree_matches) || (!tree_before && file_matches) {
before
} else {
Merge::absent()
};
let after = if (tree_after && tree_matches) || (!tree_after && file_matches) {
after
} else {
Merge::absent()
};
if before.is_absent() && after.is_absent() {
continue;
}
entries.push((path, before, after));
}
entries.reverse();
Self { entries }
}
}

impl Iterator for TreeDiffIterator<'_> {
type Item = TreeDiffEntry;

fn next(&mut self) -> Option<Self::Item> {
fn next_impl(&mut self) -> Option<TreeDiffEntry> {
while let Some(top) = self.stack.last_mut() {
let (path, before, after) = match top {
TreeDiffItem::Dir(dir) => match dir.entries.pop() {
Expand Down Expand Up @@ -788,6 +744,54 @@ impl Iterator for TreeDiffIterator<'_> {
}
}

impl TreeDiffDirItem {
fn from_trees(
dir: &RepoPath,
trees1: &Merge<Tree>,
trees2: &Merge<Tree>,
matcher: &dyn Matcher,
) -> Self {
let mut entries = vec![];
for (name, before, after) in merged_tree_entry_diff(trees1, trees2) {
let path = dir.join(name);
let before = before.to_merge();
let after = after.to_merge();
let tree_before = before.is_tree();
let tree_after = after.is_tree();
// Check if trees and files match, but only if either side is a tree or a file
// (don't query the matcher unnecessarily).
let tree_matches = (tree_before || tree_after) && !matcher.visit(&path).is_nothing();
let file_matches = (!tree_before || !tree_after) && matcher.matches(&path);

// Replace trees or files that don't match by `Merge::absent()`
let before = if (tree_before && tree_matches) || (!tree_before && file_matches) {
before
} else {
Merge::absent()
};
let after = if (tree_after && tree_matches) || (!tree_after && file_matches) {
after
} else {
Merge::absent()
};
if before.is_absent() && after.is_absent() {
continue;
}
entries.push((path, before, after));
}
entries.reverse();
Self { entries }
}
}

impl Iterator for TreeDiffIterator<'_> {
type Item = TreeDiffEntry;

fn next(&mut self) -> Option<Self::Item> {
self.next_impl()
}
}

/// Stream of differences between two trees.
pub struct TreeDiffStreamImpl<'matcher> {
matcher: &'matcher dyn Matcher,
Expand Down Expand Up @@ -997,12 +1001,11 @@ impl<'matcher> TreeDiffStreamImpl<'matcher> {
}
}
}
}

impl Stream for TreeDiffStreamImpl<'_> {
type Item = TreeDiffEntry;

fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
fn poll_next_impl(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<TreeDiffEntry>> {
// Go through all pending tree futures and poll them.
self.poll_tree_futures(cx);

Expand Down Expand Up @@ -1054,6 +1057,14 @@ impl Stream for TreeDiffStreamImpl<'_> {
}
}

impl Stream for TreeDiffStreamImpl<'_> {
type Item = TreeDiffEntry;

fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
self.as_mut().poll_next_impl(cx)
}
}

/// Helps with writing trees with conflicts. You start by creating an instance
/// of this type with one or more base trees. You then add overrides on top. The
/// overrides may be conflicts. Then you can write the result as a legacy tree
Expand Down

0 comments on commit 0349d9e

Please sign in to comment.