This commit is contained in:
Sandeep Somavarapu 2022-05-30 08:31:47 +02:00 committed by GitHub
parent 06fbe24903
commit fb3b47f42e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 9 deletions

View file

@ -14,7 +14,7 @@ import { FormattingOptions } from 'vs/base/common/jsonFormatter';
import { Disposable } from 'vs/base/common/lifecycle';
import { IExtUri } from 'vs/base/common/resources';
import { uppercaseFirstLetter } from 'vs/base/common/strings';
import { isString } from 'vs/base/common/types';
import { isString, isUndefined } from 'vs/base/common/types';
import { URI } from 'vs/base/common/uri';
import { IHeaders } from 'vs/base/parts/request/common/request';
import { localize } from 'vs/nls';
@ -798,10 +798,10 @@ export abstract class AbstractJsonFileSynchroniser extends AbstractFileSynchroni
super(file, resource, fileService, environmentService, storageService, userDataSyncStoreService, userDataSyncBackupStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService, uriIdentityService);
}
protected hasErrors(content: string): boolean {
protected hasErrors(content: string, isArray: boolean): boolean {
const parseErrors: ParseError[] = [];
parse(content, parseErrors, { allowEmptyContent: true, allowTrailingComma: true });
return parseErrors.length > 0;
const result = parse(content, parseErrors, { allowEmptyContent: true, allowTrailingComma: true });
return parseErrors.length > 0 || (!isUndefined(result) && isArray !== Array.isArray(result));
}
private _formattingOptions: Promise<FormattingOptions> | undefined = undefined;

View file

@ -103,7 +103,7 @@ export class KeybindingsSynchroniser extends AbstractJsonFileSynchroniser implem
if (remoteContent) {
let localContent: string = fileContent ? fileContent.value.toString() : '[]';
localContent = localContent || '[]';
if (this.hasErrors(localContent)) {
if (this.hasErrors(localContent, true)) {
throw new UserDataSyncError(localize('errorInvalidSettings', "Unable to sync keybindings because the content in the file is not valid. Please open the file and correct it."), UserDataSyncErrorCode.LocalInvalidContent, this.resource);
}
@ -222,7 +222,7 @@ export class KeybindingsSynchroniser extends AbstractJsonFileSynchroniser implem
if (content !== null) {
content = content.trim();
content = content || '[]';
if (this.hasErrors(content)) {
if (this.hasErrors(content, true)) {
throw new UserDataSyncError(localize('errorInvalidSettings', "Unable to sync keybindings because the content in the file is not valid. Please open the file and correct it."), UserDataSyncErrorCode.LocalInvalidContent, this.resource);
}
}

View file

@ -107,7 +107,8 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
// First time syncing to remote
else if (fileContent) {
this.logService.trace(`${this.syncResourceLogLabel}: Remote settings does not exist. Synchronizing settings for the first time.`);
mergedContent = fileContent.value.toString();
mergedContent = fileContent.value.toString().trim() || '{}';
this.validateContent(mergedContent);
hasRemoteChanged = true;
}
@ -340,7 +341,7 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
}
private validateContent(content: string): void {
if (this.hasErrors(content)) {
if (this.hasErrors(content, false)) {
throw new UserDataSyncError(localize('errorInvalidSettings', "Unable to sync settings as there are errors/warning in settings file."), UserDataSyncErrorCode.LocalInvalidContent, this.resource);
}
}

View file

@ -10,7 +10,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
import { IFileService } from 'vs/platform/files/common/files';
import { ILogService } from 'vs/platform/log/common/log';
import { getKeybindingsContentFromSyncContent, KeybindingsSynchroniser } from 'vs/platform/userDataSync/common/keybindingsSync';
import { IUserDataSyncStoreService, SyncResource } from 'vs/platform/userDataSync/common/userDataSync';
import { IUserDataSyncStoreService, SyncResource, UserDataSyncError, UserDataSyncErrorCode } from 'vs/platform/userDataSync/common/userDataSync';
import { UserDataSyncClient, UserDataSyncTestServer } from 'vs/platform/userDataSync/test/common/userDataSyncClient';
suite('KeybindingsSync', () => {
@ -202,4 +202,15 @@ suite('KeybindingsSync', () => {
assert.deepStrictEqual(server.requests, []);
});
test('sync throws invalid content error - content is an object', async () => {
await client.instantiationService.get(IFileService).writeFile(client.instantiationService.get(IEnvironmentService).keybindingsResource, VSBuffer.fromString('{}'));
try {
await testObject.sync(await client.manifest());
assert.fail('should fail with invalid content error');
} catch (e) {
assert.ok(e instanceof UserDataSyncError);
assert.deepStrictEqual((<UserDataSyncError>e).code, UserDataSyncErrorCode.LocalInvalidContent);
}
});
});

View file

@ -465,6 +465,17 @@ suite('SettingsSync - Auto', () => {
}
});
test('sync throws invalid content error - content is an array', async () => {
await updateSettings('[]', client);
try {
await testObject.sync(await client.manifest());
assert.fail('should fail with invalid content error');
} catch (e) {
assert.ok(e instanceof UserDataSyncError);
assert.deepStrictEqual((<UserDataSyncError>e).code, UserDataSyncErrorCode.LocalInvalidContent);
}
});
test('sync when there are conflicts', async () => {
const client2 = disposableStore.add(new UserDataSyncClient(server));
await client2.setUp(true);