From: Martin Vidner Date: Wed, 6 Nov 2019 14:40:13 +0000 (+0100) Subject: Parse and apply /etc/snapper/zypp-plugin.conf X-Git-Tag: v0.8.7^2~27 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=eb145c273b736b635ef7b3a3be0e39890955187f;p=thirdparty%2Fsnapper.git Parse and apply /etc/snapper/zypp-plugin.conf --- diff --git a/snapper/XmlFile.cc b/snapper/XmlFile.cc index 6b978bbf..c1972ac1 100644 --- a/snapper/XmlFile.cc +++ b/snapper/XmlFile.cc @@ -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) diff --git a/snapper/XmlFile.h b/snapper/XmlFile.h index 663ca85d..974d3349 100644 --- a/snapper/XmlFile.h +++ b/snapper/XmlFile.h @@ -73,6 +73,8 @@ namespace snapper list 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); diff --git a/zypp-plugin/snapper_zypp_plugin.cc b/zypp-plugin/snapper_zypp_plugin.cc index 1865efef..2b5a40d8 100644 --- a/zypp-plugin/snapper_zypp_plugin.cc +++ b/zypp-plugin/snapper_zypp_plugin.cc @@ -3,6 +3,8 @@ // getppid #include #include +// fnmatch +#include #include @@ -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 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 load_config() { + vector 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 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 userdata; + vector solvable_matchers; + map get_userdata(const Message&); // FIXME: what does the todo flag mean? set get_solvables(const Message&, bool todo); - void match_solvables(const set&, bool& found, bool& important); + void match_solvables(const set& solvables, bool& found, bool& important); unsigned int create_pre_snapshot(string config_name, string description, string cleanup, map userdata); }; @@ -192,9 +257,19 @@ set SnapperZyppPlugin::get_solvables(const Message& msg, bool todo) { return result; } -void SnapperZyppPlugin::match_solvables(const set&, bool& found, bool& important) { - found = true; - important = true; +void SnapperZyppPlugin::match_solvables(const set& 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