diff --git a/spec/atom-environment-spec.coffee b/spec/atom-environment-spec.coffee index 6fc5ab1a8..52e4af91a 100644 --- a/spec/atom-environment-spec.coffee +++ b/spec/atom-environment-spec.coffee @@ -461,44 +461,91 @@ describe "AtomEnvironment", -> spyOn(atom.workspace, 'open') atom.project.setPaths([]) - describe "when the opened path exists", -> - it "adds it to the project's paths", -> - pathToOpen = __filename - atom.openLocations([{pathToOpen}]) - expect(atom.project.getPaths()[0]).toBe __dirname + describe "when there is no saved state", -> + beforeEach -> + spyOn(atom, "loadState").andReturn(Promise.resolve(null)) - describe "then a second path is opened with forceAddToWindow", -> - it "adds the second path to the project's paths", -> - firstPathToOpen = __dirname - secondPathToOpen = path.resolve(__dirname, './fixtures') - atom.openLocations([{pathToOpen: firstPathToOpen}]) - atom.openLocations([{pathToOpen: secondPathToOpen, forceAddToWindow: true}]) - expect(atom.project.getPaths()).toEqual([firstPathToOpen, secondPathToOpen]) + describe "when the opened path exists", -> + it "adds it to the project's paths", -> + pathToOpen = __filename + waitsForPromise -> atom.openLocations([{pathToOpen}]) + runs -> expect(atom.project.getPaths()[0]).toBe __dirname - describe "when the opened path does not exist but its parent directory does", -> - it "adds the parent directory to the project paths", -> - pathToOpen = path.join(__dirname, 'this-path-does-not-exist.txt') - atom.openLocations([{pathToOpen}]) - expect(atom.project.getPaths()[0]).toBe __dirname + describe "then a second path is opened with forceAddToWindow", -> + it "adds the second path to the project's paths", -> + firstPathToOpen = __dirname + secondPathToOpen = path.resolve(__dirname, './fixtures') + waitsForPromise -> atom.openLocations([{pathToOpen: firstPathToOpen}]) + waitsForPromise -> atom.openLocations([{pathToOpen: secondPathToOpen, forceAddToWindow: true}]) + runs -> expect(atom.project.getPaths()).toEqual([firstPathToOpen, secondPathToOpen]) - describe "when the opened path is a file", -> - it "opens it in the workspace", -> - pathToOpen = __filename - atom.openLocations([{pathToOpen}]) - expect(atom.workspace.open.mostRecentCall.args[0]).toBe __filename + describe "when the opened path does not exist but its parent directory does", -> + it "adds the parent directory to the project paths", -> + pathToOpen = path.join(__dirname, 'this-path-does-not-exist.txt') + waitsForPromise -> atom.openLocations([{pathToOpen}]) + runs -> expect(atom.project.getPaths()[0]).toBe __dirname - describe "when the opened path is a directory", -> - it "does not open it in the workspace", -> - pathToOpen = __dirname - atom.openLocations([{pathToOpen}]) - expect(atom.workspace.open.callCount).toBe 0 + describe "when the opened path is a file", -> + it "opens it in the workspace", -> + pathToOpen = __filename + waitsForPromise -> atom.openLocations([{pathToOpen}]) + runs -> expect(atom.workspace.open.mostRecentCall.args[0]).toBe __filename - describe "when the opened path is a uri", -> - it "adds it to the project's paths as is", -> - pathToOpen = 'remote://server:7644/some/dir/path' - spyOn(atom.project, 'addPath') - atom.openLocations([{pathToOpen}]) - expect(atom.project.addPath).toHaveBeenCalledWith(pathToOpen) + describe "when the opened path is a directory", -> + it "does not open it in the workspace", -> + pathToOpen = __dirname + waitsForPromise -> atom.openLocations([{pathToOpen}]) + runs -> expect(atom.workspace.open.callCount).toBe 0 + + describe "when the opened path is a uri", -> + it "adds it to the project's paths as is", -> + pathToOpen = 'remote://server:7644/some/dir/path' + spyOn(atom.project, 'addPath') + waitsForPromise -> atom.openLocations([{pathToOpen}]) + runs -> expect(atom.project.addPath).toHaveBeenCalledWith(pathToOpen) + + describe "when there is saved state for the relevant directories", -> + state = Symbol('savedState') + + beforeEach -> + spyOn(atom, "getStateKey").andCallFake (dirs) -> dirs.join(':') + spyOn(atom, "loadState").andCallFake (key) -> + if key == __dirname then Promise.resolve(state) else Promise.resolve(null) + spyOn(atom, "attemptRestoreProjectStateForPaths") + + describe "when there are no project folders", -> + it "attempts to restore the project state", -> + pathToOpen = __dirname + waitsForPromise -> atom.openLocations([{pathToOpen}]) + runs -> + expect(atom.attemptRestoreProjectStateForPaths).toHaveBeenCalledWith(state, [pathToOpen], []) + expect(atom.project.getPaths()).toEqual([]) + + it "opens the specified files", -> + waitsForPromise -> atom.openLocations([{pathToOpen: __dirname}, {pathToOpen: __filename}]) + runs -> + expect(atom.attemptRestoreProjectStateForPaths).toHaveBeenCalledWith(state, [__dirname], [__filename]) + expect(atom.project.getPaths()).toEqual([]) + + + describe "when there are already project folders", -> + beforeEach -> + atom.project.setPaths([__dirname]) + + it "does not attempt to restore the project state, instead adding the project paths", -> + pathToOpen = path.join(__dirname, 'fixtures') + waitsForPromise -> atom.openLocations([{pathToOpen, forceAddToWindow: true}]) + runs -> + expect(atom.attemptRestoreProjectStateForPaths).not.toHaveBeenCalled() + expect(atom.project.getPaths()).toEqual([__dirname, pathToOpen]) + + it "opens the specified files", -> + pathToOpen = path.join(__dirname, 'fixtures') + fileToOpen = path.join(pathToOpen, 'michelle-is-awesome.txt') + waitsForPromise -> atom.openLocations([{pathToOpen}, {pathToOpen: fileToOpen}]) + runs -> + expect(atom.attemptRestoreProjectStateForPaths).not.toHaveBeenCalledWith(state, [pathToOpen], [fileToOpen]) + expect(atom.project.getPaths()).toEqual([__dirname]) describe "::updateAvailable(info) (called via IPC from browser process)", -> subscription = null diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 58d7ee431..ad4a2103d 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -1019,23 +1019,38 @@ class AtomEnvironment extends Model openLocations: (locations) -> needsProjectPaths = @project?.getPaths().length is 0 + foldersToAddToProject = [] + fileLocationsToOpen = [] + + pushFolderToOpen = (folder) -> + if folder not in foldersToAddToProject + foldersToAddToProject.push(folder) + for {pathToOpen, initialLine, initialColumn, forceAddToWindow} in locations if pathToOpen? and (needsProjectPaths or forceAddToWindow) if fs.existsSync(pathToOpen) - @project.addPath(pathToOpen) + pushFolderToOpen @project.getDirectoryForProjectPath(pathToOpen).getPath() else if fs.existsSync(path.dirname(pathToOpen)) - @project.addPath(path.dirname(pathToOpen)) + pushFolderToOpen @project.getDirectoryForProjectPath(path.dirname(pathToOpen)).getPath() else - @project.addPath(pathToOpen) + pushFolderToOpen @project.getDirectoryForProjectPath(pathToOpen).getPath() unless fs.isDirectorySync(pathToOpen) + fileLocationsToOpen.push({pathToOpen, initialLine, initialColumn}) + + if foldersToAddToProject.length > 0 + @loadState(@getStateKey(foldersToAddToProject)).then (state) => + if state and needsProjectPaths # only load state if this is the first path added to the project + files = (location.pathToOpen for location in fileLocationsToOpen) + @attemptRestoreProjectStateForPaths(state, foldersToAddToProject, files) + else + @project.addPath(folder) for folder in foldersToAddToProject + for {pathToOpen, initialLine, initialColumn} in fileLocationsToOpen + @workspace?.open(pathToOpen, {initialLine, initialColumn}) + else + for {pathToOpen, initialLine, initialColumn} in fileLocationsToOpen @workspace?.open(pathToOpen, {initialLine, initialColumn}) - - if needsProjectPaths - @loadState(@getStateKey(@project.getPaths())).then (state) => - @restoreStateIntoEnvironment(state) if state - - return + Promise.resolve(null) # Preserve this deprecation until 2.0. Sorry. Should have removed Q sooner. Promise.prototype.done = (callback) -> diff --git a/src/project.coffee b/src/project.coffee index a02f27dac..b9d8be32d 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -184,11 +184,7 @@ class Project extends Model # # * `projectPath` {String} The path to the directory to add. addPath: (projectPath, options) -> - directory = null - for provider in @directoryProviders - break if directory = provider.directoryForURISync?(projectPath) - directory ?= @defaultDirectoryProvider.directoryForURISync(projectPath) - + directory = @getDirectoryForProjectPath(projectPath) return unless directory.existsSync() for existingDirectory in @getDirectories() return if existingDirectory.getPath() is directory.getPath() @@ -203,6 +199,13 @@ class Project extends Model unless options?.emitEvent is false @emitter.emit 'did-change-paths', @getPaths() + getDirectoryForProjectPath: (projectPath) -> + directory = null + for provider in @directoryProviders + break if directory = provider.directoryForURISync?(projectPath) + directory ?= @defaultDirectoryProvider.directoryForURISync(projectPath) + directory + # Public: remove a path from the project's list of root paths. # # * `projectPath` {String} The path to remove.