miho 8.2.1

Repository management tools
use anyhow::Result;
use semver::{BuildMetadata, Prerelease, Version};
use strum::EnumIs;

#[allow(clippy::enum_variant_names)]
#[derive(Clone, Debug, PartialEq, Eq, EnumIs)]
pub enum Release {
  Major(BuildMetadata),
  Minor(BuildMetadata),
  Patch(BuildMetadata),
  PreMajor(Prerelease, BuildMetadata),
  PreMinor(Prerelease, BuildMetadata),
  PrePatch(Prerelease, BuildMetadata),
  PreRelease(Prerelease, BuildMetadata),
  Literal(Version),
}

impl Release {
  pub fn parser() -> Parser {
    Parser::new()
  }

  pub fn is_stable(&self) -> bool {
    self.is_major() || self.is_minor() || self.is_patch()
  }
}

#[derive(Default)]
pub struct Parser {
  prerelease: Prerelease,
  metadata: BuildMetadata,
}

impl Parser {
  fn new() -> Self {
    Self {
      prerelease: Prerelease::EMPTY,
      metadata: BuildMetadata::EMPTY,
    }
  }

  pub fn prerelease(&mut self, prerelease: &str) -> Result<&mut Self> {
    self.prerelease = Prerelease::new(prerelease)?;
    Ok(self)
  }

  pub fn metadata(&mut self, metadata: &str) -> Result<&mut Self> {
    self.metadata = BuildMetadata::new(metadata)?;
    Ok(self)
  }

  pub fn parse(self, release: &str) -> Result<Release> {
    let release = release.to_lowercase();
    let release = match release.trim() {
      "major" => Release::Major(self.metadata),
      "minor" => Release::Minor(self.metadata),
      "patch" => Release::Patch(self.metadata),
      "premajor" => Release::PreMajor(self.prerelease, self.metadata),
      "preminor" => Release::PreMinor(self.prerelease, self.metadata),
      "prepatch" => Release::PrePatch(self.prerelease, self.metadata),
      "prerelease" => Release::PreRelease(self.prerelease, self.metadata),
      rt => {
        let version = Version::parse(rt)?;
        Release::Literal(version)
      }
    };

    Ok(release)
  }
}