adnv 1.5.0

CLI that tracks, checks and auto-updates infrastructure dependency versions across Terraform, Helm, Docker, Git and npm
Documentation
use std::fmt;

use terraform_registry::Address;

use crate::Result;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TerraformSourceKind {
    Module,
    Provider,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TerraformSource {
    pub kind: TerraformSourceKind,
    pub address: String,
}

impl TerraformSource {
    pub fn new_module(address: impl Into<String>) -> Self {
        Self {
            kind: TerraformSourceKind::Module,
            address: address.into(),
        }
    }

    pub fn new_provider(address: impl Into<String>) -> Self {
        Self {
            kind: TerraformSourceKind::Provider,
            address: address.into(),
        }
    }

    pub fn kind(&self) -> TerraformSourceKind {
        self.kind
    }

    pub fn address(&self) -> &str {
        &self.address
    }

    pub fn parse_address(&self) -> Result<Address, terraform_registry::Error> {
        match self.kind {
            TerraformSourceKind::Module => Address::parse_module(&self.address),
            TerraformSourceKind::Provider => Address::parse_provider(&self.address),
        }
    }

    pub fn describe(&self) -> String {
        self.address.clone()
    }

    pub fn parse_url(url: &url::Url) -> Result<Self, crate::Error> {
        let mut repository = url.clone();
        repository.set_fragment(None);

        let address = repository
            .as_str()
            .strip_prefix("terraform://")
            .ok_or_else(|| {
                crate::Error::invalid_source(url.clone(), "expected terraform://<MODULE ADDRESS>")
            })?
            .to_string();

        Ok(Self {
            kind: TerraformSourceKind::Module,
            address,
        })
    }
}

impl fmt::Display for TerraformSource {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match self.kind {
            TerraformSourceKind::Module => "Terraform module",
            TerraformSourceKind::Provider => "Terraform provider",
        };
        f.write_str(s)
    }
}

#[derive(serde::Deserialize)]
pub(super) enum TerraformSourceSerialized {
    Module(String),
    Provider(String),
}

impl From<TerraformSourceSerialized> for TerraformSource {
    fn from(value: TerraformSourceSerialized) -> Self {
        let (kind, address) = match value {
            TerraformSourceSerialized::Module(address) => (TerraformSourceKind::Module, address),
            TerraformSourceSerialized::Provider(address) => {
                (TerraformSourceKind::Provider, address)
            }
        };

        Self { kind, address }
    }
}