ok/jj
1
0
Fork 0
forked from mirrors/jj

tree: for walking tree, replace function with callback by iterator

Iterators are a lot easier to use.
This commit is contained in:
Martin von Zweigbergk 2020-12-20 00:07:51 -08:00
parent 4734eb6493
commit 8ec100713d
3 changed files with 68 additions and 31 deletions

View file

@ -17,11 +17,14 @@ use std::fmt::{Debug, Error, Formatter};
use std::sync::Arc;
use crate::matchers::AlwaysMatcher;
use crate::repo_path::{DirRepoPath, DirRepoPathComponent, FileRepoPath, RepoPath, RepoPathJoin};
use crate::repo_path::{
DirRepoPath, DirRepoPathComponent, FileRepoPath, RepoPath, RepoPathComponent, RepoPathJoin,
};
use crate::store;
use crate::store::{ConflictId, TreeEntriesIter, TreeEntry, TreeId, TreeValue};
use crate::store_wrapper::StoreWrapper;
use crate::trees::{recursive_tree_diff, walk_entries, TreeValueDiff};
use crate::trees::{recursive_tree_diff, TreeValueDiff};
use std::pin::Pin;
#[derive(Clone)]
pub struct Tree {
@ -91,6 +94,10 @@ impl Tree {
self.data.entries()
}
pub fn entries_recursive(&self) -> TreeWalk {
TreeWalk::new(self.clone())
}
pub fn entry<N>(&self, basename: &N) -> Option<TreeEntry>
where
N: Borrow<str> + ?Sized,
@ -187,13 +194,63 @@ impl Tree {
pub fn conflicts(&self) -> Vec<(RepoPath, ConflictId)> {
let mut conflicts = vec![];
walk_entries(&self, &mut |name, value| -> Result<(), ()> {
for (name, value) in self.entries_recursive() {
if let TreeValue::Conflict(id) = value {
conflicts.push((name.clone(), id.clone()));
}
Ok(())
})
.unwrap();
}
conflicts
}
}
pub struct TreeWalk {
stack: Vec<(Pin<Box<Tree>>, TreeEntriesIter<'static>)>,
}
impl TreeWalk {
fn new(tree: Tree) -> Self {
let tree = Box::pin(tree);
let iter = tree.entries();
let iter: TreeEntriesIter<'static> = unsafe { std::mem::transmute(iter) };
Self {
stack: vec![(tree, iter)],
}
}
}
impl Iterator for TreeWalk {
type Item = (RepoPath, TreeValue);
fn next(&mut self) -> Option<Self::Item> {
while !self.stack.is_empty() {
let (tree, iter) = self.stack.last_mut().unwrap();
match iter.next() {
None => {
// No more entries in this directory
self.stack.pop().unwrap();
}
Some(entry) => {
match entry.value() {
TreeValue::Tree(id) => {
let subtree =
tree.known_sub_tree(&DirRepoPathComponent::from(entry.name()), id);
let subtree = Box::pin(subtree);
let iter = subtree.entries();
let subtree_iter: TreeEntriesIter<'static> =
unsafe { std::mem::transmute(iter) };
self.stack.push((subtree, subtree_iter));
}
other => {
let path = RepoPath::new(
tree.dir().clone(),
RepoPathComponent::from(entry.name()),
);
return Some((path, other.clone()));
}
};
}
}
}
None
}
}

View file

@ -16,33 +16,13 @@ use crate::files;
use crate::files::MergeResult;
use crate::matchers::Matcher;
use crate::repo_path::{
DirRepoPath, DirRepoPathComponent, FileRepoPath, FileRepoPathComponent, RepoPath,
RepoPathComponent, RepoPathJoin,
DirRepoPath, DirRepoPathComponent, FileRepoPath, FileRepoPathComponent, RepoPathJoin,
};
use crate::store::{Conflict, ConflictPart, StoreError, TreeId, TreeValue};
use crate::store_wrapper::StoreWrapper;
use crate::tree::Tree;
use std::cmp::Ordering;
pub fn walk_entries<E>(
tree: &Tree,
callback: &mut impl FnMut(&RepoPath, &TreeValue) -> Result<(), E>,
) -> Result<(), E> {
for entry in tree.entries() {
let path = RepoPath::new(tree.dir().clone(), RepoPathComponent::from(entry.name()));
match entry.value() {
TreeValue::Tree(id) => {
let subtree = tree.known_sub_tree(&DirRepoPathComponent::from(entry.name()), id);
walk_entries(&subtree, callback)?;
}
other => {
callback(&path, other)?;
}
};
}
Ok(())
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Diff<T> {
Modified(T, T),

View file

@ -47,7 +47,7 @@ use jj_lib::settings::UserSettings;
use jj_lib::store::{CommitId, Timestamp};
use jj_lib::store::{StoreError, TreeValue};
use jj_lib::tree::Tree;
use jj_lib::trees::{walk_entries, TreeValueDiff};
use jj_lib::trees::TreeValueDiff;
use jj_lib::working_copy::{CheckoutStats, WorkingCopy};
use self::chrono::{FixedOffset, TimeZone, Utc};
@ -565,10 +565,10 @@ fn cmd_files(
let mut repo = get_repo(ui, &matches)?;
let mut_repo = Arc::get_mut(&mut repo).unwrap();
let commit = resolve_revision_arg(ui, mut_repo, sub_matches)?;
walk_entries(&commit.tree(), &mut |name, _value| {
for (name, _value) in commit.tree().entries_recursive() {
writeln!(ui, "{}", name.to_internal_string());
Ok(())
})
}
Ok(())
}
fn print_diff(left: &[u8], right: &[u8], styler: &mut dyn Styler) {