radicle-cob: Reference conversion from git2::Reference
It will be common for Reference to be converted from a `git2::Reference` when one is implementing `object::Storage`. Provide a `TryFrom` implementation between `git2::Reference` and `Reference`. Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com> X-Clacks-Overhead: GNU Terry Pratchett
This commit is contained in:
parent
6b303bdc97
commit
4112b0fdc5
|
|
@ -83,3 +83,49 @@ pub trait Storage {
|
||||||
change: &Change,
|
change: &Change,
|
||||||
) -> Result<(), Self::UpdateError>;
|
) -> Result<(), Self::UpdateError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod convert {
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
use git_ref_format::RefString;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
use super::{Commit, Reference};
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("the reference '{name}' does not point to a commit object")]
|
||||||
|
NotCommit {
|
||||||
|
name: RefString,
|
||||||
|
#[source]
|
||||||
|
err: git2::Error,
|
||||||
|
},
|
||||||
|
#[error(transparent)]
|
||||||
|
Ref(#[from] git_ref_format::Error),
|
||||||
|
#[error(transparent)]
|
||||||
|
Utf8(#[from] str::Utf8Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<git2::Reference<'a>> for Reference {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn try_from(value: git2::Reference<'a>) -> Result<Self, Self::Error> {
|
||||||
|
let name = RefString::try_from(str::from_utf8(value.name_bytes())?)?;
|
||||||
|
let target = Commit::from(value.peel_to_commit().map_err(|err| Error::NotCommit {
|
||||||
|
name: name.clone(),
|
||||||
|
err,
|
||||||
|
})?);
|
||||||
|
Ok(Self { name, target })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<git2::Commit<'a>> for Commit {
|
||||||
|
fn from(commit: git2::Commit<'a>) -> Self {
|
||||||
|
let parents = commit.parents().map(Commit::from).collect();
|
||||||
|
Commit {
|
||||||
|
id: commit.id().into(),
|
||||||
|
parents,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
use std::{collections::HashMap, convert::TryFrom as _};
|
use std::{collections::HashMap, convert::TryFrom as _};
|
||||||
|
|
||||||
use git_ref_format::RefString;
|
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
change,
|
change,
|
||||||
object::{self, Commit, Reference},
|
object::{self, Reference},
|
||||||
ObjectId, Store,
|
ObjectId, Store,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -14,6 +13,8 @@ use super::identity::{RemoteProject, Urn};
|
||||||
pub mod error {
|
pub mod error {
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
use crate::object::storage::convert;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum Identity {
|
pub enum Identity {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
|
@ -28,6 +29,8 @@ pub mod error {
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum Objects {
|
pub enum Objects {
|
||||||
|
#[error(transparent)]
|
||||||
|
Conversion(#[from] convert::Error),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Git(#[from] git2::Error),
|
Git(#[from] git2::Error),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
|
@ -122,12 +125,15 @@ impl object::Storage for Storage {
|
||||||
);
|
);
|
||||||
let local = {
|
let local = {
|
||||||
let r = self.raw.find_reference(&name)?;
|
let r = self.raw.find_reference(&name)?;
|
||||||
Some(resolve_reference(r)?)
|
Some(Reference::try_from(r)?)
|
||||||
};
|
};
|
||||||
let remotes = self
|
let remotes = self
|
||||||
.raw
|
.raw
|
||||||
.references_glob(&glob)?
|
.references_glob(&glob)?
|
||||||
.map(|r| r.map_err(error::Objects::from).and_then(resolve_reference))
|
.map(|r| {
|
||||||
|
r.map_err(error::Objects::from)
|
||||||
|
.and_then(|r| Reference::try_from(r).map_err(error::Objects::from))
|
||||||
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
Ok(object::Objects { local, remotes })
|
Ok(object::Objects { local, remotes })
|
||||||
}
|
}
|
||||||
|
|
@ -150,7 +156,7 @@ impl object::Storage for Storage {
|
||||||
objects.insert(
|
objects.insert(
|
||||||
oid,
|
oid,
|
||||||
object::Objects {
|
object::Objects {
|
||||||
local: Some(resolve_reference(r)?),
|
local: Some(Reference::try_from(r)?),
|
||||||
remotes: Vec::new(),
|
remotes: Vec::new(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
@ -177,23 +183,3 @@ impl object::Storage for Storage {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_reference(r: git2::Reference) -> Result<Reference, error::Objects> {
|
|
||||||
let commit = r.peel_to_commit()?;
|
|
||||||
let target = resolve_parents(commit)?;
|
|
||||||
Ok(Reference {
|
|
||||||
name: RefString::try_from(r.name().unwrap().to_owned())?,
|
|
||||||
target,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_parents(commit: git2::Commit) -> Result<Commit, git2::Error> {
|
|
||||||
let parents = commit
|
|
||||||
.parents()
|
|
||||||
.map(resolve_parents)
|
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
|
||||||
Ok(Commit {
|
|
||||||
id: commit.id().into(),
|
|
||||||
parents,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue