提交 e43be978 编写于 作者: S Sandeep Somavarapu

#54483 Prepare renderer to accept folders as URIs

上级 32bebd31
......@@ -29,6 +29,11 @@ export const UNTITLED_WORKSPACE_NAME = 'workspace.json';
*/
export type ISingleFolderWorkspaceIdentifier = string;
/**
* A single folder workspace identifier is just the folder URI
*/
export type ISingleFolderWorkspaceIdentifier2 = URI;
export interface IWorkspaceIdentifier {
id: string;
configPath: string;
......@@ -137,6 +142,10 @@ export function isSingleFolderWorkspaceIdentifier(obj: any): obj is ISingleFolde
return typeof obj === 'string';
}
export function isSingleFolderWorkspaceIdentifier2(obj: any): obj is ISingleFolderWorkspaceIdentifier2 {
return obj instanceof URI;
}
export function isWorkspaceIdentifier(obj: any): obj is IWorkspaceIdentifier {
const workspaceIdentifier = obj as IWorkspaceIdentifier;
......
......@@ -49,6 +49,7 @@ import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log
import { RelayURLService } from 'vs/platform/url/common/urlService';
import { MenubarChannelClient } from 'vs/platform/menubar/common/menubarIpc';
import { IMenubarService } from 'vs/platform/menubar/common/menubar';
import { Schemas } from 'vs/base/common/network';
gracefulFs.gracefulify(fs); // enable gracefulFs
......@@ -115,22 +116,24 @@ function openWorkbench(configuration: IWindowConfiguration): TPromise<void> {
}
function createAndInitializeWorkspaceService(configuration: IWindowConfiguration, environmentService: EnvironmentService): TPromise<WorkspaceService> {
return validateSingleFolderPath(configuration).then(() => {
const folderUri = configuration.folderPath ? uri.file(configuration.folderPath) /* TODO: Change to URI.path parsing once main sends URIs*/ : null;
return validateFolderUri(folderUri, configuration.verbose).then(validatedFolderUri => {
const workspaceService = new WorkspaceService(environmentService);
return workspaceService.initialize(configuration.workspace || configuration.folderPath || configuration).then(() => workspaceService, error => workspaceService);
return workspaceService.initialize(configuration.workspace || validatedFolderUri || configuration).then(() => workspaceService, error => workspaceService);
});
}
function validateSingleFolderPath(configuration: IWindowConfiguration): TPromise<void> {
function validateFolderUri(folderUri: uri, verbose: boolean): TPromise<uri> {
// Return early if we do not have a single folder path
if (!configuration.folderPath) {
return TPromise.as(void 0);
// Return early if we do not have a single folder uri or if it is a non file uri
if (!folderUri || folderUri.scheme !== Schemas.file) {
return TPromise.as(folderUri);
}
// Otherwise: use realpath to resolve symbolic links to the truth
return realpath(configuration.folderPath).then(realFolderPath => {
return realpath(folderUri.fsPath).then(realFolderPath => {
// For some weird reason, node adds a trailing slash to UNC paths
// we never ever want trailing slashes as our workspace path unless
......@@ -140,19 +143,19 @@ function validateSingleFolderPath(configuration: IWindowConfiguration): TPromise
realFolderPath = strings.rtrim(realFolderPath, paths.nativeSep);
}
return realFolderPath;
return uri.file(realFolderPath);
}, error => {
if (configuration.verbose) {
if (verbose) {
errors.onUnexpectedError(error);
}
// Treat any error case as empty workbench case (no folder path)
return null;
}).then(realFolderPathOrNull => {
}).then(realFolderUriOrNull => {
// Update config with real path if we have one
configuration.folderPath = realFolderPathOrNull;
return realFolderUriOrNull;
});
}
......
......@@ -26,7 +26,7 @@ import { IWorkspaceConfigurationService, FOLDER_CONFIG_FOLDER_NAME, defaultSetti
import { Registry } from 'vs/platform/registry/common/platform';
import { IConfigurationNode, IConfigurationRegistry, Extensions, IConfigurationPropertySchema, allSettings, windowSettings, resourceSettings, applicationSettings } from 'vs/platform/configuration/common/configurationRegistry';
import { createHash } from 'crypto';
import { getWorkspaceLabel, IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces';
import { getWorkspaceLabel, IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier2, isSingleFolderWorkspaceIdentifier2 } from 'vs/platform/workspaces/common/workspaces';
import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { ICommandService } from 'vs/platform/commands/common/commands';
......@@ -41,6 +41,7 @@ import { UserConfiguration } from 'vs/platform/configuration/node/configuration'
import { getBaseLabel } from 'vs/base/common/labels';
import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema';
import { localize } from 'vs/nls';
import { isEqual } from 'vs/base/common/resources';
export class WorkspaceService extends Disposable implements IWorkspaceConfigurationService, IWorkspaceContextService {
......@@ -131,13 +132,18 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
public isCurrentWorkspace(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): boolean {
switch (this.getWorkbenchState()) {
case WorkbenchState.FOLDER:
return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && this.pathEquals(this.workspace.folders[0].uri.fsPath, workspaceIdentifier);
return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && isEqual(this.workspace.folders[0].uri, this.toSingleFolderWorkspaceIdentifier2(workspaceIdentifier), this.workspace.folders[0].uri.scheme !== Schemas.file || !isLinux);
case WorkbenchState.WORKSPACE:
return isWorkspaceIdentifier(workspaceIdentifier) && this.workspace.id === workspaceIdentifier.id;
}
return false;
}
private toSingleFolderWorkspaceIdentifier2(folderIdentifier: ISingleFolderWorkspaceIdentifier): URI {
const uri = URI.parse(folderIdentifier);
return uri.scheme ? uri : URI.file(folderIdentifier);
}
private doUpdateFolders(foldersToAdd: IWorkspaceFolderCreationData[], foldersToRemove: URI[], index?: number): TPromise<void> {
if (this.getWorkbenchState() !== WorkbenchState.WORKSPACE) {
return TPromise.as(void 0); // we need a workspace to begin with
......@@ -295,7 +301,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
return this._configuration.keys();
}
initialize(arg: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWindowConfiguration, postInitialisationTask: () => void = () => null): TPromise<any> {
initialize(arg: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier2 | IWindowConfiguration, postInitialisationTask: () => void = () => null): TPromise<any> {
return this.createWorkspace(arg)
.then(workspace => this.updateWorkspaceAndInitializeConfiguration(workspace, postInitialisationTask));
}
......@@ -322,12 +328,12 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
this.jsonEditingService = instantiationService.createInstance(JSONEditingService);
}
private createWorkspace(arg: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWindowConfiguration): TPromise<Workspace> {
private createWorkspace(arg: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier2 | IWindowConfiguration): TPromise<Workspace> {
if (isWorkspaceIdentifier(arg)) {
return this.createMulitFolderWorkspace(arg);
}
if (isSingleFolderWorkspaceIdentifier(arg)) {
if (isSingleFolderWorkspaceIdentifier2(arg)) {
return this.createSingleFolderWorkspace(arg);
}
......@@ -345,15 +351,18 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
});
}
private createSingleFolderWorkspace(singleFolderWorkspaceIdentifier: ISingleFolderWorkspaceIdentifier): TPromise<Workspace> {
const folderPath = URI.file(singleFolderWorkspaceIdentifier);
return stat(folderPath.fsPath)
.then(workspaceStat => {
const ctime = isLinux ? workspaceStat.ino : workspaceStat.birthtime.getTime(); // On Linux, birthtime is ctime, so we cannot use it! We use the ino instead!
const id = createHash('md5').update(folderPath.fsPath).update(ctime ? String(ctime) : '').digest('hex');
const folder = URI.file(folderPath.fsPath);
return new Workspace(id, getBaseLabel(folder), toWorkspaceFolders([{ path: folder.fsPath }]), null, ctime);
});
private createSingleFolderWorkspace(folder: ISingleFolderWorkspaceIdentifier2): TPromise<Workspace> {
if (folder.scheme === Schemas.file) {
return stat(folder.fsPath)
.then(workspaceStat => {
const ctime = isLinux ? workspaceStat.ino : workspaceStat.birthtime.getTime(); // On Linux, birthtime is ctime, so we cannot use it! We use the ino instead!
const id = createHash('md5').update(folder.fsPath).update(ctime ? String(ctime) : '').digest('hex');
return new Workspace(id, getBaseLabel(folder), toWorkspaceFolders([{ path: folder.fsPath }]), null, ctime);
});
} else {
const id = createHash('md5').update(folder.toString()).digest('hex');
return TPromise.as(new Workspace(id, getBaseLabel(folder), toWorkspaceFolders([{ uri: folder.toString() }]), null));
}
}
private createEmptyWorkspace(configuration: IWindowConfiguration): TPromise<Workspace> {
......@@ -670,15 +679,6 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
}
return {};
}
private pathEquals(path1: string, path2: string): boolean {
if (!isLinux) {
path1 = path1.toLowerCase();
path2 = path2.toLowerCase();
}
return path1 === path2;
}
}
interface IExportedConfigurationNode {
......
......@@ -38,6 +38,7 @@ import { mkdirp } from 'vs/base/node/pfs';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { CommandService } from 'vs/workbench/services/commands/common/commandService';
import URI from 'vs/base/common/uri';
class SettingsTestEnvironmentService extends EnvironmentService {
......@@ -103,7 +104,7 @@ suite('ConfigurationEditingService', () => {
instantiationService.stub(IEnvironmentService, environmentService);
const workspaceService = new WorkspaceService(environmentService);
instantiationService.stub(IWorkspaceContextService, workspaceService);
return workspaceService.initialize(noWorkspace ? {} as IWindowConfiguration : workspaceDir).then(() => {
return workspaceService.initialize(noWorkspace ? {} as IWindowConfiguration : URI.file(workspaceDir)).then(() => {
instantiationService.stub(IConfigurationService, workspaceService);
instantiationService.stub(IFileService, new FileService(workspaceService, TestEnvironmentService, new TestTextResourceConfigurationService(), new TestConfigurationService(), new TestLifecycleService(), new TestStorageService(), new TestNotificationService(), { disableWatcher: true }));
instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService));
......
......@@ -87,7 +87,7 @@ suite('WorkspaceContextService - Folder', () => {
const globalSettingsFile = path.join(parentDir, 'settings.json');
const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile);
workspaceContextService = new WorkspaceService(environmentService);
return (<WorkspaceService>workspaceContextService).initialize(folderDir);
return (<WorkspaceService>workspaceContextService).initialize(URI.file(folderDir));
});
});
......@@ -445,7 +445,7 @@ suite('WorkspaceService - Initialization', () => {
testObject.onDidChangeWorkspaceFolders(target);
testObject.onDidChangeConfiguration(target);
return testObject.initialize(path.join(parentResource, '1'))
return testObject.initialize(URI.file(path.join(parentResource, '1')))
.then(() => {
assert.equal(testObject.getValue('initialization.testSetting1'), 'userValue');
assert.equal(target.callCount, 3);
......@@ -474,7 +474,7 @@ suite('WorkspaceService - Initialization', () => {
fs.writeFileSync(path.join(parentResource, '1', '.vscode', 'settings.json'), '{ "initialization.testSetting1": "workspaceValue" }');
return testObject.initialize(path.join(parentResource, '1'))
return testObject.initialize(URI.file(path.join(parentResource, '1')))
.then(() => {
assert.equal(testObject.getValue('initialization.testSetting1'), 'workspaceValue');
assert.equal(target.callCount, 4);
......@@ -548,7 +548,7 @@ suite('WorkspaceService - Initialization', () => {
test('initialize a folder workspace from a folder workspace with no configuration changes', () => {
return testObject.initialize(path.join(parentResource, '1'))
return testObject.initialize(URI.file(path.join(parentResource, '1')))
.then(() => {
fs.writeFileSync(globalSettingsFile, '{ "initialization.testSetting1": "userValue" }');
......@@ -560,7 +560,7 @@ suite('WorkspaceService - Initialization', () => {
testObject.onDidChangeWorkspaceFolders(target);
testObject.onDidChangeConfiguration(target);
return testObject.initialize(path.join(parentResource, '2'))
return testObject.initialize(URI.file(path.join(parentResource, '2')))
.then(() => {
assert.equal(testObject.getValue('initialization.testSetting1'), 'userValue');
assert.equal(target.callCount, 1);
......@@ -576,7 +576,7 @@ suite('WorkspaceService - Initialization', () => {
test('initialize a folder workspace from a folder workspace with configuration changes', () => {
return testObject.initialize(path.join(parentResource, '1'))
return testObject.initialize(URI.file(path.join(parentResource, '1')))
.then(() => {
const target = sinon.spy();
......@@ -586,7 +586,7 @@ suite('WorkspaceService - Initialization', () => {
testObject.onDidChangeConfiguration(target);
fs.writeFileSync(path.join(parentResource, '2', '.vscode', 'settings.json'), '{ "initialization.testSetting1": "workspaceValue2" }');
return testObject.initialize(path.join(parentResource, '2'))
return testObject.initialize(URI.file(path.join(parentResource, '2')))
.then(() => {
assert.equal(testObject.getValue('initialization.testSetting1'), 'workspaceValue2');
assert.equal(target.callCount, 2);
......@@ -601,7 +601,7 @@ suite('WorkspaceService - Initialization', () => {
test('initialize a multi folder workspace from a folder workspacce triggers change events in the right order', () => {
const folderDir = path.join(parentResource, '1');
return testObject.initialize(folderDir)
return testObject.initialize(URI.file(folderDir))
.then(() => {
const target = sinon.spy();
......@@ -666,7 +666,7 @@ suite('WorkspaceConfigurationService - Folder', () => {
instantiationService.stub(IConfigurationService, workspaceService);
instantiationService.stub(IEnvironmentService, environmentService);
return workspaceService.initialize(folderDir).then(() => {
return workspaceService.initialize(URI.file(folderDir)).then(() => {
const fileService = new FileService(<IWorkspaceContextService>workspaceService, TestEnvironmentService, new TestTextResourceConfigurationService(), workspaceService, new TestLifecycleService(), new TestStorageService(), new TestNotificationService(), { disableWatcher: true });
instantiationService.stub(IFileService, fileService);
instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册