Radish alpha
r
Radicle CI broker
Radicle
Git (anonymous pull)
Log in to clone via SSH
fix: parsing of ref strings for NID; also add tests
Lars Wirzenius committed 1 year ago
commit 74862206fb7d44da4277213326a905e7b503c307
parent 0266df7e21aaad5aaf527a86be963f8c509940ad
1 file changed +106 -10
modified src/event.rs
@@ -113,7 +113,7 @@ impl NodeEventSource {
                match event {
                    Ok(ref event) if Self::is_shutdown_request(event) => {
                        info!("got shutdown request from node control socket");
-
                        return Ok(vec![BrokerEvent::Shutdown]);
+
                        return Ok(vec![BrokerEvent::shutdown()]);
                    }
                    Ok(event) => {
                        trace!("got node event {:#?}", event);
@@ -331,6 +331,10 @@ impl BrokerEvent {
        }
    }

+
    pub fn shutdown() -> Self {
+
        Self::Shutdown
+
    }
+

    /// Break up a potentially complex node event into a vector of
    /// simpler broker events.
    pub fn from_event(e: &Event) -> Option<Vec<Self>> {
@@ -346,7 +350,7 @@ impl BrokerEvent {
                    RefUpdate::Skipped { name, oid }
                        if name.as_str() == "shutdown" && oid.is_zero() =>
                    {
-
                        events.push(Self::Shutdown);
+
                        events.push(Self::shutdown());
                    }
                    RefUpdate::Created { name, oid } => {
                        events.push(Self::new(rid, name, oid, None));
@@ -434,15 +438,10 @@ impl BrokerEvent {
    /// The RefString will start with `refs/namespaces/<nid>/...`
    pub fn nid(&self) -> Option<NodeId> {
        if let Some(name) = self.name() {
-
            let mut parts = name.split('/');
-
            if let Some(nid) = parts.nth(2) {
-
                let parsed = nid.parse();
-
                if parsed.is_ok() {
-
                    return parsed.ok();
-
                }
-
            }
+
            parse_nid_from_refstring(name)
+
        } else {
+
            None
        }
-
        None
    }

    pub fn patch_id(&self) -> Option<Oid> {
@@ -455,6 +454,74 @@ impl BrokerEvent {
    }
}

+
/// Extract the NID from a the ref string in a repository.
+
/// The RefString should start with `refs/namespaces/<nid>/...`
+
pub fn parse_nid_from_refstring(name: &RefString) -> Option<NodeId> {
+
    let pat = Regex::new(r"^refs/namespaces/(?P<nid>[^/]+)/").unwrap();
+
    if let Some(captures) = pat.captures(name.as_str()) {
+
        if let Some(m) = captures.name("nid") {
+
            if let Ok(parsed) = m.as_str().parse() {
+
                return Some(parsed);
+
            }
+
        }
+
    }
+
    None
+
}
+

+
#[cfg(test)]
+
mod test_broker_event {
+
    use std::str::FromStr;
+

+
    use super::{BrokerEvent, NodeId, Oid, RefString, RepoId};
+

+
    #[test]
+
    fn name_for_branch() {
+
        let rid = RepoId::from_urn("rad:zwTxygwuz5LDGBq255RA2CbNGrz8").expect("RepoId");
+
        let name = RefString::try_from("main").expect("RefString");
+
        let oid = Oid::from_str("11d03559fb10183b0f14331175f254fbb077159a").expect("Oid");
+
        let be = BrokerEvent::new(&rid, &name, &oid, None);
+
        assert_eq!(be.name(), Some(&name));
+
    }
+

+
    #[test]
+
    fn name_for_shutdown() {
+
        let be = BrokerEvent::shutdown();
+
        assert_eq!(be.name(), None);
+
    }
+

+
    #[test]
+
    fn nid_for_plain_branch_name() {
+
        let rid = RepoId::from_urn("rad:zwTxygwuz5LDGBq255RA2CbNGrz8").expect("RepoId");
+
        let name = RefString::try_from("main").expect("RefString");
+
        let oid = Oid::from_str("11d03559fb10183b0f14331175f254fbb077159a").expect("Oid");
+
        let be = BrokerEvent::new(&rid, &name, &oid, None);
+
        assert_eq!(be.nid(), None);
+
    }
+

+
    #[test]
+
    fn nid_for_ref_without_namespace() {
+
        let rid = RepoId::from_urn("rad:zwTxygwuz5LDGBq255RA2CbNGrz8").expect("RepoId");
+
        let name = RefString::try_from("something/else/main").expect("RefString");
+
        let oid = Oid::from_str("11d03559fb10183b0f14331175f254fbb077159a").expect("Oid");
+
        let be = BrokerEvent::new(&rid, &name, &oid, None);
+
        assert_eq!(be.nid(), None);
+
    }
+

+
    #[test]
+
    fn nid_for_ref_with_namespace() {
+
        let rid = RepoId::from_urn("rad:zwTxygwuz5LDGBq255RA2CbNGrz8").expect("RepoId");
+
        let name = RefString::try_from(
+
            "refs/namespaces/z6MkgEMYod7Hxfy9qCvDv5hYHkZ4ciWmLFgfvm3Wn1b2w2FV/main",
+
        )
+
        .expect("RefString");
+
        let nid =
+
            NodeId::from_str("z6MkgEMYod7Hxfy9qCvDv5hYHkZ4ciWmLFgfvm3Wn1b2w2FV").expect("NodeId");
+
        let oid = Oid::from_str("11d03559fb10183b0f14331175f254fbb077159a").expect("Oid");
+
        let be = BrokerEvent::new(&rid, &name, &oid, None);
+
        assert_eq!(be.nid(), Some(nid));
+
    }
+
}
+

/// Parsed reference to one of the supported types
/// Patch with patch ID
/// Push with branch name
@@ -499,6 +566,35 @@ pub fn parse_ref(s: &str) -> Option<ParsedRef> {
    None
}

+
#[cfg(test)]
+
mod test_parse_ref {
+
    use super::{parse_ref, Oid, ParsedRef};
+

+
    #[test]
+
    fn plain_branch_name_is_none() {
+
        assert_eq!(parse_ref("main"), None);
+
    }
+

+
    #[test]
+
    fn namespaced_branch() {
+
        assert_eq!(
+
            parse_ref(
+
                "refs/namespaces/z6MkfBU2cwcZfaE6Z1dLqb7Ve7u4pdgbSo9tP6qUVsqFn2xv/refs/heads/main"
+
            ),
+
            Some(ParsedRef::Push("main".into()))
+
        );
+
    }
+

+
    #[test]
+
    fn namespaced_patch() {
+
        const SHA: &str = "0a4c69183fc8b8d849f5ab977d70f2a1f4788bca";
+
        assert_eq!(
+
            parse_ref(&format!("refs/namespaces/NID/refs/heads/patches/{SHA}")),
+
            Some(ParsedRef::Patch(Oid::try_from(SHA).unwrap()))
+
        );
+
    }
+
}
+

pub fn is_patch_update(name: &str) -> Option<&str> {
    let mut parts = name.split("/refs/cobs/xyz.radicle.patch/");
    if let Some(suffix) = parts.nth(1) {