Skip to content

Commit b65867d

Browse files
Akos Kittakittaakos
Akos Kitta
authored andcommitted
ATL-58: Archive sketch.
Signed-off-by: Akos Kitta <kittaakos@typefox.io>
1 parent a8e6069 commit b65867d

File tree

4 files changed

+86
-1
lines changed

4 files changed

+86
-1
lines changed

arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts

+2
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ import { Help } from './contributions/help';
139139
import { bindArduinoPreferences } from './arduino-preferences'
140140
import { SettingsService, SettingsDialog, SettingsWidget, SettingsDialogProps } from './settings';
141141
import { AddFile } from './contributions/add-file';
142+
import { ArchiveSketch } from './contributions/archive-sketch';
142143

143144
const ElementQueries = require('css-element-queries/src/ElementQueries');
144145

@@ -346,6 +347,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
346347
Contribution.configure(bind, OpenRecentSketch);
347348
Contribution.configure(bind, Help);
348349
Contribution.configure(bind, AddFile);
350+
Contribution.configure(bind, ArchiveSketch);
349351

350352
bind(OutputServiceImpl).toSelf().inSingletonScope().onActivation(({ container }, outputService) => {
351353
WebSocketConnectionProvider.createProxy(container, OutputServicePath, outputService);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { injectable } from 'inversify';
2+
import { remote } from 'electron';
3+
import * as dateFormat from 'dateformat';
4+
import URI from '@theia/core/lib/common/uri';
5+
import { ArduinoMenus } from '../menu/arduino-menus';
6+
import { SketchContribution, Command, CommandRegistry, MenuModelRegistry } from './contribution';
7+
8+
@injectable()
9+
export class ArchiveSketch extends SketchContribution {
10+
11+
registerCommands(registry: CommandRegistry): void {
12+
registry.registerCommand(ArchiveSketch.Commands.ARCHIVE_SKETCH, {
13+
execute: () => this.archiveSketch()
14+
});
15+
}
16+
17+
registerMenus(registry: MenuModelRegistry): void {
18+
registry.registerMenuAction(ArduinoMenus.TOOLS__MAIN_GROUP, {
19+
commandId: ArchiveSketch.Commands.ARCHIVE_SKETCH.id,
20+
label: 'Archive Sketch',
21+
order: '1'
22+
});
23+
}
24+
25+
protected async archiveSketch(): Promise<void> {
26+
const [sketch, config] = await Promise.all([
27+
this.sketchServiceClient.currentSketch(),
28+
this.configService.getConfiguration()
29+
]);
30+
if (!sketch) {
31+
return;
32+
}
33+
const archiveBasename = `${sketch.name}-${dateFormat(new Date(), 'yymmdd')}a.zip`;
34+
const defaultPath = await this.fileService.fsPath(new URI(config.sketchDirUri).resolve(archiveBasename));
35+
const { filePath, canceled } = await remote.dialog.showSaveDialog({ title: 'Save sketch folder as...', defaultPath });
36+
if (!filePath || canceled) {
37+
return;
38+
}
39+
const destinationUri = await this.fileSystemExt.getUri(filePath);
40+
if (!destinationUri) {
41+
return;
42+
}
43+
await this.sketchService.archive(sketch, destinationUri.toString());
44+
this.messageService.info(`Created archive '${archiveBasename}'.`, { timeout: 2000 });
45+
}
46+
47+
}
48+
49+
export namespace ArchiveSketch {
50+
export namespace Commands {
51+
export const ARCHIVE_SKETCH: Command = {
52+
id: 'arduino-archive-sketch'
53+
};
54+
}
55+
}

arduino-ide-extension/src/common/protocol/sketches-service.ts

+5
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ export interface SketchesService {
5858
*/
5959
recentlyOpenedSketches(): Promise<Sketch[]>;
6060

61+
/**
62+
* Archives the sketch, resolves to the archive URI.
63+
*/
64+
archive(sketch: Sketch, destinationUri: string): Promise<string>;
65+
6166
}
6267

6368
export interface Sketch {

arduino-ide-extension/src/node/sketches-service-impl.ts

+24-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { firstToLowerCase } from '../common/utils';
1414
import { NotificationServiceServerImpl } from './notification-service-server';
1515
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
1616
import { CoreClientProvider } from './core-client-provider';
17-
import { LoadSketchReq } from './cli-protocol/commands/commands_pb';
17+
import { LoadSketchReq, ArchiveSketchReq } from './cli-protocol/commands/commands_pb';
1818

1919
const WIN32_DRIVE_REGEXP = /^[a-zA-Z]:\\/;
2020

@@ -324,6 +324,29 @@ void loop() {
324324
return FileUri.create(destination).toString();
325325
}
326326

327+
async archive(sketch: Sketch, destinationUri: string): Promise<string> {
328+
await this.loadSketch(sketch.uri); // sanity check
329+
const { client } = await this.coreClient();
330+
const archivePath = FileUri.fsPath(destinationUri);
331+
// The CLI cannot override existing archives, so we have to wipe it manually: https://github.com/arduino/arduino-cli/issues/1160
332+
if (await fs.exists(archivePath)) {
333+
await fs.unlink(archivePath);
334+
}
335+
const req = new ArchiveSketchReq();
336+
req.setSketchPath(FileUri.fsPath(sketch.uri));
337+
req.setArchivePath(archivePath);
338+
await new Promise<string>((resolve, reject) => {
339+
client.archiveSketch(req, err => {
340+
if (err) {
341+
reject(err);
342+
return;
343+
}
344+
resolve(destinationUri);
345+
});
346+
});
347+
return destinationUri;
348+
}
349+
327350
private async coreClient(): Promise<CoreClientProvider.Client> {
328351
const coreClient = await new Promise<CoreClientProvider.Client>(async resolve => {
329352
const client = await this.coreClientProvider.client();

0 commit comments

Comments
 (0)