bin/patch: Reorganize cob-specific and common code

This commit is contained in:
Erik Kundt
2025-12-22 01:01:57 +01:00
parent 3b940482bb
commit 344bb8aa34
6 changed files with 52 additions and 73 deletions
+14 -1
View File
@@ -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))
}
-31
View File
@@ -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))
}
+13 -13
View File
@@ -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(
-12
View File
@@ -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 },
}
+23 -14
View File
@@ -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(),
},
})
}
+2 -2
View File
@@ -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))