gps 7.3.3

Official CLI & library for Git Patch Stack
Documentation
use super::super::private::utils;
use std::fmt;
use std::result::Result;
use std::time::Duration;
use ureq;
use version_compare::Version;

#[derive(Debug)]
pub enum LatestWebsiteReleaseError {
    Call(Box<ureq::Error>),
}

impl fmt::Display for LatestWebsiteReleaseError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Call(e) => write!(f, "request failed - {}", e),
        }
    }
}

pub fn latest_website_release() -> Result<String, LatestWebsiteReleaseError> {
    let config = ureq::Agent::config_builder()
        .timeout_global(Some(Duration::from_secs(5)))
        .build();

    let agent: ureq::Agent = config.into();

    let body: String = agent.get("https://git-ps.sh/latest-release-version")
    .call()
    .map_err(|e| LatestWebsiteReleaseError::Call(e.into()))?
    .body_mut()
    .read_to_string()
    .map_err(|e| LatestWebsiteReleaseError::Call(e.into()))?;

    Ok(body.trim().to_string())
}

#[derive(Debug)]
pub enum NewerReleaseAvailableError {
    LatestWebsiteRelease(LatestWebsiteReleaseError),
    ParseLatestVersion,
    ParseCurrentVersion,
}

impl fmt::Display for NewerReleaseAvailableError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::LatestWebsiteRelease(e) => {
                write!(f, "{}", e)
            }
            Self::ParseLatestVersion => write!(f, "failed to parse newer version from tag"),
            Self::ParseCurrentVersion => {
                write!(f, "failed to parse current version from CAGO_PKG_VERSION")
            }
        }
    }
}

pub fn newer_release_available() -> Result<Option<String>, NewerReleaseAvailableError> {
    let latest_version_string = latest_website_release()
        .map_err(NewerReleaseAvailableError::LatestWebsiteRelease)?;
    let latest_version = Version::from(&latest_version_string)
        .ok_or(NewerReleaseAvailableError::ParseLatestVersion)?;
    let current_version = Version::from(env!("CARGO_PKG_VERSION"))
        .ok_or(NewerReleaseAvailableError::ParseCurrentVersion)?;
    if latest_version > current_version {
        Ok(Some(latest_version_string))
    } else {
        Ok(None)
    }
}

#[cfg(not(target_os = "macos"))]
pub fn notify_of_newer_release(newer_release: Option<String>, color: bool) {
    if let Some(latest_release) = newer_release {
        utils::print_warn(
            color,
            format!(
                r#"
  A new release of gps is available!

  {} - https://book.git-ps.sh/tool/installation.html
"#,
                latest_release
            )
            .as_str(),
        )
    }
}

#[cfg(target_os = "macos")]
pub fn notify_of_newer_release(newer_release: Option<String>, color: bool) {
    if let Some(latest_release) = newer_release {
        utils::print_warn(
            color,
            format!(
                r#"
  A new release of gps is available!

  {} - https://book.git-ps.sh/tool/installation.html

  To upgrade, run: brew update && brew upgrade git-ps-rs
"#,
                latest_release
            )
            .as_str(),
        )
    }
}