From 01bd45ef4c13fa778683c1811dec474fec03c005 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Thu, 20 Dec 2018 15:59:41 -0500 Subject: [PATCH] When only a file is specified, don't open the parent directory --- spec/atom-environment-spec.js | 2 +- src/atom-environment.js | 64 +++++++++++++++++++++++------------ 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/spec/atom-environment-spec.js b/spec/atom-environment-spec.js index aea5313e8..bb95bd49c 100644 --- a/spec/atom-environment-spec.js +++ b/spec/atom-environment-spec.js @@ -652,7 +652,7 @@ describe('AtomEnvironment', () => { it("adds it to the project's paths", async () => { const pathToOpen = __filename await atom.openLocations([{pathToOpen}]) - expect(atom.project.getPaths()[0]).toBe(__dirname) + expect(atom.project.getPaths()).toEqual([]) }) describe('then a second path is opened with forceAddToWindow', () => { diff --git a/src/atom-environment.js b/src/atom-environment.js index 915ff78f1..76abb7a5e 100644 --- a/src/atom-environment.js +++ b/src/atom-environment.js @@ -1,5 +1,6 @@ const crypto = require('crypto') const path = require('path') +const util = require('util') const {ipcRenderer} = require('electron') const _ = require('underscore-plus') @@ -44,6 +45,8 @@ const TextBuffer = require('text-buffer') const TextEditorRegistry = require('./text-editor-registry') const AutoUpdateManager = require('./auto-update-manager') +const stat = util.promisify(fs.stat); + let nextId = 0 // Essential: Atom global for dealing with packages, themes, menus, and the window. @@ -1358,42 +1361,61 @@ or use Pane::saveItemAs for programmatic saving.`) async openLocations (locations) { const needsProjectPaths = this.project && this.project.getPaths().length === 0 - const foldersToAddToProject = [] + const foldersToAddToProject = new Set() const fileLocationsToOpen = [] - function pushFolderToOpen (folder) { - if (!foldersToAddToProject.includes(folder)) { - foldersToAddToProject.push(folder) - } - } + // Asynchronously fetch stat information about each requested path to open. If the path does not + // exist, fetch stat information about its parent directory, too. + const locationStats = await Promise.all( + locations.map(async location => { + const payload = {location, stats: null, parentStats: null} - for (const location of locations) { - const {pathToOpen} = location - if (pathToOpen && (needsProjectPaths || location.forceAddToWindow)) { - if (fs.existsSync(pathToOpen)) { - pushFolderToOpen(this.project.getDirectoryForProjectPath(pathToOpen).getPath()) - } else if (fs.existsSync(path.dirname(pathToOpen))) { - pushFolderToOpen(this.project.getDirectoryForProjectPath(path.dirname(pathToOpen)).getPath()) - } else { - pushFolderToOpen(this.project.getDirectoryForProjectPath(pathToOpen).getPath()) + if (!location.pathToOpen) { + return payload } - } - if (!fs.isDirectorySync(pathToOpen)) { - fileLocationsToOpen.push(location) + payload.stats = await stat(location.pathToOpen).catch(() => null) + if (!payload.stats) { + payload.parentStats = await stat(path.dirname(location.pathToOpen)).catch(() => null) + } + + return payload; + }), + ); + + for (const {location, stats, parentStats} of locationStats) { + const {pathToOpen} = location + + if (pathToOpen && (needsProjectPaths || location.forceAddToWindow)) { + if (stats !== null) { + // Path exists + if (stats.isDirectory()) { + // Directory: add as a project folder + foldersToAddToProject.add(this.project.getDirectoryForProjectPath(pathToOpen).getPath()) + } else if (stats.isFile()) { + // File: add as a file location + fileLocationsToOpen.push(location) + } + } else if (parentStats !== null && parentStats.isDirectory()) { + // Parent directory exists + foldersToAddToProject.add(this.project.getDirectoryForProjectPath(path.dirname(pathToOpen)).getPath()) + } else { + // Attempt to interpret as a URI from a different directory provider + foldersToAddToProject.add(this.project.getDirectoryForProjectPath(pathToOpen).getPath()) + } } if (location.hasWaitSession) this.pathsWithWaitSessions.add(pathToOpen) } let restoredState = false - if (foldersToAddToProject.length > 0) { - const state = await this.loadState(this.getStateKey(foldersToAddToProject)) + if (foldersToAddToProject.size > 0) { + const state = await this.loadState(this.getStateKey(Array.from(foldersToAddToProject))) // only restore state if this is the first path added to the project if (state && needsProjectPaths) { const files = fileLocationsToOpen.map((location) => location.pathToOpen) - await this.attemptRestoreProjectStateForPaths(state, foldersToAddToProject, files) + await this.attemptRestoreProjectStateForPaths(state, Array.from(foldersToAddToProject), files) restoredState = true } else { for (let folder of foldersToAddToProject) {