diff --git a/src/utils/git-cache.ts b/src/utils/git-cache.ts index ba38ccb..9e8a6bb 100644 --- a/src/utils/git-cache.ts +++ b/src/utils/git-cache.ts @@ -2,7 +2,7 @@ import { existsSync, mkdirSync, rmSync, readdirSync } from 'node:fs'; import { join } from 'node:path'; import { createHash } from 'node:crypto'; import { homedir, tmpdir } from 'node:os'; -import { execSync } from 'node:child_process'; +import { execFileSync } from 'node:child_process'; export interface ResolveRepoOptions { branch?: string; @@ -31,7 +31,7 @@ function isDirEmpty(dir: string): boolean { function detectDefaultBranch(url: string): string { try { - const output = execSync(`git ls-remote --symref ${url} HEAD`, { + const output = execFileSync('git', ['ls-remote', '--symref', url, 'HEAD'], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 15_000, @@ -92,7 +92,7 @@ export function resolveRepo(url: string, options: ResolveRepoOptions = {}): Reso function cloneRepo(url: string, branch: string, dir: string): void { mkdirSync(dir, { recursive: true }); - execSync(`git clone --depth 1 --branch ${branch} ${url} ${dir}`, { + execFileSync('git', ['clone', '--depth', '1', '--branch', branch, url, dir], { stdio: 'pipe', }); } diff --git a/src/utils/registry-provider.ts b/src/utils/registry-provider.ts index 0ea4257..9b041b4 100644 --- a/src/utils/registry-provider.ts +++ b/src/utils/registry-provider.ts @@ -1,6 +1,6 @@ -import { existsSync, mkdirSync, cpSync, readFileSync, writeFileSync } from 'node:fs'; +import { existsSync, mkdirSync, rmSync, cpSync, readFileSync, writeFileSync } from 'node:fs'; import { join, resolve } from 'node:path'; -import { execSync } from 'node:child_process'; +import { execFileSync } from 'node:child_process'; export interface RegistryConfig { name: string; @@ -186,22 +186,22 @@ export class GitHubProvider implements SkillRegistryProvider { // Clone and extract specific path const tmpDir = join(targetDir, '.tmp-git-clone'); try { - execSync(`git clone --depth 1 --filter=blob:none --sparse https://github.com/${repo}.git "${tmpDir}"`, { stdio: 'pipe' }); - execSync(`git -C "${tmpDir}" sparse-checkout set "${subPath}"`, { stdio: 'pipe' }); + execFileSync('git', ['clone', '--depth', '1', '--filter=blob:none', '--sparse', `https://github.com/${repo}.git`, tmpDir], { stdio: 'pipe' }); + execFileSync('git', ['-C', tmpDir, 'sparse-checkout', 'set', subPath], { stdio: 'pipe' }); const skillName = subPath.split('/').pop()!; const skillDir = join(targetDir, skillName); mkdirSync(skillDir, { recursive: true }); cpSync(join(tmpDir, subPath), skillDir, { recursive: true }); } finally { if (existsSync(tmpDir)) { - execSync(`rm -rf "${tmpDir}"`, { stdio: 'pipe' }); + rmSync(tmpDir, { recursive: true, force: true }); } } } else { // Clone entire repo as a skill const skillName = repo.split('/').pop()!; const skillDir = join(targetDir, skillName); - execSync(`git clone --depth 1 https://github.com/${repo}.git "${skillDir}"`, { stdio: 'pipe' }); + execFileSync('git', ['clone', '--depth', '1', `https://github.com/${repo}.git`, skillDir], { stdio: 'pipe' }); } } }