Skip to content

Commit fa8d7aa

Browse files
committed
refactor: reuse GitHub repo slug parser
1 parent a58f40d commit fa8d7aa

5 files changed

Lines changed: 27 additions & 5 deletions

File tree

src/commands/sync-parallel.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import { getSharedSkillsDir, semverDiff, SHARED_SKILLS_DIR } from '../core/share
3939
import { shutdownWorker } from '../retriv/pool.ts'
4040
import {
4141
fetchPkgDist,
42+
parseGitHubRepoSlug,
4243
parsePackageSpec,
4344
readLocalDependencies,
4445
resolvePackageDocsWithAttempts,
@@ -556,7 +557,7 @@ async function syncBaseSkill(
556557
const pkgFiles = getPkgKeyFiles(packageName, cwd, version)
557558

558559
// Write base SKILL.md
559-
const repoSlug = resolved.repoUrl?.match(/github\.com\/([^/]+\/[^/]+?)(?:\.git)?(?:[/#]|$)/)?.[1]
560+
const repoSlug = parseGitHubRepoSlug(resolved.repoUrl)
560561

561562
// Create named symlink for this package
562563
linkPkgNamed(skillDir, packageName, cwd, version)

src/commands/sync.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import { shutdownWorker } from '../retriv/pool.ts'
4545
import {
4646
fetchPkgDist,
4747
isPrerelease,
48+
parseGitHubRepoSlug,
4849
parsePackageSpec,
4950
readLocalDependencies,
5051
resolveCrateDocsWithAttempts,
@@ -460,7 +461,7 @@ async function syncSinglePackage(packageSpec: string, config: SyncConfig): Promi
460461
linkPkgNamed(skillDir, storagePackageName, cwd, version)
461462

462463
// Merge into lockfile
463-
const repoSlug = resolved.repoUrl?.match(/github\.com\/([^/]+\/[^/]+?)(?:\.git)?(?:[/#]|$)/)?.[1]
464+
const repoSlug = parseGitHubRepoSlug(resolved.repoUrl)
464465
writeLock(baseDir, skillDirName, {
465466
packageName: identityPackageName,
466467
version,
@@ -566,7 +567,7 @@ async function syncSinglePackage(packageSpec: string, config: SyncConfig): Promi
566567
const pkgFiles = getPkgKeyFiles(storagePackageName, cwd, version)
567568

568569
// Write base SKILL.md (no LLM needed)
569-
const repoSlug = resolved.repoUrl?.match(/github\.com\/([^/]+\/[^/]+?)(?:\.git)?(?:[/#]|$)/)?.[1]
570+
const repoSlug = parseGitHubRepoSlug(resolved.repoUrl)
570571

571572
// Also create named symlink for this package (skip in eject mode)
572573
if (!config.eject)
@@ -1252,7 +1253,7 @@ export async function exportPortablePrompts(packageSpec: string, opts: {
12521253
writeFileSync(join(skillDir, 'SKILL.md'), skillMd)
12531254

12541255
// Write lockfile so skilld list/update/assemble can discover this skill
1255-
const repoSlug = resolved.repoUrl?.match(/github\.com\/([^/]+\/[^/]+?)(?:\.git)?(?:[/#]|$)/)?.[1]
1256+
const repoSlug = parseGitHubRepoSlug(resolved.repoUrl)
12561257
writeLock(baseDir, skillDirName, {
12571258
packageName,
12581259
version,

src/sources/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ export {
113113
fetchText,
114114
isGitHubRepoUrl,
115115
normalizeRepoUrl,
116+
parseGitHubRepoSlug,
116117
parseGitHubUrl,
117118
parsePackageSpec,
118119
verifyUrl,

src/sources/utils.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,14 @@ export function parseGitHubUrl(url: string): { owner: string, repo: string } | n
162162
return { owner: match[1]!, repo: match[2]! }
163163
}
164164

165+
/** Parse owner/repo slug from GitHub URL */
166+
export function parseGitHubRepoSlug(url: string | undefined): string | undefined {
167+
if (!url)
168+
return undefined
169+
const parsed = parseGitHubUrl(url)
170+
return parsed ? `${parsed.owner}/${parsed.repo}` : undefined
171+
}
172+
165173
/**
166174
* Normalize git repo URL to https
167175
*/

test/unit/sources-utils.test.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, expect, it } from 'vitest'
2-
import { isGitHubRepoUrl, normalizeRepoUrl, parseGitHubUrl, parsePackageSpec } from '../../src/sources/utils'
2+
import { isGitHubRepoUrl, normalizeRepoUrl, parseGitHubRepoSlug, parseGitHubUrl, parsePackageSpec } from '../../src/sources/utils'
33

44
describe('sources/utils', () => {
55
describe('isGitHubRepoUrl', () => {
@@ -55,6 +55,17 @@ describe('sources/utils', () => {
5555
})
5656
})
5757

58+
describe('parseGitHubRepoSlug', () => {
59+
it('extracts owner/repo slug', () => {
60+
expect(parseGitHubRepoSlug('https://github.com/vuejs/vue.git#main')).toBe('vuejs/vue')
61+
})
62+
63+
it('returns undefined for missing or non-GitHub URLs', () => {
64+
expect(parseGitHubRepoSlug(undefined)).toBeUndefined()
65+
expect(parseGitHubRepoSlug('https://example.com/foo/bar')).toBeUndefined()
66+
})
67+
})
68+
5869
describe('parsePackageSpec', () => {
5970
it('parses plain package name', () => {
6071
expect(parsePackageSpec('vue')).toEqual({ name: 'vue' })

0 commit comments

Comments
 (0)