diff --git a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts index 2428e572c5e3a008e4871e97df0f0ea94c47843c..17c976db6c9da9533652562e620e3c7c78388713 100644 --- a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts +++ b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts @@ -87,7 +87,7 @@ export class WorkspacesMainService implements IWorkspacesMainService { // relative paths get resolved against the workspace location workspace.folders.forEach(folder => { - if (folder.path && !isAbsolute(folder.path)) { + if (!isAbsolute(folder.path)) { folder.path = resolve(dirname(path), folder.path); } }); @@ -105,6 +105,8 @@ export class WorkspacesMainService implements IWorkspacesMainService { } private doParseStoredWorkspace(path: string, contents: string): IStoredWorkspace { + + // Parse workspace file let storedWorkspace: IStoredWorkspace; try { storedWorkspace = JSON.parse(contents); @@ -112,6 +114,12 @@ export class WorkspacesMainService implements IWorkspacesMainService { throw new Error(`${path} cannot be parsed as JSON file (${error}).`); } + // Filter out folders which do not have a path set + if (Array.isArray(storedWorkspace.folders)) { + storedWorkspace.folders = storedWorkspace.folders.filter(folder => !!folder.path); + } + + // Validate if (!Array.isArray(storedWorkspace.folders) || storedWorkspace.folders.length === 0) { throw new Error(`${path} looks like an invalid workspace file.`); } @@ -201,14 +209,12 @@ export class WorkspacesMainService implements IWorkspacesMainService { // is a parent of the location of the workspace file itself. Otherwise keep // using absolute paths. storedWorkspace.folders.forEach(folder => { - if (folder.path) { - if (!isAbsolute(folder.path)) { - folder.path = resolve(sourceConfigFolder, folder.path); // relative paths get resolved against the workspace location - } - - if (isEqualOrParent(folder.path, targetConfigFolder, !isLinux)) { - folder.path = relative(targetConfigFolder, folder.path); // absolute paths get converted to relative ones to workspace location if possible - } + if (!isAbsolute(folder.path)) { + folder.path = resolve(sourceConfigFolder, folder.path); // relative paths get resolved against the workspace location + } + + if (isEqualOrParent(folder.path, targetConfigFolder, !isLinux)) { + folder.path = relative(targetConfigFolder, folder.path) || '.'; // absolute paths get converted to relative ones to workspace location if possible } }); diff --git a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts index 73f43059a1d8bd6a09456ad142cc258b9def192a..c6efbf77f6a149d01ba3c9a6679de42235e2832f 100644 --- a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts +++ b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts @@ -177,7 +177,7 @@ suite('WorkspacesMainService', () => { deletedEvent = e; }); - return service.createWorkspace([process.cwd(), os.tmpdir()]).then(workspace => { + return service.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 => { @@ -188,9 +188,10 @@ suite('WorkspacesMainService', () => { assert.equal(service.deleteWorkspaceCall, workspace); const ws = JSON.parse(fs.readFileSync(savedWorkspace.configPath).toString()) as IStoredWorkspace; - assert.equal(ws.folders.length, 2); + assert.equal(ws.folders.length, 3); assert.equal(ws.folders[0].path, process.cwd()); // absolute - assert.equal(ws.folders[1].path, path.relative(path.dirname(workspaceConfigPath), os.tmpdir())); // relative + assert.equal(ws.folders[1].path, '.'); // relative + assert.equal(ws.folders[2].path, path.relative(path.dirname(workspaceConfigPath), path.join(os.tmpdir(), 'somefolder'))); // relative assert.equal(savedWorkspace, savedEvent.workspace); assert.equal(workspace.configPath, savedEvent.oldConfigPath); @@ -208,7 +209,7 @@ suite('WorkspacesMainService', () => { }); test('saveWorkspace (saved workspace)', done => { - return service.createWorkspace([process.cwd(), os.tmpdir()]).then(workspace => { + return service.createWorkspace([process.cwd(), os.tmpdir(), path.join(os.tmpdir(), 'somefolder')]).then(workspace => { const workspaceConfigPath = path.join(os.tmpdir(), `myworkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); const newWorkspaceConfigPath = path.join(os.tmpdir(), `mySavedWorkspace.${Date.now()}.${WORKSPACE_EXTENSION}`); @@ -219,9 +220,10 @@ suite('WorkspacesMainService', () => { assert.equal(newSavedWorkspace.configPath, newWorkspaceConfigPath); const ws = JSON.parse(fs.readFileSync(newSavedWorkspace.configPath).toString()) as IStoredWorkspace; - assert.equal(ws.folders.length, 2); + assert.equal(ws.folders.length, 3); assert.equal(ws.folders[0].path, process.cwd()); // absolute path because outside of tmpdir - assert.equal(ws.folders[1].path, path.relative(path.dirname(workspaceConfigPath), os.tmpdir())); // relative path because inside of tmpdir + assert.equal(ws.folders[1].path, '.'); // relative path because inside of tmpdir + assert.equal(ws.folders[2].path, path.relative(path.dirname(workspaceConfigPath), path.join(os.tmpdir(), 'somefolder'))); // relative extfs.delSync(workspaceConfigPath); extfs.delSync(newWorkspaceConfigPath); diff --git a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts index b380e90b5f6c89fb8a64d2ba47aba7bc86bd60b9..33cbf289a0801ccf4044cd4c1653d57c633f9a78 100644 --- a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts @@ -75,7 +75,7 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { const workspaceConfigFolder = dirname(workspace.configuration.fsPath); const value: IStoredWorkspaceFolder[] = newWorkspaceRoots.map(newWorkspaceRoot => { if (isEqualOrParent(newWorkspaceRoot, workspaceConfigFolder, !isLinux)) { - newWorkspaceRoot = relative(workspaceConfigFolder, newWorkspaceRoot); // absolute paths get converted to relative ones to workspace location if possible + newWorkspaceRoot = relative(workspaceConfigFolder, newWorkspaceRoot) || '.'; // absolute paths get converted to relative ones to workspace location if possible } return { path: newWorkspaceRoot };