use crate::{Commit, EntryMode, Object, ObjectId, ObjectKind, Tag, Tree};
pub(crate) fn visit<E: From<Error>>(
id: ObjectId,
object: &Object,
mut edge: impl FnMut(ObjectId, ObjectKind) -> Result<(), E>,
) -> Result<(), E> {
match object.kind() {
ObjectKind::Blob => {}
ObjectKind::Commit => {
let commit = Commit::parse(object.object_format(), object.data())
.map_err(|source| Error::Commit { id, source })?;
edge(commit.tree(), ObjectKind::Tree)?;
for &parent in commit.parents() {
edge(parent, ObjectKind::Commit)?;
}
}
ObjectKind::Tree => {
let tree = Tree::parse(object.object_format(), object.data())
.map_err(|source| Error::Tree { id, source })?;
for entry in tree.entries() {
match entry.mode {
EntryMode::Gitlink => {}
EntryMode::Tree => edge(entry.id, ObjectKind::Tree)?,
_ => edge(entry.id, ObjectKind::Blob)?,
}
}
}
ObjectKind::Tag => {
let tag = Tag::parse(object.object_format(), object.data())
.map_err(|source| Error::Tag { id, source })?;
edge(tag.target(), tag.target_kind())?;
}
}
Ok(())
}
pub(crate) enum Error {
Commit {
id: ObjectId,
source: crate::CommitError,
},
Tree {
id: ObjectId,
source: crate::TreeError,
},
Tag {
id: ObjectId,
source: crate::TagError,
},
}