Skip to content

Commit 666be44

Browse files
committed
fix: preserve GitLab subgroup paths in canonicalizeRepoUrl
Signed-off-by: anilb <epipav@gmail.com>
1 parent 77e6b6c commit 666be44

2 files changed

Lines changed: 40 additions & 4 deletions

File tree

services/apps/packages_worker/src/utils/__tests__/canonicalizeRepoUrl.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,26 @@ describe('canonicalizeRepoUrl', () => {
2929
'github',
3030
],
3131
['ssh://git@github.com:2222/foo/bar.git', 'https://github.com/foo/bar', 'github'],
32+
[
33+
'https://gitlab.com/group/subgroup/project',
34+
'https://gitlab.com/group/subgroup/project',
35+
'gitlab',
36+
],
37+
[
38+
'https://gitlab.com/group/subgroup/subsubgroup/project.git',
39+
'https://gitlab.com/group/subgroup/subsubgroup/project',
40+
'gitlab',
41+
],
42+
[
43+
'https://gitlab.com/group/project/-/tree/master/src',
44+
'https://gitlab.com/group/project',
45+
'gitlab',
46+
],
47+
[
48+
'https://gitlab.com/group/subgroup/project/-/blob/main/README.md',
49+
'https://gitlab.com/group/subgroup/project',
50+
'gitlab',
51+
],
3252
])('canonicalizes %s', (input, expectedUrl, expectedHost) => {
3353
expect(canonicalizeRepoUrl(input)).toEqual({ url: expectedUrl, host: expectedHost })
3454
})

services/apps/packages_worker/src/utils/canonicalizeRepoUrl.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ const CASE_INSENSITIVE_HOSTS = new Set(['github.com', 'gitlab.com'])
3232
* Shared across the registry sub-workers (npm, Maven, …) and the GitHub
3333
* enricher so `repos.url` keys never diverge per ADR 0001. Handles npm
3434
* shorthand (`github:owner/repo`, bare `owner/repo`), SSH scp form, `ssh://`,
35-
* `git+`, `git://`, `www.`, and monorepo `/tree/<branch>/<path>` deep-links
36-
* (only the first two path segments are kept). Returns null when the input
35+
* `git+`, `git://`, `www.`, and monorepo deep-links: GitHub/Bitbucket's bare
36+
* `/tree/<branch>/<path>` (only the first two path segments are kept) and
37+
* GitLab's `/-/tree/<branch>/<path>` (kept segments run up to the `/-/`,
38+
* preserving arbitrarily nested subgroups). Returns null when the input
3739
* cannot be reduced to an owner/name pair.
3840
*/
3941
export function canonicalizeRepoUrl(raw: string): CanonicalRepo | null {
@@ -80,8 +82,22 @@ export function canonicalizeRepoUrl(raw: string): CanonicalRepo | null {
8082
if (segments.length < 2) return null
8183

8284
const isKnownHost = hostname in HOST_ENUM
83-
let ownerPath = isKnownHost ? [segments[0]] : segments.slice(0, -1)
84-
let name = (isKnownHost ? segments[1] : segments[segments.length - 1]).replace(/\.git$/, '')
85+
// GitLab uniquely supports arbitrarily nested subgroups (group/subgroup/.../project),
86+
// unlike GitHub/Bitbucket's flat owner/repo. Its deep-link suffixes (tree, blob, issues,
87+
// merge_requests, ...) are marked off by a `/-/` path segment rather than appended
88+
// directly after the repo path, so split there instead of truncating to 2 segments.
89+
let pathSegments: string[]
90+
if (hostname === 'gitlab.com') {
91+
const dashIdx = segments.indexOf('-')
92+
pathSegments = dashIdx === -1 ? segments : segments.slice(0, dashIdx)
93+
} else if (isKnownHost) {
94+
pathSegments = segments.slice(0, 2)
95+
} else {
96+
pathSegments = segments
97+
}
98+
99+
let ownerPath = pathSegments.slice(0, -1)
100+
let name = (pathSegments[pathSegments.length - 1] ?? '').replace(/\.git$/, '')
85101
if (!name || ownerPath.length === 0 || ownerPath.some((seg) => !seg)) return null
86102

87103
if (CASE_INSENSITIVE_HOSTS.has(hostname)) {

0 commit comments

Comments
 (0)