diff --git a/composer.json b/composer.json
index 71fb238..78d2a10 100644
--- a/composer.json
+++ b/composer.json
@@ -17,6 +17,7 @@
"require": {
"symfony/console": "^3.0",
"symfony/yaml": "^3.0",
- "noccylabs/downloader": "@dev"
+ "noccylabs/downloader": "@dev",
+ "symfony/expression-language": "^3.2"
}
}
diff --git a/docs/EXPRESSIONS.md b/docs/EXPRESSIONS.md
new file mode 100644
index 0000000..7f799c0
--- /dev/null
+++ b/docs/EXPRESSIONS.md
@@ -0,0 +1,29 @@
+Matching Expressions
+====================
+
+Hotfixes can provide a `for` key with an array of supported systems. The
+expressions are evaluated using Symfony's ExpressionLanguage and as such
+can handle some pretty complex stuff.
+
+For a hotfix to be considered supported, at least one of the expressions
+must evaluate to true.
+
+
+## Example:
+
+ for:
+ - lsb.id=='raspbian'
+ - lsb.id=='ubuntu' and lsb.release=>'16.04'
+
+
+## System facts
+
+### Distribution
+
+Information is retrieved using `lsb_release` or the `/etc/os-release` file.
+
+ lsb.id Distribution ID (ex. ubuntu or raspbian)
+ lsb.description Pretty description
+ lsb.release Version number (ex. 16.04 or 8)
+ lsb.codename Release codename (ex. xenial, not always present)
+
diff --git a/src/Command/ApplyCommand.php b/src/Command/ApplyCommand.php
index cc0cfef..2d52e69 100644
--- a/src/Command/ApplyCommand.php
+++ b/src/Command/ApplyCommand.php
@@ -10,7 +10,10 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Question\ChoiceQuestion;
+use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use NoccyLabs\Hotfix\Hotfix\Loader;
+use NoccyLabs\Hotfix\System\Facts;
+
class ApplyCommand extends Command
{
@@ -64,6 +67,28 @@ class ApplyCommand extends Command
} else {
$output->writeln("Warning: Hotfix is not signed or signature not valid!");
}
+
+ $requires = $hotfix->getRequirements();
+ if (count($requires)>0) {
+ $engine = new ExpressionLanguage();
+ $facts = Facts::getSystemFacts()->getFacts();
+ while (true) {
+ $expr = array_shift($requires);
+ $ret = $engine->evaluate($expr, $facts);
+ if ($ret) {
+ //$output->writeln("Hotfix is compatible with the current distribution>");
+ break;
+ }
+ if (count($requires)==0) {
+ $output->writeln("Error: This hotfix it not compatible with the current distribution>");
+ return false;
+ }
+ }
+ //} else {
+ //$output->writeln("Hotfix indicates universal compatibility.>");
+ }
+
+
$output->writeln("");
$output->writeln(" Hotfix: ".$hotfix->getName()."");
$output->writeln(" Author: ".$hotfix->getAuthor()."");
diff --git a/src/Hotfix/Hotfix.php b/src/Hotfix/Hotfix.php
index 5a510fa..1e9497f 100644
--- a/src/Hotfix/Hotfix.php
+++ b/src/Hotfix/Hotfix.php
@@ -70,6 +70,14 @@ class Hotfix
unlink($tmpfile);
}
+ public function getRequirements()
+ {
+ if (!array_key_exists('for',$this->header)) {
+ return [];
+ }
+ return $this->header['for'];
+ }
+
public function getSignedBy()
{
if (!$this->signer) {
diff --git a/src/System/Facts.php b/src/System/Facts.php
new file mode 100644
index 0000000..061d62a
--- /dev/null
+++ b/src/System/Facts.php
@@ -0,0 +1,51 @@
+read();
+ }
+ return $facts;
+ }
+
+ public function read()
+ {
+ $facts = [];
+ $has_lsb_release = exec("which lsb_release");
+ if ($has_lsb_release) {
+ exec("lsb_release -idrcs", $output);
+ $facts['lsb'] = (object)[
+ 'id' => strtolower($output[0]),
+ 'description' => $output[1],
+ 'release' => $output[2],
+ 'codename' => $output[3]
+ ];
+ } elseif (file_exists("/etc/os-release")) {
+ $ini = parse_ini_file("/etc/os-release");
+ $facts['lsb'] = (object)[
+ 'id' => strtolower(@$ini['ID']),
+ 'description' => @$ini['PRETTY_NAME'],
+ 'release' => @$ini['VERSION_ID'],
+ 'codename' => @$ini['VERSION_CODENAME']
+ ];
+ }
+
+ $this->facts = $facts;
+ }
+
+ public function getFacts()
+ {
+ return $this->facts;
+ }
+
+}