cli: add caching commands for patch and issue

In order to bootstrap the COB cache, and also in case of issues,
supply a command for caching a set of patches/issues, or a single
patch/issue.

This is necessary since reads are not read-thru, it may appear that
COBs are missing when in fact they haven't been cached when first
moving over to the cache.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
This commit is contained in:
Fintan Halpenny 2024-02-16 15:36:21 +00:00 committed by cloudhead
parent 985b0af3f6
commit 9e745b68d1
No known key found for this signature in database
4 changed files with 88 additions and 1 deletions

View File

@ -1,3 +1,6 @@
#[path = "issue/cache.rs"]
mod cache;
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::ffi::OsString; use std::ffi::OsString;
use std::str::FromStr; use std::str::FromStr;
@ -44,6 +47,7 @@ Usage
rad issue comment <issue-id> [--message <message>] [--reply-to <comment-id>] [<option>...] rad issue comment <issue-id> [--message <message>] [--reply-to <comment-id>] [<option>...]
rad issue show <issue-id> [<option>...] rad issue show <issue-id> [<option>...]
rad issue state <issue-id> [--closed | --open | --solved] [<option>...] rad issue state <issue-id> [--closed | --open | --solved] [<option>...]
rad issue cache [<issue-id>] [<option>...]
Assign options Assign options
@ -85,6 +89,7 @@ pub enum OperationName {
React, React,
Show, Show,
State, State,
Cache,
} }
/// Command line Peer argument. /// Command line Peer argument.
@ -142,6 +147,9 @@ pub enum Operation {
assigned: Option<Assigned>, assigned: Option<Assigned>,
state: Option<State>, state: Option<State>,
}, },
Cache {
id: Option<Rev>,
},
} }
#[derive(Debug, Default, PartialEq, Eq)] #[derive(Debug, Default, PartialEq, Eq)]
@ -341,6 +349,7 @@ impl Args for Options {
"s" | "state" => op = Some(OperationName::State), "s" | "state" => op = Some(OperationName::State),
"assign" => op = Some(OperationName::Assign), "assign" => op = Some(OperationName::Assign),
"label" => op = Some(OperationName::Label), "label" => op = Some(OperationName::Label),
"cache" => op = Some(OperationName::Cache),
unknown => anyhow::bail!("unknown operation '{}'", unknown), unknown => anyhow::bail!("unknown operation '{}'", unknown),
}, },
@ -397,6 +406,7 @@ impl Args for Options {
opts: label_opts, opts: label_opts,
}, },
OperationName::List => Operation::List { assigned, state }, OperationName::List => Operation::List { assigned, state },
OperationName::Cache => Operation::Cache { id },
}; };
Ok(( Ok((
@ -553,6 +563,10 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
let id = id.resolve(&repo.backend)?; let id = id.resolve(&repo.backend)?;
issues.remove(&id, &signer)?; issues.remove(&id, &signer)?;
} }
Operation::Cache { id } => {
let id = id.map(|id| id.resolve(&repo.backend)).transpose()?;
cache::run(id, &repo, &profile)?;
}
} }
if announce { if announce {

View File

@ -0,0 +1,28 @@
use std::ops::ControlFlow;
use radicle::issue::IssueId;
use radicle::storage::git::Repository;
use radicle::Profile;
use crate::terminal as term;
pub fn run(id: Option<IssueId>, repository: &Repository, profile: &Profile) -> anyhow::Result<()> {
let mut issues = profile.issues_mut(repository)?;
match id {
Some(id) => {
issues.write(&id)?;
term::success!("Successfully cached issue `{id}`");
}
None => issues.write_all(|result, progress| {
match result {
Ok((id, _)) => term::success!("Successfully cached issue `{id}`"),
Err(e) => term::warning(format!("Failed to retrieve issue: {e}")),
};
term::info!("Cached {} of {}", progress.seen(), progress.total());
ControlFlow::Continue(())
})?,
}
Ok(())
}

View File

@ -2,6 +2,8 @@
mod archive; mod archive;
#[path = "patch/assign.rs"] #[path = "patch/assign.rs"]
mod assign; mod assign;
#[path = "patch/cache.rs"]
mod cache;
#[path = "patch/checkout.rs"] #[path = "patch/checkout.rs"]
mod checkout; mod checkout;
#[path = "patch/comment.rs"] #[path = "patch/comment.rs"]
@ -67,6 +69,7 @@ Usage
rad patch edit <patch-id> [<option>...] rad patch edit <patch-id> [<option>...]
rad patch set <patch-id> [<option>...] rad patch set <patch-id> [<option>...]
rad patch comment <patch-id | revision-id> [<option>...] rad patch comment <patch-id | revision-id> [<option>...]
rad patch cache [<patch-id>] [<option>...]
Show options Show options
@ -166,6 +169,7 @@ pub enum OperationName {
Edit, Edit,
Redact, Redact,
Set, Set,
Cache,
} }
#[derive(Debug, Default, PartialEq, Eq)] #[derive(Debug, Default, PartialEq, Eq)]
@ -243,6 +247,9 @@ pub enum Operation {
Set { Set {
patch_id: Rev, patch_id: Rev,
}, },
Cache {
patch_id: Option<Rev>,
},
} }
impl Operation { impl Operation {
@ -262,7 +269,8 @@ impl Operation {
Operation::Show { .. } Operation::Show { .. }
| Operation::Diff { .. } | Operation::Diff { .. }
| Operation::Checkout { .. } | Operation::Checkout { .. }
| Operation::List { .. } => false, | Operation::List { .. }
| Operation::Cache { .. } => false,
} }
} }
} }
@ -518,6 +526,7 @@ impl Args for Options {
"comment" => op = Some(OperationName::Comment), "comment" => op = Some(OperationName::Comment),
"review" => op = Some(OperationName::Review), "review" => op = Some(OperationName::Review),
"set" => op = Some(OperationName::Set), "set" => op = Some(OperationName::Set),
"cache" => op = Some(OperationName::Cache),
unknown => anyhow::bail!("unknown operation '{}'", unknown), unknown => anyhow::bail!("unknown operation '{}'", unknown),
}, },
Value(val) if op == Some(OperationName::Redact) => { Value(val) if op == Some(OperationName::Redact) => {
@ -540,6 +549,7 @@ impl Args for Options {
Some(OperationName::Set), Some(OperationName::Set),
Some(OperationName::Assign), Some(OperationName::Assign),
Some(OperationName::Label), Some(OperationName::Label),
Some(OperationName::Cache),
] ]
.contains(&op) => .contains(&op) =>
{ {
@ -615,6 +625,7 @@ impl Args for Options {
OperationName::Set => Operation::Set { OperationName::Set => Operation::Set {
patch_id: patch_id.ok_or_else(|| anyhow!("a patch must be provided"))?, patch_id: patch_id.ok_or_else(|| anyhow!("a patch must be provided"))?,
}, },
OperationName::Cache => Operation::Cache { patch_id },
}; };
Ok(( Ok((
@ -790,6 +801,12 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
radicle::rad::setup_patch_upstream(&patch_id, *patch.head(), &workdir, true)?; radicle::rad::setup_patch_upstream(&patch_id, *patch.head(), &workdir, true)?;
} }
Operation::Cache { patch_id } => {
let patch_id = patch_id
.map(|id| id.resolve(&repository.backend))
.transpose()?;
cache::run(patch_id, &repository, &profile)?;
}
} }
if announce { if announce {

View File

@ -0,0 +1,28 @@
use std::ops::ControlFlow;
use radicle::patch::PatchId;
use radicle::storage::git::Repository;
use radicle::Profile;
use crate::terminal as term;
pub fn run(id: Option<PatchId>, repository: &Repository, profile: &Profile) -> anyhow::Result<()> {
let mut patches = profile.patches_mut(repository)?;
match id {
Some(id) => {
patches.write(&id)?;
term::success!("Successfully cached patch `{id}`");
}
None => patches.write_all(|result, progress| {
match result {
Ok((id, _)) => term::success!("Successfully cached patch `{id}`"),
Err(e) => term::warning(format!("Failed to retrieve patch: {e}")),
};
term::info!("Cached {} of {}", progress.seen(), progress.total());
ControlFlow::Continue(())
})?,
}
Ok(())
}