@@ -263,6 +263,85 @@ class CppReferenceExtension {
263
263
}
264
264
}
265
265
266
+ /**
267
+ * Finds the most appropriate download URL for MrDocs binaries
268
+ * from the list of releases.
269
+ *
270
+ * Each object in the `releasesInfo` array represents a release.
271
+ * Each release object contains a `tag_name` string and an `assets` array.
272
+ *
273
+ * Each asset in the `assets` array has an `updated_at` string and
274
+ * a `browser_download_url` string.
275
+ * The `updated_at` string is in the format "2024-01-01T00:00:00Z".
276
+ *
277
+ * This function sorts the releases in `releasesInfo` by the date
278
+ * of their latest asset, with the latest release first.
279
+ *
280
+ * Then it iterates over the releases and finds a download URL
281
+ * that's appropriate for the current platform. This iteration
282
+ * also goes from the latest asset to the oldest asset in the release.
283
+ *
284
+ * The first asset we find that matches the platform is the one for which
285
+ * we return the URL of the asset and the tag name of the release.
286
+ *
287
+ * We can identify if the asset is appropriate for the platform by checking
288
+ * if the asset URL ends with the appropriate suffix for the platform:
289
+ *
290
+ * - win64.7z
291
+ * - Linux.tar.gz
292
+ * - Darwin.tar.gz
293
+ *
294
+ * @param {Array<Object> } releasesInfo - The list of releases.
295
+ * @return {{downloadUrl, downloadTag} }
296
+ */
297
+ static findDownloadUrl ( releasesInfo ) {
298
+ // Sort the releases by the date of their latest asset
299
+ releasesInfo . sort ( ( a , b ) => {
300
+ const latestAssetA = a . assets . reduce ( ( latest , asset ) => {
301
+ return new Date ( asset . updated_at ) > new Date ( latest . updated_at ) ? asset : latest ;
302
+ } , a . assets [ 0 ] ) ;
303
+
304
+ const latestAssetB = b . assets . reduce ( ( latest , asset ) => {
305
+ return new Date ( asset . updated_at ) > new Date ( latest . updated_at ) ? asset : latest ;
306
+ } , b . assets [ 0 ] ) ;
307
+
308
+ return new Date ( latestAssetB . updated_at ) - new Date ( latestAssetA . updated_at ) ;
309
+ } ) ;
310
+
311
+ // Determine the appropriate suffix for the current platform
312
+ let platformSuffix ;
313
+ switch ( process . platform ) {
314
+ case 'win32' :
315
+ platformSuffix = 'win64.7z' ;
316
+ break ;
317
+ case 'linux' :
318
+ platformSuffix = 'Linux.tar.gz' ;
319
+ break ;
320
+ case 'darwin' :
321
+ platformSuffix = 'Darwin.tar.gz' ;
322
+ break ;
323
+ default :
324
+ throw new Error ( `Unsupported platform: ${ process . platform } . Supported platforms are win32, linux, and darwin.` ) ;
325
+ }
326
+
327
+ // Iterate over the releases
328
+ for ( const release of releasesInfo ) {
329
+ // Sort assets descending by updated_at
330
+ release . assets . sort ( ( a , b ) => new Date ( b . updated_at ) - new Date ( a . updated_at ) ) ;
331
+ // Iterate over the assets of the release
332
+ for ( const asset of release . assets ) {
333
+ // Check if the asset URL ends with the appropriate suffix for the platform
334
+ if ( asset . browser_download_url . endsWith ( platformSuffix ) ) {
335
+ // Return the URL of the asset and the tag name of the release
336
+ return { downloadUrl : asset . browser_download_url , downloadTag : release . tag_name } ;
337
+ }
338
+ }
339
+ }
340
+
341
+ // If no appropriate asset is found, return an empty object
342
+ return { downloadUrl : null , downloadTag : null }
343
+ }
344
+
266
345
/**
267
346
* Sets up MrDocs for the playbook.
268
347
*
@@ -305,31 +384,16 @@ class CppReferenceExtension {
305
384
const releasesResponse = await axios . get ( 'https://api.github.com/repos/cppalliance/mrdocs/releases' , { headers : apiHeaders } )
306
385
const releasesInfo = releasesResponse . data
307
386
this . logger . debug ( `Found ${ releasesInfo . length } MrDocs releases` )
308
- let downloadUrl = undefined
309
- let downloadRelease = undefined
310
- for ( const latestRelease of releasesInfo ) {
311
- this . logger . debug ( `Latest release: ${ latestRelease [ 'tag_name' ] } ` )
312
- const latestAssets = latestRelease [ 'assets' ] . map ( asset => asset [ 'browser_download_url' ] )
313
- this . logger . debug ( `Latest assets: ${ latestAssets . join ( ', ' ) } ` )
314
- const releaseFileSuffix = process . platform === "win32" ? 'win64.7z' : 'Linux.tar.gz'
315
- downloadUrl = latestAssets . find ( asset => asset . endsWith ( releaseFileSuffix ) )
316
- downloadRelease = latestRelease
317
- if ( downloadUrl ) {
318
- break
319
- }
320
- this . logger . warn ( `Could not find MrDocs binaries in ${ latestRelease [ 'tag_name' ] } release for ${ process . platform } ` )
321
- }
387
+ const { downloadUrl, downloadTag } = CppReferenceExtension . findDownloadUrl ( releasesInfo )
322
388
if ( ! downloadUrl ) {
323
389
this . logger . error ( `Could not find MrDocs binaries for ${ process . platform } ` )
324
390
process . exit ( 1 )
325
391
}
326
392
const mrdocsDownloadDir = path . join ( mrDocsTreeDir , process . platform )
327
- const releaseTagname = downloadRelease [ 'tag_name' ]
328
- const versionSubdir = releaseTagname . endsWith ( '-release' ) ? releaseTagname . slice ( 0 , - 8 ) : downloadRelease [ 'tag_name' ]
393
+ const versionSubdir = downloadTag . endsWith ( '-release' ) ? downloadTag . slice ( 0 , - 8 ) : downloadTag
329
394
const mrdocsExtractDir = path . join ( mrdocsDownloadDir , versionSubdir )
330
395
const platformExtension = process . platform === 'win32' ? '.exe' : ''
331
396
const mrdocsExecPath = path . join ( mrdocsExtractDir , 'bin' , 'mrdocs' ) + platformExtension
332
-
333
397
if ( await CppReferenceExtension . fileExists ( mrdocsExecPath ) ) {
334
398
this . logger . debug ( `MrDocs already exists at ${ mrdocsExtractDir } ` )
335
399
} else {
0 commit comments