ExtensionSystem: introduce versioning

Require that all extensions have a "shell-version" property in their
metadata, which is an array of supported Shell versions.
Extensions can target a specific version triple or an entire stable
version.
Optionally, they can also require a specific GJS version, to ensure
compatibility.

https://bugzilla.gnome.org/show_bug.cgi?id=639255
This commit is contained in:
Giovanni Campagna 2011-01-11 22:42:34 +01:00
parent 6200daa5bb
commit 5412ce276c
2 changed files with 42 additions and 3 deletions

View File

@ -4,6 +4,8 @@ const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const St = imports.gi.St; const St = imports.gi.St;
const Config = imports.misc.config;
const ExtensionState = { const ExtensionState = {
ENABLED: 1, ENABLED: 1,
DISABLED: 2, DISABLED: 2,
@ -25,6 +27,36 @@ var disabledExtensions;
// GFile for user extensions // GFile for user extensions
var userExtensionsDir = null; var userExtensionsDir = null;
/**
* versionCheck:
* @required: an array of versions we're compatible with
* @current: the version we have
*
* Check if a component is compatible for an extension.
* @required is an array, and at least one version must match.
* @current must be in the format <major>.<minor>.<point>.<micro>
* <micro> is always ignored
* <point> is ignored if <minor> is even (so you can target the
* whole stable release)
* <minor> and <major> must match
* Each target version must be at least <major> and <minor>
*/
function versionCheck(required, current) {
let currentArray = current.split('.');
let major = currentArray[0];
let minor = currentArray[1];
let point = currentArray[2];
for (let i = 0; i < required.length; i++) {
let requiredArray = required[i].split('.');
if (requiredArray[0] == major &&
requiredArray[1] == minor &&
(requiredArray[2] == point ||
(requiredArray[2] == undefined && parseInt(minor) % 2 == 0)))
return true;
}
return false;
}
function loadExtension(dir, enabled, type) { function loadExtension(dir, enabled, type) {
let info; let info;
let baseErrorString = 'While loading extension from "' + dir.get_parse_name() + '": '; let baseErrorString = 'While loading extension from "' + dir.get_parse_name() + '": ';
@ -43,8 +75,8 @@ function loadExtension(dir, enabled, type) {
global.logError(baseErrorString + 'Failed to parse metadata.json: ' + e); global.logError(baseErrorString + 'Failed to parse metadata.json: ' + e);
return; return;
} }
let requiredProperties = ['uuid', 'name', 'description']; let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
for (let i = 0; i < requiredProperties; i++) { for (let i = 0; i < requiredProperties.length; i++) {
let prop = requiredProperties[i]; let prop = requiredProperties[i];
if (!meta[prop]) { if (!meta[prop]) {
global.logError(baseErrorString + 'missing "' + prop + '" property in metadata.json'); global.logError(baseErrorString + 'missing "' + prop + '" property in metadata.json');
@ -68,6 +100,12 @@ function loadExtension(dir, enabled, type) {
return; return;
} }
if (!versionCheck(meta['shell-version'], Config.PACKAGE_VERSION) ||
(meta['js-version'] && !versionCheck(meta['js-version'], Config.GJS_VERSION))) {
global.logError(baseErrorString + 'extension is not compatible with current GNOME Shell and/or GJS version');
return;
}
extensionMeta[meta.uuid] = meta; extensionMeta[meta.uuid] = meta;
extensionMeta[meta.uuid].type = type; extensionMeta[meta.uuid].type = type;
extensionMeta[meta.uuid].path = dir.get_path(); extensionMeta[meta.uuid].path = dir.get_path();

View File

@ -672,7 +672,8 @@ use an extension title clicktofocus@janedoe.example.com.'''
os.makedirs(extension_path) os.makedirs(extension_path)
meta = { 'name': name, meta = { 'name': name,
'description': description, 'description': description,
'uuid': uuid } 'uuid': uuid,
'shell-version': ['@VERSION@'] }
f = open(os.path.join(extension_path, 'metadata.json'), 'w') f = open(os.path.join(extension_path, 'metadata.json'), 'w')
try: try:
json.dump(meta, f) json.dump(meta, f)