diff --git a/src/main-process/atom-application.js b/src/main-process/atom-application.js index 61c44f6fd..a8642b34b 100644 --- a/src/main-process/atom-application.js +++ b/src/main-process/atom-application.js @@ -23,6 +23,11 @@ const ConfigSchema = require('../config-schema') const LocationSuffixRegExp = /(:\d+)(:\d+)?$/ +// Increment this when changing the serialization format of `${ATOM_HOME}/storage/application.json` used by +// AtomApplication::saveCurrentWindowOptions() and AtomApplication::loadPreviousWindowOptions() in a backward- +// incompatible way. +const APPLICATION_STATE_VERSION = '1' + const getDefaultPath = () => { const editor = atom.workspace.getActiveTextEditor() if (!editor || !editor.getPath()) { @@ -1139,27 +1144,56 @@ class AtomApplication extends EventEmitter { async saveCurrentWindowOptions (allowEmpty = false) { if (this.quitting) return - const states = [] - for (let window of this.getAllWindows()) { - if (!window.isSpec) states.push({initialPaths: window.projectRoots}) + const state = { + version: APPLICATION_STATE_VERSION, + windows: this.getAllWindows() + .filter(window => !window.isSpec) + .map(window => ({projectRoots: window.projectRoots})) } - states.reverse() + state.windows.reverse() - if (states.length > 0 || allowEmpty) { - await this.storageFolder.store('application.json', states) + if (state.windows.length > 0 || allowEmpty) { + await this.storageFolder.store('application.json', state) this.emit('application:did-save-state') } } async loadPreviousWindowOptions () { - const states = await this.storageFolder.load('application.json') - if (states) { - return states.map(state => ({ - foldersToOpen: state.initialPaths, + const state = await this.storageFolder.load('application.json') + if (!state) { + return [] + } + + if (state.version === APPLICATION_STATE_VERSION) { + // Atom >=1.36.1 + // Schema: {version: '1', windows: [{projectRoots: ['', ...]}, ...]} + return state.windows.map(each => ({ + foldersToOpen: each.projectRoots, devMode: this.devMode, safeMode: this.safeMode })) + } else if (state.version === undefined) { + // Atom <= 1.36.0 + // Schema: [{initialPaths: ['', ...]}, ...] + return await Promise.all( + state.map(async windowState => { + // Classify each window's initialPaths as directories or non-directories + const classifiedPaths = await Promise.all( + windowState.initialPaths.map(initialPath => new Promise(resolve => { + fs.isDirectory(initialPath, isDir => resolve({initialPath, isDir})) + })) + ) + + // Only accept initialPaths that are existing directories + return { + foldersToOpen: classifiedPaths.filter(({isDir}) => isDir).map(({initialPath}) => initialPath), + devMode: this.devMode, + safeMode: this.safeMode + } + }) + ) } else { + // Unrecognized version (from a newer Atom?) return [] } }