git-ref-format: Integrate with workspace

Instead of depending on `git-ref-format-core`, the
`radicle-git-ref-format` crate succeeds it.
This commit is contained in:
Lorenz Leutgeb
2026-07-24 16:31:30 +02:00
parent 8731d01bca
commit ac607c8cad
16 changed files with 89 additions and 81 deletions
Generated
+6 -14
View File
@@ -1206,17 +1206,6 @@ version = "0.32.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"
[[package]]
name = "git-ref-format-core"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1955ef3abddd586f24c834d28f959d610157ab5cb71f2200911932a0018d0364"
dependencies = [
"bstr",
"serde",
"thiserror 1.0.69",
]
[[package]]
name = "git2"
version = "0.21.0"
@@ -2911,7 +2900,6 @@ name = "radicle-cob"
version = "0.21.0"
dependencies = [
"fastrand",
"git-ref-format-core",
"git2",
"log",
"nonempty 0.9.0",
@@ -2954,10 +2942,10 @@ dependencies = [
"curve25519-dalek",
"cyphernet",
"ed25519-dalek",
"git-ref-format-core",
"multibase",
"qcheck",
"qcheck-macros",
"radicle-git-ref-format",
"schemars",
"serde",
"sqlite",
@@ -3006,7 +2994,11 @@ dependencies = [
name = "radicle-git-ref-format"
version = "0.1.0"
dependencies = [
"git-ref-format-core",
"bstr",
"minicbor",
"percent-encoding",
"serde",
"thiserror 2.0.18",
]
[[package]]
-3
View File
@@ -76,9 +76,6 @@ winpipe = "0.1.1"
winsplit = "0.1.0"
zeroize = { version = "1.5.7", default-features = false }
# Crates from the "radicle-git" workspace.
git-ref-format-core = { version = "0.6.0", default-features = false }
[workspace.lints.clippy]
fallible_impl_from = "deny"
fn_params_excessive_bools = "deny"
+2 -2
View File
@@ -18,7 +18,7 @@ test = []
[dependencies]
fastrand = { workspace = true }
git-ref-format-core = { workspace = true }
radicle-git-ref-format = { workspace = true }
git2 = { workspace = true, optional = true }
log = { workspace = true }
nonempty = { workspace = true, features = ["serialize"] }
@@ -34,7 +34,7 @@ thiserror = { workspace = true, default-features = true }
fastrand = { workspace = true }
qcheck = { workspace = true }
qcheck-macros = { workspace = true }
radicle-crypto = { workspace = true, features = ["test", "git-ref-format-core"] }
radicle-crypto = { workspace = true, features = ["test", "radicle-git-ref-format"] }
radicle-git-ref-format = { workspace = true, features = ["macro"] }
radicle-oid = { workspace = true, features = ["qcheck"] }
tempfile = { workspace = true }
+1 -1
View File
@@ -59,10 +59,10 @@ extern crate qcheck;
#[macro_use(quickcheck)]
extern crate qcheck_macros;
extern crate git_ref_format_core as fmt;
extern crate radicle_crypto as crypto;
extern crate radicle_dag as dag;
extern crate radicle_git_metadata as metadata;
extern crate radicle_git_ref_format as fmt;
extern crate radicle_oid as oid;
mod backend;
+1 -1
View File
@@ -24,7 +24,7 @@ test = ["alloc", "qcheck"]
[dependencies]
cyphernet = { workspace = true, features = ["ed25519"], optional = true }
git-ref-format-core = { workspace = true, optional = true }
radicle-git-ref-format = { workspace = true, optional = true }
multibase = { workspace = true, default-features = false, optional = true }
qcheck = { workspace = true, optional = true }
schemars = { workspace = true, default-features = false, features = ["derive"], optional = true }
+11 -11
View File
@@ -225,25 +225,25 @@ impl PublicKey {
/// and `<public-key>` is encoded in human-readable format
/// ([`PublicKey::to_human`]).
#[cfg(all(
feature = "git-ref-format-core",
feature = "radicle-git-ref-format",
feature = "alloc",
feature = "multibase"
))]
pub fn to_namespace(&self) -> git_ref_format_core::RefString {
pub fn to_namespace(&self) -> radicle_git_ref_format::RefString {
use alloc::borrow::ToOwned as _;
use git_ref_format_core::name::{NAMESPACES, REFS};
use radicle_git_ref_format::name::{NAMESPACES, REFS};
REFS.to_owned().and(NAMESPACES).and(self.to_component())
}
/// Encode the public key a Git reference component, which is equivalent to
/// the human-readable format ([`PublicKey::to_human`]).
#[cfg(all(
feature = "git-ref-format-core",
feature = "radicle-git-ref-format",
feature = "alloc",
feature = "multibase"
))]
pub fn to_component(&self) -> git_ref_format_core::Component<'_> {
git_ref_format_core::Component::from(self)
pub fn to_component(&self) -> radicle_git_ref_format::Component<'_> {
radicle_git_ref_format::Component::from(self)
}
/// Decode a [`PublicKey`] from a namespaced Git reference, expected to be
@@ -254,12 +254,12 @@ impl PublicKey {
/// The `<public-key>` is decoded from the human-readable format
/// ([`PublicKey::to_human`]).
#[cfg(all(
feature = "git-ref-format-core",
feature = "radicle-git-ref-format",
feature = "alloc",
feature = "multibase"
))]
pub fn from_namespaced(
refstr: &git_ref_format_core::Namespaced,
refstr: &radicle_git_ref_format::Namespaced,
) -> Result<Self, PublicKeyError> {
use alloc::str::FromStr as _;
@@ -292,13 +292,13 @@ impl alloc::str::FromStr for PublicKey {
}
#[cfg(all(
feature = "git-ref-format-core",
feature = "radicle-git-ref-format",
feature = "alloc",
feature = "multibase"
))]
impl From<&PublicKey> for git_ref_format_core::Component<'_> {
impl From<&PublicKey> for radicle_git_ref_format::Component<'_> {
fn from(id: &PublicKey) -> Self {
use git_ref_format_core::{Component, RefString};
use radicle_git_ref_format::{Component, RefString};
let refstr =
RefString::try_from(id.to_string()).expect("encoded public keys are valid ref strings");
Component::from_refstr(refstr).expect("encoded public keys are valid refname components")
+6 -5
View File
@@ -1,9 +1,8 @@
[package]
name = "radicle-git-ref-format"
version = "0.1.0"
description = "Radicle re-exports and macros for `git-ref-format-core`"
description = "Everything you never knew you wanted for handling git ref names."
categories = ["no-std"]
keywords = ["radicle", "git", "refname", "ref", "references"]
edition.workspace = true
@@ -13,8 +12,10 @@ rust-version.workspace = true
[features]
macro = []
bstr = ["git-ref-format-core/bstr"]
serde = ["git-ref-format-core/serde"]
[dependencies]
git-ref-format-core.workspace = true
thiserror = { workspace = true }
serde = { workspace = true, optional = true, features = ["derive", "std"] }
bstr = { workspace = true, optional = true }
percent-encoding = { version = "2.1.0", optional = true }
minicbor = { version = "0.13", features = ["std"], optional = true }
+2 -3
View File
@@ -1,14 +1,13 @@
use std::convert::TryFrom;
use minicbor::{
decode,
Decode, Decoder, Encode, Encoder, decode,
encode::{self, Write},
Decode, Decoder, Encode, Encoder,
};
use crate::{
refspec::{PatternStr, PatternString},
Namespaced, Qualified, RefStr, RefString,
refspec::{PatternStr, PatternString},
};
impl<'de: 'a, 'a> Decode<'de> for &'a RefStr {
+13 -12
View File
@@ -5,9 +5,8 @@ use std::{
};
use crate::{
lit, name,
Component, RefStr, RefString, lit, name,
refspec::{PatternStr, QualifiedPattern},
Component, RefStr, RefString,
};
/// A fully-qualified refname.
@@ -28,8 +27,8 @@ impl<'a> Qualified<'a> {
///
/// # Example
///
/// ```no_run
/// use git_ref_format::{component, Qualified};
/// ```
/// use radicle_git_ref_format::{name::component, Qualified};
///
/// assert_eq!(
/// "refs/heads/main",
@@ -269,20 +268,22 @@ impl Display for Qualified<'_> {
/// A [`Qualified`] ref under a git namespace.
///
/// A ref is namespaced if it starts with "refs/namespaces/", another path
/// component, and "refs" or "HEAD". Eg.
///
/// refs/namespaces/xyz/refs/heads/main
/// refs/namespaces/xyz/HEAD
/// component, and "refs" or "HEAD".
/// For example "/namespaces/xyz/refs/heads/main"
/// or "refs/namespaces/xyz/HEAD".
///
/// Note that namespaces can be nested, so the result of
/// [`Namespaced::strip_namespace`] may be convertible to a [`Namespaced`]
/// again. For example:
///
/// ```no_run
/// let full = refname!("refs/namespaces/a/refs/namespaces/b/refs/heads/main");
/// let namespaced = full.namespaced().unwrap();
/// ```
/// use radicle_git_ref_format::RefString;
///
/// let full =
/// RefString::try_from("refs/namespaces/a/refs/namespaces/b/refs/heads/main").unwrap();
/// let namespaced = full.to_namespaced().unwrap();
/// let strip_first = namespaced.strip_namespace();
/// let nested = strip_first.namespaced().unwrap();
/// let nested = strip_first.to_namespaced().unwrap();
/// let strip_second = nested.strip_namespace();
///
/// assert_eq!("a", namespaced.namespace().as_str());
+30 -12
View File
@@ -1,16 +1,14 @@
#![no_std]
//! [`git_ref_format`]: https://crates.io/crates/git-ref-format
//! [`radicle-git-ext`]: https://crates.io/crates/radicle-git-ext
//!
//! This crate depends on and re-exports from [`git_ref_format_core`].
//!
//! ## Macros
//!
//! Instead of providing procedural macros, like [`git_ref_format`]
//! it just provides much simpler declarative macros, guarded by the feature
//! Instead of providing procedural macros, like [`git_ref_format`] this
//! crate just provides much simpler declarative macros, guarded by the feature
//! flag `macro`.
//!
//! ## Comparison to [`git_ref_format`]
//!
//! ### Benefits
//!
//! - Does not depend on [`radicle-git-ext`].
@@ -25,9 +23,29 @@
//! these tests are run, then the guarantees are equally strong. Consumers that
//! do not or cannot test their code should not use the macros then.
pub use git_ref_format_core::*;
mod check;
pub use check::{Error, Options, ref_format as check_ref_format};
/// Create a [`git_ref_format_core::RefString`] from a string literal.
mod deriv;
pub use deriv::{Namespaced, Qualified};
pub mod lit;
pub mod name;
#[cfg(feature = "percent-encoding")]
pub use name::PercentEncode;
pub use name::{Component, RefStr, RefString};
pub mod refspec;
pub use refspec::DuplicateGlob;
#[cfg(feature = "minicbor")]
mod cbor;
#[cfg(feature = "serde")]
mod serde;
/// Create a [`crate::RefString`] from a string literal.
///
/// Similar to [`core::debug_assert`], an optimized build will not validate
/// (but rather perform an unsafe conversion) unless `-C debug-assertions` is
@@ -59,7 +77,7 @@ macro_rules! refname {
}};
}
/// Create a [`git_ref_format_core::Qualified`] from a string literal.
/// Create a [`crate::Qualified`] from a string literal.
///
/// Similar to [`core::debug_assert`], an optimized build will not validate
/// (but rather perform an unsafe conversion) unless `-C debug-assertions` is
@@ -100,7 +118,7 @@ macro_rules! qualified {
}};
}
/// Create a [`git_ref_format_core::Component`] from a string literal.
/// Create a [`crate::Component`] from a string literal.
///
/// Similar to [`core::debug_assert`], an optimized build will not validate
/// (but rather perform an unsafe conversion) unless `-C debug-assertions` is
@@ -141,7 +159,7 @@ macro_rules! component {
}};
}
/// Create a [`git_ref_format_core::refspec::PatternString`] from a string literal.
/// Create a [`crate::refspec::PatternString`] from a string literal.
///
/// Similar to [`core::debug_assert`], an optimized build will not validate
/// (but rather perform an unsafe conversion) unless `-C debug-assertions` is
@@ -173,7 +191,7 @@ macro_rules! pattern {
}};
}
/// Create a [`git_ref_format_core::refspec::QualifiedPattern`] from a string literal.
/// Create a [`crate::refspec::QualifiedPattern`] from a string literal.
///
/// Similar to [`core::debug_assert`], an optimized build will not validate
/// (but rather perform an unsafe conversion) unless `-C debug-assertions` is
+1 -1
View File
@@ -1,4 +1,4 @@
use crate::{name, Qualified, RefStr};
use crate::{Qualified, RefStr, name};
/// A literal [`RefStr`].
///
+3 -4
View File
@@ -7,13 +7,12 @@ use std::{
};
use crate::{
check,
Namespaced, Qualified, check,
refspec::{PatternStr, PatternString},
Namespaced, Qualified,
};
mod iter;
pub use iter::{component, Component, Components, Iter};
pub use iter::{Component, Components, Iter, component};
#[cfg(feature = "percent-encoding")]
pub use percent_encoding::PercentEncode;
@@ -152,7 +151,7 @@ impl RefStr {
}
#[cfg(feature = "percent-encoding")]
pub fn percent_encode(&self) -> PercentEncode {
pub fn percent_encode(&self) -> PercentEncode<'_> {
/// https://url.spec.whatwg.org/#fragment-percent-encode-set
const FRAGMENT_PERCENT_ENCODE_SET: &percent_encoding::AsciiSet =
&percent_encoding::CONTROLS
+9 -8
View File
@@ -8,10 +8,10 @@ use std::{
use thiserror::Error;
use crate::{check, lit, Namespaced, Qualified, RefStr, RefString};
use crate::{Namespaced, Qualified, RefStr, RefString, check, lit};
mod iter;
pub use iter::{component, Component, Components, Iter};
pub use iter::{Component, Components, Iter, component};
pub const STAR: &PatternStr = PatternStr::from_str("*");
@@ -458,19 +458,20 @@ impl From<QualifiedPattern<'_>> for PatternString {
/// A [`PatternString`] ref under a git namespace.
///
/// A ref is namespaced if it starts with "refs/namespaces/", another path
/// component, and "refs/". Eg.
///
/// refs/namespaces/xyz/refs/heads/main
/// component, and "refs/", for example, "refs/namespaces/xyz/refs/heads/main".
///
/// Note that namespaces can be nested, so the result of
/// [`NamespacedPattern::strip_namespace`] may be convertible to a
/// [`NamespacedPattern`] again. For example:
///
/// ```no_run
/// let full = pattern!("refs/namespaces/a/refs/namespaces/b/refs/heads/*");
/// ```
/// use radicle_git_ref_format::refspec::PatternString;
///
/// let full =
/// PatternString::try_from("refs/namespaces/a/refs/namespaces/b/refs/heads/*").unwrap();
/// let namespaced = full.to_namespaced().unwrap();
/// let strip_first = namespaced.strip_namespace();
/// let nested = strip_first.namespaced().unwrap();
/// let nested = strip_first.to_namespaced().unwrap();
/// let strip_second = nested.strip_namespace();
///
/// assert_eq!("a", namespaced.namespace().as_str());
@@ -1,7 +1,7 @@
use std::fmt::{self, Display};
use super::PatternStr;
use crate::{lit, RefStr};
use crate::{RefStr, lit};
pub type Iter<'a> = std::str::Split<'a, char>;
+2 -2
View File
@@ -1,10 +1,10 @@
use std::convert::TryFrom;
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
use crate::{
refspec::{NamespacedPattern, PatternStr, PatternString, QualifiedPattern},
Namespaced, Qualified, RefStr, RefString,
refspec::{NamespacedPattern, PatternStr, PatternString, QualifiedPattern},
};
impl<'de: 'a, 'a> Deserialize<'de> for &'a RefStr {
+1 -1
View File
@@ -43,7 +43,7 @@ nonempty = { workspace = true, features = ["serialize"] }
qcheck = { workspace = true, optional = true }
radicle-cob = { workspace = true, features = ["git2"] }
radicle-core = { workspace = true, features = ["git2", "serde", "sqlite"] }
radicle-crypto = { workspace = true, features = ["git-ref-format-core", "serde", "ssh", "sqlite", "cyphernet"] }
radicle-crypto = { workspace = true, features = ["radicle-git-ref-format", "serde", "ssh", "sqlite", "cyphernet"] }
radicle-git-ref-format = { workspace = true, features = ["macro", "serde"] }
radicle-git-metadata = { workspace = true }
radicle-localtime = { workspace = true, features = ["serde"] }