Skip to content

Commit

Permalink
repository(doc): easy::object, sans a few child-modules (#164)
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Sep 13, 2021
1 parent 42080ae commit f582439
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 127 deletions.
46 changes: 46 additions & 0 deletions git-repository/src/easy/object/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#![allow(missing_docs)]
///
pub mod find {

use crate::easy;

pub(crate) type OdbError = git_odb::compound::find::Error;

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
Find(#[from] OdbError),
#[error("BUG: Part of interior state could not be borrowed.")]
BorrowState(#[from] easy::borrow::state::Error),
#[error("BUG: The repository could not be borrowed")]
BorrowRepo(#[from] easy::borrow::repo::Error),
}

pub mod existing {
use crate::easy;

pub(crate) type OdbError = git_odb::pack::find::existing::Error<git_odb::compound::find::Error>;

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
FindExisting(#[from] OdbError),
#[error("BUG: Part of interior state could not be borrowed.")]
BorrowState(#[from] easy::borrow::state::Error),
#[error("BUG: The repository could not be borrowed")]
BorrowRepo(#[from] easy::borrow::repo::Error),
}
}
}

pub mod write {
use crate::easy;

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
OdbWrite(#[from] git_odb::loose::write::Error),
#[error("BUG: The repository could not be borrowed")]
BorrowRepo(#[from] easy::borrow::repo::Error),
}
}
145 changes: 18 additions & 127 deletions git-repository/src/easy/object/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![allow(missing_docs)]
//!
use std::{cell::Ref, convert::TryInto};

use git_hash::ObjectId;
Expand All @@ -10,10 +10,15 @@ use crate::{
easy::{Object, ObjectRef, TreeRef},
};

mod errors;
mod impls;
mod tree;
pub use errors::{find, write};

pub mod peel;

impl Object {
/// Infuse this owned object with an [`easy::Access`].
pub fn attach<A>(self, access: &A) -> easy::borrow::state::Result<ObjectRef<'_, A>>
where
A: easy::Access + Sized,
Expand Down Expand Up @@ -45,64 +50,22 @@ where
})
}

/// Transform this object into a tree, or panic if it is none.
pub fn into_tree(self) -> TreeRef<'repo, A> {
match self.try_into() {
Ok(tree) => tree,
Err(this) => panic!("Tried to use {} as tree, but was {}", this.id, this.kind),
}
}

/// Transform this object into a tree, or return it as part of the `Err` if it is no tree.
pub fn try_into_tree(self) -> Result<TreeRef<'repo, A>, Self> {
self.try_into()
}
}

pub mod find {

use crate::easy;

pub(crate) type OdbError = git_odb::compound::find::Error;

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
Find(#[from] OdbError),
#[error("BUG: Part of interior state could not be borrowed.")]
BorrowState(#[from] easy::borrow::state::Error),
#[error("BUG: The repository could not be borrowed")]
BorrowRepo(#[from] easy::borrow::repo::Error),
}

pub mod existing {
use crate::easy;

pub(crate) type OdbError = git_odb::pack::find::existing::Error<git_odb::compound::find::Error>;

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
FindExisting(#[from] OdbError),
#[error("BUG: Part of interior state could not be borrowed.")]
BorrowState(#[from] easy::borrow::state::Error),
#[error("BUG: The repository could not be borrowed")]
BorrowRepo(#[from] easy::borrow::repo::Error),
}
}
}

pub mod write {
use crate::easy;

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
OdbWrite(#[from] git_odb::loose::write::Error),
#[error("BUG: The repository could not be borrowed")]
BorrowRepo(#[from] easy::borrow::repo::Error),
}
}

impl<'repo, A> ObjectRef<'repo, A> {
/// Create an owned instance of this object, copying our data in the process.
pub fn to_owned(&self) -> Object {
Object {
id: self.id,
Expand All @@ -111,6 +74,7 @@ impl<'repo, A> ObjectRef<'repo, A> {
}
}

/// Turn this instance into an owned one, copying our data in the process.
pub fn into_owned(self) -> Object {
Object {
id: self.id,
Expand All @@ -119,6 +83,9 @@ impl<'repo, A> ObjectRef<'repo, A> {
}
}

/// Sever the connection to `Easy` and turn this instance into a standalone object.
///
/// Note that the data buffer will be copied in the process.
pub fn detach(self) -> Object {
self.into()
}
Expand All @@ -128,98 +95,22 @@ impl<'repo, A> ObjectRef<'repo, A>
where
A: easy::Access + Sized,
{
/// As [`to_commit_iter()`][ObjectRef::to_commit_iter()] but panics if this is not a commit
/// Obtain a an iterator over commit tokens like in [`to_commit_iter()`][ObjectRef::to_commit_iter()], but panic if this is not a commit.
pub fn commit_iter(&self) -> CommitRefIter<'_> {
git_odb::data::Object::new(self.kind, &self.data)
.try_into_commit_iter()
.expect("BUG: This object must be a commit")
}

/// Obtain a commit token iterator from the data in this instance, if it is a commit.
// TODO: rename to try_*
pub fn to_commit_iter(&self) -> Option<CommitRefIter<'_>> {
git_odb::data::Object::new(self.kind, &self.data).try_into_commit_iter()
}

// TODO: rename to try_*
/// Obtain a tag token iterator from the data in this instance, if it is a tag.
pub fn to_tag_iter(&self) -> Option<TagRefIter<'_>> {
git_odb::data::Object::new(self.kind, &self.data).try_into_tag_iter()
}
}

pub mod peel {
use crate::{
easy,
easy::{
ext::ObjectAccessExt,
object,
object::{peel, Kind},
ObjectRef,
},
};

pub mod to_kind {
mod error {

use crate::easy::object;

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
FindExistingObject(#[from] object::find::existing::Error),
#[error("Last encountered object kind was {} while trying to peel to {}", .actual, .expected)]
NotFound {
actual: object::Kind,
expected: object::Kind,
},
}
}
pub use error::Error;
}

impl<'repo, A> ObjectRef<'repo, A>
where
A: easy::Access + Sized,
{
// TODO: tests
pub fn peel_to_kind(mut self, kind: Kind) -> Result<Self, peel::to_kind::Error> {
loop {
match self.kind {
any_kind if kind == any_kind => {
return Ok(self);
}
Kind::Commit => {
let tree_id = self.to_commit_iter().expect("commit").tree_id().expect("valid commit");
let access = self.access;
drop(self);
self = access.find_object(tree_id)?;
}
Kind::Tag => {
let target_id = self.to_tag_iter().expect("tag").target_id().expect("valid tag");
let access = self.access;
drop(self);
self = access.find_object(target_id)?;
}
Kind::Tree | Kind::Blob => {
return Err(peel::to_kind::Error::NotFound {
actual: self.kind,
expected: kind,
})
}
}
}
}

// TODO: tests
pub fn peel_to_end(mut self) -> Result<Self, object::find::existing::Error> {
loop {
match self.kind {
Kind::Commit | Kind::Tree | Kind::Blob => break Ok(self),
Kind::Tag => {
let target_id = self.to_tag_iter().expect("tag").target_id().expect("valid tag");
let access = self.access;
drop(self);
self = access.find_object(target_id)?;
}
}
}
}
}
}
78 changes: 78 additions & 0 deletions git-repository/src/easy/object/peel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#![allow(missing_docs)]
use crate::{
easy,
easy::{
ext::ObjectAccessExt,
object,
object::{peel, Kind},
ObjectRef,
},
};

pub mod to_kind {
mod error {

use crate::easy::object;

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
FindExistingObject(#[from] object::find::existing::Error),
#[error("Last encountered object kind was {} while trying to peel to {}", .actual, .expected)]
NotFound {
actual: object::Kind,
expected: object::Kind,
},
}
}
pub use error::Error;
}

impl<'repo, A> ObjectRef<'repo, A>
where
A: easy::Access + Sized,
{
// TODO: tests
pub fn peel_to_kind(mut self, kind: Kind) -> Result<Self, peel::to_kind::Error> {
loop {
match self.kind {
any_kind if kind == any_kind => {
return Ok(self);
}
Kind::Commit => {
let tree_id = self.to_commit_iter().expect("commit").tree_id().expect("valid commit");
let access = self.access;
drop(self);
self = access.find_object(tree_id)?;
}
Kind::Tag => {
let target_id = self.to_tag_iter().expect("tag").target_id().expect("valid tag");
let access = self.access;
drop(self);
self = access.find_object(target_id)?;
}
Kind::Tree | Kind::Blob => {
return Err(peel::to_kind::Error::NotFound {
actual: self.kind,
expected: kind,
})
}
}
}
}

// TODO: tests
pub fn peel_to_end(mut self) -> Result<Self, object::find::existing::Error> {
loop {
match self.kind {
Kind::Commit | Kind::Tree | Kind::Blob => break Ok(self),
Kind::Tag => {
let target_id = self.to_tag_iter().expect("tag").target_id().expect("valid tag");
let access = self.access;
drop(self);
self = access.find_object(target_id)?;
}
}
}
}
}
8 changes: 8 additions & 0 deletions git-repository/src/easy/object/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ where
A: easy::Access + Sized,
{
// TODO: move implementation to git-object, tests.
/// Follow a sequence of `path` components starting from this instance, and look them up one by one until the last component
/// is looked up and its tree entry is returned.
///
/// # Performance Notes
///
/// Searching tree entries is currently done in sequence, which allows to the search to be allocation free. It would be possible
/// to re-use a vector and use a binary search instead, which might be able to improve performance over all.
/// However, a benchmark should be created first to have some data and see which trade-off to choose here.
pub fn lookup_path<I, P>(mut self, path: I) -> Result<Option<git_object::tree::Entry>, find::existing::Error>
where
I: IntoIterator<Item = P>,
Expand Down

0 comments on commit f582439

Please sign in to comment.