Last active
March 7, 2022 18:52
-
-
Save jow-/1ea62b00cad4172fc59d6efcef32569b to your computer and use it in GitHub Desktop.
Dependency specs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"depends": { | |
/* fs: filesystem dependencies | |
* Either an array of dictionaries (each item being an ORed alternative) | |
* or single dictionary. | |
*/ | |
"fs": [ | |
/* Satisfied if either a non-empty directory /sys/class/ieee80211 exists... */ | |
{ "directory": "/sys/class/ieee80211" }, | |
/* ... or an executable file /usr/bin/whatever... */ | |
{ "executable": "/usr/bin/whatever" }, | |
/* ... or a regular file /etc/config/blub */ | |
{ "file": "/etc/config/blub" } | |
], | |
/* uci: uci dependencies | |
* Either an array of dictionaries (each item being an ORed alternative) | |
* or single dictionary. | |
*/ | |
"uci": [ | |
/* Satisfied if non-empty "foo" uci config exists ... */ | |
{ "foo": true }, | |
/* Satisfied if at least one typed, non-empty section "bar" in config "foo" exists */ | |
{ "foo": { "@bar": true } }, | |
/* Satisfied if at least one typed section "bar" in config "foo" with option "baz" exists */ | |
{ "foo": { "@bar": { "baz": true } } }, | |
/* Satisfied if at least one typed section "bar" in config "foo" with option "baz" equal to "qrx" exists */ | |
{ "foo": { "@bar": { "baz": "qrx" } } }, | |
/* Satisfied if a named, non-empty section "abc" in config "foo" exists */ | |
{ "foo": { "abc": true } }, | |
/* Satisfied if a named section "abc" in config "foo" with option "baz" exists */ | |
{ "foo": { "abc": { "baz": true } } }, | |
/* Satisfied if a named section "abc" in config "foo" with option "baz" equal to "qrx" exists */ | |
{ "foo": { "abc": { "baz": "qrx" } } }, | |
] | |
} | |
// If there's only one alternative, the array container may be omitted: | |
"depends": { | |
"fs": { "file": "/etc/config/blub" }, | |
"uci": { "wireless": { "@wifi-device": true } } | |
} | |
// Multiple fields within a dictionary are AND-ed | |
"depends": { | |
"fs": { | |
"executable": "/sbin/fw4", | |
"file": "/etc/config/firewall" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function check_fs_depends(spec) { | |
for (let path, kind in spec) { | |
if (kind == 'directory') { | |
if (!length(fs.lsdir(path))) | |
return false; | |
} | |
else if (kind == 'executable') { | |
let stat = fs.stat(path); | |
if (stat?.type != 'file' || stat?.user_exec == false) | |
return false; | |
} | |
else if (kind == 'file') { | |
let stat = fs.stat(path); | |
if (stat?.type != 'file') | |
return false; | |
} | |
} | |
return true; | |
} | |
function check_uci_depends_options(conf, s, opts) { | |
if (type(opts) == 'string') { | |
return (s['.type'] == opts); | |
} | |
else if (opts === true) { | |
for (let option, value in s) | |
if (ord(option) != 46) | |
return true; | |
} | |
else if (type(opts) == 'object') { | |
for (let option, value in opts) { | |
let sval = s[option]; | |
if (type(sval) == 'array') { | |
if (!(value in sval)) | |
return false; | |
} | |
else if (value === true) { | |
if (sval == null) | |
return false; | |
} | |
else { | |
if (sval != value) | |
return false; | |
} | |
} | |
} | |
return true; | |
} | |
function check_uci_depends_section(conf, sect) { | |
for (let section, options in sect) { | |
let stype = match(section, /^@([A-Za-z0-9_-]+)$/); | |
if (stype) { | |
let found = false; | |
uci.load(conf); | |
uci.foreach(conf, stype[1], (s) => { | |
if (check_uci_depends_options(conf, s, options)) { | |
found = true; | |
return false; | |
} | |
}); | |
if (!found) | |
return false; | |
} | |
else { | |
let s = uci.get_all(conf, section); | |
if (!s || !check_uci_depends_options(conf, s, options)) | |
return false; | |
} | |
} | |
return true; | |
} | |
function check_uci_depends(conf) { | |
for (let config, values in conf) { | |
if (values == true) { | |
let found = false; | |
uci.load(config); | |
uci.foreach(config, null, () => { found = true }); | |
if (!found) | |
return false; | |
} | |
else if (type(values) == 'object') { | |
if (!check_uci_depends_section(config, values)) | |
return false; | |
} | |
} | |
return true; | |
} | |
function check_depends(spec) { | |
if (type(spec?.depends?.fs) in ['array', 'object']) { | |
let satisfied = false; | |
let alternatives = (type(spec.depends.fs) == 'array') ? spec.depends.fs : [ spec.depends.fs ]; | |
for (let alternative in alternatives) { | |
if (check_fs_depends(alternative)) { | |
satisfied = true; | |
break; | |
} | |
} | |
if (!satisfied) | |
return false; | |
} | |
if (type(spec?.depends?.uci) in ['array', 'object']) { | |
let satisfied = false; | |
let alternatives = (type(spec.depends.uci) == 'array') ? spec.depends.uci : [ spec.depends.uci ]; | |
for (let alternative in alternatives) { | |
if (check_uci_depends(alternative)) { | |
satisfied = true; | |
break; | |
} | |
} | |
if (!satisfied) | |
return false; | |
} | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment