at bb4e6ed
use miette::{IntoDiagnostic, Result, miette}; use serde::Deserialize; use super::VersionExtractor; fn default_dirty_suffix() -> String { "-dirty".to_owned() } /// Configuration for [`GitVersion`]. #[derive(Debug, Clone, Deserialize)] pub struct GitVersionConfig { /// Strip this prefix from the tag name before returning the version. /// For example, `"v"` turns `"v1.2.3"` into `"1.2.3"`. pub tag_prefix: Option<String>, /// Suffix appended to the version when the working tree has uncommitted /// changes. Forwarded verbatim as `--dirty=<suffix>` to `git describe`. /// Defaults to `"-dirty"`. #[serde(default = "default_dirty_suffix")] pub dirty_suffix: String, } impl Default for GitVersionConfig { fn default() -> Self { Self { tag_prefix: None, dirty_suffix: default_dirty_suffix(), } } } /// Extracts the version by running `git describe --tags --always`. pub struct GitVersion; impl VersionExtractor for GitVersion { type ConfigType = GitVersionConfig; async fn get_last_version(&self, config: Self::ConfigType) -> Result<String> { let dirty_arg = format!("--dirty={}", config.dirty_suffix); let output = tokio::process::Command::new("git") .args(["describe", "--tags", "--always", &dirty_arg]) .output() .await .into_diagnostic()?; if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); return Err(miette!("git describe failed:\n{stderr}")); } let raw = String::from_utf8(output.stdout).into_diagnostic()?; let version = raw.trim(); let version = match &config.tag_prefix { Some(prefix) => version.strip_prefix(prefix.as_str()).unwrap_or(version), None => version, }; Ok(version.to_owned()) } async fn get_all_versions(&self, config: Self::ConfigType) -> Result<Vec<String>> { let output = tokio::process::Command::new("git") .args(["tag", "--list", "--sort=version:refname"]) .output() .await .into_diagnostic()?; if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); return Err(miette!("git tag failed:\n{stderr}")); } let raw = String::from_utf8(output.stdout).into_diagnostic()?; let versions = raw .lines() .filter(|s| !s.is_empty()) .map(|tag| match &config.tag_prefix { Some(prefix) => tag.strip_prefix(prefix.as_str()).unwrap_or(tag).to_owned(), None => tag.to_owned(), }) .collect(); Ok(versions) } }