Skip to content

fix(forge): parse userless scp remotes like git does and match hosts case-insensitively - #1135

Merged
BryanFRD merged 1 commit into
mainfrom
fix/extract-host-scp-case
Sep 22, 2026
Merged

BryanFRD merged 1 commit into
mainfrom
fix/extract-host-scp-case

Conversation

@BryanFRD

Copy link
Copy Markdown
Contributor

Closes #1133. Follow-up to the review on #1132.

extract_host only understood the scp form (user@host:path) when an @ was present. #1132 routed forge detection through it, so github.com:owner/repo.git (valid git syntax, no user) stopped resolving. It now follows git's own rule (url_is_local_not_ssh in connect.c): without ://, a URL is scp-style when the part before the first : contains no / and is not a Windows drive letter. The host is that part with any user@ removed.

That also fixes git@gitlab.com:group/app@v2.git, where the old rsplit('@') took the host from after the last @.

valid_host now lowercases, so https://GitHub.com/o/r.git detects GitHub. Every consumer of the host (forge detection, probe cache key, API base URL, messages) gets the canonical form.

Tests

  • github.com:owner/repo.git has host github.com and detects GitHub
  • an @ in the scp path does not move the host
  • local paths have no host: C:\repos\app.git, C:/repos/app.git, /srv/git/app.git, ../app.git, ./dir:with-colon/app.git, file:///...
  • mixed-case hosts match

The existing extract_host and detect_forge_from_url cases pass unchanged. Full suite: 2476 passed.

The other point from that review, GITHUB_TOKEN going to any remote not recognised as GitLab, changes who receives which credential, so it is filed separately as #1134 rather than folded in here.

@BryanFRD
BryanFRD enabled auto-merge (squash) September 22, 2026 08:23

@ferrfleet ferrfleet Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The scp branch matches git's url_is_local_not_ssh (no ://, no / before the first :, not a drive letter), and taking the host from rsplit('@') on the pre-colon authority is what fixes group/app@v2.git. Lowercasing in valid_host reaches every consumer that matters: the SaaS suffix match, the probe cache key, api_base in build_forge, web_base_url. I could not run the suite (no cargo in this environment), but I traced each new case by hand and they hold, including file:///... falling out of the :// branch with an empty authority.

Nit: extract_repo_slug was not brought along. It still requires an @ for the scp form and still matches hosts case-sensitively, so codeberg.org:owner/repo.git and Git.Corp.com:team/app.git now resolve a host but no slug, and forge_target still fails with UnknownForge. Only github.com and gitlab.com escape that, via the hardcoded prefix loop at the top of the function. Reusing the same rule for the slug's path split, instead of the url.contains('@') && url.contains(':') test, would make the two functions agree on what an scp URL is. Not blocking: those remotes were equally broken before this PR.

Nit: is_dos_drive applies on every platform, whereas git's has_dos_drive_prefix is compiled to 0 off Windows, so real git on Linux reads C:/repos/app.git as ssh to host c. The divergence is the safer direction and I would keep it, but the PR body says it follows git's rule, so it is worth a comment on the function.

@BryanFRD
BryanFRD merged commit 09ac061 into main Sep 22, 2026
30 checks passed
@BryanFRD
BryanFRD deleted the fix/extract-host-scp-case branch September 22, 2026 08:26
@BryanFRD

Copy link
Copy Markdown
Contributor Author

On is_dos_drive: right, git only honours the drive-letter exception on Windows, so on Linux C:/repos/app.git is ssh to host c there and a local path here. Keeping the safer direction on purpose. The repo takes no code comments, so recording it here instead: the rule matches git's url_is_local_not_ssh except that the drive-letter exclusion applies on every platform. The extract_repo_slug alignment is noted for a follow-up.

ferrflow Bot added a commit that referenced this pull request Sep 22, 2026
## [7.23.1] - 2026-09-22

### Bug Fixes

- fix(forge): parse the repo slug with the same remote rule as the host (#1137)
- fix(forge): parse userless scp remotes like git does and match hosts case-insensitively (#1135)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(forge): scp remotes without a user lose their host, and host matching is case-sensitive

1 participant