Skip to content

Commit 5749221

Browse files
authored
Replace node fs with vscode workspace.fs (intersystems-community#976)
1 parent 959ab95 commit 5749221

File tree

3 files changed

+105
-124
lines changed

3 files changed

+105
-124
lines changed

src/commands/compile.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import fs = require("fs");
21
import glob = require("glob");
32
import path = require("path");
43
import vscode = require("vscode");
@@ -55,14 +54,14 @@ export async function checkChangedOnServer(file: CurrentFile, force = false): Pr
5554
(await api
5655
.getDoc(file.name)
5756
.then((data) => data.result)
58-
.then(({ ts, content }) => {
57+
.then(async ({ ts, content }) => {
5958
const fileContent = file.content.split(/\r?\n/);
6059
const serverTime = Number(new Date(ts + "Z"));
6160
const sameContent = force
6261
? false
6362
: content.every((line, index) => line.trim() == (fileContent[index] || "").trim());
6463
const mtime =
65-
force || sameContent ? serverTime : Math.max(Number(fs.statSync(file.fileName).mtime), serverTime);
64+
force || sameContent ? serverTime : Math.max((await vscode.workspace.fs.stat(file.uri)).mtime, serverTime);
6665
return mtime;
6766
})
6867
.catch(() => -1));
@@ -197,12 +196,12 @@ export async function loadChanges(files: CurrentFile[]): Promise<any> {
197196
files.map((file) =>
198197
api
199198
.getDoc(file.name)
200-
.then((data) => {
199+
.then(async (data) => {
201200
const content = (data.result.content || []).join(file.eol === vscode.EndOfLine.LF ? "\n" : "\r\n");
202201
const mtime = Number(new Date(data.result.ts + "Z"));
203202
workspaceState.update(`${file.uniqueId}:mtime`, mtime > 0 ? mtime : undefined);
204203
if (file.uri.scheme === "file") {
205-
fs.writeFileSync(file.fileName, content);
204+
await vscode.workspace.fs.writeFile(file.uri, new TextEncoder().encode(content));
206205
} else if (file.uri.scheme === FILESYSTEM_SCHEMA || file.uri.scheme === FILESYSTEM_READONLY_SCHEMA) {
207206
fileSystemProvider.fireFileChanged(file.uri);
208207
}
@@ -398,12 +397,13 @@ export async function namespaceCompile(askFlags = false): Promise<any> {
398397
);
399398
}
400399

401-
function importFiles(files, noCompile = false) {
400+
function importFiles(files: string[], noCompile = false) {
402401
return Promise.all<CurrentFile>(
403402
files.map(
404-
throttleRequests((file) =>
405-
fs.promises
406-
.readFile(file, { encoding: "utf8" })
403+
throttleRequests((file: string) =>
404+
vscode.workspace.fs
405+
.readFile(vscode.Uri.file(file))
406+
.then((contentBytes) => new TextDecoder().decode(contentBytes))
407407
.then((content) => currentFileFromContent(file, content))
408408
.then((curFile) =>
409409
importFile(curFile).then((data) => {
@@ -418,7 +418,7 @@ function importFiles(files, noCompile = false) {
418418

419419
export async function importFolder(uri: vscode.Uri, noCompile = false): Promise<any> {
420420
const uripath = uri.fsPath;
421-
if (fs.lstatSync(uripath).isFile()) {
421+
if ((await vscode.workspace.fs.stat(uri)).type != vscode.FileType.Directory) {
422422
return importFiles([uripath], noCompile);
423423
}
424424
let globpattern = "*.{cls,inc,int,mac}";

src/commands/export.ts

Lines changed: 78 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import fs = require("fs");
21
import path = require("path");
32
import * as vscode from "vscode";
43
import { AtelierAPI } from "../api";
54
import { config, explorerProvider, OBJECTSCRIPT_FILE_SCHEMA, schemas } from "../extension";
6-
import { currentFile, mkdirSyncRecursive, notNull, outputChannel, uriOfWorkspaceFolder } from "../utils";
5+
import { currentFile, fileExists, notNull, outputChannel, uriOfWorkspaceFolder } from "../utils";
76
import { NodeBase } from "../explorer/models/nodeBase";
87

98
export const getCategory = (fileName: string, addCategory: any | boolean): string => {
@@ -99,92 +98,96 @@ export async function exportFile(
9998
const api = new AtelierAPI(workspaceFolder);
10099
api.setNamespace(namespace);
101100
const log = (status) => outputChannel.appendLine(`export "${name}" as "${fileName}" - ${status}`);
102-
const folders = path.dirname(fileName);
103-
return mkdirSyncRecursive(folders)
104-
.then(() => {
105-
return api.getDoc(name).then((data) => {
106-
if (!data || !data.result) {
107-
throw new Error("Something wrong happened");
108-
}
109-
const content = data.result.content;
110-
const { noStorage, dontExportIfNoChanges } = config("export");
101+
const foldersUri = vscode.Uri.file(path.dirname(fileName));
102+
try {
103+
if (!(await fileExists(foldersUri))) {
104+
// Only attempt to create directories that don't exist
105+
await vscode.workspace.fs.createDirectory(foldersUri);
106+
}
111107

112-
const promise = new Promise((resolve, reject) => {
113-
if (noStorage) {
114-
// get only the storage xml for the doc.
115-
api.getDoc(name + "?storageOnly=1").then((storageData) => {
116-
if (!storageData || !storageData.result) {
117-
reject(new Error("Something wrong happened fetching the storage data"));
118-
}
119-
const storageContent = storageData.result.content;
108+
api.getDoc(name).then((data) => {
109+
if (!data || !data.result) {
110+
throw new Error("Something wrong happened");
111+
}
112+
const content = data.result.content;
113+
const { noStorage, dontExportIfNoChanges } = config("export");
120114

121-
if (storageContent.length > 1 && storageContent[0] && storageContent.length < content.length) {
122-
const storageContentString = storageContent.join("\n");
123-
const contentString = content.join("\n");
115+
const promise = new Promise((resolve, reject) => {
116+
if (noStorage) {
117+
// get only the storage xml for the doc.
118+
api.getDoc(name + "?storageOnly=1").then((storageData) => {
119+
if (!storageData || !storageData.result) {
120+
reject(new Error("Something wrong happened fetching the storage data"));
121+
}
122+
const storageContent = storageData.result.content;
124123

125-
// find and replace the docs storage section with ''
126-
resolve({
127-
content: contentString.replace(storageContentString, ""),
128-
found: contentString.indexOf(storageContentString) >= 0,
129-
});
130-
} else {
131-
resolve({ found: false });
132-
}
133-
});
134-
} else {
135-
resolve({ found: false });
136-
}
137-
});
124+
if (storageContent.length > 1 && storageContent[0] && storageContent.length < content.length) {
125+
const storageContentString = storageContent.join("\n");
126+
const contentString = content.join("\n");
127+
128+
// find and replace the docs storage section with ''
129+
resolve({
130+
content: contentString.replace(storageContentString, ""),
131+
found: contentString.indexOf(storageContentString) >= 0,
132+
});
133+
} else {
134+
resolve({ found: false });
135+
}
136+
});
137+
} else {
138+
resolve({ found: false });
139+
}
140+
});
138141

139-
return promise
140-
.then((res: any) => {
141-
if (Buffer.isBuffer(content)) {
142-
// This is a binary file
143-
let isSkipped = "";
144-
if (dontExportIfNoChanges && fs.existsSync(fileName)) {
145-
const existingContent = fs.readFileSync(fileName);
146-
if (content.equals(existingContent)) {
147-
fs.writeFileSync(fileName, content);
148-
} else {
149-
isSkipped = " => skipped - no changes.";
150-
}
142+
return promise
143+
.then(async (res: any) => {
144+
const fileUri = vscode.Uri.file(fileName);
145+
if (Buffer.isBuffer(content)) {
146+
// This is a binary file
147+
let isSkipped = "";
148+
if (dontExportIfNoChanges && (await fileExists(fileUri))) {
149+
const existingContent = await vscode.workspace.fs.readFile(fileUri);
150+
if (content.equals(existingContent)) {
151+
await vscode.workspace.fs.writeFile(fileUri, content);
151152
} else {
152-
fs.writeFileSync(fileName, content);
153+
isSkipped = " => skipped - no changes.";
153154
}
154-
log(`Success ${isSkipped}`);
155155
} else {
156-
// This is a text file
157-
let joinedContent = content.join("\n");
158-
let isSkipped = "";
156+
await vscode.workspace.fs.writeFile(fileUri, content);
157+
}
158+
log(`Success ${isSkipped}`);
159+
} else {
160+
// This is a text file
161+
let joinedContent = content.join("\n");
162+
let isSkipped = "";
159163

160-
if (res.found) {
161-
joinedContent = res.content.toString("utf8");
162-
}
164+
if (res.found) {
165+
joinedContent = res.content.toString("utf8");
166+
}
163167

164-
if (dontExportIfNoChanges && fs.existsSync(fileName)) {
165-
const existingContent = fs.readFileSync(fileName, "utf8");
166-
// stringify to harmonise the text encoding.
167-
if (JSON.stringify(joinedContent) !== JSON.stringify(existingContent)) {
168-
fs.writeFileSync(fileName, joinedContent);
169-
} else {
170-
isSkipped = " => skipped - no changes.";
171-
}
168+
if (dontExportIfNoChanges && (await fileExists(fileUri))) {
169+
const existingContent = new TextDecoder().decode(await vscode.workspace.fs.readFile(fileUri));
170+
// stringify to harmonise the text encoding.
171+
if (JSON.stringify(joinedContent) !== JSON.stringify(existingContent)) {
172+
await vscode.workspace.fs.writeFile(fileUri, new TextEncoder().encode(joinedContent));
172173
} else {
173-
fs.writeFileSync(fileName, joinedContent);
174+
isSkipped = " => skipped - no changes.";
174175
}
175-
176-
log(`Success ${isSkipped}`);
176+
} else {
177+
await vscode.workspace.fs.writeFile(fileUri, new TextEncoder().encode(joinedContent));
177178
}
178-
})
179-
.catch((error) => {
180-
throw error;
181-
});
182-
});
183-
})
184-
.catch((error) => {
185-
log("ERROR: " + error);
186-
throw error;
179+
180+
log(`Success ${isSkipped}`);
181+
}
182+
})
183+
.catch((error) => {
184+
throw error;
185+
});
187186
});
187+
} catch (error) {
188+
log("ERROR: " + error);
189+
throw error;
190+
}
188191
}
189192

190193
export async function exportList(files: string[], workspaceFolder: string, namespace: string): Promise<any> {

src/utils/index.ts

Lines changed: 17 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import fs = require("fs");
21
import path = require("path");
3-
import { R_OK } from "constants";
42
import * as url from "url";
53
import { exec } from "child_process";
64
import * as vscode from "vscode";
@@ -266,29 +264,6 @@ export function currentFile(document?: vscode.TextDocument): CurrentFile {
266264
};
267265
}
268266

269-
export async function mkdirSyncRecursive(dirpath: string): Promise<string> {
270-
if (fs.existsSync(dirpath)) {
271-
return Promise.resolve(dirpath);
272-
}
273-
const mkdir = (currentPath, folder): void => {
274-
currentPath += folder + path.sep;
275-
276-
if (!fs.existsSync(currentPath)) {
277-
fs.mkdirSync(currentPath);
278-
}
279-
280-
return currentPath;
281-
};
282-
return new Promise<string>((resolve, reject): void => {
283-
try {
284-
dirpath.split(path.sep).reduce(mkdir, "");
285-
resolve(dirpath);
286-
} catch (error) {
287-
reject(error);
288-
}
289-
});
290-
}
291-
292267
export function connectionTarget(uri?: vscode.Uri): ConnectionTarget {
293268
const result: ConnectionTarget = { apiTarget: "", configName: "" };
294269
uri = uri
@@ -425,20 +400,12 @@ export async function portFromDockerCompose(): Promise<{ port: number; docker: b
425400
const workspaceFolderPath = uriOfWorkspaceFolder().fsPath;
426401
const workspaceRootPath = vscode.workspace.workspaceFolders[0].uri.fsPath;
427402

428-
const cwd: string = await new Promise((resolve, reject) => {
429-
fs.access(path.join(workspaceFolderPath, file), R_OK, (error) => {
430-
if (error) {
431-
fs.access(path.join(workspaceRootPath, file), R_OK, (error) => {
432-
if (error) {
433-
reject(new Error(`File '${file}' not found.`));
434-
} else {
435-
resolve(workspaceRootPath);
436-
}
437-
});
438-
} else {
439-
resolve(workspaceFolderPath);
440-
}
441-
});
403+
const cwd: string = await fileExists(vscode.Uri.file(path.join(workspaceFolderPath, file))).then((exists) => {
404+
if (exists) {
405+
return workspaceRootPath;
406+
} else {
407+
throw new Error(`File '${file}' not found.`);
408+
}
442409
});
443410

444411
if (!cwd) {
@@ -554,6 +521,17 @@ export function redirectDotvscodeRoot(uri: vscode.Uri): vscode.Uri {
554521
}
555522
}
556523

524+
/** Check if local `file` exists using vscode's `workspace.fs` FileSystem. */
525+
export async function fileExists(file: vscode.Uri): Promise<boolean> {
526+
try {
527+
vscode.workspace.fs.stat(file);
528+
return true;
529+
} catch {
530+
// Only error thown is "FileNotFound"
531+
return false;
532+
}
533+
}
534+
557535
// ---------------------------------------------------------------------
558536
// Source: https://github.com/amsterdamharu/lib/blob/master/src/index.js
559537

0 commit comments

Comments
 (0)