mirror of
https://github.com/martinvonz/jj.git
synced 2025-05-18 05:34:26 +00:00
tree: rewrite recursive entries iterator to not use machine stack
In the same vein as c02c4168fe2f.
This commit is contained in:
parent
a897b27770
commit
dbcecf7244
@ -231,24 +231,34 @@ impl Tree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct TreeEntriesIterator<'matcher> {
|
pub struct TreeEntriesIterator<'matcher> {
|
||||||
entry_iterator: TreeEntriesNonRecursiveIterator<'static>,
|
stack: Vec<TreeEntriesDirItem>,
|
||||||
// On drop, tree must outlive entry_iterator
|
|
||||||
tree: Pin<Box<Tree>>,
|
|
||||||
subdir_iterator: Option<Box<TreeEntriesIterator<'matcher>>>,
|
|
||||||
matcher: &'matcher dyn Matcher,
|
matcher: &'matcher dyn Matcher,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'matcher> TreeEntriesIterator<'matcher> {
|
struct TreeEntriesDirItem {
|
||||||
fn new(tree: Tree, matcher: &'matcher dyn Matcher) -> Self {
|
entry_iterator: TreeEntriesNonRecursiveIterator<'static>,
|
||||||
|
// On drop, tree must outlive entry_iterator
|
||||||
|
tree: Pin<Box<Tree>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TreeEntriesDirItem {
|
||||||
|
fn new(tree: Tree) -> Self {
|
||||||
let tree = Box::pin(tree);
|
let tree = Box::pin(tree);
|
||||||
// TODO: Restrict walk according to Matcher::visit()
|
|
||||||
let entry_iterator = tree.entries_non_recursive();
|
let entry_iterator = tree.entries_non_recursive();
|
||||||
let entry_iterator: TreeEntriesNonRecursiveIterator<'static> =
|
let entry_iterator: TreeEntriesNonRecursiveIterator<'static> =
|
||||||
unsafe { std::mem::transmute(entry_iterator) };
|
unsafe { std::mem::transmute(entry_iterator) };
|
||||||
Self {
|
Self {
|
||||||
entry_iterator,
|
entry_iterator,
|
||||||
tree,
|
tree,
|
||||||
subdir_iterator: None,
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'matcher> TreeEntriesIterator<'matcher> {
|
||||||
|
fn new(tree: Tree, matcher: &'matcher dyn Matcher) -> Self {
|
||||||
|
// TODO: Restrict walk according to Matcher::visit()
|
||||||
|
Self {
|
||||||
|
stack: vec![TreeEntriesDirItem::new(tree)],
|
||||||
matcher,
|
matcher,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -258,30 +268,25 @@ impl Iterator for TreeEntriesIterator<'_> {
|
|||||||
type Item = (RepoPath, TreeValue);
|
type Item = (RepoPath, TreeValue);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
loop {
|
while let Some(top) = self.stack.last_mut() {
|
||||||
// First return results from any subdirectory we're currently visiting.
|
if let Some(entry) = top.entry_iterator.next() {
|
||||||
if let Some(subdir_iter) = &mut self.subdir_iterator {
|
let path = top.tree.dir().join(entry.name());
|
||||||
if let Some(item) = subdir_iter.next() {
|
match entry.value() {
|
||||||
return Some(item);
|
TreeValue::Tree(id) => {
|
||||||
}
|
let subtree = top.tree.known_sub_tree(entry.name(), id);
|
||||||
self.subdir_iterator = None;
|
self.stack.push(TreeEntriesDirItem::new(subtree));
|
||||||
}
|
|
||||||
let entry = self.entry_iterator.next()?;
|
|
||||||
match entry.value() {
|
|
||||||
TreeValue::Tree(id) => {
|
|
||||||
let subtree = self.tree.known_sub_tree(entry.name(), id);
|
|
||||||
self.subdir_iterator =
|
|
||||||
Some(Box::new(TreeEntriesIterator::new(subtree, self.matcher)));
|
|
||||||
}
|
|
||||||
other => {
|
|
||||||
let path = self.tree.dir().join(entry.name());
|
|
||||||
if !self.matcher.matches(&path) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
return Some((path, other.clone()));
|
value => {
|
||||||
}
|
if self.matcher.matches(&path) {
|
||||||
};
|
return Some((path, value.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
self.stack.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user