mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-31 09:35:39 -05:00
Merge VS Code 1.31.1 (#4283)
This commit is contained in:
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { localize } from 'vs/nls';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IWorkspaceFolder, IWorkspace } from 'vs/platform/workspace/common/workspace';
|
||||
@@ -78,14 +77,11 @@ export interface IWorkspaceFolderCreationData {
|
||||
export interface IWorkspacesMainService extends IWorkspacesService {
|
||||
_serviceBrand: any;
|
||||
|
||||
onWorkspaceSaved: Event<IWorkspaceSavedEvent>;
|
||||
onUntitledWorkspaceDeleted: Event<IWorkspaceIdentifier>;
|
||||
|
||||
saveWorkspace(workspace: IWorkspaceIdentifier, target: string): TPromise<IWorkspaceIdentifier>;
|
||||
saveWorkspaceAs(workspace: IWorkspaceIdentifier, target: string): Promise<IWorkspaceIdentifier>;
|
||||
|
||||
createWorkspaceSync(folders?: IWorkspaceFolderCreationData[]): IWorkspaceIdentifier;
|
||||
|
||||
resolveWorkspace(path: string): TPromise<IResolvedWorkspace | null>;
|
||||
createUntitledWorkspaceSync(folders?: IWorkspaceFolderCreationData[]): IWorkspaceIdentifier;
|
||||
|
||||
resolveWorkspaceSync(path: string): IResolvedWorkspace | null;
|
||||
|
||||
@@ -96,12 +92,14 @@ export interface IWorkspacesMainService extends IWorkspacesService {
|
||||
getUntitledWorkspacesSync(): IWorkspaceIdentifier[];
|
||||
|
||||
getWorkspaceId(workspacePath: string): string;
|
||||
|
||||
getWorkspaceIdentifier(workspacePath: URI): IWorkspaceIdentifier;
|
||||
}
|
||||
|
||||
export interface IWorkspacesService {
|
||||
_serviceBrand: any;
|
||||
|
||||
createWorkspace(folders?: IWorkspaceFolderCreationData[]): TPromise<IWorkspaceIdentifier>;
|
||||
createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[]): Promise<IWorkspaceIdentifier>;
|
||||
}
|
||||
|
||||
export function isSingleFolderWorkspaceIdentifier(obj: any): obj is ISingleFolderWorkspaceIdentifier {
|
||||
@@ -137,4 +135,4 @@ export type IWorkspaceInitializationPayload = IMultiFolderWorkspaceInitializatio
|
||||
|
||||
export function isSingleFolderWorkspaceInitializationPayload(obj: any): obj is ISingleFolderWorkspaceInitializationPayload {
|
||||
return isSingleFolderWorkspaceIdentifier((obj.folder as ISingleFolderWorkspaceIdentifier));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,13 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IWorkspacesMainService, IWorkspaceIdentifier, WORKSPACE_EXTENSION, IWorkspaceSavedEvent, UNTITLED_WORKSPACE_NAME, IResolvedWorkspace, IStoredWorkspaceFolder, isRawFileWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IWorkspacesMainService, IWorkspaceIdentifier, WORKSPACE_EXTENSION, UNTITLED_WORKSPACE_NAME, IResolvedWorkspace, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { isParent } from 'vs/platform/files/common/files';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { extname, join, dirname, isAbsolute, resolve } from 'path';
|
||||
import { join, dirname, extname } from 'path';
|
||||
import { mkdirp, writeFile, readFile } from 'vs/base/node/pfs';
|
||||
import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
|
||||
import { isLinux, isMacintosh } from 'vs/base/common/platform';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
import { delSync, readdirSync, writeFileAndFlushSync } from 'vs/base/node/extfs';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
@@ -18,12 +17,12 @@ import { isEqual } from 'vs/base/common/paths';
|
||||
import { coalesce } from 'vs/base/common/arrays';
|
||||
import { createHash } from 'crypto';
|
||||
import * as json from 'vs/base/common/json';
|
||||
import * as jsonEdit from 'vs/base/common/jsonEdit';
|
||||
import { massageFolderPathForWorkspace } from 'vs/platform/workspaces/node/workspaces';
|
||||
import { massageFolderPathForWorkspace, rewriteWorkspaceFileForNewLocation } from 'vs/platform/workspaces/node/workspaces';
|
||||
import { toWorkspaceFolders } from 'vs/platform/workspace/common/workspace';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { fsPath, dirname as resourcesDirname } from 'vs/base/common/resources';
|
||||
|
||||
export interface IStoredWorkspace {
|
||||
folders: IStoredWorkspaceFolder[];
|
||||
@@ -35,29 +34,18 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain
|
||||
|
||||
private workspacesHome: string;
|
||||
|
||||
private readonly _onWorkspaceSaved = this._register(new Emitter<IWorkspaceSavedEvent>());
|
||||
get onWorkspaceSaved(): Event<IWorkspaceSavedEvent> { return this._onWorkspaceSaved.event; }
|
||||
|
||||
private readonly _onUntitledWorkspaceDeleted = this._register(new Emitter<IWorkspaceIdentifier>());
|
||||
get onUntitledWorkspaceDeleted(): Event<IWorkspaceIdentifier> { return this._onUntitledWorkspaceDeleted.event; }
|
||||
|
||||
constructor(
|
||||
@IEnvironmentService private environmentService: IEnvironmentService,
|
||||
@ILogService private logService: ILogService
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@ILogService private readonly logService: ILogService
|
||||
) {
|
||||
super();
|
||||
|
||||
this.workspacesHome = environmentService.workspacesHome;
|
||||
}
|
||||
|
||||
resolveWorkspace(path: string): TPromise<IResolvedWorkspace | null> {
|
||||
if (!this.isWorkspacePath(path)) {
|
||||
return TPromise.as(null); // does not look like a valid workspace config file
|
||||
}
|
||||
|
||||
return readFile(path, 'utf8').then(contents => this.doResolveWorkspace(path, contents));
|
||||
}
|
||||
|
||||
resolveWorkspaceSync(path: string): IResolvedWorkspace | null {
|
||||
if (!this.isWorkspacePath(path)) {
|
||||
return null; // does not look like a valid workspace config file
|
||||
@@ -70,21 +58,21 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain
|
||||
return null; // invalid workspace
|
||||
}
|
||||
|
||||
return this.doResolveWorkspace(path, contents);
|
||||
return this.doResolveWorkspace(URI.file(path), contents);
|
||||
}
|
||||
|
||||
private isWorkspacePath(path: string): boolean {
|
||||
return this.isInsideWorkspacesHome(path) || extname(path) === `.${WORKSPACE_EXTENSION}`;
|
||||
}
|
||||
|
||||
private doResolveWorkspace(path: string, contents: string): IResolvedWorkspace | null {
|
||||
private doResolveWorkspace(path: URI, contents: string): IResolvedWorkspace | null {
|
||||
try {
|
||||
const workspace = this.doParseStoredWorkspace(path, contents);
|
||||
|
||||
const workspaceIdentifier = this.getWorkspaceIdentifier(path);
|
||||
return {
|
||||
id: this.getWorkspaceId(path),
|
||||
configPath: path,
|
||||
folders: toWorkspaceFolders(workspace.folders, URI.file(dirname(path)))
|
||||
id: workspaceIdentifier.id,
|
||||
configPath: workspaceIdentifier.configPath,
|
||||
folders: toWorkspaceFolders(workspace.folders, resourcesDirname(path)!)
|
||||
};
|
||||
} catch (error) {
|
||||
this.logService.warn(error.toString());
|
||||
@@ -93,7 +81,7 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain
|
||||
return null;
|
||||
}
|
||||
|
||||
private doParseStoredWorkspace(path: string, contents: string): IStoredWorkspace {
|
||||
private doParseStoredWorkspace(path: URI, contents: string): IStoredWorkspace {
|
||||
|
||||
// Parse workspace file
|
||||
let storedWorkspace: IStoredWorkspace = json.parse(contents); // use fault tolerant parser
|
||||
@@ -105,7 +93,7 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain
|
||||
|
||||
// Validate
|
||||
if (!Array.isArray(storedWorkspace.folders)) {
|
||||
throw new Error(`${path} looks like an invalid workspace file.`);
|
||||
throw new Error(`${path.toString()} looks like an invalid workspace file.`);
|
||||
}
|
||||
|
||||
return storedWorkspace;
|
||||
@@ -115,16 +103,16 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain
|
||||
return isParent(path, this.environmentService.workspacesHome, !isLinux /* ignore case */);
|
||||
}
|
||||
|
||||
createWorkspace(folders?: IWorkspaceFolderCreationData[]): TPromise<IWorkspaceIdentifier> {
|
||||
const { workspace, configParent, storedWorkspace } = this.createUntitledWorkspace(folders);
|
||||
createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[]): Promise<IWorkspaceIdentifier> {
|
||||
const { workspace, configParent, storedWorkspace } = this.newUntitledWorkspace(folders);
|
||||
|
||||
return mkdirp(configParent).then(() => {
|
||||
return writeFile(workspace.configPath, JSON.stringify(storedWorkspace, null, '\t')).then(() => workspace);
|
||||
});
|
||||
}
|
||||
|
||||
createWorkspaceSync(folders?: IWorkspaceFolderCreationData[]): IWorkspaceIdentifier {
|
||||
const { workspace, configParent, storedWorkspace } = this.createUntitledWorkspace(folders);
|
||||
createUntitledWorkspaceSync(folders?: IWorkspaceFolderCreationData[]): IWorkspaceIdentifier {
|
||||
const { workspace, configParent, storedWorkspace } = this.newUntitledWorkspace(folders);
|
||||
|
||||
if (!existsSync(this.workspacesHome)) {
|
||||
mkdirSync(this.workspacesHome);
|
||||
@@ -137,7 +125,7 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain
|
||||
return workspace;
|
||||
}
|
||||
|
||||
private createUntitledWorkspace(folders: IWorkspaceFolderCreationData[] = []): { workspace: IWorkspaceIdentifier, configParent: string, storedWorkspace: IStoredWorkspace } {
|
||||
private newUntitledWorkspace(folders: IWorkspaceFolderCreationData[] = []): { workspace: IWorkspaceIdentifier, configParent: string, storedWorkspace: IStoredWorkspace } {
|
||||
const randomId = (Date.now() + Math.round(Math.random() * 1000)).toString();
|
||||
const untitledWorkspaceConfigFolder = join(this.workspacesHome, randomId);
|
||||
const untitledWorkspaceConfigPath = join(untitledWorkspaceConfigFolder, UNTITLED_WORKSPACE_NAME);
|
||||
@@ -149,7 +137,7 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain
|
||||
|
||||
// File URI
|
||||
if (folderResource.scheme === Schemas.file) {
|
||||
storedWorkspace = { path: massageFolderPathForWorkspace(folderResource.fsPath, untitledWorkspaceConfigFolder, []) };
|
||||
storedWorkspace = { path: massageFolderPathForWorkspace(fsPath(folderResource), URI.file(untitledWorkspaceConfigFolder), []) };
|
||||
}
|
||||
|
||||
// Any URI
|
||||
@@ -183,61 +171,39 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain
|
||||
return createHash('md5').update(workspaceConfigPath).digest('hex');
|
||||
}
|
||||
|
||||
getWorkspaceIdentifier(workspacePath: URI): IWorkspaceIdentifier {
|
||||
if (workspacePath.scheme === Schemas.file) {
|
||||
const configPath = fsPath(workspacePath);
|
||||
return {
|
||||
configPath,
|
||||
id: this.getWorkspaceId(configPath)
|
||||
};
|
||||
}
|
||||
throw new Error('Not yet supported');
|
||||
/*return {
|
||||
configPath: workspacePath
|
||||
id: this.getWorkspaceId(workspacePath.toString());
|
||||
};*/
|
||||
}
|
||||
|
||||
isUntitledWorkspace(workspace: IWorkspaceIdentifier): boolean {
|
||||
return this.isInsideWorkspacesHome(workspace.configPath);
|
||||
}
|
||||
|
||||
saveWorkspace(workspace: IWorkspaceIdentifier, targetConfigPath: string): TPromise<IWorkspaceIdentifier> {
|
||||
saveWorkspaceAs(workspace: IWorkspaceIdentifier, targetConfigPath: string): Promise<IWorkspaceIdentifier> {
|
||||
|
||||
// Return early if target is same as source
|
||||
if (isEqual(workspace.configPath, targetConfigPath, !isLinux)) {
|
||||
return TPromise.as(workspace);
|
||||
return Promise.resolve(workspace);
|
||||
}
|
||||
|
||||
// Read the contents of the workspace file and resolve it
|
||||
return readFile(workspace.configPath).then(raw => {
|
||||
const rawWorkspaceContents = raw.toString();
|
||||
let storedWorkspace: IStoredWorkspace;
|
||||
try {
|
||||
storedWorkspace = this.doParseStoredWorkspace(workspace.configPath, rawWorkspaceContents);
|
||||
} catch (error) {
|
||||
return TPromise.wrapError(error);
|
||||
}
|
||||
|
||||
const sourceConfigFolder = dirname(workspace.configPath);
|
||||
const targetConfigFolder = dirname(targetConfigPath);
|
||||
|
||||
// Rewrite absolute paths to relative paths if the target workspace folder
|
||||
// is a parent of the location of the workspace file itself. Otherwise keep
|
||||
// using absolute paths.
|
||||
storedWorkspace.folders.forEach(folder => {
|
||||
if (isRawFileWorkspaceFolder(folder)) {
|
||||
if (!isAbsolute(folder.path)) {
|
||||
folder.path = resolve(sourceConfigFolder, folder.path); // relative paths get resolved against the workspace location
|
||||
}
|
||||
folder.path = massageFolderPathForWorkspace(folder.path, targetConfigFolder, storedWorkspace.folders);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Preserve as much of the existing workspace as possible by using jsonEdit
|
||||
// and only changing the folders portion.
|
||||
let newRawWorkspaceContents = rawWorkspaceContents;
|
||||
const edits = jsonEdit.setProperty(rawWorkspaceContents, ['folders'], storedWorkspace.folders, { insertSpaces: false, tabSize: 4, eol: (isLinux || isMacintosh) ? '\n' : '\r\n' });
|
||||
edits.forEach(edit => {
|
||||
newRawWorkspaceContents = jsonEdit.applyEdit(rawWorkspaceContents, edit);
|
||||
});
|
||||
const targetConfigPathURI = URI.file(targetConfigPath);
|
||||
const newRawWorkspaceContents = rewriteWorkspaceFileForNewLocation(raw.toString(), URI.file(workspace.configPath), targetConfigPathURI);
|
||||
|
||||
return writeFile(targetConfigPath, newRawWorkspaceContents).then(() => {
|
||||
const savedWorkspaceIdentifier = { id: this.getWorkspaceId(targetConfigPath), configPath: targetConfigPath };
|
||||
|
||||
// Event
|
||||
this._onWorkspaceSaved.fire({ workspace: savedWorkspaceIdentifier, oldConfigPath: workspace.configPath });
|
||||
|
||||
// Delete untitled workspace
|
||||
this.deleteUntitledWorkspaceSync(workspace);
|
||||
|
||||
return savedWorkspaceIdentifier;
|
||||
return this.getWorkspaceIdentifier(targetConfigPathURI);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -293,4 +259,4 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain
|
||||
|
||||
return untitledWorkspaces;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,16 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IStoredWorkspaceFolder, isRawFileWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { isWindows, isLinux } from 'vs/base/common/platform';
|
||||
import { isAbsolute, relative } from 'path';
|
||||
import { isEqualOrParent, normalize } from 'vs/base/common/paths';
|
||||
import { IStoredWorkspaceFolder, isRawFileWorkspaceFolder, IStoredWorkspace, isStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform';
|
||||
import { isAbsolute, relative, posix, resolve } from 'path';
|
||||
import { normalize, isEqualOrParent } from 'vs/base/common/paths';
|
||||
import { normalizeDriveLetter } from 'vs/base/common/labels';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { fsPath, dirname } from 'vs/base/common/resources';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import * as jsonEdit from 'vs/base/common/jsonEdit';
|
||||
import * as json from 'vs/base/common/json';
|
||||
|
||||
const SLASH = '/';
|
||||
|
||||
@@ -19,33 +24,91 @@ const SLASH = '/';
|
||||
* @param targetConfigFolder the folder where the workspace is living in
|
||||
* @param existingFolders a set of existing folders of the workspace
|
||||
*/
|
||||
export function massageFolderPathForWorkspace(absoluteFolderPath: string, targetConfigFolder: string, existingFolders: IStoredWorkspaceFolder[]): string {
|
||||
const useSlashesForPath = shouldUseSlashForPath(existingFolders);
|
||||
export function massageFolderPathForWorkspace(absoluteFolderPath: string, targetConfigFolderURI: URI, existingFolders: IStoredWorkspaceFolder[]): string {
|
||||
|
||||
// Convert path to relative path if the target config folder
|
||||
// is a parent of the path.
|
||||
if (isEqualOrParent(absoluteFolderPath, targetConfigFolder, !isLinux)) {
|
||||
absoluteFolderPath = relative(targetConfigFolder, absoluteFolderPath) || '.';
|
||||
}
|
||||
if (targetConfigFolderURI.scheme === Schemas.file) {
|
||||
const targetFolderPath = fsPath(targetConfigFolderURI);
|
||||
// Convert path to relative path if the target config folder
|
||||
// is a parent of the path.
|
||||
if (isEqualOrParent(absoluteFolderPath, targetFolderPath, !isLinux)) {
|
||||
absoluteFolderPath = relative(targetFolderPath, absoluteFolderPath) || '.';
|
||||
}
|
||||
|
||||
// Windows gets special treatment:
|
||||
// - normalize all paths to get nice casing of drive letters
|
||||
// - convert to slashes if we want to use slashes for paths
|
||||
if (isWindows) {
|
||||
if (isAbsolute(absoluteFolderPath)) {
|
||||
if (useSlashesForPath) {
|
||||
absoluteFolderPath = normalize(absoluteFolderPath, false /* do not use OS path separator */);
|
||||
// Windows gets special treatment:
|
||||
// - normalize all paths to get nice casing of drive letters
|
||||
// - convert to slashes if we want to use slashes for paths
|
||||
if (isWindows) {
|
||||
if (isAbsolute(absoluteFolderPath)) {
|
||||
if (shouldUseSlashForPath(existingFolders)) {
|
||||
absoluteFolderPath = normalize(absoluteFolderPath, false /* do not use OS path separator */);
|
||||
}
|
||||
|
||||
absoluteFolderPath = normalizeDriveLetter(absoluteFolderPath);
|
||||
} else if (shouldUseSlashForPath(existingFolders)) {
|
||||
absoluteFolderPath = absoluteFolderPath.replace(/[\\]/g, SLASH);
|
||||
}
|
||||
|
||||
absoluteFolderPath = normalizeDriveLetter(absoluteFolderPath);
|
||||
} else if (useSlashesForPath) {
|
||||
absoluteFolderPath = absoluteFolderPath.replace(/[\\]/g, SLASH);
|
||||
}
|
||||
} else {
|
||||
if (isEqualOrParent(absoluteFolderPath, targetConfigFolderURI.path)) {
|
||||
absoluteFolderPath = posix.relative(absoluteFolderPath, targetConfigFolderURI.path) || '.';
|
||||
}
|
||||
}
|
||||
|
||||
return absoluteFolderPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrites the content of a workspace file to be saved at a new location.
|
||||
* Throws an exception if file is not a valid workspace file
|
||||
*/
|
||||
export function rewriteWorkspaceFileForNewLocation(rawWorkspaceContents: string, configPathURI: URI, targetConfigPathURI: URI) {
|
||||
let storedWorkspace = doParseStoredWorkspace(configPathURI, rawWorkspaceContents);
|
||||
|
||||
const sourceConfigFolder = dirname(configPathURI)!;
|
||||
const targetConfigFolder = dirname(targetConfigPathURI)!;
|
||||
|
||||
// Rewrite absolute paths to relative paths if the target workspace folder
|
||||
// is a parent of the location of the workspace file itself. Otherwise keep
|
||||
// using absolute paths.
|
||||
for (const folder of storedWorkspace.folders) {
|
||||
if (isRawFileWorkspaceFolder(folder)) {
|
||||
if (sourceConfigFolder.scheme === Schemas.file) {
|
||||
if (!isAbsolute(folder.path)) {
|
||||
folder.path = resolve(fsPath(sourceConfigFolder), folder.path); // relative paths get resolved against the workspace location
|
||||
}
|
||||
folder.path = massageFolderPathForWorkspace(folder.path, targetConfigFolder, storedWorkspace.folders);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Preserve as much of the existing workspace as possible by using jsonEdit
|
||||
// and only changing the folders portion.
|
||||
let newRawWorkspaceContents = rawWorkspaceContents;
|
||||
const edits = jsonEdit.setProperty(rawWorkspaceContents, ['folders'], storedWorkspace.folders, { insertSpaces: false, tabSize: 4, eol: (isLinux || isMacintosh) ? '\n' : '\r\n' });
|
||||
edits.forEach(edit => {
|
||||
newRawWorkspaceContents = jsonEdit.applyEdit(rawWorkspaceContents, edit);
|
||||
});
|
||||
return newRawWorkspaceContents;
|
||||
}
|
||||
|
||||
function doParseStoredWorkspace(path: URI, contents: string): IStoredWorkspace {
|
||||
|
||||
// Parse workspace file
|
||||
let storedWorkspace: IStoredWorkspace = json.parse(contents); // use fault tolerant parser
|
||||
|
||||
// Filter out folders which do not have a path or uri set
|
||||
if (Array.isArray(storedWorkspace.folders)) {
|
||||
storedWorkspace.folders = storedWorkspace.folders.filter(folder => isStoredWorkspaceFolder(folder));
|
||||
}
|
||||
|
||||
// Validate
|
||||
if (!Array.isArray(storedWorkspace.folders)) {
|
||||
throw new Error(`${path} looks like an invalid workspace file.`);
|
||||
}
|
||||
|
||||
return storedWorkspace;
|
||||
}
|
||||
|
||||
function shouldUseSlashForPath(storedFolders: IStoredWorkspaceFolder[]): boolean {
|
||||
|
||||
// Determine which path separator to use:
|
||||
|
||||
@@ -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 { IChannel, IServerChannel } from 'vs/base/parts/ipc/node/ipc';
|
||||
import { IWorkspacesService, IWorkspaceIdentifier, IWorkspaceFolderCreationData, IWorkspacesMainService } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -17,9 +16,9 @@ export class WorkspacesChannel implements IServerChannel {
|
||||
throw new Error(`Event not found: ${event}`);
|
||||
}
|
||||
|
||||
call(_, command: string, arg?: any): Thenable<any> {
|
||||
call(_, command: string, arg?: any): Promise<any> {
|
||||
switch (command) {
|
||||
case 'createWorkspace': {
|
||||
case 'createUntitledWorkspace': {
|
||||
const rawFolders: IWorkspaceFolderCreationData[] = arg;
|
||||
let folders: IWorkspaceFolderCreationData[] | undefined = undefined;
|
||||
if (Array.isArray(rawFolders)) {
|
||||
@@ -31,7 +30,7 @@ export class WorkspacesChannel implements IServerChannel {
|
||||
});
|
||||
}
|
||||
|
||||
return this.service.createWorkspace(folders);
|
||||
return this.service.createUntitledWorkspace(folders);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +44,7 @@ export class WorkspacesChannelClient implements IWorkspacesService {
|
||||
|
||||
constructor(private channel: IChannel) { }
|
||||
|
||||
createWorkspace(folders?: IWorkspaceFolderCreationData[]): TPromise<IWorkspaceIdentifier> {
|
||||
return TPromise.wrap(this.channel.call('createWorkspace', folders));
|
||||
createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[]): Promise<IWorkspaceIdentifier> {
|
||||
return this.channel.call('createUntitledWorkspace', folders);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import * as pfs from 'vs/base/node/pfs';
|
||||
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||
import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { WorkspacesMainService, IStoredWorkspace } from 'vs/platform/workspaces/electron-main/workspacesMainService';
|
||||
import { WORKSPACE_EXTENSION, IWorkspaceSavedEvent, IWorkspaceIdentifier, IRawFileWorkspaceFolder, IWorkspaceFolderCreationData, IRawUriWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { WORKSPACE_EXTENSION, IWorkspaceIdentifier, IRawFileWorkspaceFolder, IWorkspaceFolderCreationData, IRawUriWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { getRandomTestPath } from 'vs/workbench/test/workbenchTestServices';
|
||||
@@ -40,11 +40,11 @@ suite('WorkspacesMainService', () => {
|
||||
}
|
||||
|
||||
function createWorkspace(folders: string[], names?: string[]) {
|
||||
return service.createWorkspace(folders.map((folder, index) => ({ uri: URI.file(folder), name: names ? names[index] : void 0 } as IWorkspaceFolderCreationData)));
|
||||
return service.createUntitledWorkspace(folders.map((folder, index) => ({ uri: URI.file(folder), name: names ? names[index] : undefined } as IWorkspaceFolderCreationData)));
|
||||
}
|
||||
|
||||
function createWorkspaceSync(folders: string[], names?: string[]) {
|
||||
return service.createWorkspaceSync(folders.map((folder, index) => ({ uri: URI.file(folder), name: names ? names[index] : void 0 } as IWorkspaceFolderCreationData)));
|
||||
return service.createUntitledWorkspaceSync(folders.map((folder, index) => ({ uri: URI.file(folder), name: names ? names[index] : undefined } as IWorkspaceFolderCreationData)));
|
||||
}
|
||||
|
||||
const environmentService = new TestEnvironmentService(parseArgs(process.argv), process.execPath);
|
||||
@@ -106,8 +106,8 @@ suite('WorkspacesMainService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('createWorkspace (folders as other resource URIs)', () => {
|
||||
return service.createWorkspace([{ uri: URI.from({ scheme: 'myScheme', path: process.cwd() }) }, { uri: URI.from({ scheme: 'myScheme', path: os.tmpdir() }) }]).then(workspace => {
|
||||
test('createUntitledWorkspace (folders as other resource URIs)', () => {
|
||||
return service.createUntitledWorkspace([{ uri: URI.from({ scheme: 'myScheme', path: process.cwd() }) }, { uri: URI.from({ scheme: 'myScheme', path: os.tmpdir() }) }]).then(workspace => {
|
||||
assert.ok(workspace);
|
||||
assert.ok(fs.existsSync(workspace.configPath));
|
||||
assert.ok(service.isUntitledWorkspace(workspace));
|
||||
@@ -152,8 +152,8 @@ suite('WorkspacesMainService', () => {
|
||||
assert.equal((<IRawFileWorkspaceFolder>ws.folders[1]).name, 'tempdir');
|
||||
});
|
||||
|
||||
test('createWorkspaceSync (folders as other resource URIs)', () => {
|
||||
const workspace = service.createWorkspaceSync([{ uri: URI.from({ scheme: 'myScheme', path: process.cwd() }) }, { uri: URI.from({ scheme: 'myScheme', path: os.tmpdir() }) }]);
|
||||
test('createUntitledWorkspaceSync (folders as other resource URIs)', () => {
|
||||
const workspace = service.createUntitledWorkspaceSync([{ uri: URI.from({ scheme: 'myScheme', path: process.cwd() }) }, { uri: URI.from({ scheme: 'myScheme', path: os.tmpdir() }) }]);
|
||||
assert.ok(workspace);
|
||||
assert.ok(fs.existsSync(workspace.configPath));
|
||||
assert.ok(service.isUntitledWorkspace(workspace));
|
||||
@@ -177,9 +177,9 @@ suite('WorkspacesMainService', () => {
|
||||
workspace.configPath = newPath;
|
||||
|
||||
const resolved = service.resolveWorkspaceSync(workspace.configPath);
|
||||
assert.equal(2, resolved.folders.length);
|
||||
assert.equal(resolved.configPath, workspace.configPath);
|
||||
assert.ok(resolved.id);
|
||||
assert.equal(2, resolved!.folders.length);
|
||||
assert.equal(resolved!.configPath, workspace.configPath);
|
||||
assert.ok(resolved!.id);
|
||||
|
||||
fs.writeFileSync(workspace.configPath, JSON.stringify({ something: 'something' })); // invalid workspace
|
||||
const resolvedInvalid = service.resolveWorkspaceSync(workspace.configPath);
|
||||
@@ -192,7 +192,7 @@ suite('WorkspacesMainService', () => {
|
||||
fs.writeFileSync(workspace.configPath, JSON.stringify({ folders: [{ path: './ticino-playground/lib' }] }));
|
||||
|
||||
const resolved = service.resolveWorkspaceSync(workspace.configPath);
|
||||
assert.equal(resolved.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'lib')).fsPath);
|
||||
assert.equal(resolved!.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'lib')).fsPath);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -201,7 +201,7 @@ suite('WorkspacesMainService', () => {
|
||||
fs.writeFileSync(workspace.configPath, JSON.stringify({ folders: [{ path: './ticino-playground/lib/../other' }] }));
|
||||
|
||||
const resolved = service.resolveWorkspaceSync(workspace.configPath);
|
||||
assert.equal(resolved.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'other')).fsPath);
|
||||
assert.equal(resolved!.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'other')).fsPath);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -210,7 +210,7 @@ suite('WorkspacesMainService', () => {
|
||||
fs.writeFileSync(workspace.configPath, JSON.stringify({ folders: [{ path: 'ticino-playground/lib' }] }));
|
||||
|
||||
const resolved = service.resolveWorkspaceSync(workspace.configPath);
|
||||
assert.equal(resolved.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'lib')).fsPath);
|
||||
assert.equal(resolved!.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'lib')).fsPath);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -219,45 +219,25 @@ suite('WorkspacesMainService', () => {
|
||||
fs.writeFileSync(workspace.configPath, '{ "folders": [ { "path": "./ticino-playground/lib" } , ] }'); // trailing comma
|
||||
|
||||
const resolved = service.resolveWorkspaceSync(workspace.configPath);
|
||||
assert.equal(resolved.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'lib')).fsPath);
|
||||
assert.equal(resolved!.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'lib')).fsPath);
|
||||
});
|
||||
});
|
||||
|
||||
test('saveWorkspace (untitled)', () => {
|
||||
let savedEvent: IWorkspaceSavedEvent;
|
||||
const listener = service.onWorkspaceSaved(e => {
|
||||
savedEvent = e;
|
||||
});
|
||||
|
||||
let deletedEvent: IWorkspaceIdentifier;
|
||||
const listener2 = service.onUntitledWorkspaceDeleted(e => {
|
||||
deletedEvent = e;
|
||||
});
|
||||
|
||||
return createWorkspace([process.cwd(), os.tmpdir(), path.join(os.tmpdir(), 'somefolder')]).then(workspace => {
|
||||
const workspaceConfigPath = path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`);
|
||||
|
||||
return service.saveWorkspace(workspace, workspaceConfigPath).then(savedWorkspace => {
|
||||
return service.saveWorkspaceAs(workspace, workspaceConfigPath).then(savedWorkspace => {
|
||||
assert.ok(savedWorkspace.id);
|
||||
assert.notEqual(savedWorkspace.id, workspace.id);
|
||||
assert.equal(savedWorkspace.configPath, workspaceConfigPath);
|
||||
|
||||
assert.equal(service.deleteWorkspaceCall, workspace);
|
||||
|
||||
const ws = JSON.parse(fs.readFileSync(savedWorkspace.configPath).toString()) as IStoredWorkspace;
|
||||
assert.equal(ws.folders.length, 3);
|
||||
assertPathEquals((<IRawFileWorkspaceFolder>ws.folders[0]).path, process.cwd()); // absolute
|
||||
assertPathEquals((<IRawFileWorkspaceFolder>ws.folders[1]).path, '.'); // relative
|
||||
assertPathEquals((<IRawFileWorkspaceFolder>ws.folders[2]).path, path.relative(path.dirname(workspaceConfigPath), path.join(os.tmpdir(), 'somefolder'))); // relative
|
||||
|
||||
assert.equal(savedWorkspace, savedEvent.workspace);
|
||||
assertPathEquals(workspace.configPath, savedEvent.oldConfigPath);
|
||||
|
||||
assert.deepEqual(deletedEvent, workspace);
|
||||
|
||||
listener.dispose();
|
||||
listener2.dispose();
|
||||
|
||||
extfs.delSync(workspaceConfigPath);
|
||||
});
|
||||
});
|
||||
@@ -268,8 +248,8 @@ suite('WorkspacesMainService', () => {
|
||||
const workspaceConfigPath = path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`);
|
||||
const newWorkspaceConfigPath = path.join(os.tmpdir(), `mySavedWorkspace.${Date.now()}.${WORKSPACE_EXTENSION}`);
|
||||
|
||||
return service.saveWorkspace(workspace, workspaceConfigPath).then(savedWorkspace => {
|
||||
return service.saveWorkspace(savedWorkspace, newWorkspaceConfigPath).then(newSavedWorkspace => {
|
||||
return service.saveWorkspaceAs(workspace, workspaceConfigPath).then(savedWorkspace => {
|
||||
return service.saveWorkspaceAs(savedWorkspace, newWorkspaceConfigPath).then(newSavedWorkspace => {
|
||||
assert.ok(newSavedWorkspace.id);
|
||||
assert.notEqual(newSavedWorkspace.id, workspace.id);
|
||||
assertPathEquals(newSavedWorkspace.configPath, newWorkspaceConfigPath);
|
||||
@@ -292,11 +272,11 @@ suite('WorkspacesMainService', () => {
|
||||
const workspaceConfigPath = path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`);
|
||||
const newWorkspaceConfigPath = path.join(os.tmpdir(), `mySavedWorkspace.${Date.now()}.${WORKSPACE_EXTENSION}`);
|
||||
|
||||
return service.saveWorkspace(workspace, workspaceConfigPath).then(savedWorkspace => {
|
||||
return service.saveWorkspaceAs(workspace, workspaceConfigPath).then(savedWorkspace => {
|
||||
const contents = fs.readFileSync(savedWorkspace.configPath).toString();
|
||||
fs.writeFileSync(savedWorkspace.configPath, `// this is a comment\n${contents}`);
|
||||
|
||||
return service.saveWorkspace(savedWorkspace, newWorkspaceConfigPath).then(newSavedWorkspace => {
|
||||
return service.saveWorkspaceAs(savedWorkspace, newWorkspaceConfigPath).then(newSavedWorkspace => {
|
||||
assert.ok(newSavedWorkspace.id);
|
||||
assert.notEqual(newSavedWorkspace.id, workspace.id);
|
||||
assertPathEquals(newSavedWorkspace.configPath, newWorkspaceConfigPath);
|
||||
@@ -316,11 +296,11 @@ suite('WorkspacesMainService', () => {
|
||||
const workspaceConfigPath = path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`);
|
||||
const newWorkspaceConfigPath = path.join(os.tmpdir(), `mySavedWorkspace.${Date.now()}.${WORKSPACE_EXTENSION}`);
|
||||
|
||||
return service.saveWorkspace(workspace, workspaceConfigPath).then(savedWorkspace => {
|
||||
return service.saveWorkspaceAs(workspace, workspaceConfigPath).then(savedWorkspace => {
|
||||
const contents = fs.readFileSync(savedWorkspace.configPath).toString();
|
||||
fs.writeFileSync(savedWorkspace.configPath, contents.replace(/[\\]/g, '/')); // convert backslash to slash
|
||||
|
||||
return service.saveWorkspace(savedWorkspace, newWorkspaceConfigPath).then(newSavedWorkspace => {
|
||||
return service.saveWorkspaceAs(savedWorkspace, newWorkspaceConfigPath).then(newSavedWorkspace => {
|
||||
assert.ok(newSavedWorkspace.id);
|
||||
assert.notEqual(newSavedWorkspace.id, workspace.id);
|
||||
assertPathEquals(newSavedWorkspace.configPath, newWorkspaceConfigPath);
|
||||
@@ -349,7 +329,7 @@ suite('WorkspacesMainService', () => {
|
||||
return createWorkspace([process.cwd(), os.tmpdir()]).then(workspace => {
|
||||
const workspaceConfigPath = path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`);
|
||||
|
||||
return service.saveWorkspace(workspace, workspaceConfigPath).then(savedWorkspace => {
|
||||
return service.saveWorkspaceAs(workspace, workspaceConfigPath).then(savedWorkspace => {
|
||||
assert.ok(fs.existsSync(savedWorkspace.configPath));
|
||||
|
||||
service.deleteUntitledWorkspaceSync(savedWorkspace);
|
||||
|
||||
Reference in New Issue
Block a user