1 import { get } from "https";
2 import * as ini from "ini";
3 import { homedir } from "os";
4 import { join } from "path";
5 import Logger from "../logger.mjs";
6 import { readdirSync, statSync, readFileSync } from "fs";
7 import { getDataRoot } from "./downloadHelpers.mjs";
11 } from "./downloadHelpers.mjs";
14 "https://raspberrypi.github.io/pico-vscode/" +
15 `${CURRENT_DATA_VERSION}/supportedToolchains.ini`;
16 const supportedDistros = [
24 export interface SupportedToolchainVersion {
26 /// { [key in (typeof supportedDistros)[number]]?: string }
27 downloadUrls: { [key: string]: string };
30 export interface InstalledToolchain {
35 function parseIni(data: string): SupportedToolchainVersion[] {
36 const parsedIni: { [key: string]: { [key: string]: string } } =
38 const supportedToolchains: SupportedToolchainVersion[] = [];
40 // Iterate through sections
41 for (const version in parsedIni) {
42 const section: { [key: string]: string } = parsedIni[version];
45 [key in (typeof supportedDistros)[number]]: string;
48 // Create an object with supported distros and their URLs
49 for (const distro of supportedDistros) {
50 if (section[distro]) {
51 downloadUrls[distro] = section[distro];
55 // Add the version and downloadUrls to the result array
56 supportedToolchains.push({ version, downloadUrls });
59 return supportedToolchains;
62 export async function getSupportedToolchains(): Promise<
63 SupportedToolchainVersion[]
66 if (!(await isInternetConnected())) {
68 "Error while downloading supported toolchains list. " +
69 "No internet connection"
72 const result = await new Promise<SupportedToolchainVersion[]>(
73 (resolve, reject) => {
74 // Download the INI file
75 get(iniUrl, response => {
76 if (response.statusCode !== 200) {
79 "Error while downloading supported toolchains list. " +
80 `Status code: ${response.statusCode}`
86 // Append data as it arrives
87 response.on("data", chunk => {
91 // Parse the INI data when the download is complete
92 response.on("end", () => {
93 // Resolve with the array of SupportedToolchainVersion
94 resolve(parseIni(data));
98 response.on("error", error => {
108 error instanceof Error
110 : typeof error === "string"
116 // try to load local supported toolchains list
117 const supportedToolchains = parseIni(
118 readFileSync(join(getDataRoot(), "supportedToolchains.ini")).toString(
123 return supportedToolchains;
125 Logger.log("Error while loading local supported toolchains list.");
132 export function detectInstalledToolchains(): InstalledToolchain[] {
133 // detect installed toolchains by foldernames in $HOME/.pico-sdk/toolchain/<version>
134 const homeDirectory = homedir();
135 const toolchainDirectory = join(homeDirectory, ".pico-sdk", "toolchain");
138 // check if pico-sdk directory exists
139 if (!statSync(toolchainDirectory).isDirectory()) {
140 Logger.log("No installed toolchain found.");
145 Logger.log("No installed toolchain found.");
150 // scan foldernames in picoSDKDirectory/toolchain
151 const installedToolchains: InstalledToolchain[] = [];
153 const versions = readdirSync(toolchainDirectory);
154 // TODO: better regex or alternative
155 for (const version of versions.filter(
157 /^\d+_\d+_(?:\w+(?:-|\.))?(\d+)$/.test(version) &&
158 statSync(`${toolchainDirectory}/${version}`).isDirectory()
160 const toolchainPath = join(toolchainDirectory, version);
162 installedToolchains.push({ version, path: toolchainPath });
165 Logger.log("Error while detecting installed Toolchains.");
168 return installedToolchains;