Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/utils/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ fn strip_ssh_port(url: &str) -> Option<String> {
None => (String::new(), authority),
};
// Only normalize when there's actually a port to strip.
let (host, _port) = host_port.split_once(':')?;
let host = if host_port.starts_with('[') {
// IPv6 bracketed host, e.g. `[::1]:22` — split on `]:`.
host_port.split_once("]:").map(|(h, _)| format!("{h}]"))?
} else {
host_port.rsplit_once(':').map(|(h, _)| h.to_string())?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Behavioral change from split_once to rsplit_once in non-IPv6 path

Line 50 changes from split_once(':') to rsplit_once(':'). For valid SSH authority strings like github.com:22, these are equivalent since there is exactly one colon. The only difference would arise for malformed authorities with multiple colons (e.g. host:foo:22), where split_once would yield host=host while rsplit_once yields host=host:foo. Since such authorities are not valid URL forms and cannot match GitHub's hostname anyway, this is a safe change — but it is a subtle semantic difference worth noting.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch on the semantic difference. As noted, for any well-formed SSH authority there's exactly one colon separating host from port, so split_once and rsplit_once are equivalent. The switch to rsplit_once is intentional — it's the more defensive choice for the non-IPv6 path, mirroring RFC 3986's rule that the port is the segment after the last colon in the host info. Agreed this is safe.

};
Some(format!("ssh://{user_at}{host}/{path}"))
}

Expand Down Expand Up @@ -285,6 +290,12 @@ mod tests {
);
}

#[test]
fn strip_ssh_port_handles_ipv6() {
let result = strip_ssh_port("ssh://git@[::1]:22/owner/repo.git");
assert_eq!(result, Some("ssh://git@[::1]/owner/repo.git".to_string()),);
}

#[test]
fn rejects_ssh_scheme_with_port_for_non_github_host() {
assert_eq!(
Expand Down
Loading