1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
use futures::future::join_all;
use regex::Regex;
use std::error::Error;
use std::rc::Rc;

use crate::api::pull_request;
use crate::api::search::PullRequest;
use crate::Credentials;

const SHIELD_OPEN: &str = "<!---GHSTACKOPEN-->";
const SHIELD_CLOSE: &str = "<!---GHSTACKCLOSE-->";

fn safe_replace(body: &str, table: &str) -> String {
    let new = format!("\n{}\n{}\n{}\n", SHIELD_OPEN, table, SHIELD_CLOSE);

    if body.contains(SHIELD_OPEN) {
        let matcher = format!(
            "(?s){}.*{}",
            regex::escape(SHIELD_OPEN),
            regex::escape(SHIELD_CLOSE)
        );
        let re = Regex::new(&matcher).unwrap();
        re.replace_all(body, &new[..]).into_owned()
    } else {
        let mut body: String = body.to_owned();
        body.push_str(&new);
        body
    }
}

pub async fn persist(
    prs: &Vec<Rc<PullRequest>>,
    table: &str,
    c: &Credentials,
) -> Result<(), Box<dyn Error>> {
    let futures = prs.iter().map(|pr| {
        let description = safe_replace(pr.body(), table);
        pull_request::update_description(description, pr.clone(), c)
    });

    let results = join_all(futures.collect::<Vec<_>>()).await;

    for result in results {
        result.unwrap();
    }

    Ok(())
}