Skip to content

Commit 3ef3ef1

Browse files
committed
refactor: remove dead parse() code from git provider adapters
This was refactored at some point long ago to use a shared `parseRepoUrl` but the old unused `parse` methods were orphaned.
1 parent fe95911 commit 3ef3ef1

1 file changed

Lines changed: 23 additions & 256 deletions

File tree

app/composables/useRepoMeta.ts

Lines changed: 23 additions & 256 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ProviderId, RepoRef } from '#shared/utils/git-providers'
2-
import { GIT_PROVIDER_API_ORIGINS, parseRepoUrl, GITLAB_HOSTS } from '#shared/utils/git-providers'
2+
import { GIT_PROVIDER_API_ORIGINS, parseRepoUrl } from '#shared/utils/git-providers'
33

44
// TTL for git repo metadata (10 minutes - repo stats don't change frequently)
55
const REPO_META_TTL = 60 * 10
@@ -88,8 +88,6 @@ type RadicleProjectResponse = {
8888
}
8989

9090
type ProviderAdapter = {
91-
id: ProviderId
92-
parse(url: URL): RepoRef | null
9391
links(ref: RepoRef): RepoMetaLinks
9492
fetchMeta(
9593
cachedFetch: CachedFetchFunction,
@@ -100,25 +98,6 @@ type ProviderAdapter = {
10098
}
10199

102100
const githubAdapter: ProviderAdapter = {
103-
id: 'github',
104-
105-
parse(url) {
106-
const host = url.hostname.toLowerCase()
107-
if (host !== 'github.com' && host !== 'www.github.com') return null
108-
109-
const parts = url.pathname.split('/').filter(Boolean)
110-
if (parts.length < 2) return null
111-
112-
const owner = decodeURIComponent(parts[0] ?? '').trim()
113-
const repo = decodeURIComponent(parts[1] ?? '')
114-
.trim()
115-
.replace(/\.git$/i, '')
116-
117-
if (!owner || !repo) return null
118-
119-
return { provider: 'github', owner, repo }
120-
},
121-
122101
links(ref) {
123102
const base = `https://github.com/${ref.owner}/${ref.repo}`
124103
return {
@@ -160,31 +139,8 @@ const githubAdapter: ProviderAdapter = {
160139
}
161140

162141
const gitlabAdapter: ProviderAdapter = {
163-
id: 'gitlab',
164-
165-
parse(url) {
166-
const host = url.hostname.toLowerCase()
167-
const isGitLab = GITLAB_HOSTS.some(h => host === h || host === `www.${h}`)
168-
if (!isGitLab) return null
169-
170-
const parts = url.pathname.split('/').filter(Boolean)
171-
if (parts.length < 2) return null
172-
173-
// GitLab supports nested groups, so we join all parts except the last as owner
174-
const repo = decodeURIComponent(parts[parts.length - 1] ?? '')
175-
.trim()
176-
.replace(/\.git$/i, '')
177-
const owner = parts
178-
.slice(0, -1)
179-
.map(p => decodeURIComponent(p).trim())
180-
.join('/')
181-
182-
if (!owner || !repo) return null
183-
184-
return { provider: 'gitlab', owner, repo, host }
185-
},
186-
187142
links(ref) {
143+
// GitLab supports nested groups, so ref.owner may contain slashes.
188144
const baseHost = ref.host ?? 'gitlab.com'
189145
const base = `https://${baseHost}/${ref.owner}/${ref.repo}`
190146
return {
@@ -224,25 +180,6 @@ const gitlabAdapter: ProviderAdapter = {
224180
}
225181

226182
const bitbucketAdapter: ProviderAdapter = {
227-
id: 'bitbucket',
228-
229-
parse(url) {
230-
const host = url.hostname.toLowerCase()
231-
if (host !== 'bitbucket.org' && host !== 'www.bitbucket.org') return null
232-
233-
const parts = url.pathname.split('/').filter(Boolean)
234-
if (parts.length < 2) return null
235-
236-
const owner = decodeURIComponent(parts[0] ?? '').trim()
237-
const repo = decodeURIComponent(parts[1] ?? '')
238-
.trim()
239-
.replace(/\.git$/i, '')
240-
241-
if (!owner || !repo) return null
242-
243-
return { provider: 'bitbucket', owner, repo }
244-
},
245-
246183
links(ref) {
247184
const base = `https://bitbucket.org/${ref.owner}/${ref.repo}`
248185
return {
@@ -281,25 +218,6 @@ const bitbucketAdapter: ProviderAdapter = {
281218
}
282219

283220
const codebergAdapter: ProviderAdapter = {
284-
id: 'codeberg',
285-
286-
parse(url) {
287-
const host = url.hostname.toLowerCase()
288-
if (host !== 'codeberg.org' && host !== 'www.codeberg.org') return null
289-
290-
const parts = url.pathname.split('/').filter(Boolean)
291-
if (parts.length < 2) return null
292-
293-
const owner = decodeURIComponent(parts[0] ?? '').trim()
294-
const repo = decodeURIComponent(parts[1] ?? '')
295-
.trim()
296-
.replace(/\.git$/i, '')
297-
298-
if (!owner || !repo) return null
299-
300-
return { provider: 'codeberg', owner, repo, host: 'codeberg.org' }
301-
},
302-
303221
links(ref) {
304222
const base = `https://codeberg.org/${ref.owner}/${ref.repo}`
305223
return {
@@ -339,25 +257,6 @@ const codebergAdapter: ProviderAdapter = {
339257
}
340258

341259
const giteeAdapter: ProviderAdapter = {
342-
id: 'gitee',
343-
344-
parse(url) {
345-
const host = url.hostname.toLowerCase()
346-
if (host !== 'gitee.com' && host !== 'www.gitee.com') return null
347-
348-
const parts = url.pathname.split('/').filter(Boolean)
349-
if (parts.length < 2) return null
350-
351-
const owner = decodeURIComponent(parts[0] ?? '').trim()
352-
const repo = decodeURIComponent(parts[1] ?? '')
353-
.trim()
354-
.replace(/\.git$/i, '')
355-
356-
if (!owner || !repo) return null
357-
358-
return { provider: 'gitee', owner, repo }
359-
},
360-
361260
links(ref) {
362261
const base = `https://gitee.com/${ref.owner}/${ref.repo}`
363262
return {
@@ -398,53 +297,9 @@ const giteeAdapter: ProviderAdapter = {
398297

399298
/**
400299
* Generic Gitea adapter for self-hosted instances.
401-
* Matches common Gitea/Forgejo hosting patterns.
300+
* Matches common Gitea hosting patterns in parseRepoUrl.
402301
*/
403302
const giteaAdapter: ProviderAdapter = {
404-
id: 'gitea',
405-
406-
parse(url) {
407-
const host = url.hostname.toLowerCase()
408-
409-
// Match common Gitea/Forgejo hosting patterns
410-
const giteaPatterns = [
411-
/^git\./i, // git.example.com
412-
/^gitea\./i, // gitea.example.com
413-
/^forgejo\./i, // forgejo.example.com
414-
/^code\./i, // code.example.com
415-
/^src\./i, // src.example.com
416-
/gitea\.io$/i, // *.gitea.io
417-
]
418-
419-
// Skip if it matches other known providers
420-
const skipHosts = [
421-
'github.com',
422-
'gitlab.com',
423-
'codeberg.org',
424-
'bitbucket.org',
425-
'gitee.com',
426-
'sr.ht',
427-
'git.sr.ht',
428-
...GITLAB_HOSTS,
429-
]
430-
if (skipHosts.some(h => host === h || host.endsWith(`.${h}`))) return null
431-
432-
// Check if matches Gitea patterns
433-
if (!giteaPatterns.some(p => p.test(host))) return null
434-
435-
const parts = url.pathname.split('/').filter(Boolean)
436-
if (parts.length < 2) return null
437-
438-
const owner = decodeURIComponent(parts[0] ?? '').trim()
439-
const repo = decodeURIComponent(parts[1] ?? '')
440-
.trim()
441-
.replace(/\.git$/i, '')
442-
443-
if (!owner || !repo) return null
444-
445-
return { provider: 'gitea', owner, repo, host }
446-
},
447-
448303
links(ref) {
449304
const base = `https://${ref.host}/${ref.owner}/${ref.repo}`
450305
return {
@@ -488,27 +343,8 @@ const giteaAdapter: ProviderAdapter = {
488343
}
489344

490345
const sourcehutAdapter: ProviderAdapter = {
491-
id: 'sourcehut',
492-
493-
parse(url) {
494-
const host = url.hostname.toLowerCase()
495-
if (host !== 'sr.ht' && host !== 'git.sr.ht') return null
496-
497-
const parts = url.pathname.split('/').filter(Boolean)
498-
if (parts.length < 2) return null
499-
500-
// Sourcehut uses ~username/repo format
501-
const owner = decodeURIComponent(parts[0] ?? '').trim()
502-
const repo = decodeURIComponent(parts[1] ?? '')
503-
.trim()
504-
.replace(/\.git$/i, '')
505-
506-
if (!owner || !repo) return null
507-
508-
return { provider: 'sourcehut', owner, repo }
509-
},
510-
511346
links(ref) {
347+
// Sourcehut uses ~username/repo format.
512348
const base = `https://git.sr.ht/${ref.owner}/${ref.repo}`
513349
return {
514350
repo: base,
@@ -531,34 +367,8 @@ const sourcehutAdapter: ProviderAdapter = {
531367
}
532368

533369
const tangledAdapter: ProviderAdapter = {
534-
id: 'tangled',
535-
536-
parse(url) {
537-
const host = url.hostname.toLowerCase()
538-
if (
539-
host !== 'tangled.sh' &&
540-
host !== 'www.tangled.sh' &&
541-
host !== 'tangled.org' &&
542-
host !== 'www.tangled.org'
543-
) {
544-
return null
545-
}
546-
547-
const parts = url.pathname.split('/').filter(Boolean)
548-
if (parts.length < 2) return null
549-
550-
// Tangled uses owner/repo format (owner is a domain-like identifier)
551-
const owner = decodeURIComponent(parts[0] ?? '').trim()
552-
const repo = decodeURIComponent(parts[1] ?? '')
553-
.trim()
554-
.replace(/\.git$/i, '')
555-
556-
if (!owner || !repo) return null
557-
558-
return { provider: 'tangled', owner, repo }
559-
},
560-
561370
links(ref) {
371+
// Tangled uses owner/repo format, where owner is a domain-like identifier.
562372
const base = `https://tangled.org/${ref.owner}/${ref.repo}`
563373
return {
564374
repo: base,
@@ -595,24 +405,8 @@ const tangledAdapter: ProviderAdapter = {
595405
}
596406

597407
const radicleAdapter: ProviderAdapter = {
598-
id: 'radicle',
599-
600-
parse(url) {
601-
const host = url.hostname.toLowerCase()
602-
if (host !== 'radicle.at' && host !== 'app.radicle.at' && host !== 'seed.radicle.at') {
603-
return null
604-
}
605-
606-
// Radicle URLs: app.radicle.at/nodes/seed.radicle.at/rad:z3nP4yT1PE3m1PxLEzr173sZtJVnT
607-
const path = url.pathname
608-
const radMatch = path.match(/rad:[a-zA-Z0-9]+/)
609-
if (!radMatch?.[0]) return null
610-
611-
// Use empty owner, store full rad: ID as repo
612-
return { provider: 'radicle', owner: '', repo: radMatch[0], host }
613-
},
614-
615408
links(ref) {
409+
// Radicle refs store the full rad: ID as repo with no owner.
616410
const base = `https://app.radicle.at/nodes/seed.radicle.at/${ref.repo}`
617411
return {
618412
repo: base,
@@ -649,32 +443,10 @@ const radicleAdapter: ProviderAdapter = {
649443
},
650444
}
651445

446+
/**
447+
* Adapter for explicit Forgejo instances.
448+
*/
652449
const forgejoAdapter: ProviderAdapter = {
653-
id: 'forgejo',
654-
655-
parse(url) {
656-
const host = url.hostname.toLowerCase()
657-
658-
// Match explicit Forgejo instances
659-
const forgejoPatterns = [/^forgejo\./i, /\.forgejo\./i]
660-
const knownInstances = ['next.forgejo.org', 'try.next.forgejo.org']
661-
662-
const isMatch = knownInstances.some(h => host === h) || forgejoPatterns.some(p => p.test(host))
663-
if (!isMatch) return null
664-
665-
const parts = url.pathname.split('/').filter(Boolean)
666-
if (parts.length < 2) return null
667-
668-
const owner = decodeURIComponent(parts[0] ?? '').trim()
669-
const repo = decodeURIComponent(parts[1] ?? '')
670-
.trim()
671-
.replace(/\.git$/i, '')
672-
673-
if (!owner || !repo) return null
674-
675-
return { provider: 'forgejo', owner, repo, host }
676-
},
677-
678450
links(ref) {
679451
const base = `https://${ref.host}/${ref.owner}/${ref.repo}`
680452
return {
@@ -715,21 +487,18 @@ const forgejoAdapter: ProviderAdapter = {
715487
},
716488
}
717489

718-
// Order matters: more specific adapters should come before generic ones
719-
const providers: readonly ProviderAdapter[] = [
720-
githubAdapter,
721-
gitlabAdapter,
722-
bitbucketAdapter,
723-
codebergAdapter,
724-
giteeAdapter,
725-
sourcehutAdapter,
726-
tangledAdapter,
727-
radicleAdapter,
728-
forgejoAdapter,
729-
giteaAdapter, // Generic Gitea adapter last as fallback for self-hosted instances
730-
] as const
731-
732-
const parseRepoFromUrl = parseRepoUrl
490+
const providers = {
491+
github: githubAdapter,
492+
gitlab: gitlabAdapter,
493+
bitbucket: bitbucketAdapter,
494+
codeberg: codebergAdapter,
495+
gitee: giteeAdapter,
496+
sourcehut: sourcehutAdapter,
497+
tangled: tangledAdapter,
498+
radicle: radicleAdapter,
499+
forgejo: forgejoAdapter,
500+
gitea: giteaAdapter,
501+
} satisfies Record<ProviderId, ProviderAdapter>
733502

734503
export function useRepoMeta(repositoryUrl: MaybeRefOrGetter<string | null | undefined>) {
735504
// Get cachedFetch in setup context (outside async handler)
@@ -738,7 +507,7 @@ export function useRepoMeta(repositoryUrl: MaybeRefOrGetter<string | null | unde
738507
const repoRef = computed(() => {
739508
const url = toValue(repositoryUrl)
740509
if (!url) return null
741-
return parseRepoFromUrl(url)
510+
return parseRepoUrl(url)
742511
})
743512

744513
const { data, pending, error, refresh } = useLazyAsyncData<RepoMeta | null>(
@@ -750,9 +519,7 @@ export function useRepoMeta(repositoryUrl: MaybeRefOrGetter<string | null | unde
750519
const ref = repoRef.value
751520
if (!ref) return null
752521

753-
const adapter = providers.find(provider => provider.id === ref.provider)
754-
if (!adapter) return null
755-
522+
const adapter = providers[ref.provider]
756523
const links = adapter.links(ref)
757524
return await adapter.fetchMeta(cachedFetch, ref, links, { signal })
758525
},

0 commit comments

Comments
 (0)