Skip to content

Commit 4c90f79

Browse files
Merge pull request #857 from gjsjohnmurray/fix-854
support isfs copy
2 parents 2a2a474 + ce91c3d commit 4c90f79

File tree

2 files changed

+76
-30
lines changed

2 files changed

+76
-30
lines changed

src/api/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,8 @@ export class AtelierAPI {
390390
throw { statusCode: response.status, message: response.statusText, errorText: data.status.summary };
391391
}
392392
if (data.result.status && data.result.status !== "") {
393-
// This is a 4XX error on a doc request
393+
// This could be a 4XX error on a doc request
394+
// or a 200 from a deleteDoc request for which server-side source control blocked deletion
394395
throw { statusCode: response.status, message: response.statusText, errorText: data.result.status };
395396
}
396397
if (response.status >= 400) {

src/providers/FileSystemProvider/FileSystemProvider.ts

Lines changed: 74 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ declare function setTimeout(callback: (...args: any[]) => void, ms: number, ...a
1515
export type Entry = File | Directory;
1616

1717
export class FileSystemProvider implements vscode.FileSystemProvider {
18-
public root = new Directory("", "");
18+
private superRoot = new Directory("", "");
1919

2020
public readonly onDidChangeFile: vscode.Event<vscode.FileChangeEvent[]>;
2121

@@ -86,9 +86,9 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
8686
)
8787
.map((item: StudioOpenDialog) => {
8888
const name = item.Name;
89-
const fullName = folder === "" ? name : csp ? folder + name : folder + "/" + name;
9089
if (item.Type === "10" || item.Type === "9") {
9190
if (!parent.entries.has(name)) {
91+
const fullName = folder === "" ? name : csp ? folder + name : folder + "/" + name;
9292
parent.entries.set(name, new Directory(name, fullName));
9393
}
9494
return [name, vscode.FileType.Directory];
@@ -99,7 +99,15 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
9999
if (!csp) {
100100
return results;
101101
}
102-
return results.concat(cspSubfolders);
102+
cspSubfolders.forEach((value) => {
103+
const name = value[0];
104+
if (!parent.entries.has(name)) {
105+
const fullName = folder + name;
106+
parent.entries.set(name, new Directory(name, fullName));
107+
}
108+
results.push(value);
109+
});
110+
return results;
103111
})
104112
.catch((error) => {
105113
if (error) {
@@ -143,24 +151,42 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
143151
});
144152
}
145153

146-
private generateFileContent(fileName: string, content: Buffer): { content: string[]; enc: boolean } {
154+
private generateFileContent(fileName: string, sourceContent: Buffer): { content: string[]; enc: boolean } {
155+
const sourceLines = sourceContent.toString().split("\n");
147156
const fileExt = fileName.split(".").pop().toLowerCase();
148157
if (fileExt === "cls") {
149158
const className = fileName.split(".").slice(0, -1).join(".");
159+
const content: string[] = [];
160+
const preamble: string[] = [];
161+
162+
// If content was provided (e.g. when copying a file), use all lines except for
163+
// the Class x.y one. Replace that with one to match fileName.
164+
while (sourceLines.length > 0) {
165+
const nextLine = sourceLines.shift();
166+
if (nextLine.startsWith("Class ")) {
167+
content.push(...preamble, `Class ${className}`, ...sourceLines);
168+
break;
169+
}
170+
preamble.push(nextLine);
171+
}
172+
if (content.length === 0) {
173+
content.push(`Class ${className}`, "{", "}");
174+
}
150175
return {
151-
content: [`Class ${className} {}`],
176+
content,
152177
enc: false,
153178
};
154179
} else if (["int", "inc", "mac"].includes(fileExt)) {
180+
sourceLines.shift();
155181
const routineName = fileName.split(".").slice(0, -1).join(".");
156182
const routineType = `[ type = ${fileExt}]`;
157183
return {
158-
content: [`ROUTINE ${routineName} ${routineType}`],
184+
content: [`ROUTINE ${routineName} ${routineType}`, ...sourceLines],
159185
enc: false,
160186
};
161187
}
162188
return {
163-
content: [content.toString("base64")],
189+
content: [sourceContent.toString("base64")],
164190
enc: true,
165191
};
166192
}
@@ -265,27 +291,42 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
265291
if (fileName.startsWith(".")) {
266292
return;
267293
}
294+
if (!fileName.includes(".")) {
295+
throw new Error(`${csp ? "Folder" : "Package"} deletion is not supported on server`);
296+
}
268297
const api = new AtelierAPI(uri);
269-
return api.deleteDoc(fileName).then((response) => {
270-
if (response.result.ext) {
271-
fireOtherStudioAction(OtherStudioAction.DeletedDocument, uri, response.result.ext);
298+
return api.deleteDoc(fileName).then(
299+
async (response) => {
300+
if (response.result.ext) {
301+
fireOtherStudioAction(OtherStudioAction.DeletedDocument, uri, response.result.ext);
302+
}
303+
// Remove entry from our cache, plus any now-empty ancestor entries
304+
let thisUri = vscode.Uri.parse(uri.toString(), true);
305+
const events: vscode.FileChangeEvent[] = [];
306+
while (thisUri.path !== "/") {
307+
events.push({ type: vscode.FileChangeType.Deleted, uri: thisUri });
308+
const parentDir = await this._lookupParentDirectory(thisUri);
309+
const name = path.basename(thisUri.path);
310+
parentDir.entries.delete(name);
311+
if (!csp && parentDir.entries.size === 0) {
312+
thisUri = thisUri.with({ path: path.posix.dirname(thisUri.path) });
313+
} else {
314+
break;
315+
}
316+
}
317+
this._fireSoon(...events);
318+
},
319+
(error) => {
320+
if (error.errorText !== "") {
321+
error.message = error.errorText;
322+
}
323+
throw error;
272324
}
273-
// Remove entry from our cache
274-
this._lookupParentDirectory(uri).then((parent) => {
275-
const name = path.basename(uri.path);
276-
parent.entries.delete(name);
277-
});
278-
this._fireSoon({ type: vscode.FileChangeType.Deleted, uri });
279-
});
325+
);
280326
}
281327

282328
public rename(oldUri: vscode.Uri, newUri: vscode.Uri, options: { overwrite: boolean }): void | Thenable<void> {
283-
throw new Error("Not implemented");
284-
return;
285-
}
286-
public copy?(source: vscode.Uri, destination: vscode.Uri, options: { overwrite: boolean }): void | Thenable<void> {
287-
throw new Error("Not implemented");
288-
return;
329+
throw new Error("Move / rename is not supported on server");
289330
}
290331

291332
public watch(uri: vscode.Uri): vscode.Disposable {
@@ -296,17 +337,23 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
296337

297338
// Fetch entry (a file or directory) from cache, else from server
298339
private async _lookup(uri: vscode.Uri): Promise<Entry> {
340+
const api = new AtelierAPI(uri);
299341
if (uri.path === "/") {
300-
const api = new AtelierAPI(uri);
301342
await api
302343
.serverInfo()
303344
.then()
304345
.catch(() => {
305346
throw vscode.FileSystemError.Unavailable(`${uri.toString()} is unavailable`);
306347
});
307348
}
349+
const config = api.config;
350+
const rootName = `${config.username}@${config.host}:${config.port}${config.pathPrefix}/${config.ns.toUpperCase()}`;
351+
let entry: Entry = this.superRoot.entries.get(rootName);
352+
if (!entry) {
353+
entry = new Directory(rootName, "");
354+
this.superRoot.entries.set(rootName, entry);
355+
}
308356
const parts = uri.path.split("/");
309-
let entry: Entry = this.root;
310357
for (let i = 0; i < parts.length; i++) {
311358
const part = parts[i];
312359
if (!part) {
@@ -317,10 +364,8 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
317364
child = entry.entries.get(part);
318365
// If the last element of path is dotted and is one we haven't already cached as a directory
319366
// then it is assumed to be a file.
320-
if ((!part.includes(".") || i + 1 < parts.length) && !child) {
321-
const fullName = entry.name === "" ? part : entry.fullName + "/" + part;
322-
child = new Directory(part, fullName);
323-
entry.entries.set(part, child);
367+
if (!child && (!part.includes(".") || i + 1 < parts.length)) {
368+
throw vscode.FileSystemError.FileNotFound(uri);
324369
}
325370
}
326371
if (!child) {

0 commit comments

Comments
 (0)