Parse bracketed IPv6 file endpoints
ci / test (push) Canceled after 0s
ci / fuzz-smoke (push) Canceled after 0s
ci / windows-client (push) Canceled after 0s
ci / package-release (linux-x86_64, ubuntu-latest) (push) Canceled after 0s
ci / package-release (macos-aarch64, macos-14) (push) Canceled after 0s
ci / package-release (macos-x86_64, macos-13) (push) Canceled after 0s
ci / package-release (windows-x86_64, windows-latest) (push) Canceled after 0s
ci / remote-bench (push) Canceled after 0s
ci / publish-gitea-release (push) Canceled after 0s

This commit is contained in:
DuProcess
2026-07-12 23:18:31 -04:00
parent 4b82334e02
commit 17cc1f6131
2 changed files with 82 additions and 17 deletions
+51
View File
@@ -165,6 +165,12 @@ pub fn parse_copy_endpoint(raw: &str) -> CopyEndpoint {
if looks_like_windows_path(raw) {
return CopyEndpoint::Local(PathBuf::from(raw));
}
if let Some((host, path)) = parse_bracketed_remote_endpoint(raw) {
return CopyEndpoint::Remote { host, path };
}
if raw.starts_with('[') {
return CopyEndpoint::Local(PathBuf::from(raw));
}
let Some(index) = raw.find(':') else {
return CopyEndpoint::Local(PathBuf::from(raw));
};
@@ -183,6 +189,25 @@ pub fn parse_copy_endpoint(raw: &str) -> CopyEndpoint {
}
}
fn parse_bracketed_remote_endpoint(raw: &str) -> Option<(String, String)> {
let rest = raw.strip_prefix('[')?;
let close = rest.find(']')?;
let host = &rest[..close];
let suffix = &rest[close + 1..];
if host.is_empty() || host.contains('/') || host.contains('\\') || !suffix.starts_with(':') {
return None;
}
let path = &suffix[1..];
Some((
host.to_string(),
if path.is_empty() {
".".to_string()
} else {
path.to_string()
},
))
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CopyEndpoint {
Local(PathBuf),
@@ -277,4 +302,30 @@ mod tests {
CopyEndpoint::Local(PathBuf::from("C:\\Users\\palav\\x"))
);
}
#[test]
fn copy_endpoint_parses_bracketed_ipv6_remote_paths() {
assert_eq!(
parse_copy_endpoint("[2001:db8::1]:/var/log/syslog"),
CopyEndpoint::Remote {
host: "2001:db8::1".to_string(),
path: "/var/log/syslog".to_string()
}
);
assert_eq!(
parse_copy_endpoint("[::1]:"),
CopyEndpoint::Remote {
host: "::1".to_string(),
path: ".".to_string()
}
);
assert_eq!(
parse_copy_endpoint("[bad/host]:path"),
CopyEndpoint::Local(PathBuf::from("[bad/host]:path"))
);
assert_eq!(
parse_copy_endpoint("[::1]"),
CopyEndpoint::Local(PathBuf::from("[::1]"))
);
}
}