Skip to content

Commit 85f1a48

Browse files
committed
[repository #190] first shot at ancestor iteration…
…which surprisingly enough works with our kind of caching system. Amazing. Does it really work though?
1 parent e7188e0 commit 85f1a48

File tree

11 files changed

+134
-32
lines changed

11 files changed

+134
-32
lines changed

Cargo.toml

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,17 @@ env_logger = { version = "0.9.0", optional = true, default-features = false, fea
8080
crosstermion = { version = "0.8.0", optional = true, default-features = false }
8181
futures-lite = { version = "1.12.0", optional = true, default-features = false, features = ["std"] }
8282

83-
[profile.dev.package]
84-
git-object.opt-level = 3
85-
git-ref.opt-level = 3
86-
git-pack.opt-level = 3
87-
git-hash.opt-level = 3
88-
git-actor.opt-level = 3
89-
git-config.opt-level = 3
90-
miniz_oxide.opt-level = 3
91-
sha-1.opt-level = 3
92-
sha1.opt-level = 3
83+
# toml_edit can't parse this :(
84+
#[profile.dev.package]
85+
#git-object.opt-level = 3
86+
#git-ref.opt-level = 3
87+
#git-pack.opt-level = 3
88+
#git-hash.opt-level = 3
89+
#git-actor.opt-level = 3
90+
#git-config.opt-level = 3
91+
#miniz_oxide.opt-level = 3
92+
#sha-1.opt-level = 3
93+
#sha1.opt-level = 3
9394

9495
[profile.release]
9596
overflow-checks = false

experiments/diffing/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ where
255255
where
256256
L: for<'a> FnMut(&oid, &'a mut Vec<u8>) -> Option<odb::data::Object<'a>>,
257257
{
258-
find(id, buf).and_then(|o| o.into_tree_iter())
258+
find(id, buf).and_then(|o| o.try_into_tree_iter())
259259
}
260260

261261
fn tree_iter_by_commit<'b, L>(id: &oid, buf: &'b mut Vec<u8>, mut find: L) -> TreeRefIter<'b>
@@ -264,7 +264,7 @@ where
264264
{
265265
let tid = find(id, buf)
266266
.expect("commit present")
267-
.into_commit_iter()
267+
.try_into_commit_iter()
268268
.expect("a commit")
269269
.tree_id()
270270
.expect("tree id present and decodable");

experiments/traversal/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,13 @@ where
209209
for commit in commits {
210210
let tree_id = db
211211
.try_find(commit, &mut buf, &mut cache)?
212-
.and_then(|o| o.into_commit_iter().and_then(|mut c| c.tree_id()))
212+
.and_then(|o| o.try_into_commit_iter().and_then(|mut c| c.tree_id()))
213213
.expect("commit as starting point");
214214

215215
let mut count = Count { entries: 0, seen };
216216
db.find_tree_iter(tree_id, &mut buf2, &mut cache)?.traverse(
217217
&mut state,
218-
|oid, buf| db.find(oid, buf, &mut cache).ok().and_then(|o| o.into_tree_iter()),
218+
|oid, buf| db.find(oid, buf, &mut cache).ok().and_then(|o| o.try_into_tree_iter()),
219219
&mut count,
220220
)?;
221221
entries += count.entries as u64;

git-diff/tests/visit/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ mod changes {
3434
Ok(db
3535
.try_find(tree_id, buf, &mut pack::cache::Never)?
3636
.expect("main tree present")
37-
.into_tree_iter()
37+
.try_into_tree_iter()
3838
.expect("id to be a tree"))
3939
}
4040

@@ -53,7 +53,7 @@ mod changes {
5353
db.try_find(oid, buf, &mut pack::cache::Never)
5454
.ok()
5555
.flatten()
56-
.and_then(|obj| obj.into_tree_iter())
56+
.and_then(|obj| obj.try_into_tree_iter())
5757
},
5858
&mut recorder,
5959
)?;
@@ -78,7 +78,7 @@ mod changes {
7878
let current_tree = db
7979
.try_find(main_tree_id, &mut buf, &mut pack::cache::Never)?
8080
.expect("main tree present")
81-
.into_tree_iter()
81+
.try_into_tree_iter()
8282
.expect("id to be a tree");
8383
let mut buf2 = Vec::new();
8484
let previous_tree: Option<_> = {
@@ -88,7 +88,7 @@ mod changes {
8888
.and_then(|c| c.into_commit())
8989
.map(|c| c.tree())
9090
.and_then(|tree| db.try_find(tree, &mut buf2, &mut pack::cache::Never).ok().flatten())
91-
.and_then(|tree| tree.into_tree_iter())
91+
.and_then(|tree| tree.try_into_tree_iter())
9292
};
9393

9494
let mut recorder = git_diff::tree::Recorder::default();
@@ -99,7 +99,7 @@ mod changes {
9999
db.try_find(oid, buf, &mut pack::cache::Never)
100100
.ok()
101101
.flatten()
102-
.and_then(|obj| obj.into_tree_iter())
102+
.and_then(|obj| obj.try_into_tree_iter())
103103
},
104104
&mut recorder,
105105
)?;
@@ -133,7 +133,7 @@ mod changes {
133133
db.try_find(oid, buf, &mut pack::cache::Never)
134134
.ok()
135135
.flatten()
136-
.and_then(|o| o.into_commit_iter())
136+
.and_then(|o| o.try_into_commit_iter())
137137
})
138138
.collect::<Vec<_>>()
139139
.into_iter()

git-pack/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
### 0.10.0 (2021-08-??)
2+
3+
- **renames**
4+
- `data::Object::into_commit_iter()` -> `data::Object::try_into_commit_iter()`
5+
- `data::Object::into_tree_iter()` -> `data::Object::try_into_tree_iter()`
6+
- `data::Object::into_tag_iter()` -> `data::Object::try_into_tag_iter()`
7+
18
### 0.9.0 (2021-08-27)
29

310
- **renames / moves / visibility**

git-pack/src/data/object.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ impl<'a> Object<'a> {
2929

3030
/// Returns this object as tree iterator to parse entries one at a time to avoid allocations, or
3131
/// `None` if this is not a tree object.
32-
pub fn into_tree_iter(self) -> Option<TreeRefIter<'a>> {
32+
pub fn try_into_tree_iter(self) -> Option<TreeRefIter<'a>> {
3333
match self.kind {
3434
git_object::Kind::Tree => Some(TreeRefIter::from_bytes(self.data)),
3535
_ => None,
@@ -38,7 +38,7 @@ impl<'a> Object<'a> {
3838

3939
/// Returns this object as commit iterator to parse tokens one at a time to avoid allocations, or
4040
/// `None` if this is not a commit object.
41-
pub fn into_commit_iter(self) -> Option<CommitRefIter<'a>> {
41+
pub fn try_into_commit_iter(self) -> Option<CommitRefIter<'a>> {
4242
match self.kind {
4343
git_object::Kind::Commit => Some(CommitRefIter::from_bytes(self.data)),
4444
_ => None,
@@ -47,7 +47,7 @@ impl<'a> Object<'a> {
4747

4848
/// Returns this object as tag iterator to parse tokens one at a time to avoid allocations, or
4949
/// `None` if this is not a tag object.
50-
pub fn into_tag_iter(self) -> Option<TagRefIter<'a>> {
50+
pub fn try_into_tag_iter(self) -> Option<TagRefIter<'a>> {
5151
match self.kind {
5252
git_object::Kind::Tag => Some(TagRefIter::from_bytes(self.data)),
5353
_ => None,

git-pack/src/data/output/count/objects.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ where
217217
progress.inc();
218218
stats.expanded_objects += 1;
219219
out.push(output::Count::from_data(oid, &obj));
220-
obj.into_tree_iter()
220+
obj.try_into_tree_iter()
221221
}
222222
None => None,
223223
}
@@ -300,7 +300,7 @@ where
300300
progress.inc();
301301
stats.expanded_objects += 1;
302302
out.push(output::Count::from_data(oid, &obj));
303-
obj.into_tree_iter()
303+
obj.try_into_tree_iter()
304304
}
305305
None => None,
306306
}

git-pack/src/find_traits.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,9 @@ mod ext {
127127
make_obj_lookup!(find_tree, ObjectRef::Tree, Kind::Tree, TreeRef<'a>);
128128
make_obj_lookup!(find_tag, ObjectRef::Tag, Kind::Tag, TagRef<'a>);
129129
make_obj_lookup!(find_blob, ObjectRef::Blob, Kind::Blob, BlobRef<'a>);
130-
make_iter_lookup!(find_commit_iter, Kind::Blob, CommitRefIter<'a>, into_commit_iter);
131-
make_iter_lookup!(find_tree_iter, Kind::Tree, TreeRefIter<'a>, into_tree_iter);
132-
make_iter_lookup!(find_tag_iter, Kind::Tag, TagRefIter<'a>, into_tag_iter);
130+
make_iter_lookup!(find_commit_iter, Kind::Blob, CommitRefIter<'a>, try_into_commit_iter);
131+
make_iter_lookup!(find_tree_iter, Kind::Tree, TreeRefIter<'a>, try_into_tree_iter);
132+
make_iter_lookup!(find_tag_iter, Kind::Tag, TagRefIter<'a>, try_into_tag_iter);
133133
}
134134

135135
impl<T: super::Find> FindExt for T {}

git-repository/src/easy/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub mod commit;
2929
pub mod head;
3030
pub mod iter;
3131
pub mod object;
32-
mod oid;
32+
pub mod oid;
3333
pub mod reference;
3434
pub mod state;
3535

git-repository/src/easy/object/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,16 +131,16 @@ where
131131
/// As [`to_commit_iter()`][ObjectRef::to_commit_iter()] but panics if this is not a commit
132132
pub fn commit_iter(&self) -> CommitRefIter<'_> {
133133
git_odb::data::Object::new(self.kind, &self.data)
134-
.into_commit_iter()
134+
.try_into_commit_iter()
135135
.expect("BUG: This object must be a commit")
136136
}
137137

138138
pub fn to_commit_iter(&self) -> Option<CommitRefIter<'_>> {
139-
git_odb::data::Object::new(self.kind, &self.data).into_commit_iter()
139+
git_odb::data::Object::new(self.kind, &self.data).try_into_commit_iter()
140140
}
141141

142142
pub fn to_tag_iter(&self) -> Option<TagRefIter<'_>> {
143-
git_odb::data::Object::new(self.kind, &self.data).into_tag_iter()
143+
git_odb::data::Object::new(self.kind, &self.data).try_into_tag_iter()
144144
}
145145
}
146146

git-repository/src/easy/oid.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![allow(missing_docs)]
12
use std::ops::Deref;
23

34
use git_hash::{oid, ObjectId};
@@ -6,6 +7,7 @@ use crate::{
67
easy,
78
easy::{ext::ObjectAccessExt, object::find, ObjectRef, Oid},
89
};
10+
use std::cell::RefMut;
911

1012
impl<'repo, A> Oid<'repo, A>
1113
where
@@ -49,6 +51,98 @@ where
4951
}
5052
}
5153

54+
pub struct Ancestors<'repo, A>
55+
where
56+
A: easy::Access + Sized,
57+
{
58+
repo: A::RepoRef,
59+
pack_cache: RefMut<'repo, easy::PackCache>,
60+
access: &'repo A,
61+
tip: ObjectId,
62+
}
63+
64+
pub mod ancestors {
65+
use crate::easy;
66+
use crate::easy::oid::Ancestors;
67+
use crate::easy::Oid;
68+
use git_odb::Find;
69+
use std::ops::{Deref, DerefMut};
70+
71+
impl<'repo, A> Oid<'repo, A>
72+
where
73+
A: easy::Access + Sized,
74+
{
75+
pub fn ancestors(&self) -> Result<Ancestors<'repo, A>, Error> {
76+
let pack_cache = self.access.state().try_borrow_mut_pack_cache()?;
77+
let repo = self.access.repo()?;
78+
Ok(Ancestors {
79+
pack_cache,
80+
repo,
81+
access: self.access,
82+
tip: self.inner,
83+
})
84+
}
85+
}
86+
87+
pub struct Iter<'a, 'repo, A>
88+
where
89+
A: easy::Access + Sized,
90+
{
91+
access: &'repo A,
92+
inner: Box<dyn Iterator<Item = Result<git_hash::ObjectId, git_traverse::commit::ancestors::Error>> + 'a>,
93+
}
94+
95+
impl<'repo, A> Ancestors<'repo, A>
96+
where
97+
A: easy::Access + Sized,
98+
{
99+
// TODO: tests
100+
pub fn all(&mut self) -> Iter<'_, 'repo, A> {
101+
Iter {
102+
access: self.access,
103+
inner: Box::new(git_traverse::commit::Ancestors::new(
104+
Some(self.tip),
105+
git_traverse::commit::ancestors::State::default(),
106+
move |oid, buf| {
107+
self.repo
108+
.deref()
109+
.odb
110+
.try_find(oid, buf, self.pack_cache.deref_mut())
111+
.ok()
112+
.flatten()
113+
.and_then(|obj| obj.try_into_commit_iter())
114+
},
115+
)),
116+
}
117+
}
118+
}
119+
120+
impl<'a, 'repo, A> Iterator for Iter<'a, 'repo, A>
121+
where
122+
A: easy::Access + Sized,
123+
{
124+
type Item = Result<Oid<'repo, A>, git_traverse::commit::ancestors::Error>;
125+
126+
fn next(&mut self) -> Option<Self::Item> {
127+
self.inner.next().map(|res| res.map(|oid| oid.attach(self.access)))
128+
}
129+
}
130+
131+
mod error {
132+
use crate::easy;
133+
134+
#[derive(Debug, thiserror::Error)]
135+
pub enum Error {
136+
#[error(transparent)]
137+
BorrowRepo(#[from] easy::borrow::repo::Error),
138+
#[error(transparent)]
139+
BorrowBufMut(#[from] easy::borrow::state::Error),
140+
}
141+
}
142+
use crate::ext::ObjectIdExt;
143+
use error::Error;
144+
}
145+
52146
mod impls {
53147
use git_hash::{oid, ObjectId};
54148

0 commit comments

Comments
 (0)