Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
Allow unknown fields in Project deserialization
Merged fintohaps opened 1 year ago
3 files changed +80 -0 43b0b2b4 e8f2f88b
added radicle-cli/examples/rad-id-unknown-field.md
@@ -0,0 +1,47 @@
+
The payloads in the identity document are extensible and arbitrary fields can be
+
added. Here we will add an emoji alias for the heartwood project:
+

+
```
+
$ rad id update --title "Add emoji alias" --description "Adding alias field" --payload xyz.radicle.project alias '"❤️🪵"'
+
✓ Identity revision 05100d3f0a73b9373681677158615a53ba51940e created
+
╭────────────────────────────────────────────────────────────────────────╮
+
│ Title    Add emoji alias                                               │
+
│ Revision 05100d3f0a73b9373681677158615a53ba51940e                      │
+
│ Blob     a0f421c928dcfc6eca129fc2ea1f50877de7dc20                      │
+
│ Author   did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi      │
+
│ State    accepted                                                      │
+
│ Quorum   yes                                                           │
+
│                                                                        │
+
│ Adding alias field                                                     │
+
├────────────────────────────────────────────────────────────────────────┤
+
│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
+
╰────────────────────────────────────────────────────────────────────────╯
+

+
@@ -1,13 +1,14 @@
+
 {
+
   "payload": {
+
     "xyz.radicle.project": {
+
+      "alias": "❤️🪵",
+
       "defaultBranch": "master",
+
       "description": "Radicle Heartwood Protocol & Stack",
+
       "name": "heartwood"
+
     }
+
   },
+
   "delegates": [
+
     "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
+
   ],
+
   "threshold": 1
+
 }
+
```
+

+
We can see that the project payload still loads by using `rad ls` which will
+
attempt to deserialize the payload:
+

+
```
+
$ rad ls
+
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
+
│ Name        RID                                 Visibility   Head      Description                        │
+
├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
+
│ heartwood   rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji   public       f2de534   Radicle Heartwood Protocol & Stack │
+
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+
```
modified radicle-cli/tests/commands.rs
@@ -628,6 +628,35 @@ fn rad_id_conflict() {
}

#[test]
+
fn rad_id_unknown_field() {
+
    let mut environment = Environment::new();
+
    let alice = environment.node(config::node("alice"));
+
    let working = tempfile::tempdir().unwrap();
+
    let working = working.path();
+

+
    // Setup a test repository.
+
    fixtures::repository(working.join("alice"));
+

+
    test(
+
        "examples/rad-init.md",
+
        working.join("alice"),
+
        Some(&alice.home),
+
        [],
+
    )
+
    .unwrap();
+

+
    let alice = alice.spawn();
+

+
    test(
+
        "examples/rad-id-unknown-field.md",
+
        working.join("alice"),
+
        Some(&alice.home),
+
        [],
+
    )
+
    .unwrap();
+
}
+

+
#[test]
fn rad_node_connect() {
    let mut environment = Environment::new();
    let alice = environment.node(Config::test(Alias::new("alice")));
modified radicle/src/identity/project.rs
@@ -47,6 +47,9 @@ impl<'de> Deserialize<'de> for Project {
            Name,
            Description,
            DefaultBranch,
+
            /// A catch-all variant to allow for unknown fields
+
            #[allow(dead_code)]
+
            Unknown(String),
        }

        struct ProjectVisitor;
@@ -86,6 +89,7 @@ impl<'de> Deserialize<'de> for Project {
                            }
                            default_branch = Some(map.next_value()?);
                        }
+
                        Field::Unknown(_) => continue,
                    }
                }
                let name = name.ok_or_else(|| de::Error::missing_field("name"))?;