Skip to content

Commit 09697bc

Browse files
author
Akos Kitta
committed
feat: remote rename
Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
1 parent 1ceffaf commit 09697bc

15 files changed

+273
-190
lines changed

arduino-ide-extension/src/browser/contributions/create-contribution.ts

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,31 @@ import { SketchContribution } from './contribution';
1919
export function sketchAlreadyExists(input: string): string {
2020
return nls.localize(
2121
'arduino/cloudSketch/sketchAlreadyExists',
22-
"Remote sketch '{0}' already exists.",
22+
"Cloud sketch '{0}' already exists.",
23+
input
24+
);
25+
}
26+
27+
export function notFound(input: string): string {
28+
return nls.localize(
29+
'arduino/cloudSketch/notFound',
30+
"Could not pull the cloud sketch '{0}'. It does not exist.",
31+
input
32+
);
33+
}
34+
35+
export function pullingSketch(input: string): string {
36+
return nls.localize(
37+
'arduino/cloudSketch/pulling',
38+
"Synchronizing sketchbook, pulling '{0}'...",
39+
input
40+
);
41+
}
42+
43+
export function pushingSketch(input: string): string {
44+
return nls.localize(
45+
'arduino/cloudSketch/pushing',
46+
"Synchronizing sketchbook, pushing '{0}'...",
2347
input
2448
);
2549
}
@@ -39,6 +63,15 @@ export abstract class CloudSketchContribution extends SketchContribution {
3963
return this.localCacheFsProvider.from(new URI(sketch.uri));
4064
}
4165

66+
protected localCacheUri(cloudUri: URI): URI | undefined {
67+
if (cloudUri.scheme !== CreateUri.scheme) {
68+
throw new Error(
69+
`Expected '${CreateUri.scheme}'. Got ${cloudUri.toString()}`
70+
);
71+
}
72+
return this.localCacheFsProvider.to(cloudUri);
73+
}
74+
4275
protected async treeModel(): Promise<
4376
(CloudSketchbookTreeModel & { root: CompositeTreeNode }) | undefined
4477
> {
@@ -65,7 +98,7 @@ export abstract class CloudSketchContribution extends SketchContribution {
6598
}
6699
}
67100

68-
private async pull(
101+
protected async pull(
69102
sketch: Create.Sketch
70103
): Promise<CloudSketchbookTree.CloudSketchDirNode | undefined> {
71104
const treeModel = await this.treeModel();
@@ -76,26 +109,21 @@ export abstract class CloudSketchContribution extends SketchContribution {
76109
const node = treeModel.getNode(id);
77110
if (!node) {
78111
throw new Error(
79-
`Could not find remote sketchbook tree node with Tree node ID: ${id}.`
112+
`Could not find cloud sketchbook tree node with ID: ${id}.`
80113
);
81114
}
82115
if (!CloudSketchbookTree.CloudSketchDirNode.is(node)) {
83116
throw new Error(
84-
`Remote sketchbook tree node expected to represent a directory but it did not. Tree node ID: ${id}.`
117+
`Cloud sketchbook tree node expected to represent a directory but it did not. Tree node ID: ${id}.`
85118
);
86119
}
87120
try {
88121
await treeModel.sketchbookTree().pull({ node });
122+
return node;
89123
} catch (err) {
90124
if (isNotFound(err)) {
91125
await treeModel.refresh();
92-
this.messageService.error(
93-
nls.localize(
94-
'arduino/cloudSketch/notFound',
95-
"Could not pull the remote sketch '{0}'. It does not exist.",
96-
sketch.name
97-
)
98-
);
126+
this.messageService.error(notFound(sketch.name));
99127
return undefined;
100128
}
101129
throw err;

arduino-ide-extension/src/browser/contributions/delete-sketch.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export class DeleteSketch extends CloudSketchContribution {
5959
if (!willNavigateAway) {
6060
return this.sketchesService.deleteSketch(sketch);
6161
}
62-
const cloudUri = this.cloudUri(sketch); // TODO: warn user that it's a remote sketch
62+
const cloudUri = this.cloudUri(sketch); // TODO: warn user that it's a cloud sketch
6363
if (willNavigateAway !== 'force') {
6464
const { response } = await remote.dialog.showMessageBox({
6565
title: nls.localizeByDefault('Delete'),
@@ -77,22 +77,22 @@ export class DeleteSketch extends CloudSketchContribution {
7777
}
7878
if (cloudUri) {
7979
const posixPath = cloudUri.path.toString();
80-
const remoteSketch = this.createApi.sketchCache.getSketch(posixPath);
81-
if (!remoteSketch) {
80+
const cloudSketch = this.createApi.sketchCache.getSketch(posixPath);
81+
if (!cloudSketch) {
8282
throw new Error(
83-
`Remote sketch with path '${posixPath}' was not cached. Cache: ${this.createApi.sketchCache.toString()}`
83+
`Cloud sketch with path '${posixPath}' was not cached. Cache: ${this.createApi.sketchCache.toString()}`
8484
);
8585
}
8686
try {
8787
// IDE2 cannot use DELETE directory as the server responses with HTTP 500 if it's missing.
8888
// https://github.com/arduino/arduino-ide/issues/1825#issuecomment-1406301406
89-
await this.createApi.deleteSketch(remoteSketch.path);
89+
await this.createApi.deleteSketch(cloudSketch.path);
9090
} catch (err) {
9191
if (!isNotFound(err)) {
9292
throw err;
9393
} else {
9494
console.info(
95-
`Could not delete the remote sketch with path '${posixPath}'. It does not exist.`
95+
`Could not delete the cloud sketch with path '${posixPath}'. It does not exist.`
9696
);
9797
}
9898
}

arduino-ide-extension/src/browser/contributions/new-cloud-sketch.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { CloudSketchbookTreeModel } from '../widgets/cloud-sketchbook/cloud-sket
1919
import { Command, CommandRegistry, Sketch } from './contribution';
2020
import {
2121
CloudSketchContribution,
22+
pullingSketch,
2223
sketchAlreadyExists,
2324
} from './create-contribution';
2425

@@ -51,7 +52,7 @@ export class NewCloudSketch extends CloudSketchContribution {
5152
override registerMenus(registry: MenuModelRegistry): void {
5253
registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, {
5354
commandId: NewCloudSketch.Commands.NEW_CLOUD_SKETCH.id,
54-
label: nls.localize('arduino/cloudSketch/new', 'New Remote Sketch'),
55+
label: nls.localize('arduino/cloudSketch/new', 'New Cloud Sketch'),
5556
order: '1',
5657
});
5758
}
@@ -86,7 +87,7 @@ export class NewCloudSketch extends CloudSketchContribution {
8687
{
8788
title: nls.localize(
8889
'arduino/newCloudSketch/newSketchTitle',
89-
'Name of the new Remote Sketch'
90+
'Name of the new Cloud Sketch'
9091
),
9192
parentUri: CreateUri.root,
9293
initialValue,
@@ -112,7 +113,7 @@ export class NewCloudSketch extends CloudSketchContribution {
112113
progress.report({
113114
message: nls.localize(
114115
'arduino/cloudSketch/creating',
115-
"Creating remote sketch '{0}'...",
116+
"Creating cloud sketch '{0}'...",
116117
value
117118
),
118119
});
@@ -126,11 +127,7 @@ export class NewCloudSketch extends CloudSketchContribution {
126127
} finally {
127128
if (result) {
128129
progress.report({
129-
message: nls.localize(
130-
'arduino/cloudSketch/synchronizing',
131-
"Synchronizing sketchbook, pulling '{0}'...",
132-
value
133-
),
130+
message: pullingSketch(value),
134131
});
135132
await treeModel.refresh();
136133
}

arduino-ide-extension/src/browser/contributions/rename-cloud-sketch.ts

Lines changed: 68 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { CompositeTreeNode } from '@theia/core/lib/browser/tree';
1+
import { CompositeTreeNode } from '@theia/core/lib/browser';
22
import { Progress } from '@theia/core/lib/common/message-service-protocol';
33
import { nls } from '@theia/core/lib/common/nls';
44
import { injectable } from '@theia/core/shared/inversify';
@@ -12,10 +12,12 @@ import {
1212
import { WorkspaceInputDialogWithProgress } from '../theia/workspace/workspace-input-dialog';
1313
import { CloudSketchbookTree } from '../widgets/cloud-sketchbook/cloud-sketchbook-tree';
1414
import { CloudSketchbookTreeModel } from '../widgets/cloud-sketchbook/cloud-sketchbook-tree-model';
15-
import { SketchbookTree } from '../widgets/sketchbook/sketchbook-tree';
1615
import { Command, CommandRegistry, Sketch, URI } from './contribution';
17-
import { CloudSketchContribution } from './create-contribution';
18-
import { DeleteSketch, DeleteSketchParams } from './delete-sketch';
16+
import {
17+
CloudSketchContribution,
18+
pushingSketch,
19+
sketchAlreadyExists,
20+
} from './create-contribution';
1921

2022
export interface RenameCloudSketchParams {
2123
readonly cloudUri: URI;
@@ -33,109 +35,121 @@ export class RenameCloudSketch extends CloudSketchContribution {
3335
private async renameSketch(
3436
params: RenameCloudSketchParams,
3537
initValue: string = params.sketch.name
36-
): Promise<URI | undefined> {
38+
): Promise<string | undefined> {
3739
const treeModel = await this.treeModel();
3840
if (treeModel) {
3941
const posixPath = params.cloudUri.path.toString();
4042
const node = treeModel.getNode(posixPath);
41-
if (SketchbookTree.SketchDirNode.is(node)) {
42-
const result = await this.openWizard(
43-
params,
44-
node,
45-
treeModel.root,
46-
treeModel,
47-
initValue
48-
);
49-
if (result) {
50-
console.log(result);
51-
}
43+
const parentNode = node?.parent;
44+
if (
45+
CloudSketchbookTree.CloudSketchDirNode.is(node) &&
46+
CompositeTreeNode.is(parentNode)
47+
) {
48+
return this.openWizard(params, node, parentNode, treeModel, initValue);
5249
}
5350
}
5451
return undefined;
5552
}
5653

5754
private async openWizard(
5855
params: RenameCloudSketchParams,
59-
node: SketchbookTree.SketchDirNode,
60-
rootNode: CompositeTreeNode,
56+
node: CloudSketchbookTree.CloudSketchDirNode,
57+
parentNode: CompositeTreeNode,
6158
treeModel: CloudSketchbookTreeModel,
6259
initialValue?: string | undefined
6360
): Promise<string | undefined> {
64-
const existingNames = rootNode.children
61+
const parentUri = CloudSketchbookTree.CloudSketchDirNode.is(parentNode)
62+
? parentNode.uri
63+
: CreateUri.root;
64+
const existingNames = parentNode.children
6565
.filter(CloudSketchbookTree.CloudSketchDirNode.is)
6666
.map(({ fileStat }) => fileStat.name);
67-
return new WorkspaceInputDialogWithProgress(
67+
const value = await new WorkspaceInputDialogWithProgress(
6868
{
6969
title: nls.localize(
7070
'arduino/renameCloudSketch/renameSketchTitle',
71-
'New name of the Remote Sketch'
71+
'New name of the Cloud Sketch'
7272
),
73-
parentUri: CreateUri.root,
73+
parentUri,
7474
initialValue,
7575
validate: (input) => {
7676
if (existingNames.includes(input)) {
77-
return nls.localize(
78-
'arduino/newCloudSketch/sketchAlreadyExists',
79-
"Remote sketch '{0}' already exists.",
80-
input
81-
);
77+
return sketchAlreadyExists(input);
8278
}
8379
return Sketch.validateCloudSketchFolderName(input) ?? '';
8480
},
8581
},
8682
this.labelProvider,
87-
(value) => this.renameSketchWithProgress(params, value, treeModel)
83+
(value) => {
84+
return this.renameSketchWithProgress(params, node, treeModel, value);
85+
}
8886
).open();
87+
// The input dialog resolves with the <input> value not the URI.
88+
// IDE2 must remap the value string to the target URI string in the local cache.
89+
if (value) {
90+
return new URI(params.sketch.uri).parent.resolve(value).toString();
91+
}
92+
return undefined;
8993
}
9094

9195
private renameSketchWithProgress(
9296
params: RenameCloudSketchParams,
93-
value: string,
94-
treeModel: CloudSketchbookTreeModel
97+
node: CloudSketchbookTree.CloudSketchDirNode,
98+
treeModel: CloudSketchbookTreeModel,
99+
value: string
95100
): (progress: Progress) => Promise<unknown> {
96101
return async (progress: Progress) => {
97-
let result: Create.Sketch | undefined | ConflictError;
102+
const fromPosixPath = params.cloudUri.path.toString();
103+
const toPosixPath = params.cloudUri.parent.resolve(value).path.toString();
104+
let result: Create.Sketch | ConflictError | undefined;
98105
try {
106+
// push
107+
progress.report({ message: pushingSketch(params.sketch.name) });
108+
await treeModel.sketchbookTree().push(node);
109+
110+
// rename
99111
progress.report({
100112
message: nls.localize(
101113
'arduino/cloudSketch/renaming',
102-
"Renaming remote sketch '{0}'...",
114+
"Renaming cloud sketch '{0}'...",
103115
value
104116
),
105117
});
106-
result = await this.createApi.createSketch(value);
118+
await this.createApi.rename(fromPosixPath, toPosixPath);
119+
120+
// sync
121+
progress.report({
122+
message: nls.localize(
123+
'arduino/cloudSketch/renaming',
124+
"Renaming cloud sketch '{0}'...",
125+
value
126+
),
127+
});
128+
this.createApi.sketchCache.init(); // invalidate the cache
129+
await this.createApi.sketches(); // IDE2 must pull all sketches to find the new one
130+
const newSketch = this.createApi.sketchCache.getSketch(toPosixPath);
131+
if (!newSketch) {
132+
return undefined;
133+
}
134+
135+
// pull
136+
await treeModel.refresh();
137+
const pulledNode = await this.pull(newSketch);
138+
if (pulledNode) {
139+
result = newSketch;
140+
}
107141
} catch (err) {
108142
if (isConflict(err)) {
109143
result = err;
110144
} else {
111145
throw err;
112146
}
113-
} finally {
114-
if (result) {
115-
progress.report({
116-
message: nls.localize(
117-
'arduino/cloudSketch/synchronizing',
118-
"Synchronizing sketchbook, pulling '{0}'...",
119-
value
120-
),
121-
});
122-
await treeModel.refresh();
123-
}
124147
}
125148
if (result instanceof CreateError) {
126149
return this.renameSketch(params, value);
127150
}
128151
if (result) {
129-
setTimeout(() => {
130-
this.commandService.executeCommand(
131-
DeleteSketch.Commands.DELETE_SKETCH.id,
132-
<DeleteSketchParams>{
133-
toDelete: params.sketch,
134-
willNavigateAway: 'force',
135-
}
136-
);
137-
}, 0);
138-
return this.openInNewWindow(result);
152+
return CreateUri.toUri(result).toString();
139153
}
140154
return undefined;
141155
};

0 commit comments

Comments
 (0)