Merge from vscode 27ada910e121e23a6d95ecca9cae595fb98ab568

This commit is contained in:
ADS Merger
2020-04-30 00:53:43 +00:00
parent 87e5239713
commit 93f35ca321
413 changed files with 7190 additions and 8756 deletions

View File

@@ -98,8 +98,13 @@ export function merge(originalLocalContent: string, originalRemoteContent: strin
return { conflictsSettings: [], localContent: updateIgnoredSettings(originalRemoteContent, originalLocalContent, ignoredSettings, formattingOptions), remoteContent: null, hasConflicts: false };
}
/* remote and local has changed */
/* local is empty and not synced before */
if (baseContent === null && isEmpty(originalLocalContent)) {
const localContent = areSame(originalLocalContent, originalRemoteContent, ignoredSettings) ? null : updateIgnoredSettings(originalRemoteContent, originalLocalContent, ignoredSettings, formattingOptions);
return { conflictsSettings: [], localContent, remoteContent: null, hasConflicts: false };
}
/* remote and local has changed */
let localContent = originalLocalContent;
let remoteContent = originalRemoteContent;
const local = parse(originalLocalContent);
@@ -258,6 +263,11 @@ export function areSame(localContent: string, remoteContent: string, ignoredSett
return true;
}
export function isEmpty(content: string): boolean {
const nodes = parseSettings(content);
return nodes.length === 0;
}
function compare(from: IStringDictionary<any> | null, to: IStringDictionary<any>, ignored: Set<string>): { added: Set<string>, removed: Set<string>, updated: Set<string> } {
const fromKeys = from ? Object.keys(from).filter(key => !ignored.has(key)) : [];
const toKeys = Object.keys(to).filter(key => !ignored.has(key));

View File

@@ -6,15 +6,13 @@
import { IFileService, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files';
import { UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService, CONFIGURATION_SYNC_STORE_KEY, SyncResource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, USER_DATA_SYNC_SCHEME, PREVIEW_DIR_NAME, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync';
import { VSBuffer } from 'vs/base/common/buffer';
import { parse } from 'vs/base/common/json';
import { localize } from 'vs/nls';
import { Event } from 'vs/base/common/event';
import { createCancelablePromise } from 'vs/base/common/async';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { CancellationToken } from 'vs/base/common/cancellation';
import { updateIgnoredSettings, merge, getIgnoredSettings } from 'vs/platform/userDataSync/common/settingsMerge';
import { isEmptyObject } from 'vs/base/common/types';
import { updateIgnoredSettings, merge, getIgnoredSettings, isEmpty } from 'vs/platform/userDataSync/common/settingsMerge';
import { edit } from 'vs/platform/userDataSync/common/content';
import { IFileSyncPreviewResult, AbstractJsonFileSynchroniser, IRemoteUserData } from 'vs/platform/userDataSync/common/abstractSynchronizer';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -160,10 +158,7 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser {
if (localFileContent) {
const formatUtils = await this.getFormattingOptions();
const content = edit(localFileContent.value.toString(), [CONFIGURATION_SYNC_STORE_KEY], undefined, formatUtils);
const settings = parse(content);
if (!isEmptyObject(settings)) {
return true;
}
return !isEmpty(content);
}
} catch (error) {
if ((<FileOperationError>error).fileOperationResult !== FileOperationResult.FILE_NOT_FOUND) {

View File

@@ -417,7 +417,7 @@ export class SnippetsSynchroniser extends AbstractSynchroniser implements IUserD
for (const entry of stat.children || []) {
const resource = entry.resource;
const extension = extname(resource);
if (extension === '.json' || extension === '.code-snippet') {
if (extension === '.json' || extension === '.code-snippets') {
const key = relativePath(this.snippetsFolder, resource)!;
const content = await this.fileService.readFile(resource);
snippets[key] = content;

View File

@@ -42,7 +42,7 @@ export class UserDataAutoSyncService extends Disposable implements IUserDataAuto
}
private async updateEnablement(stopIfDisabled: boolean, auto: boolean): Promise<void> {
const enabled = await this.isAutoSyncEnabled();
const { enabled, reason } = await this.isAutoSyncEnabled();
if (this.enabled === enabled) {
return;
}
@@ -56,7 +56,7 @@ export class UserDataAutoSyncService extends Disposable implements IUserDataAuto
this.resetFailures();
if (stopIfDisabled) {
this.userDataSyncService.stop();
this.logService.info('Auto Sync: stopped.');
this.logService.info('Auto Sync: stopped because', reason);
}
}
@@ -95,10 +95,18 @@ export class UserDataAutoSyncService extends Disposable implements IUserDataAuto
}
}
private async isAutoSyncEnabled(): Promise<boolean> {
return this.userDataSyncEnablementService.isEnabled()
&& this.userDataSyncService.status !== SyncStatus.Uninitialized
&& !!(await this.authTokenService.getToken());
private async isAutoSyncEnabled(): Promise<{ enabled: boolean, reason?: string }> {
if (!this.userDataSyncEnablementService.isEnabled()) {
return { enabled: false, reason: 'sync is disabled' };
}
if (this.userDataSyncService.status === SyncStatus.Uninitialized) {
return { enabled: false, reason: 'sync is not initialized' };
}
const token = await this.authTokenService.getToken();
if (!token) {
return { enabled: false, reason: 'token is not avaialable' };
}
return { enabled: true };
}
private resetFailures(): void {

View File

@@ -26,19 +26,6 @@ import { isArray, isString, isObject } from 'vs/base/common/types';
export const CONFIGURATION_SYNC_STORE_KEY = 'configurationSync.store';
export interface ISyncConfiguration {
sync: {
enable: boolean,
enableSettings: boolean,
enableKeybindings: boolean,
enableUIState: boolean,
enableExtensions: boolean,
keybindingsPerPlatform: boolean,
ignoredExtensions: string[],
ignoredSettings: string[]
}
}
export function getDisallowedIgnoredSettings(): string[] {
const allSettings = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).getConfigurationProperties();
return Object.keys(allSettings).filter(setting => !!allSettings[setting].disallowSyncIgnore);

View File

@@ -723,6 +723,23 @@ suite('SettingsMerge - Merge', () => {
assert.deepEqual(actual.conflictsSettings, expectedConflicts);
assert.ok(actual.hasConflicts);
});
test('merge when remote has comments and local is empty', async () => {
const localContent = `
{
}`;
const remoteContent = stringify`
{
// this is a comment
"a": 1,
}`;
const actual = merge(localContent, remoteContent, null, [], [], formattingOptions);
assert.equal(actual.localContent, remoteContent);
assert.equal(actual.remoteContent, null);
assert.equal(actual.conflictsSettings.length, 0);
assert.ok(!actual.hasConflicts);
});
});
suite('SettingsMerge - Compute Remote Content', () => {

View File

@@ -597,7 +597,7 @@ suite('SnippetsSync', () => {
});
test('sync global and language snippet', async () => {
await updateSnippet('global.code-snippet', globalSnippet, client2);
await updateSnippet('global.code-snippets', globalSnippet, client2);
await updateSnippet('html.json', htmlSnippet1, client2);
await client2.sync();
@@ -607,17 +607,17 @@ suite('SnippetsSync', () => {
const actual1 = await readSnippet('html.json', testClient);
assert.equal(actual1, htmlSnippet1);
const actual2 = await readSnippet('global.code-snippet', testClient);
const actual2 = await readSnippet('global.code-snippets', testClient);
assert.equal(actual2, globalSnippet);
const { content } = await testClient.read(testObject.resource);
assert.ok(content !== null);
const actual = parseSnippets(content!);
assert.deepEqual(actual, { 'html.json': htmlSnippet1, 'global.code-snippet': globalSnippet });
assert.deepEqual(actual, { 'html.json': htmlSnippet1, 'global.code-snippets': globalSnippet });
});
test('sync should ignore non snippets', async () => {
await updateSnippet('global.code-snippet', globalSnippet, client2);
await updateSnippet('global.code-snippets', globalSnippet, client2);
await updateSnippet('html.html', htmlSnippet1, client2);
await updateSnippet('typescript.json', tsSnippet1, client2);
await client2.sync();
@@ -628,7 +628,7 @@ suite('SnippetsSync', () => {
const actual1 = await readSnippet('typescript.json', testClient);
assert.equal(actual1, tsSnippet1);
const actual2 = await readSnippet('global.code-snippet', testClient);
const actual2 = await readSnippet('global.code-snippets', testClient);
assert.equal(actual2, globalSnippet);
const actual3 = await readSnippet('html.html', testClient);
assert.equal(actual3, null);
@@ -636,7 +636,7 @@ suite('SnippetsSync', () => {
const { content } = await testClient.read(testObject.resource);
assert.ok(content !== null);
const actual = parseSnippets(content!);
assert.deepEqual(actual, { 'typescript.json': tsSnippet1, 'global.code-snippet': globalSnippet });
assert.deepEqual(actual, { 'typescript.json': tsSnippet1, 'global.code-snippets': globalSnippet });
});
function parseSnippets(content: string): IStringDictionary<string> {