Skip to content

Commit 562b0c9

Browse files
committed
fix: make file:// url parsing with full backslashed path more robust on windows. (#1063)
1 parent 117357e commit 562b0c9

File tree

3 files changed

+22
-4
lines changed

3 files changed

+22
-4
lines changed

gix-url/src/parse.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,10 @@ pub(crate) fn file_url(input: &BStr, protocol_colon: usize) -> Result<crate::Url
169169
let input = input_to_utf8(input, UrlKind::Url)?;
170170
let input_after_protocol = &input[protocol_colon + "://".len()..];
171171

172-
let Some(first_slash) = input_after_protocol.find('/') else {
172+
let Some(first_slash) = input_after_protocol
173+
.find('/')
174+
.or_else(|| cfg!(windows).then(|| input_after_protocol.find('\\')).flatten())
175+
else {
173176
return Err(Error::MissingRepositoryPath {
174177
url: input.to_owned().into(),
175178
kind: UrlKind::Url,

gix-url/tests/parse/file.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use assert_matches::assert_matches;
21
use bstr::ByteSlice;
32
use gix_url::Scheme;
43

@@ -93,11 +92,19 @@ fn no_relative_paths_if_protocol() -> crate::Result {
9392
assert_url_roundtrip("file://../", url(Scheme::File, None, "..", None, b"/"))?;
9493
assert_url_roundtrip("file://./", url(Scheme::File, None, ".", None, b"/"))?;
9594
assert_url_roundtrip("file://a/", url(Scheme::File, None, "a", None, b"/"))?;
96-
assert_matches!(
95+
if cfg!(windows) {
96+
assert_eq!(
97+
gix_url::parse("file://.\\".into())?,
98+
url(Scheme::File, None, ".", None, b"\\"),
99+
"we are just as none-sensical as git here due to special handling."
100+
);
101+
} else {
102+
assert_matches::assert_matches!(
97103
gix_url::parse("file://.\\".into()),
98104
Err(gix_url::parse::Error::MissingRepositoryPath { .. }),
99105
"DEVIATION: on windows, this parses with git into something nonesensical Diag: url=file://./ Diag: protocol=file Diag: hostandport=./ Diag: path=//./"
100106
);
107+
}
101108
Ok(())
102109
}
103110

@@ -122,6 +129,15 @@ mod windows {
122129
use crate::parse::{assert_url, assert_url_roundtrip, url, url_alternate};
123130
use gix_url::Scheme;
124131

132+
#[test]
133+
fn reproduce_1063() -> crate::Result {
134+
let input = "C:\\Users\\RUNNER~1\\AppData\\Local\\Temp\\tmp.vIa4tyjv17";
135+
let url_input = "file://C:\\Users\\RUNNER~1\\AppData\\Local\\Temp\\tmp.vIa4tyjv17";
136+
assert_url(url_input, url(Scheme::File, None, None, None, input.as_bytes()))?;
137+
assert_url(input, url_alternate(Scheme::File, None, None, None, input.as_bytes()))?;
138+
Ok(())
139+
}
140+
125141
#[test]
126142
fn url_from_absolute_path() -> crate::Result {
127143
assert_url(

gix-url/tests/parse/invalid.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ fn empty_input() {
3333
fn file_missing_host_path_separator() {
3434
assert_matches!(parse("file://.."), Err(MissingRepositoryPath { .. }));
3535
assert_matches!(parse("file://."), Err(MissingRepositoryPath { .. }));
36-
assert_matches!(parse("file://.\\"), Err(MissingRepositoryPath { .. }));
3736
assert_matches!(parse("file://a"), Err(MissingRepositoryPath { .. }));
3837
}
3938

0 commit comments

Comments
 (0)