feat: use GitHub API to find a matching MinGW releases

This commit is contained in:
Amin Yahyaabadi 2024-09-03 03:42:37 -07:00
parent 81c10d4abc
commit 11fad2b093
No known key found for this signature in database
GPG Key ID: F52AF77F636088F0
19 changed files with 423 additions and 107 deletions

View File

@ -9,7 +9,8 @@
"**/.venv/",
"**/.*cache/",
"coverage/",
"**/coverage/"
"**/coverage/",
"**/github_brechtsanders_winlibs_mingw.json"
],
"ignoreUnknown": true
},

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -37,6 +37,7 @@
"./.cache/",
"**/build",
"**/dist",
"**/github_brechtsanders_winlibs_mingw.json",
"dev/cpp_vcpkg_project"
],
"plugins": [

View File

@ -33,9 +33,7 @@
"build.modern": "shx cp -r ./dist/actions/* ./dist/modern",
"bump": "ncu -u -x numerous,execa,prettier,@types/node,eslint,@types/eslint && pnpm update && pnpx typesync && pnpm run clean",
"clean": "shx rm -rf ./dist ./packages/*/dist ./exe ./.parcel-cache && shx mkdir -p ./dist/legacy ./dist/actions ./dist/modern ",
"copy.matchers": "run-p copy.matchers.legacy copy.matchers.actions",
"copy.matchers.legacy": "shx cp ./src/gcc/gcc_matcher.json ./dist/legacy/ && shx cp ./src/msvc/msvc_matcher.json ./dist/legacy/ && shx cp ./src/python/python_matcher.json ./dist/legacy/ && shx cp ./src/llvm/llvm_matcher.json ./dist/legacy/",
"copy.matchers.actions": "shx cp ./src/gcc/gcc_matcher.json ./dist/actions/ && shx cp ./src/msvc/msvc_matcher.json ./dist/actions/ && shx cp ./src/python/python_matcher.json ./dist/actions/ && shx cp ./src/llvm/llvm_matcher.json ./dist/actions/",
"copy.matchers": "shx cp ./src/*/*.json ./dist/legacy/ && shx cp ./dist/legacy/*.json ./dist/actions",
"dev.parcel": "cross-env NODE_ENV=development parcel watch",
"dev.packages": "turbo dev",
"dev": "run-p dev.packages dev.parcel",
@ -67,6 +65,12 @@
"@babel/plugin-transform-private-methods": "^7.25.4",
"@biomejs/biome": "^1.8.3",
"@iarna/toml": "^2.2.5",
"@octokit/core": "^6.1.2",
"@octokit/openapi-types": "^22.2.0",
"@octokit/plugin-paginate-rest": "^11.3.3",
"@octokit/plugin-rest-endpoint-methods": "^13.2.4",
"@octokit/rest": "^21.0.2",
"@octokit/types": "^13.5.0",
"@shockpkg/archive-files": "github:aminya/archive-files#54ec59fad46aca736ac6feb6c7bb526528141b9d",
"@swc/jest": "^0.2.36",
"@types/cross-spawn": "^6.0.6",
@ -115,6 +119,7 @@
"prettier-config-atomic": "^4.0.0",
"readme-md-generator": "^1.0.0",
"retry-as-promised": "^7.0.4",
"safe-stable-stringify": "^2.5.0",
"semver": "7.6.3",
"setup-apt": "workspace:*",
"setup-brew": "workspace:*",

View File

@ -40,6 +40,24 @@ importers:
'@iarna/toml':
specifier: ^2.2.5
version: 2.2.5
'@octokit/core':
specifier: ^6.1.2
version: 6.1.2
'@octokit/openapi-types':
specifier: ^22.2.0
version: 22.2.0
'@octokit/plugin-paginate-rest':
specifier: ^11.3.3
version: 11.3.3(@octokit/core@6.1.2)
'@octokit/plugin-rest-endpoint-methods':
specifier: ^13.2.4
version: 13.2.4(@octokit/core@6.1.2)
'@octokit/rest':
specifier: ^21.0.2
version: 21.0.2
'@octokit/types':
specifier: ^13.5.0
version: 13.5.0
'@shockpkg/archive-files':
specifier: github:aminya/archive-files#54ec59fad46aca736ac6feb6c7bb526528141b9d
version: https://codeload.github.com/aminya/archive-files/tar.gz/54ec59fad46aca736ac6feb6c7bb526528141b9d
@ -184,6 +202,9 @@ importers:
retry-as-promised:
specifier: ^7.0.4
version: 7.0.4
safe-stable-stringify:
specifier: ^2.5.0
version: 2.5.0
semver:
specifier: 7.6.3
version: 7.6.3
@ -1227,6 +1248,58 @@ packages:
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'}
'@octokit/auth-token@5.1.1':
resolution: {integrity: sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==}
engines: {node: '>= 18'}
'@octokit/core@6.1.2':
resolution: {integrity: sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg==}
engines: {node: '>= 18'}
'@octokit/endpoint@10.1.1':
resolution: {integrity: sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==}
engines: {node: '>= 18'}
'@octokit/graphql@8.1.1':
resolution: {integrity: sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==}
engines: {node: '>= 18'}
'@octokit/openapi-types@22.2.0':
resolution: {integrity: sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==}
'@octokit/plugin-paginate-rest@11.3.3':
resolution: {integrity: sha512-o4WRoOJZlKqEEgj+i9CpcmnByvtzoUYC6I8PD2SA95M+BJ2x8h7oLcVOg9qcowWXBOdcTRsMZiwvM3EyLm9AfA==}
engines: {node: '>= 18'}
peerDependencies:
'@octokit/core': '>=6'
'@octokit/plugin-request-log@5.3.1':
resolution: {integrity: sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==}
engines: {node: '>= 18'}
peerDependencies:
'@octokit/core': '>=6'
'@octokit/plugin-rest-endpoint-methods@13.2.4':
resolution: {integrity: sha512-gusyAVgTrPiuXOdfqOySMDztQHv6928PQ3E4dqVGEtOvRXAKRbJR4b1zQyniIT9waqaWk/UDaoJ2dyPr7Bk7Iw==}
engines: {node: '>= 18'}
peerDependencies:
'@octokit/core': '>=6'
'@octokit/request-error@6.1.4':
resolution: {integrity: sha512-VpAhIUxwhWZQImo/dWAN/NpPqqojR6PSLgLYAituLM6U+ddx9hCioFGwBr5Mi+oi5CLeJkcAs3gJ0PYYzU6wUg==}
engines: {node: '>= 18'}
'@octokit/request@9.1.3':
resolution: {integrity: sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA==}
engines: {node: '>= 18'}
'@octokit/rest@21.0.2':
resolution: {integrity: sha512-+CiLisCoyWmYicH25y1cDfCrv41kRSvTq6pPWtRroRJzhsCZWZyCqGyI8foJT5LmScADSwRAnr/xo+eewL04wQ==}
engines: {node: '>= 18'}
'@octokit/types@13.5.0':
resolution: {integrity: sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==}
'@parcel/bundler-default@2.12.0':
resolution: {integrity: sha512-3ybN74oYNMKyjD6V20c9Gerdbh7teeNvVMwIoHIQMzuIFT6IGX53PyOLlOKRLbjxMc0TMimQQxIt2eQqxR5LsA==}
engines: {node: '>= 12.0.0', parcel: ^2.12.0}
@ -2122,6 +2195,9 @@ packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
before-after-hook@3.0.2:
resolution: {integrity: sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==}
binary-extensions@2.3.0:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
@ -4800,6 +4876,10 @@ packages:
resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==}
engines: {node: '>= 0.4'}
safe-stable-stringify@2.5.0:
resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
engines: {node: '>=10'}
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
@ -5300,6 +5380,9 @@ packages:
unist-util-stringify-position@4.0.0:
resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
universal-user-agent@7.0.2:
resolution: {integrity: sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==}
universalify@2.0.1:
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
engines: {node: '>= 10.0.0'}
@ -6509,6 +6592,67 @@ snapshots:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.17.1
'@octokit/auth-token@5.1.1': {}
'@octokit/core@6.1.2':
dependencies:
'@octokit/auth-token': 5.1.1
'@octokit/graphql': 8.1.1
'@octokit/request': 9.1.3
'@octokit/request-error': 6.1.4
'@octokit/types': 13.5.0
before-after-hook: 3.0.2
universal-user-agent: 7.0.2
'@octokit/endpoint@10.1.1':
dependencies:
'@octokit/types': 13.5.0
universal-user-agent: 7.0.2
'@octokit/graphql@8.1.1':
dependencies:
'@octokit/request': 9.1.3
'@octokit/types': 13.5.0
universal-user-agent: 7.0.2
'@octokit/openapi-types@22.2.0': {}
'@octokit/plugin-paginate-rest@11.3.3(@octokit/core@6.1.2)':
dependencies:
'@octokit/core': 6.1.2
'@octokit/types': 13.5.0
'@octokit/plugin-request-log@5.3.1(@octokit/core@6.1.2)':
dependencies:
'@octokit/core': 6.1.2
'@octokit/plugin-rest-endpoint-methods@13.2.4(@octokit/core@6.1.2)':
dependencies:
'@octokit/core': 6.1.2
'@octokit/types': 13.5.0
'@octokit/request-error@6.1.4':
dependencies:
'@octokit/types': 13.5.0
'@octokit/request@9.1.3':
dependencies:
'@octokit/endpoint': 10.1.1
'@octokit/request-error': 6.1.4
'@octokit/types': 13.5.0
universal-user-agent: 7.0.2
'@octokit/rest@21.0.2':
dependencies:
'@octokit/core': 6.1.2
'@octokit/plugin-paginate-rest': 11.3.3(@octokit/core@6.1.2)
'@octokit/plugin-request-log': 5.3.1(@octokit/core@6.1.2)
'@octokit/plugin-rest-endpoint-methods': 13.2.4(@octokit/core@6.1.2)
'@octokit/types@13.5.0':
dependencies:
'@octokit/openapi-types': 22.2.0
'@parcel/bundler-default@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)':
dependencies:
'@parcel/diagnostic': 2.12.0
@ -7852,6 +7996,8 @@ snapshots:
base64-js@1.5.1: {}
before-after-hook@3.0.2: {}
binary-extensions@2.3.0:
optional: true
@ -11119,6 +11265,8 @@ snapshots:
es-errors: 1.3.0
is-regex: 1.1.4
safe-stable-stringify@2.5.0: {}
safer-buffer@2.1.2: {}
sax@1.4.1: {}
@ -11652,6 +11800,8 @@ snapshots:
dependencies:
'@types/unist': 3.0.3
universal-user-agent@7.0.2: {}
universalify@2.0.1: {}
update-browserslist-db@1.1.0(browserslist@4.23.3):

14
src/gcc/assets-list.ts Normal file
View File

@ -0,0 +1,14 @@
import { saveGitHubAssetList } from "../utils/github/fetch-assets.ts"
/**
* Generate the list of all releases of a GitHub repository and save it to a json file
*/
async function main() {
// https://github.com/brechtsanders/winlibs_mingw/releases
await saveGitHubAssetList("brechtsanders", "winlibs_mingw", "./src/gcc/github_brechtsanders_winlibs_mingw.json")
}
main().catch((err) => {
console.error(err)
process.exit(1)
})

View File

@ -14,64 +14,34 @@ import { setupMacOSSDK } from "../macos-sdk/macos-sdk.js"
import { hasDnf } from "../utils/env/hasDnf.js"
import { isArch } from "../utils/env/isArch.js"
import { isUbuntu } from "../utils/env/isUbuntu.js"
import { loadGitHubAssetList, matchAsset } from "../utils/github/load-assets.js"
import { extract7Zip } from "../utils/setup/extract.js"
import { type InstallationInfo, type PackageInfo, setupBin } from "../utils/setup/setupBin.js"
import { setupChocoPack } from "../utils/setup/setupChocoPack.js"
import { setupDnfPack } from "../utils/setup/setupDnfPack.js"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack.js"
interface MingwInfo {
releaseName: string
fileSuffix: string
}
// https://github.com/brechtsanders/winlibs_mingw/releases
const GccToMingwInfo = {
"13": { releaseName: "13.2.0-16.0.6-11.0.0-ucrt-r1", fileSuffix: "13.2.0-mingw-w64ucrt-11.0.0-r1" },
"13.2-ucrt": { releaseName: "13.2.0-16.0.6-11.0.0-ucrt-r1", fileSuffix: "13.2.0-mingw-w64ucrt-11.0.0-r1" },
"13.2-ucrt-mcf": { releaseName: "13.2.0mcf-16.0.6-11.0.1-ucrt-r2", fileSuffix: "13.2.0-mingw-w64ucrt-11.0.1-r2" },
"13.2-msvcrt": { releaseName: "13.2.0-16.0.6-11.0.1-msvcrt-r1", fileSuffix: "13.2.0-mingw-w64msvcrt-11.0.1-r1" },
"13.1-ucrt": { releaseName: "13.1.0posix-16.0.3-11.0.0-ucrt-r1", fileSuffix: "13.1.0-mingw-w64ucrt-11.0.0-r1" },
"13.1-msvcrt": { releaseName: "13.1.0posix-16.0.3-11.0.0-msvcrt-r1", fileSuffix: "13.1.0-mingw-w64msvcrt-11.0.0-r1" },
"12": { releaseName: "12.3.0-16.0.4-11.0.0-ucrt-r1", fileSuffix: "12.3.0-mingw-w64ucrt-11.0.0-r1" },
"12.3.0-ucrt": { releaseName: "12.3.0-16.0.4-11.0.0-ucrt-r1", fileSuffix: "12.3.0-mingw-w64ucrt-11.0.0-r1" },
"12.3.0-msvcrt": { releaseName: "12.3.0-16.0.4-11.0.0-msvcrt-r1", fileSuffix: "12.3.0-mingw-w64msvcrt-11.0.0-r1" },
"12.2.0-ucrt": { releaseName: "12.2.0-14.0.6-10.0.0-ucrt-r2", fileSuffix: "12.2.0-mingw-w64ucrt-10.0.0-r2" },
"12.2.0-msvcrt": { releaseName: "12.2.0-14.0.6-10.0.0-msvcrt-r2", fileSuffix: "12.2.0-mingw-w64msvcrt-10.0.0-r2" },
"12.1.0-ucrt": { releaseName: "12.1.0-14.0.4-10.0.0-ucrt-r2", fileSuffix: "12.1.0-mingw-w64ucrt-10.0.0-r2" },
"12.1.0-msvcrt": {
releaseName: "12.1.0-14.0.6-10.0.0-msvcrt-r3",
fileSuffix: "12.1.0-llvm-14.0.6-mingw-w64msvcrt-10.0.0-r3",
},
"11": { releaseName: "11.3.0-14.0.3-10.0.0-ucrt-r3", fileSuffix: "11.3.0-mingw-w64ucrt-10.0.0-r3" },
"11.3.0-ucrt": { releaseName: "11.3.0-14.0.3-10.0.0-ucrt-r3", fileSuffix: "11.3.0-mingw-w64ucrt-10.0.0-r3" },
"11.3.0-msvcrt": { releaseName: "11.3.0-14.0.3-10.0.0-msvcrt-r3", fileSuffix: "11.3.0-mingw-w64msvcrt-10.0.0-r3" },
"11.2.0-ucrt": { releaseName: "11.2.0-9.0.0-ucrt-r5", fileSuffix: "11.2.0-mingw-w64ucrt-9.0.0-r5" },
"11.2.0-msvcrt": { releaseName: "11.2.0-9.0.0-msvcrt-r5", fileSuffix: "11.2.0-mingw-w64msvcrt-9.0.0-r5" },
"10": { releaseName: "10.5.0-11.0.1-msvcrt-r1", fileSuffix: "10.5.0-mingw-w64msvcrt-11.0.1-r1" },
"10.5.0-msvcrt": { releaseName: "10.5.0-11.0.1-msvcrt-r1", fileSuffix: "10.5.0-mingw-w64msvcrt-11.0.1-r1" },
"10.3.0": { releaseName: "10.3.0-12.0.0-9.0.0-r2", fileSuffix: "10.3.0-llvm-12.0.0-mingw-w64-9.0.0-r2" },
"10.2.0": { releaseName: "10.2.0-7.0.0-r4", fileSuffix: "10.2.0-llvm-10.0.1-mingw-w64-7.0.0-r4" },
"9": { releaseName: "9.4.0-9.0.0-r1", fileSuffix: "9.4.0-mingw-w64-9.0.0-r1" },
"9.4.0": { releaseName: "9.4.0-9.0.0-r1", fileSuffix: "9.4.0-mingw-w64-9.0.0-r1" },
} as Record<string, MingwInfo | undefined>
function getGccPackageInfo(version: string, platform: NodeJS.Platform, arch: string): PackageInfo {
async function getGccPackageInfo(version: string, platform: NodeJS.Platform, arch: string): Promise<PackageInfo> {
switch (platform) {
case "win32": {
const mingwInfo = GccToMingwInfo[version]
if (mingwInfo === undefined) {
throw new Error(`mingw version ${version} is not supported`)
}
const mingwArch = arch === "ia32" ? "i686" : "x86_64"
const exceptionModel: "seh" | "dwarf" = "seh" // SEH is native windows exception model https://github.com/brechtsanders/winlibs_mingw/issues/4#issuecomment-599296483
const mingwAssets = await loadGitHubAssetList(
join(__dirname, "github_brechtsanders_winlibs_mingw.json"),
)
const asset = matchAsset(
mingwAssets,
{
version,
arch,
filterName: (name) => name.endsWith(".7z"),
},
)
return {
binRelativeDir: "bin/",
binFileName: addExeExt("g++"),
extractedFolderName: "mingw64",
extractFunction: extract7Zip,
url:
`https://github.com/brechtsanders/winlibs_mingw/releases/download/${mingwInfo.releaseName}/winlibs-${mingwArch}-posix-${exceptionModel}-gcc-${mingwInfo.fileSuffix}.7z`,
url: `https://github.com/brechtsanders/winlibs_mingw/releases/download/${asset.tag}/${asset.name}`,
}
}
default:
@ -110,7 +80,7 @@ export async function setupGcc(version: string, setupDir: string, arch: string,
{ name: "libstdc++-devel" },
])
} else if (isUbuntu()) {
if (version === undefined) {
if (version === "") {
// the default version
installationInfo = await installAptPack([{ name: "gcc" }, { name: "g++" }])
} else {
@ -136,7 +106,7 @@ export async function setupGcc(version: string, setupDir: string, arch: string,
if (isArch()) {
await setupPacmanPack("gcc-multilib", version)
} else if (isUbuntu()) {
if (version === undefined) {
if (version === "") {
// the default version
await installAptPack([{ name: "gcc-multilib" }])
} else {

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,79 @@
import { Octokit } from "@octokit/rest"
import { writeFile } from "fs/promises"
import JsonStringify from "safe-stable-stringify"
import { type Assets, compareTag } from "./load-assets.ts"
/**
* Get the list of all releases of a GitHub repository
* @param owner The owner of the repository
* @param repo The name of the repository
* @param prerelease Whether to include prereleases
*/
async function fetchGitHubAssetList(owner: string, repo: string, prerelease = false) {
const octokit = new Octokit({
auth: process.env.GITHUB_TOKEN,
})
const assets: Assets = {}
for (let page = 1; page !== 101; page++) {
console.log(`Fetching page ${page}`)
try {
/* eslint-disable no-await-in-loop */
const res = await octokit.repos.listReleases({
owner,
repo,
per_page: 100, // maximum supported by GitHub API
page,
})
if (res.data.length === 0) {
break
}
for (const release of res.data) {
if (release.draft) {
continue
}
if (!prerelease && release.prerelease) {
continue
}
if (!(release.tag_name in assets)) {
assets[release.tag_name] = []
}
const assets_ref = assets[release.tag_name]
for (const asset of release.assets) {
assets_ref.push(asset.name)
}
}
} catch (err) {
console.error(err)
break
}
}
return assets
}
/**
* Save the list of all releases of a GitHub repository to a json file
*/
export async function saveGitHubAssetList(
owner: string,
repo: string,
path: string,
) {
const assets = await fetchGitHubAssetList(owner, repo)
const jsonStringify = JsonStringify.configure({
deterministic: compareTag,
})
const data = jsonStringify(assets)
// write the assets to a json file
await writeFile(path, data)
}

View File

@ -0,0 +1,93 @@
import { readFile } from "fs/promises"
import coerce from "semver/functions/coerce.js"
/**
* The list of assets of a GitHub release
* @key tag The tag of the release
* @value assets The names of the assets of the release
*/
export type Assets = Record<string, string[]>
export function compareTag(tag1: string, tag2: string) {
const v1 = coerce(tag1)
const v2 = coerce(tag2)
if (v1 !== null && v2 !== null) {
// put the latest version first
return v2.compare(v1)
}
// if the tags are not semver, compare them as strings, putting the latest tag first
return tag2.localeCompare(tag1)
}
export async function loadGitHubAssetList(path: string): Promise<Assets> {
const data = await readFile(path, "utf-8")
return JSON.parse(data)
}
type MatchAssetOpts = {
version: string
arch?: string
filterTag?: (version: string) => boolean
filterName?: (asset: string) => boolean
}
/**
* Match the asset that matches the version and arch
*/
export function matchAsset(
assets: Assets,
opts: MatchAssetOpts,
): { tag: string; name: string } {
// get the list of versions
let tags = Object.keys(assets)
// filter the versions
if (opts.filterTag !== undefined) {
tags = tags.filter(opts.filterTag)
}
if (tags.length === 0) {
throw new Error(`no tag found for version ${opts.version}`)
}
// find the first tag that starts with the version
// loop over the versions starting with the latest
let tag: string | undefined
for (const mingwVersion of tags) {
if (mingwVersion.startsWith(opts.version)) {
tag = mingwVersion
break
}
}
if (tag === undefined) {
throw new Error(`version ${opts.version} is not supported`)
}
// get the list of assets
let matchedNames = assets[tag]
// filter the assets
if (opts.filterName !== undefined) {
matchedNames = matchedNames.filter(opts.filterName)
}
if (matchedNames.length === 0) {
throw new Error(`no asset found for version ${opts.version} and arch ${opts.arch}`)
}
// use the first asset if the arch is not specified
if (opts.arch === undefined) {
return { tag, name: matchedNames[0] }
}
// find the asset that matches the arch
for (const name of matchedNames) {
// search each asset name for the arch
if (name.includes(opts.arch)) {
return { tag, name }
}
}
throw new Error(`arch ${opts.arch} could not be found among ${JSON.stringify(matchedNames)}`)
}

View File

@ -1,5 +1,4 @@
import { isArch } from "../utils/env/isArch.js"
import { isUbuntu } from "../utils/env/isUbuntu.js"
// passing "" to a tool installed by a package manager (apt, brew, choco) will result in the default version of that package manager.
// the directly downloaded tools require a given version ("" doesn't work).
@ -32,7 +31,7 @@ export const DefaultVersions: Record<string, string | undefined> = {
task: "3.38.0", // https://github.com/go-task/task/releases
doxygen: isArch() ? "1.11.0-4" : "1.11.0", // https://www.doxygen.nl/download.html // https://packages.ubuntu.com/search?suite=all&arch=any&searchon=names&keywords=doxygen // https://formulae.brew.sh/formula/doxygen // https://archlinux.org/packages/extra/x86_64/doxygen/
gcc: process.platform === "win32"
? "13"
? "14.2.0posix-18.1.8-12.0.0-ucrt-r1"
: undefined, // use the default version on Ubuntu, Fedora, Arch, macOS, etc.
// mingw: isArch() ? "12.2.0-1" : "8", // https://archlinux.org/packages/extra/x86_64/mingw-w64-gcc/
powershell: "7.4.5", // https://github.com/PowerShell/PowerShell/releases/tag/v7.4.5