hyperhive/hive-forge/src/verbs/pr_commits.rs

49 lines
1.6 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 serde_json::json;
use crate::client::Client;
use crate::verbs::print_json;
/// 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;
#[derive(ClapArgs)]
pub struct Args {
/// PR number.
number: u64,
}
pub fn run(client: &Client, args: Args) -> Result<()> {
let repo = client.repo();
let commits = client.get_json_all(
&format!("/repos/{repo}/pulls/{}/commits", args.number),
MAX_PAGES,
)?;
let trimmed: Vec<_> = commits
.iter()
.map(|c| {
let commit = c.get("commit");
json!({
"sha": c.get("sha"),
"message": commit.and_then(|x| x.get("message")),
"author_date": commit
.and_then(|x| x.get("author"))
.and_then(|a| a.get("date")),
"author": c.get("author").and_then(|u| u.get("login")),
})
})
.collect();
print_json(&json!(trimmed))
}