ATL-58: Archive sketch.

Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
Akos Kitta 2021-02-01 11:04:42 +01:00 committed by Akos Kitta
parent a8e60698a8
commit b65867d2f4
4 changed files with 86 additions and 1 deletions

View File

@ -139,6 +139,7 @@ import { Help } from './contributions/help';
import { bindArduinoPreferences } from './arduino-preferences'
import { SettingsService, SettingsDialog, SettingsWidget, SettingsDialogProps } from './settings';
import { AddFile } from './contributions/add-file';
import { ArchiveSketch } from './contributions/archive-sketch';
const ElementQueries = require('css-element-queries/src/ElementQueries');
@ -346,6 +347,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
Contribution.configure(bind, OpenRecentSketch);
Contribution.configure(bind, Help);
Contribution.configure(bind, AddFile);
Contribution.configure(bind, ArchiveSketch);
bind(OutputServiceImpl).toSelf().inSingletonScope().onActivation(({ container }, outputService) => {
WebSocketConnectionProvider.createProxy(container, OutputServicePath, outputService);

View File

@ -0,0 +1,55 @@
import { injectable } from 'inversify';
import { remote } from 'electron';
import * as dateFormat from 'dateformat';
import URI from '@theia/core/lib/common/uri';
import { ArduinoMenus } from '../menu/arduino-menus';
import { SketchContribution, Command, CommandRegistry, MenuModelRegistry } from './contribution';
@injectable()
export class ArchiveSketch extends SketchContribution {
registerCommands(registry: CommandRegistry): void {
registry.registerCommand(ArchiveSketch.Commands.ARCHIVE_SKETCH, {
execute: () => this.archiveSketch()
});
}
registerMenus(registry: MenuModelRegistry): void {
registry.registerMenuAction(ArduinoMenus.TOOLS__MAIN_GROUP, {
commandId: ArchiveSketch.Commands.ARCHIVE_SKETCH.id,
label: 'Archive Sketch',
order: '1'
});
}
protected async archiveSketch(): Promise<void> {
const [sketch, config] = await Promise.all([
this.sketchServiceClient.currentSketch(),
this.configService.getConfiguration()
]);
if (!sketch) {
return;
}
const archiveBasename = `${sketch.name}-${dateFormat(new Date(), 'yymmdd')}a.zip`;
const defaultPath = await this.fileService.fsPath(new URI(config.sketchDirUri).resolve(archiveBasename));
const { filePath, canceled } = await remote.dialog.showSaveDialog({ title: 'Save sketch folder as...', defaultPath });
if (!filePath || canceled) {
return;
}
const destinationUri = await this.fileSystemExt.getUri(filePath);
if (!destinationUri) {
return;
}
await this.sketchService.archive(sketch, destinationUri.toString());
this.messageService.info(`Created archive '${archiveBasename}'.`, { timeout: 2000 });
}
}
export namespace ArchiveSketch {
export namespace Commands {
export const ARCHIVE_SKETCH: Command = {
id: 'arduino-archive-sketch'
};
}
}

View File

@ -58,6 +58,11 @@ export interface SketchesService {
*/
recentlyOpenedSketches(): Promise<Sketch[]>;
/**
* Archives the sketch, resolves to the archive URI.
*/
archive(sketch: Sketch, destinationUri: string): Promise<string>;
}
export interface Sketch {

View File

@ -14,7 +14,7 @@ import { firstToLowerCase } from '../common/utils';
import { NotificationServiceServerImpl } from './notification-service-server';
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
import { CoreClientProvider } from './core-client-provider';
import { LoadSketchReq } from './cli-protocol/commands/commands_pb';
import { LoadSketchReq, ArchiveSketchReq } from './cli-protocol/commands/commands_pb';
const WIN32_DRIVE_REGEXP = /^[a-zA-Z]:\\/;
@ -324,6 +324,29 @@ void loop() {
return FileUri.create(destination).toString();
}
async archive(sketch: Sketch, destinationUri: string): Promise<string> {
await this.loadSketch(sketch.uri); // sanity check
const { client } = await this.coreClient();
const archivePath = FileUri.fsPath(destinationUri);
// The CLI cannot override existing archives, so we have to wipe it manually: https://github.com/arduino/arduino-cli/issues/1160
if (await fs.exists(archivePath)) {
await fs.unlink(archivePath);
}
const req = new ArchiveSketchReq();
req.setSketchPath(FileUri.fsPath(sketch.uri));
req.setArchivePath(archivePath);
await new Promise<string>((resolve, reject) => {
client.archiveSketch(req, err => {
if (err) {
reject(err);
return;
}
resolve(destinationUri);
});
});
return destinationUri;
}
private async coreClient(): Promise<CoreClientProvider.Client> {
const coreClient = await new Promise<CoreClientProvider.Client>(async resolve => {
const client = await this.coreClientProvider.client();