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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use std::env::consts;

#[cfg(any(target_os = "windows", target_os = "linux"))]
use regex::Regex;
#[cfg(any(target_os = "windows", target_os = "linux"))]
use self_update::backends::github::{ReleaseList, UpdateBuilder};
use thiserror::Error;

#[cfg(not(any(target_os = "windows", target_os = "linux")))]
#[derive(Debug, Clone, Copy, Error)]
pub enum UpdateError {
    #[error("Not supported on the platform: {0}")]
    NotSupported(&'static str),
}

#[cfg(any(target_os = "windows", target_os = "linux"))]
#[derive(Debug, Error)]
pub enum UpdateError {
    #[error("Version tag not in the format of '(v)X.Y.Z'")]
    VersionTag,
    #[error("No release is available for the target")]
    MissingRelease,
    #[error("{0}")]
    SelfUpdate(#[from] self_update::errors::Error),
}

#[allow(unused_variables)]
#[allow(clippy::missing_panics_doc)]
pub fn update(
    bin_name: &str,
    current_version: &str,
    target_version: Option<&str>,
) -> Result<(), UpdateError> {
    #[cfg(not(any(target_os = "windows", target_os = "linux")))]
    {
        Err(UpdateError::NotSupported(consts::OS))
    }
    #[cfg(any(target_os = "windows", target_os = "linux"))]
    {
        let mut version = if let Some(version) = target_version {
            let version = version.to_owned();
            let re = Regex::new(r"^v?[0-9]+\.[0-9]+\.[0-9]+$").unwrap();
            if !re.is_match(&version) {
                return Err(UpdateError::VersionTag);
            }
            version
        } else {
            let releases = ReleaseList::configure()
                .repo_owner("amtep")
                .repo_name("ck3-tiger")
                .with_target(consts::OS)
                .build()?
                .fetch()?;

            releases.first().ok_or(UpdateError::MissingRelease)?.version.clone()
        };

        if !version.starts_with('v') {
            version.insert(0, 'v');
        }

        #[cfg(target_os = "linux")]
        let bin_path = format!("{0}-{1}-{2}/{0}", bin_name, consts::OS, version);
        #[cfg(target_os = "windows")]
        let bin_path = format!("{}.exe", bin_name);

        let mut updater = UpdateBuilder::new();
        updater
            .repo_owner("amtep")
            .repo_name("ck3-tiger")
            .bin_name(bin_name)
            .bin_path_in_archive(&bin_path)
            .identifier(bin_name)
            .target(consts::OS)
            .current_version(current_version)
            .show_download_progress(true);

        if target_version.is_some() {
            updater.target_version_tag(&version);
        }
        updater.build()?.update()?;

        Ok(())
    }
}