userDataSync.ts 6.3 KB
Newer Older
1 2 3 4 5 6 7
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { Event } from 'vs/base/common/event';
S
Sandeep Somavarapu 已提交
8
import { IExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement';
9
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
10
import { Registry } from 'vs/platform/registry/common/platform';
11
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope, allSettings } from 'vs/platform/configuration/common/configurationRegistry';
12
import { localize } from 'vs/nls';
13 14 15
import { IDisposable } from 'vs/base/common/lifecycle';
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
16
import { ILogService } from 'vs/platform/log/common/log';
17

18
export const DEFAULT_IGNORED_SETTINGS = [
19
	'configurationSync.enable',
S
Sandeep Somavarapu 已提交
20 21
	'configurationSync.enableSettings',
	'configurationSync.enableExtensions',
22 23
];

24 25 26 27
export function registerConfiguration(): IDisposable {
	const ignoredSettingsSchemaId = 'vscode://schemas/ignoredSettings';
	const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
	configurationRegistry.registerConfiguration({
28
		id: 'configurationSync',
29
		order: 30,
30
		title: localize('configurationSync', "Configuration Sync"),
31 32
		type: 'object',
		properties: {
33
			'configurationSync.enable': {
34
				type: 'boolean',
D
Daniel Imms 已提交
35
				description: localize('configurationSync.enable', "When enabled, synchronizes configuration that includes Settings and Extensions."),
36 37 38
				default: true,
				scope: ConfigurationScope.APPLICATION
			},
S
Sandeep Somavarapu 已提交
39
			'configurationSync.enableSettings': {
40
				type: 'boolean',
D
Daniel Imms 已提交
41
				description: localize('configurationSync.enableSettings', "When enabled settings are synchronized while synchronizing configuration."),
42 43 44
				default: true,
				scope: ConfigurationScope.APPLICATION,
			},
S
Sandeep Somavarapu 已提交
45
			'configurationSync.enableExtensions': {
46
				type: 'boolean',
D
Daniel Imms 已提交
47
				description: localize('configurationSync.enableExtensions', "When enabled extensions are synchronized while synchronizing configuration."),
48 49 50
				default: true,
				scope: ConfigurationScope.APPLICATION,
			},
S
Sandeep Somavarapu 已提交
51
			'configurationSync.extensionsToIgnore': {
52
				'type': 'array',
S
Sandeep Somavarapu 已提交
53
				description: localize('configurationSync.extensionsToIgnore', "Configure extensions to be ignored while syncing."),
54 55 56 57
				'default': [],
				'scope': ConfigurationScope.APPLICATION,
				uniqueItems: true
			},
S
Sandeep Somavarapu 已提交
58
			'configurationSync.settingsToIgnore': {
59
				'type': 'array',
S
Sandeep Somavarapu 已提交
60
				description: localize('configurationSync.settingsToIgnore', "Configure settings to be ignored while syncing. \nDefault Ignored Settings:\n\n{0}", DEFAULT_IGNORED_SETTINGS.sort().map(setting => `- ${setting}`).join('\n')),
61
				'default': [],
62 63 64 65
				'scope': ConfigurationScope.APPLICATION,
				$ref: ignoredSettingsSchemaId,
				additionalProperties: true,
				uniqueItems: true
S
Sandeep Somavarapu 已提交
66 67 68 69 70 71
			},
			'configurationSync.enableAuth': {
				'type': 'boolean',
				description: localize('configurationSync.enableAuth', "Enables authentication and requires VS Code restart when changed"),
				'default': false,
				'scope': ConfigurationScope.APPLICATION
72 73 74 75 76 77 78 79
			}
		}
	});
	const registerIgnoredSettingsSchema = () => {
		const jsonRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
		const ignoredSettingsSchema: IJSONSchema = {
			items: {
				type: 'string',
80
				enum: [...Object.keys(allSettings.properties).filter(setting => DEFAULT_IGNORED_SETTINGS.indexOf(setting) === -1), ...DEFAULT_IGNORED_SETTINGS.map(setting => `-${setting}`)]
81
			}
82 83 84 85
		};
		jsonRegistry.registerSchema(ignoredSettingsSchemaId, ignoredSettingsSchema);
	};
	return configurationRegistry.onDidUpdateConfiguration(() => registerIgnoredSettingsSchema());
86
}
87 88 89

export interface IUserData {
	ref: string;
90
	content: string | null;
91 92 93
}

export enum UserDataSyncStoreErrorCode {
S
Sandeep Somavarapu 已提交
94
	Unauthroized = 'Unauthroized',
95 96 97 98 99 100 101 102 103 104 105 106
	Rejected = 'Rejected',
	Unknown = 'Unknown'
}

export class UserDataSyncStoreError extends Error {

	constructor(message: string, public readonly code: UserDataSyncStoreErrorCode) {
		super(message);
	}

}

107 108 109 110
export const IUserDataSyncStoreService = createDecorator<IUserDataSyncStoreService>('IUserDataSyncStoreService');

export interface IUserDataSyncStoreService {
	_serviceBrand: undefined;
111

112 113
	readonly enabled: boolean;

114
	read(key: string, oldValue: IUserData | null): Promise<IUserData>;
115
	write(key: string, content: string, ref: string | null): Promise<string>;
116 117
}

S
Sandeep Somavarapu 已提交
118 119 120 121 122 123
export interface ISyncExtension {
	identifier: IExtensionIdentifier;
	version?: string;
	enabled: boolean;
}

S
Sandeep Somavarapu 已提交
124
export const enum SyncSource {
125 126 127
	Settings = 1,
	Extensions
}
128

S
Sandeep Somavarapu 已提交
129
export const enum SyncStatus {
130 131 132 133 134 135 136 137 138 139 140 141
	Uninitialized = 'uninitialized',
	Idle = 'idle',
	Syncing = 'syncing',
	HasConflicts = 'hasConflicts',
}

export interface ISynchroniser {

	readonly status: SyncStatus;
	readonly onDidChangeStatus: Event<SyncStatus>;
	readonly onDidChangeLocal: Event<void>;

142
	sync(_continue?: boolean): Promise<boolean>;
S
Sandeep Somavarapu 已提交
143
	stop(): void;
144 145 146 147 148 149
}

export const IUserDataSyncService = createDecorator<IUserDataSyncService>('IUserDataSyncService');

export interface IUserDataSyncService extends ISynchroniser {
	_serviceBrand: any;
150
	readonly conflictsSource: SyncSource | null;
151 152

	removeExtension(identifier: IExtensionIdentifier): Promise<void>;
153
}
154 155 156 157 158 159 160

export const ISettingsMergeService = createDecorator<ISettingsMergeService>('ISettingsMergeService');

export interface ISettingsMergeService {

	_serviceBrand: undefined;

161
	merge(localContent: string, remoteContent: string, baseContent: string | null, ignoredSettings: string[]): Promise<{ mergeContent: string, hasChanges: boolean, hasConflicts: boolean }>;
162

163
	computeRemoteContent(localContent: string, remoteContent: string, ignoredSettings: string[]): Promise<string>;
164 165

}
166

167 168 169 170 171 172
export const IUserDataSyncLogService = createDecorator<IUserDataSyncLogService>('IUserDataSyncLogService');

export interface IUserDataSyncLogService extends ILogService {

}

173
export const CONTEXT_SYNC_STATE = new RawContextKey<string>('syncStatus', SyncStatus.Uninitialized);