Radish alpha
r
rad:z39mP9rQAaGmERfUMPULfPUi473tY
Radicle terminal user interface
Radicle
Git
bin/patch: Reorganize cob-specific and common code
Erik Kundt committed 4 months ago
commit 344bb8aa34183be2ee56ef42763582840ef7d598
parent 3b94048
6 files changed +52 -73
modified bin/cob.rs
@@ -1,2 +1,15 @@
+
use radicle::node::device::Device;
+
use radicle::patch::{Patch, Review, ReviewId, Revision};
+

pub mod issue;
-
pub mod patch;
+

+
pub fn find_review<'a, G>(
+
    patch: &'a Patch,
+
    revision: &Revision,
+
    signer: &Device<G>,
+
) -> Option<(ReviewId, &'a Review)> {
+
    patch
+
        .reviews_of(revision.id())
+
        .find(|(_, review)| review.author().public_key() == signer.public_key())
+
        .map(|(id, review)| (*id, review))
+
}
deleted bin/cob/patch.rs
@@ -1,31 +0,0 @@
-
use anyhow::Result;
-

-
use radicle::cob::patch::{Patch, PatchId};
-
use radicle::node::device::Device;
-
use radicle::patch::cache::Patches;
-
use radicle::patch::{Review, ReviewId, Revision};
-
use radicle::storage::git::Repository;
-
use radicle::Profile;
-

-
pub fn all(profile: &Profile, repository: &Repository) -> Result<Vec<(PatchId, Patch)>> {
-
    let cache = profile.patches(repository)?;
-
    let patches = cache.list()?;
-

-
    Ok(patches.flatten().collect())
-
}
-

-
pub fn find(profile: &Profile, repository: &Repository, id: &PatchId) -> Result<Option<Patch>> {
-
    let cache = profile.patches(repository)?;
-
    Ok(cache.get(id)?)
-
}
-

-
pub fn find_review<'a, G>(
-
    patch: &'a Patch,
-
    revision: &Revision,
-
    signer: &Device<G>,
-
) -> Option<(ReviewId, &'a Review)> {
-
    patch
-
        .reviews_of(revision.id())
-
        .find(|(_, review)| review.author().public_key() == signer.public_key())
-
        .map(|(id, review)| (*id, review))
-
}
modified bin/commands/patch.rs
@@ -1,5 +1,3 @@
-
#[path = "patch/common.rs"]
-
mod common;
#[path = "patch/list.rs"]
mod list;
#[path = "patch/review.rs"]
@@ -11,6 +9,7 @@ use anyhow::anyhow;

use radicle::cob::ObjectId;
use radicle::identity::RepoId;
+
use radicle::prelude::Did;
use radicle::patch::{Patch, Revision, RevisionId, Status};
use radicle::storage::git::Repository;

@@ -18,7 +17,6 @@ use radicle_cli::git::Rev;
use radicle_cli::terminal::args;
use radicle_cli::terminal::args::{string, Args, Error, Help};

-
use crate::commands::tui_patch::common::PatchOperation;
use crate::terminal;
use crate::terminal::Quiet;
use crate::ui::items::patch::filter::PatchFilter;
@@ -236,6 +234,7 @@ impl Args for Options {

#[tokio::main]
pub async fn run(options: Options, ctx: impl radicle_cli::terminal::Context) -> anyhow::Result<()> {
+
    use crate::tui_patch::list::PatchOperation;
    use radicle::storage::ReadStorage;

    let (_, rid) = radicle::rad::cwd()
@@ -324,10 +323,10 @@ pub async fn run(options: Options, ctx: impl radicle_cli::terminal::Context) ->
mod interface {
    use anyhow::anyhow;

-
    use radicle::cob;
+
    use radicle::cob::patch::cache::Patches;
    use radicle::identity::RepoId;
-
    use radicle::patch::PatchId;
-
    use radicle::patch::Verdict;
+
    use radicle::patch;
+
    use radicle::patch::{PatchId, Verdict};
    use radicle::storage::git::cob::DraftStore;
    use radicle::storage::ReadStorage;
    use radicle::Profile;
@@ -336,8 +335,7 @@ mod interface {

    use radicle_tui::Selection;

-
    use crate::cob::patch;
-
    use crate::commands::tui_patch::common::PatchOperation;
+
    use crate::cob;
    use crate::tui_patch::list;
    use crate::tui_patch::review::builder::CommentBuilder;
    use crate::tui_patch::review::ReviewAction;
@@ -351,7 +349,7 @@ mod interface {
        opts: ListOptions,
        profile: Profile,
        rid: RepoId,
-
    ) -> anyhow::Result<Option<Selection<PatchOperation>>> {
+
    ) -> anyhow::Result<Option<Selection<list::PatchOperation>>> {
        let repository = profile.storage.repository(rid).unwrap();

        log::info!("Starting patch selection interface in project {rid}..");
@@ -373,14 +371,16 @@ mod interface {
    ) -> anyhow::Result<()> {
        let repo = profile.storage.repository(rid)?;
        let signer = terminal::signer(&profile)?;
+
        let cache = profile.patches(&repo)?;

-
        let patch = patch::find(&profile, &repo, &patch_id)?
+
        let patch = cache
+
            .get(&patch_id)?
            .ok_or_else(|| anyhow!("Patch `{patch_id}` not found"))?;
        let (_, revision) = opts.revision_or_latest(&patch, &repo)?;
        let hunks = ReviewBuilder::new(&repo).hunks(revision)?;

        let drafts = DraftStore::new(&repo, *signer.public_key());
-
        let mut patches = cob::patch::Cache::no_cache(&drafts)?;
+
        let mut patches = patch::Cache::no_cache(&drafts)?;
        let mut patch = patches.get_mut(&patch_id)?;

        if let Some(review) = revision.review_by(signer.public_key()) {
@@ -394,7 +394,7 @@ mod interface {
        };

        let mode = if opts.edit {
-
            if let Some((id, _)) = patch::find_review(&patch, revision, &signer) {
+
            if let Some((id, _)) = cob::find_review(&patch, revision, &signer) {
                // Review already started, resume.
                log::info!("Resuming review {id}..");

@@ -422,7 +422,7 @@ mod interface {
        loop {
            // Reload review
            let signer = profile.signer()?;
-
            let (review_id, review) = patch::find_review(&patch, revision, &signer)
+
            let (review_id, review) = cob::find_review(&patch, revision, &signer)
                .ok_or_else(|| anyhow!("Could not find review."))?;

            let response = review::Tui::new(
deleted bin/commands/patch/common.rs
@@ -1,12 +0,0 @@
-
use radicle::patch::PatchId;
-
use serde::Serialize;
-

-
/// The selected patch operation returned by the operation
-
/// selection widget.
-
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
-
pub enum PatchOperation {
-
    Checkout { id: PatchId },
-
    Diff { id: PatchId },
-
    Show { id: PatchId },
-
    _Review { id: PatchId },
-
}
modified bin/commands/patch/list.rs
@@ -3,6 +3,8 @@ use std::sync::{Arc, Mutex};

use anyhow::Result;

+
use radicle::patch::cache::Patches;
+
use radicle::patch::PatchId;
use radicle::storage::git::Repository;
use radicle::Profile;

@@ -13,6 +15,7 @@ use ratatui::{Frame, Viewport};

use radicle_tui as tui;

+
use serde::Serialize;
use tui::event::Key;
use tui::store;
use tui::task::EmptyProcessors;
@@ -23,9 +26,6 @@ use tui::ui::im::Show;
use tui::ui::{BufferedValue, Column, Spacing};
use tui::{Channel, Exit};

-
use super::common::PatchOperation;
-

-
use crate::cob::patch;
use crate::ui::items::filter::Filter;
use crate::ui::items::patch::filter::PatchFilter;
use crate::ui::items::patch::Patch;
@@ -54,6 +54,16 @@ const HELP: &str = r#"# Generic keybindings
Pattern:    is:<state> | is:authored | authors:[<did>, <did>] | <search>
Example:    is:open is:authored improve"#;

+
/// The selected patch operation returned by the operation
+
/// selection widget.
+
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
+
pub enum PatchOperation {
+
    Checkout { id: PatchId },
+
    Diff { id: PatchId },
+
    Show { id: PatchId },
+
    _Review { id: PatchId },
+
}
+

type Selection = tui::Selection<PatchOperation>;

pub struct Context {
@@ -135,22 +145,21 @@ impl TryFrom<&Context> for App {
    type Error = anyhow::Error;

    fn try_from(context: &Context) -> Result<Self, Self::Error> {
-
        let patches = patch::all(&context.profile, &context.repository)?;
+
        let cache = &context.profile.patches(&context.repository)?;
+
        let mut patches = cache
+
            .list()?
+
            .filter_map(|patch| patch.ok())
+
            .flat_map(|patch| Patch::new(&context.profile, &context.repository, patch.clone()).ok())
+
            .collect::<Vec<_>>();
+
        patches.sort_by(|a, b| b.timestamp.cmp(&a.timestamp));
+

        let search = {
            let raw = context.filter.to_string();
            raw.trim().to_string()
        };
-
        let filter = PatchFilter::from_str(&context.filter.to_string()).unwrap_or_default();
-

-
        let mut items = patches
-
            .into_iter()
-
            .flat_map(|patch| Patch::new(&context.profile, &context.repository, patch.clone()).ok())
-
            .collect::<Vec<_>>();
-

-
        items.sort_by(|a, b| b.timestamp.cmp(&a.timestamp));

        Ok(App {
-
            patches: Arc::new(Mutex::new(items.clone())),
+
            patches: Arc::new(Mutex::new(patches.clone())),
            state: AppState {
                page: Page::Main,
                main_group: ContainerState::new(3, Some(0)),
@@ -161,7 +170,7 @@ impl TryFrom<&Context> for App {
                }),
                show_search: false,
                help: TextViewState::new(Position::default()),
-
                filter,
+
                filter: PatchFilter::from_str(&context.filter.to_string()).unwrap_or_default(),
            },
        })
    }
modified bin/commands/patch/review.rs
@@ -717,7 +717,7 @@ mod test {
        use radicle::storage::git::cob::DraftStore;
        use radicle::storage::git::Repository;

-
        use crate::cob::patch;
+
        use crate::cob;
        use crate::test::setup::NodeWithRepo;

        use super::builder::ReviewBuilder;
@@ -762,7 +762,7 @@ mod test {
                &node.node.signer,
            )?;

-
            let (_, review) = patch::find_review(draft, revision, &node.node.signer)
+
            let (_, review) = cob::find_review(draft, revision, &node.node.signer)
                .ok_or_else(|| anyhow!("Could not find review."))?;

            Ok((id, review))