Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 39 additions & 6 deletions lib/shared/theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,17 +196,50 @@ export class ThemeManagerBase extends GObject.Object {
if (this._needUpdate()) {
let originalCss = this.configMgr.defaultStylesheetFile;
let configCss = this.configMgr.stylesheetFile;
let copyConfigCss = Gio.File.new_for_path(this.configMgr.stylesheetFileName + ".bak");
let backupFine = configCss.copy(copyConfigCss, Gio.FileCopyFlags.OVERWRITE, null, null);
let copyFine = originalCss.copy(configCss, Gio.FileCopyFlags.OVERWRITE, null, null);
if (backupFine && copyFine) {
this.settings.set_uint("css-last-update", this.cssTag);
return true;
if (!originalCss || !configCss) return false;
// The backup goes next to the user's stylesheet (it went to "undefined.bak" in the
// working directory, #266)
let copyConfigCss = Gio.File.new_for_path(`${configCss.get_path()}.bak`);
try {
let backupFine = this._copyFile(configCss, copyConfigCss);
let copyFine = this._copyFile(originalCss, configCss);
if (backupFine && copyFine) {
this.settings.set_uint("css-last-update", this.cssTag);
return true;
}
} catch (e) {
console.warn(`Forge: can't update the stylesheet ${configCss.get_path()}: ${e.message}`);
}
}
return false;
}

/**
* Copies `source` over `target`. The copy gets the usual permissions of a new file, not those
* of `source`: the extension's own files can be read-only (e.g. on NixOS), and a read-only copy
* couldn't be overwritten at the next update (#266). A read-only copy left by an earlier
* version is replaced.
* @param {Gio.File} source
* @param {Gio.File} target
*/
_copyFile(source, target) {
const flags = Gio.FileCopyFlags.OVERWRITE | Gio.FileCopyFlags.TARGET_DEFAULT_PERMS;
try {
return source.copy(target, flags, null, null);
} catch (e) {
// (only a target that exists and is read-only: not when the source can't be read)
const readOnlyTarget =
e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.PERMISSION_DENIED) &&
target.query_exists(null) &&
!target
.query_info("access::can-write", Gio.FileQueryInfoFlags.NONE, null)
.get_attribute_boolean("access::can-write");
if (!readOnlyTarget) throw e;
target.delete(null);
return source.copy(target, flags, null, null);
}
}

/**
* Credits: ExtensionSystem.js:_callExtensionEnable()
*/
Expand Down