From 87bf1d80652c928d4c81cfa95b05bbf285e6dd84 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 15 Dec 2021 17:20:55 +0100 Subject: [PATCH] #126376 remove user configuration file service and use atomic read --- .../sharedProcess/sharedProcessMain.ts | 4 - src/vs/code/electron-main/app.ts | 6 -- .../common/userConfigurationFileService.ts | 99 ------------------- .../userData/common/fileUserDataProvider.ts | 67 ++++--------- .../common/abstractSynchronizer.ts | 6 +- .../userDataSync/common/settingsSync.ts | 8 +- .../test/common/userDataSyncClient.ts | 2 - .../configuration/browser/configuration.ts | 25 +---- .../common/configurationEditingService.ts | 19 +--- .../userConfigurationFileService.ts | 9 -- .../configurationEditingService.test.ts | 2 - .../test/browser/configurationService.test.ts | 4 - src/vs/workbench/workbench.sandbox.main.ts | 1 - src/vs/workbench/workbench.web.main.ts | 2 - 14 files changed, 26 insertions(+), 228 deletions(-) delete mode 100644 src/vs/platform/configuration/common/userConfigurationFileService.ts delete mode 100644 src/vs/workbench/services/configuration/electron-sandbox/userConfigurationFileService.ts diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index 8f913491b31..7b96b75a0ad 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -91,7 +91,6 @@ import { ipcSharedProcessTunnelChannelName, ISharedProcessTunnelService } from ' import { SharedProcessTunnelService } from 'vs/platform/remote/node/sharedProcessTunnelService'; import { ipcSharedProcessWorkerChannelName, ISharedProcessWorkerConfiguration, ISharedProcessWorkerService } from 'vs/platform/sharedProcess/common/sharedProcessWorkerService'; import { SharedProcessWorkerService } from 'vs/platform/sharedProcess/electron-browser/sharedProcessWorkerService'; -import { IUserConfigurationFileService, UserConfigurationFileServiceId } from 'vs/platform/configuration/common/userConfigurationFileService'; import { AssignmentService } from 'vs/platform/assignment/common/assignmentService'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; import { UriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentityService'; @@ -226,9 +225,6 @@ class SharedProcessMain extends Disposable { storageService.initialize() ]); - // User Configuration File - services.set(IUserConfigurationFileService, ProxyChannel.toService(mainProcessService.getChannel(UserConfigurationFileServiceId))); - // URI Identity services.set(IUriIdentityService, new UriIdentityService(fileService)); diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 270507783aa..dc37be376ef 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -32,7 +32,6 @@ import { localize } from 'vs/nls'; import { IBackupMainService } from 'vs/platform/backup/electron-main/backup'; import { BackupMainService } from 'vs/platform/backup/electron-main/backupMainService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { UserConfigurationFileService, UserConfigurationFileServiceId } from 'vs/platform/configuration/common/userConfigurationFileService'; import { ElectronExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/electron-main/extensionHostDebugIpc'; import { IDiagnosticsService } from 'vs/platform/diagnostics/common/diagnostics'; import { DialogMainService, IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService'; @@ -573,11 +572,6 @@ export class CodeApplication extends Disposable { mainProcessElectronServer.registerChannel('localFilesystem', fileSystemProviderChannel); sharedProcessClient.then(client => client.registerChannel('localFilesystem', fileSystemProviderChannel)); - // User Configuration File - const userConfigurationFileService = new UserConfigurationFileService(this.environmentMainService, this.fileService, this.logService); - mainProcessElectronServer.registerChannel(UserConfigurationFileServiceId, ProxyChannel.fromService(userConfigurationFileService)); - sharedProcessClient.then(client => client.registerChannel(UserConfigurationFileServiceId, ProxyChannel.fromService(userConfigurationFileService))); - // Update const updateChannel = new UpdateChannel(accessor.get(IUpdateService)); mainProcessElectronServer.registerChannel('update', updateChannel); diff --git a/src/vs/platform/configuration/common/userConfigurationFileService.ts b/src/vs/platform/configuration/common/userConfigurationFileService.ts deleted file mode 100644 index 2507cb3e1f4..00000000000 --- a/src/vs/platform/configuration/common/userConfigurationFileService.ts +++ /dev/null @@ -1,99 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Queue } from 'vs/base/common/async'; -import { VSBuffer } from 'vs/base/common/buffer'; -import { JSONPath, parse, ParseError } from 'vs/base/common/json'; -import { setProperty } from 'vs/base/common/jsonEdit'; -import { Edit, FormattingOptions } from 'vs/base/common/jsonFormatter'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { FileOperationError, FileOperationResult, IFileService, IWriteFileOptions } from 'vs/platform/files/common/files'; -import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { ILogService } from 'vs/platform/log/common/log'; - -export const enum UserConfigurationErrorCode { - ERROR_INVALID_FILE = 'ERROR_INVALID_FILE', - ERROR_FILE_MODIFIED_SINCE = 'ERROR_FILE_MODIFIED_SINCE' -} - -export interface IJSONValue { - path: JSONPath; - value: any; -} - -export const UserConfigurationFileServiceId = 'IUserConfigurationFileService'; -export const IUserConfigurationFileService = createDecorator(UserConfigurationFileServiceId); - -export interface IUserConfigurationFileService { - readonly _serviceBrand: undefined; - - updateSettings(value: IJSONValue, formattingOptions: FormattingOptions): Promise; - write(value: VSBuffer, options?: IWriteFileOptions): Promise; -} - -export class UserConfigurationFileService implements IUserConfigurationFileService { - - readonly _serviceBrand: undefined; - - private readonly queue: Queue; - - constructor( - @IEnvironmentService private readonly environmentService: IEnvironmentService, - @IFileService private readonly fileService: IFileService, - @ILogService private readonly logService: ILogService, - ) { - this.queue = new Queue(); - } - - async updateSettings(value: IJSONValue, formattingOptions: FormattingOptions): Promise { - return this.queue.queue(() => this.doWrite(value, formattingOptions)); // queue up writes to prevent race conditions - } - - private async doWrite(jsonValue: IJSONValue, formattingOptions: FormattingOptions): Promise { - this.logService.trace(`${UserConfigurationFileServiceId}#write`, this.environmentService.settingsResource.toString(), jsonValue); - const { value, mtime, etag } = await this.fileService.readFile(this.environmentService.settingsResource, { atomic: true }); - let content = value.toString(); - - const parseErrors: ParseError[] = []; - parse(content, parseErrors, { allowTrailingComma: true, allowEmptyContent: true }); - if (parseErrors.length) { - throw new Error(UserConfigurationErrorCode.ERROR_INVALID_FILE); - } - - const edit = this.getEdits(jsonValue, content, formattingOptions)[0]; - if (edit) { - content = content.substring(0, edit.offset) + edit.content + content.substring(edit.offset + edit.length); - try { - await this.fileService.writeFile(this.environmentService.settingsResource, VSBuffer.fromString(content), { etag, mtime }); - } catch (error) { - if ((error).fileOperationResult === FileOperationResult.FILE_MODIFIED_SINCE) { - throw new Error(UserConfigurationErrorCode.ERROR_FILE_MODIFIED_SINCE); - } - } - } - } - - async write(content: VSBuffer, options?: IWriteFileOptions): Promise { - // queue up writes to prevent race conditions - return this.queue.queue(async () => { - await this.fileService.writeFile(this.environmentService.settingsResource, content, options); - }); - } - - private getEdits({ value, path }: IJSONValue, modelContent: string, formattingOptions: FormattingOptions): Edit[] { - if (path.length) { - return setProperty(modelContent, path, value, formattingOptions); - } - - // Without jsonPath, the entire configuration file is being replaced, so we just use JSON.stringify - const content = JSON.stringify(value, null, formattingOptions.insertSpaces && formattingOptions.tabSize ? ' '.repeat(formattingOptions.tabSize) : '\t'); - return [{ - content, - length: modelContent.length, - offset: 0 - }]; - } -} - diff --git a/src/vs/platform/userData/common/fileUserDataProvider.ts b/src/vs/platform/userData/common/fileUserDataProvider.ts index 3381d39b283..211f88f7da6 100644 --- a/src/vs/platform/userData/common/fileUserDataProvider.ts +++ b/src/vs/platform/userData/common/fileUserDataProvider.ts @@ -2,15 +2,15 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - import { Event, Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import { IFileSystemProviderWithFileReadWriteCapability, IFileChange, IWatchOptions, IStat, FileOverwriteOptions, FileType, FileWriteOptions, FileDeleteOptions, FileSystemProviderCapabilities, IFileSystemProviderWithOpenReadWriteCloseCapability, FileOpenOptions, hasReadWriteCapability, hasOpenReadWriteCloseCapability, IFileSystemProviderWithFileReadStreamCapability, FileReadStreamOptions, hasFileReadStreamCapability } from 'vs/platform/files/common/files'; +import { IFileSystemProviderWithFileReadWriteCapability, IFileChange, IWatchOptions, IStat, FileOverwriteOptions, FileType, FileWriteOptions, FileDeleteOptions, FileSystemProviderCapabilities, IFileSystemProviderWithFileReadStreamCapability, FileReadStreamOptions, IFileSystemProviderWithFileAtomicReadCapability } from 'vs/platform/files/common/files'; import { URI } from 'vs/base/common/uri'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { ReadableStreamEvents } from 'vs/base/common/stream'; +import { newWriteableStream, ReadableStreamEvents } from 'vs/base/common/stream'; import { ILogService } from 'vs/platform/log/common/log'; import { TernarySearchTree } from 'vs/base/common/map'; +import { VSBuffer } from 'vs/base/common/buffer'; /** * This is a wrapper on top of the local filesystem provider which will @@ -19,10 +19,10 @@ import { TernarySearchTree } from 'vs/base/common/map'; */ export class FileUserDataProvider extends Disposable implements IFileSystemProviderWithFileReadWriteCapability, - IFileSystemProviderWithOpenReadWriteCloseCapability, - IFileSystemProviderWithFileReadStreamCapability { + IFileSystemProviderWithFileReadStreamCapability, + IFileSystemProviderWithFileAtomicReadCapability { - get capabilities() { return this.fileSystemProvider.capabilities; } + get capabilities() { return this.fileSystemProvider.capabilities & ~FileSystemProviderCapabilities.FileOpenReadWriteClose; } readonly onDidChangeCapabilities: Event = this.fileSystemProvider.onDidChangeCapabilities; private readonly _onDidChangeFile = this._register(new Emitter()); @@ -32,7 +32,7 @@ export class FileUserDataProvider extends Disposable implements constructor( private readonly fileSystemScheme: string, - private readonly fileSystemProvider: IFileSystemProviderWithFileReadWriteCapability | IFileSystemProviderWithOpenReadWriteCloseCapability, + private readonly fileSystemProvider: IFileSystemProviderWithFileReadWriteCapability & (IFileSystemProviderWithFileReadStreamCapability | IFileSystemProviderWithFileAtomicReadCapability), private readonly userDataScheme: string, private readonly logService: ILogService, ) { @@ -62,17 +62,21 @@ export class FileUserDataProvider extends Disposable implements } readFile(resource: URI): Promise { - if (hasReadWriteCapability(this.fileSystemProvider)) { - return this.fileSystemProvider.readFile(this.toFileSystemResource(resource)); - } - throw new Error('not supported'); + return this.fileSystemProvider.readFile(this.toFileSystemResource(resource), { atomic: true }); } readFileStream(resource: URI, opts: FileReadStreamOptions, token: CancellationToken): ReadableStreamEvents { - if (hasFileReadStreamCapability(this.fileSystemProvider)) { - return this.fileSystemProvider.readFileStream(this.toFileSystemResource(resource), opts, token); - } - throw new Error('not supported'); + const stream = newWriteableStream(data => VSBuffer.concat(data.map(data => VSBuffer.wrap(data))).buffer); + (async () => { + try { + const contents = await this.readFile(resource); + stream.end(contents); + } catch (error) { + stream.error(error); + stream.end(); + } + })(); + return stream; } readdir(resource: URI): Promise<[string, FileType][]> { @@ -80,38 +84,7 @@ export class FileUserDataProvider extends Disposable implements } writeFile(resource: URI, content: Uint8Array, opts: FileWriteOptions): Promise { - if (hasReadWriteCapability(this.fileSystemProvider)) { - return this.fileSystemProvider.writeFile(this.toFileSystemResource(resource), content, opts); - } - throw new Error('not supported'); - } - - open(resource: URI, opts: FileOpenOptions): Promise { - if (hasOpenReadWriteCloseCapability(this.fileSystemProvider)) { - return this.fileSystemProvider.open(this.toFileSystemResource(resource), opts); - } - throw new Error('not supported'); - } - - close(fd: number): Promise { - if (hasOpenReadWriteCloseCapability(this.fileSystemProvider)) { - return this.fileSystemProvider.close(fd); - } - throw new Error('not supported'); - } - - read(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise { - if (hasOpenReadWriteCloseCapability(this.fileSystemProvider)) { - return this.fileSystemProvider.read(fd, pos, data, offset, length); - } - throw new Error('not supported'); - } - - write(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise { - if (hasOpenReadWriteCloseCapability(this.fileSystemProvider)) { - return this.fileSystemProvider.write(fd, pos, data, offset, length); - } - throw new Error('not supported'); + return this.fileSystemProvider.writeFile(this.toFileSystemResource(resource), content, opts); } delete(resource: URI, opts: FileDeleteOptions): Promise { diff --git a/src/vs/platform/userDataSync/common/abstractSynchronizer.ts b/src/vs/platform/userDataSync/common/abstractSynchronizer.ts index 1469f889cb8..923da78af6c 100644 --- a/src/vs/platform/userDataSync/common/abstractSynchronizer.ts +++ b/src/vs/platform/userDataSync/common/abstractSynchronizer.ts @@ -753,7 +753,7 @@ export abstract class AbstractFileSynchroniser extends AbstractSynchroniser { try { if (oldContent) { // file exists already - await this.writeFileContent(newContent, oldContent, force); + await this.fileService.writeFile(this.file, VSBuffer.fromString(newContent), force ? undefined : oldContent); } else { // file does not exist await this.fileService.createFile(this.file, VSBuffer.fromString(newContent), { overwrite: force }); @@ -768,10 +768,6 @@ export abstract class AbstractFileSynchroniser extends AbstractSynchroniser { } } - protected async writeFileContent(newContent: string, oldContent: IFileContent, force: boolean): Promise { - await this.fileService.writeFile(this.file, VSBuffer.fromString(newContent), force ? undefined : oldContent); - } - private onFileChanges(e: FileChangesEvent): void { if (!e.contains(this.file)) { return; diff --git a/src/vs/platform/userDataSync/common/settingsSync.ts b/src/vs/platform/userDataSync/common/settingsSync.ts index 5eff7eb26eb..1ec503c1420 100644 --- a/src/vs/platform/userDataSync/common/settingsSync.ts +++ b/src/vs/platform/userDataSync/common/settingsSync.ts @@ -10,10 +10,9 @@ import { URI } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ConfigurationModelParser } from 'vs/platform/configuration/common/configurationModels'; -import { IUserConfigurationFileService } from 'vs/platform/configuration/common/userConfigurationFileService'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { FileOperationError, FileOperationResult, IFileContent, IFileService } from 'vs/platform/files/common/files'; +import { FileOperationError, FileOperationResult, IFileService } from 'vs/platform/files/common/files'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; @@ -62,7 +61,6 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement @IUserDataSyncEnablementService userDataSyncEnablementService: IUserDataSyncEnablementService, @ITelemetryService telemetryService: ITelemetryService, @IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService, - @IUserConfigurationFileService private readonly userConfigurationFileService: IUserConfigurationFileService, @IUriIdentityService uriIdentityService: IUriIdentityService, ) { super(environmentService.settingsResource, SyncResource.Settings, fileService, environmentService, storageService, userDataSyncStoreService, userDataSyncBackupStoreService, userDataSyncEnablementService, telemetryService, logService, userDataSyncUtilService, configurationService, uriIdentityService); @@ -341,10 +339,6 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement return getIgnoredSettings(defaultIgnoredSettings, this.configurationService, content); } - protected override async writeFileContent(newContent: string, oldContent: IFileContent, force: boolean): Promise { - await this.userConfigurationFileService.write(VSBuffer.fromString(newContent), force ? undefined : { etag: oldContent.etag, mtime: oldContent.mtime }); - } - private validateContent(content: string): void { if (this.hasErrors(content)) { throw new UserDataSyncError(localize('errorInvalidSettings', "Unable to sync settings as there are errors/warning in settings file."), UserDataSyncErrorCode.LocalInvalidContent, this.resource); diff --git a/src/vs/platform/userDataSync/test/common/userDataSyncClient.ts b/src/vs/platform/userDataSync/test/common/userDataSyncClient.ts index 194c6892996..df284282c0e 100644 --- a/src/vs/platform/userDataSync/test/common/userDataSyncClient.ts +++ b/src/vs/platform/userDataSync/test/common/userDataSyncClient.ts @@ -16,7 +16,6 @@ import { generateUuid } from 'vs/base/common/uuid'; import { IHeaders, IRequestContext, IRequestOptions } from 'vs/base/parts/request/common/request'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ConfigurationService } from 'vs/platform/configuration/common/configurationService'; -import { IUserConfigurationFileService, UserConfigurationFileService } from 'vs/platform/configuration/common/userConfigurationFileService'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { GlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService'; import { DidUninstallExtensionEvent, IExtensionGalleryService, IExtensionManagementService, IGlobalExtensionEnablementService, InstallExtensionResult } from 'vs/platform/extensionManagement/common/extensionManagement'; @@ -90,7 +89,6 @@ export class UserDataSyncClient extends Disposable { const configurationService = this._register(new ConfigurationService(environmentService.settingsResource, fileService)); await configurationService.initialize(); this.instantiationService.stub(IConfigurationService, configurationService); - this.instantiationService.stub(IUserConfigurationFileService, this.instantiationService.createInstance(UserConfigurationFileService)); this.instantiationService.stub(IUriIdentityService, this.instantiationService.createInstance(UriIdentityService)); this.instantiationService.stub(IRequestService, this.testServer); diff --git a/src/vs/workbench/services/configuration/browser/configuration.ts b/src/vs/workbench/services/configuration/browser/configuration.ts index b92fea9cdda..57e9e9c1c03 100644 --- a/src/vs/workbench/services/configuration/browser/configuration.ts +++ b/src/vs/workbench/services/configuration/browser/configuration.ts @@ -7,7 +7,7 @@ import { URI } from 'vs/base/common/uri'; import { Event, Emitter } from 'vs/base/common/event'; import * as errors from 'vs/base/common/errors'; import { Disposable, IDisposable, dispose, toDisposable, MutableDisposable, combinedDisposable, DisposableStore } from 'vs/base/common/lifecycle'; -import { RunOnceScheduler, timeout } from 'vs/base/common/async'; +import { RunOnceScheduler } from 'vs/base/common/async'; import { FileChangeType, FileChangesEvent, IFileService, whenProviderRegistered, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files'; import { ConfigurationModel, ConfigurationModelParser, ConfigurationParseOptions, DefaultConfigurationModel, UserSettings } from 'vs/platform/configuration/common/configurationModels'; import { WorkspaceConfigurationModelParser, StandaloneConfigurationModelParser } from 'vs/workbench/services/configuration/common/configurationModels'; @@ -22,7 +22,6 @@ import { hash } from 'vs/base/common/hash'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; import { ILogService } from 'vs/platform/log/common/log'; import { IStringDictionary } from 'vs/base/common/collections'; -import { ResourceMap } from 'vs/base/common/map'; import { joinPath } from 'vs/base/common/resources'; import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -194,10 +193,6 @@ class FileServiceBasedConfiguration extends Disposable { private readonly _onDidChange: Emitter = this._register(new Emitter()); readonly onDidChange: Event = this._onDidChange.event; - private readonly resourcesContentMap = new ResourceMap(uri => this.uriIdentityService.extUri.getComparisonKey(uri)); - - private disposed: boolean = false; - constructor( name: string, private readonly settingsResource: URI, @@ -221,7 +216,6 @@ class FileServiceBasedConfiguration extends Disposable { this._cache = new ConfigurationModel(); this._register(Event.debounce(Event.filter(this.fileService.onDidFilesChange, e => this.handleFileEvents(e)), () => undefined, 100)(() => this._onDidChange.fire())); - this._register(toDisposable(() => this.disposed = true)); } async resolveContents(): Promise<[string | undefined, [string, string | undefined][]]> { @@ -229,24 +223,9 @@ class FileServiceBasedConfiguration extends Disposable { const resolveContents = async (resources: URI[]): Promise<(string | undefined)[]> => { return Promise.all(resources.map(async resource => { try { - let content = (await this.fileService.readFile(resource, { atomic: true })).value.toString(); - - // If file is empty and had content before then file would have been truncated by node because of parallel writes from other windows - // To prevent such case, retry reading the file in 20ms intervals until file has content or max 5 trials or disposed. - // https://github.com/microsoft/vscode/issues/115740 https://github.com/microsoft/vscode/issues/125970 - for (let trial = 1; !content && this.resourcesContentMap.get(resource) && !this.disposed && trial <= 5; trial++) { - await timeout(20); - this.logService.debug(`Retry (${trial}): Reading the configuration file`, resource.toString()); - content = (await this.fileService.readFile(resource)).value.toString(); - } - - this.resourcesContentMap.set(resource, !!content); - if (!content) { - this.logService.debug(`Configuration file '${resource.toString()}' is empty`); - } + const content = (await this.fileService.readFile(resource)).value.toString(); return content; } catch (error) { - this.resourcesContentMap.delete(resource); this.logService.trace(`Error while resolving configuration file '${resource.toString()}': ${errors.getErrorMessage(error)}`); if ((error).fileOperationResult !== FileOperationResult.FILE_NOT_FOUND && (error).fileOperationResult !== FileOperationResult.FILE_NOT_DIRECTORY) { diff --git a/src/vs/workbench/services/configuration/common/configurationEditingService.ts b/src/vs/workbench/services/configuration/common/configurationEditingService.ts index ff704ab4edb..fb1cad2125b 100644 --- a/src/vs/workbench/services/configuration/common/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/common/configurationEditingService.ts @@ -15,7 +15,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IConfigurationService, IConfigurationUpdateOverrides } from 'vs/platform/configuration/common/configuration'; import { FOLDER_SETTINGS_PATH, WORKSPACE_STANDALONE_CONFIGURATIONS, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY, USER_STANDALONE_CONFIGURATIONS, TASKS_DEFAULT, FOLDER_SCOPES } from 'vs/workbench/services/configuration/common/configuration'; -import { IFileService, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files'; +import { IFileService } from 'vs/platform/files/common/files'; import { IResolvedTextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope, keyFromOverrideIdentifiers, OVERRIDE_PROPERTY_REGEX } from 'vs/platform/configuration/common/configurationRegistry'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -24,7 +24,6 @@ import { IOpenSettingsOptions, IPreferencesService } from 'vs/workbench/services import { withUndefinedAsNull, withNullAsUndefined } from 'vs/base/common/types'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; -import { IUserConfigurationFileService, UserConfigurationErrorCode } from 'vs/platform/configuration/common/userConfigurationFileService'; import { ITextModel } from 'vs/editor/common/model'; import { IReference } from 'vs/base/common/lifecycle'; import { Range } from 'vs/editor/common/core/range'; @@ -153,7 +152,6 @@ export class ConfigurationEditingService { @IEditorService private readonly editorService: IEditorService, @IRemoteAgentService remoteAgentService: IRemoteAgentService, @IUriIdentityService private readonly uriIdentityService: IUriIdentityService, - @IUserConfigurationFileService private readonly userConfigurationFileService: IUserConfigurationFileService, ) { this.queue = new Queue(); remoteAgentService.getEnvironment().then(environment => { @@ -181,20 +179,7 @@ export class ConfigurationEditingService { const reference = await this.resolveModelReference(resource); try { const formattingOptions = this.getFormattingOptions(reference.object.textEditorModel); - if (!this.textFileService.isDirty(resource) /* go through text model save if the model is dirty */ - && this.uriIdentityService.extUri.isEqual(resource, this.environmentService.settingsResource)) { - await this.userConfigurationFileService.updateSettings({ path: operation.jsonPath, value: operation.value }, formattingOptions); - } else { - await this.updateConfiguration(operation, reference.object.textEditorModel, formattingOptions); - } - } catch (error) { - if ((error).message === UserConfigurationErrorCode.ERROR_INVALID_FILE) { - throw this.toConfigurationEditingError(ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION, operation.target, operation); - } - if ((error).message === UserConfigurationErrorCode.ERROR_FILE_MODIFIED_SINCE || (error).fileOperationResult === FileOperationResult.FILE_MODIFIED_SINCE) { - throw this.toConfigurationEditingError(ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_MODIFIED_SINCE, operation.target, operation); - } - throw error; + await this.updateConfiguration(operation, reference.object.textEditorModel, formattingOptions); } finally { reference.dispose(); } diff --git a/src/vs/workbench/services/configuration/electron-sandbox/userConfigurationFileService.ts b/src/vs/workbench/services/configuration/electron-sandbox/userConfigurationFileService.ts deleted file mode 100644 index 4d8c29e82d7..00000000000 --- a/src/vs/workbench/services/configuration/electron-sandbox/userConfigurationFileService.ts +++ /dev/null @@ -1,9 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { registerMainProcessRemoteService } from 'vs/platform/ipc/electron-sandbox/services'; -import { IUserConfigurationFileService, UserConfigurationFileServiceId } from 'vs/platform/configuration/common/userConfigurationFileService'; - -registerMainProcessRemoteService(IUserConfigurationFileService, UserConfigurationFileServiceId); diff --git a/src/vs/workbench/services/configuration/test/browser/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/browser/configurationEditingService.test.ts index baf5d279ff0..69c555c5eba 100644 --- a/src/vs/workbench/services/configuration/test/browser/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/browser/configurationEditingService.test.ts @@ -39,7 +39,6 @@ import { VSBuffer } from 'vs/base/common/buffer'; import { RemoteAgentService } from 'vs/workbench/services/remote/browser/remoteAgentServiceImpl'; import { BrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService'; import { getSingleFolderWorkspaceIdentifier } from 'vs/workbench/services/workspaces/browser/workspaces'; -import { IUserConfigurationFileService, UserConfigurationFileService } from 'vs/platform/configuration/common/userConfigurationFileService'; const ROOT = URI.file('tests').with({ scheme: 'vscode-tests' }); @@ -107,7 +106,6 @@ suite('ConfigurationEditingService', () => { instantiationService.stub(ITextFileService, disposables.add(instantiationService.createInstance(TestTextFileService))); instantiationService.stub(ITextModelService, disposables.add(instantiationService.createInstance(TextModelResolverService))); instantiationService.stub(ICommandService, CommandService); - instantiationService.stub(IUserConfigurationFileService, new UserConfigurationFileService(environmentService, fileService, logService)); testObject = instantiationService.createInstance(ConfigurationEditingService); }); diff --git a/src/vs/workbench/services/configuration/test/browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/browser/configurationService.test.ts index 594cd2ceb9d..25652304a1f 100644 --- a/src/vs/workbench/services/configuration/test/browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/browser/configurationService.test.ts @@ -44,7 +44,6 @@ import { BrowserWorkbenchEnvironmentService } from 'vs/workbench/services/enviro import { RemoteAgentService } from 'vs/workbench/services/remote/browser/remoteAgentServiceImpl'; import { RemoteAuthorityResolverService } from 'vs/platform/remote/browser/remoteAuthorityResolverService'; import { hash } from 'vs/base/common/hash'; -import { IUserConfigurationFileService, UserConfigurationFileService } from 'vs/platform/configuration/common/userConfigurationFileService'; function convertToWorkspacePayload(folder: URI): ISingleFolderWorkspaceIdentifier { return { @@ -704,7 +703,6 @@ suite('WorkspaceConfigurationService - Folder', () => { instantiationService.stub(IKeybindingEditingService, instantiationService.createInstance(KeybindingsEditingService)); instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); - instantiationService.stub(IUserConfigurationFileService, new UserConfigurationFileService(environmentService, fileService, logService)); workspaceService.acquireInstantiationService(instantiationService); }); @@ -1378,7 +1376,6 @@ suite('WorkspaceConfigurationService-Multiroot', () => { instantiationService.stub(IKeybindingEditingService, instantiationService.createInstance(KeybindingsEditingService)); instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); - instantiationService.stub(IUserConfigurationFileService, new UserConfigurationFileService(environmentService, fileService, logService)); workspaceService.acquireInstantiationService(instantiationService); workspaceContextService = workspaceService; @@ -2033,7 +2030,6 @@ suite('WorkspaceConfigurationService - Remote Folder', () => { instantiationService.stub(IConfigurationService, testObject); instantiationService.stub(IEnvironmentService, environmentService); instantiationService.stub(IFileService, fileService); - instantiationService.stub(IUserConfigurationFileService, new UserConfigurationFileService(environmentService, fileService, logService)); }); async function initialize(): Promise { diff --git a/src/vs/workbench/workbench.sandbox.main.ts b/src/vs/workbench/workbench.sandbox.main.ts index 3a79b7167b7..52896dd1c14 100644 --- a/src/vs/workbench/workbench.sandbox.main.ts +++ b/src/vs/workbench/workbench.sandbox.main.ts @@ -77,7 +77,6 @@ import 'vs/platform/diagnostics/electron-sandbox/diagnosticsService'; import 'vs/platform/checksum/electron-sandbox/checksumService'; import 'vs/platform/telemetry/electron-sandbox/customEndpointTelemetryService'; import 'vs/workbench/services/files/electron-sandbox/elevatedFileService'; -import 'vs/workbench/services/configuration/electron-sandbox/userConfigurationFileService'; import 'vs/workbench/services/search/electron-sandbox/searchService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts index 73cbe1c7451..6deb2a3be56 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts @@ -85,11 +85,9 @@ import { TitlebarPart } from 'vs/workbench/browser/parts/titlebar/titlebarPart'; import { ITimerService, TimerService } from 'vs/workbench/services/timer/browser/timerService'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { ConfigurationResolverService } from 'vs/workbench/services/configurationResolver/browser/configurationResolverService'; -import { IUserConfigurationFileService, UserConfigurationFileService } from 'vs/platform/configuration/common/userConfigurationFileService'; import { WebUserDataSyncEnablementService } from 'vs/workbench/services/userDataSync/browser/userDataSyncEnablementService'; registerSingleton(IUserDataSyncEnablementService, WebUserDataSyncEnablementService); -registerSingleton(IUserConfigurationFileService, UserConfigurationFileService); registerSingleton(IWorkbenchExtensionManagementService, ExtensionManagementService); registerSingleton(IAccessibilityService, AccessibilityService, true); registerSingleton(IContextMenuService, ContextMenuService);