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
// Copyright (C) 2022 Leandro Lisboa Penz <lpenz@lpenz.org>
// This file is subject to the terms and conditions defined in
// file 'LICENSE', which is part of this source code package.

//! The resolver can deal with different upstream API's by using the
//! [`Upd`] trait, which is generic over the currently supported
//! [`docker`] and [`github`] upstreams.

use async_trait::async_trait;

use crate::entity::Entity;
use crate::error::Error;
use crate::error::Result;
use crate::version::Version;

#[async_trait]
pub trait Updater: std::fmt::Debug {
    fn url(&self, resource: &str) -> Option<String>;
    async fn get_versions(&self, url: &str) -> Result<Vec<Version>>;
    fn updated_line(&self, entity: &Entity) -> Option<String>;
}

pub mod docker;
pub mod github;

#[derive(Debug)]
pub enum Upd {
    Docker(docker::Docker),
    Github(github::Github),
}

#[async_trait]
impl Updater for Upd {
    fn url(&self, resource: &str) -> Option<String> {
        match self {
            Upd::Docker(i) => i.url(resource),
            Upd::Github(i) => i.url(resource),
        }
    }
    async fn get_versions(&self, url: &str) -> Result<Vec<Version>> {
        match self {
            Upd::Docker(i) => i.get_versions(url),
            Upd::Github(i) => i.get_versions(url),
        }
        .await
    }
    fn updated_line(&self, entity: &Entity) -> Option<String> {
        match self {
            Upd::Docker(i) => i.updated_line(entity),
            Upd::Github(i) => i.updated_line(entity),
        }
    }
}

pub fn updater_for(resource: &str) -> Result<impl Updater> {
    if let Some(_url) = docker::url(resource) {
        Ok(Upd::Docker(docker::Docker::default()))
    } else if let Some(_url) = github::url(resource) {
        Ok(Upd::Github(github::Github::default()))
    } else {
        Err(Error::UpdaterNotFound(resource.into()))
    }
}