From a985e067a51a9042282c6129a97375e5ecaaf7cc Mon Sep 17 00:00:00 2001 From: Fintan Halpenny Date: Wed, 16 Nov 2022 14:05:13 +0000 Subject: [PATCH] Add TypeName & ObjectId parser Added the `parse_refname` function for parsing a reference into its `TypeName` and `ObjectId`, if possible. This replaces the `cob_suffix` function in `radicle`. This change also fixes the `FromStr` instance of `ObjectId` to use `from_str` instead of `TryFrom` for bytes. Signed-off-by: Fintan Halpenny X-Clacks-Overhead: GNU Terry Pratchett --- radicle-cob/src/object.rs | 6 ++-- radicle-cob/src/object/collaboration.rs | 40 +++++++++++++++++++++++++ radicle/src/git.rs | 14 --------- radicle/src/storage/git.rs | 2 +- 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/radicle-cob/src/object.rs b/radicle-cob/src/object.rs index dfded07a..ccd35ccc 100644 --- a/radicle-cob/src/object.rs +++ b/radicle-cob/src/object.rs @@ -11,7 +11,9 @@ use serde::{Deserialize, Serialize}; use thiserror::Error; pub mod collaboration; -pub use collaboration::{create, get, info, list, update, CollaborativeObject, Create, Update}; +pub use collaboration::{ + create, get, info, list, parse_refstr, update, CollaborativeObject, Create, Update, +}; pub mod storage; pub use storage::{Commit, Objects, Reference, Storage}; @@ -30,7 +32,7 @@ impl FromStr for ObjectId { type Err = ParseObjectId; fn from_str(s: &str) -> Result { - let oid = Oid::try_from(s.as_bytes())?; + let oid = Oid::from_str(s)?; Ok(ObjectId(oid)) } } diff --git a/radicle-cob/src/object/collaboration.rs b/radicle-cob/src/object/collaboration.rs index 8b46538d..430734ec 100644 --- a/radicle-cob/src/object/collaboration.rs +++ b/radicle-cob/src/object/collaboration.rs @@ -53,3 +53,43 @@ impl CollaborativeObject { 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///[/*]` +/// +/// 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(name: &R) -> Option<(TypeName, ObjectId)> +where + R: AsRef, +{ + 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::().ok())?; + let name = typename.parse::().ok()?; + Some((name, object)) +} diff --git a/radicle/src/git.rs b/radicle/src/git.rs index 7e0ec040..6d56989f 100644 --- a/radicle/src/git.rs +++ b/radicle/src/git.rs @@ -141,20 +141,6 @@ pub mod refs { .join(Component::from(typename)) .join(Component::from(object_id)) } - - pub fn cob_suffix(cob: &R) -> Option<(cob::TypeName, cob::ObjectId)> - where - R: AsRef, - { - let cob = cob.as_ref().to_namespaced()?; - let cob = cob.strip_namespace(); - let (_refs, _cobs, typename, mut object_id) = cob.non_empty_components(); - let object_id = object_id - .next() - .and_then(|oid| oid.parse::().ok())?; - let typename = typename.parse::().ok()?; - Some((typename, object_id.into())) - } } pub mod workdir { diff --git a/radicle/src/storage/git.rs b/radicle/src/storage/git.rs index e53d60e4..f3f9a1f3 100644 --- a/radicle/src/storage/git.rs +++ b/radicle/src/storage/git.rs @@ -736,7 +736,7 @@ impl cob::object::Storage for Repository { let reference = reference.ok()?; match RefStr::try_from_str(reference.name()?) { Ok(name) => { - let (ty, object_id) = git::refs::storage::cob_suffix(&name)?; + let (ty, object_id) = cob::object::parse_refstr(&name)?; if ty == *typename { Some( cob::object::Reference::try_from(reference)