66 lines
2.1 KiB
Rust
66 lines
2.1 KiB
Rust
//! `pr-commits <number> [repo]` — list a PR's commits as JSON
|
|
//! (sha, message, author date, author login), paginated.
|
|
//!
|
|
//! The forge stores a PR's commits against its branch ref, so this
|
|
//! returns them even for a PR whose shas were rewritten by a rebase
|
|
//! merge. The commit message and author date survive a rebase
|
|
//! unchanged, so a caller can match these rows against the linear
|
|
//! `main` history to recover the merged-final commits when the PR's
|
|
//! recorded shas no longer resolve.
|
|
|
|
use anyhow::Result;
|
|
use clap::Args as ClapArgs;
|
|
use forgejo_api::structs::{Commit, RepoGetPullRequestCommitsQuery};
|
|
use serde_json::json;
|
|
|
|
use crate::client::{Client, index};
|
|
use crate::verbs::{print_json, rfc3339};
|
|
|
|
/// Page cap for the commit list. Forgejo serves up to 50 commits per
|
|
/// page; 40 pages (2000 commits) is far beyond any real PR.
|
|
const MAX_PAGES: u32 = 40;
|
|
|
|
/// Page size on the commit list endpoint (Forgejo's cap).
|
|
const PAGE_SIZE: u32 = 50;
|
|
|
|
#[derive(ClapArgs)]
|
|
pub struct Args {
|
|
/// PR number.
|
|
number: u64,
|
|
}
|
|
|
|
pub fn run(client: &Client, args: Args) -> Result<()> {
|
|
let (owner, name) = client.owner_repo()?;
|
|
let idx = index(args.number)?;
|
|
let mut commits: Vec<Commit> = Vec::new();
|
|
for page in 1..=MAX_PAGES {
|
|
let (_, batch) = client
|
|
.api()
|
|
.repo_get_pull_request_commits(
|
|
owner,
|
|
name,
|
|
idx,
|
|
RepoGetPullRequestCommitsQuery::default(),
|
|
)
|
|
.page(page)
|
|
.page_size(PAGE_SIZE)
|
|
.send()?;
|
|
let short = batch.len() < PAGE_SIZE as usize;
|
|
commits.extend(batch);
|
|
if short {
|
|
break;
|
|
}
|
|
}
|
|
let trimmed: Vec<_> = commits
|
|
.iter()
|
|
.map(|c| {
|
|
json!({
|
|
"sha": c.sha,
|
|
"message": c.commit.as_ref().and_then(|x| x.message.as_deref()),
|
|
"author_date": rfc3339(c.commit.as_ref().and_then(|x| x.author.as_ref()).and_then(|a| a.date)),
|
|
"author": c.author.as_ref().and_then(|u| u.login.as_deref()),
|
|
})
|
|
})
|
|
.collect();
|
|
print_json(&json!(trimmed))
|
|
}
|