| 1 | |
|
| 2 | |
|
| 3 | |
|
| 4 | |
|
| 5 | | use crate::db::{self, issues as idb, proposals as pdb}; |
| 6 | | use crate::render::refs; |
| 7 | | use crate::Shared; |
| 8 | |
|
| 9 | |
|
| 10 | | #[derive(Clone, Debug)] |
| 11 | | pub struct Link { |
| 12 | | |
| 13 | | pub kind: &'static str, |
| 14 | | pub number: i64, |
| 15 | | pub title: String, |
| 16 | | |
| 17 | | pub state: String, |
| 18 | | pub url: String, |
| 19 | | } |
| 20 | |
|
| 21 | |
|
| 22 | 75× | pub async fn issues_closed_by(app: &Shared, row: &db::repos::RepoRow, texts: &[&str]) -> Vec<Link> { |
| 23 | 149× | let mut numbers: Vec<i64> = texts.iter().flat_map(|t| refs::closes(t)).collect(); |
| 24 | 75× | numbers.sort(); |
| 25 | 75× | numbers.dedup(); |
| 26 | 75× | let mut out = Vec::new(); |
| 27 | 75× | for n in numbers { |
| 28 | 10× | if let Ok(Some(i)) = idb::get(&app.db, row.id, n).await { |
| 29 | 10× | out.push(Link { kind: "issue", number: n, title: i.title, state: i.state, url: format!("/{}/issue/{n}", row.slug()) }); |
| 30 | 10× | } |
| 31 | | } |
| 32 | 75× | out |
| 33 | 75× | } |
| 34 | |
|
| 35 | |
|
| 36 | |
|
| 37 | 30× | pub async fn proposals_closing(app: &Shared, row: &db::repos::RepoRow, n: i64) -> Vec<Link> { |
| 38 | 30× | let all = pdb::list(&app.db, row.id, &["draft", "open", "landed", "closed"]).await.unwrap_or_default(); |
| 39 | | |
| 40 | 30× | let hashes: Vec<Vec<String>> = all.iter().map(|p| p.projected_changes()).collect(); |
| 41 | 30× | let messages: Vec<Vec<String>> = match crate::repos::RepoName::new(&row.owner, &row.name) { |
| 42 | 30× | Some(name) => { |
| 43 | 30× | let wanted = hashes.clone(); |
| 44 | 30× | app.repos |
| 45 | 30× | .read(&name, move |r, _| { |
| 46 | 30× | Ok(wanted |
| 47 | 30× | .iter() |
| 48 | 30× | .map(|hs| { |
| 49 | 8× | hs.iter() |
| 50 | 8× | .filter_map(|h| oxy_core::hash::ChangeHash::from_hex(h)) |
| 51 | 8× | .filter_map(|h| r.store().get_change_meta(&h).ok().map(|c| c.message)) |
| 52 | 8× | .collect() |
| 53 | 8× | }) |
| 54 | 30× | .collect()) |
| 55 | 30× | }) |
| 56 | 30× | .await |
| 57 | 30× | .unwrap_or_else(|_| vec![vec![]; hashes.len()]) |
| 58 | | } |
| 59 | 0× | None => vec![vec![]; hashes.len()], |
| 60 | | }; |
| 61 | 30× | all.into_iter() |
| 62 | 30× | .zip(messages) |
| 63 | 30× | .filter(|(p, msgs)| { |
| 64 | 8× | refs::closes(&p.body).contains(&n) || refs::closes(&p.title).contains(&n) || msgs.iter().any(|m| refs::closes(m).contains(&n)) |
| 65 | 8× | }) |
| 66 | 30× | .map(|(p, _)| Link { |
| 67 | | kind: "proposal", |
| 68 | 2× | number: p.number, |
| 69 | 2× | url: format!("/{}/proposal/{}", row.slug(), p.number), |
| 70 | 2× | title: p.title, |
| 71 | 2× | state: p.state, |
| 72 | 2× | }) |
| 73 | 30× | .collect() |
| 74 | 30× | } |