Merge from vscode f2d41726ba5a0e8abfe61b2c743022b1b6372010 (#7415)

* Merge from vscode f2d41726ba5a0e8abfe61b2c743022b1b6372010

* add missing files
This commit is contained in:
Anthony Dresser
2019-09-27 23:30:36 -07:00
committed by GitHub
parent d0fb6de390
commit bca7c8e6bd
123 changed files with 1704 additions and 1330 deletions

View File

@@ -79,6 +79,7 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser
return false;
}
this.logService.trace('Extensions: Started synchronising extensions...');
this.setStatus(SyncStatus.Syncing);
try {
@@ -142,7 +143,9 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser
remoteData = await this.writeToRemote(remote, remoteData.ref);
}
if (remoteData.content) {
if (remoteData.content
&& (!lastSyncData || lastSyncData.ref !== remoteData.ref)
) {
// update last sync
this.logService.info('Extensions: Updating last synchronised extensions...');
await this.updateLastSyncValue(remoteData);

View File

@@ -177,6 +177,8 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser {
// Delete the preview
await this.fileService.del(this.environmentService.settingsSyncPreviewResource);
} else {
this.logService.trace('Settings: No changes found during synchronising settings.');
}
this.logService.trace('Settings: Finised synchronising settings.');

View File

@@ -104,11 +104,6 @@ export interface IUserDataSyncStoreService {
readonly enabled: boolean;
readonly loggedIn: boolean;
readonly onDidChangeLoggedIn: Event<boolean>;
login(): Promise<void>;
logout(): Promise<void>;
read(key: string, oldValue: IUserData | null): Promise<IUserData>;
write(key: string, content: string, ref: string | null): Promise<string>;
}

View File

@@ -12,6 +12,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { timeout } from 'vs/base/common/async';
import { ExtensionsSynchroniser } from 'vs/platform/userDataSync/common/extensionsSync';
import { IExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IAuthTokenService, AuthTokenStatus } from 'vs/platform/auth/common/auth';
export class UserDataSyncService extends Disposable implements IUserDataSyncService {
@@ -35,6 +36,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
constructor(
@IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IAuthTokenService private readonly authTokenService: IAuthTokenService,
) {
super();
this.settingsSynchroniser = this._register(this.instantiationService.createInstance(SettingsSynchroniser));
@@ -43,12 +45,16 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
this.updateStatus();
this._register(Event.any(...this.synchronisers.map(s => Event.map(s.onDidChangeStatus, () => undefined)))(() => this.updateStatus()));
this.onDidChangeLocal = Event.any(...this.synchronisers.map(s => s.onDidChangeLocal));
this._register(authTokenService.onDidChangeStatus(() => this.onDidChangeAuthTokenStatus()));
}
async sync(_continue?: boolean): Promise<boolean> {
if (!this.userDataSyncStoreService.enabled) {
throw new Error('Not enabled');
}
if (this.authTokenService.status === AuthTokenStatus.Inactive) {
return Promise.reject('Not Authenticated. Please sign in to start sync.');
}
for (const synchroniser of this.synchronisers) {
if (!await synchroniser.sync(_continue)) {
return false;
@@ -105,36 +111,51 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
return null;
}
private onDidChangeAuthTokenStatus(): void {
if (this.authTokenService.status === AuthTokenStatus.Inactive) {
this.stop();
}
}
}
export class UserDataAutoSync extends Disposable {
private enabled: boolean = false;
constructor(
@IConfigurationService private readonly configurationService: IConfigurationService,
@IUserDataSyncService private readonly userDataSyncService: IUserDataSyncService,
@IUserDataSyncStoreService userDataSyncStoreService: IUserDataSyncStoreService,
@IUserDataSyncLogService private readonly userDataSyncLogService: IUserDataSyncLogService,
@IAuthTokenService private readonly authTokenService: IAuthTokenService,
) {
super();
if (userDataSyncStoreService.enabled) {
this.sync(true);
this._register(Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('configurationSync.enable'))(() => {
if (this.isSyncEnabled()) {
userDataSyncLogService.info('Syncing configuration started...');
this.sync(true);
} else {
this.userDataSyncService.stop();
userDataSyncLogService.info('Syncing configuration stopped.');
}
}));
this.updateEnablement();
this.sync(true);
this._register(Event.any<any>(authTokenService.onDidChangeStatus, userDataSyncService.onDidChangeStatus)(() => this.updateEnablement()));
this._register(Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('configurationSync.enable'))(() => this.updateEnablement()));
// Sync immediately if there is a local change.
this._register(Event.debounce(this.userDataSyncService.onDidChangeLocal, () => undefined, 500)(() => this.sync(false)));
// Sync immediately if there is a local change.
this._register(Event.debounce(this.userDataSyncService.onDidChangeLocal, () => undefined, 500)(() => this.sync(false)));
}
private updateEnablement(): void {
const enabled = this.isSyncEnabled();
if (this.enabled !== enabled) {
this.enabled = enabled;
if (this.enabled) {
this.userDataSyncLogService.info('Syncing configuration started');
this.sync(true);
} else {
this.userDataSyncService.stop();
this.userDataSyncLogService.info('Syncing configuration stopped.');
}
}
}
private async sync(loop: boolean): Promise<void> {
if (this.isSyncEnabled()) {
if (this.enabled) {
try {
await this.userDataSyncService.sync();
} catch (e) {
@@ -148,7 +169,9 @@ export class UserDataAutoSync extends Disposable {
}
private isSyncEnabled(): boolean {
return this.configurationService.getValue<boolean>('configurationSync.enable');
return this.configurationService.getValue<boolean>('configurationSync.enable')
&& this.userDataSyncService.status !== SyncStatus.Uninitialized
&& this.authTokenService.status !== AuthTokenStatus.Inactive;
}
}

View File

@@ -4,14 +4,14 @@
*--------------------------------------------------------------------------------------------*/
import { Disposable, } from 'vs/base/common/lifecycle';
import { IUserData, IUserDataSyncStoreService, UserDataSyncStoreErrorCode, UserDataSyncStoreError } from 'vs/platform/userDataSync/common/userDataSync';
import { IUserData, IUserDataSyncStoreService, UserDataSyncStoreErrorCode, UserDataSyncStoreError, IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync';
import { IProductService } from 'vs/platform/product/common/productService';
import { Emitter, Event } from 'vs/base/common/event';
import { IRequestService, asText } from 'vs/platform/request/common/request';
import { IRequestService, asText, isSuccess } from 'vs/platform/request/common/request';
import { URI } from 'vs/base/common/uri';
import { joinPath } from 'vs/base/common/resources';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IHeaders } from 'vs/base/parts/request/common/request';
import { IHeaders, IRequestOptions, IRequestContext } from 'vs/base/parts/request/common/request';
import { IAuthTokenService, AuthTokenStatus } from 'vs/platform/auth/common/auth';
export class UserDataSyncStoreService extends Disposable implements IUserDataSyncStoreService {
@@ -19,24 +19,15 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
get enabled(): boolean { return !!this.productService.settingsSyncStoreUrl; }
private _loggedIn: boolean = false;
get loggedIn(): boolean { return this._loggedIn; }
private readonly _onDidChangeLoggedIn: Emitter<boolean> = this._register(new Emitter<boolean>());
readonly onDidChangeLoggedIn: Event<boolean> = this._onDidChangeLoggedIn.event;
constructor(
@IProductService private readonly productService: IProductService,
@IRequestService private readonly requestService: IRequestService,
@IUserDataSyncLogService private readonly logService: IUserDataSyncLogService,
@IAuthTokenService private readonly authTokenService: IAuthTokenService,
) {
super();
}
async login(): Promise<void> {
}
async logout(): Promise<void> {
}
async read(key: string, oldValue: IUserData | null): Promise<IUserData> {
if (!this.enabled) {
return Promise.reject(new Error('No settings sync store url configured.'));
@@ -48,13 +39,17 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
headers['If-None-Match'] = oldValue.ref;
}
const context = await this.requestService.request({ type: 'GET', url, headers }, CancellationToken.None);
const context = await this.request({ type: 'GET', url, headers }, CancellationToken.None);
if (context.res.statusCode === 304) {
// There is no new value. Hence return the old value.
return oldValue!;
}
if (!isSuccess(context)) {
throw new Error('Server returned ' + context.res.statusCode);
}
const ref = context.res.headers['etag'];
if (!ref) {
throw new Error('Server did not return the ref');
@@ -74,13 +69,17 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
headers['If-Match'] = ref;
}
const context = await this.requestService.request({ type: 'POST', url, data, headers }, CancellationToken.None);
const context = await this.request({ type: 'POST', url, data, headers }, CancellationToken.None);
if (context.res.statusCode === 412) {
// There is a new value. Throw Rejected Error
throw new UserDataSyncStoreError('New data exists', UserDataSyncStoreErrorCode.Rejected);
}
if (!isSuccess(context)) {
throw new Error('Server returned ' + context.res.statusCode);
}
const newRef = context.res.headers['etag'];
if (!newRef) {
throw new Error('Server did not return the ref');
@@ -88,4 +87,27 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
return newRef;
}
private async request(options: IRequestOptions, token: CancellationToken): Promise<IRequestContext> {
if (this.authTokenService.status !== AuthTokenStatus.Disabled) {
const authToken = await this.authTokenService.getToken();
if (!authToken) {
return Promise.reject(new Error('No Auth Token Available.'));
}
options.headers = options.headers || {};
options.headers['authorization'] = `Bearer ${authToken}`;
}
const context = await this.requestService.request(options, token);
if (context.res.statusCode === 401) {
// Not Authorized
this.logService.info('Authroization Failed.');
this.authTokenService.refreshToken();
Promise.reject('Authroization Failed.');
}
return context;
}
}