Skip to content

Commit 1d96e16

Browse files
committed
Remove nearly all remaining uses of Node.JS fs module
The last one involves a stream.
1 parent 7293a19 commit 1d96e16

File tree

8 files changed

+40
-45
lines changed

8 files changed

+40
-45
lines changed

src/features/ExtensionCommands.ts

+3-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
// TODO: This file needs some TLC to use strict mode.
55

6-
import * as fs from "fs";
76
import * as os from "os";
87
import * as path from "path";
98
import * as vscode from "vscode";
@@ -530,15 +529,9 @@ export class ExtensionCommandsFeature extends LanguageClientConsumer {
530529

531530
// Write it to the new document path
532531
try {
533-
// TODO: Change this to be asynchronous
534-
await new Promise<void>((resolve, reject) => {
535-
fs.writeFile(destinationAbsolutePath, oldDocument.getText(), (err) => {
536-
if (err) {
537-
return reject(err);
538-
}
539-
return resolve();
540-
});
541-
});
532+
await vscode.workspace.fs.writeFile(
533+
vscode.Uri.file(destinationAbsolutePath),
534+
Buffer.from(oldDocument.getText()));
542535
} catch (e) {
543536
this.log.writeAndShowWarning(`<${ExtensionCommandsFeature.name}>: ` +
544537
`Unable to save file to path '${destinationAbsolutePath}': ${e}`);

src/features/UpdatePowerShell.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Licensed under the MIT License.
33

44
import { spawn } from "child_process";
5-
import * as fs from "fs";
5+
import * as fs from "fs"; // TODO: Remove, but it's for a stream.
66
import fetch, { RequestInit } from "node-fetch";
77
import * as os from "os";
88
import * as path from "path";

src/logging.ts

+17-13
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
"use strict";
55

6-
import fs = require("fs");
6+
import utils = require("./utils");
77
import os = require("os");
88
import vscode = require("vscode");
99

@@ -62,7 +62,7 @@ export class Logger implements ILogger {
6262
return vscode.Uri.joinPath(this.logSessionPath, `${baseName}.log`);
6363
}
6464

65-
public writeAtLevel(logLevel: LogLevel, message: string, ...additionalMessages: string[]): void {
65+
private writeAtLevel(logLevel: LogLevel, message: string, ...additionalMessages: string[]): void {
6666
if (logLevel >= this.MinimumLogLevel) {
6767
this.writeLine(message, logLevel);
6868

@@ -170,22 +170,26 @@ export class Logger implements ILogger {
170170
}
171171
}
172172

173-
private writeLine(message: string, level: LogLevel = LogLevel.Normal): void {
173+
// TODO: Should we await this function above?
174+
private async writeLine(message: string, level: LogLevel = LogLevel.Normal): Promise<void> {
174175
const now = new Date();
175176
const timestampedMessage =
176-
`${now.toLocaleDateString()} ${now.toLocaleTimeString()} [${LogLevel[level].toUpperCase()}] - ${message}`;
177+
`${now.toLocaleDateString()} ${now.toLocaleTimeString()} [${LogLevel[level].toUpperCase()}] - ${message}${os.EOL}`;
177178

178179
this.logChannel.appendLine(timestampedMessage);
179180
if (this.logFilePath && this.MinimumLogLevel !== LogLevel.None) {
180-
fs.appendFile(
181-
this.logFilePath.fsPath,
182-
timestampedMessage + os.EOL,
183-
(err) => {
184-
if (err) {
185-
// tslint:disable-next-line:no-console
186-
console.log(`Error writing to vscode-powershell log file: ${err}`);
187-
}
188-
});
181+
try {
182+
let log = new Uint8Array();
183+
if (await utils.checkIfFileExists(this.logFilePath)) {
184+
log = await vscode.workspace.fs.readFile(this.logFilePath);
185+
}
186+
await vscode.workspace.fs.writeFile(
187+
this.logFilePath,
188+
Buffer.concat([log, Buffer.from(timestampedMessage)]));
189+
} catch (e) {
190+
// tslint:disable-next-line:no-console
191+
console.log(`Error writing to vscode-powershell log file: ${e}`)
192+
}
189193
}
190194
}
191195
}

src/platform.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4-
import * as fs from "fs";
4+
import * as vscode from "vscode"
55
import * as os from "os";
66
import * as path from "path";
77
import * as process from "process";
88
import { IPowerShellAdditionalExePathSettings } from "./settings";
9+
910
// This uses require so we can rewire it in unit tests!
1011
// tslint:disable-next-line:no-var-requires
1112
const utils = require("./utils")
@@ -290,11 +291,10 @@ export class PowerShellExeFinder {
290291
: { pwshMsixDirRegex: PowerShellExeFinder.PwshMsixRegex, pwshMsixName: "PowerShell (Store)" };
291292

292293
// We should find only one such application, so return on the first one
293-
// TODO: Use VS Code async fs API for this.
294-
for (const subdir of fs.readdirSync(msixAppDir)) {
295-
if (pwshMsixDirRegex.test(subdir)) {
296-
const pwshMsixPath = path.join(msixAppDir, subdir, "pwsh.exe");
297-
return new PossiblePowerShellExe(pwshMsixPath, pwshMsixName);
294+
for (const [name, type] of await vscode.workspace.fs.readDirectory(vscode.Uri.file(msixAppDir))) {
295+
// tslint:disable-next-line:no-bitwise
296+
if ((type & vscode.FileType.Directory) !== 0 && pwshMsixDirRegex.test(name)) {
297+
return new PossiblePowerShellExe(path.join(msixAppDir, name, "pwsh.exe"), pwshMsixName);
298298
}
299299
}
300300

@@ -329,7 +329,7 @@ export class PowerShellExeFinder {
329329

330330
let highestSeenVersion: number = -1;
331331
let pwshExePath: string = null;
332-
for (const item of fs.readdirSync(powerShellInstallBaseDir)) {
332+
for (const [item, _type] of await vscode.workspace.fs.readDirectory(vscode.Uri.file(powerShellInstallBaseDir))) {
333333

334334
let currentVersion: number = -1;
335335
if (findPreview) {

src/process.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4-
import fs = require("fs");
54
import cp = require("child_process");
65
import * as semver from "semver";
76
import path = require("path");
@@ -189,10 +188,9 @@ export class PowerShellProcess {
189188
return true;
190189
}
191190

192-
private static readSessionFile(sessionFilePath: vscode.Uri): IEditorServicesSessionDetails {
193-
// TODO: Use vscode.workspace.fs.readFile instead of fs.readFileSync.
194-
const fileContents = fs.readFileSync(sessionFilePath.fsPath, "utf-8");
195-
return JSON.parse(fileContents);
191+
private static async readSessionFile(sessionFilePath: vscode.Uri): Promise<IEditorServicesSessionDetails> {
192+
const fileContents = await vscode.workspace.fs.readFile(sessionFilePath);
193+
return JSON.parse(fileContents.toString());
196194
}
197195

198196
private static async deleteSessionFile(sessionFilePath: vscode.Uri) {
@@ -213,7 +211,7 @@ export class PowerShellProcess {
213211
for (let i = numOfTries; i > 0; i--) {
214212
if (await utils.checkIfFileExists(this.sessionFilePath)) {
215213
this.log.write("Session file found!");
216-
const sessionDetails = PowerShellProcess.readSessionFile(this.sessionFilePath);
214+
const sessionDetails = await PowerShellProcess.readSessionFile(this.sessionFilePath);
217215
PowerShellProcess.deleteSessionFile(this.sessionFilePath);
218216
return sessionDetails;
219217
}

test/core/paths.test.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
// Licensed under the MIT License.
33

44
import * as assert from "assert";
5-
import * as fs from "fs";
65
import * as vscode from "vscode";
76
import { IPowerShellExtensionClient } from "../../src/features/ExternalApi";
87
import utils = require("../utils");
8+
import { checkIfDirectoryExists } from "../../src/utils"
99

1010
describe("Path assumptions", function () {
1111
let globalStorageUri: vscode.Uri;
@@ -21,11 +21,11 @@ describe("Path assumptions", function () {
2121
assert(await vscode.commands.executeCommand("PowerShell.OpenExamplesFolder"));
2222
});
2323

24-
it("Creates the session folder at the correct path", function () {
25-
assert(fs.existsSync(vscode.Uri.joinPath(globalStorageUri, "sessions").fsPath));
24+
it("Creates the session folder at the correct path", async function () {
25+
assert(await checkIfDirectoryExists(vscode.Uri.joinPath(globalStorageUri, "sessions")));
2626
});
2727

28-
it("Creates the log folder at the correct path", function () {
29-
assert(fs.existsSync(vscode.Uri.joinPath(globalStorageUri, "logs").fsPath));
28+
it("Creates the log folder at the correct path", async function () {
29+
assert(await checkIfDirectoryExists(vscode.Uri.joinPath(globalStorageUri, "logs")));
3030
});
3131
});

test/core/platform.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import * as path from "path";
88
import rewire = require("rewire");
99
import * as sinon from "sinon";
1010
import * as platform from "../../src/platform";
11-
import * as fs from "fs";
11+
import * as fs from "fs"; // NOTE: Necessary for mock-fs.
1212
import * as vscode from "vscode";
1313

1414
// We have to rewire the platform module so that mock-fs can be used, as it

test/features/RunCode.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
// Licensed under the MIT License.
33

44
import * as assert from "assert";
5-
import * as fs from "fs";
65
import * as path from "path";
76
import rewire = require("rewire");
87
import vscode = require("vscode");
98
import utils = require("../utils");
9+
import { checkIfFileExists } from "../../src/utils"
1010

1111
// Setup function that is not exported.
1212
const customViews = rewire("../../src/features/RunCode");
@@ -43,7 +43,7 @@ describe("RunCode feature", function () {
4343

4444
it("Runs Pester tests from a file", async function () {
4545
const pesterTests = path.resolve(__dirname, "../../../examples/Tests/SampleModule.Tests.ps1");
46-
assert(fs.existsSync(pesterTests));
46+
assert(checkIfFileExists(pesterTests));
4747

4848
// Open the PowerShell file with Pester tests and then wait a while for
4949
// the extension to finish connecting to the server.

0 commit comments

Comments
 (0)