upstream_rs/providers/
release_provider.rs1#![allow(async_fn_in_trait)]
2
3use std::path::Path;
4
5use anyhow::{Result, anyhow};
6use async_trait::async_trait;
7use chrono::{DateTime, Utc};
8
9use crate::models::{
10 common::Version,
11 provider::{Asset, Release, RepositorySearchFilters, RepositorySearchResult},
12};
13
14#[async_trait(?Send)]
15pub trait ReleaseProvider {
16 async fn get_latest_release(&self, slug: &str) -> Result<Release>;
17
18 async fn get_releases(
19 &self,
20 slug: &str,
21 per_page: Option<u32>,
22 max_total: Option<u32>,
23 ) -> Result<Vec<Release>>;
24
25 async fn get_releases_newer_than(
26 &self,
27 slug: &str,
28 from_version: &Version,
29 per_page: Option<u32>,
30 ) -> Result<Vec<Release>> {
31 let releases = self.get_releases(slug, per_page, None).await?;
32 Ok(releases
33 .into_iter()
34 .filter(|release| release.version > *from_version)
35 .collect())
36 }
37
38 async fn get_release_by_tag(&self, slug: &str, tag: &str) -> Result<Release>;
39
40 async fn get_branch_head_sha(&self, _slug: &str, _branch: &str) -> Result<String> {
41 Err(anyhow!("Branch builds are not supported for this provider"))
42 }
43
44 async fn search_repositories(
45 &self,
46 _query: &str,
47 _limit: Option<u32>,
48 _filters: &RepositorySearchFilters,
49 ) -> Result<Vec<RepositorySearchResult>> {
50 Err(anyhow!(
51 "Repository search is not supported for this provider"
52 ))
53 }
54
55 async fn get_latest_release_if_modified_since(
56 &self,
57 slug: &str,
58 _last_upgraded: Option<DateTime<Utc>>,
59 ) -> Result<Option<Release>> {
60 Ok(Some(self.get_latest_release(slug).await?))
61 }
62
63 async fn download_asset(
64 &self,
65 asset: &Asset,
66 destination_path: &Path,
67 dl_callback: Option<&mut (dyn FnMut(u64, u64) + '_)>,
68 ) -> Result<()>;
69}
70
71#[async_trait(?Send)]
72impl<T> ReleaseProvider for &T
73where
74 T: ReleaseProvider + ?Sized,
75{
76 async fn get_latest_release(&self, slug: &str) -> Result<Release> {
77 (*self).get_latest_release(slug).await
78 }
79
80 async fn get_releases(
81 &self,
82 slug: &str,
83 per_page: Option<u32>,
84 max_total: Option<u32>,
85 ) -> Result<Vec<Release>> {
86 (*self).get_releases(slug, per_page, max_total).await
87 }
88
89 async fn get_releases_newer_than(
90 &self,
91 slug: &str,
92 from_version: &Version,
93 per_page: Option<u32>,
94 ) -> Result<Vec<Release>> {
95 (*self)
96 .get_releases_newer_than(slug, from_version, per_page)
97 .await
98 }
99
100 async fn get_release_by_tag(&self, slug: &str, tag: &str) -> Result<Release> {
101 (*self).get_release_by_tag(slug, tag).await
102 }
103
104 async fn get_branch_head_sha(&self, slug: &str, branch: &str) -> Result<String> {
105 (*self).get_branch_head_sha(slug, branch).await
106 }
107
108 async fn search_repositories(
109 &self,
110 query: &str,
111 limit: Option<u32>,
112 filters: &RepositorySearchFilters,
113 ) -> Result<Vec<RepositorySearchResult>> {
114 (*self).search_repositories(query, limit, filters).await
115 }
116
117 async fn get_latest_release_if_modified_since(
118 &self,
119 slug: &str,
120 last_upgraded: Option<DateTime<Utc>>,
121 ) -> Result<Option<Release>> {
122 (*self)
123 .get_latest_release_if_modified_since(slug, last_upgraded)
124 .await
125 }
126
127 async fn download_asset(
128 &self,
129 asset: &Asset,
130 destination_path: &Path,
131 dl_callback: Option<&mut (dyn FnMut(u64, u64) + '_)>,
132 ) -> Result<()> {
133 (*self)
134 .download_asset(asset, destination_path, dl_callback)
135 .await
136 }
137}