Skip to content

Commit 77dabe0

Browse files
Centralize fs usage. (#8993)
(for #8995) This is a partial un-revert of the recent FS changes. This change in particular only consolidates all FS-related operations to use of FileSystem objects.
1 parent 9976f85 commit 77dabe0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+349
-322
lines changed

src/client/common/application/webPanels/webPanel.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
'use strict';
44
import '../../extensions';
55

6-
import * as fs from 'fs-extra';
76
import * as uuid from 'uuid/v4';
87
import { Uri, Webview, WebviewPanel, window } from 'vscode';
98

109
import { Identifiers } from '../../../datascience/constants';
1110
import { InteractiveWindowMessages } from '../../../datascience/interactive-common/interactiveWindowTypes';
1211
import { SharedMessages } from '../../../datascience/messages';
12+
import { IFileSystem } from '../../platform/types';
1313
import { IDisposableRegistry } from '../../types';
1414
import * as localize from '../../utils/localize';
1515
import { IWebPanel, IWebPanelOptions, WebPanelMessage } from '../types';
@@ -26,10 +26,12 @@ export class WebPanel implements IWebPanel {
2626
private id = uuid();
2727

2828
constructor(
29+
private fs: IFileSystem,
2930
private disposableRegistry: IDisposableRegistry,
3031
private port: number | undefined,
3132
private token: string | undefined,
32-
private options: IWebPanelOptions) {
33+
private options: IWebPanelOptions
34+
) {
3335
this.panel = window.createWebviewPanel(
3436
options.title.toLowerCase().replace(' ', ''),
3537
options.title,
@@ -86,7 +88,7 @@ export class WebPanel implements IWebPanel {
8688
// tslint:disable-next-line:no-any
8789
private async load() {
8890
if (this.panel) {
89-
const localFilesExist = await Promise.all(this.options.scripts.map(s => fs.pathExists(s)));
91+
const localFilesExist = await Promise.all(this.options.scripts.map(s => this.fs.fileExists(s)));
9092
if (localFilesExist.every(exists => exists === true)) {
9193

9294
// Call our special function that sticks this script inside of an html page

src/client/common/application/webPanels/webPanelProvider.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { inject, injectable } from 'inversify';
55
import * as portfinder from 'portfinder';
66
import * as uuid from 'uuid/v4';
77

8+
import { IFileSystem } from '../../platform/types';
89
import { IDisposableRegistry } from '../../types';
910
import { IWebPanel, IWebPanelOptions, IWebPanelProvider } from '../types';
1011
import { WebPanel } from './webPanel';
@@ -15,13 +16,15 @@ export class WebPanelProvider implements IWebPanelProvider {
1516
private port: number | undefined;
1617
private token: string | undefined;
1718

18-
constructor(@inject(IDisposableRegistry) private disposableRegistry: IDisposableRegistry) {
19-
}
19+
constructor(
20+
@inject(IDisposableRegistry) private disposableRegistry: IDisposableRegistry,
21+
@inject(IFileSystem) private fs: IFileSystem
22+
) { }
2023

2124
// tslint:disable-next-line:no-any
2225
public async create(options: IWebPanelOptions): Promise<IWebPanel> {
2326
const serverData = options.startHttpServer ? await this.ensureServerIsRunning() : { port: undefined, token: undefined };
24-
return new WebPanel(this.disposableRegistry, serverData.port, serverData.token, options);
27+
return new WebPanel(this.fs, this.disposableRegistry, serverData.port, serverData.token, options);
2528
}
2629

2730
private async ensureServerIsRunning(): Promise<{ port: number; token: string }> {
@@ -36,7 +39,7 @@ export class WebPanelProvider implements IWebPanelProvider {
3639
const webPanelServerModule = require('./webPanelServer') as typeof import('./webPanelServer');
3740

3841
// Start the server listening.
39-
const webPanelServer = new webPanelServerModule.WebPanelServer(this.port, this.token);
42+
const webPanelServer = new webPanelServerModule.WebPanelServer(this.port, this.token, this.fs);
4043
webPanelServer.start();
4144
this.disposableRegistry.push(webPanelServer);
4245
}

src/client/common/application/webPanels/webPanelServer.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33
import * as Cors from '@koa/cors';
4-
import * as fs from 'fs-extra';
54
import * as http from 'http';
65
import * as Koa from 'koa';
76
import * as compress from 'koa-compress';
@@ -11,6 +10,7 @@ import * as path from 'path';
1110
import { EXTENSION_ROOT_DIR } from '../../../constants';
1211
import { Identifiers } from '../../../datascience/constants';
1312
import { SharedMessages } from '../../../datascience/messages';
13+
import { IFileSystem } from '../../platform/types';
1414

1515
interface IState {
1616
cwd: string;
@@ -23,7 +23,7 @@ export class WebPanelServer {
2323
private server: http.Server | undefined;
2424
private state = new Map<string, IState>();
2525

26-
constructor(private port: number, private token: string) {
26+
constructor(private port: number, private token: string, private fs: IFileSystem) {
2727
this.app.use(Cors());
2828
this.app.use(compress());
2929
this.app.use(logger());
@@ -110,7 +110,7 @@ export class WebPanelServer {
110110
break;
111111

112112
}
113-
ctx.body = fs.createReadStream(filePath);
113+
ctx.body = this.fs.createReadStream(filePath);
114114
}
115115

116116
// Debugging tips:

src/client/common/editor.ts

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { Diff, diff_match_patch } from 'diff-match-patch';
2-
import * as fs from 'fs-extra';
32
import { injectable } from 'inversify';
43
import * as md5 from 'md5';
54
import { EOL } from 'os';
65
import * as path from 'path';
76
import { Position, Range, TextDocument, TextEdit, Uri, WorkspaceEdit } from 'vscode';
7+
import { IFileSystem } from '../common/platform/types';
88
import { IEditorUtils } from './types';
99

1010
// Code borrowed from goFormat.ts (Go Extension for VS Code)
@@ -80,7 +80,7 @@ export function getTextEditsFromPatch(before: string, patch: string): TextEdit[]
8080

8181
return textEdits;
8282
}
83-
export function getWorkspaceEditsFromPatch(filePatches: string[], workspaceRoot?: string): WorkspaceEdit {
83+
export function getWorkspaceEditsFromPatch(filePatches: string[], workspaceRoot: string | undefined, fs: IFileSystem): WorkspaceEdit {
8484
const workspaceEdit = new WorkspaceEdit();
8585
filePatches.forEach(patch => {
8686
const indexOfAtAt = patch.indexOf('@@');
@@ -107,7 +107,7 @@ export function getWorkspaceEditsFromPatch(filePatches: string[], workspaceRoot?
107107

108108
let fileName = fileNameLines[0].substring(fileNameLines[0].indexOf(' a') + 3).trim();
109109
fileName = workspaceRoot && !path.isAbsolute(fileName) ? path.resolve(workspaceRoot, fileName) : fileName;
110-
if (!fs.existsSync(fileName)) {
110+
if (!fs.fileExistsSync(fileName)) {
111111
return;
112112
}
113113

@@ -123,7 +123,7 @@ export function getWorkspaceEditsFromPatch(filePatches: string[], workspaceRoot?
123123
throw new Error('Unable to parse Patch string');
124124
}
125125

126-
const fileSource = fs.readFileSync(fileName).toString('utf8');
126+
const fileSource = fs.readFileSync(fileName);
127127
const fileUri = Uri.file(fileName);
128128

129129
// Add line feeds and build the text edits
@@ -226,24 +226,22 @@ function getTextEditsInternal(before: string, diffs: [number, string][], startLi
226226
return edits;
227227
}
228228

229-
export function getTempFileWithDocumentContents(document: TextDocument): Promise<string> {
230-
return new Promise<string>((resolve, reject) => {
231-
const ext = path.extname(document.uri.fsPath);
232-
// Don't create file in temp folder since external utilities
233-
// look into configuration files in the workspace and are not able
234-
// to find custom rules if file is saved in a random disk location.
235-
// This means temp file has to be created in the same folder
236-
// as the original one and then removed.
229+
export async function getTempFileWithDocumentContents(document: TextDocument, fs: IFileSystem): Promise<string> {
230+
const ext = path.extname(document.uri.fsPath);
231+
// Don't create file in temp folder since external utilities
232+
// look into configuration files in the workspace and are not
233+
// to find custom rules if file is saved in a random disk location.
234+
// This means temp file has to be created in the same folder
235+
// as the original one and then removed.
237236

238-
// tslint:disable-next-line:no-require-imports
239-
const fileName = `${document.uri.fsPath}.${md5(document.uri.fsPath)}${ext}`;
240-
fs.writeFile(fileName, document.getText(), ex => {
241-
if (ex) {
242-
reject(`Failed to create a temporary file, ${ex.message}`);
243-
}
244-
resolve(fileName);
245-
});
246-
});
237+
// tslint:disable-next-line:no-require-imports
238+
const fileName = `${document.uri.fsPath}.${md5(document.uri.fsPath)}${ext}`;
239+
try {
240+
await fs.writeFile(fileName, document.getText());
241+
} catch (ex) {
242+
throw Error(`Failed to create a temporary file, ${ex.message}`);
243+
}
244+
return fileName;
247245
}
248246

249247
/**

src/client/common/envFileParser.ts

Lines changed: 0 additions & 63 deletions
This file was deleted.

src/client/common/installer/moduleInstaller.ts

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4-
import * as fs from 'fs';
54
import { injectable } from 'inversify';
65
import * as path from 'path';
76
import { CancellationToken, OutputChannel, ProgressLocation, ProgressOptions, window } from 'vscode';
@@ -12,10 +11,11 @@ import { EventName } from '../../telemetry/constants';
1211
import { IApplicationShell } from '../application/types';
1312
import { wrapCancellationTokens } from '../cancellation';
1413
import { STANDARD_OUTPUT_CHANNEL } from '../constants';
14+
import { IFileSystem } from '../platform/types';
1515
import { ITerminalServiceFactory } from '../terminal/types';
1616
import { ExecutionInfo, IConfigurationService, IOutputChannel } from '../types';
1717
import { Products } from '../utils/localize';
18-
import { isResource, noop } from '../utils/misc';
18+
import { isResource } from '../utils/misc';
1919
import { IModuleInstaller, InterpreterUri } from './types';
2020

2121
@injectable()
@@ -42,10 +42,11 @@ export abstract class ModuleInstaller implements IModuleInstaller {
4242
if (!interpreter || interpreter.type !== InterpreterType.Unknown) {
4343
await terminalService.sendCommand(pythonPath, args, token);
4444
} else if (settings.globalModuleInstallation) {
45-
if (await this.isPathWritableAsync(path.dirname(pythonPath))) {
46-
await terminalService.sendCommand(pythonPath, args, token);
47-
} else {
45+
const fs = this.serviceContainer.get<IFileSystem>(IFileSystem);
46+
if (await fs.isDirReadonly(path.dirname(pythonPath))) {
4847
this.elevatedInstall(pythonPath, args);
48+
} else {
49+
await terminalService.sendCommand(pythonPath, args, token);
4950
}
5051
} else {
5152
await terminalService.sendCommand(pythonPath, args.concat(['--user']), token);
@@ -88,19 +89,6 @@ export abstract class ModuleInstaller implements IModuleInstaller {
8889
}
8990
return args;
9091
}
91-
private async isPathWritableAsync(directoryPath: string): Promise<boolean> {
92-
const filePath = `${directoryPath}${path.sep}___vscpTest___`;
93-
return new Promise<boolean>(resolve => {
94-
fs.open(filePath, fs.constants.O_CREAT | fs.constants.O_RDWR, (error, fd) => {
95-
if (!error) {
96-
fs.close(fd, () => {
97-
fs.unlink(filePath, noop);
98-
});
99-
}
100-
return resolve(!error);
101-
});
102-
});
103-
}
10492

10593
private elevatedInstall(execPath: string, args: string[]) {
10694
const options = {

src/client/common/net/fileDownloader.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@
33

44
'use strict';
55

6-
import { WriteStream } from 'fs';
76
import { inject, injectable } from 'inversify';
87
import * as requestTypes from 'request';
98
import { Progress, ProgressLocation } from 'vscode';
109
import { IApplicationShell } from '../application/types';
11-
import { IFileSystem } from '../platform/types';
10+
import { IFileSystem, WriteStream } from '../platform/types';
1211
import { DownloadOptions, IFileDownloader, IHttpClient } from '../types';
1312
import { Http } from '../utils/localize';
1413
import { noop } from '../utils/misc';

0 commit comments

Comments
 (0)