Save application state with a version-tagged schema

Load application state from the current or previous application.json 
schema. Filter out file paths when loading old state.
This commit is contained in:
Ash Wilson 2019-04-24 10:18:47 -04:00
parent f4be123137
commit 2b1aaa7a13
No known key found for this signature in database
GPG Key ID: 81B1DDB704F69D2A

View File

@ -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: ['<root-dir>', ...]}, ...]}
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: ['<root-dir>', ...]}, ...]
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 []
}
}