Abbaye

at bb4e6ed

use miette::{Result, bail};
use serde::Deserialize;

pub mod cargo;
pub mod git;

use cargo::{CargoVersion, CargoVersionConfig};
use git::{GitVersion, GitVersionConfig};

#[allow(async_fn_in_trait)]
pub trait VersionExtractor {
    type ConfigType: Default + for<'de> Deserialize<'de> + Clone;

    async fn get_last_version(&self, config: Self::ConfigType) -> Result<String>;

    async fn get_all_versions(&self, _config: Self::ConfigType) -> Result<Vec<String>> {
        bail!("get_all_versions is not supported by this version extractor")
    }
}

#[derive(Debug, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum AnyVersionExtractor {
    /// Reads the version from the `version` field in the `[package]` section
    /// of a `Cargo.toml` file.
    ///
    /// ```toml
    /// [version_extractor]
    /// type = "cargo"
    /// manifest_path = "Cargo.toml" # optional, defaults to ./Cargo.toml
    /// ```
    Cargo(CargoVersionConfig),

    /// Derives the version from the most recent Git tag using
    /// `git describe --tags --always`.
    /// Supports stripping a tag prefix (e.g. `"v"`) and customising the
    /// suffix appended when the working tree has uncommitted changes.
    ///
    /// ```toml
    /// [version_extractor]
    /// type = "git"
    /// tag_prefix = "v"      # optional, strips leading "v"
    /// dirty_suffix = "-dev" # optional, defaults to "-dirty"
    /// ```
    Git(GitVersionConfig),
}

impl AnyVersionExtractor {
    pub async fn extract(&self) -> Result<String> {
        match self {
            Self::Cargo(config) => CargoVersion.get_last_version(config.clone()).await,
            Self::Git(config) => GitVersion.get_last_version(config.clone()).await,
        }
    }

    pub async fn extract_all(&self) -> Result<Vec<String>> {
        match self {
            Self::Cargo(config) => CargoVersion.get_all_versions(config.clone()).await,
            Self::Git(config) => GitVersion.get_all_versions(config.clone()).await,
        }
    }
}