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 get_project_readme(&self, _slug: &str) -> Result<String> {
45 Err(anyhow!("Project README is not supported for this provider"))
46 }
47
48 async fn search_repositories(
49 &self,
50 _query: &str,
51 _limit: Option<u32>,
52 _filters: &RepositorySearchFilters,
53 ) -> Result<Vec<RepositorySearchResult>> {
54 Err(anyhow!(
55 "Repository search is not supported for this provider"
56 ))
57 }
58
59 async fn get_latest_release_if_modified_since(
60 &self,
61 slug: &str,
62 _last_upgraded: Option<DateTime<Utc>>,
63 ) -> Result<Option<Release>> {
64 Ok(Some(self.get_latest_release(slug).await?))
65 }
66
67 async fn download_asset(
68 &self,
69 asset: &Asset,
70 destination_path: &Path,
71 dl_callback: Option<&mut (dyn FnMut(u64, u64) + '_)>,
72 ) -> Result<()>;
73}
74
75#[async_trait(?Send)]
76impl<T> ReleaseProvider for &T
77where
78 T: ReleaseProvider + ?Sized,
79{
80 async fn get_latest_release(&self, slug: &str) -> Result<Release> {
81 (*self).get_latest_release(slug).await
82 }
83
84 async fn get_releases(
85 &self,
86 slug: &str,
87 per_page: Option<u32>,
88 max_total: Option<u32>,
89 ) -> Result<Vec<Release>> {
90 (*self).get_releases(slug, per_page, max_total).await
91 }
92
93 async fn get_releases_newer_than(
94 &self,
95 slug: &str,
96 from_version: &Version,
97 per_page: Option<u32>,
98 ) -> Result<Vec<Release>> {
99 (*self)
100 .get_releases_newer_than(slug, from_version, per_page)
101 .await
102 }
103
104 async fn get_release_by_tag(&self, slug: &str, tag: &str) -> Result<Release> {
105 (*self).get_release_by_tag(slug, tag).await
106 }
107
108 async fn get_branch_head_sha(&self, slug: &str, branch: &str) -> Result<String> {
109 (*self).get_branch_head_sha(slug, branch).await
110 }
111
112 async fn get_project_readme(&self, slug: &str) -> Result<String> {
113 (*self).get_project_readme(slug).await
114 }
115
116 async fn search_repositories(
117 &self,
118 query: &str,
119 limit: Option<u32>,
120 filters: &RepositorySearchFilters,
121 ) -> Result<Vec<RepositorySearchResult>> {
122 (*self).search_repositories(query, limit, filters).await
123 }
124
125 async fn get_latest_release_if_modified_since(
126 &self,
127 slug: &str,
128 last_upgraded: Option<DateTime<Utc>>,
129 ) -> Result<Option<Release>> {
130 (*self)
131 .get_latest_release_if_modified_since(slug, last_upgraded)
132 .await
133 }
134
135 async fn download_asset(
136 &self,
137 asset: &Asset,
138 destination_path: &Path,
139 dl_callback: Option<&mut (dyn FnMut(u64, u64) + '_)>,
140 ) -> Result<()> {
141 (*self)
142 .download_asset(asset, destination_path, dl_callback)
143 .await
144 }
145}