@@ -103,11 +103,11 @@ export function parseGitHubRepoForReleases(source: string): {
103103 return { owner, repo } ;
104104}
105105
106- async function fetchFromGithub (
106+ async function fetchReleaseFromGithub (
107107 owner : string ,
108108 repo : string ,
109109 ref ?: string ,
110- ) : Promise < { assets : Asset [ ] ; tag_name : string } > {
110+ ) : Promise < GithubReleaseData > {
111111 const endpoint = ref ? `releases/tags/${ ref } ` : 'releases/latest' ;
112112 const url = `https://api.github.com/repos/${ owner } /${ repo } /${ endpoint } ` ;
113113 return await fetchJson ( url ) ;
@@ -199,7 +199,7 @@ export async function checkForExtensionUpdate(
199199 }
200200 const { owner, repo } = parseGitHubRepoForReleases ( source ) ;
201201
202- const releaseData = await fetchFromGithub (
202+ const releaseData = await fetchReleaseFromGithub (
203203 owner ,
204204 repo ,
205205 installMetadata . ref ,
@@ -228,32 +228,44 @@ export async function downloadFromGitHubRelease(
228228 const { owner, repo } = parseGitHubRepoForReleases ( source ) ;
229229
230230 try {
231- const releaseData = await fetchFromGithub ( owner , repo , ref ) ;
231+ const releaseData = await fetchReleaseFromGithub ( owner , repo , ref ) ;
232232 if ( ! releaseData ) {
233233 throw new Error (
234234 `No release data found for ${ owner } /${ repo } at tag ${ ref } ` ,
235235 ) ;
236236 }
237237
238238 const asset = findReleaseAsset ( releaseData . assets ) ;
239- if ( ! asset ) {
240- // If there are no release assets, then we just clone the repo using the
241- // ref the release points to.
242- await cloneFromGit (
243- {
244- ...installMetadata ,
245- ref : releaseData . tag_name ,
246- } ,
247- destination ,
239+ let archiveUrl : string | undefined ;
240+ let isTar = false ;
241+ let isZip = false ;
242+ if ( asset ) {
243+ archiveUrl = asset . browser_download_url ;
244+ } else {
245+ if ( releaseData . tarball_url ) {
246+ archiveUrl = releaseData . tarball_url ;
247+ isTar = true ;
248+ } else if ( releaseData . zipball_url ) {
249+ archiveUrl = releaseData . zipball_url ;
250+ isZip = true ;
251+ }
252+ }
253+ if ( ! archiveUrl ) {
254+ throw new Error (
255+ `No assets found for release with tag ${ releaseData . tag_name } ` ,
248256 ) ;
249- return releaseData . tag_name ;
250257 }
251-
252- const downloadedAssetPath = path . join (
258+ let downloadedAssetPath = path . join (
253259 destination ,
254- path . basename ( asset . browser_download_url ) ,
260+ path . basename ( new URL ( archiveUrl ) . pathname ) ,
255261 ) ;
256- await downloadFile ( asset . browser_download_url , downloadedAssetPath ) ;
262+ if ( isTar && ! downloadedAssetPath . endsWith ( '.tar.gz' ) ) {
263+ downloadedAssetPath += '.tar.gz' ;
264+ } else if ( isZip && ! downloadedAssetPath . endsWith ( '.zip' ) ) {
265+ downloadedAssetPath += '.zip' ;
266+ }
267+
268+ await downloadFile ( archiveUrl , downloadedAssetPath ) ;
257269
258270 extractFile ( downloadedAssetPath , destination ) ;
259271
@@ -284,6 +296,13 @@ export async function downloadFromGitHubRelease(
284296 }
285297}
286298
299+ interface GithubReleaseData {
300+ assets : Asset [ ] ;
301+ tag_name : string ;
302+ tarball_url ?: string ;
303+ zipball_url ?: string ;
304+ }
305+
287306interface Asset {
288307 name : string ;
289308 browser_download_url : string ;
@@ -326,9 +345,7 @@ export function findReleaseAsset(assets: Asset[]): Asset | undefined {
326345 return undefined ;
327346}
328347
329- async function fetchJson (
330- url : string ,
331- ) : Promise < { assets : Asset [ ] ; tag_name : string } > {
348+ async function fetchJson < T > ( url : string ) : Promise < T > {
332349 const headers : { 'User-Agent' : string ; Authorization ?: string } = {
333350 'User-Agent' : 'gemini-cli' ,
334351 } ;
@@ -348,7 +365,7 @@ async function fetchJson(
348365 res . on ( 'data' , ( chunk ) => chunks . push ( chunk ) ) ;
349366 res . on ( 'end' , ( ) => {
350367 const data = Buffer . concat ( chunks ) . toString ( ) ;
351- resolve ( JSON . parse ( data ) as { assets : Asset [ ] ; tag_name : string } ) ;
368+ resolve ( JSON . parse ( data ) as T ) ;
352369 } ) ;
353370 } )
354371 . on ( 'error' , reject ) ;
0 commit comments