]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
Parse and apply /etc/snapper/zypp-plugin.conf
authorMartin Vidner <mvidner@suse.cz>
Wed, 6 Nov 2019 14:40:13 +0000 (15:40 +0100)
committerMartin Vidner <mvidner@suse.cz>
Fri, 13 Dec 2019 15:31:47 +0000 (16:31 +0100)
snapper/XmlFile.cc
snapper/XmlFile.h
zypp-plugin/snapper_zypp_plugin.cc

index 6b978bbfef4aed3c3ab019ad1dd2aecc815dbc97..c1972ac18890eb70acbdd4819c91cba4e6261be5 100644 (file)
@@ -137,6 +137,18 @@ namespace snapper
        return ret;
     }
 
+    bool
+    getValue(const xmlNode* node, string& value)
+    {
+       xmlChar* tmp = xmlNodeGetContent(node);
+       if (tmp == nullptr)
+           value = "";
+       else {
+           value = (const char *) tmp;
+           xmlFree(tmp);
+       }
+       return true;
+    }
 
     bool
     getChildValue(const xmlNode* node, const char* name, string& value)
@@ -172,6 +184,27 @@ namespace snapper
        return true;
     }
 
+    bool
+    getAttributeValue(const xmlNode* node, const char* name, string& value)
+    {
+       xmlChar* tmp = xmlGetNoNsProp(node, (const xmlChar *) name);
+       if (tmp == nullptr)
+           return false;
+       value = (const char *) tmp;
+       xmlFree(tmp);
+       return true;
+    }
+
+    bool
+    getAttributeValue(const xmlNode* node, const char* name, bool& value)
+    {
+       string tmp;
+       if (!getAttributeValue(node, name, tmp))
+           return false;
+
+       value = tmp == "true";
+       return true;
+    }
 
     void
     setChildValue(xmlNode* node, const char* name, const char* value)
index 663ca85d614dadec34d6901f3a93d646fbc52bd0..974d3349e008bc56d2d3b1ad2382788c62bcd715 100644 (file)
@@ -73,6 +73,8 @@ namespace snapper
     list<const xmlNode*> getChildNodes(const xmlNode* node, const char* name);
 
 
+    bool getValue(const xmlNode* node, string& value);
+
     bool getChildValue(const xmlNode* node, const char* name, string& value);
     bool getChildValue(const xmlNode* node, const char* name, bool& value);
 
@@ -89,6 +91,8 @@ namespace snapper
        return true;
     }
 
+    bool getAttributeValue(const xmlNode* node, const char* name, string& value);
+    bool getAttributeValue(const xmlNode* node, const char* name, bool& value);
 
     void setChildValue(xmlNode* node, const char* name, const char* value);
     void setChildValue(xmlNode* node, const char* name, const string& value);
index 1865efef62ca3315b13a23663d6d23a80a30d76a..2b5a40d8e32b602a2f1a1bc0d753db8751914458 100644 (file)
@@ -3,6 +3,8 @@
 // getppid
 #include <sys/types.h>
 #include <unistd.h>
+// fnmatch
+#include <fnmatch.h>
 
 #include <boost/regex.hpp>
 
@@ -19,6 +21,7 @@ using snapper::Exception;
 using snapper::CodeLocation;
 #include "client/commands.h"
 #include "snapper/Log.h"
+#include "snapper/XmlFile.h"
 
 #include "zypp_commit_plugin.h"
 
@@ -36,11 +39,71 @@ ostream& operator <<(ostream& os, set<string> ss) {
     return os;
 }
 
+
 class SnapperZyppPlugin : public ZyppCommitPlugin {
 public:
+    struct SolvableMatcher {
+       enum class Kind {
+           Glob,
+           Regex
+       };
+       string pattern;
+       Kind kind;
+       bool important;
+
+       SolvableMatcher(string apattern, Kind akind, bool aimportant)
+       : pattern(apattern)
+       , kind(akind)
+       , important(aimportant)
+       {}
+
+       bool match(const string& solvable) {
+           y2deb("match? " << solvable << " by " << ((kind == Kind::Glob)? "GLOB '": "REGEX '") << pattern << '\'');
+           bool res;
+           if (kind == Kind::Glob) {
+               static const int flags = 0;
+               res = fnmatch(pattern.c_str(), solvable.c_str(), flags) == 0;
+           }
+           else {
+               // POSIX Extended Regular Expression Syntax
+               boost::regex rx_pattern(pattern, boost::regex::extended);
+               res = boost::regex_match(solvable, rx_pattern);
+           }
+           y2deb("-> " << res);
+           return res;
+       }
+
+       static vector<SolvableMatcher> load_config() {
+           vector<SolvableMatcher> result;
+
+           XmlFile config("/etc/snapper/zypp-plugin.conf");
+           // FIXME test parse errors
+           const xmlNode* root = config.getRootElement();
+           const xmlNode* solvables_n = getChildNode(root, "solvables");
+           const list<const xmlNode*> solvables_l = getChildNodes(solvables_n, "solvable");
+           for (auto it = solvables_l.begin(); it != solvables_l.end(); ++it) {
+               string pattern;
+               Kind kind = Kind::Regex;
+               bool important = false;
+
+               getAttributeValue(*it, "important", important);
+               string kind_s;
+               getAttributeValue(*it, "match", kind_s);
+               if (kind_s == "w") { // w for wildcard
+                   kind = Kind::Glob;
+               }
+               getValue(*it, pattern);
+
+               result.emplace_back(SolvableMatcher(pattern, kind, important));
+           }
+           return result;
+       }
+    };
+
     SnapperZyppPlugin()
     : dbus_conn(DBUS_BUS_SYSTEM)
     , pre_snapshot_num(0)
+    , solvable_matchers(SolvableMatcher::load_config())
     {
        snapshot_description = "zypp(%s)"; // % basename(readlink("/proc/%d/exe" % getppid()))
     }
@@ -147,12 +210,14 @@ private:
     string snapshot_description;
     map<string, string> userdata;
 
+    vector<SolvableMatcher> solvable_matchers;
+
     map<string, string> get_userdata(const Message&);
 
     // FIXME: what does the todo flag mean?
     set<string> get_solvables(const Message&, bool todo);
 
-    void match_solvables(const set<string>&, bool& found, bool& important);
+    void match_solvables(const set<string>& solvables, bool& found, bool& important);
 
     unsigned int create_pre_snapshot(string config_name, string description, string cleanup, map<string, string> userdata);
 };
@@ -192,9 +257,19 @@ set<string> SnapperZyppPlugin::get_solvables(const Message& msg, bool todo) {
     return result;
 }
 
-void SnapperZyppPlugin::match_solvables(const set<string>&, bool& found, bool& important) {
-    found = true;
-    important = true;
+void SnapperZyppPlugin::match_solvables(const set<string>& solvables, bool& found, bool& important) {
+    found = false;
+    important = false;
+    for (auto s: solvables) {
+       for (auto matcher: solvable_matchers) {
+           if (matcher.match(s)) {
+               found = true;
+               important = important || matcher.important;
+               if (found && important)
+                   return; // short circuit
+           }
+       }
+    }
 }
 
 bool