Skip to main content

pgit_native/
http.rs

1use anyhow::{Context, Result};
2
3/// Download a URL to bytes, optionally with a Bearer token.
4pub fn get_bytes(url: &str, token: Option<&str>) -> Result<Vec<u8>> {
5    let mut req = ureq::get(url);
6    if let Some(t) = token {
7        req = req.header("Authorization", &format!("Bearer {}", t));
8    }
9    let response = req.call().with_context(|| format!("GET {}", url))?;
10    let buf = response
11        .into_body()
12        .read_to_vec()
13        .context("reading response body")?;
14    Ok(buf)
15}
16
17/// Fetch the latest release tag for a GitHub repo via the GitHub API.
18pub fn github_latest_tag(owner: &str, repo: &str, token: Option<&str>) -> Result<String> {
19    let url = format!("https://api.github.com/repos/{}/{}/releases/latest", owner, repo);
20    let bytes = get_bytes(&url, token)?;
21    let json: serde_json::Value =
22        serde_json::from_slice(&bytes).context("parsing GitHub release JSON")?;
23    json["tag_name"]
24        .as_str()
25        .map(str::to_string)
26        .with_context(|| "tag_name missing from GitHub release response")
27}
28
29/// Fetch the latest release tag for a GitLab project via the GitLab API.
30pub fn gitlab_latest_tag(host: &str, project: &str, token: Option<&str>) -> Result<String> {
31    let encoded = urlencoding(project);
32    let url = format!("https://{}/api/v4/projects/{}/releases?per_page=1", host, encoded);
33    let bytes = get_bytes(&url, token)?;
34    let json: serde_json::Value =
35        serde_json::from_slice(&bytes).context("parsing GitLab release JSON")?;
36    json[0]["tag_name"]
37        .as_str()
38        .map(str::to_string)
39        .with_context(|| "tag_name missing from GitLab release response")
40}
41
42fn urlencoding(s: &str) -> String {
43    s.replace('/', "%2F")
44}