use anyhow::Result;
use futures::future::try_join_all;
use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
use crate::api::github::{Client, CommitMeta, ContributorMeta, Repository};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MaintainersRawData {
pub commits_18m: Vec<CommitMeta>,
pub contributors: Vec<ContributorMeta>,
pub has_codeowners: bool,
pub has_maintainers_md: bool,
pub has_governance_doc: bool,
pub archived: bool,
}
const CODEOWNERS_PATHS: &[&str] = &[
"CODEOWNERS",
".github/CODEOWNERS",
"docs/CODEOWNERS",
".gitlab/CODEOWNERS",
];
const GOVERNANCE_PATHS: &[&str] = &["GOVERNANCE.md", "GOVERNANCE", "docs/GOVERNANCE.md"];
pub async fn collect(
client: &Client,
owner: &str,
repo: &str,
now: OffsetDateTime,
) -> Result<(Repository, MaintainersRawData)> {
let metadata = client.get_repo(owner, repo).await?;
let cutoff_18m = now - time::Duration::days(30 * 18);
let commits_18m = client.list_commits(owner, repo, cutoff_18m, now).await?;
let contributors = client.list_contributors(owner, repo).await?;
let codeowners_futures = CODEOWNERS_PATHS
.iter()
.map(|p| client.file_exists(owner, repo, p));
let codeowners_results: Vec<bool> = try_join_all(codeowners_futures).await?;
let has_codeowners = codeowners_results.into_iter().any(|x| x);
let has_maintainers_md = client.file_exists(owner, repo, "MAINTAINERS.md").await?;
let governance_futures = GOVERNANCE_PATHS
.iter()
.map(|p| client.file_exists(owner, repo, p));
let governance_results: Vec<bool> = try_join_all(governance_futures).await?;
let has_governance_doc = governance_results.into_iter().any(|x| x);
let raw = MaintainersRawData {
commits_18m,
contributors,
has_codeowners,
has_maintainers_md,
has_governance_doc,
archived: metadata.archived,
};
Ok((metadata, raw))
}