Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert all the FS-related changes. #8970

Merged
4 changes: 0 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,3 @@ tmp/**
test-results.xml
uitests/out/**
!build/

# TODO (GH-8925) This is temporary. We will remove it when we adjust
# tests to not leave the file behind.
src/test/get-pip.py
1 change: 0 additions & 1 deletion news/2 Fixes/8890.md

This file was deleted.

1 change: 0 additions & 1 deletion news/3 Code Health/6911.md

This file was deleted.

49 changes: 22 additions & 27 deletions src/client/common/editor.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Diff, diff_match_patch } from 'diff-match-patch';
import * as fs from 'fs-extra';
import { injectable } from 'inversify';
import * as md5 from 'md5';
import { EOL } from 'os';
import * as path from 'path';
import { Position, Range, TextDocument, TextEdit, Uri, WorkspaceEdit } from 'vscode';
import { IFileSystem } from './platform/types';
import { IEditorUtils } from './types';

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

return textEdits;
}
export function getWorkspaceEditsFromPatch(
filePatches: string[],
fs: IFileSystem,
workspaceRoot?: string
): WorkspaceEdit {
export function getWorkspaceEditsFromPatch(filePatches: string[], workspaceRoot?: string): WorkspaceEdit {
const workspaceEdit = new WorkspaceEdit();
filePatches.forEach(patch => {
const indexOfAtAt = patch.indexOf('@@');
Expand All @@ -111,7 +107,7 @@ export function getWorkspaceEditsFromPatch(

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

Expand All @@ -127,7 +123,7 @@ export function getWorkspaceEditsFromPatch(
throw new Error('Unable to parse Patch string');
}

const fileSource = fs.readFileSync(fileName);
const fileSource = fs.readFileSync(fileName).toString('utf8');
const fileUri = Uri.file(fileName);

// Add line feeds and build the text edits
Expand Down Expand Up @@ -230,25 +226,24 @@ function getTextEditsInternal(before: string, diffs: [number, string][], startLi
return edits;
}

export async function getTempFileWithDocumentContents(
document: TextDocument,
fs: IFileSystem
): Promise<string> {
// Don't create file in temp folder since external utilities
// look into configuration files in the workspace and are not able
// to find custom rules if file is saved in a random disk location.
// This means temp file has to be created in the same folder
// as the original one and then removed.

const ext = path.extname(document.uri.fsPath);
const filename = `${document.uri.fsPath}.${md5(document.uri.fsPath)}${ext}`;
await (
fs.writeFile(filename, document.getText())
.catch(err => {
throw Error(`Failed to create a temporary file, ${err.message}`);
})
);
return filename;
export function getTempFileWithDocumentContents(document: TextDocument): Promise<string> {
return new Promise<string>((resolve, reject) => {
const ext = path.extname(document.uri.fsPath);
// Don't create file in temp folder since external utilities
// look into configuration files in the workspace and are not able
// to find custom rules if file is saved in a random disk location.
// This means temp file has to be created in the same folder
// as the original one and then removed.

// tslint:disable-next-line:no-require-imports
const fileName = `${document.uri.fsPath}.${md5(document.uri.fsPath)}${ext}`;
fs.writeFile(fileName, document.getText(), ex => {
if (ex) {
reject(`Failed to create a temporary file, ${ex.message}`);
}
resolve(fileName);
});
});
}

/**
Expand Down
63 changes: 63 additions & 0 deletions src/client/common/envFileParser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import * as fs from 'fs-extra';
import { IS_WINDOWS } from './platform/constants';
import { PathUtils } from './platform/pathUtils';
import { EnvironmentVariablesService } from './variables/environment';
import { EnvironmentVariables } from './variables/types';
function parseEnvironmentVariables(contents: string): EnvironmentVariables | undefined {
if (typeof contents !== 'string' || contents.length === 0) {
return undefined;
}

const env: EnvironmentVariables = {};
contents.split('\n').forEach(line => {
const match = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/);
if (match !== null) {
let value = typeof match[2] === 'string' ? match[2] : '';
if (value.length > 0 && value.charAt(0) === '"' && value.charAt(value.length - 1) === '"') {
value = value.replace(/\\n/gm, '\n');
}
env[match[1]] = value.replace(/(^['"]|['"]$)/g, '');
}
});
return env;
}

export function parseEnvFile(envFile: string, mergeWithProcessEnvVars: boolean = true): EnvironmentVariables {
const buffer = fs.readFileSync(envFile, 'utf8');
const env = parseEnvironmentVariables(buffer)!;
return mergeWithProcessEnvVars ? mergeEnvVariables(env, process.env) : mergePythonPath(env, process.env.PYTHONPATH as string);
}

/**
* Merge the target environment variables into the source.
* Note: The source variables are modified and returned (i.e. it modifies value passed in).
* @export
* @param {EnvironmentVariables} targetEnvVars target environment variables.
* @param {EnvironmentVariables} [sourceEnvVars=process.env] source environment variables (defaults to current process variables).
* @returns {EnvironmentVariables}
*/
export function mergeEnvVariables(targetEnvVars: EnvironmentVariables, sourceEnvVars: EnvironmentVariables = process.env): EnvironmentVariables {
const service = new EnvironmentVariablesService(new PathUtils(IS_WINDOWS));
service.mergeVariables(sourceEnvVars, targetEnvVars);
if (sourceEnvVars.PYTHONPATH) {
service.appendPythonPath(targetEnvVars, sourceEnvVars.PYTHONPATH);
}
return targetEnvVars;
}

/**
* Merge the target PYTHONPATH value into the env variables passed.
* Note: The env variables passed in are modified and returned (i.e. it modifies value passed in).
* @export
* @param {EnvironmentVariables} env target environment variables.
* @param {string | undefined} [currentPythonPath] PYTHONPATH value.
* @returns {EnvironmentVariables}
*/
export function mergePythonPath(env: EnvironmentVariables, currentPythonPath: string | undefined): EnvironmentVariables {
if (typeof currentPythonPath !== 'string' || currentPythonPath.length === 0) {
return env;
}
const service = new EnvironmentVariablesService(new PathUtils(IS_WINDOWS));
service.appendPythonPath(env, currentPythonPath);
return env;
}
22 changes: 16 additions & 6 deletions src/client/common/installer/moduleInstaller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import * as fs from 'fs';
import { injectable } from 'inversify';
import * as path from 'path';
import { OutputChannel, window } from 'vscode';
Expand All @@ -9,10 +10,9 @@ import { IServiceContainer } from '../../ioc/types';
import { sendTelemetryEvent } from '../../telemetry';
import { EventName } from '../../telemetry/constants';
import { STANDARD_OUTPUT_CHANNEL } from '../constants';
import { IFileSystem } from '../platform/types';
import { ITerminalServiceFactory } from '../terminal/types';
import { ExecutionInfo, IConfigurationService, IOutputChannel } from '../types';
import { isResource } from '../utils/misc';
import { isResource, noop } from '../utils/misc';
import { InterpreterUri } from './types';

@injectable()
Expand All @@ -38,10 +38,7 @@ export abstract class ModuleInstaller {
if (!interpreter || interpreter.type !== InterpreterType.Unknown) {
await terminalService.sendCommand(pythonPath, args);
} else if (settings.globalModuleInstallation) {
const dirname = path.dirname(pythonPath);
const fs = this.serviceContainer.get<IFileSystem>(IFileSystem);
const isWritable = ! await fs.isDirReadonly(dirname);
if (isWritable) {
if (await this.isPathWritableAsync(path.dirname(pythonPath))) {
await terminalService.sendCommand(pythonPath, args);
} else {
this.elevatedInstall(pythonPath, args);
Expand Down Expand Up @@ -71,6 +68,19 @@ export abstract class ModuleInstaller {
}
return args;
}
private async isPathWritableAsync(directoryPath: string): Promise<boolean> {
const filePath = `${directoryPath}${path.sep}___vscpTest___`;
return new Promise<boolean>(resolve => {
fs.open(filePath, fs.constants.O_CREAT | fs.constants.O_RDWR, (error, fd) => {
if (!error) {
fs.close(fd, () => {
fs.unlink(filePath, noop);
});
}
return resolve(!error);
});
});
}

private elevatedInstall(execPath: string, args: string[]) {
const options = {
Expand Down
3 changes: 2 additions & 1 deletion src/client/common/net/fileDownloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@

'use strict';

import { WriteStream } from 'fs';
import { inject, injectable } from 'inversify';
import * as requestTypes from 'request';
import { Progress, ProgressLocation } from 'vscode';
import { IApplicationShell } from '../application/types';
import { IFileSystem, WriteStream } from '../platform/types';
import { IFileSystem } from '../platform/types';
import { DownloadOptions, IFileDownloader, IHttpClient } from '../types';
import { Http } from '../utils/localize';
import { noop } from '../utils/misc';
Expand Down
Loading