use super::GitProvider;
use crate::types::GitUrlParseHint;
use crate::{GitUrl, GitUrlParseError};
use getset::Getters;
use nom::Parser;
use nom::bytes::complete::{is_not, tag, take_until};
use nom::combinator::opt;
use nom::sequence::separated_pair;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "url")]
use url::Url;
#[derive(Debug, PartialEq, Eq, Clone, Getters)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[getset(get = "pub")]
pub struct GenericProvider {
owner: String,
repo: String,
}
impl GenericProvider {
fn parse_path(input: &str) -> Result<(&str, GenericProvider), GitUrlParseError> {
let (input, _) = opt(tag("/")).parse(input)?;
let (input, (user, repo)) = if input.ends_with(".git") {
separated_pair(is_not("/"), tag("/"), take_until(".git")).parse(input)?
} else {
separated_pair(is_not("/"), tag("/"), is_not("/")).parse(input)?
};
Ok((
input,
GenericProvider {
owner: user.to_string(),
repo: repo.to_string(),
},
))
}
pub fn fullname(&self) -> String {
format!("{}/{}", self.owner, self.repo)
}
}
impl GitProvider<GitUrl, GitUrlParseError> for GenericProvider {
fn from_git_url(url: &GitUrl) -> Result<Self, GitUrlParseError> {
if url.hint() == GitUrlParseHint::Filelike {
return Err(GitUrlParseError::ProviderUnsupported);
}
let path = url.path();
Self::parse_path(path).map(|(_, provider)| provider)
}
}
#[cfg(feature = "url")]
impl GitProvider<Url, GitUrlParseError> for GenericProvider {
fn from_git_url(url: &Url) -> Result<Self, GitUrlParseError> {
if url.scheme() == "file" {
return Err(GitUrlParseError::ProviderUnsupported);
}
let path = url.path();
Self::parse_path(path).map(|(_, provider)| provider)
}
}