1use console::style;
2use serde::Deserialize;
3use url::Url;
4
5use super::{
6 version::{DistVersion, UserVersion},
7 SnmRes,
8};
9
10#[derive(Debug, PartialEq, Eq)]
11pub enum Lts {
12 No,
13 Yes(String),
14}
15
16impl<'de> Deserialize<'de> for Lts {
20 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
21 where
22 D: serde::Deserializer<'de>,
23 {
24 let val = match String::deserialize(deserializer) {
25 Ok(v) => Self::Yes(v.to_lowercase()),
26 _ => Self::No,
27 };
28
29 Ok(val)
30 }
31}
32
33#[derive(Debug, Deserialize)]
34pub struct Release {
35 pub version: DistVersion,
36 pub lts: Lts,
37}
38
39pub struct Fetcher {
40 releases: Vec<Release>,
41}
42
43impl Fetcher {
44 pub fn fetch(mirror: &Url) -> SnmRes<Self> {
45 let releases: Vec<Release> = ureq::get(&format!("{}/index.json", mirror))
46 .call()?
47 .into_json()?;
48
49 Ok(Self { releases })
50 }
51
52 pub fn lts(&self) -> SnmRes<&Release> {
53 self.releases
54 .iter()
55 .find(|x| matches!(x.lts, Lts::Yes(_)))
56 .ok_or_else(|| anyhow::anyhow!("Unable to find {} release", style("lts").bold()))
57 }
58
59 pub fn latest(&self) -> SnmRes<&Release> {
60 self.releases
61 .iter()
62 .find(|x| matches!(x.lts, Lts::No))
63 .ok_or_else(|| anyhow::anyhow!("Unable to find {} release", style("latest").bold()))
64 }
65
66 pub fn find_release(&self, version: &UserVersion) -> Option<&Release> {
67 self.releases
68 .iter()
69 .find(|release| version.match_release(release))
70 }
71
72 pub fn find_releases(self, version: &UserVersion) -> Vec<Release> {
73 self.releases
74 .into_iter()
75 .filter(|v| version.match_release(v))
76 .collect()
77 }
78
79 pub fn get_all(self) -> Vec<Release> {
80 self.releases
81 }
82}