mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-15 02:48:30 -05:00
Merge VS Code 1.31.1 (#4283)
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IWorkspaceIdentifier, IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -18,49 +17,38 @@ export interface IWorkspaceEditingService {
|
||||
* Add folders to the existing workspace.
|
||||
* When `donotNotifyError` is `true`, error will be bubbled up otherwise, the service handles the error with proper message and action
|
||||
*/
|
||||
addFolders(folders: IWorkspaceFolderCreationData[], donotNotifyError?: boolean): TPromise<void>;
|
||||
addFolders(folders: IWorkspaceFolderCreationData[], donotNotifyError?: boolean): Promise<void>;
|
||||
|
||||
/**
|
||||
* Remove folders from the existing workspace
|
||||
* When `donotNotifyError` is `true`, error will be bubbled up otherwise, the service handles the error with proper message and action
|
||||
*/
|
||||
removeFolders(folders: URI[], donotNotifyError?: boolean): TPromise<void>;
|
||||
removeFolders(folders: URI[], donotNotifyError?: boolean): Promise<void>;
|
||||
|
||||
/**
|
||||
* Allows to add and remove folders to the existing workspace at once.
|
||||
* When `donotNotifyError` is `true`, error will be bubbled up otherwise, the service handles the error with proper message and action
|
||||
*/
|
||||
updateFolders(index: number, deleteCount?: number, foldersToAdd?: IWorkspaceFolderCreationData[], donotNotifyError?: boolean): TPromise<void>;
|
||||
updateFolders(index: number, deleteCount?: number, foldersToAdd?: IWorkspaceFolderCreationData[], donotNotifyError?: boolean): Promise<void>;
|
||||
|
||||
/**
|
||||
* enters the workspace with the provided path.
|
||||
*/
|
||||
enterWorkspace(path: string): TPromise<void>;
|
||||
enterWorkspace(path: URI): Promise<void>;
|
||||
|
||||
/**
|
||||
* creates a new workspace with the provided folders and opens it. if path is provided
|
||||
* the workspace will be saved into that location.
|
||||
*/
|
||||
createAndEnterWorkspace(folders?: IWorkspaceFolderCreationData[], path?: string): TPromise<void>;
|
||||
createAndEnterWorkspace(folders: IWorkspaceFolderCreationData[], path?: URI): Promise<void>;
|
||||
|
||||
/**
|
||||
* saves the workspace to the provided path and opens it. requires a workspace to be opened.
|
||||
* saves the current workspace to the provided path and opens it. requires a workspace to be opened.
|
||||
*/
|
||||
saveAndEnterWorkspace(path: string): TPromise<void>;
|
||||
saveAndEnterWorkspace(path: URI): Promise<void>;
|
||||
|
||||
/**
|
||||
* copies current workspace settings to the target workspace.
|
||||
*/
|
||||
copyWorkspaceSettings(toWorkspace: IWorkspaceIdentifier): TPromise<void>;
|
||||
}
|
||||
|
||||
export const IWorkspaceMigrationService = createDecorator<IWorkspaceMigrationService>('workspaceMigrationService');
|
||||
|
||||
export interface IWorkspaceMigrationService {
|
||||
|
||||
/**
|
||||
* Migrate current workspace to given workspace
|
||||
*/
|
||||
migrate(toWokspaceId: IWorkspaceIdentifier): TPromise<void>;
|
||||
|
||||
copyWorkspaceSettings(toWorkspace: IWorkspaceIdentifier): Promise<void>;
|
||||
}
|
||||
@@ -6,15 +6,14 @@
|
||||
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import * as nls from 'vs/nls';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWindowService, IEnterWorkspaceResult } from 'vs/platform/windows/common/windows';
|
||||
import { IWindowService, MessageBoxOptions, IWindowsService } from 'vs/platform/windows/common/windows';
|
||||
import { IJSONEditingService, JSONEditingError, JSONEditingErrorCode } from 'vs/workbench/services/configuration/common/jsonEditing';
|
||||
import { IWorkspaceIdentifier, IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IWorkspaceIdentifier, IWorkspaceFolderCreationData, isWorkspaceIdentifier, toWorkspaceIdentifier, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { DelegatingStorageService } from 'vs/platform/storage/node/storageService';
|
||||
import { StorageService } from 'vs/platform/storage/node/storageService';
|
||||
import { ConfigurationScope, IConfigurationRegistry, Extensions as ConfigurationExtensions, IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
@@ -23,27 +22,32 @@ import { BackupFileService } from 'vs/workbench/services/backup/node/backupFileS
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { distinct } from 'vs/base/common/arrays';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
import { isEqual, basename } from 'vs/base/common/resources';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { rewriteWorkspaceFileForNewLocation } from 'vs/platform/workspaces/node/workspaces';
|
||||
|
||||
export class WorkspaceEditingService implements IWorkspaceEditingService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
constructor(
|
||||
@IJSONEditingService private jsonEditingService: IJSONEditingService,
|
||||
@IWorkspaceContextService private contextService: WorkspaceService,
|
||||
@IWindowService private windowService: IWindowService,
|
||||
@IWorkspaceConfigurationService private workspaceConfigurationService: IWorkspaceConfigurationService,
|
||||
@IStorageService private storageService: IStorageService,
|
||||
@IExtensionService private extensionService: IExtensionService,
|
||||
@IBackupFileService private backupFileService: IBackupFileService,
|
||||
@INotificationService private notificationService: INotificationService,
|
||||
@ICommandService private commandService: ICommandService
|
||||
@IJSONEditingService private readonly jsonEditingService: IJSONEditingService,
|
||||
@IWorkspaceContextService private readonly contextService: WorkspaceService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IWorkspaceConfigurationService private readonly workspaceConfigurationService: IWorkspaceConfigurationService,
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IBackupFileService private readonly backupFileService: IBackupFileService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@ICommandService private readonly commandService: ICommandService,
|
||||
@IFileService private readonly fileSystemService: IFileService,
|
||||
@IWindowsService private readonly windowsService: IWindowsService,
|
||||
@IWorkspacesService private readonly workspaceService: IWorkspacesService
|
||||
) {
|
||||
}
|
||||
|
||||
updateFolders(index: number, deleteCount?: number, foldersToAdd?: IWorkspaceFolderCreationData[], donotNotifyError?: boolean): TPromise<void> {
|
||||
updateFolders(index: number, deleteCount?: number, foldersToAdd?: IWorkspaceFolderCreationData[], donotNotifyError?: boolean): Promise<void> {
|
||||
const folders = this.contextService.getWorkspace().folders;
|
||||
|
||||
let foldersToDelete: URI[] = [];
|
||||
@@ -55,7 +59,7 @@ export class WorkspaceEditingService implements IWorkspaceEditingService {
|
||||
const wantsToAdd = Array.isArray(foldersToAdd) && foldersToAdd.length > 0;
|
||||
|
||||
if (!wantsToAdd && !wantsToDelete) {
|
||||
return TPromise.as(void 0); // return early if there is nothing to do
|
||||
return Promise.resolve(); // return early if there is nothing to do
|
||||
}
|
||||
|
||||
// Add Folders
|
||||
@@ -88,16 +92,16 @@ export class WorkspaceEditingService implements IWorkspaceEditingService {
|
||||
}
|
||||
}
|
||||
|
||||
private doUpdateFolders(foldersToAdd: IWorkspaceFolderCreationData[], foldersToDelete: URI[], index?: number, donotNotifyError: boolean = false): TPromise<void> {
|
||||
private doUpdateFolders(foldersToAdd: IWorkspaceFolderCreationData[], foldersToDelete: URI[], index?: number, donotNotifyError: boolean = false): Promise<void> {
|
||||
return this.contextService.updateFolders(foldersToAdd, foldersToDelete, index)
|
||||
.then(() => null, error => donotNotifyError ? TPromise.wrapError(error) : this.handleWorkspaceConfigurationEditingError(error));
|
||||
.then(() => null, error => donotNotifyError ? Promise.reject(error) : this.handleWorkspaceConfigurationEditingError(error));
|
||||
}
|
||||
|
||||
addFolders(foldersToAdd: IWorkspaceFolderCreationData[], donotNotifyError: boolean = false): TPromise<void> {
|
||||
return this.doAddFolders(foldersToAdd, void 0, donotNotifyError);
|
||||
addFolders(foldersToAdd: IWorkspaceFolderCreationData[], donotNotifyError: boolean = false): Promise<void> {
|
||||
return this.doAddFolders(foldersToAdd, undefined, donotNotifyError);
|
||||
}
|
||||
|
||||
private doAddFolders(foldersToAdd: IWorkspaceFolderCreationData[], index?: number, donotNotifyError: boolean = false): TPromise<void> {
|
||||
private doAddFolders(foldersToAdd: IWorkspaceFolderCreationData[], index?: number, donotNotifyError: boolean = false): Promise<void> {
|
||||
const state = this.contextService.getWorkbenchState();
|
||||
|
||||
// If we are in no-workspace or single-folder workspace, adding folders has to
|
||||
@@ -108,7 +112,7 @@ export class WorkspaceEditingService implements IWorkspaceEditingService {
|
||||
newWorkspaceFolders = distinct(newWorkspaceFolders, folder => isLinux ? folder.uri.toString() : folder.uri.toString().toLowerCase());
|
||||
|
||||
if (state === WorkbenchState.EMPTY && newWorkspaceFolders.length === 0 || state === WorkbenchState.FOLDER && newWorkspaceFolders.length === 1) {
|
||||
return TPromise.as(void 0); // return if the operation is a no-op for the current state
|
||||
return Promise.resolve(); // return if the operation is a no-op for the current state
|
||||
}
|
||||
|
||||
return this.createAndEnterWorkspace(newWorkspaceFolders);
|
||||
@@ -116,10 +120,10 @@ export class WorkspaceEditingService implements IWorkspaceEditingService {
|
||||
|
||||
// Delegate addition of folders to workspace service otherwise
|
||||
return this.contextService.addFolders(foldersToAdd, index)
|
||||
.then(() => null, error => donotNotifyError ? TPromise.wrapError(error) : this.handleWorkspaceConfigurationEditingError(error));
|
||||
.then(() => null, error => donotNotifyError ? Promise.reject(error) : this.handleWorkspaceConfigurationEditingError(error));
|
||||
}
|
||||
|
||||
removeFolders(foldersToRemove: URI[], donotNotifyError: boolean = false): TPromise<void> {
|
||||
removeFolders(foldersToRemove: URI[], donotNotifyError: boolean = false): Promise<void> {
|
||||
|
||||
// If we are in single-folder state and the opened folder is to be removed,
|
||||
// we create an empty workspace and enter it.
|
||||
@@ -129,7 +133,7 @@ export class WorkspaceEditingService implements IWorkspaceEditingService {
|
||||
|
||||
// Delegate removal of folders to workspace service otherwise
|
||||
return this.contextService.removeFolders(foldersToRemove)
|
||||
.then(() => null, error => donotNotifyError ? TPromise.wrapError(error) : this.handleWorkspaceConfigurationEditingError(error));
|
||||
.then(() => null, error => donotNotifyError ? Promise.reject(error) : this.handleWorkspaceConfigurationEditingError(error));
|
||||
}
|
||||
|
||||
private includesSingleFolderWorkspace(folders: URI[]): boolean {
|
||||
@@ -141,30 +145,78 @@ export class WorkspaceEditingService implements IWorkspaceEditingService {
|
||||
return false;
|
||||
}
|
||||
|
||||
enterWorkspace(path: string): TPromise<void> {
|
||||
return this.doEnterWorkspace(() => this.windowService.enterWorkspace(path));
|
||||
async createAndEnterWorkspace(folders: IWorkspaceFolderCreationData[], path?: URI): Promise<void> {
|
||||
if (path && !this.isValidTargetWorkspacePath(path)) {
|
||||
return Promise.reject(null);
|
||||
}
|
||||
|
||||
const untitledWorkspace = await this.workspaceService.createUntitledWorkspace(folders);
|
||||
if (path) {
|
||||
await this.saveWorkspaceAs(untitledWorkspace, path);
|
||||
} else {
|
||||
path = URI.file(untitledWorkspace.configPath);
|
||||
}
|
||||
return this.enterWorkspace(path);
|
||||
}
|
||||
|
||||
createAndEnterWorkspace(folders?: IWorkspaceFolderCreationData[], path?: string): TPromise<void> {
|
||||
return this.doEnterWorkspace(() => this.windowService.createAndEnterWorkspace(folders, path));
|
||||
async saveAndEnterWorkspace(path: URI): Promise<void> {
|
||||
if (!this.isValidTargetWorkspacePath(path)) {
|
||||
return Promise.reject(null);
|
||||
}
|
||||
const currentWorkspaceIdentifier = toWorkspaceIdentifier(this.contextService.getWorkspace());
|
||||
if (!isWorkspaceIdentifier(currentWorkspaceIdentifier)) {
|
||||
return Promise.reject(null);
|
||||
}
|
||||
await this.saveWorkspaceAs(currentWorkspaceIdentifier, path);
|
||||
|
||||
return this.enterWorkspace(path);
|
||||
}
|
||||
|
||||
saveAndEnterWorkspace(path: string): TPromise<void> {
|
||||
return this.doEnterWorkspace(() => this.windowService.saveAndEnterWorkspace(path));
|
||||
async isValidTargetWorkspacePath(path: URI): Promise<boolean> {
|
||||
|
||||
const windows = await this.windowsService.getWindows();
|
||||
|
||||
// Prevent overwriting a workspace that is currently opened in another window
|
||||
if (windows.some(window => window.workspace && isEqual(URI.file(window.workspace.configPath), path))) {
|
||||
const options: MessageBoxOptions = {
|
||||
type: 'info',
|
||||
buttons: [nls.localize('ok', "OK")],
|
||||
message: nls.localize('workspaceOpenedMessage', "Unable to save workspace '{0}'", basename(path)),
|
||||
detail: nls.localize('workspaceOpenedDetail', "The workspace is already opened in another window. Please close that window first and then try again."),
|
||||
noLink: true
|
||||
};
|
||||
return this.windowService.showMessageBox(options).then(() => false);
|
||||
}
|
||||
|
||||
return Promise.resolve(true); // OK
|
||||
}
|
||||
|
||||
private handleWorkspaceConfigurationEditingError(error: JSONEditingError): TPromise<void> {
|
||||
private async saveWorkspaceAs(workspace: IWorkspaceIdentifier, targetConfigPathURI: URI): Promise<any> {
|
||||
const configPathURI = URI.file(workspace.configPath);
|
||||
|
||||
// Return early if target is same as source
|
||||
if (isEqual(configPathURI, targetConfigPathURI)) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
// Read the contents of the workspace file, update it to new location and save it.
|
||||
const raw = await this.fileSystemService.resolveContent(configPathURI);
|
||||
const newRawWorkspaceContents = rewriteWorkspaceFileForNewLocation(raw.value, configPathURI, targetConfigPathURI);
|
||||
await this.fileSystemService.createFile(targetConfigPathURI, newRawWorkspaceContents, { overwrite: true });
|
||||
}
|
||||
|
||||
private handleWorkspaceConfigurationEditingError(error: JSONEditingError): Promise<void> {
|
||||
switch (error.code) {
|
||||
case JSONEditingErrorCode.ERROR_INVALID_FILE:
|
||||
this.onInvalidWorkspaceConfigurationFileError();
|
||||
return TPromise.as(void 0);
|
||||
return Promise.resolve();
|
||||
case JSONEditingErrorCode.ERROR_FILE_DIRTY:
|
||||
this.onWorkspaceConfigurationFileDirtyError();
|
||||
return TPromise.as(void 0);
|
||||
return Promise.resolve();
|
||||
}
|
||||
this.notificationService.error(error.message);
|
||||
|
||||
return TPromise.as(void 0);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
private onInvalidWorkspaceConfigurationFileError(): void {
|
||||
@@ -186,7 +238,7 @@ export class WorkspaceEditingService implements IWorkspaceEditingService {
|
||||
);
|
||||
}
|
||||
|
||||
private doEnterWorkspace(mainSidePromise: () => TPromise<IEnterWorkspaceResult>): TPromise<void> {
|
||||
enterWorkspace(path: URI): Promise<void> {
|
||||
|
||||
// Stop the extension host first to give extensions most time to shutdown
|
||||
this.extensionService.stopExtensionHost();
|
||||
@@ -197,7 +249,7 @@ export class WorkspaceEditingService implements IWorkspaceEditingService {
|
||||
extensionHostStarted = true;
|
||||
};
|
||||
|
||||
return mainSidePromise().then(result => {
|
||||
return this.windowService.enterWorkspace(path).then(result => {
|
||||
|
||||
// Migrate storage and settings if we are to enter a workspace
|
||||
if (result) {
|
||||
@@ -214,17 +266,17 @@ export class WorkspaceEditingService implements IWorkspaceEditingService {
|
||||
});
|
||||
}
|
||||
|
||||
return TPromise.as(void 0);
|
||||
}).then(null, error => {
|
||||
return Promise.resolve();
|
||||
}).then(undefined, error => {
|
||||
if (!extensionHostStarted) {
|
||||
startExtensionHost(); // start the extension host if not started
|
||||
}
|
||||
|
||||
return TPromise.wrapError(error);
|
||||
return Promise.reject(error);
|
||||
});
|
||||
}
|
||||
|
||||
private migrate(toWorkspace: IWorkspaceIdentifier): Thenable<void> {
|
||||
private migrate(toWorkspace: IWorkspaceIdentifier): Promise<void> {
|
||||
|
||||
// Storage migration
|
||||
return this.migrateStorage(toWorkspace).then(() => {
|
||||
@@ -234,25 +286,25 @@ export class WorkspaceEditingService implements IWorkspaceEditingService {
|
||||
return this.migrateWorkspaceSettings(toWorkspace);
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
private migrateStorage(toWorkspace: IWorkspaceIdentifier): Thenable<void> {
|
||||
const storageImpl = this.storageService as DelegatingStorageService;
|
||||
private migrateStorage(toWorkspace: IWorkspaceIdentifier): Promise<void> {
|
||||
const storageImpl = this.storageService as StorageService;
|
||||
|
||||
return storageImpl.storage.migrate(toWorkspace);
|
||||
return storageImpl.migrate(toWorkspace);
|
||||
}
|
||||
|
||||
private migrateWorkspaceSettings(toWorkspace: IWorkspaceIdentifier): TPromise<void> {
|
||||
private migrateWorkspaceSettings(toWorkspace: IWorkspaceIdentifier): Promise<void> {
|
||||
return this.doCopyWorkspaceSettings(toWorkspace, setting => setting.scope === ConfigurationScope.WINDOW);
|
||||
}
|
||||
|
||||
copyWorkspaceSettings(toWorkspace: IWorkspaceIdentifier): TPromise<void> {
|
||||
copyWorkspaceSettings(toWorkspace: IWorkspaceIdentifier): Promise<void> {
|
||||
return this.doCopyWorkspaceSettings(toWorkspace);
|
||||
}
|
||||
|
||||
private doCopyWorkspaceSettings(toWorkspace: IWorkspaceIdentifier, filter?: (config: IConfigurationPropertySchema) => boolean): TPromise<void> {
|
||||
private doCopyWorkspaceSettings(toWorkspace: IWorkspaceIdentifier, filter?: (config: IConfigurationPropertySchema) => boolean): Promise<void> {
|
||||
const configurationProperties = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).getConfigurationProperties();
|
||||
const targetWorkspaceConfiguration = {};
|
||||
for (const key of this.workspaceConfigurationService.keys().workspace) {
|
||||
|
||||
Reference in New Issue
Block a user