From d3dd777d95797aa345e267f6ae1a23b6a66c9f83 Mon Sep 17 00:00:00 2001 From: Fintan Halpenny Date: Wed, 22 Nov 2023 14:53:09 +0000 Subject: [PATCH] surf: expose BlobRef The current `blob` function is limited to always associating a Blob with a Commit. Expose `BlobRef` through a `blob_ref` method, and add useful methods and serialization to it. Signed-off-by: Fintan Halpenny X-Clacks-Overhead: GNU Terry Pratchett --- radicle-surf/src/blob.rs | 31 ++++++++++++++++++++++++++++++- radicle-surf/src/repo.rs | 6 ++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/radicle-surf/src/blob.rs b/radicle-surf/src/blob.rs index 2a9ba83..2326e74 100644 --- a/radicle-surf/src/blob.rs +++ b/radicle-surf/src/blob.rs @@ -95,7 +95,13 @@ impl<'a> Blob> { /// Represents a blob with borrowed content bytes. pub struct BlobRef<'a> { - inner: git2::Blob<'a>, + pub(crate) inner: git2::Blob<'a>, +} + +impl<'a> BlobRef<'a> { + pub fn id(&self) -> Oid { + self.inner.id().into() + } } impl AsRef<[u8]> for BlobRef<'_> { @@ -138,3 +144,26 @@ where state.end() } } + +#[cfg(feature = "serde")] +impl<'a> Serialize for BlobRef<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + const FIELDS: usize = 3; + let mut state = serializer.serialize_struct("BlobRef", FIELDS)?; + state.serialize_field("id", &self.id())?; + state.serialize_field("binary", &self.inner.is_binary())?; + + let bytes = self.as_ref(); + match std::str::from_utf8(bytes) { + Ok(s) => state.serialize_field("content", s)?, + Err(_) => { + let encoded = base64::encode(bytes); + state.serialize_field("content", &encoded)? + }, + }; + state.end() + } +} diff --git a/radicle-surf/src/repo.rs b/radicle-surf/src/repo.rs index 9d75350..7d98f6f 100644 --- a/radicle-surf/src/repo.rs +++ b/radicle-surf/src/repo.rs @@ -301,6 +301,12 @@ impl Repository { Ok(Blob::>::new(file.id(), git2_blob, last_commit)) } + pub fn blob_ref(&self, oid: Oid) -> Result, Error> { + Ok(BlobRef { + inner: self.find_blob(oid)?, + }) + } + /// Returns the last commit, if exists, for a `path` in the history of /// `rev`. pub fn last_commit(&self, path: &P, rev: C) -> Result, Error>