Skip to main content

upstream_rs/providers/
release_provider.rs

1#![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}