mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-08 09:38:26 -05:00
Merge from vscode 5b9869eb02fa4c96205a74d05cad9164dfd06d60 (#5607)
This commit is contained in:
@@ -100,6 +100,10 @@ export const enum MenuId {
|
||||
NotebookToolbar,
|
||||
DataExplorerContext,
|
||||
DataExplorerAction,
|
||||
CommentThreadTitle,
|
||||
CommentThreadActions,
|
||||
CommentTitle,
|
||||
CommentActions
|
||||
}
|
||||
|
||||
export interface IMenuActionOptions {
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as path from 'vs/base/common/path';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
import { toDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { flatten } from 'vs/base/common/arrays';
|
||||
import { flatten, isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { extract, ExtractError, zip, IFile } from 'vs/base/node/zip';
|
||||
import {
|
||||
IExtensionManagementService, IExtensionGalleryService, ILocalExtension,
|
||||
@@ -44,9 +44,7 @@ import { Schemas } from 'vs/base/common/network';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { getPathFromAmdModule } from 'vs/base/common/amd';
|
||||
import { getManifest } from 'vs/platform/extensionManagement/node/extensionManagementUtil';
|
||||
import { IExtensionManifest, ExtensionType, ExtensionIdentifierWithVersion, isLanguagePackExtension } from 'vs/platform/extensions/common/extensions';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { isUIExtension } from 'vs/platform/extensions/node/extensionsUtil';
|
||||
import { IExtensionManifest, ExtensionType, ExtensionIdentifierWithVersion } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
// {{SQL CARBON EDIT}
|
||||
import product from 'vs/platform/product/node/product';
|
||||
@@ -132,9 +130,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||
onDidUninstallExtension: Event<DidUninstallExtensionEvent> = this._onDidUninstallExtension.event;
|
||||
|
||||
constructor(
|
||||
private readonly remote: boolean,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IExtensionGalleryService private readonly galleryService: IExtensionGalleryService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@optional(IDownloadService) private downloadService: IDownloadService,
|
||||
@@ -270,7 +266,18 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||
|
||||
private installFromZipPath(identifierWithVersion: ExtensionIdentifierWithVersion, zipPath: string, metadata: IGalleryMetadata | null, type: ExtensionType, operation: InstallOperation, token: CancellationToken): Promise<ILocalExtension> {
|
||||
return this.toNonCancellablePromise(this.installExtension({ zipPath, identifierWithVersion, metadata }, type, token)
|
||||
.then(local => this.installDependenciesAndPackExtensions(local, null).then(() => local, error => this.uninstall(local, true).then(() => Promise.reject(error), () => Promise.reject(error))))
|
||||
.then(local => this.installDependenciesAndPackExtensions(local, null)
|
||||
.then(
|
||||
() => local,
|
||||
error => {
|
||||
if (isNonEmptyArray(local.manifest.extensionDependencies)) {
|
||||
this.logService.warn(`Cannot install dependencies of extension:`, local.identifier.id, error.message);
|
||||
}
|
||||
if (isNonEmptyArray(local.manifest.extensionPack)) {
|
||||
this.logService.warn(`Cannot install packed extensions of extension:`, local.identifier.id, error.message);
|
||||
}
|
||||
return local;
|
||||
}))
|
||||
.then(
|
||||
local => { this._onDidInstallExtension.fire({ identifier: identifierWithVersion.identifier, zipPath, local, operation }); return local; },
|
||||
error => { this._onDidInstallExtension.fire({ identifier: identifierWithVersion.identifier, zipPath, operation, error }); return Promise.reject(error); }
|
||||
@@ -526,16 +533,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||
return this.galleryService.query({ names, pageSize: dependenciesAndPackExtensions.length }, CancellationToken.None)
|
||||
.then(galleryResult => {
|
||||
const extensionsToInstall = galleryResult.firstPage;
|
||||
return Promise.all(extensionsToInstall.map(async e => {
|
||||
if (this.remote) {
|
||||
const manifest = await this.galleryService.getManifest(e, CancellationToken.None);
|
||||
if (manifest && isUIExtension(manifest, [], this.configurationService) && !isLanguagePackExtension(manifest)) {
|
||||
this.logService.info('Ignored installing the UI dependency', e.identifier.id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return this.installFromGallery(e);
|
||||
}))
|
||||
return Promise.all(extensionsToInstall.map(e => this.installFromGallery(e)))
|
||||
.then(() => null, errors => this.rollback(extensionsToInstall).then(() => Promise.reject(errors), () => Promise.reject(errors)));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IExtensionManifest } from 'vs/platform/extensions/common/extensions';
|
||||
import { getGalleryExtensionId, areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import product from 'vs/platform/product/node/product';
|
||||
|
||||
export function isUIExtension(manifest: IExtensionManifest, uiContributions: string[], configurationService: IConfigurationService): boolean {
|
||||
const extensionId = getGalleryExtensionId(manifest.publisher, manifest.name);
|
||||
const extensionKind = getExtensionKind(manifest, configurationService);
|
||||
switch (extensionKind) {
|
||||
case 'ui': return true;
|
||||
case 'workspace': return false;
|
||||
default: {
|
||||
// Tagged as UI extension in product
|
||||
if (isNonEmptyArray(product.uiExtensions) && product.uiExtensions.some(id => areSameExtensions({ id }, { id: extensionId }))) {
|
||||
return true;
|
||||
}
|
||||
// Not an UI extension if it has main
|
||||
if (manifest.main) {
|
||||
return false;
|
||||
}
|
||||
// Not an UI extension if it has dependencies or an extension pack
|
||||
if (isNonEmptyArray(manifest.extensionDependencies) || isNonEmptyArray(manifest.extensionPack)) {
|
||||
return false;
|
||||
}
|
||||
if (manifest.contributes) {
|
||||
// Not an UI extension if it has no ui contributions
|
||||
if (!uiContributions.length || Object.keys(manifest.contributes).some(contribution => uiContributions.indexOf(contribution) === -1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getExtensionKind(manifest: IExtensionManifest, configurationService: IConfigurationService): string | undefined {
|
||||
const extensionId = getGalleryExtensionId(manifest.publisher, manifest.name);
|
||||
const configuredExtensionKinds = configurationService.getValue<{ [key: string]: string }>('remote.extensionKind') || {};
|
||||
for (const id of Object.keys(configuredExtensionKinds)) {
|
||||
if (areSameExtensions({ id: extensionId }, { id })) {
|
||||
return configuredExtensionKinds[id];
|
||||
}
|
||||
}
|
||||
return manifest.extensionKind;
|
||||
}
|
||||
@@ -75,6 +75,23 @@ export class IssueService implements IIssueService {
|
||||
event.sender.send('vscode:listProcessesResponse', processes);
|
||||
});
|
||||
|
||||
ipcMain.on('vscode:issueReporterClipboard', (event: Event) => {
|
||||
const messageOptions = {
|
||||
message: localize('issueReporterWriteToClipboard', "There is too much data to send to GitHub. Would you like to write the information to the clipboard so that it can be pasted?"),
|
||||
type: 'warning',
|
||||
buttons: [
|
||||
localize('yes', "Yes"),
|
||||
localize('cancel', "Cancel")
|
||||
]
|
||||
};
|
||||
|
||||
if (this._issueWindow) {
|
||||
dialog.showMessageBox(this._issueWindow, messageOptions, response => {
|
||||
event.sender.send('vscode:issueReporterClipboardResponse', response === 0);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.on('vscode:issuePerformanceInfoRequest', (event: Event) => {
|
||||
this.getPerformanceInfo().then(msg => {
|
||||
event.sender.send('vscode:issuePerformanceInfoResponse', msg);
|
||||
|
||||
@@ -58,9 +58,9 @@ export abstract class AbstractLifecycleService extends Disposable implements ILi
|
||||
}
|
||||
}
|
||||
|
||||
when(phase: LifecyclePhase): Promise<void> {
|
||||
async when(phase: LifecyclePhase): Promise<void> {
|
||||
if (phase <= this._phase) {
|
||||
return Promise.resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
let barrier = this.phaseWhen.get(phase);
|
||||
@@ -69,6 +69,6 @@ export abstract class AbstractLifecycleService extends Disposable implements ILi
|
||||
this.phaseWhen.set(phase, barrier);
|
||||
}
|
||||
|
||||
return barrier.wait().then(undefined);
|
||||
await barrier.wait();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,18 +75,17 @@ export class LifecycleService extends AbstractLifecycleService {
|
||||
});
|
||||
|
||||
// Main side indicates that we will indeed shutdown
|
||||
ipc.on('vscode:onWillUnload', (_event: unknown, reply: { replyChannel: string, reason: ShutdownReason }) => {
|
||||
ipc.on('vscode:onWillUnload', async (_event: unknown, reply: { replyChannel: string, reason: ShutdownReason }) => {
|
||||
this.logService.trace(`lifecycle: onWillUnload (reason: ${reply.reason})`);
|
||||
|
||||
// trigger onWillShutdown events and joining
|
||||
return this.handleWillShutdown(reply.reason).then(() => {
|
||||
await this.handleWillShutdown(reply.reason);
|
||||
|
||||
// trigger onShutdown event now that we know we will quit
|
||||
this._onShutdown.fire();
|
||||
// trigger onShutdown event now that we know we will quit
|
||||
this._onShutdown.fire();
|
||||
|
||||
// acknowledge to main side
|
||||
ipc.send(reply.replyChannel, windowId);
|
||||
});
|
||||
// acknowledge to main side
|
||||
ipc.send(reply.replyChannel, windowId);
|
||||
});
|
||||
|
||||
// Save shutdown reason to retrieve on next startup
|
||||
@@ -111,7 +110,7 @@ export class LifecycleService extends AbstractLifecycleService {
|
||||
});
|
||||
}
|
||||
|
||||
private handleWillShutdown(reason: ShutdownReason): Promise<void> {
|
||||
private async handleWillShutdown(reason: ShutdownReason): Promise<void> {
|
||||
const joiners: Promise<void>[] = [];
|
||||
|
||||
this._onWillShutdown.fire({
|
||||
@@ -123,9 +122,11 @@ export class LifecycleService extends AbstractLifecycleService {
|
||||
reason
|
||||
});
|
||||
|
||||
return Promise.all(joiners).then(() => undefined, err => {
|
||||
this.notificationService.error(toErrorMessage(err));
|
||||
onUnexpectedError(err);
|
||||
});
|
||||
try {
|
||||
await Promise.all(joiners);
|
||||
} catch (error) {
|
||||
this.notificationService.error(toErrorMessage(error));
|
||||
onUnexpectedError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,7 +291,7 @@ export class LifecycleService extends Disposable implements ILifecycleService {
|
||||
});
|
||||
}
|
||||
|
||||
unload(window: ICodeWindow, reason: UnloadReason): Promise<boolean /* veto */> {
|
||||
async unload(window: ICodeWindow, reason: UnloadReason): Promise<boolean /* veto */> {
|
||||
|
||||
// Always allow to unload a window that is not yet ready
|
||||
if (!window.isReady) {
|
||||
@@ -302,27 +302,27 @@ export class LifecycleService extends Disposable implements ILifecycleService {
|
||||
|
||||
// first ask the window itself if it vetos the unload
|
||||
const windowUnloadReason = this._quitRequested ? UnloadReason.QUIT : reason;
|
||||
return this.onBeforeUnloadWindowInRenderer(window, windowUnloadReason).then(veto => {
|
||||
if (veto) {
|
||||
this.logService.trace(`Lifecycle#unload() - veto in renderer (window ID ${window.id})`);
|
||||
let veto = await this.onBeforeUnloadWindowInRenderer(window, windowUnloadReason);
|
||||
if (veto) {
|
||||
this.logService.trace(`Lifecycle#unload() - veto in renderer (window ID ${window.id})`);
|
||||
|
||||
return this.handleWindowUnloadVeto(veto);
|
||||
}
|
||||
return this.handleWindowUnloadVeto(veto);
|
||||
}
|
||||
|
||||
// then check for vetos in the main side
|
||||
return this.onBeforeUnloadWindowInMain(window, windowUnloadReason).then(veto => {
|
||||
if (veto) {
|
||||
this.logService.trace(`Lifecycle#unload() - veto in main (window ID ${window.id})`);
|
||||
// then check for vetos in the main side
|
||||
veto = await this.onBeforeUnloadWindowInMain(window, windowUnloadReason);
|
||||
if (veto) {
|
||||
this.logService.trace(`Lifecycle#unload() - veto in main (window ID ${window.id})`);
|
||||
|
||||
return this.handleWindowUnloadVeto(veto);
|
||||
}
|
||||
return this.handleWindowUnloadVeto(veto);
|
||||
}
|
||||
|
||||
this.logService.trace(`Lifecycle#unload() - no veto (window ID ${window.id})`);
|
||||
this.logService.trace(`Lifecycle#unload() - no veto (window ID ${window.id})`);
|
||||
|
||||
// finally if there are no vetos, unload the renderer
|
||||
return this.onWillUnloadWindowInRenderer(window, windowUnloadReason).then(() => false);
|
||||
});
|
||||
});
|
||||
// finally if there are no vetos, unload the renderer
|
||||
await this.onWillUnloadWindowInRenderer(window, windowUnloadReason);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private handleWindowUnloadVeto(veto: boolean): boolean {
|
||||
|
||||
@@ -26,21 +26,23 @@ export class FileStorage {
|
||||
return this._database;
|
||||
}
|
||||
|
||||
init(): Promise<void> {
|
||||
return readFile(this.dbPath).then(contents => {
|
||||
async init(): Promise<void> {
|
||||
try {
|
||||
const contents = await readFile(this.dbPath);
|
||||
|
||||
try {
|
||||
this.lastFlushedSerializedDatabase = contents.toString();
|
||||
this._database = JSON.parse(this.lastFlushedSerializedDatabase);
|
||||
} catch (error) {
|
||||
this._database = {};
|
||||
}
|
||||
}, error => {
|
||||
} catch (error) {
|
||||
if (error.code !== 'ENOENT') {
|
||||
this.onError(error);
|
||||
}
|
||||
|
||||
this._database = {};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private loadSync(): object {
|
||||
|
||||
@@ -14,38 +14,37 @@ suite('StateService', () => {
|
||||
const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'stateservice');
|
||||
const storageFile = path.join(parentDir, 'storage.json');
|
||||
|
||||
teardown(done => {
|
||||
rimraf(parentDir, RimRafMode.MOVE).then(done, done);
|
||||
teardown(async () => {
|
||||
await rimraf(parentDir, RimRafMode.MOVE);
|
||||
});
|
||||
|
||||
test('Basics', () => {
|
||||
return mkdirp(parentDir).then(() => {
|
||||
writeFileSync(storageFile, '');
|
||||
test('Basics', async () => {
|
||||
await mkdirp(parentDir);
|
||||
writeFileSync(storageFile, '');
|
||||
|
||||
let service = new FileStorage(storageFile, () => null);
|
||||
let service = new FileStorage(storageFile, () => null);
|
||||
|
||||
service.setItem('some.key', 'some.value');
|
||||
assert.equal(service.getItem('some.key'), 'some.value');
|
||||
service.setItem('some.key', 'some.value');
|
||||
assert.equal(service.getItem('some.key'), 'some.value');
|
||||
|
||||
service.removeItem('some.key');
|
||||
assert.equal(service.getItem('some.key', 'some.default'), 'some.default');
|
||||
service.removeItem('some.key');
|
||||
assert.equal(service.getItem('some.key', 'some.default'), 'some.default');
|
||||
|
||||
assert.ok(!service.getItem('some.unknonw.key'));
|
||||
assert.ok(!service.getItem('some.unknonw.key'));
|
||||
|
||||
service.setItem('some.other.key', 'some.other.value');
|
||||
service.setItem('some.other.key', 'some.other.value');
|
||||
|
||||
service = new FileStorage(storageFile, () => null);
|
||||
service = new FileStorage(storageFile, () => null);
|
||||
|
||||
assert.equal(service.getItem('some.other.key'), 'some.other.value');
|
||||
assert.equal(service.getItem('some.other.key'), 'some.other.value');
|
||||
|
||||
service.setItem('some.other.key', 'some.other.value');
|
||||
assert.equal(service.getItem('some.other.key'), 'some.other.value');
|
||||
service.setItem('some.other.key', 'some.other.value');
|
||||
assert.equal(service.getItem('some.other.key'), 'some.other.value');
|
||||
|
||||
service.setItem('some.undefined.key', undefined);
|
||||
assert.equal(service.getItem('some.undefined.key', 'some.default'), 'some.default');
|
||||
service.setItem('some.undefined.key', undefined);
|
||||
assert.equal(service.getItem('some.undefined.key', 'some.default'), 'some.default');
|
||||
|
||||
service.setItem('some.null.key', null);
|
||||
assert.equal(service.getItem('some.null.key', 'some.default'), 'some.default');
|
||||
});
|
||||
service.setItem('some.null.key', null);
|
||||
assert.equal(service.getItem('some.null.key', 'some.default'), 'some.default');
|
||||
});
|
||||
});
|
||||
@@ -45,20 +45,21 @@ export class GlobalStorageDatabaseChannel extends Disposable implements IServerC
|
||||
this.whenReady = this.init();
|
||||
}
|
||||
|
||||
private init(): Promise<void> {
|
||||
return this.storageMainService.initialize().then(undefined, error => {
|
||||
private async init(): Promise<void> {
|
||||
try {
|
||||
await this.storageMainService.initialize();
|
||||
} catch (error) {
|
||||
onUnexpectedError(error);
|
||||
this.logService.error(error);
|
||||
}).then(() => {
|
||||
}
|
||||
|
||||
// Apply global telemetry values as part of the initialization
|
||||
// These are global across all windows and thereby should be
|
||||
// written from the main process once.
|
||||
this.initTelemetry();
|
||||
// Apply global telemetry values as part of the initialization
|
||||
// These are global across all windows and thereby should be
|
||||
// written from the main process once.
|
||||
this.initTelemetry();
|
||||
|
||||
// Setup storage change listeners
|
||||
this.registerListeners();
|
||||
});
|
||||
// Setup storage change listeners
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private initTelemetry(): void {
|
||||
@@ -112,33 +113,39 @@ export class GlobalStorageDatabaseChannel extends Disposable implements IServerC
|
||||
throw new Error(`Event not found: ${event}`);
|
||||
}
|
||||
|
||||
call(_: unknown, command: string, arg?: any): Promise<any> {
|
||||
async call(_: unknown, command: string, arg?: any): Promise<any> {
|
||||
|
||||
// ensure to always wait for ready
|
||||
await this.whenReady;
|
||||
|
||||
// handle call
|
||||
switch (command) {
|
||||
case 'getItems': {
|
||||
return this.whenReady.then(() => mapToSerializable(this.storageMainService.items));
|
||||
return mapToSerializable(this.storageMainService.items);
|
||||
}
|
||||
|
||||
case 'updateItems': {
|
||||
return this.whenReady.then(() => {
|
||||
const items: ISerializableUpdateRequest = arg;
|
||||
if (items.insert) {
|
||||
for (const [key, value] of items.insert) {
|
||||
this.storageMainService.store(key, value);
|
||||
}
|
||||
const items: ISerializableUpdateRequest = arg;
|
||||
if (items.insert) {
|
||||
for (const [key, value] of items.insert) {
|
||||
this.storageMainService.store(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (items.delete) {
|
||||
items.delete.forEach(key => this.storageMainService.remove(key));
|
||||
}
|
||||
});
|
||||
if (items.delete) {
|
||||
items.delete.forEach(key => this.storageMainService.remove(key));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'checkIntegrity': {
|
||||
return this.whenReady.then(() => this.storageMainService.checkIntegrity(arg));
|
||||
return this.storageMainService.checkIntegrity(arg);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`Call not found: ${command}`);
|
||||
default:
|
||||
throw new Error(`Call not found: ${command}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,8 +174,10 @@ export class GlobalStorageDatabaseChannelClient extends Disposable implements IS
|
||||
}
|
||||
}
|
||||
|
||||
getItems(): Promise<Map<string, string>> {
|
||||
return this.channel.call('getItems').then((data: Item[]) => serializableToMap(data));
|
||||
async getItems(): Promise<Map<string, string>> {
|
||||
const items: Item[] = await this.channel.call('getItems');
|
||||
|
||||
return serializableToMap(items);
|
||||
}
|
||||
|
||||
updateItems(request: IUpdateRequest): Promise<void> {
|
||||
|
||||
@@ -10,7 +10,6 @@ import { ILogService, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IStorage, Storage, SQLiteStorageDatabase, ISQLiteStorageDatabaseLoggingOptions, InMemoryStorageDatabase } from 'vs/base/node/storage';
|
||||
import { join } from 'vs/base/common/path';
|
||||
import { exists } from 'vs/base/node/pfs';
|
||||
|
||||
export const IStorageMainService = createDecorator<IStorageMainService>('storageMainService');
|
||||
|
||||
@@ -121,25 +120,14 @@ export class StorageMainService extends Disposable implements IStorageMainServic
|
||||
}
|
||||
|
||||
private doInitialize(): Promise<void> {
|
||||
const useInMemoryStorage = this.storagePath === SQLiteStorageDatabase.IN_MEMORY_PATH;
|
||||
this.storage.dispose();
|
||||
this.storage = new Storage(new SQLiteStorageDatabase(this.storagePath, {
|
||||
logging: this.createLogginOptions()
|
||||
}));
|
||||
|
||||
let globalStorageExists: Promise<boolean>;
|
||||
if (useInMemoryStorage) {
|
||||
globalStorageExists = Promise.resolve(true);
|
||||
} else {
|
||||
globalStorageExists = exists(this.storagePath);
|
||||
}
|
||||
this._register(this.storage.onDidChangeStorage(key => this._onDidChangeStorage.fire({ key })));
|
||||
|
||||
return globalStorageExists.then(exists => {
|
||||
this.storage.dispose();
|
||||
this.storage = new Storage(new SQLiteStorageDatabase(this.storagePath, {
|
||||
logging: this.createLogginOptions()
|
||||
}));
|
||||
|
||||
this._register(this.storage.onDidChangeStorage(key => this._onDidChangeStorage.fire({ key })));
|
||||
|
||||
return this.storage.init();
|
||||
});
|
||||
return this.storage.init();
|
||||
}
|
||||
|
||||
get(key: string, fallbackValue: string): string;
|
||||
|
||||
@@ -62,38 +62,38 @@ export class StorageService extends Disposable implements IStorageService {
|
||||
return this.initializePromise;
|
||||
}
|
||||
|
||||
private doInitialize(payload: IWorkspaceInitializationPayload): Promise<void> {
|
||||
return Promise.all([
|
||||
private async doInitialize(payload: IWorkspaceInitializationPayload): Promise<void> {
|
||||
await Promise.all([
|
||||
this.initializeGlobalStorage(),
|
||||
this.initializeWorkspaceStorage(payload)
|
||||
]).then(() => undefined);
|
||||
]);
|
||||
}
|
||||
|
||||
private initializeGlobalStorage(): Promise<void> {
|
||||
return this.globalStorage.init();
|
||||
}
|
||||
|
||||
private initializeWorkspaceStorage(payload: IWorkspaceInitializationPayload): Promise<void> {
|
||||
private async initializeWorkspaceStorage(payload: IWorkspaceInitializationPayload): Promise<void> {
|
||||
|
||||
// Prepare workspace storage folder for DB
|
||||
return this.prepareWorkspaceStorageFolder(payload).then(result => {
|
||||
try {
|
||||
const result = await this.prepareWorkspaceStorageFolder(payload);
|
||||
|
||||
const useInMemoryStorage = !!this.environmentService.extensionTestsLocationURI; // no storage during extension tests!
|
||||
|
||||
// Create workspace storage and initalize
|
||||
mark('willInitWorkspaceStorage');
|
||||
return this.createWorkspaceStorage(useInMemoryStorage ? SQLiteStorageDatabase.IN_MEMORY_PATH : join(result.path, StorageService.WORKSPACE_STORAGE_NAME), result.wasCreated ? StorageHint.STORAGE_DOES_NOT_EXIST : undefined).init().then(() => {
|
||||
try {
|
||||
await this.createWorkspaceStorage(useInMemoryStorage ? SQLiteStorageDatabase.IN_MEMORY_PATH : join(result.path, StorageService.WORKSPACE_STORAGE_NAME), result.wasCreated ? StorageHint.STORAGE_DOES_NOT_EXIST : undefined).init();
|
||||
} finally {
|
||||
mark('didInitWorkspaceStorage');
|
||||
}, error => {
|
||||
mark('didInitWorkspaceStorage');
|
||||
|
||||
return Promise.reject(error);
|
||||
});
|
||||
}).then(undefined, error => {
|
||||
}
|
||||
} catch (error) {
|
||||
onUnexpectedError(error);
|
||||
|
||||
// Upon error, fallback to in-memory storage
|
||||
return this.createWorkspaceStorage(SQLiteStorageDatabase.IN_MEMORY_PATH).init();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private createWorkspaceStorage(workspaceStoragePath: string, hint?: StorageHint): IStorage {
|
||||
@@ -120,22 +120,20 @@ export class StorageService extends Disposable implements IStorageService {
|
||||
return join(this.environmentService.workspaceStorageHome, payload.id); // workspace home + workspace id;
|
||||
}
|
||||
|
||||
private prepareWorkspaceStorageFolder(payload: IWorkspaceInitializationPayload): Promise<{ path: string, wasCreated: boolean }> {
|
||||
private async prepareWorkspaceStorageFolder(payload: IWorkspaceInitializationPayload): Promise<{ path: string, wasCreated: boolean }> {
|
||||
const workspaceStorageFolderPath = this.getWorkspaceStorageFolderPath(payload);
|
||||
|
||||
return exists(workspaceStorageFolderPath).then<{ path: string, wasCreated: boolean }>(exists => {
|
||||
if (exists) {
|
||||
return { path: workspaceStorageFolderPath, wasCreated: false };
|
||||
}
|
||||
const storageExists = await exists(workspaceStorageFolderPath);
|
||||
if (storageExists) {
|
||||
return { path: workspaceStorageFolderPath, wasCreated: false };
|
||||
}
|
||||
|
||||
return mkdirp(workspaceStorageFolderPath).then(() => {
|
||||
await mkdirp(workspaceStorageFolderPath);
|
||||
|
||||
// Write metadata into folder
|
||||
this.ensureWorkspaceStorageFolderMeta(payload);
|
||||
// Write metadata into folder
|
||||
this.ensureWorkspaceStorageFolderMeta(payload);
|
||||
|
||||
return { path: workspaceStorageFolderPath, wasCreated: true };
|
||||
});
|
||||
});
|
||||
return { path: workspaceStorageFolderPath, wasCreated: true };
|
||||
}
|
||||
|
||||
private ensureWorkspaceStorageFolderMeta(payload: IWorkspaceInitializationPayload): void {
|
||||
@@ -148,13 +146,16 @@ export class StorageService extends Disposable implements IStorageService {
|
||||
|
||||
if (meta) {
|
||||
const workspaceStorageMetaPath = join(this.getWorkspaceStorageFolderPath(payload), StorageService.WORKSPACE_META_NAME);
|
||||
exists(workspaceStorageMetaPath).then(exists => {
|
||||
if (exists) {
|
||||
return undefined; // already existing
|
||||
(async function () {
|
||||
try {
|
||||
const storageExists = await exists(workspaceStorageMetaPath);
|
||||
if (!storageExists) {
|
||||
await writeFile(workspaceStorageMetaPath, JSON.stringify(meta, undefined, 2));
|
||||
}
|
||||
} catch (error) {
|
||||
onUnexpectedError(error);
|
||||
}
|
||||
|
||||
return writeFile(workspaceStorageMetaPath, JSON.stringify(meta, undefined, 2));
|
||||
}).then(undefined, error => onUnexpectedError(error));
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,16 +185,16 @@ export class StorageService extends Disposable implements IStorageService {
|
||||
this.getStorage(scope).delete(key);
|
||||
}
|
||||
|
||||
close(): Promise<void> {
|
||||
async close(): Promise<void> {
|
||||
|
||||
// Signal as event so that clients can still store data
|
||||
this._onWillSaveState.fire({ reason: WillSaveStateReason.SHUTDOWN });
|
||||
|
||||
// Do it
|
||||
return Promise.all([
|
||||
await Promise.all([
|
||||
this.globalStorage.close(),
|
||||
this.workspaceStorage.close()
|
||||
]).then(() => undefined);
|
||||
]);
|
||||
}
|
||||
|
||||
private getStorage(scope: StorageScope): IStorage {
|
||||
@@ -208,77 +209,75 @@ export class StorageService extends Disposable implements IStorageService {
|
||||
return scope === StorageScope.GLOBAL ? this.globalStorage.checkIntegrity(full) : this.workspaceStorage.checkIntegrity(full);
|
||||
}
|
||||
|
||||
logStorage(): Promise<void> {
|
||||
return Promise.all([
|
||||
async logStorage(): Promise<void> {
|
||||
const result = await Promise.all([
|
||||
this.globalStorage.items,
|
||||
this.workspaceStorage.items,
|
||||
this.globalStorage.checkIntegrity(true /* full */),
|
||||
this.workspaceStorage.checkIntegrity(true /* full */)
|
||||
]).then(result => {
|
||||
const safeParse = (value: string) => {
|
||||
try {
|
||||
return JSON.parse(value);
|
||||
} catch (error) {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
]);
|
||||
|
||||
const globalItems = new Map<string, string>();
|
||||
const globalItemsParsed = new Map<string, string>();
|
||||
result[0].forEach((value, key) => {
|
||||
globalItems.set(key, value);
|
||||
globalItemsParsed.set(key, safeParse(value));
|
||||
});
|
||||
const safeParse = (value: string) => {
|
||||
try {
|
||||
return JSON.parse(value);
|
||||
} catch (error) {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
const workspaceItems = new Map<string, string>();
|
||||
const workspaceItemsParsed = new Map<string, string>();
|
||||
result[1].forEach((value, key) => {
|
||||
workspaceItems.set(key, value);
|
||||
workspaceItemsParsed.set(key, safeParse(value));
|
||||
});
|
||||
|
||||
console.group(`Storage: Global (integrity: ${result[2]}, path: ${this.environmentService.globalStorageHome})`);
|
||||
let globalValues: { key: string, value: string }[] = [];
|
||||
globalItems.forEach((value, key) => {
|
||||
globalValues.push({ key, value });
|
||||
});
|
||||
console.table(globalValues);
|
||||
console.groupEnd();
|
||||
|
||||
console.log(globalItemsParsed);
|
||||
|
||||
console.group(`Storage: Workspace (integrity: ${result[3]}, load: ${getDuration('willInitWorkspaceStorage', 'didInitWorkspaceStorage')}, path: ${this.workspaceStoragePath})`);
|
||||
let workspaceValues: { key: string, value: string }[] = [];
|
||||
workspaceItems.forEach((value, key) => {
|
||||
workspaceValues.push({ key, value });
|
||||
});
|
||||
console.table(workspaceValues);
|
||||
console.groupEnd();
|
||||
|
||||
console.log(workspaceItemsParsed);
|
||||
const globalItems = new Map<string, string>();
|
||||
const globalItemsParsed = new Map<string, string>();
|
||||
result[0].forEach((value, key) => {
|
||||
globalItems.set(key, value);
|
||||
globalItemsParsed.set(key, safeParse(value));
|
||||
});
|
||||
|
||||
const workspaceItems = new Map<string, string>();
|
||||
const workspaceItemsParsed = new Map<string, string>();
|
||||
result[1].forEach((value, key) => {
|
||||
workspaceItems.set(key, value);
|
||||
workspaceItemsParsed.set(key, safeParse(value));
|
||||
});
|
||||
|
||||
console.group(`Storage: Global (integrity: ${result[2]}, path: ${this.environmentService.globalStorageHome})`);
|
||||
let globalValues: { key: string, value: string }[] = [];
|
||||
globalItems.forEach((value, key) => {
|
||||
globalValues.push({ key, value });
|
||||
});
|
||||
console.table(globalValues);
|
||||
console.groupEnd();
|
||||
|
||||
console.log(globalItemsParsed);
|
||||
|
||||
console.group(`Storage: Workspace (integrity: ${result[3]}, load: ${getDuration('willInitWorkspaceStorage', 'didInitWorkspaceStorage')}, path: ${this.workspaceStoragePath})`);
|
||||
let workspaceValues: { key: string, value: string }[] = [];
|
||||
workspaceItems.forEach((value, key) => {
|
||||
workspaceValues.push({ key, value });
|
||||
});
|
||||
console.table(workspaceValues);
|
||||
console.groupEnd();
|
||||
|
||||
console.log(workspaceItemsParsed);
|
||||
}
|
||||
|
||||
migrate(toWorkspace: IWorkspaceInitializationPayload): Promise<void> {
|
||||
async migrate(toWorkspace: IWorkspaceInitializationPayload): Promise<void> {
|
||||
if (this.workspaceStoragePath === SQLiteStorageDatabase.IN_MEMORY_PATH) {
|
||||
return Promise.resolve(); // no migration needed if running in memory
|
||||
}
|
||||
|
||||
// Close workspace DB to be able to copy
|
||||
return this.workspaceStorage.close().then(() => {
|
||||
await this.workspaceStorage.close();
|
||||
|
||||
// Prepare new workspace storage folder
|
||||
return this.prepareWorkspaceStorageFolder(toWorkspace).then(result => {
|
||||
const newWorkspaceStoragePath = join(result.path, StorageService.WORKSPACE_STORAGE_NAME);
|
||||
// Prepare new workspace storage folder
|
||||
const result = await this.prepareWorkspaceStorageFolder(toWorkspace);
|
||||
|
||||
// Copy current storage over to new workspace storage
|
||||
return copy(this.workspaceStoragePath, newWorkspaceStoragePath).then(() => {
|
||||
const newWorkspaceStoragePath = join(result.path, StorageService.WORKSPACE_STORAGE_NAME);
|
||||
|
||||
// Recreate and init workspace storage
|
||||
return this.createWorkspaceStorage(newWorkspaceStoragePath).init();
|
||||
});
|
||||
});
|
||||
});
|
||||
// Copy current storage over to new workspace storage
|
||||
await copy(this.workspaceStoragePath, newWorkspaceStoragePath);
|
||||
|
||||
// Recreate and init workspace storage
|
||||
return this.createWorkspaceStorage(newWorkspaceStoragePath).init();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,15 +89,15 @@ export class TelemetryService implements ITelemetryService {
|
||||
return this._userOptIn && this._enabled;
|
||||
}
|
||||
|
||||
getTelemetryInfo(): Promise<ITelemetryInfo> {
|
||||
return this._commonProperties.then(values => {
|
||||
// well known properties
|
||||
let sessionId = values['sessionID'];
|
||||
let instanceId = values['common.instanceId'];
|
||||
let machineId = values['common.machineId'];
|
||||
async getTelemetryInfo(): Promise<ITelemetryInfo> {
|
||||
const values = await this._commonProperties;
|
||||
|
||||
return { sessionId, instanceId, machineId };
|
||||
});
|
||||
// well known properties
|
||||
let sessionId = values['sessionID'];
|
||||
let instanceId = values['common.instanceId'];
|
||||
let machineId = values['common.machineId'];
|
||||
|
||||
return { sessionId, instanceId, machineId };
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
|
||||
@@ -10,8 +10,9 @@ import { readFile } from 'vs/base/node/pfs';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
import product from 'vs/platform/product/node/product';
|
||||
const productObject = product;
|
||||
|
||||
export function resolveCommonProperties(commit: string | undefined, version: string | undefined, machineId: string | undefined, installSourcePath: string): Promise<{ [name: string]: string | undefined; }> {
|
||||
export async function resolveCommonProperties(commit: string | undefined, version: string | undefined, machineId: string | undefined, installSourcePath: string, product?: string): Promise<{ [name: string]: string | undefined; }> {
|
||||
const result: { [name: string]: string | undefined; } = Object.create(null);
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
@@ -36,8 +37,8 @@ export function resolveCommonProperties(commit: string | undefined, version: str
|
||||
result['common.nodeArch'] = process.arch;
|
||||
// __GDPR__COMMON__ "common.product" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
// {{SQL CARBON EDIT}}
|
||||
result['common.product'] = product.nameShort || 'desktop';
|
||||
result['common.application.name'] = product.nameLong;
|
||||
result['common.product'] = productObject.nameShort || 'desktop';
|
||||
result['common.application.name'] = productObject.nameLong;
|
||||
|
||||
// dynamic properties which value differs on each call
|
||||
let seq = 0;
|
||||
@@ -65,13 +66,14 @@ export function resolveCommonProperties(commit: string | undefined, version: str
|
||||
result['common.snap'] = 'true';
|
||||
}
|
||||
|
||||
return readFile(installSourcePath, 'utf8').then(contents => {
|
||||
try {
|
||||
const contents = await readFile(installSourcePath, 'utf8');
|
||||
|
||||
// __GDPR__COMMON__ "common.source" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
result['common.source'] = contents.slice(0, 30);
|
||||
} catch (error) {
|
||||
// ignore error
|
||||
}
|
||||
|
||||
return result;
|
||||
}, error => {
|
||||
return result;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -3,20 +3,18 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import product from 'vs/platform/product/node/product';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
|
||||
export function addGAParameters(telemetryService: ITelemetryService, environmentService: IEnvironmentService, uri: URI, origin: string, experiment = '1'): Promise<URI> {
|
||||
export async function addGAParameters(telemetryService: ITelemetryService, environmentService: IEnvironmentService, uri: URI, origin: string, experiment = '1'): Promise<URI> {
|
||||
if (environmentService.isBuilt && !environmentService.isExtensionDevelopment && !environmentService.args['disable-telemetry'] && !!product.enableTelemetry) {
|
||||
if (uri.scheme === 'https' && uri.authority === 'code.visualstudio.com') {
|
||||
return telemetryService.getTelemetryInfo()
|
||||
.then(info => {
|
||||
return uri.with({ query: `${uri.query ? uri.query + '&' : ''}utm_source=VsCode&utm_medium=${encodeURIComponent(origin)}&utm_campaign=${encodeURIComponent(info.instanceId)}&utm_content=${encodeURIComponent(experiment)}` });
|
||||
});
|
||||
const info = await telemetryService.getTelemetryInfo();
|
||||
|
||||
return uri.with({ query: `${uri.query ? uri.query + '&' : ''}utm_source=VsCode&utm_medium=${encodeURIComponent(origin)}&utm_campaign=${encodeURIComponent(info.instanceId)}&utm_content=${encodeURIComponent(experiment)}` });
|
||||
}
|
||||
}
|
||||
return Promise.resolve(uri);
|
||||
return uri;
|
||||
}
|
||||
|
||||
@@ -14,35 +14,38 @@ export const lastSessionDateStorageKey = 'telemetry.lastSessionDate';
|
||||
// {{ SQL CARBON EDIT }}
|
||||
import product from 'vs/platform/product/node/product';
|
||||
|
||||
export function resolveWorkbenchCommonProperties(storageService: IStorageService, commit: string | undefined, version: string | undefined, machineId: string, installSourcePath: string): Promise<{ [name: string]: string | undefined }> {
|
||||
return resolveCommonProperties(commit, version, machineId, installSourcePath).then(result => {
|
||||
const instanceId = storageService.get(instanceStorageKey, StorageScope.GLOBAL)!;
|
||||
const firstSessionDate = storageService.get(firstSessionDateStorageKey, StorageScope.GLOBAL)!;
|
||||
const lastSessionDate = storageService.get(lastSessionDateStorageKey, StorageScope.GLOBAL)!;
|
||||
export async function resolveWorkbenchCommonProperties(storageService: IStorageService, commit: string | undefined, version: string | undefined, machineId: string, installSourcePath: string): Promise<{ [name: string]: string | undefined }> {
|
||||
const result = await resolveCommonProperties(commit, version, machineId, installSourcePath);
|
||||
const instanceId = storageService.get(instanceStorageKey, StorageScope.GLOBAL)!;
|
||||
const firstSessionDate = storageService.get(firstSessionDateStorageKey, StorageScope.GLOBAL)!;
|
||||
const lastSessionDate = storageService.get(lastSessionDateStorageKey, StorageScope.GLOBAL)!;
|
||||
|
||||
// __GDPR__COMMON__ "common.version.shell" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
result['common.version.shell'] = process.versions && process.versions['electron'];
|
||||
// __GDPR__COMMON__ "common.version.renderer" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
result['common.version.renderer'] = process.versions && process.versions['chrome'];
|
||||
// {{SQL CARBON EDIT}}
|
||||
result['common.application.name'] = product.nameLong;
|
||||
// {{SQL CARBON EDIT}}
|
||||
result['common.userId'] = '';
|
||||
// __GDPR__COMMON__ "common.version.shell" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
// result['common.version.shell'] = process.versions && process.versions['electron'];
|
||||
// __GDPR__COMMON__ "common.version.renderer" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
// result['common.version.renderer'] = process.versions && process.versions['chrome'];
|
||||
// __GDPR__COMMON__ "common.firstSessionDate" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
// result['common.firstSessionDate'] = firstSessionDate;
|
||||
// __GDPR__COMMON__ "common.lastSessionDate" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
// result['common.lastSessionDate'] = lastSessionDate || '';
|
||||
// __GDPR__COMMON__ "common.isNewSession" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
// result['common.isNewSession'] = !lastSessionDate ? '1' : '0';
|
||||
// __GDPR__COMMON__ "common.instanceId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
// result['common.instanceId'] = instanceId;
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
// // __GDPR__COMMON__ "common.firstSessionDate" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
// result['common.firstSessionDate'] = firstSessionDate;
|
||||
// // __GDPR__COMMON__ "common.lastSessionDate" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
// result['common.lastSessionDate'] = lastSessionDate || '';
|
||||
// // __GDPR__COMMON__ "common.isNewSession" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
// result['common.isNewSession'] = !lastSessionDate ? '1' : '0';
|
||||
// // __GDPR__COMMON__ "common.instanceId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
// result['common.instanceId'] = instanceId;
|
||||
// __GDPR__COMMON__ "common.version.shell" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
result['common.version.shell'] = process.versions && process.versions['electron'];
|
||||
// __GDPR__COMMON__ "common.version.renderer" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
result['common.version.renderer'] = process.versions && process.versions['chrome'];
|
||||
// {{SQL CARBON EDIT}}
|
||||
result['common.application.name'] = product.nameLong;
|
||||
// {{SQL CARBON EDIT}}
|
||||
result['common.userId'] = '';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
setUsageDates(storageService);
|
||||
return result;
|
||||
});
|
||||
// {{SQL CARBON EDIT}}
|
||||
setUsageDates(storageService);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
|
||||
@@ -74,13 +74,13 @@ export class WindowsService implements IWindowsService {
|
||||
return this.channel.call('closeWorkspace', windowId);
|
||||
}
|
||||
|
||||
enterWorkspace(windowId: number, path: URI): Promise<IEnterWorkspaceResult | undefined> {
|
||||
return this.channel.call('enterWorkspace', [windowId, path]).then((result: IEnterWorkspaceResult) => {
|
||||
if (result) {
|
||||
result.workspace = reviveWorkspaceIdentifier(result.workspace);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
async enterWorkspace(windowId: number, path: URI): Promise<IEnterWorkspaceResult | undefined> {
|
||||
const result: IEnterWorkspaceResult = await this.channel.call('enterWorkspace', [windowId, path]);
|
||||
if (result) {
|
||||
result.workspace = reviveWorkspaceIdentifier(result.workspace);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
toggleFullScreen(windowId: number): Promise<void> {
|
||||
@@ -103,13 +103,12 @@ export class WindowsService implements IWindowsService {
|
||||
return this.channel.call('clearRecentlyOpened');
|
||||
}
|
||||
|
||||
getRecentlyOpened(windowId: number): Promise<IRecentlyOpened> {
|
||||
return this.channel.call('getRecentlyOpened', windowId)
|
||||
.then((recentlyOpened: IRecentlyOpened) => {
|
||||
recentlyOpened.workspaces.forEach(recent => isRecentWorkspace(recent) ? recent.workspace = reviveWorkspaceIdentifier(recent.workspace) : recent.folderUri = URI.revive(recent.folderUri));
|
||||
recentlyOpened.files.forEach(recent => recent.fileUri = URI.revive(recent.fileUri));
|
||||
return recentlyOpened;
|
||||
});
|
||||
async getRecentlyOpened(windowId: number): Promise<IRecentlyOpened> {
|
||||
const recentlyOpened: IRecentlyOpened = await this.channel.call('getRecentlyOpened', windowId);
|
||||
recentlyOpened.workspaces.forEach(recent => isRecentWorkspace(recent) ? recent.workspace = reviveWorkspaceIdentifier(recent.workspace) : recent.folderUri = URI.revive(recent.folderUri));
|
||||
recentlyOpened.files.forEach(recent => recent.fileUri = URI.revive(recent.fileUri));
|
||||
|
||||
return recentlyOpened;
|
||||
}
|
||||
|
||||
newWindowTab(): Promise<void> {
|
||||
@@ -196,18 +195,26 @@ export class WindowsService implements IWindowsService {
|
||||
return this.channel.call('openNewWindow', options);
|
||||
}
|
||||
|
||||
getWindows(): Promise<{ id: number; workspace?: IWorkspaceIdentifier; folderUri?: ISingleFolderWorkspaceIdentifier; title: string; filename?: string; }[]> {
|
||||
return this.channel.call<{ id: number; workspace?: IWorkspaceIdentifier; folderUri?: ISingleFolderWorkspaceIdentifier; title: string; filename?: string; }[]>('getWindows').then(result => {
|
||||
for (const win of result) {
|
||||
if (win.folderUri) {
|
||||
win.folderUri = URI.revive(win.folderUri);
|
||||
}
|
||||
if (win.workspace) {
|
||||
win.workspace = reviveWorkspaceIdentifier(win.workspace);
|
||||
}
|
||||
async getWindows(): Promise<{ id: number; workspace?: IWorkspaceIdentifier; folderUri?: ISingleFolderWorkspaceIdentifier; title: string; filename?: string; }[]> {
|
||||
const result = await this.channel.call<{
|
||||
id: number;
|
||||
workspace?: IWorkspaceIdentifier;
|
||||
folderUri?: ISingleFolderWorkspaceIdentifier;
|
||||
title: string;
|
||||
filename?: string;
|
||||
}[]>('getWindows');
|
||||
|
||||
for (const win of result) {
|
||||
if (win.folderUri) {
|
||||
win.folderUri = URI.revive(win.folderUri);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
|
||||
if (win.workspace) {
|
||||
win.workspace = reviveWorkspaceIdentifier(win.workspace);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
getWindowCount(): Promise<number> {
|
||||
|
||||
@@ -103,13 +103,14 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain
|
||||
return isEqualOrParent(path, this.environmentService.untitledWorkspacesHome);
|
||||
}
|
||||
|
||||
createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise<IWorkspaceIdentifier> {
|
||||
async createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise<IWorkspaceIdentifier> {
|
||||
const { workspace, storedWorkspace } = this.newUntitledWorkspace(folders, remoteAuthority);
|
||||
const configPath = workspace.configPath.fsPath;
|
||||
|
||||
return mkdirp(dirname(configPath)).then(() => {
|
||||
return writeFile(configPath, JSON.stringify(storedWorkspace, null, '\t')).then(() => workspace);
|
||||
});
|
||||
await mkdirp(dirname(configPath));
|
||||
await writeFile(configPath, JSON.stringify(storedWorkspace, null, '\t'));
|
||||
|
||||
return workspace;
|
||||
}
|
||||
|
||||
createUntitledWorkspaceSync(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): IWorkspaceIdentifier {
|
||||
|
||||
Reference in New Issue
Block a user