diff --git a/arduino-ide-extension/package.json b/arduino-ide-extension/package.json index 2cd904e14..6ebff3eca 100644 --- a/arduino-ide-extension/package.json +++ b/arduino-ide-extension/package.json @@ -155,7 +155,7 @@ ], "arduino": { "cli": { - "version": "0.24.0" + "version": "0.25.0-rc1" }, "fwuploader": { "version": "2.2.0" diff --git a/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx b/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx index a1d92bf6f..ede419afc 100644 --- a/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx +++ b/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx @@ -10,7 +10,6 @@ import { SketchesService, ExecutableService, Sketch, - LibraryService, ArduinoDaemon, } from '../common/protocol'; import { Mutex } from 'async-mutex'; @@ -77,7 +76,6 @@ import { IDEUpdater } from '../common/protocol/ide-updater'; import { FileSystemFrontendContribution } from '@theia/filesystem/lib/browser/filesystem-frontend-contribution'; import { HostedPluginEvents } from './hosted-plugin-events'; -const INIT_LIBS_AND_PACKAGES = 'initializedLibsAndPackages'; export const SKIP_IDE_VERSION = 'skipIDEVersion'; @injectable() @@ -98,9 +96,6 @@ export class ArduinoFrontendContribution @inject(BoardsService) private readonly boardsService: BoardsService; - @inject(LibraryService) - private readonly libraryService: LibraryService; - @inject(BoardsServiceProvider) private readonly boardsServiceClientImpl: BoardsServiceProvider; @@ -162,27 +157,6 @@ export class ArduinoFrontendContribution @postConstruct() protected async init(): Promise { - const isFirstStartup = !(await this.localStorageService.getData( - INIT_LIBS_AND_PACKAGES - )); - if (isFirstStartup) { - await this.localStorageService.setData(INIT_LIBS_AND_PACKAGES, true); - const avrPackage = await this.boardsService.getBoardPackage({ - id: 'arduino:avr', - }); - const builtInLibrary = ( - await this.libraryService.search({ - query: 'Arduino_BuiltIn', - }) - )[0]; - - !!avrPackage && (await this.boardsService.install({ item: avrPackage })); - !!builtInLibrary && - (await this.libraryService.install({ - item: builtInLibrary, - installDependencies: true, - })); - } if (!window.navigator.onLine) { // tslint:disable-next-line:max-line-length this.messageService.warn( diff --git a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts index 44fde3c4d..231b6636a 100644 --- a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts +++ b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts @@ -304,6 +304,7 @@ import { WidgetManager as TheiaWidgetManager } from '@theia/core/lib/browser/wid import { StartupTask } from './widgets/sketchbook/startup-task'; import { IndexesUpdateProgress } from './contributions/indexes-update-progress'; import { Daemon } from './contributions/daemon'; +import { FirstStartupInstaller } from './contributions/first-startup-installer'; MonacoThemingService.register({ id: 'arduino-theme', @@ -699,6 +700,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { Contribution.configure(bind, StartupTask); Contribution.configure(bind, IndexesUpdateProgress); Contribution.configure(bind, Daemon); + Contribution.configure(bind, FirstStartupInstaller); // Disabled the quick-pick customization from Theia when multiple formatters are available. // Use the default VS Code behavior, and pick the first one. In the IDE2, clang-format has `exclusive` selectors. diff --git a/arduino-ide-extension/src/browser/contributions/first-startup-installer.ts b/arduino-ide-extension/src/browser/contributions/first-startup-installer.ts new file mode 100644 index 000000000..5010c5fc9 --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/first-startup-installer.ts @@ -0,0 +1,97 @@ +import { LocalStorageService } from '@theia/core/lib/browser'; +import { inject, injectable } from '@theia/core/shared/inversify'; +import { BoardsService, LibraryService } from '../../common/protocol'; +import { Contribution } from './contribution'; + +@injectable() +export class FirstStartupInstaller extends Contribution { + @inject(LocalStorageService) + private readonly localStorageService: LocalStorageService; + @inject(BoardsService) + private readonly boardsService: BoardsService; + @inject(LibraryService) + private readonly libraryService: LibraryService; + + override async onReady(): Promise { + const isFirstStartup = !(await this.localStorageService.getData( + FirstStartupInstaller.INIT_LIBS_AND_PACKAGES + )); + if (isFirstStartup) { + const avrPackage = await this.boardsService.getBoardPackage({ + id: 'arduino:avr', + }); + const builtInLibrary = ( + await this.libraryService.search({ query: 'Arduino_BuiltIn' }) + )[0]; + + let avrPackageError: Error | undefined; + let builtInLibraryError: Error | undefined; + + if (avrPackage) { + try { + await this.boardsService.install({ + item: avrPackage, + noOverwrite: true, // We don't want to automatically replace custom platforms the user might already have in place + }); + } catch (e) { + // There's no error code, I need to parse the error message: https://github.com/arduino/arduino-cli/commit/ffe4232b359fcfa87238d68acf1c3b64a1621f14#diff-10ffbdde46838dd9caa881fd1f2a5326a49f8061f6cfd7c9d430b4875a6b6895R62 + if ( + e.message.includes( + `Platform ${avrPackage.id}@${avrPackage.installedVersion} already installed` + ) + ) { + // If arduino:avr installation fails because it's already installed we don't want to retry on next start-up + console.error(e); + } else { + // But if there is any other error (e.g.: no interntet cconnection), we want to retry next time + avrPackageError = e; + } + } + } else { + avrPackageError = new Error('Could not find platform.'); + } + + if (builtInLibrary) { + try { + await this.libraryService.install({ + item: builtInLibrary, + installDependencies: true, + noOverwrite: true, // We don't want to automatically replace custom libraries the user might already have in place + }); + } catch (e) { + // There's no error code, I need to parse the error message: https://github.com/arduino/arduino-cli/commit/2ea3608453b17b1157f8a1dc892af2e13e40f4f0#diff-1de7569144d4e260f8dde0e0d00a4e2a218c57966d583da1687a70d518986649R95 + if (/Library (.*) is already installed/.test(e.message)) { + // If Arduino_BuiltIn installation fails because it's already installed we don't want to retry on next start-up + console.log('error installing core', e); + } else { + // But if there is any other error (e.g.: no interntet cconnection), we want to retry next time + builtInLibraryError = e; + } + } + } else { + builtInLibraryError = new Error('Could not find library'); + } + + if (avrPackageError) { + this.messageService.error( + `Could not install Arduino AVR platform: ${avrPackageError}` + ); + } + if (builtInLibraryError) { + this.messageService.error( + `Could not install ${builtInLibrary.name} library: ${builtInLibraryError}` + ); + } + + if (!avrPackageError && !builtInLibraryError) { + await this.localStorageService.setData( + FirstStartupInstaller.INIT_LIBS_AND_PACKAGES, + true + ); + } + } + } +} +export namespace FirstStartupInstaller { + export const INIT_LIBS_AND_PACKAGES = 'initializedLibsAndPackages'; +} diff --git a/arduino-ide-extension/src/common/protocol/installable.ts b/arduino-ide-extension/src/common/protocol/installable.ts index e0e2e6346..7d8a7e363 100644 --- a/arduino-ide-extension/src/common/protocol/installable.ts +++ b/arduino-ide-extension/src/common/protocol/installable.ts @@ -17,6 +17,7 @@ export interface Installable { item: T; progressId?: string; version?: Installable.Version; + noOverwrite?: boolean; }): Promise; /** diff --git a/arduino-ide-extension/src/common/protocol/library-service.ts b/arduino-ide-extension/src/common/protocol/library-service.ts index b2d897a54..235ca9ef6 100644 --- a/arduino-ide-extension/src/common/protocol/library-service.ts +++ b/arduino-ide-extension/src/common/protocol/library-service.ts @@ -16,6 +16,7 @@ export interface LibraryService progressId?: string; version?: Installable.Version; installDependencies?: boolean; + noOverwrite?: boolean; }): Promise; installZip(options: { zipUri: string; diff --git a/arduino-ide-extension/src/node/boards-service-impl.ts b/arduino-ide-extension/src/node/boards-service-impl.ts index 5f2e1e64e..b46a79677 100644 --- a/arduino-ide-extension/src/node/boards-service-impl.ts +++ b/arduino-ide-extension/src/node/boards-service-impl.ts @@ -391,6 +391,7 @@ export class BoardsServiceImpl item: BoardsPackage; progressId?: string; version?: Installable.Version; + noOverwrite?: boolean; }): Promise { const item = options.item; const version = !!options.version @@ -406,6 +407,7 @@ export class BoardsServiceImpl req.setArchitecture(architecture); req.setPlatformPackage(platform); req.setVersion(version); + req.setNoOverwrite(Boolean(options.noOverwrite)); console.info('>>> Starting boards package installation...', item); @@ -430,7 +432,7 @@ export class BoardsServiceImpl chunk: `Failed to install platform: ${item.id}.\n`, }); this.responseService.appendToOutput({ - chunk: error.toString(), + chunk: `${error.toString()}\n`, }); reject(error); }); diff --git a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/compile_pb.d.ts b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/compile_pb.d.ts index db947e130..34c8ec082 100644 --- a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/compile_pb.d.ts +++ b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/compile_pb.d.ts @@ -95,6 +95,9 @@ export class CompileRequest extends jspb.Message { getEncryptKey(): string; setEncryptKey(value: string): CompileRequest; + getSkipLibrariesDiscovery(): boolean; + setSkipLibrariesDiscovery(value: boolean): CompileRequest; + serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): CompileRequest.AsObject; @@ -133,6 +136,7 @@ export namespace CompileRequest { keysKeychain: string, signKey: string, encryptKey: string, + skipLibrariesDiscovery: boolean, } } diff --git a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/compile_pb.js b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/compile_pb.js index 69aafe386..c2bae211d 100644 --- a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/compile_pb.js +++ b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/compile_pb.js @@ -149,7 +149,8 @@ proto.cc.arduino.cli.commands.v1.CompileRequest.toObject = function(includeInsta libraryList: (f = jspb.Message.getRepeatedField(msg, 24)) == null ? undefined : f, keysKeychain: jspb.Message.getFieldWithDefault(msg, 25, ""), signKey: jspb.Message.getFieldWithDefault(msg, 26, ""), - encryptKey: jspb.Message.getFieldWithDefault(msg, 27, "") + encryptKey: jspb.Message.getFieldWithDefault(msg, 27, ""), + skipLibrariesDiscovery: jspb.Message.getBooleanFieldWithDefault(msg, 28, false) }; if (includeInstance) { @@ -286,6 +287,10 @@ proto.cc.arduino.cli.commands.v1.CompileRequest.deserializeBinaryFromReader = fu var value = /** @type {string} */ (reader.readString()); msg.setEncryptKey(value); break; + case 28: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setSkipLibrariesDiscovery(value); + break; default: reader.skipField(); break; @@ -482,6 +487,13 @@ proto.cc.arduino.cli.commands.v1.CompileRequest.serializeBinaryToWriter = functi f ); } + f = message.getSkipLibrariesDiscovery(); + if (f) { + writer.writeBool( + 28, + f + ); + } }; @@ -1016,6 +1028,24 @@ proto.cc.arduino.cli.commands.v1.CompileRequest.prototype.setEncryptKey = functi }; +/** + * optional bool skip_libraries_discovery = 28; + * @return {boolean} + */ +proto.cc.arduino.cli.commands.v1.CompileRequest.prototype.getSkipLibrariesDiscovery = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 28, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.cc.arduino.cli.commands.v1.CompileRequest} returns this + */ +proto.cc.arduino.cli.commands.v1.CompileRequest.prototype.setSkipLibrariesDiscovery = function(value) { + return jspb.Message.setProto3BooleanField(this, 28, value); +}; + + /** * List of repeated fields within this message type. diff --git a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/core_pb.d.ts b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/core_pb.d.ts index cec05ce33..30792fd12 100644 --- a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/core_pb.d.ts +++ b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/core_pb.d.ts @@ -26,6 +26,9 @@ export class PlatformInstallRequest extends jspb.Message { getSkipPostInstall(): boolean; setSkipPostInstall(value: boolean): PlatformInstallRequest; + getNoOverwrite(): boolean; + setNoOverwrite(value: boolean): PlatformInstallRequest; + serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): PlatformInstallRequest.AsObject; @@ -44,6 +47,7 @@ export namespace PlatformInstallRequest { architecture: string, version: string, skipPostInstall: boolean, + noOverwrite: boolean, } } diff --git a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/core_pb.js b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/core_pb.js index 6db0ad1b4..093656172 100644 --- a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/core_pb.js +++ b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/core_pb.js @@ -339,7 +339,8 @@ proto.cc.arduino.cli.commands.v1.PlatformInstallRequest.toObject = function(incl platformPackage: jspb.Message.getFieldWithDefault(msg, 2, ""), architecture: jspb.Message.getFieldWithDefault(msg, 3, ""), version: jspb.Message.getFieldWithDefault(msg, 4, ""), - skipPostInstall: jspb.Message.getBooleanFieldWithDefault(msg, 5, false) + skipPostInstall: jspb.Message.getBooleanFieldWithDefault(msg, 5, false), + noOverwrite: jspb.Message.getBooleanFieldWithDefault(msg, 6, false) }; if (includeInstance) { @@ -397,6 +398,10 @@ proto.cc.arduino.cli.commands.v1.PlatformInstallRequest.deserializeBinaryFromRea var value = /** @type {boolean} */ (reader.readBool()); msg.setSkipPostInstall(value); break; + case 6: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setNoOverwrite(value); + break; default: reader.skipField(); break; @@ -462,6 +467,13 @@ proto.cc.arduino.cli.commands.v1.PlatformInstallRequest.serializeBinaryToWriter f ); } + f = message.getNoOverwrite(); + if (f) { + writer.writeBool( + 6, + f + ); + } }; @@ -574,6 +586,24 @@ proto.cc.arduino.cli.commands.v1.PlatformInstallRequest.prototype.setSkipPostIns }; +/** + * optional bool no_overwrite = 6; + * @return {boolean} + */ +proto.cc.arduino.cli.commands.v1.PlatformInstallRequest.prototype.getNoOverwrite = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 6, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.cc.arduino.cli.commands.v1.PlatformInstallRequest} returns this + */ +proto.cc.arduino.cli.commands.v1.PlatformInstallRequest.prototype.setNoOverwrite = function(value) { + return jspb.Message.setProto3BooleanField(this, 6, value); +}; + + diff --git a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/lib_pb.d.ts b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/lib_pb.d.ts index c3e5155fd..d8f4dc9cd 100644 --- a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/lib_pb.d.ts +++ b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/lib_pb.d.ts @@ -79,6 +79,9 @@ export class LibraryInstallRequest extends jspb.Message { getNoDeps(): boolean; setNoDeps(value: boolean): LibraryInstallRequest; + getNoOverwrite(): boolean; + setNoOverwrite(value: boolean): LibraryInstallRequest; + serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): LibraryInstallRequest.AsObject; @@ -96,6 +99,7 @@ export namespace LibraryInstallRequest { name: string, version: string, noDeps: boolean, + noOverwrite: boolean, } } diff --git a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/lib_pb.js b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/lib_pb.js index 44f24309b..be2398106 100644 --- a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/lib_pb.js +++ b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/lib_pb.js @@ -967,7 +967,8 @@ proto.cc.arduino.cli.commands.v1.LibraryInstallRequest.toObject = function(inclu instance: (f = msg.getInstance()) && cc_arduino_cli_commands_v1_common_pb.Instance.toObject(includeInstance, f), name: jspb.Message.getFieldWithDefault(msg, 2, ""), version: jspb.Message.getFieldWithDefault(msg, 3, ""), - noDeps: jspb.Message.getBooleanFieldWithDefault(msg, 4, false) + noDeps: jspb.Message.getBooleanFieldWithDefault(msg, 4, false), + noOverwrite: jspb.Message.getBooleanFieldWithDefault(msg, 5, false) }; if (includeInstance) { @@ -1021,6 +1022,10 @@ proto.cc.arduino.cli.commands.v1.LibraryInstallRequest.deserializeBinaryFromRead var value = /** @type {boolean} */ (reader.readBool()); msg.setNoDeps(value); break; + case 5: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setNoOverwrite(value); + break; default: reader.skipField(); break; @@ -1079,6 +1084,13 @@ proto.cc.arduino.cli.commands.v1.LibraryInstallRequest.serializeBinaryToWriter = f ); } + f = message.getNoOverwrite(); + if (f) { + writer.writeBool( + 5, + f + ); + } }; @@ -1173,6 +1185,24 @@ proto.cc.arduino.cli.commands.v1.LibraryInstallRequest.prototype.setNoDeps = fun }; +/** + * optional bool no_overwrite = 5; + * @return {boolean} + */ +proto.cc.arduino.cli.commands.v1.LibraryInstallRequest.prototype.getNoOverwrite = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 5, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.cc.arduino.cli.commands.v1.LibraryInstallRequest} returns this + */ +proto.cc.arduino.cli.commands.v1.LibraryInstallRequest.prototype.setNoOverwrite = function(value) { + return jspb.Message.setProto3BooleanField(this, 5, value); +}; + + diff --git a/arduino-ide-extension/src/node/library-service-impl.ts b/arduino-ide-extension/src/node/library-service-impl.ts index e0d3be567..c205826b5 100644 --- a/arduino-ide-extension/src/node/library-service-impl.ts +++ b/arduino-ide-extension/src/node/library-service-impl.ts @@ -252,6 +252,7 @@ export class LibraryServiceImpl progressId?: string; version?: Installable.Version; installDependencies?: boolean; + noOverwrite?: boolean; }): Promise { const item = options.item; const version = !!options.version @@ -265,6 +266,7 @@ export class LibraryServiceImpl req.setName(item.name); req.setVersion(version); req.setNoDeps(!options.installDependencies); + req.setNoOverwrite(Boolean(options.noOverwrite)); console.info('>>> Starting library package installation...', item); @@ -291,7 +293,7 @@ export class LibraryServiceImpl }.\n`, }); this.responseService.appendToOutput({ - chunk: error.toString(), + chunk: `${error.toString()}\n`, }); reject(error); });