diff --git a/lib/shared/settings.js b/lib/shared/settings.js index f0932107..8ece9c51 100644 --- a/lib/shared/settings.js +++ b/lib/shared/settings.js @@ -110,6 +110,8 @@ export class ConfigManager extends GObject.Object { const defaultContents = this.loadFileContents(defaultFile); Logger.trace(defaultContents); createdStream.write_all(defaultContents, null); + // close it, or the file can stay empty (#415) + createdStream.close(null); } } } @@ -137,7 +139,29 @@ export class ConfigManager extends GObject.Object { if (success) { const windowConfigContents = imports.byteArray.toString(contents); Logger.trace(`${windowConfigContents}`); - windowProps = JSON.parse(windowConfigContents); + try { + windowProps = JSON.parse(windowConfigContents); + if (!Array.isArray(windowProps?.overrides)) throw new Error("no overrides list"); + } catch (e) { + // An empty or broken file mustn't stop Forge from starting (#415): use the default + // rules. Forge rewrites the file on the next change of the rules (e.g. a window closing), + // so keep a copy of it first. + let backup = ""; + if (windowConfigContents.trim()) { + try { + const backupFile = Gio.File.new_for_path(`${windowConfigFile.get_path()}.bak`); + windowConfigFile.copy(backupFile, Gio.FileCopyFlags.OVERWRITE, null, null); + backup = `; it was copied to ${backupFile.get_path()}`; + } catch (copyError) { + backup = `; it couldn't be copied (${copyError.message})`; + } + } + console.warn( + `Forge: ${windowConfigFile.get_path()} is not valid (${e.message}); ` + + `using the default window rules${backup}` + ); + windowProps = this.loadDefaultWindowConfigContents(); + } } return windowProps; }