fileUtils: Refactor collectFromDatadirs to be a generator

This change enables mapping each collected file to a Promise in
asynchronous operations.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2364>
This commit is contained in:
Evan Welsh 2022-11-29 20:17:20 -06:00 committed by Marge Bot
parent 577d1ecf41
commit b7c097ba79
4 changed files with 40 additions and 16 deletions

View File

@ -6,7 +6,20 @@ const { Gio, GLib } = imports.gi;
var { loadInterfaceXML } = imports.misc.dbusUtils; var { loadInterfaceXML } = imports.misc.dbusUtils;
function collectFromDatadirs(subdir, includeUserDir, processFile) { /**
* @typedef {object} SubdirInfo
* @property {Gio.File} dir the file object for the subdir
* @property {Gio.FileInfo} info the file descriptor for the subdir
*/
/**
* @param {string} subdir the subdirectory to search within the data directories
* @param {boolean} includeUserDir whether the user's data directory should also be searched in addition
* to the system data directories
* @returns {Generator<SubdirInfo, void, void>} a generator which yields file info for subdirectories named
* `subdir` within data directories
*/
function* collectFromDatadirs(subdir, includeUserDir) {
let dataDirs = GLib.get_system_data_dirs(); let dataDirs = GLib.get_system_data_dirs();
if (includeUserDir) if (includeUserDir)
dataDirs.unshift(GLib.get_user_data_dir()); dataDirs.unshift(GLib.get_user_data_dir());
@ -18,14 +31,14 @@ function collectFromDatadirs(subdir, includeUserDir, processFile) {
let fileEnum; let fileEnum;
try { try {
fileEnum = dir.enumerate_children('standard::name,standard::type', fileEnum = dir.enumerate_children('standard::name,standard::type',
Gio.FileQueryInfoFlags.NONE, null); Gio.FileQueryInfoFlags.NONE, null);
} catch (e) { } catch (e) {
fileEnum = null; fileEnum = null;
} }
if (fileEnum != null) { if (fileEnum != null) {
let info; let info;
while ((info = fileEnum.next_file(null))) while ((info = fileEnum.next_file(null)))
processFile(fileEnum.get_child(info), info); yield {dir: fileEnum.get_child(info), info};
} }
} }
} }

View File

@ -571,10 +571,10 @@ var ExtensionManager = class extends Signals.EventEmitter {
if (!this.updatesSupported) if (!this.updatesSupported)
return; return;
FileUtils.collectFromDatadirs('extension-updates', true, (dir, info) => { for (const {dir, info} of FileUtils.collectFromDatadirs('extension-updates', true)) {
let fileType = info.get_file_type(); let fileType = info.get_file_type();
if (fileType !== Gio.FileType.DIRECTORY) if (fileType !== Gio.FileType.DIRECTORY)
return; continue;
let uuid = info.get_name(); let uuid = info.get_name();
let extensionDir = Gio.File.new_for_path( let extensionDir = Gio.File.new_for_path(
GLib.build_filenamev([global.userdatadir, 'extensions', uuid])); GLib.build_filenamev([global.userdatadir, 'extensions', uuid]));
@ -587,7 +587,7 @@ var ExtensionManager = class extends Signals.EventEmitter {
} finally { } finally {
FileUtils.recursivelyDeleteDir(dir, true); FileUtils.recursivelyDeleteDir(dir, true);
} }
}); }
} }
_loadExtensions() { _loadExtensions() {
@ -609,15 +609,17 @@ var ExtensionManager = class extends Signals.EventEmitter {
this._enabledExtensions = this._getEnabledExtensions(); this._enabledExtensions = this._getEnabledExtensions();
let perUserDir = Gio.File.new_for_path(global.userdatadir); let perUserDir = Gio.File.new_for_path(global.userdatadir);
FileUtils.collectFromDatadirs('extensions', true, (dir, info) => {
const extensionFiles = [...FileUtils.collectFromDatadirs('extensions', true)];
const extensionObjects = extensionFiles.map(({dir, info}) => {
let fileType = info.get_file_type(); let fileType = info.get_file_type();
if (fileType != Gio.FileType.DIRECTORY) if (fileType !== Gio.FileType.DIRECTORY)
return; return null;
let uuid = info.get_name(); let uuid = info.get_name();
let existing = this.lookup(uuid); let existing = this.lookup(uuid);
if (existing) { if (existing) {
log(`Extension ${uuid} already installed in ${existing.path}. ${dir.get_path()} will not be loaded`); log(`Extension ${uuid} already installed in ${existing.path}. ${dir.get_path()} will not be loaded`);
return; return null;
} }
let extension; let extension;
@ -626,12 +628,16 @@ var ExtensionManager = class extends Signals.EventEmitter {
: ExtensionType.SYSTEM; : ExtensionType.SYSTEM;
try { try {
extension = this.createExtensionObject(uuid, dir, type); extension = this.createExtensionObject(uuid, dir, type);
} catch (e) { } catch (error) {
logError(e, `Could not load extension ${uuid}`); logError(error, `Could not load extension ${uuid}`);
return; return null;
} }
return extension;
}).filter(extension => extension !== null);
for (const extension of extensionObjects)
this.loadExtension(extension); this.loadExtension(extension);
});
} }
_enableAllExtensions() { _enableAllExtensions() {

View File

@ -139,7 +139,8 @@ function loadRemoteSearchProviders(searchSettings) {
if (searchSettings.get_boolean('disable-external')) if (searchSettings.get_boolean('disable-external'))
return []; return [];
FileUtils.collectFromDatadirs('search-providers', false, loadRemoteSearchProvider); for (const {dir} of FileUtils.collectFromDatadirs('search-providers', false))
loadRemoteSearchProvider(dir);
let sortOrder = searchSettings.get_strv('sort-order'); let sortOrder = searchSettings.get_strv('sort-order');

View File

@ -126,8 +126,12 @@ function _loadMode(file, info) {
_modes[modeName]['isPrimary'] = true; _modes[modeName]['isPrimary'] = true;
} }
/**
* Loads external session modes from the system data directories.
*/
function _loadModes() { function _loadModes() {
FileUtils.collectFromDatadirs('modes', false, _loadMode); for (const {dir, info} of FileUtils.collectFromDatadirs('modes', false))
_loadMode(dir, info);
} }
function listModes() { function listModes() {