-
Notifications
You must be signed in to change notification settings - Fork 1
/
github.rs
103 lines (92 loc) · 2.98 KB
/
github.rs
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use regex::Regex;
use reqwest::Url;
use serde::Deserialize;
use serde::Serialize;
use crate::utils::config::Repo;
use crate::utils::httpclient::get_binary_pattern_by_arch;
use crate::utils::httpclient::get_binary_pattern_by_os;
use super::Providers;
#[derive(Debug, Serialize, Deserialize)]
pub struct GitHubReleaseAsset {
name: String,
content_type: String,
browser_download_url: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct GitHubRelease {
pub tag_name: String,
pub assets: Vec<GitHubReleaseAsset>,
}
pub fn get_repo_release_asset_url(repo: &Repo) -> Result<String, Box<dyn std::error::Error>> {
let all_release_url = match Providers::from(&repo.provider) {
Providers::GitHub => Url::parse(&format!(
"https://api.github.com/repos/{}/releases",
&repo.repo
))?,
Providers::GitLab => Url::parse(&format!(
"https://gitlab.com/api/v4/projects/{}/releases",
&repo.repo
))?,
Providers::Gitee => Url::parse(&format!(
"https://gitee.com/api/v5/repos/{}/releases",
&repo.repo
))?,
};
let client = reqwest::blocking::Client::builder().timeout(None).build()?;
let res = client
.get(all_release_url)
.header("Accept", "*/*")
.header("User-Agent", "orbiter")
.send()?;
let releases: Vec<GitHubRelease> = res.json()?;
let release = if let Some(ver) = &repo.ver {
releases
.iter()
.find(|release| release.tag_name.eq_ignore_ascii_case(ver))
.unwrap()
} else {
releases
.iter()
.find(|release| !release.tag_name.contains("nightly"))
.unwrap()
};
get_matched_asset_url(&repo.binary_pattern, release)
}
fn get_matched_asset_url(
binary_pattern: &Option<String>,
release: &GitHubRelease,
) -> Result<String, Box<dyn std::error::Error>> {
let assets = release
.assets
.iter()
.filter(|asset| !asset.name.contains("sha256"))
.collect::<Vec<&GitHubReleaseAsset>>();
let matched_assets = if let Some(binary_pattern) = binary_pattern {
let re = Regex::new(binary_pattern)?;
assets
.into_iter()
.filter(|asset| re.is_match(&asset.name))
.collect::<Vec<&GitHubReleaseAsset>>()
} else {
let re_os = get_binary_pattern_by_os()?;
let re_arch = get_binary_pattern_by_arch()?;
let matched_assets = assets
.clone()
.into_iter()
.filter(|asset| {
re_os.is_match(&asset.name.to_lowercase())
|| re_arch.is_match(&asset.name.to_lowercase())
})
.collect::<Vec<&GitHubReleaseAsset>>();
if !matched_assets.is_empty() {
matched_assets
} else {
assets.into_iter().collect()
}
};
Ok(matched_assets
.first()
.unwrap()
.browser_download_url
.to_owned())
}