Skip to content

Commit 0ae243b

Browse files
committed
Add interchange support with url::Url
1 parent 1dcc198 commit 0ae243b

File tree

5 files changed

+344
-59
lines changed

5 files changed

+344
-59
lines changed

src/lib.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
//! - 🏗️ Host provider info extraction
1616
//! - Easy to implement trait [`GitProvider`](crate::types::provider::GitProvider) for custom provider parsing
1717
//! - Built-in support for multiple Git hosting providers
18-
//! * [Generic](crate::types::provider::GenericProvider) (`git@host:owner/repo.git` style urls)
19-
//! * [GitLab](crate::types::provider::GitLabProvider)
20-
//! * [Azure DevOps](crate::types::provider::AzureDevOpsProvider)
18+
//! * [Generic](crate::types::provider::generic::GenericProvider) (`git@host:owner/repo.git` style urls)
19+
//! * [GitLab](crate::types::provider::gitlab::GitLabProvider)
20+
//! * [Azure DevOps](crate::types::provider::azure_devops::AzureDevOpsProvider)
2121
//!
2222
//! ## Quick Example
2323
//!
@@ -90,7 +90,12 @@
9090
//! #### `url`
9191
//! (**enabled by default**)
9292
//!
93-
//! Uses [url](https://docs.rs/url/latest/) during parsing for full url validation
93+
//! `GitUrl` parsing finishes with [url](https://docs.rs/url/latest/) during parsing for full url validation
94+
//!
95+
//! [`GitUrl::parse_to_url`] will normalize an ssh-based url and return [`url::Url`](https://docs.rs/url/latest/url/struct.Url.html)
96+
//!
97+
//! You can use `url::Url` with the built-in [`GitProvider`](crate::types::provider::GitProvider) host parsers. See the `url_interop` tests for examples
98+
//!
9499
//!
95100
96101
pub mod types;

src/types/mod.rs

Lines changed: 45 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,6 @@ pub struct GitUrl {
6767
hint: GitUrlParseHint,
6868
}
6969

70-
/// Build the printable GitUrl from its components
71-
impl fmt::Display for GitUrl {
72-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73-
let git_url_str = self.display();
74-
75-
write!(f, "{git_url_str}",)
76-
}
77-
}
78-
7970
impl GitUrl {
8071
/// scheme name (i.e. `scheme://`)
8172
pub fn scheme(&self) -> Option<&str> {
@@ -130,7 +121,7 @@ impl GitUrl {
130121
}
131122

132123
/// This method rebuilds the printable GitUrl from its components.
133-
/// `url_compat` results in output that can be parsed by the `url` crate
124+
/// `url_compat` results in output that can be parsed by the [`url`](https://docs.rs/url/latest/url/) crate
134125
fn build_string(&self, url_compat: bool) -> String {
135126
let scheme = if self.print_scheme() || url_compat {
136127
if let Some(scheme) = self.scheme() {
@@ -176,45 +167,7 @@ impl GitUrl {
176167
let git_url_str = format!("{scheme}{auth_info}{host}{port}{path}");
177168
git_url_str
178169
}
179-
}
180-
181-
#[cfg(feature = "url")]
182-
impl TryFrom<&GitUrl> for Url {
183-
type Error = url::ParseError;
184-
fn try_from(value: &GitUrl) -> Result<Self, Self::Error> {
185-
// Since we don't fully implement any spec, we'll rely on the url crate
186-
Url::parse(&value.url_compat_display())
187-
}
188-
}
189-
190-
#[cfg(feature = "url")]
191-
impl TryFrom<GitUrl> for Url {
192-
type Error = url::ParseError;
193-
fn try_from(value: GitUrl) -> Result<Self, Self::Error> {
194-
// Since we don't fully implement any spec, we'll rely on the url crate
195-
Url::parse(&value.url_compat_display())
196-
}
197-
}
198-
199-
#[cfg(feature = "url")]
200-
impl TryFrom<&Url> for GitUrl {
201-
type Error = GitUrlParseError;
202-
fn try_from(value: &Url) -> Result<Self, Self::Error> {
203-
// Since we don't fully implement any spec, we'll rely on the url crate
204-
GitUrl::parse(value.as_str())
205-
}
206-
}
207-
208-
#[cfg(feature = "url")]
209-
impl TryFrom<Url> for GitUrl {
210-
type Error = GitUrlParseError;
211-
fn try_from(value: Url) -> Result<Self, Self::Error> {
212-
// Since we don't fully implement any spec, we'll rely on the url crate
213-
GitUrl::parse(value.as_str())
214-
}
215-
}
216170

217-
impl GitUrl {
218171
/// Returns `GitUrl` after removing all user info values
219172
pub fn trim_auth(&self) -> GitUrl {
220173
let mut new_giturl = self.clone();
@@ -244,7 +197,7 @@ impl GitUrl {
244197
Ok(git_url)
245198
}
246199

247-
/// Internal parse to `GitUrl` without further validation
200+
/// Internal parse to `GitUrl` without validation steps
248201
fn parse_to_git_url(input: &str) -> Result<Self, GitUrlParseError> {
249202
let mut git_url_result = GitUrl::default();
250203
// Error if there are null bytes within the url
@@ -414,3 +367,46 @@ impl GitUrl {
414367
Ok(())
415368
}
416369
}
370+
371+
/// Build the printable GitUrl from its components
372+
impl fmt::Display for GitUrl {
373+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
374+
let git_url_str = self.display();
375+
376+
write!(f, "{git_url_str}",)
377+
}
378+
}
379+
380+
#[cfg(feature = "url")]
381+
impl TryFrom<&GitUrl> for Url {
382+
type Error = url::ParseError;
383+
fn try_from(value: &GitUrl) -> Result<Self, Self::Error> {
384+
// Since we don't fully implement any spec, we'll rely on the url crate
385+
Url::parse(&value.url_compat_display())
386+
}
387+
}
388+
389+
#[cfg(feature = "url")]
390+
impl TryFrom<GitUrl> for Url {
391+
type Error = url::ParseError;
392+
fn try_from(value: GitUrl) -> Result<Self, Self::Error> {
393+
// Since we don't fully implement any spec, we'll rely on the url crate
394+
Url::parse(&value.url_compat_display())
395+
}
396+
}
397+
398+
#[cfg(feature = "url")]
399+
impl TryFrom<&Url> for GitUrl {
400+
type Error = GitUrlParseError;
401+
fn try_from(value: &Url) -> Result<Self, Self::Error> {
402+
GitUrl::parse(value.as_str())
403+
}
404+
}
405+
406+
#[cfg(feature = "url")]
407+
impl TryFrom<Url> for GitUrl {
408+
type Error = GitUrlParseError;
409+
fn try_from(value: Url) -> Result<Self, Self::Error> {
410+
GitUrl::parse(value.as_str())
411+
}
412+
}

src/types/provider/azure_devops.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::{GitUrl, GitUrlParseError};
44

55
use getset::Getters;
66
use nom::Parser;
7+
use nom::branch::alt;
78
use nom::bytes::complete::{is_not, tag, take_until};
89
use nom::combinator::opt;
910
use nom::sequence::{preceded, separated_pair, terminated};
@@ -82,8 +83,10 @@ impl AzureDevOpsProvider {
8283

8384
/// Parse the path of an ssh url for Azure Devops patterns
8485
fn parse_ssh_path(input: &str) -> Result<(&str, AzureDevOpsProvider), GitUrlParseError> {
85-
// Handle optional leading v3/ or other prefix
86-
let (input, _) = opt(take_until("/")).parse(input)?;
86+
// Handle optional leading /v3/ or v3/ prefix
87+
let (input, _) =
88+
opt(alt((preceded(tag("/"), tag("v3/")), take_until("/")))).parse(input)?;
89+
8790
let (input, _) = opt(tag("/")).parse(input)?;
8891

8992
// Parse org/project/repo

src/types/provider/mod.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@
99
//! - [GitLab](crate::types::provider::GitLabProvider)
1010
//! - Custom (via [`GitProvider`] trait)
1111
12-
mod azure_devops;
13-
mod generic;
14-
mod gitlab;
12+
/// Azure DevOps git host
13+
pub mod azure_devops;
14+
/// Generic git host
15+
pub mod generic;
16+
/// GitLab git host
17+
pub mod gitlab;
1518

1619
pub use azure_devops::AzureDevOpsProvider;
1720
pub use generic::GenericProvider;
1821
pub use gitlab::GitLabProvider;
1922

20-
/// Secondary parser called by [`GitUrl::provider_info()`] to extract Git host provider info from url
23+
/// Secondary parser called by [`crate::GitUrl::provider_info()`] to extract Git host provider info from url
2124
///
2225
/// ```
2326
/// // Custom trait example
@@ -43,6 +46,8 @@ pub use gitlab::GitLabProvider;
4346
/// let expected = MyCustomProvider;
4447
/// assert_eq!(provider_info, expected)
4548
/// ```
49+
///
50+
/// With `feature = url`, there is support for parsing Git host provider info from [`url::Url`](https://docs.rs/url/latest/url/struct.Url.html)
4651
pub trait GitProvider<T, E>: Clone + std::fmt::Debug {
4752
/// Trait method called by `GitUrl::provider_info()`
4853
///

0 commit comments

Comments
 (0)