diff --git a/electron/__tests__/review-source.test.ts b/electron/__tests__/review-source.test.ts index d7a0e4be..9b2f078f 100644 --- a/electron/__tests__/review-source.test.ts +++ b/electron/__tests__/review-source.test.ts @@ -3,7 +3,12 @@ import { expect, test } from 'vite-plus/test'; const require = createRequire(import.meta.url); -const { parseReviewUrl } = require('../review-source.cjs') as { +const { parseRemoteUrl, parseReviewUrl } = require('../review-source.cjs') as { + parseRemoteUrl: (value: string) => { + host: string; + projectPath: string; + provider: 'github' | 'gitlab'; + } | null; parseReviewUrl: (value: string) => { host: string; number: number; @@ -129,3 +134,32 @@ test('parseReviewUrl rejects values that are not review URLs', () => { expect(parseReviewUrl(value)).toBe(null); } }); + +test('parseRemoteUrl drops a custom port from `ssh://` remotes', () => { + expect(parseRemoteUrl('ssh://git@gitlab.example.com:2222/group/project.git')).toEqual({ + host: 'gitlab.example.com', + projectPath: 'group/project', + provider: 'gitlab', + }); +}); + +test('parseRemoteUrl keeps an explicit port on `https://` remotes', () => { + expect(parseRemoteUrl('https://gitlab.example.com:8443/group/subgroup/project.git')).toEqual({ + host: 'gitlab.example.com:8443', + projectPath: 'group/subgroup/project', + provider: 'gitlab', + }); +}); + +test('parseRemoteUrl reads scp-style and GitHub remotes', () => { + expect(parseRemoteUrl('git@gitlab.example.com:group/project.git')).toEqual({ + host: 'gitlab.example.com', + projectPath: 'group/project', + provider: 'gitlab', + }); + expect(parseRemoteUrl('https://github.com/nkzw-tech/codiff.git')).toEqual({ + host: 'github.com', + projectPath: 'nkzw-tech/codiff', + provider: 'github', + }); +}); diff --git a/electron/review-source.cjs b/electron/review-source.cjs index 8e7f6536..0e51d270 100644 --- a/electron/review-source.cjs +++ b/electron/review-source.cjs @@ -106,7 +106,10 @@ const parseRemoteUrl = (value) => { const projectPath = url.pathname.replaceAll(/^\/+|\.git$/gi, ''); return projectPath ? { - host: url.host.toLowerCase(), + // A custom SSH port (`ssh://git@host:2222/...`) is transport detail, not part + // of the instance identifier, and glab's `--hostname` rejects `host:port` — + // strip it. An explicit port on `https://` remotes stays: it identifies the instance. + host: (url.protocol === 'ssh:' ? url.hostname : url.host).toLowerCase(), projectPath, provider: /** @type {ReviewProvider} */ ( url.hostname.toLowerCase() === 'github.com' ? 'github' : 'gitlab' @@ -175,6 +178,7 @@ const resolveReviewUrl = (repositoryPath, number, provider) => { }; module.exports = { + parseRemoteUrl, parseReviewUrl, readReviewRemotes, resolveReviewUrl,