Skip to content

Commit 8825598

Browse files
committed
Merge commit '911c625d4a6ecef07271c5200f3fdc16bd9efe84' into future-main
2 parents 31088d9 + 911c625 commit 8825598

File tree

6 files changed

+258
-21
lines changed

6 files changed

+258
-21
lines changed

CHANGELOG.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# [0.3.0](https://github.com/tjtelan/git-url-parse-rs/compare/v0.2.0...v0.3.0)
2+
- Add `CHANGELOG.md`
3+
- Add new schemes `Ftp` and `Ftps`
4+
- Update `GitUrl` format for `Scheme::File` for `GitUrl.host` and `GitUrl.path`
5+
- Add more tests
6+
7+
# [0.2.0](https://github.com/tjtelan/git-url-parse-rs/compare/v0.1.1...v0.2.0)
8+
- Updating `GitUrl` format
9+
- Add `trim_auth()`
10+
- Add `impl Display` for `GitUrl`
11+
- Rename enum `Protocol` to `Scheme`
12+
13+
# [0.1.1](https://github.com/tjtelan/git-url-parse-rs/compare/v0.1.0...v0.1.1)
14+
- Add CI via Github Actions
15+
- Add badges for docs, crates, build to `README`
16+
- Update `README.md`
17+
- Making enums and Structs `Clone`
18+
19+
# [0.1.0](https://github.com/tjtelan/git-url-parse-rs/compare/v0.0.1...v0.1.0)
20+
- Add support for Azure DevOps
21+
- Add `README.md`
22+
23+
# [0.0.1](https://github.com/tjtelan/git-url-parse-rs/commit/9255fc3f0516e6cfa60c651dd0436fa702b701b1)
24+
- Pre-process urls before feeding to `url` crate
25+
- Specialized normalization rules between ssh or file path urls

Cargo.toml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@ license = "MIT"
99
name = "git-url-parse"
1010
readme = "README.md"
1111
repository = "https://github.com/tjtelan/git-url-parse-rs"
12-
version = "0.2.0"
12+
version = "0.3.0"
1313

1414
[badges.maintenance]
1515
status = "actively-developed"
1616

1717
[dependencies]
18-
log = "0.4"
19-
url = "2.1"
20-
strum = "0.18"
21-
strum_macros = "0.18"
22-
anyhow = "1.0"
23-
regex = "1.3"
18+
log = "~0.4"
19+
url = "~2.1"
20+
strum = "~0.18"
21+
strum_macros = "~0.18"
22+
anyhow = "~1.0"
23+
regex = "~1.3"
2424

2525
[dev-dependencies]
26-
env_logger = "0.7"
26+
env_logger = "~0.7"

examples/multi.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ fn main() -> Result<()> {
1616
"~/path/to/repo.git/",
1717
"./path/to/repo.git/",
1818
"./path/to/repo.git",
19+
"../test_repo",
20+
"..\\test_repo",
1921
"[email protected]:v3/CompanyName/ProjectName/RepoName",
2022
"https://[email protected]/CompanyName/ProjectName/_git/RepoName",
2123
];

src/lib.rs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,25 @@ use url::Url;
1010
#[derive(Debug, PartialEq, EnumString, EnumVariantNames, Clone, Display, Copy)]
1111
#[strum(serialize_all = "kebab_case")]
1212
pub enum Scheme {
13-
/// Represents No url scheme
14-
Unspecified,
1513
/// Represents `file://` url scheme
1614
File,
15+
/// Represents `ftp://` url scheme
16+
Ftp,
17+
/// Represents `ftps://` url scheme
18+
Ftps,
19+
/// Represents `git://` url scheme
20+
Git,
21+
/// Represents `git+ssh://` url scheme
22+
#[strum(serialize = "git+ssh")]
23+
GitSsh,
1724
/// Represents `http://` url scheme
1825
Http,
1926
/// Represents `https://` url scheme
2027
Https,
2128
/// Represents `ssh://` url scheme
2229
Ssh,
23-
/// Represents `git://` url scheme
24-
Git,
25-
/// Represents `git+ssh://` url scheme
26-
#[strum(serialize = "git+ssh")]
27-
GitSsh,
30+
/// Represents No url scheme
31+
Unspecified,
2832
}
2933

3034
/// GitUrl represents an input url that is a url used by git
@@ -244,16 +248,34 @@ impl GitUrl {
244248
}
245249
};
246250

247-
Ok(GitUrl {
248-
host: match normalized.host_str() {
251+
let final_scheme = Scheme::from_str(normalized.scheme()).expect("Scheme unsupported");
252+
253+
let final_host = match final_scheme {
254+
Scheme::File => None,
255+
_ => match normalized.host_str() {
249256
Some(h) => Some(h.to_string()),
250257
None => None,
251258
},
259+
};
260+
261+
let final_path = match final_scheme {
262+
Scheme::File => {
263+
if let Some(host) = normalized.host_str() {
264+
format!("{}{}", host, urlpath)
265+
} else {
266+
urlpath
267+
}
268+
},
269+
_ => urlpath,
270+
};
271+
272+
Ok(GitUrl {
273+
host: final_host,
252274
name: name,
253275
owner: owner,
254276
organization: organization,
255277
fullname: fullname,
256-
scheme: Scheme::from_str(normalized.scheme()).expect("Scheme unsupported"),
278+
scheme: final_scheme,
257279
user: match normalized.username().to_string().len() {
258280
0 => None,
259281
_ => Some(normalized.username().to_string()),
@@ -263,7 +285,7 @@ impl GitUrl {
263285
None => None,
264286
},
265287
port: normalized.port(),
266-
path: urlpath,
288+
path: final_path,
267289
git_suffix: *git_suffix_check,
268290
scheme_prefix: url.contains("://"),
269291
..Default::default()

tests/normalize.rs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,21 +59,74 @@ fn ssh_no_scheme_no_user() {
5959
}
6060

6161
#[test]
62-
fn file_scheme() {
62+
fn unix_file_scheme_abs_path() {
6363
let test_url = "file:///user/project-name.git";
6464
let normalized = normalize_url(test_url).expect("Normalizing url failed");
6565

6666
assert_eq!(normalized.as_str(), "file:///user/project-name.git");
6767
}
6868

6969
#[test]
70-
fn file_no_scheme() {
70+
fn unix_file_no_scheme_abs_path() {
7171
let test_url = "/user/project-name.git";
7272
let normalized = normalize_url(test_url).expect("Normalizing url failed");
7373

7474
assert_eq!(normalized.as_str(), "file:///user/project-name.git");
7575
}
7676

77+
#[test]
78+
fn unix_file_scheme_rel_path() {
79+
let test_url = "file://../user/project-name.git";
80+
let normalized = normalize_url(test_url).expect("Normalizing url failed");
81+
82+
assert_eq!(normalized.as_str(), "file://../user/project-name.git");
83+
}
84+
85+
#[test]
86+
fn unix_file_no_scheme_rel_path() {
87+
let test_url = "../user/project-name.git";
88+
let normalized = normalize_url(test_url).expect("Normalizing url failed");
89+
90+
assert_eq!(normalized.as_str(), "file://../user/project-name.git");
91+
}
92+
93+
#[should_panic(expected = "assertion failed: `(left == right)")]
94+
#[test]
95+
fn win_file_scheme_abs_path() {
96+
let test_url = "file://c:\\user\\project-name.git";
97+
let normalized = normalize_url(test_url).expect("Normalizing url failed");
98+
99+
// I actually don't know how this should be normalized.
100+
assert_eq!(normalized.as_str(), "file://c:\\user\\project-name.git");
101+
}
102+
103+
#[should_panic(expected = "assertion failed: `(left == right)")]
104+
#[test]
105+
fn win_file_no_scheme_abs_path() {
106+
let test_url = "c:\\user\\project-name.git";
107+
let normalized = normalize_url(test_url).expect("Normalizing url failed");
108+
109+
// I actually don't know how this should be normalized.
110+
assert_eq!(normalized.as_str(), "file://c:\\user\\project-name.git");
111+
}
112+
113+
#[test]
114+
fn win_file_scheme_rel_path() {
115+
let test_url = "file://..\\user\\project-name.git";
116+
let normalized = normalize_url(test_url).expect("Normalizing url failed");
117+
118+
// I actually don't know how this should be normalized.
119+
assert_eq!(normalized.as_str(), "file://../user/project-name.git");
120+
}
121+
122+
#[test]
123+
fn win_file_no_scheme_rel_path() {
124+
let test_url = "..\\user\\project-name.git";
125+
let normalized = normalize_url(test_url).expect("Normalizing url failed");
126+
127+
// I actually don't know how this should be normalized.
128+
assert_eq!(normalized.as_str(), "file://../user/project-name.git");
129+
}
77130
#[test]
78131
fn multi_git_ssh() {
79132
let test_url = "git+ssh://host.tld/user/project-name.git";

tests/parse.rs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,138 @@ fn https_user_azure_devops() {
197197

198198
assert_eq!(parsed, expected);
199199
}
200+
201+
#[test]
202+
fn ftp_user() {
203+
let test_url = "ftp://[email protected]/user/project-name.git";
204+
let parsed = GitUrl::parse(test_url).expect("URL parse failed");
205+
let expected = GitUrl {
206+
host: Some("host.tld".to_string()),
207+
name: "project-name".to_string(),
208+
owner: Some("user".to_string()),
209+
organization: None,
210+
fullname: "user/project-name".to_string(),
211+
scheme: Scheme::Ftp,
212+
user: Some("git".to_string()),
213+
token: None,
214+
port: None,
215+
path: "/user/project-name.git".to_string(),
216+
git_suffix: true,
217+
scheme_prefix: true,
218+
};
219+
220+
assert_eq!(parsed, expected);
221+
}
222+
223+
#[test]
224+
fn ftps_user() {
225+
let test_url = "ftps://[email protected]/user/project-name.git";
226+
let parsed = GitUrl::parse(test_url).expect("URL parse failed");
227+
let expected = GitUrl {
228+
host: Some("host.tld".to_string()),
229+
name: "project-name".to_string(),
230+
owner: Some("user".to_string()),
231+
organization: None,
232+
fullname: "user/project-name".to_string(),
233+
scheme: Scheme::Ftps,
234+
user: Some("git".to_string()),
235+
token: None,
236+
port: None,
237+
path: "/user/project-name.git".to_string(),
238+
git_suffix: true,
239+
scheme_prefix: true,
240+
};
241+
242+
assert_eq!(parsed, expected);
243+
}
244+
245+
#[test]
246+
fn relative_unix_path() {
247+
let test_url = "../project-name.git";
248+
let parsed = GitUrl::parse(test_url).expect("URL parse failed");
249+
let expected = GitUrl {
250+
host: None,
251+
name: "project-name".to_string(),
252+
owner: None,
253+
organization: None,
254+
fullname: "project-name".to_string(),
255+
scheme: Scheme::File,
256+
user: None,
257+
token: None,
258+
port: None,
259+
path: "../project-name.git".to_string(),
260+
git_suffix: true,
261+
scheme_prefix: false,
262+
};
263+
264+
assert_eq!(parsed, expected);
265+
}
266+
267+
#[test]
268+
fn absolute_unix_path() {
269+
let test_url = "/path/to/project-name.git";
270+
let parsed = GitUrl::parse(test_url).expect("URL parse failed");
271+
let expected = GitUrl {
272+
host: None,
273+
name: "project-name".to_string(),
274+
owner: None,
275+
organization: None,
276+
fullname: "project-name".to_string(),
277+
scheme: Scheme::File,
278+
user: None,
279+
token: None,
280+
port: None,
281+
path: "/path/to/project-name.git".to_string(),
282+
git_suffix: true,
283+
scheme_prefix: false,
284+
};
285+
286+
assert_eq!(parsed, expected);
287+
}
288+
289+
// Issue #6 - Relative Windows paths will parse into Unix paths
290+
#[test]
291+
fn relative_windows_path() {
292+
let test_url = "..\\project-name.git";
293+
let parsed = GitUrl::parse(test_url).expect("URL parse failed");
294+
let expected = GitUrl {
295+
host: None,
296+
name: "project-name".to_string(),
297+
owner: None,
298+
organization: None,
299+
fullname: "project-name".to_string(),
300+
scheme: Scheme::File,
301+
user: None,
302+
token: None,
303+
port: None,
304+
path: "../project-name.git".to_string(),
305+
git_suffix: true,
306+
scheme_prefix: false,
307+
};
308+
309+
assert_eq!(parsed, expected);
310+
}
311+
312+
// Issue #7 - Absolute Windows paths will not parse at all
313+
#[should_panic(expected = "index out of bounds: the len is 1 but the index is 1")]
314+
#[test]
315+
fn absolute_windows_path() {
316+
let test_url = "c:\\project-name.git";
317+
let parsed = GitUrl::parse(test_url).expect("URL parse failed");
318+
let expected = GitUrl {
319+
host: None,
320+
name: "project-name".to_string(),
321+
owner: None,
322+
organization: None,
323+
fullname: "project-name".to_string(),
324+
scheme: Scheme::File,
325+
user: None,
326+
token: None,
327+
port: None,
328+
path: "c:\\project-name.git".to_string(),
329+
git_suffix: true,
330+
scheme_prefix: true,
331+
};
332+
333+
assert_eq!(parsed, expected);
334+
}

0 commit comments

Comments
 (0)