|
1 | | -# git-url-parse |
2 | | - |
3 | 1 | [](https://crates.io/crates/git-url-parse) |
4 | | - |
| 2 | +[](https://crates.io/crates/git-url-parse) |
| 3 | + |
5 | 4 | [](https://github.com/tjtelan/git-url-parse-rs/actions/workflows/ci.yml) |
6 | 5 | [](https://docs.rs/git-url-parse/) |
7 | 6 | [](LICENSE) |
8 | 7 |  |
9 | 8 |
|
10 | | -Supports common protocols as specified by the [Pro Git book](https://git-scm.com/book/en/v2) |
| 9 | +--- |
11 | 10 |
|
12 | | -See: [4.1 Git on the Server - The Protocols](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols) |
| 11 | +<!-- cargo-rdme start --> |
13 | 12 |
|
14 | | -Supports parsing SSH/HTTPS repo urls for: |
15 | | -* Github |
16 | | -* Bitbucket |
17 | | -* Azure Devops |
| 13 | +# Git Url Parse |
18 | 14 |
|
19 | | -See [tests/parse.rs](tests/parse.rs) for expected output for a variety of inputs. |
| 15 | +Parses url used by git (e.g. `git clone <url>`) |
20 | 16 |
|
21 | | ---- |
| 17 | +## Features |
| 18 | + |
| 19 | +- 🔍 Parses `git clone` compatible urls into [`GitUrl`](https://docs.rs/git-url-parse/latest/git_url_parse/types/struct.GitUrl.html) |
| 20 | + - Supports multiple Git URL schemes (SSH, HTTP, HTTPS, File) |
| 21 | + - Inspired by [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) with adaptations to support Git urls |
| 22 | + |
| 23 | +- 🏗️ Host provider info extraction |
| 24 | + - Easy to implement trait [`GitProvider`](https://docs.rs/git-url-parse/latest/git_url_parse/types/provider/trait.GitProvider.html) for custom provider parsing |
| 25 | + - Built-in support for multiple Git hosting providers |
| 26 | + * [Generic](https://docs.rs/git-url-parse/latest/git_url_parse/types/provider/struct.GenericProvider.html) (`git@host:owner/repo.git` style urls) |
| 27 | + * [GitLab](https://docs.rs/git-url-parse/latest/git_url_parse/types/provider/struct.GitLabProvider.html) |
| 28 | + * [Azure DevOps](https://docs.rs/git-url-parse/latest/git_url_parse/types/provider/struct.AzureDevOpsProvider.html) |
| 29 | + |
| 30 | +## Quick Example |
| 31 | + |
| 32 | +```rust |
| 33 | +use git_url_parse::{GitUrl, GitUrlParseError}; |
| 34 | +use git_url_parse::types::provider::GitProvider; |
| 35 | +use git_url_parse::types::provider::GenericProvider; |
| 36 | + |
| 37 | +fn main() -> Result<(), git_url_parse::GitUrlParseError> { |
| 38 | + let http_url = GitUrl::parse("https://github.com/tjtelan/git-url-parse-rs.git")?; |
| 39 | + |
| 40 | + // Extract basic URL components |
| 41 | + assert_eq!(http_url.host(), Some("github.com")); |
| 42 | + assert_eq!(http_url.path(), "/tjtelan/git-url-parse-rs.git"); |
| 43 | + |
| 44 | + // Support ssh-based urls as well |
| 45 | + let ssh_url = GitUrl::parse( "[email protected]:tjtelan/git-url-parse-rs.git") ?; |
| 46 | + |
| 47 | + assert_eq!(ssh_url.scheme(), Some("ssh")); |
| 48 | + assert_eq!(ssh_url.host(), Some("github.com")); |
| 49 | + assert_eq!(ssh_url.path(), "tjtelan/git-url-parse-rs.git"); |
| 50 | + |
| 51 | + // Extract provider-specific information |
| 52 | + // Built-in support for Github (Generic), Gitlab, Azure Devops style urls |
| 53 | + let provider : GenericProvider = ssh_url.provider_info()?; |
| 54 | + assert_eq!(provider.owner(), "tjtelan"); |
| 55 | + assert_eq!(provider.repo(), "git-url-parse-rs"); |
| 56 | + |
| 57 | + // Implement your own provider |
| 58 | + #[derive(Debug, Clone, PartialEq, Eq)] |
| 59 | + struct CustomProvider; |
| 60 | + |
| 61 | + impl GitProvider<GitUrl<'_>, GitUrlParseError> for CustomProvider { |
| 62 | + fn from_git_url(_url: &GitUrl) -> Result<Self, GitUrlParseError> { |
| 63 | + // Your custom provider parsing here |
| 64 | + Ok(Self) |
| 65 | + } |
| 66 | + } |
| 67 | + |
| 68 | + let custom_provider: CustomProvider = ssh_url.provider_info()?; |
| 69 | + let expected = CustomProvider; |
| 70 | + assert_eq!(custom_provider, expected); |
| 71 | + |
| 72 | + Ok(()) |
| 73 | +} |
| 74 | +``` |
22 | 75 |
|
23 | | -URLs that use the `ssh://` protocol (implicitly or explicitly) undergo a small normalization process in order to be parsed. |
| 76 | +## Limitations |
24 | 77 |
|
25 | | -Internally uses `Url::parse()` from the [Url](https://crates.io/crates/url) crate after normalization. |
| 78 | + Intended only for git repo urls. Url spec [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) is not fully implemented. |
26 | 79 |
|
27 | | -## Examples |
| 80 | +- No support for: |
| 81 | + - Query parameters |
| 82 | + - Fragment identifiers |
| 83 | + - Percent-encoding |
| 84 | + - Complex IP address formats |
28 | 85 |
|
29 | | -### Run example with debug output |
| 86 | +## Install |
30 | 87 |
|
31 | 88 | ```shell |
32 | | -$ RUST_LOG=git_url_parse cargo run --example multi |
33 | | -$ RUST_LOG=git_url_parse cargo run --example trim_auth |
| 89 | +cargo add git-url-parse |
34 | 90 | ``` |
35 | 91 |
|
36 | | -### Simple usage and output |
| 92 | +### Cargo Features |
37 | 93 |
|
38 | | -```bash |
39 | | -$ cargo run --example readme |
40 | | -``` |
| 94 | +#### `log` |
| 95 | +Enable for internal `debug!` output from [log](https://docs.rs/log/latest) |
| 96 | +#### `serde` |
| 97 | +Enable for [serde](https://docs.rs/serde/latest/) `Serialize`/`Deserialize` on [`GitUrl`](https://docs.rs/git-url-parse/latest/git_url_parse/types/struct.GitUrl.html) |
| 98 | +#### `url` |
| 99 | +(**enabled by default**) |
41 | 100 |
|
42 | | -```rust |
43 | | -use git_url_parse::GitUrl; |
| 101 | +Uses [url](https://docs.rs/url/latest/) during parsing for full url validation |
44 | 102 |
|
45 | | -fn main() { |
46 | | - println!( "SSH: {:#?}", GitUrl::parse( "[email protected]:tjtelan/git-url-parse-rs.git")); |
47 | | - println!("HTTPS: {:#?}", GitUrl::parse("https://github.com/tjtelan/git-url-parse-rs")); |
48 | | -} |
49 | | -``` |
| 103 | +<!-- cargo-rdme end --> |
| 104 | + |
| 105 | +## Migration from 0.4.x and earlier |
| 106 | + |
| 107 | +This crate was one of my first serious projects in Rust. Because I was still learning, it had some maintenance problems and was a bit awkward to use. In version 0.5, I rewrote most of it to fix those issues. |
| 108 | + |
| 109 | +The [`GitUrl`](https://docs.rs/git-url-parse/latest/git_url_parse/types/struct.GitUrl.html) struct is only meant to handle parsing urls used by `git`, which the [url](https://docs.rs/url/latest/url) crate doesn't handle. The recent updates make it so the input string is parsed and internally stored into a simple string slice (`&str`). And, instead of exposing all the internal fields of the struct, those details are hidden, and we use methods to interact with it. |
| 110 | + |
| 111 | +The [`GitProvider`](https://docs.rs/git-url-parse/latest/git_url_parse/types/provider/trait.GitProvider.html) trait helps extract common pieces of information that are often found in different url patterns using the [`GitUrl::provider_info`](https://docs.rs/git-url-parse/latest/git_url_parse/types/struct.GitUrl.html#method.provider_info) method. Several example provider parsers are included to show how this works. The result of [`GitUrl::parse`](https://docs.rs/git-url-parse/latest/git_url_parse/types/struct.GitUrl.html#method.parse) is more straightforward to use, but the internal details are hidden, and working with provider-specific information at the git host level is more specialized. |
| 112 | + |
| 113 | +The most common pattern for git url paths, like `/owner/repo.git`, is handled by [`GenericProvider`](https://docs.rs/git-url-parse/latest/git_url_parse/types/provider/struct.GenericProvider.html). |
| 114 | + |
| 115 | +There's also [`AzureDevOpsProvider`](https://docs.rs/git-url-parse/latest/git_url_parse/types/provider/struct.AzureDevOpsProvider.html), which is designed for Azure DevOps urls that follow the `org`, `project`, `repo` pattern. |
50 | 116 |
|
51 | | -### Example Output |
52 | | -```bash |
53 | | -SSH: Ok( |
54 | | - GitUrl { |
55 | | - host: Some( |
56 | | - "github.com", |
57 | | - ), |
58 | | - name: "git-url-parse-rs", |
59 | | - owner: Some( |
60 | | - "tjtelan", |
61 | | - ), |
62 | | - organization: None, |
63 | | - fullname: "tjtelan/git-url-parse-rs", |
64 | | - scheme: Ssh, |
65 | | - user: Some( |
66 | | - "git", |
67 | | - ), |
68 | | - token: None, |
69 | | - port: None, |
70 | | - path: "tjtelan/git-url-parse-rs.git", |
71 | | - git_suffix: true, |
72 | | - scheme_prefix: false, |
73 | | - }, |
74 | | -) |
75 | | -HTTPS: Ok( |
76 | | - GitUrl { |
77 | | - host: Some( |
78 | | - "github.com", |
79 | | - ), |
80 | | - name: "git-url-parse-rs", |
81 | | - owner: Some( |
82 | | - "tjtelan", |
83 | | - ), |
84 | | - organization: None, |
85 | | - fullname: "tjtelan/git-url-parse-rs", |
86 | | - scheme: Https, |
87 | | - user: None, |
88 | | - token: None, |
89 | | - port: None, |
90 | | - path: "/tjtelan/git-url-parse-rs", |
91 | | - git_suffix: false, |
92 | | - scheme_prefix: true, |
93 | | - }, |
94 | | -) |
95 | | -``` |
| 117 | +Finally, there's a new supported provider called [`GitLabProvider`](https://docs.rs/git-url-parse/latest/git_url_parse/types/provider/struct.GitLabProvider.html), which is for GitLab urls. It supports the common `owner/repo` pattern shared with [`GenericProvider`](https://docs.rs/git-url-parse/latest/git_url_parse/types/provider/struct.GenericProvider.html), and also handles GitLab’s subgroups. |
0 commit comments