Skip to content

Commit

Permalink
Prevent overwriting existing libraries and platforms at first IDE sta…
Browse files Browse the repository at this point in the history
…rt-up (arduino#1169)

* move initialization of libs and platforms into new contribution

* use noOverwrite when install built-in libraries and platform

* catch errors when installing platforms and libraries at first start-up

* arduino-cli version 0.25.0-rc1

* refine platforms and libraries initialization in case of errors

* add trailing newline when libraries and platform installation fail

* use regex to check error if builtin library dependencies are already installed

* rename contribution
  • Loading branch information
Alberto Iannaccone authored Jul 15, 2022
1 parent 46fcc71 commit 73835ec
Show file tree
Hide file tree
Showing 14 changed files with 213 additions and 32 deletions.
2 changes: 1 addition & 1 deletion arduino-ide-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@
],
"arduino": {
"cli": {
"version": "0.24.0"
"version": "0.25.0-rc1"
},
"fwuploader": {
"version": "2.2.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
SketchesService,
ExecutableService,
Sketch,
LibraryService,
ArduinoDaemon,
} from '../common/protocol';
import { Mutex } from 'async-mutex';
Expand Down Expand Up @@ -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()
Expand All @@ -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;

Expand Down Expand Up @@ -162,27 +157,6 @@ export class ArduinoFrontendContribution

@postConstruct()
protected async init(): Promise<void> {
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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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<void> {
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';
}
1 change: 1 addition & 0 deletions arduino-ide-extension/src/common/protocol/installable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export interface Installable<T extends ArduinoComponent> {
item: T;
progressId?: string;
version?: Installable.Version;
noOverwrite?: boolean;
}): Promise<void>;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface LibraryService
progressId?: string;
version?: Installable.Version;
installDependencies?: boolean;
noOverwrite?: boolean;
}): Promise<void>;
installZip(options: {
zipUri: string;
Expand Down
4 changes: 3 additions & 1 deletion arduino-ide-extension/src/node/boards-service-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ export class BoardsServiceImpl
item: BoardsPackage;
progressId?: string;
version?: Installable.Version;
noOverwrite?: boolean;
}): Promise<void> {
const item = options.item;
const version = !!options.version
Expand All @@ -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);

Expand All @@ -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);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -133,6 +136,7 @@ export namespace CompileRequest {
keysKeychain: string,
signKey: string,
encryptKey: string,
skipLibrariesDiscovery: boolean,
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -482,6 +487,13 @@ proto.cc.arduino.cli.commands.v1.CompileRequest.serializeBinaryToWriter = functi
f
);
}
f = message.getSkipLibrariesDiscovery();
if (f) {
writer.writeBool(
28,
f
);
}
};


Expand Down Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -44,6 +47,7 @@ export namespace PlatformInstallRequest {
architecture: string,
version: string,
skipPostInstall: boolean,
noOverwrite: boolean,
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -462,6 +467,13 @@ proto.cc.arduino.cli.commands.v1.PlatformInstallRequest.serializeBinaryToWriter
f
);
}
f = message.getNoOverwrite();
if (f) {
writer.writeBool(
6,
f
);
}
};


Expand Down Expand Up @@ -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);
};





Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -96,6 +99,7 @@ export namespace LibraryInstallRequest {
name: string,
version: string,
noDeps: boolean,
noOverwrite: boolean,
}
}

Expand Down
Loading

0 comments on commit 73835ec

Please sign in to comment.