node: Use git oid for project id
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This commit is contained in:
parent
84119b0265
commit
6353d6115b
|
|
@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
|
|||
use thiserror::Error;
|
||||
|
||||
use crate::crypto::{self, Verified};
|
||||
use crate::hash;
|
||||
use crate::git;
|
||||
use crate::serde_ext;
|
||||
use crate::storage::Remotes;
|
||||
|
||||
|
|
@ -17,14 +17,14 @@ pub use doc::{Delegate, Doc};
|
|||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum IdError {
|
||||
#[error("invalid digest: {0}")]
|
||||
InvalidDigest(#[from] hash::DecodeError),
|
||||
#[error("invalid git object id: {0}")]
|
||||
InvalidOid(#[from] git2::Error),
|
||||
#[error(transparent)]
|
||||
Multibase(#[from] multibase::Error),
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Id(hash::Digest);
|
||||
pub struct Id(git::Oid);
|
||||
|
||||
impl fmt::Display for Id {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
|
@ -40,12 +40,12 @@ impl fmt::Debug for Id {
|
|||
|
||||
impl Id {
|
||||
pub fn to_human(&self) -> String {
|
||||
multibase::encode(multibase::Base::Base58Btc, &self.0.as_ref())
|
||||
multibase::encode(multibase::Base::Base58Btc, self.0.as_bytes())
|
||||
}
|
||||
|
||||
pub fn from_human(s: &str) -> Result<Self, IdError> {
|
||||
let (_, bytes) = multibase::decode(s)?;
|
||||
let array: hash::Digest = bytes.as_slice().try_into()?;
|
||||
let array: git::Oid = bytes.as_slice().try_into()?;
|
||||
|
||||
Ok(Self(array))
|
||||
}
|
||||
|
|
@ -68,14 +68,20 @@ impl TryFrom<OsString> for Id {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<hash::Digest> for Id {
|
||||
fn from(digest: hash::Digest) -> Self {
|
||||
Self(digest)
|
||||
impl From<git::Oid> for Id {
|
||||
fn from(oid: git::Oid) -> Self {
|
||||
Self(oid)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<git2::Oid> for Id {
|
||||
fn from(oid: git2::Oid) -> Self {
|
||||
Self(oid.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Id {
|
||||
type Target = hash::Digest;
|
||||
type Target = git::Oid;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ use thiserror::Error;
|
|||
use crate::crypto;
|
||||
use crate::crypto::{Signature, Unverified, Verified};
|
||||
use crate::git;
|
||||
use crate::hash;
|
||||
use crate::identity::{Did, Id};
|
||||
use crate::storage::git::trailers;
|
||||
use crate::storage::{BranchName, ReadRepository, RemoteId};
|
||||
|
|
@ -79,22 +78,17 @@ pub struct Doc<V> {
|
|||
}
|
||||
|
||||
impl Doc<Verified> {
|
||||
pub fn write<W: io::Write>(&self, mut writer: W) -> Result<Id, Error> {
|
||||
pub fn encode(&self) -> Result<(Id, Vec<u8>), Error> {
|
||||
let mut buf = Vec::new();
|
||||
let mut ser =
|
||||
let mut serializer =
|
||||
serde_json::Serializer::with_formatter(&mut buf, olpc_cjson::CanonicalFormatter::new());
|
||||
|
||||
self.serialize(&mut ser)?;
|
||||
self.serialize(&mut serializer)?;
|
||||
|
||||
let digest = hash::Digest::new(&buf);
|
||||
let id = Id::from(digest);
|
||||
let oid = git2::Oid::hash_object(git2::ObjectType::Blob, &buf)?;
|
||||
let id = Id::from(oid);
|
||||
|
||||
// TODO: Currently, we serialize the document in canonical JSON. This isn't strictly
|
||||
// necessary, as we could use CJSON just to get the hash, but then write a prettified
|
||||
// version to disk to make it easier for users to edit.
|
||||
writer.write_all(&buf)?;
|
||||
|
||||
Ok(id)
|
||||
Ok((id, buf))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -367,9 +361,7 @@ mod test {
|
|||
|
||||
#[quickcheck]
|
||||
fn prop_encode_decode(doc: Doc<Verified>) {
|
||||
let mut bytes = Vec::new();
|
||||
|
||||
doc.write(&mut bytes).unwrap();
|
||||
let (_, bytes) = doc.encode().unwrap();
|
||||
assert_eq!(Doc::from_json(&bytes).unwrap().verified().unwrap(), doc);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,17 +47,15 @@ pub fn init<'r, G: Signer, S: storage::WriteStorage<'r>>(
|
|||
name: String::from("anonymous"),
|
||||
id: identity::Did::from(*pk),
|
||||
};
|
||||
let doc = identity::Doc::initial(
|
||||
let (id, doc) = identity::Doc::initial(
|
||||
name.to_owned(),
|
||||
description.to_owned(),
|
||||
default_branch.clone(),
|
||||
delegate,
|
||||
)
|
||||
.verified()?;
|
||||
.verified()?
|
||||
.encode()?;
|
||||
|
||||
let filename = *identity::doc::PATH;
|
||||
let mut doc_bytes = Vec::new();
|
||||
let id = doc.write(&mut doc_bytes)?;
|
||||
let project = storage.repository(&id)?;
|
||||
|
||||
{
|
||||
|
|
@ -70,11 +68,14 @@ pub fn init<'r, G: Signer, S: storage::WriteStorage<'r>>(
|
|||
// git fetch rad
|
||||
// git checkout -b radicle/id remotes/rad/radicle/id
|
||||
//
|
||||
let filename = *identity::doc::PATH;
|
||||
let repo = project.raw();
|
||||
let tree = {
|
||||
let id_blob = repo.blob(&doc_bytes)?;
|
||||
let doc_blob = repo.blob(&doc)?;
|
||||
let mut builder = repo.treebuilder(None)?;
|
||||
builder.insert(filename, id_blob, 0o100_644)?;
|
||||
builder.insert(filename, doc_blob, 0o100_644)?;
|
||||
|
||||
assert_eq!(git::Oid::from(doc_blob), *id);
|
||||
|
||||
let tree_id = builder.write()?;
|
||||
repo.find_tree(tree_id)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,10 @@ impl<const N: usize> ByteArray<N> {
|
|||
pub fn into_inner(self) -> [u8; N] {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
self.0.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Arbitrary for ByteArray<N> {
|
||||
|
|
@ -174,9 +178,8 @@ impl Arbitrary for MockStorage {
|
|||
|
||||
impl Arbitrary for Project {
|
||||
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
|
||||
let mut buf = Vec::new();
|
||||
let doc = Doc::<Verified>::arbitrary(g);
|
||||
let id = doc.write(&mut buf).unwrap();
|
||||
let (id, _) = doc.encode().unwrap();
|
||||
let remotes = storage::Remotes::arbitrary(g);
|
||||
let path = PathBuf::arbitrary(g);
|
||||
|
||||
|
|
@ -311,8 +314,10 @@ impl Arbitrary for MockSigner {
|
|||
|
||||
impl Arbitrary for Id {
|
||||
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
|
||||
let digest = hash::Digest::arbitrary(g);
|
||||
Id::from(digest)
|
||||
let bytes = ByteArray::<20>::arbitrary(g);
|
||||
let oid = git::Oid::try_from(bytes.as_slice()).unwrap();
|
||||
|
||||
Id::from(oid)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -375,9 +375,9 @@ impl Decode for git::Url {
|
|||
|
||||
impl Decode for Id {
|
||||
fn decode<R: io::Read + ?Sized>(reader: &mut R) -> Result<Self, Error> {
|
||||
let digest: Digest = Decode::decode(reader)?;
|
||||
let oid: git::Oid = Decode::decode(reader)?;
|
||||
|
||||
Ok(Self::from(digest))
|
||||
Ok(Self::from(oid))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue