Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
cli: test rad patch delete
Merged fintohaps opened 2 years ago

No tests for rad patch delete existed.

Add a test where two peers interact on a patch and one decides to delete the patch. It ensures that the patch is still visible to the peer that did not delete the patch.

6 files changed +211 -52 00102beb 3bba7d16
added radicle-cli/examples/rad-patch-delete.md
@@ -0,0 +1,123 @@
+
``` ~alice
+
$ git checkout -b prepare-license
+
$ touch LICENSE
+
$ git add LICENSE
+
$ git commit -m "Introduce license"
+
[prepare-license 717c900] Introduce license
+
 1 file changed, 0 insertions(+), 0 deletions(-)
+
 create mode 100644 LICENSE
+
```
+

+
``` ~alice (stderr)
+
$ git push rad -o patch.draft -o patch.message="Define LICENSE for project" HEAD:refs/patches
+
✓ Patch 6c61ef1716ad8a5c11e04dd7a3fec51e01fba70b drafted
+
✓ Synced with 1 node(s)
+
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+
 * [new reference]   HEAD -> refs/patches
+
```
+

+
``` ~bob
+
$ cd heartwood
+
$ rad sync -f
+
✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MknSL…StBU8Vi..
+
✓ Fetched repository from 1 seed(s)
+
$ rad patch comment 6c61ef1 -m "I think we should use MIT"
+
╭───────────────────────────╮
+
│ bob (you) now 833db19     │
+
│ I think we should use MIT │
+
╰───────────────────────────╯
+
✓ Synced with 1 node(s)
+
```
+

+
``` ~alice
+
$ rad patch show 6c61ef1 -v
+
╭────────────────────────────────────────────────────╮
+
│ Title     Define LICENSE for project               │
+
│ Patch     6c61ef1716ad8a5c11e04dd7a3fec51e01fba70b │
+
│ Author    alice (you)                              │
+
│ Head      717c900ec17735639587325e0fd9fe09991c9edd │
+
│ Base      f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 │
+
│ Branches  prepare-license                          │
+
│ Commits   ahead 1, behind 0                        │
+
│ Status    draft                                    │
+
├────────────────────────────────────────────────────┤
+
│ 717c900 Introduce license                          │
+
├────────────────────────────────────────────────────┤
+
│ ● opened by alice (you) (717c900) now              │
+
├────────────────────────────────────────────────────┤
+
│ bob z6Mkt67…v4N1tRk now 833db19                    │
+
│ I think we should use MIT                          │
+
╰────────────────────────────────────────────────────╯
+
$ rad patch comment 6c61ef1 --reply-to 833db19 -m "Thanks, I'll add it!"
+
╭─────────────────────────╮
+
│ alice (you) now 1803a38 │
+
│ Thanks, I'll add it!    │
+
╰─────────────────────────╯
+
✓ Synced with 1 node(s)
+
```
+

+
``` ~alice
+
$ touch MIT
+
$ ln MIT LICENSE -f
+
$ git add MIT
+
$ git commit -am "Add MIT License"
+
[prepare-license 1cc8cd9] Add MIT License
+
 1 file changed, 0 insertions(+), 0 deletions(-)
+
 create mode 100644 MIT
+
```
+

+
``` ~alice (stderr)
+
$ git push -f
+
✓ Patch 6c61ef1 updated to revision 93915b9afa94a9dc4f52f12cdf077d4613ea3eb3
+
✓ Synced with 1 node(s)
+
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+
   717c900..1cc8cd9  prepare-license -> patches/6c61ef1716ad8a5c11e04dd7a3fec51e01fba70b
+
```
+

+
``` ~bob
+
$ rad patch review 6c61ef1 --accept -m "LGTM!"
+
✓ Patch 6c61ef1 accepted
+
✓ Synced with 1 node(s)
+
$ rad patch show 6c61ef1 -v
+
╭─────────────────────────────────────────────────────────────────────╮
+
│ Title    Define LICENSE for project                                 │
+
│ Patch    6c61ef1716ad8a5c11e04dd7a3fec51e01fba70b                   │
+
│ Author   alice z6MknSL…StBU8Vi                                      │
+
│ Head     1cc8cd9de8ccc44b4fe3876f2dbd2cd1cf9ddc0e                   │
+
│ Base     f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354                   │
+
│ Commits  ahead 2, behind 0                                          │
+
│ Status   draft                                                      │
+
├─────────────────────────────────────────────────────────────────────┤
+
│ 1cc8cd9 Add MIT License                                             │
+
│ 717c900 Introduce license                                           │
+
├─────────────────────────────────────────────────────────────────────┤
+
│ ● opened by alice z6MknSL…StBU8Vi (717c900) now                     │
+
│ ↑ updated to 93915b9afa94a9dc4f52f12cdf077d4613ea3eb3 (1cc8cd9) now │
+
│   └─ ✓ accepted by bob (you) now                                    │
+
╰─────────────────────────────────────────────────────────────────────╯
+
```
+

+
``` ~bob
+
$ rad patch delete 6c61ef1
+
✓ Synced with 1 node(s)
+
```
+

+
``` ~alice
+
$ rad patch show 6c61ef1 -v
+
╭─────────────────────────────────────────────────────────────────────╮
+
│ Title     Define LICENSE for project                                │
+
│ Patch     6c61ef1716ad8a5c11e04dd7a3fec51e01fba70b                  │
+
│ Author    alice (you)                                               │
+
│ Head      1cc8cd9de8ccc44b4fe3876f2dbd2cd1cf9ddc0e                  │
+
│ Base      f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354                  │
+
│ Branches  prepare-license                                           │
+
│ Commits   ahead 2, behind 0                                         │
+
│ Status    draft                                                     │
+
├─────────────────────────────────────────────────────────────────────┤
+
│ 1cc8cd9 Add MIT License                                             │
+
│ 717c900 Introduce license                                           │
+
├─────────────────────────────────────────────────────────────────────┤
+
│ ● opened by alice (you) (717c900) now                               │
+
│ ↑ updated to 93915b9afa94a9dc4f52f12cdf077d4613ea3eb3 (1cc8cd9) now │
+
╰─────────────────────────────────────────────────────────────────────╯
+
```
modified radicle-cli/src/commands/patch.rs
@@ -84,6 +84,7 @@ Diff options
Comment options

    -m, --message <string>     Provide a comment message via the command-line
+
        --reply-to <comment>   The comment to reply to

Edit options

modified radicle-cli/src/terminal/patch.rs
@@ -435,6 +435,16 @@ pub fn show(
    for line in timeline::timeline(profile, patch) {
        widget.push(line);
    }
+

+
    if verbose {
+
        for (id, comment) in revision.replies() {
+
            let hstack = term::comment::header(id, comment, profile);
+

+
            widget = widget.divider();
+
            widget.push(hstack);
+
            widget.push(term::textarea(comment.body()).wrap(60));
+
        }
+
    }
    widget.print();

    Ok(())
modified radicle-cli/tests/commands.rs
@@ -898,6 +898,55 @@ fn rad_review_by_hunk() {
}

#[test]
+
fn rad_patch_delete() {
+
    let mut environment = Environment::new();
+
    let alice = environment.node(Config::test(Alias::new("alice")));
+
    let bob = environment.node(Config::test(Alias::new("bob")));
+
    let working = environment.tmp().join("working");
+
    let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+

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

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

+
    let mut alice = alice.spawn();
+
    let mut bob = bob.spawn();
+

+
    bob.handle.seed(acme, Scope::All).unwrap();
+
    alice.connect(&bob).converge([&bob]);
+

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

+
    formula(&environment.tmp(), "examples/rad-patch-delete.md")
+
        .unwrap()
+
        .home(
+
            "alice",
+
            working.join("alice"),
+
            [("RAD_HOME", alice.home.path().display())],
+
        )
+
        .home(
+
            "bob",
+
            working.join("bob"),
+
            [("RAD_HOME", bob.home.path().display())],
+
        )
+
        .run()
+
        .unwrap();
+
}
+

+
#[test]
fn rad_clean() {
    let mut environment = Environment::new();
    let alice = environment.node(Config::test(Alias::new("alice")));
modified radicle-node/src/worker/fetch.rs
@@ -217,64 +217,35 @@ where
    let patches = cob::patch::Patches::open(storage)?;
    for update in refs {
        match update {
-
            RefUpdate::Updated { name, .. } | RefUpdate::Created { name, .. } => {
-
                match name.to_namespaced() {
-
                    Some(name) => {
-
                        let Some(identifier) = cob::TypedId::from_namespaced(&name)? else {
-
                            continue;
-
                        };
-
                        if identifier.is_issue() {
-
                            if let Some(issue) = issues.get(&identifier.id)? {
-
                                cache
-
                                    .update(rid, &identifier.id, &issue)
-
                                    .map(|_| ())
-
                                    .map_err(|e| error::Cache::Update {
-
                                        id: identifier.id,
-
                                        type_name: identifier.type_name,
-
                                        err: e.into(),
-
                                    })?;
-
                            }
-
                        } else if identifier.is_patch() {
-
                            if let Some(patch) = patches.get(&identifier.id)? {
-
                                cache
-
                                    .update(rid, &identifier.id, &patch)
-
                                    .map(|_| ())
-
                                    .map_err(|e| error::Cache::Update {
-
                                        id: identifier.id,
-
                                        type_name: identifier.type_name,
-
                                        err: e.into(),
-
                                    })?;
-
                            }
-
                        }
-
                    }
-
                    None => continue,
-
                }
-
            }
-
            RefUpdate::Deleted { name, .. } => match name.to_namespaced() {
+
            RefUpdate::Updated { name, .. }
+
            | RefUpdate::Created { name, .. }
+
            | RefUpdate::Deleted { name, .. } => match name.to_namespaced() {
                Some(name) => {
                    let Some(identifier) = cob::TypedId::from_namespaced(&name)? else {
                        continue;
                    };
                    if identifier.is_issue() {
-
                        cob::cache::Remove::<cob::issue::Issue>::remove(cache, &identifier.id)
-
                            .map(|_| ())
-
                            .map_err(|e| error::Cache::Remove {
-
                                id: identifier.id,
-
                                type_name: identifier.type_name,
-
                                err: e.into(),
-
                            })?;
+
                        if let Some(issue) = issues.get(&identifier.id)? {
+
                            cache
+
                                .update(rid, &identifier.id, &issue)
+
                                .map(|_| ())
+
                                .map_err(|e| error::Cache::Update {
+
                                    id: identifier.id,
+
                                    type_name: identifier.type_name,
+
                                    err: e.into(),
+
                                })?;
+
                        }
                    } else if identifier.is_patch() {
-
                        cob::cache::Remove::<cob::patch::Patch>::remove(cache, &identifier.id)
-
                            .map(|_| ())
-
                            .map_err(
-
                                |e: <C as cob::cache::Remove<cob::patch::Patch>>::RemoveError| {
-
                                    error::Cache::Remove {
-
                                        id: identifier.id,
-
                                        type_name: identifier.type_name,
-
                                        err: e.into(),
-
                                    }
-
                                },
-
                            )?;
+
                        if let Some(patch) = patches.get(&identifier.id)? {
+
                            cache
+
                                .update(rid, &identifier.id, &patch)
+
                                .map(|_| ())
+
                                .map_err(|e| error::Cache::Update {
+
                                    id: identifier.id,
+
                                    type_name: identifier.type_name,
+
                                    err: e.into(),
+
                                })?;
+
                        }
                    }
                }
                None => continue,
modified radicle/src/cob/patch.rs
@@ -1420,6 +1420,11 @@ impl Revision {
        &self.discussion
    }

+
    /// Iterate over all top-level replies.
+
    pub fn replies(&self) -> impl Iterator<Item = (&CommentId, &thread::Comment<CodeLocation>)> {
+
        self.discussion.comments()
+
    }
+

    /// Reviews of this revision's changes (one per actor).
    pub fn reviews(&self) -> impl DoubleEndedIterator<Item = (&PublicKey, &Review)> {
        self.reviews