Skip to content

Commit 710701c

Browse files
authored
Merge pull request #1004 from joshtriplett/nth
Tree iteration: Make skipping ahead more efficient
2 parents 8136881 + 5d0628e commit 710701c

File tree

1 file changed

+48
-16
lines changed

1 file changed

+48
-16
lines changed

src/tree.rs

+48-16
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,9 @@ impl<'tree> Iterator for TreeIter<'tree> {
397397
fn size_hint(&self) -> (usize, Option<usize>) {
398398
self.range.size_hint()
399399
}
400+
fn nth(&mut self, n: usize) -> Option<TreeEntry<'tree>> {
401+
self.range.nth(n).and_then(|i| self.tree.get(i))
402+
}
400403
}
401404
impl<'tree> DoubleEndedIterator for TreeIter<'tree> {
402405
fn next_back(&mut self) -> Option<TreeEntry<'tree>> {
@@ -472,20 +475,41 @@ mod tests {
472475

473476
let tree = repo.find_tree(commit.tree_id()).unwrap();
474477
assert_eq!(tree.id(), commit.tree_id());
475-
assert_eq!(tree.len(), 1);
478+
assert_eq!(tree.len(), 8);
476479

477480
for entry in tree_iter(&tree, &repo) {
478481
println!("iter entry {:?}", entry.name());
479482
}
480483
}
481484

485+
#[test]
486+
fn smoke_tree_nth() {
487+
let (td, repo) = crate::test::repo_init();
488+
489+
setup_repo(&td, &repo);
490+
491+
let head = repo.head().unwrap();
492+
let target = head.target().unwrap();
493+
let commit = repo.find_commit(target).unwrap();
494+
495+
let tree = repo.find_tree(commit.tree_id()).unwrap();
496+
assert_eq!(tree.id(), commit.tree_id());
497+
assert_eq!(tree.len(), 8);
498+
let mut it = tree.iter();
499+
let e = it.nth(4).unwrap();
500+
assert_eq!(e.name(), Some("f4"));
501+
}
502+
482503
fn setup_repo(td: &TempDir, repo: &Repository) {
483504
let mut index = repo.index().unwrap();
484-
File::create(&td.path().join("foo"))
485-
.unwrap()
486-
.write_all(b"foo")
487-
.unwrap();
488-
index.add_path(Path::new("foo")).unwrap();
505+
for n in 0..8 {
506+
let name = format!("f{n}");
507+
File::create(&td.path().join(&name))
508+
.unwrap()
509+
.write_all(name.as_bytes())
510+
.unwrap();
511+
index.add_path(Path::new(&name)).unwrap();
512+
}
489513
let id = index.write_tree().unwrap();
490514
let sig = repo.signature().unwrap();
491515
let tree = repo.find_tree(id).unwrap();
@@ -515,14 +539,22 @@ mod tests {
515539

516540
let tree = repo.find_tree(commit.tree_id()).unwrap();
517541
assert_eq!(tree.id(), commit.tree_id());
518-
assert_eq!(tree.len(), 1);
542+
assert_eq!(tree.len(), 8);
519543
{
520-
let e1 = tree.get(0).unwrap();
544+
let e0 = tree.get(0).unwrap();
545+
assert!(e0 == tree.get_id(e0.id()).unwrap());
546+
assert!(e0 == tree.get_name("f0").unwrap());
547+
assert!(e0 == tree.get_name_bytes(b"f0").unwrap());
548+
assert!(e0 == tree.get_path(Path::new("f0")).unwrap());
549+
assert_eq!(e0.name(), Some("f0"));
550+
e0.to_object(&repo).unwrap();
551+
552+
let e1 = tree.get(1).unwrap();
521553
assert!(e1 == tree.get_id(e1.id()).unwrap());
522-
assert!(e1 == tree.get_name("foo").unwrap());
523-
assert!(e1 == tree.get_name_bytes(b"foo").unwrap());
524-
assert!(e1 == tree.get_path(Path::new("foo")).unwrap());
525-
assert_eq!(e1.name(), Some("foo"));
554+
assert!(e1 == tree.get_name("f1").unwrap());
555+
assert!(e1 == tree.get_name_bytes(b"f1").unwrap());
556+
assert!(e1 == tree.get_path(Path::new("f1")).unwrap());
557+
assert_eq!(e1.name(), Some("f1"));
526558
e1.to_object(&repo).unwrap();
527559
}
528560
tree.into_object();
@@ -551,20 +583,20 @@ mod tests {
551583

552584
let mut ct = 0;
553585
tree.walk(TreeWalkMode::PreOrder, |_, entry| {
554-
assert_eq!(entry.name(), Some("foo"));
586+
assert_eq!(entry.name(), Some(format!("f{ct}").as_str()));
555587
ct += 1;
556588
0
557589
})
558590
.unwrap();
559-
assert_eq!(ct, 1);
591+
assert_eq!(ct, 8);
560592

561593
let mut ct = 0;
562594
tree.walk(TreeWalkMode::PreOrder, |_, entry| {
563-
assert_eq!(entry.name(), Some("foo"));
595+
assert_eq!(entry.name(), Some(format!("f{ct}").as_str()));
564596
ct += 1;
565597
TreeWalkResult::Ok
566598
})
567599
.unwrap();
568-
assert_eq!(ct, 1);
600+
assert_eq!(ct, 8);
569601
}
570602
}

0 commit comments

Comments
 (0)