diff --git a/src/commands/switchSDK.mts b/src/commands/switchSDK.mts index 50a6161..1a9037d 100644 --- a/src/commands/switchSDK.mts +++ b/src/commands/switchSDK.mts @@ -33,6 +33,8 @@ import VersionBundlesLoader, { import { sep } from "path"; import { join as posixJoin } from "path/posix"; import { NINJA_AUTO_INSTALL_DISABLED } from "../webview/newProjectPanel.mjs"; +import Logger from "../logger.mjs"; +import type { Progress as GotProgress } from "got"; export interface AdvancedSwitchSDKOptions { toolchainVersion: { label: string; toolchain: SupportedToolchainVersion }; @@ -47,6 +49,7 @@ interface SwitchSDKOptions { export default class SwitchSDKCommand extends Command { private _versionBundlesLoader: VersionBundlesLoader; + private _logger: Logger = new Logger("SwitchSDKCommand"); public static readonly id = "switchSDK"; @@ -383,107 +386,305 @@ export default class SwitchSDKCommand extends Command { //options.advancedOptions is defined options.advancedOptions!.toolchainVersion; - // show progress bar while installing - const result = await window.withProgress( + // show individual progress bars while installing + let result = await window.withProgress( { - title: - `Installing SDK ${selectedSDK.label}, ` + - `toolchain ${selectedToolchain.label} ` + - "and tools...", location: ProgressLocation.Notification, + title: "Installing SDK...", + cancellable: false, }, async progress => { // download and install selected SDK - if ( - (await downloadAndInstallSDK(selectedSDK.sdk, SDK_REPOSITORY_URL)) && - (await downloadAndInstallTools(selectedSDK.sdk)) - ) { + // TODO: maybe parse python3 path + const result = await downloadAndInstallSDK( + selectedSDK.sdk, + SDK_REPOSITORY_URL + ); + + if (result) { + this._logger.debug("Successfully installed SDK."); + progress.report({ - increment: 40, + increment: 100, + // TODO: maybe only finished or sth like that + message: `Successfully installed SDK ${selectedSDK.label}.`, }); - if (await downloadAndInstallToolchain(selectedToolchain.toolchain)) { + return true; + } + + this._logger.error("Failed to install SDK."); + + progress.report({ + increment: 100, + }); + + void window.showErrorMessage( + `Failed to install SDK ${selectedSDK.label}. ` + + "Make sure all requirements are met." + ); + + return false; + } + ); + + if (!result) { + return; + } + + let progressState = 0; + result = await window.withProgress( + { + location: ProgressLocation.Notification, + title: "Installing toolchain...", + cancellable: false, + }, + async progress => { + // download and install selected toolchain + const result = await downloadAndInstallToolchain( + selectedToolchain.toolchain, + (prog: GotProgress) => { + const percent = prog.percent * 100; + progress.report({ + increment: percent - progressState, + }); + progressState = percent; + } + ); + + if (result) { + this._logger.debug("Successfully installed toolchain."); + + progress.report({ + increment: 100, + message: + "Successfully installed " + + `toolchain ${selectedToolchain.label}.`, + }); + + return true; + } + + this._logger.error("Failed to install toolchain."); + + progress.report({ + increment: 100, + }); + + void window.showErrorMessage( + `Failed to install toolchain ${selectedToolchain.label}.` + ); + + return false; + } + ); + + if (!result) { + return; + } + + progressState = 0; + result = await window.withProgress( + { + location: ProgressLocation.Notification, + title: "Installing tools...", + cancellable: false, + }, + async progress => { + // download and install tools + const result = await downloadAndInstallTools( + selectedSDK.sdk, + (prog: GotProgress) => { + const percent = prog.percent * 100; progress.report({ - increment: 20, + increment: percent - progressState, }); + progressState = percent; + } + ); + + if (result) { + this._logger.debug("Successfully installed tools."); + + progress.report({ + increment: 100, + message: "Successfully installed tools.", + }); + + return true; + } + + this._logger.error("Failed to install tools."); + + progress.report({ + increment: 100, + }); + + void window.showErrorMessage("Failed to install tools."); + + return false; + } + ); + + if (!result) { + return; + } - if ( - options.advancedOptions?.ninjaVersion !== undefined && - (await downloadAndInstallNinja( - options.advancedOptions.ninjaVersion - )) - ) { + if (options.advancedOptions?.ninjaVersion !== undefined) { + progressState = 0; + result = await window.withProgress( + { + location: ProgressLocation.Notification, + title: "Downloading and installing Ninja...", + cancellable: false, + }, + async progress => { + const result = await downloadAndInstallNinja( + options.advancedOptions!.ninjaVersion!, + (prog: GotProgress) => { + const percent = prog.percent * 100; progress.report({ - increment: 10, + increment: percent - progressState, }); + progressState = percent; } + ); + + if (result) { + progress.report({ + increment: 100, + message: "Successfully installed Ninja.", + }); + + return true; + } + + progress.report({ + increment: 100, + }); - // install if cmakeVersion is not a path and not a command - if ( - options.advancedOptions?.cmakeVersion !== undefined && + void window.showWarningMessage("Failed to install Ninja."); + + return false; + } + ); + + if (!result) { + return; + } + } else { + // TODO: maybe show error + /* + this._logger.error("Advanced options are undefined."); + + void window.showErrorMessage("Failed to get Ninja version."); + + return; + */ + } + + // TODO: check if not version bundle check here would be better + /* compare with ninja checks + options.advancedOptions?.cmakeVersion !== undefined && !options.advancedOptions.cmakeVersion.includes("/") && options.advancedOptions.cmakeVersion !== "cmake" && (await downloadAndInstallCmake( options.advancedOptions.cmakeVersion - )) - ) { + ))*/ + if ( + options.advancedOptions?.cmakeVersion !== undefined && + !options.advancedOptions.cmakeVersion.includes("/") && + options.advancedOptions.cmakeVersion !== "cmake" + ) { + progressState = 0; + result = await window.withProgress( + { + location: ProgressLocation.Notification, + title: "Downloading and installing CMake...", + cancellable: false, + }, + async progress => { + const result = await downloadAndInstallCmake( + options.advancedOptions!.cmakeVersion, + (prog: GotProgress) => { + const percent = prog.percent * 100; progress.report({ - increment: 10, + increment: percent - progressState, }); + progressState = percent; } + ); - await updateVSCodeStaticConfigs( - workspaceFolder.uri.fsPath, - selectedSDK.sdk, - selectedToolchain.toolchain.version, - options.advancedOptions?.ninjaVersion, - options.advancedOptions?.cmakeVersion - ); + if (result) { + this._logger.debug("Successfully installed CMake."); progress.report({ - increment: 10, + increment: 100, }); - const cmakeUpdateResult = await cmakeUpdateSDK( - workspaceFolder.uri, - selectedSDK.sdk, - selectedToolchain.toolchain.version, - selectedPicotool ?? "2.0.0" - ); - - if (!cmakeUpdateResult) { - void window.showWarningMessage( - "Failed to update CMakeLists.txt for new SDK version." - ); - } - - progress.report({ - // show sdk installed notification - message: `Successfully installed SDK ${selectedSDK.label}.`, - increment: 10, - }); + void window.showInformationMessage("Successfully installed CMake."); return true; - } else { - progress.report({ - message: - "Failed to install " + `toolchain ${selectedToolchain.label}.`, - increment: 60, - }); - - return false; } + + this._logger.error("Failed to install CMake."); + + progress.report({ + increment: 100, + }); + + void window.showWarningMessage("Failed to install CMake."); + + return false; } + ); + + if (!result) { + return; + } + } + + result = await window.withProgress( + { + location: ProgressLocation.Notification, + title: "Updating project configuration...", + cancellable: false, + }, + async progress => { + await updateVSCodeStaticConfigs( + workspaceFolder.uri.fsPath, + selectedSDK.sdk, + selectedToolchain.toolchain.version, + options.advancedOptions?.ninjaVersion, + options.advancedOptions?.cmakeVersion + ); progress.report({ - // show sdk install failed notification - message: - `Failed to install SDK ${selectedSDK.label}.` + - "Make sure all requirements are met.", - increment: 100, + increment: 50, + message: "Project configuration updated.", }); - return false; + const cmakeUpdateResult = await cmakeUpdateSDK( + workspaceFolder.uri, + selectedSDK.sdk, + selectedToolchain.toolchain.version, + selectedPicotool ?? "2.0.0" + ); + + progress.report({ + increment: 50, + message: "CMakeLists.txt updated.", + }); + + if (!cmakeUpdateResult) { + void window.showWarningMessage( + "Failed to update CMakeLists.txt for new SDK version." + ); + + return false; + } + + return true; } ); diff --git a/src/extension.mts b/src/extension.mts index aa9a95d..972da30 100644 --- a/src/extension.mts +++ b/src/extension.mts @@ -76,6 +76,7 @@ import UninstallPicoSDKCommand from "./commands/uninstallPicoSDK.mjs"; import FlashProjectSWDCommand from "./commands/flashProjectSwd.mjs"; // eslint-disable-next-line max-len import { NewMicroPythonProjectPanel } from "./webview/newMicroPythonProjectPanel.mjs"; +import type { Got, Progress as GotProgress } from "got"; export async function activate(context: ExtensionContext): Promise { Logger.info(LoggerSource.extension, "Extension activation triggered"); @@ -247,26 +248,30 @@ export async function activate(context: ExtensionContext): Promise { toolchain => toolchain.version === selectedToolchainAndSDKVersions[1] ); + // TODO: for failed installation message add option to change version + let installSuccess = true; // install if needed await window.withProgress( { location: ProgressLocation.Notification, title: - "Downloading and installing Pico SDK, Toolchain and " + - "tools as selected. " + + "Downloading and installing Pico SDK as selected. " + "This may take a while...", cancellable: false, }, async progress => { - // install if needed - if ( - !(await downloadAndInstallSDK( - selectedToolchainAndSDKVersions[0], - SDK_REPOSITORY_URL - )) || - !(await downloadAndInstallTools(selectedToolchainAndSDKVersions[0])) || - !(await downloadAndInstallPicotool(selectedToolchainAndSDKVersions[2])) - ) { + const result = await downloadAndInstallSDK( + selectedToolchainAndSDKVersions[0], + SDK_REPOSITORY_URL + ); + + progress.report({ + increment: 100, + }); + + if (!result) { + installSuccess = false; + Logger.error( LoggerSource.extension, "Failed to install project SDK", @@ -283,29 +288,53 @@ export async function activate(context: ExtensionContext): Promise { "Found/installed project SDK", `version: ${selectedToolchainAndSDKVersions[0]}` ); + } + } + ); - if (!(await downloadAndInstallOpenOCD(openOCDVersion))) { - Logger.error( - LoggerSource.extension, - "Failed to download and install openocd." - ); - } else { - Logger.debug( - LoggerSource.extension, - "Successfully downloaded and installed openocd." - ); + if (!installSuccess) { + return; + } + + if (selectedToolchain === undefined) { + Logger.error( + LoggerSource.extension, + "Failed to detect project toolchain version." + ); + + void window.showErrorMessage("Failed to detect project toolchain version."); + + return; + } + + let progressState = 0; + await window.withProgress( + { + location: ProgressLocation.Notification, + title: + "Downloading and installing toolchain as selected. " + + "This may take a while...", + cancellable: false, + }, + async progress => { + const result = await downloadAndInstallToolchain( + selectedToolchain, + (prog: GotProgress) => { + const percent = prog.percent * 100; + progress.report({ + increment: percent - progressState, + }); + progressState = percent; } - } + ); progress.report({ - increment: 50, + increment: 100, }); - // install if needed - if ( - selectedToolchain === undefined || - !(await downloadAndInstallToolchain(selectedToolchain)) - ) { + if (!result) { + installSuccess = false; + Logger.error( LoggerSource.extension, "Failed to install project toolchain", @@ -324,10 +353,149 @@ export async function activate(context: ExtensionContext): Promise { `version: ${selectedToolchainAndSDKVersions[1]}` ); } + } + ); + + if (!installSuccess) { + return; + } + + progressState = 0; + await window.withProgress( + { + location: ProgressLocation.Notification, + title: + "Downloading and installing tools as selected. " + + "This may take a while...", + cancellable: false, + }, + async progress => { + const result = await downloadAndInstallTools( + selectedToolchainAndSDKVersions[0], + (prog: GotProgress) => { + const percent = prog.percent * 100; + progress.report({ + increment: percent - progressState, + }); + progressState = percent; + } + ); + + progress.report({ + increment: 100, + }); + + if (!result) { + installSuccess = false; + + Logger.error( + LoggerSource.extension, + "Failed to install project SDK", + `version: ${selectedToolchainAndSDKVersions[0]}.`, + "Make sure all requirements are met." + ); + + void window.showErrorMessage("Failed to install project SDK version."); + + return; + } else { + Logger.info( + LoggerSource.extension, + "Found/installed project SDK", + `version: ${selectedToolchainAndSDKVersions[0]}` + ); + } + } + ); + + if (!installSuccess) { + return; + } + + progressState = 0; + await window.withProgress( + { + location: ProgressLocation.Notification, + title: + "Downloading and installing picotool as selected. " + + "This may take a while...", + cancellable: false, + }, + async progress => { + const result = await downloadAndInstallPicotool( + selectedToolchainAndSDKVersions[2], + (prog: GotProgress) => { + const percent = prog.percent * 100; + progress.report({ + increment: percent - progressState, + }); + progressState = percent; + } + ); + + progress.report({ + increment: 100, + }); + + if (!result) { + installSuccess = false; + Logger.error(LoggerSource.extension, "Failed to install picotool."); + + void window.showErrorMessage("Failed to install picotool."); + + return; + } else { + Logger.debug( + LoggerSource.extension, + "Successfully downloaded and installed picotool." + ); + } + } + ); + + if (!installSuccess) { + return; + } + + progressState = 0; + await window.withProgress( + { + location: ProgressLocation.Notification, + title: "Downloading and installing OpenOCD. This may take a while...", + cancellable: false, + }, + async progress => { + const result = await downloadAndInstallOpenOCD( + openOCDVersion, + (prog: GotProgress) => { + const percent = prog.percent * 100; + progress.report({ + increment: percent - progressState, + }); + progressState = percent; + } + ); progress.report({ - increment: 50, + increment: 100, }); + + if (!result) { + Logger.error( + LoggerSource.extension, + "Failed to download and install OpenOCD." + ); + void window.showWarningMessage( + "Failed to download and install OpenOCD." + ); + } else { + Logger.debug( + LoggerSource.extension, + "Successfully downloaded and installed OpenOCD." + ); + + void window.showInformationMessage("OpenOCD installed successfully."); + } } ); @@ -359,6 +527,7 @@ export async function activate(context: ExtensionContext): Promise { } let result = false; + progressState = 0; await window.withProgress( { location: ProgressLocation.Notification, @@ -366,7 +535,16 @@ export async function activate(context: ExtensionContext): Promise { cancellable: false, }, async progress => { - result = await downloadAndInstallNinja(ninjaVersion); + result = await downloadAndInstallNinja( + ninjaVersion, + (prog: GotProgress) => { + const percent = prog.percent * 100; + progress.report({ + increment: percent - progressState, + }); + progressState = percent; + } + ); progress.report({ increment: 100, }); @@ -418,6 +596,7 @@ export async function activate(context: ExtensionContext): Promise { } let result = false; + progressState = 0; await window.withProgress( { location: ProgressLocation.Notification, @@ -425,7 +604,16 @@ export async function activate(context: ExtensionContext): Promise { cancellable: false, }, async progress => { - result = await downloadAndInstallCmake(cmakeVersion); + result = await downloadAndInstallCmake( + cmakeVersion, + (prog: GotProgress) => { + const percent = prog.percent * 100; + progress.report({ + increment: percent - progressState, + }); + progressState = percent; + } + ); progress.report({ increment: 100, }); diff --git a/src/utils/download.mts b/src/utils/download.mts index 6cca1c1..0e6f31d 100644 --- a/src/utils/download.mts +++ b/src/utils/download.mts @@ -41,7 +41,7 @@ import { import { unxzFile, unzipFile } from "./downloadHelpers.mjs"; import type { Writable } from "stream"; import { unknownErrorToString } from "./errorHelper.mjs"; -import { got } from "got"; +import { got, type Progress } from "got"; import { pipeline as streamPipeline } from "node:stream/promises"; /// Translate nodejs platform names to ninja platform names @@ -199,7 +199,8 @@ export async function downloadAndInstallArchive( logName: string, extraCallback?: () => void, redirectURL?: string, - extraHeaders?: { [key: string]: string } + extraHeaders?: { [key: string]: string }, + progressCallback?: (progress: Progress) => void ): Promise { // Check if the SDK is already installed if ( @@ -234,7 +235,7 @@ export async function downloadAndInstallArchive( try { let isSuccess = false; - if (process.platform !== "linux") { + if (process.platform === "sunos") { const undiciRet = await downloadFileUndici( client, downloadUrl, @@ -257,7 +258,8 @@ export async function downloadAndInstallArchive( isSuccess = await downloadFileGot( downloadUrl, archiveFilePath, - extraHeaders + extraHeaders, + progressCallback ); } @@ -365,24 +367,27 @@ async function downloadFileUndici( async function downloadFileGot( url: URL, archiveFilePath: string, - extraHeaders?: { [key: string]: string } + extraHeaders?: { [key: string]: string }, + progressCallback?: (progress: Progress) => void ): Promise { - await streamPipeline( - got.stream(url.toString(), { - headers: { - // eslint-disable-next-line @typescript-eslint/naming-convention - "User-Agent": EXT_USER_AGENT, - // eslint-disable-next-line @typescript-eslint/naming-convention - Accept: "*/*", - // eslint-disable-next-line @typescript-eslint/naming-convention - "Accept-Encoding": "gzip, deflate, br", - ...extraHeaders, - }, - followRedirect: true, - method: "GET", - }), - createWriteStream(archiveFilePath) - ); + const request = got.stream(url.toString(), { + headers: { + // eslint-disable-next-line @typescript-eslint/naming-convention + "User-Agent": EXT_USER_AGENT, + // eslint-disable-next-line @typescript-eslint/naming-convention + Accept: "*/*", + // eslint-disable-next-line @typescript-eslint/naming-convention + "Accept-Encoding": "gzip, deflate, br", + ...extraHeaders, + }, + followRedirect: true, + method: "GET", + }); + if (progressCallback) { + request.on("downloadProgress", progressCallback); + } + + await streamPipeline(request, createWriteStream(archiveFilePath)); return true; } @@ -537,7 +542,8 @@ async function downloadAndInstallGithubAsset( logName: string, extraCallback?: () => void, - redirectURL?: string + redirectURL?: string, + progressCallback?: (progress: Progress) => void ): Promise { // Check if the asset has already been installed if ( @@ -656,7 +662,7 @@ async function downloadAndInstallGithubAsset( }; } - if (process.platform !== "linux" || process.arch !== "arm64") { + if (process.platform === "sunos") { // keep track of retries let retries = 0; @@ -786,25 +792,26 @@ async function downloadAndInstallGithubAsset( } else { const urlObj = new URL(url); - // Linux arm64 return downloadAndInstallArchive( urlObj.origin + urlObj.pathname + urlObj.search, targetDirectory, archiveFileName, logName, - undefined, + extraCallback, undefined, { ...getAuthorizationHeaders(), // github headers ...headers, - } + }, + progressCallback ); } } export async function downloadAndInstallTools( - version: string + version: string, + progressCallback?: (progress: Progress) => void ): Promise { if (parseInt(version.split(".")[0]) < 2) { if (process.platform !== "win32") { @@ -834,12 +841,16 @@ export async function downloadAndInstallTools( targetDirectory, archiveFileName, assetName, - "SDK Tools" + "SDK Tools", + undefined, + undefined, + progressCallback ); } export async function downloadAndInstallPicotool( - version: string + version: string, + progressCallback?: (progress: Progress) => void ): Promise { const assetExt: string = process.platform === "linux" ? "tar.gz" : "zip"; const targetDirectory = buildPicotoolPath(version); @@ -859,12 +870,16 @@ export async function downloadAndInstallPicotool( targetDirectory, archiveFileName, assetName, - "Picotool" + "Picotool", + undefined, + undefined, + progressCallback ); } export async function downloadAndInstallToolchain( - toolchain: SupportedToolchainVersion + toolchain: SupportedToolchainVersion, + progressCallback?: (progress: Progress) => void ): Promise { const targetDirectory = buildToolchainPath(toolchain.version); @@ -887,7 +902,11 @@ export async function downloadAndInstallToolchain( downloadUrl, targetDirectory, archiveFileName, - "Toolchain" + "Toolchain", + undefined, + undefined, + undefined, + progressCallback ); } @@ -899,7 +918,8 @@ export async function downloadAndInstallToolchain( * successfully downloaded and installed, false otherwise */ export async function downloadAndInstallNinja( - version: string + version: string, + progressCallback?: (progress: Progress) => void ): Promise { const targetDirectory = buildNinjaPath(version); const archiveFileName = `ninja.zip`; @@ -918,7 +938,10 @@ export async function downloadAndInstallNinja( targetDirectory, archiveFileName, assetName, - "ninja" + "ninja", + undefined, + undefined, + progressCallback ); } @@ -948,7 +971,8 @@ export async function downloadAndInstallNinja( // } export async function downloadAndInstallOpenOCD( - version: string + version: string, + progressCallback?: (progress: Progress) => void ): Promise { if ( (process.platform === "darwin" && process.arch === "x64") || @@ -994,7 +1018,9 @@ export async function downloadAndInstallOpenOCD( archiveFileName, assetName, "OpenOCD", - extraCallback + extraCallback, + undefined, + progressCallback ); } @@ -1005,7 +1031,8 @@ export async function downloadAndInstallOpenOCD( * @returns */ export async function downloadAndInstallCmake( - version: string + version: string, + progressCallback?: (progress: Progress) => void ): Promise { const targetDirectory = buildCMakePath(version); const assetExt = process.platform === "win32" ? "zip" : "tar.gz"; @@ -1044,7 +1071,9 @@ export async function downloadAndInstallCmake( archiveFileName, assetName, "CMake", - extraCallback + extraCallback, + undefined, + progressCallback ); } @@ -1109,6 +1138,7 @@ export async function downloadEmbedPython( `python-${versionBundle.python.version}.zip` ); + // TODO: replace with got return new Promise(resolve => { const client = new Client(downloadUrl.origin); diff --git a/src/webview/newProjectPanel.mts b/src/webview/newProjectPanel.mts index bad45cf..f74aeee 100644 --- a/src/webview/newProjectPanel.mts +++ b/src/webview/newProjectPanel.mts @@ -61,6 +61,7 @@ import { setupExample, } from "../utils/examplesUtil.mjs"; import { unknownErrorToString } from "../utils/errorHelper.mjs"; +import type { Progress as GotProgress } from "got"; export const NINJA_AUTO_INSTALL_DISABLED = false; // process.platform === "linux" && process.arch === "arm64"; @@ -794,7 +795,7 @@ export class NewProjectPanel { message: "Failed", increment: 100, }); - await window.showErrorMessage("Failed to find selected SDK version."); + void window.showErrorMessage("Failed to find selected SDK version."); return; } @@ -809,7 +810,7 @@ export class NewProjectPanel { { location: ProgressLocation.Notification, title: - "Download and installing Python. This may take a while...", + "Downloading and installing Python. This may take a while...", cancellable: false, }, async progress2 => { @@ -837,7 +838,7 @@ export class NewProjectPanel { "Automatic Python installation is only supported on Windows and macOS." ); - await window.showErrorMessage( + void window.showErrorMessage( "Automatic Python installation is only supported on Windows and macOS." ); } @@ -861,7 +862,7 @@ export class NewProjectPanel { message: "Failed", increment: 100, }); - await window.showErrorMessage("Failed to find python3 executable."); + void window.showErrorMessage("Failed to find python3 executable."); return; } @@ -871,45 +872,169 @@ export class NewProjectPanel { // install selected sdk and toolchain if necessary // show user feedback as downloads can take a while - let installedSuccessfully = false; + let installedSuccessfully = true; await window.withProgress( { location: ProgressLocation.Notification, - title: "Downloading SDK and Toolchain", + title: "Downloading and installing SDK", cancellable: false, }, async progress2 => { - // download both - if ( - !(await downloadAndInstallSDK( - selectedSDK, - SDK_REPOSITORY_URL, - // python3Path is only possible undefined if downloaded and there is already checked and returned if this happened - python3Path!.replace(HOME_VAR, homedir().replaceAll("\\", "/")) - )) || - !(await downloadAndInstallToolchain(selectedToolchain)) || - !(await downloadAndInstallTools(selectedSDK)) || - !(await downloadAndInstallPicotool(selectedPicotool)) - ) { - this._logger.error( - `Failed to download and install toolchain and SDK.` - ); + const result = await downloadAndInstallSDK( + selectedSDK, + SDK_REPOSITORY_URL, + // python3Path is only possible undefined if downloaded and there is already checked and returned if this happened + python3Path!.replace(HOME_VAR, homedir().replaceAll("\\", "/")) + ); + if (!result) { + this._logger.error(`Failed to download and install SDK.`); + installedSuccessfully = false; progress2.report({ message: "Failed - Make sure all requirements are met.", increment: 100, }); + void window.showErrorMessage( + "Failed to download and install SDK. Make sure all requirements are met." + ); + + return; + } + } + ); + + if (!installedSuccessfully) { + progress.report({ + message: "Failed", + increment: 100, + }); + + return; + } + + let prog2LastState = 0; + await window.withProgress( + { + location: ProgressLocation.Notification, + title: "Downloading and installing toolchain", + cancellable: false, + }, + async progress2 => { + const result = await downloadAndInstallToolchain( + selectedToolchain, + (prog: GotProgress) => { + const per = prog.percent * 100; + progress2.report({ + increment: per - prog2LastState, + }); + prog2LastState = per; + } + ); + + if (!result) { + this._logger.error(`Failed to download and install toolchain.`); installedSuccessfully = false; - } else { - installedSuccessfully = true; - if (!(await downloadAndInstallOpenOCD(openOCDVersion))) { - this._logger.error(`Failed to download and install openocd.`); - } else { - this._logger.info( - `Successfully downloaded and installed openocd.` - ); + progress2.report({ + message: "Failed", + increment: 100, + }); + + void window.showErrorMessage( + "Failed to download and install toolchain." + ); + + return; + } + } + ); + + if (!installedSuccessfully) { + progress.report({ + message: "Failed", + increment: 100, + }); + + return; + } + + prog2LastState = 0; + await window.withProgress( + { + location: ProgressLocation.Notification, + title: "Downloading and installing tools", + cancellable: false, + }, + async progress2 => { + const result = await downloadAndInstallTools( + selectedSDK, + (prog: GotProgress) => { + const per = prog.percent * 100; + progress2.report({ + increment: per - prog2LastState, + }); + prog2LastState = per; + } + ); + + if (!result) { + this._logger.error(`Failed to download and install tools.`); + installedSuccessfully = false; + progress2.report({ + message: "Failed", + increment: 100, + }); + + void window.showErrorMessage( + "Failed to download and install tools." + ); + + return; + } + } + ); + + if (!installedSuccessfully) { + progress.report({ + message: "Failed", + increment: 100, + }); + + return; + } + + prog2LastState = 0; + await window.withProgress( + { + location: ProgressLocation.Notification, + title: "Downloading and installing picotool", + cancellable: false, + }, + async progress2 => { + const result = await downloadAndInstallPicotool( + selectedPicotool, + (prog: GotProgress) => { + const per = prog.percent * 100; + progress2.report({ + increment: per - prog2LastState, + }); + prog2LastState = per; } + ); + + if (!result) { + this._logger.error(`Failed to download and install picotool.`); + installedSuccessfully = false; + progress2.report({ + message: "Failed", + increment: 100, + }); + + void window.showErrorMessage( + "Failed to download and install picotool." + ); + + return; } } ); @@ -919,13 +1044,43 @@ export class NewProjectPanel { message: "Failed", increment: 100, }); - await window.showErrorMessage( - "Failed to download and install SDK and/or toolchain." - ); return; } + prog2LastState = 0; + await window.withProgress( + { + location: ProgressLocation.Notification, + title: "Downloading and installing OpenOCD", + cancellable: false, + }, + async progress2 => { + const result = await downloadAndInstallOpenOCD( + openOCDVersion, + (prog: GotProgress) => { + const per = prog.percent * 100; + progress2.report({ + increment: per - prog2LastState, + }); + prog2LastState = per; + } + ); + + if (!result) { + this._logger.error(`Failed to download and install OpenOCD.`); + // not required + //installedSuccessfully = false; + progress2.report({ + message: "Failed", + increment: 100, + }); + + return; + } + } + ); + let ninjaExecutable: string; let cmakeExecutable: string; switch (data.ninjaMode) { @@ -947,16 +1102,28 @@ export class NewProjectPanel { // eslint-disable-next-line no-fallthrough case 2: installedSuccessfully = false; + prog2LastState = 0; await window.withProgress( { location: ProgressLocation.Notification, - title: "Download and install ninja", + title: "Download and install Ninja", cancellable: false, }, async progress2 => { - if (await downloadAndInstallNinja(data.ninjaVersion)) { + if ( + await downloadAndInstallNinja( + data.ninjaVersion, + (prog: GotProgress) => { + const per = prog.percent * 100; + progress2.report({ + increment: per - prog2LastState, + }); + prog2LastState = per; + } + ) + ) { progress2.report({ - message: "Successfully downloaded and installed ninja.", + message: "Successfully downloaded and installed Ninja.", increment: 100, }); @@ -976,7 +1143,7 @@ export class NewProjectPanel { message: "Failed", increment: 100, }); - await window.showErrorMessage( + void window.showErrorMessage( "Failed to download and install ninja. Make sure all requirements are met." ); @@ -1005,7 +1172,7 @@ export class NewProjectPanel { message: "Failed", increment: 100, }); - await window.showErrorMessage("Unknown ninja selection."); + void window.showErrorMessage("Unknown ninja selection."); this._logger.error("Unknown ninja selection."); return; @@ -1019,16 +1186,29 @@ export class NewProjectPanel { // eslint-disable-next-line no-fallthrough case 2: installedSuccessfully = false; + prog2LastState = 0; await window.withProgress( { location: ProgressLocation.Notification, - title: "Download and install cmake", + title: "Download and install CMake", cancellable: false, }, async progress2 => { - if (await downloadAndInstallCmake(data.cmakeVersion)) { + if ( + await downloadAndInstallCmake( + data.cmakeVersion, + (prog: GotProgress) => { + const per = prog.percent * 100; + progress2.report({ + increment: per - prog2LastState, + }); + prog2LastState = per; + } + ) + ) { progress.report({ - message: "Successfully downloaded and installed cmake.", + // TODO: maybe just finished or something like that + message: "Successfully downloaded and installed CMake.", increment: 100, }); @@ -1048,8 +1228,9 @@ export class NewProjectPanel { message: "Failed", increment: 100, }); - await window.showErrorMessage( - "Failed to download and install cmake. Make sure all requirements are met." + void window.showErrorMessage( + // TODO: maybe remove all requirements met part + "Failed to download and install CMake. Make sure all requirements are met." ); return; @@ -1076,7 +1257,7 @@ export class NewProjectPanel { message: "Failed", increment: 100, }); - await window.showErrorMessage("Unknown cmake selection."); + void window.showErrorMessage("Unknown cmake selection."); this._logger.error("Unknown cmake selection."); return;