mirror of
https://github.com/Microsoft/vscode
synced 2024-10-12 14:30:13 +00:00
more adoption of IWorkspace2
This commit is contained in:
parent
77bf512f0e
commit
f2e1911761
|
@ -11,8 +11,7 @@ import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlighte
|
|||
import { IMatch } from 'vs/base/common/filters';
|
||||
import uri from 'vs/base/common/uri';
|
||||
import paths = require('vs/base/common/paths');
|
||||
import types = require('vs/base/common/types');
|
||||
import { IWorkspaceProvider, getPathLabel, IUserHomeProvider } from 'vs/base/common/labels';
|
||||
import { IRootProvider, getPathLabel, IUserHomeProvider } from 'vs/base/common/labels';
|
||||
|
||||
export interface IIconLabelCreationOptions {
|
||||
supportHighlights?: boolean;
|
||||
|
@ -99,30 +98,15 @@ export class IconLabel {
|
|||
|
||||
export class FileLabel extends IconLabel {
|
||||
|
||||
constructor(container: HTMLElement, file: uri, provider: IWorkspaceProvider, userHome?: IUserHomeProvider) {
|
||||
constructor(container: HTMLElement, file: uri, provider: IRootProvider, userHome?: IUserHomeProvider) {
|
||||
super(container);
|
||||
|
||||
this.setFile(file, provider, userHome);
|
||||
}
|
||||
|
||||
public setFile(file: uri, provider: IWorkspaceProvider, userHome: IUserHomeProvider): void {
|
||||
const path = getPath(file);
|
||||
const parent = paths.dirname(path);
|
||||
public setFile(file: uri, provider: IRootProvider, userHome: IUserHomeProvider): void {
|
||||
const parent = paths.dirname(file.fsPath);
|
||||
|
||||
this.setValue(paths.basename(path), parent && parent !== '.' ? getPathLabel(parent, provider, userHome) : '', { title: path });
|
||||
this.setValue(paths.basename(file.fsPath), parent && parent !== '.' ? getPathLabel(parent, provider, userHome) : '', { title: file.fsPath });
|
||||
}
|
||||
}
|
||||
|
||||
function getPath(arg1: uri | IWorkspaceProvider): string {
|
||||
if (!arg1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (types.isFunction((<IWorkspaceProvider>arg1).getWorkspace)) {
|
||||
const ws = (<IWorkspaceProvider>arg1).getWorkspace();
|
||||
|
||||
return ws ? ws.resource.fsPath : void 0;
|
||||
}
|
||||
|
||||
return (<uri>arg1).fsPath;
|
||||
}
|
|
@ -6,8 +6,7 @@
|
|||
|
||||
import URI from 'vs/base/common/uri';
|
||||
import platform = require('vs/base/common/platform');
|
||||
import types = require('vs/base/common/types');
|
||||
import { nativeSep, normalize, isEqualOrParent, isEqual } from 'vs/base/common/paths';
|
||||
import { nativeSep, normalize, isEqualOrParent, isEqual, basename, join } from 'vs/base/common/paths';
|
||||
import { endsWith, ltrim } from 'vs/base/common/strings';
|
||||
|
||||
export interface ILabelProvider {
|
||||
|
@ -18,9 +17,10 @@ export interface ILabelProvider {
|
|||
getLabel(element: any): string;
|
||||
}
|
||||
|
||||
export interface IWorkspaceProvider {
|
||||
getWorkspace(): {
|
||||
resource: URI;
|
||||
export interface IRootProvider {
|
||||
getRoot(resource: URI): URI;
|
||||
getWorkspace2(): {
|
||||
roots: URI[];
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -28,27 +28,42 @@ export interface IUserHomeProvider {
|
|||
userHome: string;
|
||||
}
|
||||
|
||||
export function getPathLabel(resource: URI | string, basePathProvider?: URI | string | IWorkspaceProvider, userHomeProvider?: IUserHomeProvider): string {
|
||||
const absolutePath = getPath(resource);
|
||||
if (!absolutePath) {
|
||||
export function getPathLabel(resource: URI | string, rootProvider?: IRootProvider, userHomeProvider?: IUserHomeProvider): string {
|
||||
if (!resource) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const basepath = basePathProvider && getPath(basePathProvider);
|
||||
if (typeof resource === 'string') {
|
||||
resource = URI.file(resource);
|
||||
}
|
||||
|
||||
if (basepath && isEqualOrParent(absolutePath, basepath, !platform.isLinux /* ignorecase */)) {
|
||||
if (isEqual(basepath, absolutePath, !platform.isLinux /* ignorecase */)) {
|
||||
return ''; // no label if pathes are identical
|
||||
// return early if we can resolve a relative path label from the root
|
||||
const baseResource = rootProvider ? rootProvider.getRoot(resource) : null;
|
||||
if (baseResource) {
|
||||
const hasMultipleRoots = rootProvider.getWorkspace2().roots.length > 1;
|
||||
|
||||
let pathLabel: string;
|
||||
if (isEqual(baseResource.fsPath, resource.fsPath, !platform.isLinux /* ignorecase */)) {
|
||||
pathLabel = ''; // no label if pathes are identical
|
||||
} else {
|
||||
pathLabel = normalize(ltrim(resource.fsPath.substr(baseResource.fsPath.length), nativeSep), true);
|
||||
}
|
||||
|
||||
return normalize(ltrim(absolutePath.substr(basepath.length), nativeSep), true);
|
||||
if (hasMultipleRoots) {
|
||||
const rootName = basename(baseResource.fsPath);
|
||||
pathLabel = pathLabel ? join(rootName, pathLabel) : rootName; // always show root basename if there are multiple
|
||||
}
|
||||
|
||||
return pathLabel;
|
||||
}
|
||||
|
||||
if (platform.isWindows && absolutePath && absolutePath[1] === ':') {
|
||||
return normalize(absolutePath.charAt(0).toUpperCase() + absolutePath.slice(1), true); // convert c:\something => C:\something
|
||||
// convert c:\something => C:\something
|
||||
if (platform.isWindows && resource.fsPath && resource.fsPath[1] === ':') {
|
||||
return normalize(resource.fsPath.charAt(0).toUpperCase() + resource.fsPath.slice(1), true);
|
||||
}
|
||||
|
||||
let res = normalize(absolutePath, true);
|
||||
// normalize and tildify (macOS, Linux only)
|
||||
let res = normalize(resource.fsPath, true);
|
||||
if (!platform.isWindows && userHomeProvider) {
|
||||
res = tildify(res, userHomeProvider.userHome);
|
||||
}
|
||||
|
@ -56,23 +71,6 @@ export function getPathLabel(resource: URI | string, basePathProvider?: URI | st
|
|||
return res;
|
||||
}
|
||||
|
||||
function getPath(arg1: URI | string | IWorkspaceProvider): string {
|
||||
if (!arg1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof arg1 === 'string') {
|
||||
return arg1;
|
||||
}
|
||||
|
||||
if (types.isFunction((<IWorkspaceProvider>arg1).getWorkspace)) {
|
||||
const ws = (<IWorkspaceProvider>arg1).getWorkspace();
|
||||
return ws ? ws.resource.fsPath : void 0;
|
||||
}
|
||||
|
||||
return (<URI>arg1).fsPath;
|
||||
}
|
||||
|
||||
export function tildify(path: string, userHome: string): string {
|
||||
if (path && (platform.isMacintosh || platform.isLinux) && isEqualOrParent(path, userHome, !platform.isLinux /* ignorecase */)) {
|
||||
path = `~${path.substr(userHome.length)}`;
|
||||
|
|
|
@ -10,7 +10,7 @@ import Event, { Emitter } from 'vs/base/common/event';
|
|||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IExtensionManagementService, DidUninstallExtensionEvent, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { adoptToGalleryExtensionId, getIdAndVersionFromLocalExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { IWorkspaceContextService, ILegacyWorkspace } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
|
||||
|
@ -34,8 +34,8 @@ export class ExtensionEnablementService implements IExtensionEnablementService {
|
|||
extensionManagementService.onDidUninstallExtension(this.onDidUninstallExtension, this, this.disposables);
|
||||
}
|
||||
|
||||
private get workspace(): ILegacyWorkspace {
|
||||
return this.contextService.getWorkspace();
|
||||
private get hasWorkspace(): boolean {
|
||||
return this.contextService.hasWorkspace();
|
||||
}
|
||||
|
||||
public getGloballyDisabledExtensions(): string[] {
|
||||
|
@ -60,7 +60,7 @@ export class ExtensionEnablementService implements IExtensionEnablementService {
|
|||
}
|
||||
|
||||
public setEnablement(identifier: string, enable: boolean, workspace: boolean = false): TPromise<boolean> {
|
||||
if (workspace && !this.workspace) {
|
||||
if (workspace && !this.hasWorkspace) {
|
||||
return TPromise.wrapError<boolean>(localize('noWorkspace', "No workspace."));
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ export class ExtensionEnablementService implements IExtensionEnablementService {
|
|||
}
|
||||
|
||||
private getDisabledExtensions(scope: StorageScope): string[] {
|
||||
if (scope === StorageScope.WORKSPACE && !this.workspace) {
|
||||
if (scope === StorageScope.WORKSPACE && !this.hasWorkspace) {
|
||||
return [];
|
||||
}
|
||||
const value = this.storageService.get(DISABLED_EXTENSIONS_STORAGE_PATH, scope, '');
|
||||
|
|
|
@ -69,7 +69,7 @@ suite('ExtensionEnablementService Test', () => {
|
|||
test('test when no extensions are disabled for workspace when there is no workspace', (done) => {
|
||||
testObject.setEnablement('pub.a', false, true)
|
||||
.then(() => {
|
||||
instantiationService.stub(IWorkspaceContextService, 'getWorkspace', null);
|
||||
instantiationService.stub(IWorkspaceContextService, 'hasWorkspace', false);
|
||||
assert.deepEqual([], testObject.getWorkspaceDisabledExtensions());
|
||||
})
|
||||
.then(done, done);
|
||||
|
@ -174,7 +174,7 @@ suite('ExtensionEnablementService Test', () => {
|
|||
});
|
||||
|
||||
test('test disable an extension for workspace when there is no workspace throws error', (done) => {
|
||||
instantiationService.stub(IWorkspaceContextService, 'getWorkspace', null);
|
||||
instantiationService.stub(IWorkspaceContextService, 'hasWorkspace', false);
|
||||
testObject.setEnablement('pub.a', false, true)
|
||||
.then(() => assert.fail('should throw an error'), error => assert.ok(error))
|
||||
.then(done, done);
|
||||
|
|
|
@ -8,7 +8,7 @@ import types = require('vs/base/common/types');
|
|||
import errors = require('vs/base/common/errors');
|
||||
import strings = require('vs/base/common/strings');
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import URI from "vs/base/common/uri";
|
||||
import { IWorkspace } from "vs/platform/workspace/common/workspace";
|
||||
|
||||
// Browser localStorage interface
|
||||
export interface IStorage {
|
||||
|
@ -20,11 +20,6 @@ export interface IStorage {
|
|||
removeItem(key: string): void;
|
||||
}
|
||||
|
||||
export interface IWorkspaceStorageIdentifier {
|
||||
resource: URI;
|
||||
uid?: number;
|
||||
}
|
||||
|
||||
export class StorageService implements IStorageService {
|
||||
|
||||
public _serviceBrand: any;
|
||||
|
@ -43,36 +38,35 @@ export class StorageService implements IStorageService {
|
|||
constructor(
|
||||
globalStorage: IStorage,
|
||||
workspaceStorage: IStorage,
|
||||
workspaceIdentifier?: IWorkspaceStorageIdentifier
|
||||
workspace?: IWorkspace,
|
||||
legacyWorkspaceId?: number
|
||||
) {
|
||||
this.globalStorage = globalStorage;
|
||||
this.workspaceStorage = workspaceStorage || globalStorage;
|
||||
|
||||
// Calculate workspace storage key
|
||||
this.workspaceKey = this.getWorkspaceKey(workspaceIdentifier ? workspaceIdentifier.resource : void 0);
|
||||
this.workspaceKey = this.getWorkspaceKey(workspace ? workspace.id : void 0);
|
||||
|
||||
// Make sure to delete all workspace storage if the workspace has been recreated meanwhile
|
||||
// which is only possible if a UID property is provided that we can check on
|
||||
if (workspaceIdentifier && types.isNumber(workspaceIdentifier.uid)) {
|
||||
this.cleanupWorkspaceScope(workspaceIdentifier.uid);
|
||||
// which is only possible if a id property is provided that we can check on
|
||||
if (workspace && types.isNumber(legacyWorkspaceId)) {
|
||||
this.cleanupWorkspaceScope(legacyWorkspaceId);
|
||||
}
|
||||
}
|
||||
|
||||
private getWorkspaceKey(workspaceId?: URI): string {
|
||||
if (!workspaceId) {
|
||||
private getWorkspaceKey(id?: string): string {
|
||||
if (!id) {
|
||||
return StorageService.NO_WORKSPACE_IDENTIFIER;
|
||||
}
|
||||
|
||||
let workspaceIdStr = workspaceId.toString();
|
||||
|
||||
// Special case file:// URIs: strip protocol from key to produce shorter key
|
||||
const fileProtocol = 'file:///';
|
||||
if (workspaceIdStr.indexOf(fileProtocol) === 0) {
|
||||
workspaceIdStr = workspaceIdStr.substr(fileProtocol.length);
|
||||
if (id.indexOf(fileProtocol) === 0) {
|
||||
id = id.substr(fileProtocol.length);
|
||||
}
|
||||
|
||||
// Always end with "/"
|
||||
return `${strings.rtrim(workspaceIdStr, '/')}/`;
|
||||
return `${strings.rtrim(id, '/')}/`;
|
||||
}
|
||||
|
||||
private cleanupWorkspaceScope(workspaceUid: number): void {
|
||||
|
|
|
@ -8,14 +8,13 @@
|
|||
import * as assert from 'assert';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { IWorkspaceContextService, LegacyWorkspace } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { StorageService, InMemoryLocalStorage } from 'vs/platform/storage/common/storageService';
|
||||
import { TestContextService } from 'vs/workbench/test/workbenchTestServices';
|
||||
import { TestWorkspace } from 'vs/platform/workspace/test/common/testWorkspace';
|
||||
|
||||
suite('Workbench StorageSevice', () => {
|
||||
|
||||
let contextService, instantiationService;
|
||||
let contextService: IWorkspaceContextService;
|
||||
let instantiationService: TestInstantiationService;
|
||||
|
||||
setup(() => {
|
||||
instantiationService = new TestInstantiationService();
|
||||
|
@ -23,7 +22,7 @@ suite('Workbench StorageSevice', () => {
|
|||
});
|
||||
|
||||
test('Swap Data with undefined default value', () => {
|
||||
let s = new StorageService(new InMemoryLocalStorage(), null, contextService.getWorkspace());
|
||||
let s = new StorageService(new InMemoryLocalStorage(), null, contextService.getWorkspace2());
|
||||
|
||||
s.swap('Monaco.IDE.Core.Storage.Test.swap', 'foobar', 'barfoo');
|
||||
assert.strictEqual('foobar', s.get('Monaco.IDE.Core.Storage.Test.swap'));
|
||||
|
@ -34,7 +33,7 @@ suite('Workbench StorageSevice', () => {
|
|||
});
|
||||
|
||||
test('Remove Data', () => {
|
||||
let s = new StorageService(new InMemoryLocalStorage(), null, contextService.getWorkspace());
|
||||
let s = new StorageService(new InMemoryLocalStorage(), null, contextService.getWorkspace2());
|
||||
s.store('Monaco.IDE.Core.Storage.Test.remove', 'foobar');
|
||||
assert.strictEqual('foobar', s.get('Monaco.IDE.Core.Storage.Test.remove'));
|
||||
|
||||
|
@ -43,7 +42,7 @@ suite('Workbench StorageSevice', () => {
|
|||
});
|
||||
|
||||
test('Get Data, Integer, Boolean', () => {
|
||||
let s = new StorageService(new InMemoryLocalStorage(), null, contextService.getWorkspace());
|
||||
let s = new StorageService(new InMemoryLocalStorage(), null, contextService.getWorkspace2());
|
||||
|
||||
assert.strictEqual(s.get('Monaco.IDE.Core.Storage.Test.get', StorageScope.GLOBAL, 'foobar'), 'foobar');
|
||||
assert.strictEqual(s.get('Monaco.IDE.Core.Storage.Test.get', StorageScope.GLOBAL, ''), '');
|
||||
|
@ -77,16 +76,15 @@ suite('Workbench StorageSevice', () => {
|
|||
|
||||
test('StorageSevice cleans up when workspace changes', () => {
|
||||
let storageImpl = new InMemoryLocalStorage();
|
||||
let ws = contextService.getWorkspace();
|
||||
ws.uid = new Date().getTime();
|
||||
let s = new StorageService(storageImpl, null, ws);
|
||||
let time = new Date().getTime();
|
||||
let s = new StorageService(storageImpl, null, contextService.getWorkspace2(), time);
|
||||
|
||||
s.store('key1', 'foobar');
|
||||
s.store('key2', 'something');
|
||||
s.store('wkey1', 'foo', StorageScope.WORKSPACE);
|
||||
s.store('wkey2', 'foo2', StorageScope.WORKSPACE);
|
||||
|
||||
s = new StorageService(storageImpl, null, contextService.getWorkspace());
|
||||
s = new StorageService(storageImpl, null, contextService.getWorkspace2(), time);
|
||||
|
||||
assert.strictEqual(s.get('key1', StorageScope.GLOBAL), 'foobar');
|
||||
assert.strictEqual(s.get('key1', StorageScope.WORKSPACE, null), null);
|
||||
|
@ -95,9 +93,7 @@ suite('Workbench StorageSevice', () => {
|
|||
assert.strictEqual(s.get('wkey1', StorageScope.WORKSPACE), 'foo');
|
||||
assert.strictEqual(s.get('wkey2', StorageScope.WORKSPACE), 'foo2');
|
||||
|
||||
ws = new LegacyWorkspace(TestWorkspace.resource, Date.now());
|
||||
ws.uid = new Date().getTime() + 100;
|
||||
s = new StorageService(storageImpl, null, ws);
|
||||
s = new StorageService(storageImpl, null, contextService.getWorkspace2(), time + 100);
|
||||
|
||||
assert.strictEqual(s.get('key1', StorageScope.GLOBAL), 'foobar');
|
||||
assert.strictEqual(s.get('key1', StorageScope.WORKSPACE, null), null);
|
||||
|
|
|
@ -10,7 +10,6 @@ import { resolveWorkbenchCommonProperties } from 'vs/platform/telemetry/node/wor
|
|||
import { StorageService, InMemoryLocalStorage } from 'vs/platform/storage/common/storageService';
|
||||
import { TestWorkspace } from 'vs/platform/workspace/test/common/testWorkspace';
|
||||
|
||||
|
||||
suite('Telemetry - common properties', function () {
|
||||
|
||||
const commit = void 0;
|
||||
|
|
|
@ -56,7 +56,7 @@ export interface IWindowsService {
|
|||
getWindowCount(): TPromise<number>;
|
||||
log(severity: string, ...messages: string[]): TPromise<void>;
|
||||
// TODO@joao: what?
|
||||
closeExtensionHostWindow(extensionDevelopmentPath: string): TPromise<void>;
|
||||
closeExtensionHostWindow(extensionDevelopmentPaths: string[]): TPromise<void>;
|
||||
showItemInFolder(path: string): TPromise<void>;
|
||||
|
||||
// This needs to be handled from browser process to prevent
|
||||
|
|
|
@ -43,7 +43,7 @@ export interface IWindowsChannel extends IChannel {
|
|||
call(command: 'whenSharedProcessReady'): TPromise<void>;
|
||||
call(command: 'toggleSharedProcess'): TPromise<void>;
|
||||
call(command: 'log', arg: [string, string[]]): TPromise<void>;
|
||||
call(command: 'closeExtensionHostWindow', arg: string): TPromise<void>;
|
||||
call(command: 'closeExtensionHostWindow', arg: string[]): TPromise<void>;
|
||||
call(command: 'showItemInFolder', arg: string): TPromise<void>;
|
||||
call(command: 'openExternal', arg: string): TPromise<boolean>;
|
||||
call(command: 'startCrashReporter', arg: Electron.CrashReporterStartOptions): TPromise<void>;
|
||||
|
@ -235,8 +235,8 @@ export class WindowsChannelClient implements IWindowsService {
|
|||
return this.channel.call('log', [severity, messages]);
|
||||
}
|
||||
|
||||
closeExtensionHostWindow(extensionDevelopmentPath: string): TPromise<void> {
|
||||
return this.channel.call('closeExtensionHostWindow', extensionDevelopmentPath);
|
||||
closeExtensionHostWindow(extensionDevelopmentPaths: string[]): TPromise<void> {
|
||||
return this.channel.call('closeExtensionHostWindow', extensionDevelopmentPaths);
|
||||
}
|
||||
|
||||
showItemInFolder(path: string): TPromise<void> {
|
||||
|
|
|
@ -263,12 +263,12 @@ export class WindowsService implements IWindowsService, IDisposable {
|
|||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
closeExtensionHostWindow(extensionDevelopmentPath: string): TPromise<void> {
|
||||
const windowOnExtension = this.windowsMainService.findWindow(null, null, extensionDevelopmentPath);
|
||||
|
||||
if (windowOnExtension) {
|
||||
windowOnExtension.win.close();
|
||||
}
|
||||
closeExtensionHostWindow(extensionDevelopmentPaths: string[]): TPromise<void> {
|
||||
extensionDevelopmentPaths.map(p => this.windowsMainService.findWindow(null, null, p)).forEach(windowOnExtension => {
|
||||
if (windowOnExtension) {
|
||||
windowOnExtension.win.close();
|
||||
}
|
||||
});
|
||||
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { LegacyWorkspace } from 'vs/platform/workspace/common/workspace';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { Workspace } from "vs/platform/workspace/common/workspace";
|
||||
|
||||
export const TestWorkspace = new LegacyWorkspace(
|
||||
URI.file('C:\\testWorkspace'),
|
||||
Date.now()
|
||||
const wsUri = URI.file('C:\\testWorkspace');
|
||||
export const TestWorkspace = new Workspace(
|
||||
wsUri.toString(),
|
||||
wsUri.fsPath,
|
||||
[wsUri]
|
||||
);
|
||||
|
|
|
@ -49,13 +49,13 @@ export class MainThreadWorkspace extends MainThreadWorkspaceShape {
|
|||
// --- search ---
|
||||
|
||||
$startSearch(include: string, exclude: string, maxResults: number, requestId: number): Thenable<URI[]> {
|
||||
const workspace = this._contextService.getWorkspace();
|
||||
const workspace = this._contextService.getWorkspace2();
|
||||
if (!workspace) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const search = this._searchService.search({
|
||||
folderResources: [workspace.resource],
|
||||
folderResources: workspace.roots,
|
||||
type: QueryType.File,
|
||||
maxResults,
|
||||
includePattern: { [include]: true },
|
||||
|
|
|
@ -57,6 +57,7 @@ export class ResourceLabel extends IconLabel {
|
|||
private registerListeners(): void {
|
||||
this.extensionService.onReady().then(() => this.render(true /* clear cache */)); // update when extensions are loaded with potentially new languages
|
||||
this.toDispose.push(this.configurationService.onDidUpdateConfiguration(() => this.render(true /* clear cache */))); // update when file.associations change
|
||||
this.toDispose.push(this.contextService.onDidChangeWorkspaceRoots(() => this.render(true /* clear cache */))); // update when roots change
|
||||
}
|
||||
|
||||
public setLabel(label: IEditorLabel, options?: IResourceLabelOptions): void {
|
||||
|
|
|
@ -71,7 +71,7 @@ export class TitlebarPart extends Part implements ITitleService {
|
|||
|
||||
this.isPure = true;
|
||||
this.activeEditorListeners = [];
|
||||
this.workspacePath = contextService.hasWorkspace() ? labels.getPathLabel(contextService.getWorkspace().resource, void 0, environmentService) : '';
|
||||
this.computeWorkspacePath();
|
||||
|
||||
this.init();
|
||||
|
||||
|
@ -100,6 +100,7 @@ export class TitlebarPart extends Part implements ITitleService {
|
|||
this.toUnbind.push(DOM.addDisposableListener(window, DOM.EventType.FOCUS, () => this.onFocus()));
|
||||
this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(() => this.onConfigurationChanged(true)));
|
||||
this.toUnbind.push(this.editorGroupService.onEditorsChanged(() => this.onEditorsChanged()));
|
||||
this.toUnbind.push(this.contextService.onDidChangeWorkspaceRoots(() => this.onDidChangeWorkspaceRoots()));
|
||||
}
|
||||
|
||||
private onBlur(): void {
|
||||
|
@ -112,6 +113,20 @@ export class TitlebarPart extends Part implements ITitleService {
|
|||
this.updateStyles();
|
||||
}
|
||||
|
||||
private onDidChangeWorkspaceRoots(): void {
|
||||
this.computeWorkspacePath();
|
||||
this.setTitle(this.getWindowTitle());
|
||||
}
|
||||
|
||||
private computeWorkspacePath(): void {
|
||||
const workspace = this.contextService.getWorkspace2();
|
||||
if (workspace && workspace.roots.length === 1) {
|
||||
this.workspacePath = labels.getPathLabel(workspace.roots[0], void 0, this.environmentService);
|
||||
} else {
|
||||
this.workspacePath = '';
|
||||
}
|
||||
}
|
||||
|
||||
private onConfigurationChanged(update?: boolean): void {
|
||||
const currentTitleTemplate = this.titleTemplate;
|
||||
this.titleTemplate = this.configurationService.lookup<string>('window.title').value;
|
||||
|
|
|
@ -30,7 +30,7 @@ import { KeyboardMapperFactory } from "vs/workbench/services/keybinding/electron
|
|||
import { IWindowConfiguration, IPath } from "vs/platform/windows/common/windows";
|
||||
import { IStorageService } from "vs/platform/storage/common/storage";
|
||||
import { IEnvironmentService } from "vs/platform/environment/common/environment";
|
||||
import { StorageService, inMemoryLocalStorageInstance, IWorkspaceStorageIdentifier } from "vs/platform/storage/common/storageService";
|
||||
import { StorageService, inMemoryLocalStorageInstance } from "vs/platform/storage/common/storageService";
|
||||
|
||||
import { webFrame } from 'electron';
|
||||
|
||||
|
@ -97,10 +97,11 @@ function toInputs(paths: IPath[], isUntitledFile?: boolean): IResourceInput[] {
|
|||
|
||||
function openWorkbench(configuration: IWindowConfiguration, options: IOptions): TPromise<void> {
|
||||
return resolveLegacyWorkspace(configuration).then(legacyWorkspace => {
|
||||
const workspace = legacyWorkspaceToMultiRootWorkspace(legacyWorkspace);
|
||||
const environmentService = new EnvironmentService(configuration, configuration.execPath);
|
||||
const workspaceConfigurationService = new WorkspaceConfigurationService(environmentService, legacyWorkspaceToMultiRootWorkspace(legacyWorkspace));
|
||||
const timerService = new TimerService((<any>window).MonacoEnvironment.timers as IInitData, !!legacyWorkspace);
|
||||
const storageService = createStorageService(legacyWorkspace, configuration, environmentService);
|
||||
const workspaceConfigurationService = new WorkspaceConfigurationService(environmentService, workspace);
|
||||
const timerService = new TimerService((<any>window).MonacoEnvironment.timers as IInitData, !!workspace);
|
||||
const storageService = createStorageService(legacyWorkspace, workspace, configuration, environmentService);
|
||||
|
||||
// Since the configuration service is one of the core services that is used in so many places, we initialize it
|
||||
// right before startup of the workbench shell to have its data ready for consumers
|
||||
|
@ -135,11 +136,15 @@ function openWorkbench(configuration: IWindowConfiguration, options: IOptions):
|
|||
}
|
||||
|
||||
function legacyWorkspaceToMultiRootWorkspace(legacyWorkspace: LegacyWorkspace): Workspace {
|
||||
return legacyWorkspace ? new Workspace(
|
||||
if (!legacyWorkspace) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Workspace(
|
||||
createHash('md5').update(legacyWorkspace.resource.fsPath).update(legacyWorkspace.ctime ? String(legacyWorkspace.ctime) : '').digest('hex'),
|
||||
path.basename(legacyWorkspace.resource.fsPath),
|
||||
[legacyWorkspace.resource]
|
||||
) : null;
|
||||
);
|
||||
}
|
||||
|
||||
function resolveLegacyWorkspace(configuration: IWindowConfiguration): TPromise<LegacyWorkspace> {
|
||||
|
@ -172,10 +177,10 @@ function resolveLegacyWorkspace(configuration: IWindowConfiguration): TPromise<L
|
|||
});
|
||||
}
|
||||
|
||||
function createStorageService(workspace: LegacyWorkspace, configuration: IWindowConfiguration, environmentService: IEnvironmentService): IStorageService {
|
||||
let id: IWorkspaceStorageIdentifier;
|
||||
function createStorageService(legacyWorkspace: LegacyWorkspace, workspace: Workspace, configuration: IWindowConfiguration, environmentService: IEnvironmentService): IStorageService {
|
||||
let id: string;
|
||||
if (workspace) {
|
||||
id = { resource: workspace.resource, uid: workspace.ctime };
|
||||
id = legacyWorkspace.resource.toString();
|
||||
} else if (configuration.backupPath) {
|
||||
// if we do not have a workspace open, we need to find another identifier for the window to store
|
||||
// workspace UI state. if we have a backup path in the configuration we can use that because this
|
||||
|
@ -183,13 +188,13 @@ function createStorageService(workspace: LegacyWorkspace, configuration: IWindow
|
|||
// dirty files in the workspace.
|
||||
// We use basename() to produce a short identifier, we do not need the full path. We use a custom
|
||||
// scheme so that we can later distinguish these identifiers from the workspace one.
|
||||
id = { resource: uri.from({ path: path.basename(configuration.backupPath), scheme: 'empty' }) };
|
||||
id = uri.from({ path: path.basename(configuration.backupPath), scheme: 'empty' }).toString();
|
||||
}
|
||||
|
||||
const disableStorage = !!environmentService.extensionTestsPath; // never keep any state when running extension tests!
|
||||
const storage = disableStorage ? inMemoryLocalStorageInstance : window.localStorage;
|
||||
|
||||
return new StorageService(storage, storage, id);
|
||||
return new StorageService(storage, storage, { id, name: workspace && workspace.name, roots: workspace && workspace.roots }, legacyWorkspace ? legacyWorkspace.ctime : void 0);
|
||||
}
|
||||
|
||||
function loaderError(err: Error): Error {
|
||||
|
|
|
@ -397,7 +397,7 @@ export class DebugService implements debug.IDebugService {
|
|||
const process = this.viewModel.focusedProcess;
|
||||
if (process && session && process.getId() === session.getId() && strings.equalsIgnoreCase(process.configuration.type, 'extensionhost') && this.sessionStates.get(session.getId()) === debug.State.Running &&
|
||||
process && this.contextService.hasWorkspace() && process.configuration.noDebug) {
|
||||
this.windowsService.closeExtensionHostWindow(this.contextService.getWorkspace().resource.fsPath);
|
||||
this.windowsService.closeExtensionHostWindow(this.contextService.getWorkspace2().roots.map(r => r.fsPath));
|
||||
}
|
||||
if (session && session.getId() === event.body.sessionId) {
|
||||
this.onSessionEnd(session);
|
||||
|
|
|
@ -285,7 +285,7 @@ export abstract class EmmetEditorAction extends EditorAction {
|
|||
const modeService = accessor.get(IModeService);
|
||||
const messageService = accessor.get(IMessageService);
|
||||
const contextService = accessor.get(IWorkspaceContextService);
|
||||
const workspaceRoot = contextService.getWorkspace() ? contextService.getWorkspace().resource.fsPath : '';
|
||||
const workspaceRoot = contextService.hasWorkspace() ? contextService.getWorkspace().resource.fsPath : '';
|
||||
const telemetryService = accessor.get(ITelemetryService);
|
||||
const commandService = accessor.get(ICommandService);
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ export class OpenFileHandler extends QuickOpenHandler {
|
|||
|
||||
private doFindResults(searchValue: string, cacheKey?: string, maxSortedResults?: number): TPromise<FileQuickOpenModel> {
|
||||
const query: IQueryOptions = {
|
||||
folderResources: this.contextService.hasWorkspace() ? [this.contextService.getWorkspace().resource] : [],
|
||||
folderResources: this.contextService.hasWorkspace() ? this.contextService.getWorkspace2().roots : [],
|
||||
extraFileResources: getOutOfWorkspaceEditorResources(this.editorGroupService, this.contextService),
|
||||
filePattern: searchValue,
|
||||
cacheKey: cacheKey
|
||||
|
@ -189,7 +189,7 @@ export class OpenFileHandler extends QuickOpenHandler {
|
|||
|
||||
private cacheQuery(cacheKey: string): ISearchQuery {
|
||||
const options: IQueryOptions = {
|
||||
folderResources: this.contextService.hasWorkspace() ? [this.contextService.getWorkspace().resource] : [],
|
||||
folderResources: this.contextService.hasWorkspace() ? this.contextService.getWorkspace2().roots : [],
|
||||
extraFileResources: getOutOfWorkspaceEditorResources(this.editorGroupService, this.contextService),
|
||||
filePattern: '',
|
||||
cacheKey: cacheKey,
|
||||
|
|
|
@ -28,7 +28,6 @@ import { toResource } from 'vs/workbench/common/editor';
|
|||
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IListService } from 'vs/platform/list/browser/listService';
|
||||
import { explorerItemToFileResource } from 'vs/workbench/parts/files/common/files';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { OS } from 'vs/base/common/platform';
|
||||
|
||||
export function isSearchViewletFocussed(viewletService: IViewletService): boolean {
|
||||
|
@ -262,7 +261,6 @@ export class FindInFolderAction extends Action {
|
|||
export const findInFolderCommand = (accessor: ServicesAccessor, resource?: URI) => {
|
||||
const listService = accessor.get(IListService);
|
||||
const viewletService = accessor.get(IViewletService);
|
||||
const contextService = accessor.get(IWorkspaceContextService);
|
||||
|
||||
if (!URI.isUri(resource)) {
|
||||
const focused = listService.getFocused() ? listService.getFocused().getFocus() : void 0;
|
||||
|
@ -274,15 +272,9 @@ export const findInFolderCommand = (accessor: ServicesAccessor, resource?: URI)
|
|||
}
|
||||
}
|
||||
|
||||
if (!URI.isUri(resource) && contextService.hasWorkspace()) {
|
||||
resource = contextService.getWorkspace().resource;
|
||||
}
|
||||
|
||||
if (URI.isUri(resource)) {
|
||||
viewletService.openViewlet(Constants.VIEWLET_ID, true).then((viewlet: SearchViewlet) => {
|
||||
viewlet.searchInFolder(resource);
|
||||
}).done(null, errors.onUnexpectedError);
|
||||
}
|
||||
viewletService.openViewlet(Constants.VIEWLET_ID, true).then((viewlet: SearchViewlet) => {
|
||||
viewlet.searchInFolder(resource);
|
||||
}).done(null, errors.onUnexpectedError);
|
||||
};
|
||||
|
||||
export class RefreshAction extends Action {
|
||||
|
|
|
@ -889,13 +889,9 @@ export class SearchViewlet extends Viewlet {
|
|||
}
|
||||
}
|
||||
|
||||
public searchInFolder(resource: URI): void {
|
||||
const workspace = this.contextService.getWorkspace();
|
||||
if (!workspace) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (workspace.resource.toString() === resource.toString()) {
|
||||
public searchInFolder(resource?: URI): void {
|
||||
const workspaceRelativePath = this.contextService.toWorkspaceRelativePath(resource);
|
||||
if (!workspaceRelativePath || workspaceRelativePath === '.') {
|
||||
this.inputPatternIncludes.setValue('');
|
||||
this.searchWidget.focus();
|
||||
return;
|
||||
|
@ -904,12 +900,10 @@ export class SearchViewlet extends Viewlet {
|
|||
if (!this.showsFileTypes()) {
|
||||
this.toggleQueryDetails(true, true);
|
||||
}
|
||||
const workspaceRelativePath = this.contextService.toWorkspaceRelativePath(resource);
|
||||
if (workspaceRelativePath) {
|
||||
this.inputPatternIncludes.setIsGlobPattern(false);
|
||||
this.inputPatternIncludes.setValue('./' + workspaceRelativePath);
|
||||
this.searchWidget.focus(false);
|
||||
}
|
||||
|
||||
this.inputPatternIncludes.setIsGlobPattern(false);
|
||||
this.inputPatternIncludes.setValue('./' + workspaceRelativePath);
|
||||
this.searchWidget.focus(false);
|
||||
}
|
||||
|
||||
public onQueryChanged(rerunQuery: boolean, preserveFocus?: boolean): void {
|
||||
|
@ -956,7 +950,7 @@ export class SearchViewlet extends Viewlet {
|
|||
const { expression: includePattern, searchPaths } = this.inputPatternIncludes.getGlob();
|
||||
|
||||
const options: IQueryOptions = {
|
||||
folderResources: this.contextService.hasWorkspace() ? [this.contextService.getWorkspace().resource] : [],
|
||||
folderResources: this.contextService.hasWorkspace() ? this.contextService.getWorkspace2().roots : [],
|
||||
extraFileResources: getOutOfWorkspaceEditorResources(this.editorGroupService, this.contextService),
|
||||
excludePattern,
|
||||
includePattern,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import * as assert from 'assert';
|
||||
import { Platform } from 'vs/base/common/platform';
|
||||
import { TerminalLinkHandler, LineColumnInfo } from 'vs/workbench/parts/terminal/electron-browser/terminalLinkHandler';
|
||||
import { LegacyWorkspace } from 'vs/platform/workspace/common/workspace';
|
||||
import { Workspace } from 'vs/platform/workspace/common/workspace';
|
||||
import { TestContextService } from 'vs/workbench/test/workbenchTestServices';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
|
@ -45,9 +45,9 @@ interface LinkFormatInfo {
|
|||
column?: string;
|
||||
}
|
||||
|
||||
class TestWorkspace extends LegacyWorkspace {
|
||||
class TestWorkspace extends Workspace {
|
||||
constructor(private basePath: string) {
|
||||
super(new TestURI(basePath));
|
||||
super(basePath, basePath, [new TestURI(basePath)]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -227,8 +227,8 @@ class WelcomePage {
|
|||
|
||||
recentlyOpened.then(({ folders }) => {
|
||||
if (this.contextService.hasWorkspace()) {
|
||||
const current = this.contextService.getWorkspace().resource.fsPath;
|
||||
folders = folders.filter(folder => !this.pathEquals(folder, current));
|
||||
const currents = this.contextService.getWorkspace2().roots;
|
||||
folders = folders.filter(folder => !currents.some(current => this.pathEquals(folder, current.fsPath)));
|
||||
}
|
||||
if (!folders.length) {
|
||||
const recent = container.querySelector('.welcomePage') as HTMLElement;
|
||||
|
|
|
@ -20,6 +20,7 @@ import { EnvironmentService } from 'vs/platform/environment/node/environmentServ
|
|||
import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { RawTextSource } from 'vs/editor/common/model/textSource';
|
||||
import { TestContextService } from 'vs/workbench/test/workbenchTestServices';
|
||||
import { Workspace } from "vs/platform/workspace/common/workspace";
|
||||
|
||||
class TestEnvironmentService extends EnvironmentService {
|
||||
|
||||
|
@ -48,7 +49,7 @@ const untitledBackupPath = path.join(workspaceBackupPath, 'untitled', crypto.cre
|
|||
|
||||
class TestBackupFileService extends BackupFileService {
|
||||
constructor(workspace: Uri, backupHome: string, workspacesJsonPath: string) {
|
||||
const fileService = new FileService(workspace.fsPath, { disableWatcher: true }, new TestContextService());
|
||||
const fileService = new FileService(new TestContextService(new Workspace(workspace.fsPath, workspace.fsPath, [workspace])), { disableWatcher: true });
|
||||
|
||||
super(workspaceBackupPath, fileService);
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ suite('ConfigurationEditingService', () => {
|
|||
instantiationService.stub(ITelemetryService, NullTelemetryService);
|
||||
instantiationService.stub(IModeService, ModeServiceImpl);
|
||||
instantiationService.stub(IModelService, instantiationService.createInstance(ModelServiceImpl));
|
||||
instantiationService.stub(IFileService, instantiationService.createInstance(FileService, workspaceDir, { disableWatcher: true }));
|
||||
instantiationService.stub(IFileService, new FileService(workspaceService, { disableWatcher: true }));
|
||||
instantiationService.stub(IUntitledEditorService, instantiationService.createInstance(UntitledEditorService));
|
||||
|
||||
instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService));
|
||||
|
|
|
@ -19,7 +19,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
|||
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import nls = require('vs/nls');
|
||||
import { getPathLabel, IWorkspaceProvider } from 'vs/base/common/labels';
|
||||
import { getPathLabel } from 'vs/base/common/labels';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { once } from 'vs/base/common/event';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
|
@ -287,7 +287,7 @@ export class WorkbenchEditorService implements IWorkbenchEditorService {
|
|||
return input;
|
||||
}
|
||||
|
||||
private toDiffLabel(res1: URI, res2: URI, context: IWorkspaceProvider, environment: IEnvironmentService): string {
|
||||
private toDiffLabel(res1: URI, res2: URI, context: IWorkspaceContextService, environment: IEnvironmentService): string {
|
||||
const leftName = getPathLabel(res1.fsPath, context, environment);
|
||||
const rightName = getPathLabel(res2.fsPath, context, environment);
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ export class FileService implements IFileService {
|
|||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IWorkspaceContextService private contextService: IWorkspaceContextService,
|
||||
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
|
||||
@IEnvironmentService environmentService: IEnvironmentService,
|
||||
@IEnvironmentService private environmentService: IEnvironmentService,
|
||||
@IEditorGroupService private editorGroupService: IEditorGroupService,
|
||||
@ILifecycleService private lifecycleService: ILifecycleService,
|
||||
@IMessageService private messageService: IMessageService,
|
||||
|
@ -65,13 +65,6 @@ export class FileService implements IFileService {
|
|||
|
||||
const configuration = this.configurationService.getConfiguration<IFilesConfiguration>();
|
||||
|
||||
// adjust encodings
|
||||
const encodingOverride: IEncodingOverride[] = [];
|
||||
encodingOverride.push({ resource: uri.file(environmentService.appSettingsHome), encoding: encoding.UTF8 });
|
||||
if (this.contextService.hasWorkspace()) {
|
||||
encodingOverride.push({ resource: uri.file(paths.join(this.contextService.getWorkspace().resource.fsPath, '.vscode')), encoding: encoding.UTF8 });
|
||||
}
|
||||
|
||||
let watcherIgnoredPatterns: string[] = [];
|
||||
if (configuration.files && configuration.files.watcherExclude) {
|
||||
watcherIgnoredPatterns = Object.keys(configuration.files.watcherExclude).filter(k => !!configuration.files.watcherExclude[k]);
|
||||
|
@ -82,15 +75,14 @@ export class FileService implements IFileService {
|
|||
errorLogger: (msg: string) => this.onFileServiceError(msg),
|
||||
encoding: configuration.files && configuration.files.encoding,
|
||||
autoGuessEncoding: configuration.files && configuration.files.autoGuessEncoding,
|
||||
encodingOverride,
|
||||
encodingOverride: this.getEncodingOverrides(),
|
||||
watcherIgnoredPatterns,
|
||||
verboseLogging: environmentService.verbose,
|
||||
useExperimentalFileWatcher: configuration.files.useExperimentalFileWatcher
|
||||
};
|
||||
|
||||
// create service
|
||||
const workspace = this.contextService.getWorkspace();
|
||||
this.raw = new NodeFileService(workspace ? workspace.resource.fsPath : void 0, fileServiceConfig, contextService);
|
||||
this.raw = new NodeFileService(contextService, fileServiceConfig);
|
||||
|
||||
// Listeners
|
||||
this.registerListeners();
|
||||
|
@ -140,10 +132,29 @@ export class FileService implements IFileService {
|
|||
// Editor changing
|
||||
this.toUnbind.push(this.editorGroupService.onEditorsChanged(() => this.onEditorsChanged()));
|
||||
|
||||
// Root changes
|
||||
this.toUnbind.push(this.contextService.onDidChangeWorkspaceRoots(() => this.onDidChangeWorkspaceRoots()));
|
||||
|
||||
// Lifecycle
|
||||
this.lifecycleService.onShutdown(this.dispose, this);
|
||||
}
|
||||
|
||||
private onDidChangeWorkspaceRoots(): void {
|
||||
this.updateOptions({ encodingOverride: this.getEncodingOverrides() });
|
||||
}
|
||||
|
||||
private getEncodingOverrides(): IEncodingOverride[] {
|
||||
const encodingOverride: IEncodingOverride[] = [];
|
||||
encodingOverride.push({ resource: uri.file(this.environmentService.appSettingsHome), encoding: encoding.UTF8 });
|
||||
if (this.contextService.hasWorkspace()) {
|
||||
this.contextService.getWorkspace2().roots.forEach(root => {
|
||||
encodingOverride.push({ resource: uri.file(paths.join(root.fsPath, '.vscode')), encoding: encoding.UTF8 });
|
||||
});
|
||||
}
|
||||
|
||||
return encodingOverride;
|
||||
}
|
||||
|
||||
private onEditorsChanged(): void {
|
||||
this.handleOutOfWorkspaceWatchers();
|
||||
}
|
||||
|
@ -240,11 +251,6 @@ export class FileService implements IFileService {
|
|||
}
|
||||
|
||||
private doMoveItemToTrash(resource: uri): TPromise<void> {
|
||||
const workspace = this.contextService.getWorkspace();
|
||||
if (!workspace) {
|
||||
return TPromise.wrapError<void>('Need a workspace to use this');
|
||||
}
|
||||
|
||||
const absolutePath = resource.fsPath;
|
||||
const result = shell.moveItemToTrash(absolutePath);
|
||||
if (!result) {
|
||||
|
|
|
@ -12,7 +12,6 @@ import crypto = require('crypto');
|
|||
import assert = require('assert');
|
||||
|
||||
import { isParent, FileOperation, FileOperationEvent, IContent, IFileService, IResolveFileOptions, IResolveContentOptions, IFileStat, IStreamContent, IFileOperationResult, FileOperationResult, IUpdateContentOptions, FileChangeType, IImportResult, MAX_FILE_SIZE, FileChangesEvent } from 'vs/platform/files/common/files';
|
||||
import strings = require('vs/base/common/strings');
|
||||
import { isEqualOrParent } from 'vs/base/common/paths';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import arrays = require('vs/base/common/arrays');
|
||||
|
@ -80,7 +79,6 @@ export class FileService implements IFileService {
|
|||
private static FS_REWATCH_DELAY = 300; // delay to rewatch a file that was renamed or deleted (in ms)
|
||||
private static MAX_DEGREE_OF_PARALLEL_FS_OPS = 10; // degree of parallel fs calls that we accept at the same time
|
||||
|
||||
private basePath: string;
|
||||
private tmpPath: string;
|
||||
private options: IFileServiceOptions;
|
||||
|
||||
|
@ -94,25 +92,10 @@ export class FileService implements IFileService {
|
|||
private undeliveredRawFileChangesEvents: IRawFileChange[];
|
||||
|
||||
constructor(
|
||||
basePath: string,
|
||||
private contextService: IWorkspaceContextService,
|
||||
options: IFileServiceOptions,
|
||||
private contextService: IWorkspaceContextService
|
||||
) {
|
||||
this.toDispose = [];
|
||||
this.basePath = basePath ? paths.normalize(basePath) : void 0;
|
||||
|
||||
if (this.basePath && this.basePath.indexOf('\\\\') === 0 && strings.endsWith(this.basePath, paths.sep)) {
|
||||
// for some weird reason, node adds a trailing slash to UNC paths
|
||||
// we never ever want trailing slashes as our base path unless
|
||||
// someone opens root ("/").
|
||||
// See also https://github.com/nodejs/io.js/issues/1765
|
||||
this.basePath = strings.rtrim(this.basePath, paths.sep);
|
||||
}
|
||||
|
||||
if (this.basePath && !paths.isAbsolute(basePath)) {
|
||||
throw new Error('basePath has to be an absolute path');
|
||||
}
|
||||
|
||||
this.options = options || Object.create(null);
|
||||
this.tmpPath = this.options.tmpDir || os.tmpdir();
|
||||
|
||||
|
@ -126,7 +109,7 @@ export class FileService implements IFileService {
|
|||
this.options.errorLogger = console.error;
|
||||
}
|
||||
|
||||
if (this.basePath && !this.options.disableWatcher) {
|
||||
if (contextService.hasWorkspace() && !this.options.disableWatcher) {
|
||||
if (this.options.useExperimentalFileWatcher) {
|
||||
this.setupNsfwWorkspceWatching();
|
||||
} else {
|
||||
|
@ -158,15 +141,15 @@ export class FileService implements IFileService {
|
|||
}
|
||||
|
||||
private setupWin32WorkspaceWatching(): void {
|
||||
this.toDispose.push(toDisposable(new WindowsWatcherService(this.basePath, this.options.watcherIgnoredPatterns, e => this._onFileChanges.fire(e), this.options.errorLogger, this.options.verboseLogging).startWatching()));
|
||||
this.toDispose.push(toDisposable(new WindowsWatcherService(this.contextService, this.options.watcherIgnoredPatterns, e => this._onFileChanges.fire(e), this.options.errorLogger, this.options.verboseLogging).startWatching()));
|
||||
}
|
||||
|
||||
private setupUnixWorkspaceWatching(): void {
|
||||
this.toDispose.push(toDisposable(new UnixWatcherService(this.basePath, this.options.watcherIgnoredPatterns, e => this._onFileChanges.fire(e), this.options.errorLogger, this.options.verboseLogging).startWatching()));
|
||||
this.toDispose.push(toDisposable(new UnixWatcherService(this.contextService, this.options.watcherIgnoredPatterns, e => this._onFileChanges.fire(e), this.options.errorLogger, this.options.verboseLogging).startWatching()));
|
||||
}
|
||||
|
||||
private setupNsfwWorkspceWatching(): void {
|
||||
this.toDispose.push(toDisposable(new NsfwWatcherService(this.basePath, this.options.watcherIgnoredPatterns, e => this._onFileChanges.fire(e), this.options.errorLogger, this.options.verboseLogging, this.contextService).startWatching()));
|
||||
this.toDispose.push(toDisposable(new NsfwWatcherService(this.contextService, this.options.watcherIgnoredPatterns, e => this._onFileChanges.fire(e), this.options.errorLogger, this.options.verboseLogging).startWatching()));
|
||||
}
|
||||
|
||||
public resolveFile(resource: uri, options?: IResolveFileOptions): TPromise<IFileStat> {
|
||||
|
|
|
@ -13,6 +13,7 @@ import { toFileChangesEvent, IRawFileChange } from 'vs/workbench/services/files/
|
|||
import { IWatcherChannel, WatcherChannelClient } from 'vs/workbench/services/files/node/watcher/nsfw/watcherIpc';
|
||||
import { FileChangesEvent } from 'vs/platform/files/common/files';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { normalize } from "path";
|
||||
|
||||
export class FileWatcher {
|
||||
private static MAX_RESTARTS = 5;
|
||||
|
@ -21,12 +22,11 @@ export class FileWatcher {
|
|||
private restartCounter: number;
|
||||
|
||||
constructor(
|
||||
private basePath: string,
|
||||
private contextService: IWorkspaceContextService,
|
||||
private ignored: string[],
|
||||
private onFileChanges: (changes: FileChangesEvent) => void,
|
||||
private errorLogger: (msg: string) => void,
|
||||
private verboseLogging: boolean,
|
||||
private contextService: IWorkspaceContextService
|
||||
) {
|
||||
this.isDisposed = false;
|
||||
this.restartCounter = 0;
|
||||
|
@ -52,7 +52,8 @@ export class FileWatcher {
|
|||
const service = new WatcherChannelClient(channel);
|
||||
|
||||
// Start watching
|
||||
service.watch({ basePath: this.basePath, ignored: this.ignored, verboseLogging: this.verboseLogging }).then(null, (err) => {
|
||||
const basePath: string = normalize(this.contextService.getWorkspace2().roots[0].fsPath);
|
||||
service.watch({ basePath, ignored: this.ignored, verboseLogging: this.verboseLogging }).then(null, (err) => {
|
||||
if (!(err instanceof Error && err.name === 'Canceled' && err.message === 'Canceled')) {
|
||||
return TPromise.wrapError(err); // the service lib uses the promise cancel error to indicate the process died, we do not want to bubble this up
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ import uri from 'vs/base/common/uri';
|
|||
import { toFileChangesEvent, IRawFileChange } from 'vs/workbench/services/files/node/watcher/common';
|
||||
import { IWatcherChannel, WatcherChannelClient } from 'vs/workbench/services/files/node/watcher/unix/watcherIpc';
|
||||
import { FileChangesEvent } from 'vs/platform/files/common/files';
|
||||
import { IWorkspaceContextService } from "vs/platform/workspace/common/workspace";
|
||||
import { normalize } from "path";
|
||||
|
||||
export class FileWatcher {
|
||||
private static MAX_RESTARTS = 5;
|
||||
|
@ -20,7 +22,7 @@ export class FileWatcher {
|
|||
private restartCounter: number;
|
||||
|
||||
constructor(
|
||||
private basePath: string,
|
||||
private contextService: IWorkspaceContextService,
|
||||
private ignored: string[],
|
||||
private onFileChanges: (changes: FileChangesEvent) => void,
|
||||
private errorLogger: (msg: string) => void,
|
||||
|
@ -50,7 +52,8 @@ export class FileWatcher {
|
|||
const service = new WatcherChannelClient(channel);
|
||||
|
||||
// Start watching
|
||||
service.watch({ basePath: this.basePath, ignored: this.ignored, verboseLogging: this.verboseLogging }).then(null, (err) => {
|
||||
const basePath: string = normalize(this.contextService.getWorkspace2().roots[0].fsPath);
|
||||
service.watch({ basePath: basePath, ignored: this.ignored, verboseLogging: this.verboseLogging }).then(null, (err) => {
|
||||
if (!(err instanceof Error && err.name === 'Canceled' && err.message === 'Canceled')) {
|
||||
return TPromise.wrapError(err); // the service lib uses the promise cancel error to indicate the process died, we do not want to bubble this up
|
||||
}
|
||||
|
@ -63,7 +66,6 @@ export class FileWatcher {
|
|||
if (this.restartCounter <= FileWatcher.MAX_RESTARTS) {
|
||||
this.errorLogger('[FileWatcher] terminated unexpectedly and is restarted again...');
|
||||
this.restartCounter++;
|
||||
// TODO: What do we do for multi-root here?
|
||||
this.startWatching();
|
||||
} else {
|
||||
this.errorLogger('[FileWatcher] failed to start after retrying for some time, giving up. Please report this as a bug report!');
|
||||
|
|
|
@ -8,11 +8,15 @@
|
|||
import { IRawFileChange, toFileChangesEvent } from 'vs/workbench/services/files/node/watcher/common';
|
||||
import { OutOfProcessWin32FolderWatcher } from 'vs/workbench/services/files/node/watcher/win32/csharpWatcherService';
|
||||
import { FileChangesEvent } from 'vs/platform/files/common/files';
|
||||
import { IWorkspaceContextService } from "vs/platform/workspace/common/workspace";
|
||||
import { normalize } from "path";
|
||||
import { rtrim, endsWith } from "vs/base/common/strings";
|
||||
import { sep } from "vs/base/common/paths";
|
||||
|
||||
export class FileWatcher {
|
||||
|
||||
constructor(
|
||||
private basePath: string,
|
||||
private contextService: IWorkspaceContextService,
|
||||
private ignored: string[],
|
||||
private onFileChanges: (changes: FileChangesEvent) => void,
|
||||
private errorLogger: (msg: string) => void,
|
||||
|
@ -21,8 +25,18 @@ export class FileWatcher {
|
|||
}
|
||||
|
||||
public startWatching(): () => void {
|
||||
let watcher = new OutOfProcessWin32FolderWatcher(
|
||||
this.basePath,
|
||||
let basePath: string = normalize(this.contextService.getWorkspace2().roots[0].fsPath);
|
||||
|
||||
if (basePath && basePath.indexOf('\\\\') === 0 && endsWith(basePath, sep)) {
|
||||
// for some weird reason, node adds a trailing slash to UNC paths
|
||||
// we never ever want trailing slashes as our base path unless
|
||||
// someone opens root ("/").
|
||||
// See also https://github.com/nodejs/io.js/issues/1765
|
||||
basePath = rtrim(basePath, sep);
|
||||
}
|
||||
|
||||
const watcher = new OutOfProcessWin32FolderWatcher(
|
||||
basePath,
|
||||
this.ignored,
|
||||
(events) => this.onRawFileEvents(events),
|
||||
(error) => this.onError(error),
|
||||
|
|
|
@ -20,6 +20,7 @@ import encodingLib = require('vs/base/node/encoding');
|
|||
import utils = require('vs/workbench/services/files/test/node/utils');
|
||||
import { onError } from 'vs/base/test/common/utils';
|
||||
import { TestContextService } from "vs/workbench/test/workbenchTestServices";
|
||||
import { Workspace } from "vs/platform/workspace/common/workspace";
|
||||
|
||||
suite('FileService', () => {
|
||||
let service: FileService;
|
||||
|
@ -36,7 +37,7 @@ suite('FileService', () => {
|
|||
return onError(error, done);
|
||||
}
|
||||
|
||||
service = new FileService(testDir, { disableWatcher: true }, new TestContextService());
|
||||
service = new FileService(new TestContextService(new Workspace(testDir, testDir, [uri.file(testDir)])), { disableWatcher: true });
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -732,11 +733,11 @@ suite('FileService', () => {
|
|||
encoding: 'utf16le'
|
||||
});
|
||||
|
||||
let _service = new FileService(_testDir, {
|
||||
let _service = new FileService(new TestContextService(new Workspace(_testDir, _testDir, [uri.file(_testDir)])), {
|
||||
encoding: 'windows1252',
|
||||
encodingOverride: encodingOverride,
|
||||
encodingOverride,
|
||||
disableWatcher: true
|
||||
}, new TestContextService());
|
||||
});
|
||||
|
||||
_service.resolveContent(uri.file(path.join(testDir, 'index.html'))).done(c => {
|
||||
assert.equal(c.encoding, 'windows1252');
|
||||
|
@ -760,9 +761,9 @@ suite('FileService', () => {
|
|||
let _sourceDir = require.toUrl('./fixtures/service');
|
||||
let resource = uri.file(path.join(testDir, 'index.html'));
|
||||
|
||||
let _service = new FileService(_testDir, {
|
||||
let _service = new FileService(new TestContextService(new Workspace(_testDir, _testDir, [uri.file(_testDir)])), {
|
||||
disableWatcher: true
|
||||
}, new TestContextService());
|
||||
});
|
||||
|
||||
extfs.copy(_sourceDir, _testDir, () => {
|
||||
fs.readFile(resource.fsPath, (error, data) => {
|
||||
|
|
|
@ -9,6 +9,7 @@ import assert = require('assert');
|
|||
import os = require('os');
|
||||
import path = require('path');
|
||||
import fs = require('fs');
|
||||
import uri from 'vs/base/common/uri';
|
||||
import * as json from 'vs/base/common/json';
|
||||
import { OS } from 'vs/base/common/platform';
|
||||
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
|
||||
|
@ -17,7 +18,7 @@ import { KeyCode, SimpleKeybinding, ChordKeybinding } from 'vs/base/common/keyCo
|
|||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import extfs = require('vs/base/node/extfs');
|
||||
import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestContextService } from 'vs/workbench/test/workbenchTestServices';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspaceContextService, Workspace } from 'vs/platform/workspace/common/workspace';
|
||||
import uuid = require('vs/base/common/uuid');
|
||||
import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';
|
||||
import { FileService } from 'vs/workbench/services/files/node/fileService';
|
||||
|
@ -53,7 +54,7 @@ suite('Keybindings Editing', () => {
|
|||
|
||||
let instantiationService: TestInstantiationService;
|
||||
let testObject: KeybindingsEditingService;
|
||||
let testDir;
|
||||
let testDir: string;
|
||||
let keybindingsFile;
|
||||
|
||||
setup(() => {
|
||||
|
@ -73,7 +74,7 @@ suite('Keybindings Editing', () => {
|
|||
instantiationService.stub(ITelemetryService, NullTelemetryService);
|
||||
instantiationService.stub(IModeService, ModeServiceImpl);
|
||||
instantiationService.stub(IModelService, instantiationService.createInstance(ModelServiceImpl));
|
||||
instantiationService.stub(IFileService, new FileService(testDir, { disableWatcher: true }, new TestContextService()));
|
||||
instantiationService.stub(IFileService, new FileService(new TestContextService(new Workspace(testDir, testDir, [uri.file(testDir)])), { disableWatcher: true }));
|
||||
instantiationService.stub(IUntitledEditorService, instantiationService.createInstance(UntitledEditorService));
|
||||
instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService));
|
||||
instantiationService.stub(ITextModelService, <ITextModelService>instantiationService.createInstance(TextModelResolverService));
|
||||
|
|
|
@ -64,7 +64,7 @@ export const TestEnvironmentService = new EnvironmentService(parseArgs(process.a
|
|||
export class TestContextService implements IWorkspaceContextService {
|
||||
public _serviceBrand: any;
|
||||
|
||||
private workspace: ILegacyWorkspace;
|
||||
private workspace: IWorkspace;
|
||||
private id: string;
|
||||
private options: any;
|
||||
|
||||
|
@ -82,7 +82,7 @@ export class TestContextService implements IWorkspaceContextService {
|
|||
}
|
||||
|
||||
public getFolders(): URI[] {
|
||||
return this.workspace ? [this.workspace.resource] : [];
|
||||
return this.workspace ? this.workspace.roots : [];
|
||||
}
|
||||
|
||||
public hasWorkspace(): boolean {
|
||||
|
@ -90,15 +90,15 @@ export class TestContextService implements IWorkspaceContextService {
|
|||
}
|
||||
|
||||
public getWorkspace(): ILegacyWorkspace {
|
||||
return this.workspace;
|
||||
return this.workspace ? { resource: this.workspace.roots[0] } : void 0;
|
||||
}
|
||||
|
||||
public getWorkspace2(): IWorkspace {
|
||||
return this.workspace ? { id: this.id, roots: [this.workspace.resource], name: this.workspace.resource.fsPath } : void 0;
|
||||
return this.workspace;
|
||||
}
|
||||
|
||||
public getRoot(resource: URI): URI {
|
||||
return this.isInsideWorkspace(resource) ? this.workspace.resource : null;
|
||||
return this.isInsideWorkspace(resource) ? this.workspace.roots[0] : null;
|
||||
}
|
||||
|
||||
public setWorkspace(workspace: any): void {
|
||||
|
@ -115,7 +115,7 @@ export class TestContextService implements IWorkspaceContextService {
|
|||
|
||||
public isInsideWorkspace(resource: URI): boolean {
|
||||
if (resource && this.workspace) {
|
||||
return paths.isEqualOrParent(resource.fsPath, this.workspace.resource.fsPath, !isLinux /* ignorecase */);
|
||||
return paths.isEqualOrParent(resource.fsPath, this.workspace.roots[0].fsPath, !isLinux /* ignorecase */);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -363,7 +363,7 @@ export class TestStorageService extends EventEmitter implements IStorageService
|
|||
super();
|
||||
|
||||
let context = new TestContextService();
|
||||
this.storage = new StorageService(new InMemoryLocalStorage(), null, context.getWorkspace());
|
||||
this.storage = new StorageService(new InMemoryLocalStorage(), null, context.getWorkspace2());
|
||||
}
|
||||
|
||||
store(key: string, value: any, scope: StorageScope = StorageScope.GLOBAL): void {
|
||||
|
@ -1012,7 +1012,7 @@ export class TestWindowsService implements IWindowsService {
|
|||
return TPromise.as(void 0);
|
||||
}
|
||||
// TODO@joao: what?
|
||||
closeExtensionHostWindow(extensionDevelopmentPath: string): TPromise<void> {
|
||||
closeExtensionHostWindow(extensionDevelopmentPaths: string[]): TPromise<void> {
|
||||
return TPromise.as(void 0);
|
||||
}
|
||||
showItemInFolder(path: string): TPromise<void> {
|
||||
|
|
Loading…
Reference in a new issue