hive-forge: timeline --since no longer errors on an empty window
This commit is contained in:
parent
780df10d9d
commit
7a3e7af6b8
1 changed files with 28 additions and 11 deletions
|
|
@ -25,13 +25,14 @@
|
||||||
//! what `forgejo-api` actually returns), so unlike the old `--limit`-only
|
//! what `forgejo-api` actually returns), so unlike the old `--limit`-only
|
||||||
//! shape this is now an exact count, not a boolean "more" flag.
|
//! shape this is now an exact count, not a boolean "more" flag.
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::{Context, Result};
|
||||||
use clap::Args as ClapArgs;
|
use clap::Args as ClapArgs;
|
||||||
use forgejo_api::structs::{IssueGetCommentsAndTimelineQuery, TimelineComment};
|
use forgejo_api::structs::{IssueGetCommentsAndTimelineQuery, TimelineComment};
|
||||||
use serde_json::{Value, json};
|
use serde_json::{Value, json};
|
||||||
|
use time::format_description::well_known::Rfc3339;
|
||||||
|
|
||||||
use crate::client::{Client, index};
|
use crate::client::{Client, index};
|
||||||
use crate::verbs::{MAX_LIMIT, PAGE_SIZE, clamp_limit, parse_rfc3339, print_json};
|
use crate::verbs::{MAX_LIMIT, NullableVec, PAGE_SIZE, clamp_limit, parse_rfc3339, print_json};
|
||||||
|
|
||||||
#[derive(ClapArgs)]
|
#[derive(ClapArgs)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
|
|
@ -246,6 +247,20 @@ fn fetch_tail(
|
||||||
/// `comments.rs`'s `fetch_since` does: ask for `limit + 1`, and a full
|
/// `comments.rs`'s `fetch_since` does: ask for `limit + 1`, and a full
|
||||||
/// extra row means there's more. Returns `(events, more)`, `more` a
|
/// extra row means there's more. Returns `(events, more)`, `more` a
|
||||||
/// boolean rather than an exact count.
|
/// boolean rather than an exact count.
|
||||||
|
///
|
||||||
|
/// Deliberately bypasses the typed `forgejo-api` client
|
||||||
|
/// (`issue_get_comments_and_timeline`) rather than calling it directly:
|
||||||
|
/// this endpoint answers an empty `--since` window with a JSON `null`
|
||||||
|
/// body, and the typed client's generated response type is
|
||||||
|
/// `Vec<TimelineComment>`, which fails to deserialize `null` at all — the
|
||||||
|
/// single most common answer to "anything new since my last check?"
|
||||||
|
/// turns into a hard error instead of an empty list. The sibling
|
||||||
|
/// `issue_get_comments` endpoint `comments.rs`'s own `fetch_since` calls
|
||||||
|
/// returns `[]` for the same case and never hits this. [`NullableVec`] is
|
||||||
|
/// this codebase's existing, tested newtype for exactly this shape of
|
||||||
|
/// problem — used the same way for reactions and blocking-issue lists —
|
||||||
|
/// so this reuses it via [`Client::get_api_json`] rather than inventing a
|
||||||
|
/// second null-tolerant path.
|
||||||
fn fetch_since(
|
fn fetch_since(
|
||||||
client: &Client,
|
client: &Client,
|
||||||
number: u64,
|
number: u64,
|
||||||
|
|
@ -253,16 +268,18 @@ fn fetch_since(
|
||||||
limit: u64,
|
limit: u64,
|
||||||
) -> Result<(Vec<TimelineComment>, bool)> {
|
) -> Result<(Vec<TimelineComment>, bool)> {
|
||||||
let (owner, name) = client.owner_repo()?;
|
let (owner, name) = client.owner_repo()?;
|
||||||
let query = IssueGetCommentsAndTimelineQuery {
|
let idx = index(number)?;
|
||||||
since: Some(since),
|
|
||||||
before: None,
|
|
||||||
};
|
|
||||||
let fetch_limit = limit.saturating_add(1);
|
let fetch_limit = limit.saturating_add(1);
|
||||||
let (_, events) = client
|
let since_str = since
|
||||||
.api()
|
.format(&Rfc3339)
|
||||||
.issue_get_comments_and_timeline(owner, name, index(number)?, query)
|
.context("format --since timestamp as RFC 3339")?;
|
||||||
.page_size(u32::try_from(fetch_limit).unwrap_or(u32::MAX))
|
let fetch_limit_str = fetch_limit.to_string();
|
||||||
.send()?;
|
let path = format!("/repos/{owner}/{name}/issues/{idx}/timeline");
|
||||||
|
let events: NullableVec<TimelineComment> = client.get_api_json(
|
||||||
|
&path,
|
||||||
|
&[("since", since_str.as_str()), ("limit", &fetch_limit_str)],
|
||||||
|
)?;
|
||||||
|
let events = events.0;
|
||||||
let limit = usize::try_from(limit).unwrap_or(usize::MAX);
|
let limit = usize::try_from(limit).unwrap_or(usize::MAX);
|
||||||
let more = events.len() > limit;
|
let more = events.len() > limit;
|
||||||
let mut events = events;
|
let mut events = events;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue