Watch
0
0
Fork
You've already forked hyperhive
0

hive-forge: smaller comments/timeline defaults, report truncation instead of hiding it

This commit is contained in:
damocles 2026-08-03 19:01:30 +02:00 • committed by mara
commit c7d0e4c317
2 changed files with 144 additions and 53 deletions

View file

@ -10,16 +10,27 @@
//! a human-readable form by default; pass the global `--json` flag
//! for the raw API shape.
//!
//! `--tail N` is a follow-up (the timeline endpoint doesn't expose a
//! total-count field so we can't use the count-then-page trick that
//! `comments --tail` uses; future shape probably mirrors
//! `comments --tail` once Forgejo grows a `count` query or we accept
//! the trailing-slice cost).
//! Default `--limit` is 10 (was 50): this is the verb `hive-forge-notify`
//! points agents at for "there's new activity, go look" — a big default
//! was the same silent-truncation trap `comments`' old default was.
//!
//! **`more` is a boolean, not an exact count**, unlike `comments`'s
//! `more_before`/`more_after`. `comments` gets an exact count for free
//! from the issue's own `comments` field; the timeline endpoint has no
//! equivalent total (mixed event types, no `count` query), and
//! `forgejo-api`'s typed `.send()` doesn't surface response headers
//! (checked: `X-Total-Count`, if Forgejo even sends one, is consumed
//! inside `FromResponse` and never reaches the caller — getting it would
//! mean bypassing the typed endpoint for a raw request, a bigger change
//! than this fix warrants). So this over-fetches by one: ask for
//! `limit + 1`, and if that many come back, trim to `limit` and report
//! "there's more" without saying how much. `--tail` stays a real
//! follow-up if an exact count/tail becomes worth the cost.
use anyhow::Result;
use clap::Args as ClapArgs;
use forgejo_api::structs::IssueGetCommentsAndTimelineQuery;
use serde_json::Value;
use serde_json::{Value, json};
use crate::client::{Client, index};
use crate::verbs::print_json;
@ -28,13 +39,17 @@ use crate::verbs::print_json;
pub struct Args {
/// Issue or PR number.
pub(crate) number: u64,
/// Page size (Forgejo caps at 50). Returns the first `N` events.
#[arg(long, default_value_t = 50)]
/// Return the first `N` events. Default kept small on purpose — see
/// the module doc comment.
#[arg(long, default_value_t = 10)]
limit: u64,
}
pub fn run(client: &Client, args: Args) -> Result<()> {
let (owner, name) = client.owner_repo()?;
// Over-fetch by one to detect truncation without an exact total —
// see the module doc comment for why there's no count query here.
let fetch_limit = args.limit.saturating_add(1);
let (_, events) = client
.api()
.issue_get_comments_and_timeline(
@ -43,13 +58,16 @@ pub fn run(client: &Client, args: Args) -> Result<()> {
index(args.number)?,
IssueGetCommentsAndTimelineQuery::default(),
)
.page_size(u32::try_from(args.limit).unwrap_or(u32::MAX))
.page_size(u32::try_from(fetch_limit).unwrap_or(u32::MAX))
.send()?;
let limit = usize::try_from(args.limit).unwrap_or(usize::MAX);
let more = events.len() > limit;
let events: Vec<_> = events.into_iter().take(limit).collect();
// Serialize back to the API's JSON shape so the per-type render
// arms (and their tests) keep working on plain `Value`s.
let v = serde_json::to_value(events)?;
let v = serde_json::to_value(&events)?;
if client.json_mode() {
return print_json(&v);
return print_json(&json!({ "events": v, "more": more }));
}
let Some(events) = v.as_array() else {
return print_json(&v);
@ -57,6 +75,11 @@ pub fn run(client: &Client, args: Args) -> Result<()> {
for ev in events {
print_event(ev);
}
if more {
println!(
"(more activity not shown — raise --limit to see it; exact count not available)"
);
}
Ok(())
}