From a7311377451b473f3f5b13dde87684ffab909920 Mon Sep 17 00:00:00 2001 From: taskylizard <75871323+taskylizard@users.noreply.github.com> Date: Fri, 4 Sep 2026 09:49:37 +0000 Subject: [PATCH 1/4] fix: follow bare github shorthands --- shared/utils/git-providers.ts | 5 +++++ test/unit/shared/utils/git-providers.spec.ts | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/shared/utils/git-providers.ts b/shared/utils/git-providers.ts index aa92dab98a..204eca581c 100644 --- a/shared/utils/git-providers.ts +++ b/shared/utils/git-providers.ts @@ -308,6 +308,11 @@ export function normalizeGitUrl(input: string): string | null { .replace(/(\.[^./]+?):/, '$1/') // change ".com:" to ".com/" from "ssh://user@host.com:..." .replace(/^git:\/\//, 'https://') .replace(/^ssh:\/\//, 'https://') + // Bare GitHub shorthand (e.g. "repository": "owner/repo"), following npm's convention + const hostAndPath = url.split('/') + if (!url.includes('://') && hostAndPath.length === 2 && !hostAndPath[0]!.includes('.')) { + return `https://github.com/${url}` + } if (!url) return null return url.includes('://') ? url : `https://${url}` } diff --git a/test/unit/shared/utils/git-providers.spec.ts b/test/unit/shared/utils/git-providers.spec.ts index 2d7c337522..0fe2c1b9c0 100644 --- a/test/unit/shared/utils/git-providers.spec.ts +++ b/test/unit/shared/utils/git-providers.spec.ts @@ -96,6 +96,26 @@ describe('normalizeGitUrl', () => { .soft(normalizeGitUrl('github:user/repo.git#readme')) .toBe('https://github.com/user/repo#readme') }) + + it('should expand bare owner/repo GitHub shorthand', () => { + expect.soft(normalizeGitUrl('wevm/ox')).toBe('https://github.com/wevm/ox') + expect.soft(normalizeGitUrl('user/repo.git')).toBe('https://github.com/user/repo') + expect.soft(normalizeGitUrl(' user/repo ')).toBe('https://github.com/user/repo') + }) + + it('should not treat host-prefixed paths as owner/repo shorthand', () => { + expect.soft(normalizeGitUrl('git.sr.ht/~user/repo')).toBe('https://git.sr.ht/~user/repo') + expect.soft(normalizeGitUrl('example.com/user/repo')).toBe('https://example.com/user/repo') + }) + + it('should parse bare shorthand repository fields', () => { + const info = parseRepositoryInfo('wevm/ox') + expect.soft(info?.provider).toBe('github') + expect.soft(info?.owner).toBe('wevm') + expect.soft(info?.repo).toBe('ox') + expect.soft(info?.rawBaseUrl).toBe('https://raw.githubusercontent.com/wevm/ox/HEAD') + expect.soft(info?.blobBaseUrl).toBe('https://github.com/wevm/ox/blob/HEAD') + }) }) describe('parseRepositoryInfo', () => { From e18a0bff5c5f5122a9c3acc42ecce94034e6ab10 Mon Sep 17 00:00:00 2001 From: taskylizard <75871323+taskylizard@users.noreply.github.com> Date: Fri, 4 Sep 2026 15:37:05 +0530 Subject: [PATCH 2/4] Update shared/utils/git-providers.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- shared/utils/git-providers.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/shared/utils/git-providers.ts b/shared/utils/git-providers.ts index 204eca581c..cbc623a17a 100644 --- a/shared/utils/git-providers.ts +++ b/shared/utils/git-providers.ts @@ -310,7 +310,19 @@ export function normalizeGitUrl(input: string): string | null { .replace(/^ssh:\/\//, 'https://') // Bare GitHub shorthand (e.g. "repository": "owner/repo"), following npm's convention const hostAndPath = url.split('/') - if (!url.includes('://') && hostAndPath.length === 2 && !hostAndPath[0]!.includes('.')) { + const scpMatch = /^(?:[^@/]+@)?([^/:]+):(.+)$/.exec(url) + if (!url.includes('://') && scpMatch) { + const [, host, path] = scpMatch + if (host && path) url = `https://${host}/${path}` + } + + const shorthandMatch = /^([^./:?#]+)\/([^/?#:]+)([?#].*)?$/.exec(url) + if (shorthandMatch) { + const [, owner, repo, suffix] = shorthandMatch + if (owner && repo) { + return `https://github.com/${owner}/${repo}${suffix ?? ''}` + } + } return `https://github.com/${url}` } if (!url) return null From eedd2b10aaaed1f50d783c45c0456ada1be4b38f Mon Sep 17 00:00:00 2001 From: taskylizard <75871323+taskylizard@users.noreply.github.com> Date: Fri, 4 Sep 2026 12:06:01 +0000 Subject: [PATCH 3/4] [fix/follow-bare-gh-shorthands] suggestions fix --- shared/utils/git-providers.ts | 30 ++++++++++++-------- test/unit/shared/utils/git-providers.spec.ts | 12 +++++++- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/shared/utils/git-providers.ts b/shared/utils/git-providers.ts index cbc623a17a..6a834be461 100644 --- a/shared/utils/git-providers.ts +++ b/shared/utils/git-providers.ts @@ -308,23 +308,29 @@ export function normalizeGitUrl(input: string): string | null { .replace(/(\.[^./]+?):/, '$1/') // change ".com:" to ".com/" from "ssh://user@host.com:..." .replace(/^git:\/\//, 'https://') .replace(/^ssh:\/\//, 'https://') - // Bare GitHub shorthand (e.g. "repository": "owner/repo"), following npm's convention - const hostAndPath = url.split('/') - const scpMatch = /^(?:[^@/]+@)?([^/:]+):(.+)$/.exec(url) - if (!url.includes('://') && scpMatch) { - const [, host, path] = scpMatch - if (host && path) url = `https://${host}/${path}` + // SCP-style shorthand with a dotless host (e.g. "git@localhost:owner/repo"); hosts with a + // dot (e.g. "git@github.com:user/repo") are already handled by the replacements above + if (!url.includes('://')) { + const scpMatch = /^(?:[^@/]+@)?([^/:]+):(.+)$/.exec(url) + const host = scpMatch?.[1] + const path = scpMatch?.[2] + if (host && path) { + url = `https://${host}/${path}` + } } - const shorthandMatch = /^([^./:?#]+)\/([^/?#:]+)([?#].*)?$/.exec(url) - if (shorthandMatch) { - const [, owner, repo, suffix] = shorthandMatch + // Bare GitHub shorthand (e.g. "repository": "owner/repo"), following npm's convention; + // host-prefixed paths (e.g. "git.sr.ht/~user/repo") are preserved as-is + if (!url.includes('://')) { + const shorthandMatch = /^([^./?#]+)\/([^?#]*)([?#].*)?$/.exec(url) + const owner = shorthandMatch?.[1] + const repo = shorthandMatch?.[2] + const suffix = shorthandMatch?.[3] ?? '' if (owner && repo) { - return `https://github.com/${owner}/${repo}${suffix ?? ''}` + return `https://github.com/${owner}/${repo}${suffix}` } } - return `https://github.com/${url}` - } + if (!url) return null return url.includes('://') ? url : `https://${url}` } diff --git a/test/unit/shared/utils/git-providers.spec.ts b/test/unit/shared/utils/git-providers.spec.ts index 0fe2c1b9c0..84c652ad3a 100644 --- a/test/unit/shared/utils/git-providers.spec.ts +++ b/test/unit/shared/utils/git-providers.spec.ts @@ -1,4 +1,3 @@ -import { describe, expect, it } from 'vitest' import { normalizeGitUrl, parseRepositoryInfo, @@ -101,6 +100,17 @@ describe('normalizeGitUrl', () => { expect.soft(normalizeGitUrl('wevm/ox')).toBe('https://github.com/wevm/ox') expect.soft(normalizeGitUrl('user/repo.git')).toBe('https://github.com/user/repo') expect.soft(normalizeGitUrl(' user/repo ')).toBe('https://github.com/user/repo') + expect.soft(normalizeGitUrl('user/repo#readme')).toBe('https://github.com/user/repo#readme') + expect + .soft(normalizeGitUrl('user/repo?path=packages/core')) + .toBe('https://github.com/user/repo?path=packages/core') + expect + .soft(normalizeGitUrl('user/repo/tree/main')) + .toBe('https://github.com/user/repo/tree/main') + }) + + it('should convert scp-style shorthand with a dotless host', () => { + expect.soft(normalizeGitUrl('git@localhost:owner/repo')).toBe('https://localhost/owner/repo') }) it('should not treat host-prefixed paths as owner/repo shorthand', () => { From bdd9668895c7ce1b47d918c37736683efa7f40e4 Mon Sep 17 00:00:00 2001 From: taskylizard <75871323+taskylizard@users.noreply.github.com> Date: Fri, 4 Sep 2026 12:34:56 +0000 Subject: [PATCH 4/4] oops --- test/unit/shared/utils/git-providers.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/shared/utils/git-providers.spec.ts b/test/unit/shared/utils/git-providers.spec.ts index 84c652ad3a..c035dc4e65 100644 --- a/test/unit/shared/utils/git-providers.spec.ts +++ b/test/unit/shared/utils/git-providers.spec.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest' import { normalizeGitUrl, parseRepositoryInfo,