diff --git a/Cargo.lock b/Cargo.lock index d1e0171..71ff877 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -260,7 +260,7 @@ dependencies = [ [[package]] name = "git-ref-format" -version = "0.3.0" +version = "0.3.1" dependencies = [ "git-ref-format-core", "git-ref-format-macro", @@ -268,7 +268,7 @@ dependencies = [ [[package]] name = "git-ref-format-core" -version = "0.3.0" +version = "0.3.1" dependencies = [ "bstr", "minicbor", @@ -279,7 +279,7 @@ dependencies = [ [[package]] name = "git-ref-format-macro" -version = "0.3.0" +version = "0.3.1" dependencies = [ "git-ref-format-core", "proc-macro-error", @@ -641,7 +641,7 @@ dependencies = [ [[package]] name = "radicle-git-ext" -version = "0.8.0" +version = "0.8.1" dependencies = [ "git-ref-format", "git2", @@ -671,7 +671,7 @@ version = "0.1.0" [[package]] name = "radicle-surf" -version = "0.22.0" +version = "0.22.1" dependencies = [ "anyhow", "base64", diff --git a/radicle-git-ext/Cargo.toml b/radicle-git-ext/Cargo.toml index 241c80c..612d139 100644 --- a/radicle-git-ext/Cargo.toml +++ b/radicle-git-ext/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "radicle-git-ext" -version = "0.8.0" +version = "0.8.1" authors = [ "Alexis Sellier ", "Kim Altintop ", @@ -31,7 +31,7 @@ default-features = false features = ["vendored-libgit2"] [dependencies.git-ref-format] -version = "0.3.0" +version = "0.3.1" path = "./git-ref-format" features = ["macro", "serde"] diff --git a/radicle-git-ext/git-ref-format/Cargo.toml b/radicle-git-ext/git-ref-format/Cargo.toml index 34dca3b..83a7b76 100644 --- a/radicle-git-ext/git-ref-format/Cargo.toml +++ b/radicle-git-ext/git-ref-format/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git-ref-format" -version = "0.3.0" +version = "0.3.1" authors = [ "Kim Altintop ", "Fintan Halpenny ", @@ -22,10 +22,10 @@ percent-encoding = ["git-ref-format-core/percent-encoding"] serde = ["git-ref-format-core/serde"] [dependencies.git-ref-format-core] -version = "0.3.0" +version = "0.3.1" path = "./core" [dependencies.git-ref-format-macro] -version = "0.3.0" +version = "0.3.1" path = "./macro" optional = true diff --git a/radicle-git-ext/git-ref-format/core/Cargo.toml b/radicle-git-ext/git-ref-format/core/Cargo.toml index c420cd2..29d4256 100644 --- a/radicle-git-ext/git-ref-format/core/Cargo.toml +++ b/radicle-git-ext/git-ref-format/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git-ref-format-core" -version = "0.3.0" +version = "0.3.1" authors = ["Kim Altintop "] edition = "2018" license = "GPL-3.0-or-later" diff --git a/radicle-git-ext/git-ref-format/core/src/refspec.rs b/radicle-git-ext/git-ref-format/core/src/refspec.rs index c2b1591..d47af01 100644 --- a/radicle-git-ext/git-ref-format/core/src/refspec.rs +++ b/radicle-git-ext/git-ref-format/core/src/refspec.rs @@ -13,7 +13,7 @@ use std::{ use thiserror::Error; -use crate::{check, lit, RefStr, RefString}; +use crate::{check, lit, Namespaced, Qualified, RefStr, RefString}; mod iter; pub use iter::{component, Component, Components, Iter}; @@ -430,6 +430,20 @@ impl AsRef for QualifiedPattern<'_> { } } +impl Display for QualifiedPattern<'_> { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + +impl<'a> From> for QualifiedPattern<'a> { + #[inline] + fn from(q: Qualified<'a>) -> Self { + Self(Cow::Owned(q.into_refstring().into())) + } +} + impl<'a> From> for Cow<'a, PatternStr> { #[inline] fn from(q: QualifiedPattern<'a>) -> Self { @@ -534,6 +548,13 @@ impl Borrow for NamespacedPattern<'_> { } } +impl<'a> From> for NamespacedPattern<'a> { + #[inline] + fn from(ns: Namespaced<'a>) -> Self { + NamespacedPattern(Cow::Owned(ns.to_ref_string().into())) + } +} + impl<'a> From> for QualifiedPattern<'a> { #[inline] fn from(ns: NamespacedPattern<'a>) -> Self { diff --git a/radicle-git-ext/git-ref-format/core/src/serde.rs b/radicle-git-ext/git-ref-format/core/src/serde.rs index 0d621d0..5bead98 100644 --- a/radicle-git-ext/git-ref-format/core/src/serde.rs +++ b/radicle-git-ext/git-ref-format/core/src/serde.rs @@ -5,10 +5,10 @@ use std::convert::TryFrom; -use ::serde::{de, Deserialize, Deserializer, Serialize, Serializer}; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use crate::{ - refspec::{PatternStr, PatternString}, + refspec::{NamespacedPattern, PatternStr, PatternString, QualifiedPattern}, Namespaced, Qualified, RefStr, RefString, }; @@ -145,3 +145,51 @@ impl Serialize for Namespaced<'_> { serializer.serialize_str(self.as_str()) } } + +impl<'de> Deserialize<'de> for QualifiedPattern<'_> { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).and_then(|s: String| { + let s = PatternString::try_from(s).map_err(de::Error::custom)?; + s.qualified() + .ok_or_else(|| de::Error::custom("not a qualified ref")) + .map(|q| q.into_owned()) + }) + } +} + +impl Serialize for QualifiedPattern<'_> { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> Deserialize<'de> for NamespacedPattern<'_> { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).and_then(|s: String| { + let s = PatternString::try_from(s).map_err(de::Error::custom)?; + s.to_namespaced() + .ok_or_else(|| de::Error::custom("not a qualified ref")) + .map(|q| q.into_owned()) + }) + } +} + +impl Serialize for NamespacedPattern<'_> { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(self.as_str()) + } +} diff --git a/radicle-git-ext/git-ref-format/macro/Cargo.toml b/radicle-git-ext/git-ref-format/macro/Cargo.toml index 034d68f..01312b1 100644 --- a/radicle-git-ext/git-ref-format/macro/Cargo.toml +++ b/radicle-git-ext/git-ref-format/macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git-ref-format-macro" -version = "0.3.0" +version = "0.3.1" authors = ["Kim Altintop "] edition = "2018" license = "GPL-3.0-or-later" @@ -18,5 +18,5 @@ quote = "1" syn = "2" [dependencies.git-ref-format-core] -version = "0.3.0" +version = "0.3.1" path = "../core" diff --git a/radicle-git-ext/git-ref-format/macro/src/lib.rs b/radicle-git-ext/git-ref-format/macro/src/lib.rs index e3ceaa3..4bf33ef 100644 --- a/radicle-git-ext/git-ref-format/macro/src/lib.rs +++ b/radicle-git-ext/git-ref-format/macro/src/lib.rs @@ -166,3 +166,35 @@ pub fn pattern(input: TokenStream) -> TokenStream { } } } + +/// Create a [`git_ref_format_core::refspec::QualifiedPattern`] from a string +/// literal. +/// +/// The string is validated at compile time, and an unsafe conversion is +/// emitted. +#[proc_macro_error] +#[proc_macro] +pub fn qualified_pattern(input: TokenStream) -> TokenStream { + let lit = parse_macro_input!(input as LitStr); + let val = lit.value(); + + let parsed: Result<&PatternStr, Error> = val.as_str().try_into(); + match parsed { + Ok(safe) => { + let safe: &str = safe.as_str(); + let expand = quote! { + unsafe { + use ::std::mem::transmute; + use ::radicle_git_ext::ref_format::refspec::QualifiedPattern; + + transmute::<_, QualifiedPattern>(#safe.to_owned()) + } + }; + TokenStream::from(expand) + } + + Err(e) => { + abort!(lit.span(), "invalid refspec pattern literal: {}", e); + } + } +} diff --git a/radicle-git-ext/git-ref-format/src/lib.rs b/radicle-git-ext/git-ref-format/src/lib.rs index 4ff0510..98f6d4e 100644 --- a/radicle-git-ext/git-ref-format/src/lib.rs +++ b/radicle-git-ext/git-ref-format/src/lib.rs @@ -145,4 +145,7 @@ pub mod refspec { #[cfg(any(feature = "macro", feature = "git-ref-format-macro"))] pub use git_ref_format_macro::pattern; + + #[cfg(any(feature = "macro", feature = "git-ref-format-macro"))] + pub use git_ref_format_macro::qualified_pattern; } diff --git a/radicle-surf/Cargo.toml b/radicle-surf/Cargo.toml index 0ad006e..3060d87 100644 --- a/radicle-surf/Cargo.toml +++ b/radicle-surf/Cargo.toml @@ -2,7 +2,7 @@ name = "radicle-surf" description = "A code surfing library for Git repositories" readme = "README.md" -version = "0.22.0" +version = "0.22.1" authors = ["The Radicle Team "] edition = "2021" homepage = "https://github.com/radicle-dev/radicle-git/blob/main/radicle-surf/README.md" @@ -41,7 +41,7 @@ default-features = false features = ["vendored-libgit2"] [dependencies.radicle-git-ext] -version = "0.8.0" +version = "0.8.1" path = "../radicle-git-ext" features = ["serde"]