mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode de81ccf04849309f843db21130c806a5783678f7 (#4738)
This commit is contained in:
@@ -85,7 +85,8 @@ export class FileDialogService implements IFileDialogService {
|
||||
}
|
||||
|
||||
private shouldUseSimplified(schema: string): boolean {
|
||||
return (schema !== Schemas.file) || (this.configurationService.getValue('workbench.dialogs.useSimplified') === 'true');
|
||||
const setting = this.configurationService.getValue('workbench.dialogs.useSimplified');
|
||||
return (schema !== Schemas.file) || ((setting === 'true') || (setting === true));
|
||||
}
|
||||
|
||||
private ensureFileSchema(schema: string): string[] {
|
||||
|
||||
@@ -34,6 +34,7 @@ import { ExtensionIdentifier, IExtension, ExtensionType, IExtensionDescription }
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { parseExtensionDevOptions } from 'vs/workbench/services/extensions/common/extensionDevOptions';
|
||||
|
||||
const hasOwnProperty = Object.hasOwnProperty;
|
||||
const NO_OP_VOID_PROMISE = Promise.resolve<void>(undefined);
|
||||
@@ -843,7 +844,16 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
}
|
||||
|
||||
public _onExtensionHostExit(code: number): void {
|
||||
ipc.send('vscode:exit', code);
|
||||
// Expected development extension termination: When the extension host goes down we also shutdown the window
|
||||
const devOpts = parseExtensionDevOptions(this._environmentService);
|
||||
if (!devOpts.isExtensionDevTestFromCli) {
|
||||
this._windowService.closeWindow();
|
||||
}
|
||||
|
||||
// When CLI testing make sure to exit with proper exit code
|
||||
else {
|
||||
ipc.send('vscode:exit', code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -287,7 +287,7 @@ function createPatchedModules(configProvider: ExtHostConfigProvider, resolveProx
|
||||
};
|
||||
configProvider.onDidChangeConfiguration(e => {
|
||||
certSetting.config = !!configProvider.getConfiguration('http')
|
||||
.get<string>('systemCertificates');
|
||||
.get<boolean>('systemCertificates');
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -332,9 +332,10 @@ function patches(originals: typeof http | typeof https, resolveProxy: ReturnType
|
||||
return original.apply(null, arguments as unknown as any[]);
|
||||
}
|
||||
|
||||
const optionsPatched = options.agent instanceof ProxyAgent;
|
||||
const config = onRequest && ((<any>options)._vscodeProxySupport || /* LS */ (<any>options)._vscodeSystemProxy) || proxySetting.config;
|
||||
const useProxySettings = (config === 'override' || config === 'on' && !options.agent) && !(options.agent instanceof ProxyAgent);
|
||||
const useSystemCertificates = certSetting.config && originals === https && !(options as https.RequestOptions).ca;
|
||||
const useProxySettings = !optionsPatched && (config === 'override' || config === 'on' && !options.agent);
|
||||
const useSystemCertificates = !optionsPatched && certSetting.config && originals === https && !(options as https.RequestOptions).ca;
|
||||
|
||||
if (useProxySettings || useSystemCertificates) {
|
||||
if (url) {
|
||||
|
||||
@@ -206,7 +206,7 @@ export class FileService2 extends Disposable implements IFileService {
|
||||
});
|
||||
}
|
||||
|
||||
private async toFileStat(provider: IFileSystemProvider, resource: URI, stat: IStat, siblings: number | undefined, resolveMetadata: boolean, recurse: (stat: IFileStat, siblings?: number) => boolean): Promise<IFileStat> {
|
||||
private async toFileStat(provider: IFileSystemProvider, resource: URI, stat: IStat | { type: FileType } & Partial<IStat>, siblings: number | undefined, resolveMetadata: boolean, recurse: (stat: IFileStat, siblings?: number) => boolean): Promise<IFileStat> {
|
||||
|
||||
// convert to file stat
|
||||
const fileStat: IFileStat = {
|
||||
@@ -355,11 +355,11 @@ export class FileService2 extends Disposable implements IFileService {
|
||||
const targetProvider = this.throwIfFileSystemIsReadonly(await this.withProvider(target));
|
||||
|
||||
// move
|
||||
await this.doMoveCopy(sourceProvider, source, targetProvider, target, 'move', overwrite);
|
||||
const mode = await this.doMoveCopy(sourceProvider, source, targetProvider, target, 'move', overwrite);
|
||||
|
||||
// resolve and send events
|
||||
const fileStat = await this.resolveFile(target, { resolveMetadata: true });
|
||||
this._onAfterOperation.fire(new FileOperationEvent(source, FileOperation.MOVE, fileStat));
|
||||
this._onAfterOperation.fire(new FileOperationEvent(source, mode === 'move' ? FileOperation.MOVE : FileOperation.COPY, fileStat));
|
||||
|
||||
return fileStat;
|
||||
}
|
||||
@@ -369,16 +369,16 @@ export class FileService2 extends Disposable implements IFileService {
|
||||
const targetProvider = this.throwIfFileSystemIsReadonly(await this.withProvider(target));
|
||||
|
||||
// copy
|
||||
await this.doMoveCopy(sourceProvider, source, targetProvider, target, 'copy', overwrite);
|
||||
const mode = await this.doMoveCopy(sourceProvider, source, targetProvider, target, 'copy', overwrite);
|
||||
|
||||
// resolve and send events
|
||||
const fileStat = await this.resolveFile(target, { resolveMetadata: true });
|
||||
this._onAfterOperation.fire(new FileOperationEvent(source, FileOperation.COPY, fileStat));
|
||||
this._onAfterOperation.fire(new FileOperationEvent(source, mode === 'copy' ? FileOperation.COPY : FileOperation.MOVE, fileStat));
|
||||
|
||||
return fileStat;
|
||||
}
|
||||
|
||||
private async doMoveCopy(sourceProvider: IFileSystemProvider, source: URI, targetProvider: IFileSystemProvider, target: URI, mode: 'move' | 'copy', overwrite?: boolean): Promise<void> {
|
||||
private async doMoveCopy(sourceProvider: IFileSystemProvider, source: URI, targetProvider: IFileSystemProvider, target: URI, mode: 'move' | 'copy', overwrite?: boolean): Promise<'move' | 'copy'> {
|
||||
|
||||
// validation
|
||||
const { exists, isCaseChange } = await this.doValidateMoveCopy(sourceProvider, source, targetProvider, target, overwrite);
|
||||
@@ -396,7 +396,7 @@ export class FileService2 extends Disposable implements IFileService {
|
||||
|
||||
// same provider with fast copy: leverage copy() functionality
|
||||
if (sourceProvider === targetProvider && hasFileFolderCopyCapability(sourceProvider)) {
|
||||
return sourceProvider.copy(source, target, { overwrite: !!overwrite });
|
||||
return sourceProvider.copy(source, target, { overwrite: !!overwrite }).then(() => mode);
|
||||
}
|
||||
|
||||
// otherwise, ensure we got the capabilities to do this
|
||||
@@ -411,9 +411,9 @@ export class FileService2 extends Disposable implements IFileService {
|
||||
// traverse the source if it is a folder and not a file
|
||||
const sourceFile = await this.resolveFile(source);
|
||||
if (sourceFile.isDirectory) {
|
||||
return this.doCopyFolder(sourceProvider, sourceFile, targetProvider, target, overwrite);
|
||||
return this.doCopyFolder(sourceProvider, sourceFile, targetProvider, target, overwrite).then(() => mode);
|
||||
} else {
|
||||
return this.doCopyFile(sourceProvider, source, targetProvider, target, overwrite);
|
||||
return this.doCopyFile(sourceProvider, source, targetProvider, target, overwrite).then(() => mode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,14 +422,14 @@ export class FileService2 extends Disposable implements IFileService {
|
||||
|
||||
// same provider: leverage rename() functionality
|
||||
if (sourceProvider === targetProvider) {
|
||||
return sourceProvider.rename(source, target, { overwrite: !!overwrite });
|
||||
return sourceProvider.rename(source, target, { overwrite: !!overwrite }).then(() => mode);
|
||||
}
|
||||
|
||||
// across providers: copy to target & delete at source
|
||||
else {
|
||||
await this.doMoveCopy(sourceProvider, source, targetProvider, target, 'copy', overwrite);
|
||||
|
||||
return this.del(source, { recursive: true });
|
||||
return this.del(source, { recursive: true }).then(() => 'copy' as 'move' | 'copy');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,11 +12,12 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { isLinux, isWindows } from 'vs/base/common/platform';
|
||||
import { statLink, readdir, unlink, del, move, copy, readFile, writeFile, fileExists, truncate } from 'vs/base/node/pfs';
|
||||
import { normalize } from 'vs/base/common/path';
|
||||
import { normalize, basename, dirname } from 'vs/base/common/path';
|
||||
import { joinPath } from 'vs/base/common/resources';
|
||||
import { isEqual } from 'vs/base/common/extpath';
|
||||
import { retry } from 'vs/base/common/async';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
export class DiskFileSystemProvider extends Disposable implements IFileSystemProvider {
|
||||
|
||||
@@ -113,9 +114,9 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro
|
||||
// Validate target
|
||||
const exists = await fileExists(filePath);
|
||||
if (exists && !opts.overwrite) {
|
||||
throw createFileSystemProviderError(new Error('File already exists'), FileSystemProviderErrorCode.FileExists);
|
||||
throw createFileSystemProviderError(new Error(localize('fileExists', "File already exists")), FileSystemProviderErrorCode.FileExists);
|
||||
} else if (!exists && !opts.create) {
|
||||
throw createFileSystemProviderError(new Error('File does not exist'), FileSystemProviderErrorCode.FileNotFound);
|
||||
throw createFileSystemProviderError(new Error(localize('fileNotExists', "File does not exist")), FileSystemProviderErrorCode.FileNotFound);
|
||||
}
|
||||
|
||||
if (exists && isWindows) {
|
||||
@@ -241,9 +242,10 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro
|
||||
}
|
||||
|
||||
async rename(from: URI, to: URI, opts: FileOverwriteOptions): Promise<void> {
|
||||
const fromFilePath = this.toFilePath(from);
|
||||
const toFilePath = this.toFilePath(to);
|
||||
|
||||
try {
|
||||
const fromFilePath = this.toFilePath(from);
|
||||
const toFilePath = this.toFilePath(to);
|
||||
|
||||
// Ensure target does not exist
|
||||
await this.validateTargetDeleted(from, to, opts && opts.overwrite);
|
||||
@@ -251,14 +253,22 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro
|
||||
// Move
|
||||
await move(fromFilePath, toFilePath);
|
||||
} catch (error) {
|
||||
|
||||
// rewrite some typical errors that can happen especially around symlinks
|
||||
// to something the user can better understand
|
||||
if (error.code === 'EINVAL' || error.code === 'EBUSY' || error.code === 'ENAMETOOLONG') {
|
||||
error = new Error(localize('moveError', "Unable to move '{0}' into '{1}' ({2}).", basename(fromFilePath), basename(dirname(toFilePath)), error.toString()));
|
||||
}
|
||||
|
||||
throw this.toFileSystemProviderError(error);
|
||||
}
|
||||
}
|
||||
|
||||
async copy(from: URI, to: URI, opts: FileOverwriteOptions): Promise<void> {
|
||||
const fromFilePath = this.toFilePath(from);
|
||||
const toFilePath = this.toFilePath(to);
|
||||
|
||||
try {
|
||||
const fromFilePath = this.toFilePath(from);
|
||||
const toFilePath = this.toFilePath(to);
|
||||
|
||||
// Ensure target does not exist
|
||||
await this.validateTargetDeleted(from, to, opts && opts.overwrite);
|
||||
@@ -266,6 +276,13 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro
|
||||
// Copy
|
||||
await copy(fromFilePath, toFilePath);
|
||||
} catch (error) {
|
||||
|
||||
// rewrite some typical errors that can happen especially around symlinks
|
||||
// to something the user can better understand
|
||||
if (error.code === 'EINVAL' || error.code === 'EBUSY' || error.code === 'ENAMETOOLONG') {
|
||||
error = new Error(localize('copyError', "Unable to copy '{0}' into '{1}' ({2}).", basename(fromFilePath), basename(dirname(toFilePath)), error.toString()));
|
||||
}
|
||||
|
||||
throw this.toFileSystemProviderError(error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import { getRandomTestPath } from 'vs/base/test/node/testUtils';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { join, basename, dirname, posix } from 'vs/base/common/path';
|
||||
import { getPathFromAmdModule } from 'vs/base/common/amd';
|
||||
import { copy, del } from 'vs/base/node/pfs';
|
||||
import { copy, del, symlink } from 'vs/base/node/pfs';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { existsSync, statSync, readdirSync, readFileSync } from 'fs';
|
||||
import { FileOperation, FileOperationEvent, IFileStat, FileOperationResult, FileSystemProviderCapabilities } from 'vs/platform/files/common/files';
|
||||
@@ -313,11 +313,11 @@ suite('Disk File Service', () => {
|
||||
|
||||
test('resolveFile - folder symbolic link', async () => {
|
||||
if (isWindows) {
|
||||
return; // only for unix systems
|
||||
return; // not happy
|
||||
}
|
||||
|
||||
const link = URI.file(join(testDir, 'deep-link'));
|
||||
await promisify(exec)(`ln -s deep ${basename(link.fsPath)}`, { cwd: testDir });
|
||||
await symlink(join(testDir, 'deep'), link.fsPath);
|
||||
|
||||
const resolved = await service.resolveFile(link);
|
||||
assert.equal(resolved.children!.length, 4);
|
||||
@@ -327,11 +327,11 @@ suite('Disk File Service', () => {
|
||||
|
||||
test('resolveFile - file symbolic link', async () => {
|
||||
if (isWindows) {
|
||||
return; // only for unix systems
|
||||
return; // not happy
|
||||
}
|
||||
|
||||
const link = URI.file(join(testDir, 'lorem.txt-linked'));
|
||||
await promisify(exec)(`ln -s lorem.txt ${basename(link.fsPath)}`, { cwd: testDir });
|
||||
await symlink(join(testDir, 'lorem.txt'), link.fsPath);
|
||||
|
||||
const resolved = await service.resolveFile(link);
|
||||
assert.equal(resolved.isDirectory, false);
|
||||
@@ -340,10 +340,11 @@ suite('Disk File Service', () => {
|
||||
|
||||
test('resolveFile - invalid symbolic link does not break', async () => {
|
||||
if (isWindows) {
|
||||
return; // only for unix systems
|
||||
return; // not happy
|
||||
}
|
||||
|
||||
await promisify(exec)('ln -s foo bar', { cwd: testDir });
|
||||
const link = URI.file(join(testDir, 'foo'));
|
||||
await symlink(link.fsPath, join(testDir, 'bar'));
|
||||
|
||||
const resolved = await service.resolveFile(URI.file(testDir));
|
||||
assert.equal(resolved.isDirectory, true);
|
||||
@@ -488,7 +489,7 @@ suite('Disk File Service', () => {
|
||||
assert.equal(existsSync(source.fsPath), false);
|
||||
assert.ok(event!);
|
||||
assert.equal(event!.resource.fsPath, source.fsPath);
|
||||
assert.equal(event!.operation, FileOperation.MOVE);
|
||||
assert.equal(event!.operation, FileOperation.COPY);
|
||||
assert.equal(event!.target!.resource.fsPath, renamed.resource.fsPath);
|
||||
|
||||
const targetContents = readFileSync(target.fsPath);
|
||||
@@ -575,7 +576,7 @@ suite('Disk File Service', () => {
|
||||
assert.equal(existsSync(source.fsPath), false);
|
||||
assert.ok(event!);
|
||||
assert.equal(event!.resource.fsPath, source.fsPath);
|
||||
assert.equal(event!.operation, FileOperation.MOVE);
|
||||
assert.equal(event!.operation, FileOperation.COPY);
|
||||
assert.equal(event!.target!.resource.fsPath, renamed.resource.fsPath);
|
||||
|
||||
const targetChildren = readdirSync(target.fsPath);
|
||||
|
||||
@@ -279,7 +279,7 @@ class FileOutputChannelModel extends AbstractFileOutputChannelModel implements I
|
||||
}
|
||||
}
|
||||
|
||||
class BufferredOutputChannel extends Disposable implements IOutputChannelModel {
|
||||
export class BufferredOutputChannel extends Disposable implements IOutputChannelModel {
|
||||
|
||||
readonly file: URI | null = null;
|
||||
scrollLock: boolean = false;
|
||||
|
||||
@@ -9,7 +9,7 @@ export class OutputAppender {
|
||||
|
||||
private appender: RotatingLogger;
|
||||
|
||||
constructor(name: string, file: string) {
|
||||
constructor(name: string, readonly file: string) {
|
||||
this.appender = createRotatingLogger(name, file, 1024 * 1024 * 30, 1);
|
||||
this.appender.clearFormatters();
|
||||
}
|
||||
|
||||
@@ -6,21 +6,23 @@
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import * as extfs from 'vs/base/node/extfs';
|
||||
import { dirname, join } from 'vs/base/common/path';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ThrottledDelayer } from 'vs/base/common/async';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { toDisposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { toDisposable, IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IOutputChannelModel, AbstractFileOutputChannelModel, IOutputChannelModelService, AsbtractOutputChannelModelService } from 'vs/workbench/services/output/common/outputChannelModel';
|
||||
import { IOutputChannelModel, AbstractFileOutputChannelModel, IOutputChannelModelService, AsbtractOutputChannelModelService, BufferredOutputChannel } from 'vs/workbench/services/output/common/outputChannelModel';
|
||||
import { OutputAppender } from 'vs/workbench/services/output/node/outputAppender';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { toLocalISOString } from 'vs/base/common/date';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
|
||||
let watchingOutputDir = false;
|
||||
let callbacks: ((eventType: string, fileName?: string) => void)[] = [];
|
||||
@@ -55,15 +57,13 @@ class OutputChannelBackedByFile extends AbstractFileOutputChannelModel implement
|
||||
id: string,
|
||||
modelUri: URI,
|
||||
mimeType: string,
|
||||
@IWindowService windowService: IWindowService,
|
||||
@IEnvironmentService environmentService: IEnvironmentService,
|
||||
file: URI,
|
||||
@IFileService fileService: IFileService,
|
||||
@IModelService modelService: IModelService,
|
||||
@IModeService modeService: IModeService,
|
||||
@ILogService logService: ILogService
|
||||
) {
|
||||
const outputDir = join(environmentService.logsPath, `output_${windowService.getCurrentWindowId()}_${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}`);
|
||||
super(modelUri, mimeType, URI.file(join(outputDir, `${id}.log`)), fileService, modelService, modeService);
|
||||
super(modelUri, mimeType, file, fileService, modelService, modeService);
|
||||
this.appendedMessage = '';
|
||||
this.loadingFromFileInProgress = false;
|
||||
|
||||
@@ -159,32 +159,93 @@ class OutputChannelBackedByFile extends AbstractFileOutputChannelModel implement
|
||||
}
|
||||
}
|
||||
|
||||
class DelegatedOutputChannelModel extends Disposable implements IOutputChannelModel {
|
||||
|
||||
private readonly _onDidAppendedContent: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidAppendedContent: Event<void> = this._onDidAppendedContent.event;
|
||||
|
||||
private readonly _onDispose: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDispose: Event<void> = this._onDispose.event;
|
||||
|
||||
private readonly outputChannelModel: Promise<IOutputChannelModel>;
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
modelUri: URI,
|
||||
mimeType: string,
|
||||
outputDir: Promise<URI>,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
) {
|
||||
super();
|
||||
this.outputChannelModel = this.createOutputChannelModel(id, modelUri, mimeType, outputDir);
|
||||
}
|
||||
|
||||
private async createOutputChannelModel(id: string, modelUri: URI, mimeType: string, outputDirPromise: Promise<URI>): Promise<IOutputChannelModel> {
|
||||
let outputChannelModel: IOutputChannelModel;
|
||||
try {
|
||||
const outputDir = await outputDirPromise;
|
||||
const file = resources.joinPath(outputDir, `${id}.log`);
|
||||
outputChannelModel = this.instantiationService.createInstance(OutputChannelBackedByFile, id, modelUri, mimeType, file);
|
||||
} catch (e) {
|
||||
// Do not crash if spdlog rotating logger cannot be loaded (workaround for https://github.com/Microsoft/vscode/issues/47883)
|
||||
this.logService.error(e);
|
||||
/* __GDPR__
|
||||
"output.channel.creation.error" : {}
|
||||
*/
|
||||
this.telemetryService.publicLog('output.channel.creation.error');
|
||||
outputChannelModel = this.instantiationService.createInstance(BufferredOutputChannel, modelUri, mimeType);
|
||||
}
|
||||
this._register(outputChannelModel);
|
||||
this._register(outputChannelModel.onDidAppendedContent(() => this._onDidAppendedContent.fire()));
|
||||
this._register(outputChannelModel.onDispose(() => this._onDispose.fire()));
|
||||
return outputChannelModel;
|
||||
}
|
||||
|
||||
append(output: string): void {
|
||||
this.outputChannelModel.then(outputChannelModel => outputChannelModel.append(output));
|
||||
}
|
||||
|
||||
update(): void {
|
||||
this.outputChannelModel.then(outputChannelModel => outputChannelModel.update());
|
||||
}
|
||||
|
||||
loadModel(): Promise<ITextModel> {
|
||||
return this.outputChannelModel.then(outputChannelModel => outputChannelModel.loadModel());
|
||||
}
|
||||
|
||||
clear(till?: number): void {
|
||||
this.outputChannelModel.then(outputChannelModel => outputChannelModel.clear(till));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class OutputChannelModelService extends AsbtractOutputChannelModelService implements IOutputChannelModelService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
constructor(
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IFileService private readonly fileService: IFileService
|
||||
) {
|
||||
super(instantiationService);
|
||||
}
|
||||
|
||||
createOutputChannelModel(id: string, modelUri: URI, mimeType: string, file?: URI): IOutputChannelModel {
|
||||
if (!file) {
|
||||
try {
|
||||
return this.instantiationService.createInstance(OutputChannelBackedByFile, id, modelUri, mimeType);
|
||||
} catch (e) {
|
||||
// Do not crash if spdlog rotating logger cannot be loaded (workaround for https://github.com/Microsoft/vscode/issues/47883)
|
||||
this.logService.error(e);
|
||||
/* __GDPR__
|
||||
"output.channel.creation.error" : {}
|
||||
*/
|
||||
this.telemetryService.publicLog('output.channel.creation.error');
|
||||
}
|
||||
return file ? super.createOutputChannelModel(id, modelUri, mimeType, file) :
|
||||
this.instantiationService.createInstance(DelegatedOutputChannelModel, id, modelUri, mimeType, this.outputDir);
|
||||
}
|
||||
|
||||
private _outputDir: Promise<URI> | null;
|
||||
private get outputDir(): Promise<URI> {
|
||||
if (!this._outputDir) {
|
||||
const outputDir = URI.file(join(this.environmentService.logsPath, `output_${this.windowService.getCurrentWindowId()}_${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}`));
|
||||
this._outputDir = this.fileService.createFolder(outputDir).then(() => outputDir);
|
||||
}
|
||||
return super.createOutputChannelModel(id, modelUri, mimeType, file);
|
||||
return this._outputDir;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user