radicle-heartwood-lfs/radicle-cob/src/object/collaboration.rs

96 lines
2.5 KiB
Rust

// Copyright © 2022 The Radicle Link Contributors
//
// This file is part of radicle-link, distributed under the GPLv3 with Radicle
// Linking Exception. For full terms see the included LICENSE file.
use std::collections::BTreeSet;
use git_ext::Oid;
use crate::{change, identity::Identity, Contents, History, ObjectId, TypeName};
pub mod error;
mod create;
pub use create::{create, Create};
mod get;
pub use get::get;
pub mod info;
mod list;
pub use list::list;
mod update;
pub use update::{update, Update};
/// A collaborative object
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CollaborativeObject {
/// The typename of this object
pub(crate) typename: TypeName,
/// The CRDT history we know about for this object
pub(crate) history: History,
/// The id of the object
pub(crate) id: ObjectId,
}
impl CollaborativeObject {
pub fn history(&self) -> &History {
&self.history
}
pub fn id(&self) -> &ObjectId {
&self.id
}
pub fn typename(&self) -> &TypeName {
&self.typename
}
fn tips(&self) -> BTreeSet<Oid> {
self.history.tips().into_iter().map(Oid::from).collect()
}
}
/// Takes a `refname` and performs a best attempt to extract out the
/// [`TypeName`] and [`ObjectId`] from it.
///
/// This assumes that the `refname` is in a
/// [`git_ref_format::Qualified`] format. If it has any
/// `refs/namespaces`, they will be stripped to access the underlying
/// [`git_ref_format::Qualified`] format.
///
/// In the [`git_ref_format::Qualified`] format it assumes that the
/// reference name is of the form:
///
/// `refs/<category>/<typename>/<object_id>[/<rest>*]`
///
/// Note that their may be more components to the path after the
/// [`ObjectId`] but they are ignored.
///
/// Also note that this will return `None` if:
///
/// * The `refname` is not [`git_ref_format::Qualified`]
/// * The parsing of the [`ObjectId`] fails
/// * The parsing of the [`TypeName`] fails
pub fn parse_refstr<R>(name: &R) -> Option<(TypeName, ObjectId)>
where
R: AsRef<git_ref_format::RefStr>,
{
use git_ref_format::Qualified;
let name = name.as_ref();
let refs_cobs = match name.to_namespaced() {
None => Qualified::from_refstr(name)?,
Some(ns) => ns.strip_namespace_recursive(),
};
let (_refs, _cobs, typename, mut object_id) = refs_cobs.non_empty_components();
let object = object_id
.next()
.and_then(|oid| oid.parse::<ObjectId>().ok())?;
let name = typename.parse::<TypeName>().ok()?;
Some((name, object))
}