@@ -11,7 +11,7 @@ import { tmpdir } from "node:os";
1111import { isAbsolute , join , resolve } from "node:path" ;
1212
1313import type { ClassifiedRef , Logger } from "./types.js" ;
14- import { ensureDir , run , runChecked } from "./util.js" ;
14+ import { ensureDir , git , gitChecked } from "./util.js" ;
1515
1616/**
1717 * Classify a ref string. Explicit prefixes (`local:`, `github:`, `gh:`) are
@@ -95,7 +95,7 @@ const FALLBACK_REPO = "microsoft/typespec";
9595async function detectOriginRepo ( repoRoot : string | undefined , log : Logger ) : Promise < string > {
9696 if ( ! repoRoot ) return FALLBACK_REPO ;
9797 try {
98- const res = await run ( " git" , [ "remote" , "get-url" , "origin" ] , { cwd : repoRoot } ) ;
98+ const res = await git ( [ "remote" , "get-url" , "origin" ] , { cwd : repoRoot } ) ;
9999 if ( res . code === 0 ) {
100100 const parsed = parseOwnerRepoFromUrl ( res . stdout . trim ( ) ) ;
101101 if ( parsed ) return parsed ;
@@ -114,7 +114,7 @@ async function detectOriginRepo(repoRoot: string | undefined, log: Logger): Prom
114114 * origin.
115115 */
116116export async function getRemoteRepo ( repoRoot : string , remote : string ) : Promise < string | undefined > {
117- const res = await run ( " git" , [ "remote" , "get-url" , remote ] , { cwd : repoRoot } ) ;
117+ const res = await git ( [ "remote" , "get-url" , remote ] , { cwd : repoRoot } ) ;
118118 if ( res . code !== 0 ) return undefined ;
119119 return parseOwnerRepoFromUrl ( res . stdout . trim ( ) ) ;
120120}
@@ -199,21 +199,20 @@ async function cloneGithub(
199199 const cloneUrl = `https://github.com/${ repo } .git` ;
200200
201201 log . step ( `Fetching ${ repo } @${ gitRef } ` ) ;
202- // Shallow-init and fetch the requested ref.
203- await runChecked ( "git" , [ "init" , "-q" ] , { cwd : dest } ) ;
204- // Ignore failure when origin already exists (dest dir reused from a prior fetch).
205- await runChecked ( "git" , [ "remote" , "add" , "origin" , cloneUrl ] , { cwd : dest } ) . catch ( ( ) => { } ) ;
206- const fetched = await runChecked ( "git" , [ "fetch" , "--depth" , "1" , "origin" , gitRef ] , {
207- cwd : dest ,
208- } ) . catch ( ( ) => undefined ) ;
209- if ( fetched ) {
202+ // Shallow-init and configure origin once, on first creation of this dir.
203+ if ( ! existsSync ( join ( dest , ".git" ) ) ) {
204+ await gitChecked ( [ "init" , "-q" ] , { cwd : dest } ) ;
205+ await gitChecked ( [ "remote" , "add" , "origin" , cloneUrl ] , { cwd : dest } ) ;
206+ }
207+ const fetched = await git ( [ "fetch" , "--depth" , "1" , "origin" , gitRef ] , { cwd : dest } ) ;
208+ if ( fetched . code === 0 ) {
210209 // Targeted fetch resolves to FETCH_HEAD.
211- await runChecked ( "git" , [ "checkout" , "-q" , "FETCH_HEAD" ] , { cwd : dest } ) ;
210+ await gitChecked ( [ "checkout" , "-q" , "FETCH_HEAD" ] , { cwd : dest } ) ;
212211 } else {
213212 // Some servers reject bare SHA fetches; full-fetch and checkout by ref name.
214213 // `--end-of-options` prevents treating the ref as a flag.
215- await runChecked ( "git" , [ "fetch" , "origin" ] , { cwd : dest } ) ;
216- await runChecked ( "git" , [ "checkout" , "-q" , "--end-of-options" , gitRef ] , { cwd : dest } ) ;
214+ await gitChecked ( [ "fetch" , "origin" ] , { cwd : dest } ) ;
215+ await gitChecked ( [ "checkout" , "-q" , "--end-of-options" , gitRef ] , { cwd : dest } ) ;
217216 }
218217 return dest ;
219218}
@@ -233,7 +232,7 @@ async function checkoutCachedWorktree(repo: string, gitRef: string, log: Logger)
233232
234233 ensureDir ( cacheRoot ) ;
235234 log . step ( `Creating cached worktree ${ repo } @${ sha } ` ) ;
236- await runChecked ( "git" , [ "worktree" , "add" , "--detach" , dest , sha ] , { cwd : cacheRepo } ) ;
235+ await gitChecked ( [ "worktree" , "add" , "--detach" , dest , sha ] , { cwd : cacheRepo } ) ;
237236 return dest ;
238237}
239238
@@ -242,21 +241,19 @@ async function ensureCacheRepo(repo: string, _log: Logger): Promise<string> {
242241 const gitDir = join ( repoRoot , ".git" ) ;
243242 const cloneUrl = `https://github.com/${ repo } .git` ;
244243
244+ // Init and configure origin once, on first creation of the cache repo.
245245 if ( ! existsSync ( gitDir ) ) {
246- await runChecked ( "git" , [ "init" , "-q" ] , { cwd : repoRoot } ) ;
246+ await gitChecked ( [ "init" , "-q" ] , { cwd : repoRoot } ) ;
247+ await gitChecked ( [ "remote" , "add" , "origin" , cloneUrl ] , { cwd : repoRoot } ) ;
247248 }
248-
249- // Ensure remote points at the expected repo, without failing if it already exists.
250- await runChecked ( "git" , [ "remote" , "add" , "origin" , cloneUrl ] , { cwd : repoRoot } ) . catch ( ( ) => { } ) ;
251- await runChecked ( "git" , [ "remote" , "set-url" , "origin" , cloneUrl ] , { cwd : repoRoot } ) ;
252249 return repoRoot ;
253250}
254251
255252async function fetchAndResolveCommit ( cacheRepo : string , gitRef : string ) : Promise < string > {
256253 // Resolve an immutable commit SHA from FETCH_HEAD.
257- await runChecked ( "git" , [ "fetch" , "--depth" , "1" , "origin" , gitRef ] , { cwd : cacheRepo } ) ;
254+ await gitChecked ( [ "fetch" , "--depth" , "1" , "origin" , gitRef ] , { cwd : cacheRepo } ) ;
258255 const sha = (
259- await runChecked ( "git" , [ "rev-parse" , "--verify" , "FETCH_HEAD" ] , { cwd : cacheRepo } )
256+ await gitChecked ( [ "rev-parse" , "--verify" , "FETCH_HEAD" ] , { cwd : cacheRepo } )
260257 ) . stdout . trim ( ) ;
261258 if ( ! sha ) {
262259 throw new Error ( `Could not resolve git ref '${ gitRef } ' from FETCH_HEAD.` ) ;
0 commit comments