mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-17 15:24:40 +01:00
Fix #134909
This commit is contained in:
@@ -94,6 +94,7 @@ 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';
|
||||
|
||||
class SharedProcessMain extends Disposable {
|
||||
|
||||
@@ -218,6 +219,9 @@ class SharedProcessMain extends Disposable {
|
||||
storageService.initialize()
|
||||
]);
|
||||
|
||||
// User Configuration File
|
||||
services.set(IUserConfigurationFileService, ProxyChannel.toService<IUserConfigurationFileService>(mainProcessService.getChannel(UserConfigurationFileServiceId)));
|
||||
|
||||
// Request
|
||||
services.set(IRequestService, new SyncDescriptor(RequestService));
|
||||
|
||||
|
||||
@@ -567,8 +567,10 @@ export class CodeApplication extends Disposable {
|
||||
const fileSystemProviderChannel = new DiskFileSystemProviderChannel(diskFileSystemProvider, this.logService);
|
||||
mainProcessElectronServer.registerChannel('localFilesystem', fileSystemProviderChannel);
|
||||
|
||||
// Configuration
|
||||
mainProcessElectronServer.registerChannel(UserConfigurationFileServiceId, ProxyChannel.fromService(new UserConfigurationFileService(this.environmentMainService, this.fileService, this.logService)));
|
||||
// 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));
|
||||
|
||||
@@ -8,9 +8,8 @@ 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 { URI } from 'vs/base/common/uri';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { FileOperationError, FileOperationResult, IFileService } from 'vs/platform/files/common/files';
|
||||
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';
|
||||
|
||||
@@ -31,6 +30,7 @@ export interface IUserConfigurationFileService {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
updateSettings(value: IJSONValue, formattingOptions: FormattingOptions): Promise<void>;
|
||||
write(value: VSBuffer, options?: IWriteFileOptions): Promise<void>;
|
||||
}
|
||||
|
||||
export class UserConfigurationFileService implements IUserConfigurationFileService {
|
||||
@@ -48,12 +48,12 @@ export class UserConfigurationFileService implements IUserConfigurationFileServi
|
||||
}
|
||||
|
||||
async updateSettings(value: IJSONValue, formattingOptions: FormattingOptions): Promise<void> {
|
||||
return this.queue.queue(() => this.doWrite(this.environmentService.settingsResource, value, formattingOptions)); // queue up writes to prevent race conditions
|
||||
return this.queue.queue(() => this.doWrite(value, formattingOptions)); // queue up writes to prevent race conditions
|
||||
}
|
||||
|
||||
private async doWrite(resource: URI, jsonValue: IJSONValue, formattingOptions: FormattingOptions): Promise<void> {
|
||||
this.logService.trace(`${UserConfigurationFileServiceId}#write`, resource.toString(), jsonValue);
|
||||
const { value, mtime, etag } = await this.fileService.readFile(resource, { atomic: true });
|
||||
private async doWrite(jsonValue: IJSONValue, formattingOptions: FormattingOptions): Promise<void> {
|
||||
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[] = [];
|
||||
@@ -66,7 +66,7 @@ export class UserConfigurationFileService implements IUserConfigurationFileServi
|
||||
if (edit) {
|
||||
content = content.substring(0, edit.offset) + edit.content + content.substring(edit.offset + edit.length);
|
||||
try {
|
||||
await this.fileService.writeFile(resource, VSBuffer.fromString(content), { etag, mtime });
|
||||
await this.write(VSBuffer.fromString(content), { etag, mtime });
|
||||
} catch (error) {
|
||||
if ((<FileOperationError>error).fileOperationResult === FileOperationResult.FILE_MODIFIED_SINCE) {
|
||||
throw new Error(UserConfigurationErrorCode.ERROR_FILE_MODIFIED_SINCE);
|
||||
@@ -75,6 +75,10 @@ export class UserConfigurationFileService implements IUserConfigurationFileServi
|
||||
}
|
||||
}
|
||||
|
||||
async write(content: VSBuffer, options?: IWriteFileOptions): Promise<void> {
|
||||
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);
|
||||
|
||||
@@ -760,7 +760,7 @@ export abstract class AbstractFileSynchroniser extends AbstractSynchroniser {
|
||||
try {
|
||||
if (oldContent) {
|
||||
// file exists already
|
||||
await this.fileService.writeFile(this.file, VSBuffer.fromString(newContent), force ? undefined : oldContent);
|
||||
await this.writeFileContent(newContent, oldContent, force);
|
||||
} else {
|
||||
// file does not exist
|
||||
await this.fileService.createFile(this.file, VSBuffer.fromString(newContent), { overwrite: force });
|
||||
@@ -775,6 +775,10 @@ export abstract class AbstractFileSynchroniser extends AbstractSynchroniser {
|
||||
}
|
||||
}
|
||||
|
||||
protected async writeFileContent(newContent: string, oldContent: IFileContent, force: boolean): Promise<void> {
|
||||
await this.fileService.writeFile(this.file, VSBuffer.fromString(newContent), force ? undefined : oldContent);
|
||||
}
|
||||
|
||||
private onFileChanges(e: FileChangesEvent): void {
|
||||
if (!e.contains(this.file)) {
|
||||
return;
|
||||
|
||||
@@ -12,9 +12,10 @@ 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, IFileService } from 'vs/platform/files/common/files';
|
||||
import { FileOperationError, FileOperationResult, IFileContent, IFileService } from 'vs/platform/files/common/files';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { AbstractInitializer, AbstractJsonFileSynchroniser, IAcceptResult, IFileResourcePreview, IMergeResult } from 'vs/platform/userDataSync/common/abstractSynchronizer';
|
||||
@@ -62,6 +63,7 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
||||
@IUserDataSyncResourceEnablementService userDataSyncResourceEnablementService: IUserDataSyncResourceEnablementService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
|
||||
@IUserConfigurationFileService private readonly userConfigurationFileService: IUserConfigurationFileService,
|
||||
) {
|
||||
super(environmentService.settingsResource, SyncResource.Settings, fileService, environmentService, storageService, userDataSyncStoreService, userDataSyncBackupStoreService, userDataSyncResourceEnablementService, telemetryService, logService, userDataSyncUtilService, configurationService);
|
||||
}
|
||||
@@ -325,6 +327,10 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
||||
return getIgnoredSettings(defaultIgnoredSettings, this.configurationService, content);
|
||||
}
|
||||
|
||||
protected override async writeFileContent(newContent: string, oldContent: IFileContent, force: boolean): Promise<void> {
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user