Fix #134909

上级 32744a08
......@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册