model: distinguish unknown refs/meta/* namespaces from non-meta refs
commit
f3f2418model: distinguish unknown refs/meta/* namespaces from non-meta refs
namespace::classify returned None both for a ref outside
refs/meta/* and for a meta ref in a namespace this build does not
know, but the gate and receive must route the latter generically
(model.extensibility: a stock server carries entity types it cannot
parse). A new Namespace::Unknown variant on the #[non_exhaustive]
enum keeps the two cases apart; None now means only "not forge
state".
Assisted-by: Claude:claude-fable-5
Reviews
No reviews of this commit yet — record a verdict below.
Start a review
crates/ents-model/src/namespace.rs
@@ -138,11 +138,22 @@
Account,
/// The fixed `refs/meta/config` ref.
Config,
+ /// Under `refs/meta/*`, but in no namespace this build of the vocabulary
+ /// knows. `model.extensibility` requires a stock server to carry entity
+ /// types it cannot parse, so the gate and `receive` must be able to
+ /// route an unknown meta namespace generically rather than confuse it
+ /// with a ref that is not forge state at all — which is why this is a
+ /// variant and not a `None`.
+ Unknown,
}
-/// Classify a `refs/meta/*` refname by which entity's namespace it falls in,
-/// or `None` if `name` is not under `refs/meta/*` at all
+/// Classify a `refs/meta/*` refname by which entity's namespace it falls in.
+///
+/// Returns `None` only when `name` is not under `refs/meta/*` at all
/// (`meta-ref.namespace`: "All forge state MUST live under `refs/meta/*`").
+/// A refname under `refs/meta/*` whose namespace this build does not know
+/// classifies as [`Namespace::Unknown`] instead — it is still forge state
+/// (`model.extensibility`), just state this vocabulary cannot interpret.
///
/// # Examples
///
@@ -154,8 +165,11 @@
///
/// let outside: gix::refs::FullName = "refs/heads/main".try_into().expect("valid");
/// assert_eq!(namespace::classify(outside.as_ref()), None);
+///
+/// let novel: gix::refs::FullName = "refs/meta/reviews/7".try_into().expect("valid");
+/// assert_eq!(namespace::classify(novel.as_ref()), Some(Namespace::Unknown));
/// ```
-// @relation(meta-ref.namespace, meta-ref.granularity, scope=function)
+// @relation(meta-ref.namespace, meta-ref.granularity, model.extensibility, scope=function)
#[must_use]
pub fn classify(name: &FullNameRef) -> Option<Namespace> {
let path = name.as_bstr().to_string();
@@ -177,7 +191,7 @@
"toolchains" => Some(Namespace::Toolchain),
"redactions" => Some(Namespace::Redaction),
"inbox" => Some(Namespace::Inbox),
- _ => None,
+ _ => Some(Namespace::Unknown),
}
}
@@ -234,7 +248,8 @@
#[case::account("refs/meta/account", Some(Namespace::Account))]
#[case::config("refs/meta/config", Some(Namespace::Config))]
#[case::outside_meta("refs/heads/main", None)]
- #[case::unrecognized("refs/meta/index/abc", None)]
+ #[case::unrecognized("refs/meta/index/abc", Some(Namespace::Unknown))]
+ #[case::novel_namespace("refs/meta/reviews/7", Some(Namespace::Unknown))]
// @relation(meta-ref.namespace, meta-ref.granularity, scope=function, role=Verifies)
fn classify_matches_the_namespace_table(
#[case] refname: &str,