Merge from master

This commit is contained in:
Raj Musuku
2019-02-21 17:56:04 -08:00
parent 5a146e34fa
commit 666ae11639
11482 changed files with 119352 additions and 255574 deletions

View File

@@ -3,21 +3,12 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { TPromise } from 'vs/base/common/winjs.base';
import { isParent } from 'vs/platform/files/common/files';
import { localize } from 'vs/nls';
import { basename, dirname, join } from 'vs/base/common/paths';
import { isLinux } from 'vs/base/common/platform';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { Event } from 'vs/base/common/event';
import { getBaseLabel } from 'vs/base/common/labels';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import URI from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import { IUriDisplayService } from 'vs/platform/uriDisplay/common/uriDisplay';
import { IWorkspaceFolder, IWorkspace } from 'vs/platform/workspace/common/workspace';
import { URI } from 'vs/base/common/uri';
export const IWorkspacesMainService = createDecorator<IWorkspacesMainService>('workspacesMainService');
export const IWorkspacesService = createDecorator<IWorkspacesService>('workspacesService');
@@ -94,9 +85,9 @@ export interface IWorkspacesMainService extends IWorkspacesService {
createWorkspaceSync(folders?: IWorkspaceFolderCreationData[]): IWorkspaceIdentifier;
resolveWorkspace(path: string): TPromise<IResolvedWorkspace>;
resolveWorkspace(path: string): TPromise<IResolvedWorkspace | null>;
resolveWorkspaceSync(path: string): IResolvedWorkspace;
resolveWorkspaceSync(path: string): IResolvedWorkspace | null;
isUntitledWorkspace(workspace: IWorkspaceIdentifier): boolean;
@@ -113,34 +104,6 @@ export interface IWorkspacesService {
createWorkspace(folders?: IWorkspaceFolderCreationData[]): TPromise<IWorkspaceIdentifier>;
}
export function getWorkspaceLabel(workspace: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier), environmentService: IEnvironmentService, uriDisplayService: IUriDisplayService, options?: { verbose: boolean }): string {
// Workspace: Single Folder
if (isSingleFolderWorkspaceIdentifier(workspace)) {
// Folder on disk
if (workspace.scheme === Schemas.file) {
return options && options.verbose ? uriDisplayService.getLabel(workspace) : getBaseLabel(workspace);
}
// Remote folder
return options && options.verbose ? uriDisplayService.getLabel(workspace) : `${getBaseLabel(workspace)} (${workspace.scheme})`;
}
// Workspace: Untitled
if (isParent(workspace.configPath, environmentService.workspacesHome, !isLinux /* ignore case */)) {
return localize('untitledWorkspace', "Untitled (Workspace)");
}
// Workspace: Saved
const filename = basename(workspace.configPath);
const workspaceName = filename.substr(0, filename.length - WORKSPACE_EXTENSION.length - 1);
if (options && options.verbose) {
return localize('workspaceNameVerbose', "{0} (Workspace)", uriDisplayService.getLabel(URI.file(join(dirname(workspace.configPath), workspaceName))));
}
return localize('workspaceName', "{0} (Workspace)", workspaceName);
}
export function isSingleFolderWorkspaceIdentifier(obj: any): obj is ISingleFolderWorkspaceIdentifier {
return obj instanceof URI;
}
@@ -150,3 +113,28 @@ export function isWorkspaceIdentifier(obj: any): obj is IWorkspaceIdentifier {
return workspaceIdentifier && typeof workspaceIdentifier.id === 'string' && typeof workspaceIdentifier.configPath === 'string';
}
export function toWorkspaceIdentifier(workspace: IWorkspace): IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | undefined {
if (workspace.configuration) {
return {
configPath: workspace.configuration.fsPath,
id: workspace.id
};
}
if (workspace.folders.length === 1) {
return workspace.folders[0].uri;
}
// Empty workspace
return undefined;
}
export type IMultiFolderWorkspaceInitializationPayload = IWorkspaceIdentifier;
export interface ISingleFolderWorkspaceInitializationPayload { id: string; folder: ISingleFolderWorkspaceIdentifier; }
export interface IEmptyWorkspaceInitializationPayload { id: string; }
export type IWorkspaceInitializationPayload = IMultiFolderWorkspaceInitializationPayload | ISingleFolderWorkspaceInitializationPayload | IEmptyWorkspaceInitializationPayload;
export function isSingleFolderWorkspaceInitializationPayload(obj: any): obj is ISingleFolderWorkspaceInitializationPayload {
return isSingleFolderWorkspaceIdentifier((obj.folder as ISingleFolderWorkspaceIdentifier));
}

View File

@@ -3,15 +3,13 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
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 { isParent } from 'vs/platform/files/common/files';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { extname, join, dirname, isAbsolute, resolve } from 'path';
import { mkdirp, writeFile, readFile } from 'vs/base/node/pfs';
import { readFileSync, existsSync, mkdirSync } from 'fs';
import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
import { isLinux, isMacintosh } from 'vs/base/common/platform';
import { delSync, readdirSync, writeFileAndFlushSync } from 'vs/base/node/extfs';
import { Event, Emitter } from 'vs/base/common/event';
@@ -21,44 +19,38 @@ 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 { applyEdit } from 'vs/base/common/jsonFormatter';
import { massageFolderPathForWorkspace } from 'vs/platform/workspaces/node/workspaces';
import { toWorkspaceFolders } from 'vs/platform/workspace/common/workspace';
import URI from 'vs/base/common/uri';
import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import { Disposable } from 'vs/base/common/lifecycle';
export interface IStoredWorkspace {
folders: IStoredWorkspaceFolder[];
}
export class WorkspacesMainService implements IWorkspacesMainService {
export class WorkspacesMainService extends Disposable implements IWorkspacesMainService {
_serviceBrand: any;
protected workspacesHome: string;
private workspacesHome: string;
private readonly _onWorkspaceSaved: Emitter<IWorkspaceSavedEvent>;
private readonly _onUntitledWorkspaceDeleted: Emitter<IWorkspaceIdentifier>;
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
) {
super();
this.workspacesHome = environmentService.workspacesHome;
this._onWorkspaceSaved = new Emitter<IWorkspaceSavedEvent>();
this._onUntitledWorkspaceDeleted = new Emitter<IWorkspaceIdentifier>();
}
get onWorkspaceSaved(): Event<IWorkspaceSavedEvent> {
return this._onWorkspaceSaved.event;
}
get onUntitledWorkspaceDeleted(): Event<IWorkspaceIdentifier> {
return this._onUntitledWorkspaceDeleted.event;
}
resolveWorkspace(path: string): TPromise<IResolvedWorkspace> {
resolveWorkspace(path: string): TPromise<IResolvedWorkspace | null> {
if (!this.isWorkspacePath(path)) {
return TPromise.as(null); // does not look like a valid workspace config file
}
@@ -66,7 +58,7 @@ export class WorkspacesMainService implements IWorkspacesMainService {
return readFile(path, 'utf8').then(contents => this.doResolveWorkspace(path, contents));
}
resolveWorkspaceSync(path: string): IResolvedWorkspace {
resolveWorkspaceSync(path: string): IResolvedWorkspace | null {
if (!this.isWorkspacePath(path)) {
return null; // does not look like a valid workspace config file
}
@@ -85,7 +77,7 @@ export class WorkspacesMainService implements IWorkspacesMainService {
return this.isInsideWorkspacesHome(path) || extname(path) === `.${WORKSPACE_EXTENSION}`;
}
private doResolveWorkspace(path: string, contents: string): IResolvedWorkspace {
private doResolveWorkspace(path: string, contents: string): IResolvedWorkspace | null {
try {
const workspace = this.doParseStoredWorkspace(path, contents);
@@ -233,7 +225,7 @@ export class WorkspacesMainService implements IWorkspacesMainService {
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 = applyEdit(rawWorkspaceContents, edit);
newRawWorkspaceContents = jsonEdit.applyEdit(rawWorkspaceContents, edit);
});
return writeFile(targetConfigPath, newRawWorkspaceContents).then(() => {
@@ -264,7 +256,15 @@ export class WorkspacesMainService implements IWorkspacesMainService {
private doDeleteUntitledWorkspaceSync(configPath: string): void {
try {
// Delete Workspace
delSync(dirname(configPath));
// Mark Workspace Storage to be deleted
const workspaceStoragePath = join(this.environmentService.workspaceStorageHome, this.getWorkspaceId(configPath));
if (existsSync(workspaceStoragePath)) {
writeFileSync(join(workspaceStoragePath, 'obsolete'), '');
}
} catch (error) {
this.logService.warn(`Unable to delete untitled workspace ${configPath} (${error}).`);
}

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IStoredWorkspaceFolder, isRawFileWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces';
import { isWindows, isLinux } from 'vs/base/common/platform';
import { isAbsolute, relative } from 'path';

View File

@@ -3,32 +3,25 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
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';
import { URI } from 'vs/base/common/uri';
import { Event } from 'vs/base/common/event';
export interface IWorkspacesChannel extends IChannel {
call(command: 'createWorkspace', arg: [IWorkspaceFolderCreationData[]]): TPromise<string>;
call(command: string, arg?: any): TPromise<any>;
}
export class WorkspacesChannel implements IWorkspacesChannel {
export class WorkspacesChannel implements IServerChannel {
constructor(private service: IWorkspacesMainService) { }
listen<T>(event: string, arg?: any): Event<T> {
throw new Error('No events');
listen<T>(_, event: string): Event<T> {
throw new Error(`Event not found: ${event}`);
}
call(command: string, arg?: any): TPromise<any> {
call(_, command: string, arg?: any): Thenable<any> {
switch (command) {
case 'createWorkspace': {
const rawFolders: IWorkspaceFolderCreationData[] = arg;
let folders: IWorkspaceFolderCreationData[];
let folders: IWorkspaceFolderCreationData[] | undefined = undefined;
if (Array.isArray(rawFolders)) {
folders = rawFolders.map(rawFolder => {
return {
@@ -42,7 +35,7 @@ export class WorkspacesChannel implements IWorkspacesChannel {
}
}
return void 0;
throw new Error(`Call not found: ${command}`);
}
}
@@ -50,9 +43,9 @@ export class WorkspacesChannelClient implements IWorkspacesService {
_serviceBrand: any;
constructor(private channel: IWorkspacesChannel) { }
constructor(private channel: IChannel) { }
createWorkspace(folders?: IWorkspaceFolderCreationData[]): TPromise<IWorkspaceIdentifier> {
return this.channel.call('createWorkspace', folders);
return TPromise.wrap(this.channel.call('createWorkspace', folders));
}
}

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import * as fs from 'fs';
import * as os from 'os';
@@ -16,7 +14,7 @@ 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 { NullLogService } from 'vs/platform/log/common/log';
import URI from 'vs/base/common/uri';
import { URI } from 'vs/base/common/uri';
import { getRandomTestPath } from 'vs/workbench/test/workbenchTestServices';
import { isWindows } from 'vs/base/common/platform';
import { normalizeDriveLetter } from 'vs/base/common/labels';
@@ -366,14 +364,22 @@ suite('WorkspacesMainService', () => {
assert.equal(0, untitled.length);
return createWorkspace([process.cwd(), os.tmpdir()]).then(untitledOne => {
assert.ok(fs.existsSync(untitledOne.configPath));
untitled = service.getUntitledWorkspacesSync();
assert.equal(1, untitled.length);
assert.equal(untitledOne.id, untitled[0].id);
return createWorkspace([os.tmpdir(), process.cwd()]).then(untitledTwo => {
assert.ok(fs.existsSync(untitledTwo.configPath));
untitled = service.getUntitledWorkspacesSync();
if (untitled.length === 1) {
assert.fail('Unexpected workspaces count, contents:\n' + fs.readFileSync(untitledTwo.configPath, 'utf8'));
}
assert.equal(2, untitled.length);
service.deleteUntitledWorkspaceSync(untitledOne);