]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
- coding style 775/head
authorArvin Schnell <aschnell@suse.de>
Wed, 25 Jan 2023 10:11:21 +0000 (11:11 +0100)
committerArvin Schnell <aschnell@suse.de>
Wed, 25 Jan 2023 10:11:21 +0000 (11:11 +0100)
zypp-plugin/Makefile.am
zypp-plugin/snapper-zypp-commit-plugin.cc [new file with mode: 0644]
zypp-plugin/snapper-zypp-commit-plugin.h [new file with mode: 0644]
zypp-plugin/snapper-zypp-plugin.cc [deleted file]
zypp-plugin/zypp-commit-plugin.cc
zypp-plugin/zypp-commit-plugin.h
zypp-plugin/zypp-plugin.cc
zypp-plugin/zypp-plugin.h

index 5970cb0b6c0885b89a2fa885dee0c01ab68dc225..a293a5d2e8b1a8692b3065a00182af7193548229 100644 (file)
@@ -12,7 +12,7 @@ plugin_PROGRAMS = snapper-zypp-plugin
 AM_CPPFLAGS = $(DBUS_CFLAGS) $(XML2_CFLAGS) $(JSONC_CFLAGS)
 
 snapper_zypp_plugin_SOURCES = \
-       snapper-zypp-plugin.cc \
+       snapper-zypp-commit-plugin.cc snapper-zypp-commit-plugin.h \
        solvable-matcher.cc solvable-matcher.h \
        zypp-commit-plugin.cc zypp-commit-plugin.h \
        zypp-plugin.cc zypp-plugin.h
diff --git a/zypp-plugin/snapper-zypp-commit-plugin.cc b/zypp-plugin/snapper-zypp-commit-plugin.cc
new file mode 100644 (file)
index 0000000..103f847
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) [2019-2023] SUSE LLC
+ *
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, contact SUSE LLC.
+ *
+ * To contact SUSE about this file by physical or electronic mail, you may
+ * find current contact information at www.suse.com.
+ */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <map>
+#include <set>
+#include <string>
+#include <regex>
+#include <boost/algorithm/string.hpp>
+
+#include <json.h>
+// a collision with client/errors.h
+#ifdef error_description
+#undef error_description
+#endif
+
+#include "dbus/DBusConnection.h"
+#include "snapper/Exception.h"
+#include "client/commands.h"
+#include "client/errors.h"
+
+#include "snapper-zypp-commit-plugin.h"
+
+using namespace std;
+using namespace snapper;
+
+
+ostream&
+operator<<(ostream& os, const set<string>& ss)
+{
+    bool seen_first = false;
+    os << '{';
+    for (auto s : ss)
+    {
+       if (seen_first)
+           os << ", ";
+
+       os << s;
+       seen_first = true;
+    }
+    os << '}';
+    return os;
+}
+
+
+ProgramOptions::ProgramOptions()
+{
+    const char* s;
+
+    s = getenv("SNAPPER_ZYPP_PLUGIN_CONFIG");
+    if (s)
+       plugin_config = s;
+    else
+       plugin_config = locate_file("zypp-plugin.conf", "/etc/snapper", "/usr/share/snapper");
+
+    s = getenv("SNAPPER_ZYPP_PLUGIN_SNAPPER_CONFIG");
+    if (s)
+       snapper_config = s;
+
+    s = getenv("SNAPPER_ZYPP_PLUGIN_DBUS_SESSION");
+    if (s)
+       bus = DBUS_BUS_SESSION;
+}
+
+
+SnapperZyppCommitPlugin::SnapperZyppCommitPlugin(const ProgramOptions& opts)
+    : snapper_cfg(opts.snapper_config), dbus_conn(opts.bus), pre_snapshot_num(0),
+      solvable_matchers(SolvableMatcher::load_config(opts.plugin_config))
+{
+    string caller_prog;
+    readlink(sformat("/proc/%d/exe", getppid()), caller_prog);
+    snapshot_description = sformat("zypp(%s)", basename(caller_prog).c_str());
+}
+
+
+ZyppCommitPlugin::Message
+SnapperZyppCommitPlugin::plugin_begin(const Message& msg)
+{
+    cerr << "INFO:" << "PLUGINBEGIN" << endl;
+    userdata = get_userdata(msg);
+
+    return ack();
+}
+
+
+ZyppCommitPlugin::Message
+SnapperZyppCommitPlugin::plugin_end(const Message& msg)
+{
+    cerr << "INFO:" << "PLUGINEND" << endl;
+    return ack();
+}
+
+
+ZyppCommitPlugin::Message
+SnapperZyppCommitPlugin::commit_begin(const Message& msg)
+{
+    cerr << "INFO:" << "COMMITBEGIN" << endl;
+
+    set<string> solvables = get_solvables(msg, Phase::BEFORE);
+    cerr << "DEBUG:" << "solvables: " << solvables << endl;
+
+    bool found, important;
+    match_solvables(solvables, found, important);
+    cerr << "INFO:" << "found: " << found << ", important: " << important << endl;
+
+    if (found || important)
+    {
+       userdata["important"] = important ? "yes" : "no";
+
+       try
+       {
+           cerr << "INFO:" << "creating pre snapshot" << endl;
+           pre_snapshot_num = command_create_pre_snapshot(
+               dbus_conn, snapper_cfg,
+               snapshot_description, cleanup_algorithm, userdata
+               );
+           cerr << "DEBUG:" << "created pre snapshot " << pre_snapshot_num << endl;
+       }
+       catch (const DBus::ErrorException& ex)
+       {
+           SN_CAUGHT(ex);
+           cerr << "ERROR:" << error_description(ex) << endl;
+       }
+       catch (const Exception& ex)
+       {
+           SN_CAUGHT(ex);
+       }
+    }
+
+    return ack();
+}
+
+
+ZyppCommitPlugin::Message
+SnapperZyppCommitPlugin::commit_end(const Message& msg)
+{
+    cerr << "INFO:" << "COMMITEND" << endl;
+
+    if (pre_snapshot_num != 0)
+    {
+       set<string> solvables = get_solvables(msg, Phase::AFTER);
+       cerr << "DEBUG:" << "solvables: " << solvables << endl;
+
+       bool found, important;
+       match_solvables(solvables, found, important);
+       cerr << "INFO:" << "found: " << found << ", important: " << important << endl;
+
+       if (found || important)
+       {
+           userdata["important"] = important ? "yes" : "no";
+
+           try
+           {
+               cerr << "INFO:" << "setting snapshot data" << endl;
+               snapper::SMD modification_data;
+               modification_data.description = snapshot_description;
+               modification_data.cleanup = cleanup_algorithm;
+               modification_data.userdata = userdata;
+               command_set_snapshot(dbus_conn, snapper_cfg, pre_snapshot_num, modification_data);
+           }
+           catch (const DBus::ErrorException& ex)
+           {
+               SN_CAUGHT(ex);
+               cerr << "ERROR:" << error_description(ex) << endl;
+           }
+           catch (const Exception& ex)
+           {
+               SN_CAUGHT(ex);
+           }
+
+           try
+           {
+               cerr << "INFO:" << "creating post snapshot" << endl;
+               unsigned int post_snapshot_num = command_create_post_snapshot(
+                   dbus_conn, snapper_cfg,
+                   pre_snapshot_num, "", cleanup_algorithm, userdata
+                   );
+               cerr << "DEBUG:" << "created post snapshot " << post_snapshot_num << endl;
+           }
+           catch (const DBus::ErrorException& ex)
+           {
+               SN_CAUGHT(ex);
+               cerr << "ERROR:" << error_description(ex) << endl;
+           }
+           catch (const Exception& ex)
+           {
+               SN_CAUGHT(ex);
+           }
+       }
+       else
+       {
+           try
+           {
+               cerr << "INFO:" << "deleting pre snapshot" << endl;
+               vector<unsigned int> nums{ pre_snapshot_num };
+               bool verbose = false;
+               command_delete_snapshots(dbus_conn, snapper_cfg, nums, verbose);
+               cerr << "DEBUG:" << "deleted pre snapshot " << pre_snapshot_num << endl;
+           }
+           catch (const DBus::ErrorException& ex)
+           {
+               SN_CAUGHT(ex);
+               cerr << "ERROR:" << error_description(ex) << endl;
+           }
+           catch (const Exception& ex)
+           {
+               SN_CAUGHT(ex);
+           }
+       }
+    }
+    return ack();
+}
+
+
+const string SnapperZyppCommitPlugin::cleanup_algorithm = "number";
+
+
+map<string, string>
+SnapperZyppCommitPlugin::get_userdata(const Message& msg)
+{
+    map<string, string> result;
+    auto it = msg.headers.find("userdata");
+    if (it != msg.headers.end())
+    {
+       const string& userdata_s = it->second;
+       vector<string> key_values;
+       boost::split(key_values, userdata_s, boost::is_any_of(","));
+       for (auto kv : key_values)
+       {
+           static const regex rx_keyval("([^=]*)=(.+)", regex::extended);
+           smatch match;
+
+           if (regex_match(kv, match, rx_keyval))
+           {
+               string key = boost::trim_copy(match[1].str());
+               string value = boost::trim_copy(match[2].str());
+               result[key] = value;
+           }
+           else
+           {
+               cerr << "ERROR:" << "invalid userdata: expecting comma separated key=value pairs" << endl;
+           }
+       }
+    }
+    return result;
+}
+
+
+static json_object*
+object_get(json_object* obj, const char* name)
+{
+    json_object * result;
+    if (!json_object_object_get_ex(obj, name, &result))
+    {
+       cerr << "ERROR:" << '"' << name << "\" not found" << endl;
+       return NULL;
+    }
+    return result;
+}
+
+
+class JsonTokener
+{
+public:
+
+    JsonTokener()
+       : p(json_tokener_new())
+    {
+       if (!p)
+           throw runtime_error("out of memory");
+    }
+
+    ~JsonTokener()
+    {
+       json_tokener_free(p);
+    }
+
+    json_tokener* get() { return p; }
+
+private:
+
+    json_tokener* p;
+
+};
+
+
+set<string>
+SnapperZyppCommitPlugin::get_solvables(const Message& msg, Phase phase) const
+{
+    set<string> result;
+
+    JsonTokener tokener;
+    json_object* zypp = json_tokener_parse_ex(tokener.get(), msg.body.c_str(), msg.body.size());
+    json_tokener_error jerr = json_tokener_get_error(tokener.get());
+    if (jerr != json_tokener_success)
+    {
+       cerr << "ERROR:" << "parsing zypp JSON failed: "
+                        << json_tokener_error_desc(jerr) << endl;
+       return result;
+    }
+
+    // JSON structure:
+    // {"TransactionStepList":[{"type":"?","stage":"?","solvable":{"n":"mypackage"}}]}
+    // https://doc.opensuse.org/projects/libzypp/SLE12SP2/plugin-commit.html
+    json_object* steps = object_get(zypp, "TransactionStepList");
+    if (!steps)
+       return result;
+
+    if (json_object_get_type(steps) == json_type_array)
+    {
+       size_t len = json_object_array_length(steps);
+       for (size_t i = 0; i < len; ++i)
+       {
+           json_object* step = json_object_array_get_idx(steps, i);
+           bool have_type = json_object_object_get_ex(step, "type", NULL);
+           bool have_stage = json_object_object_get_ex(step, "stage", NULL);
+           if (have_type && (phase == Phase::BEFORE || have_stage))
+           {
+               json_object* solvable = object_get(step, "solvable");
+               if (!solvable)
+               {
+                   cerr << "ERROR:" << "in item #" << i << endl;
+                   continue;
+               }
+
+               json_object* name = object_get(solvable, "n");
+               if (!name)
+               {
+                   cerr << "ERROR:" << "in item #" << i << endl;
+                   continue;
+               }
+
+               if (json_object_get_type(name) != json_type_string)
+               {
+                   cerr << "ERROR:" << "\"n\" is not a string" << endl;
+                   cerr << "ERROR:" << "in item #" << i << endl;
+                   continue;
+               }
+               else
+               {
+                   const char * prize = json_object_get_string(name);
+                   result.insert(prize);
+               }
+           }
+       }
+    }
+
+    return result;
+}
+
+
+void
+SnapperZyppCommitPlugin::match_solvables(const set<string>& solvables, bool& found, bool& important) const
+{
+    found = false;
+    important = false;
+
+    for (const string& solvable : solvables)
+    {
+       for (const SolvableMatcher& solvable_matcher : solvable_matchers)
+       {
+           if (solvable_matcher.match(solvable))
+           {
+               found = true;
+
+               if (solvable_matcher.is_important())
+               {
+                   important = true;
+                   return; // short circuit
+               }
+           }
+       }
+    }
+}
+
+
+int
+main()
+{
+    if (getenv("DISABLE_SNAPPER_ZYPP_PLUGIN"))
+    {
+       cerr << "INFO:" << "$DISABLE_SNAPPER_ZYPP_PLUGIN is set - disabling snapper-zypp-plugin" << endl;
+       DummyZyppCommitPlugin plugin;
+       return plugin.main();
+    }
+
+    ProgramOptions options;
+    SnapperZyppCommitPlugin plugin(options);
+    return plugin.main();
+}
diff --git a/zypp-plugin/snapper-zypp-commit-plugin.h b/zypp-plugin/snapper-zypp-commit-plugin.h
new file mode 100644 (file)
index 0000000..cb519cd
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) [2019-2023] SUSE LLC
+ *
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, contact SUSE LLC.
+ *
+ * To contact SUSE about this file by physical or electronic mail, you may
+ * find current contact information at www.suse.com.
+ */
+
+#ifndef SNAPPER_ZYPP_COMMIT_PLUGIN_H
+#define SNAPPER_ZYPP_COMMIT_PLUGIN_H
+
+#include "zypp-commit-plugin.h"
+#include "solvable-matcher.h"
+
+
+// Normally the only configuration this program needs is
+// the zypp-plugin.conf file in /etc/snapper or /usr/share/snapper.
+// But for testing we need more places to inject mocks.
+// This is done with SNAPPER_ZYPP_PLUGIN_* environment variables.
+// (Using argv is not useful since libzypp does not use it in the
+// plugin protocol.)
+class ProgramOptions
+{
+public:
+
+    ProgramOptions();
+
+    string plugin_config;
+    string snapper_config = "root";
+    DBusBusType bus = DBUS_BUS_SYSTEM;
+
+};
+
+
+class SnapperZyppCommitPlugin : public ZyppCommitPlugin
+{
+public:
+
+    SnapperZyppCommitPlugin(const ProgramOptions& opts);
+
+    Message plugin_begin(const Message& msg) override;
+    Message plugin_end(const Message& msg) override;
+
+    Message commit_begin(const Message& msg) override;
+    Message commit_end(const Message& msg) override;
+
+private:
+
+    static const string cleanup_algorithm;
+
+    const string snapper_cfg;
+
+    DBus::Connection dbus_conn;
+    unsigned int pre_snapshot_num;
+    string snapshot_description;
+    map<string, string> userdata;
+
+    vector<SolvableMatcher> solvable_matchers;
+
+    map<string, string> get_userdata(const Message& msg);
+
+    enum class Phase { BEFORE, AFTER };
+
+    std::set<string> get_solvables(const Message& msg, Phase phase) const;
+
+    void match_solvables(const std::set<string>& solvables, bool& found, bool& important) const;
+
+};
+
+
+#endif
diff --git a/zypp-plugin/snapper-zypp-plugin.cc b/zypp-plugin/snapper-zypp-plugin.cc
deleted file mode 100644 (file)
index 7c044e8..0000000
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (c) [2019-2023] SUSE LLC
- *
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, contact SUSE LLC.
- *
- * To contact SUSE about this file by physical or electronic mail, you may
- * find current contact information at www.suse.com.
- */
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <iostream>
-#include <map>
-#include <set>
-#include <string>
-#include <regex>
-#include <boost/algorithm/string.hpp>
-
-using namespace std;
-
-#include <json.h>
-// a collision with client/errors.h
-#ifdef error_description
-#undef error_description
-#endif
-
-#include "dbus/DBusConnection.h"
-#include "snapper/Exception.h"
-using snapper::Exception;
-using snapper::CodeLocation;
-#include "client/commands.h"
-#include "client/errors.h"
-
-#include "zypp-commit-plugin.h"
-#include "solvable-matcher.h"
-
-ostream&
-operator<<(ostream& os, const set<string>& ss)
-{
-    bool seen_first = false;
-    os << '{';
-    for (auto s : ss)
-    {
-       if (seen_first)
-           os << ", ";
-
-       os << s;
-       seen_first = true;
-    }
-    os << '}';
-    return os;
-}
-
-
-// Normally the only configuration this program needs is
-// the zypp-plugin.conf file in /etc/snapper or /usr/share/snapper.
-// But for testing we need more places to inject mocks.
-// This is done with SNAPPER_ZYPP_PLUGIN_* environment variables.
-// (Using argv is not useful since libzypp does not use it in the
-// plugin protocol.)
-class ProgramOptions
-{
-
-public:
-
-    string plugin_config;
-    string snapper_config = "root";
-    DBusBusType bus = DBUS_BUS_SYSTEM;
-
-    ProgramOptions()
-    {
-       const char* s;
-
-       s = getenv("SNAPPER_ZYPP_PLUGIN_CONFIG");
-       if (s)
-           plugin_config = s;
-       else
-           plugin_config = locate_file("zypp-plugin.conf", "/etc/snapper", "/usr/share/snapper");
-
-       s = getenv("SNAPPER_ZYPP_PLUGIN_SNAPPER_CONFIG");
-       if (s)
-           snapper_config = s;
-
-       s = getenv("SNAPPER_ZYPP_PLUGIN_DBUS_SESSION");
-       if (s)
-           bus = DBUS_BUS_SESSION;
-    }
-
-};
-
-
-class SnapperZyppPlugin : public ZyppCommitPlugin
-{
-public:
-    SnapperZyppPlugin(const ProgramOptions& opts)
-    : snapper_cfg(opts.snapper_config)
-    , dbus_conn(opts.bus)
-    , pre_snapshot_num(0)
-    , solvable_matchers(SolvableMatcher::load_config(opts.plugin_config))
-    {
-       string caller_prog;
-       readlink(sformat("/proc/%d/exe", getppid()), caller_prog);
-       snapshot_description = sformat("zypp(%s)", basename(caller_prog).c_str());
-    }
-
-    Message plugin_begin(const Message& m) override {
-       cerr << "INFO:" << "PLUGINBEGIN" << endl;
-       userdata = get_userdata(m);
-
-       return ack();
-    }
-    Message plugin_end(const Message& m) override {
-       cerr << "INFO:" << "PLUGINEND" << endl;
-       return ack();
-    }
-    Message commit_begin(const Message& msg) override {
-       cerr << "INFO:" << "COMMITBEGIN" << endl;
-
-       set<string> solvables = get_solvables(msg, Phase::BEFORE);
-       cerr << "DEBUG:" << "solvables: " << solvables << endl;
-
-       bool found, important;
-       match_solvables(solvables, found, important);
-       cerr << "INFO:" << "found: " << found << ", important: " << important << endl;
-
-       if (found || important) {
-           userdata["important"] = important ? "yes" : "no";
-
-           try {
-               cerr << "INFO:" << "creating pre snapshot" << endl;
-               pre_snapshot_num = command_create_pre_snapshot(
-                   dbus_conn, snapper_cfg,
-                   snapshot_description, cleanup_algorithm, userdata
-               );
-               cerr << "DEBUG:" << "created pre snapshot " << pre_snapshot_num << endl;
-           }
-           catch (const DBus::ErrorException& ex) {
-               SN_CAUGHT(ex);
-               cerr << "ERROR:" << error_description(ex) << endl;
-           }
-           catch (const Exception& ex) {
-               SN_CAUGHT(ex);
-           }
-       }
-
-       return ack();
-    }
-
-    Message commit_end(const Message& msg) override {
-       cerr << "INFO:" << "COMMITEND" << endl;
-
-       if (pre_snapshot_num != 0) {
-           set<string> solvables = get_solvables(msg, Phase::AFTER);
-           cerr << "DEBUG:" << "solvables: " << solvables << endl;
-
-           bool found, important;
-           match_solvables(solvables, found, important);
-           cerr << "INFO:" << "found: " << found << ", important: " << important << endl;
-
-           if (found || important) {
-               userdata["important"] = important ? "yes" : "no";
-
-               try {
-                   cerr << "INFO:" << "setting snapshot data" << endl;
-                   snapper::SMD modification_data;
-                   modification_data.description = snapshot_description;
-                   modification_data.cleanup = cleanup_algorithm;
-                   modification_data.userdata = userdata;
-                   command_set_snapshot(
-                       dbus_conn, snapper_cfg,
-                       pre_snapshot_num, modification_data
-                   );
-               }
-               catch (const DBus::ErrorException& ex) {
-                   SN_CAUGHT(ex);
-                   cerr << "ERROR:" << error_description(ex) << endl;
-               }
-               catch (const Exception& ex) {
-                   SN_CAUGHT(ex);
-               }
-               try {
-                   cerr << "INFO:" << "creating post snapshot" << endl;
-                   unsigned int post_snapshot_num = command_create_post_snapshot(
-                       dbus_conn, snapper_cfg,
-                       pre_snapshot_num, "", cleanup_algorithm, userdata
-                   );
-                   cerr << "DEBUG:" << "created post snapshot " << post_snapshot_num << endl;
-               }
-               catch (const DBus::ErrorException& ex) {
-                   SN_CAUGHT(ex);
-                   cerr << "ERROR:" << error_description(ex) << endl;
-               }
-               catch (const Exception& ex) {
-                   SN_CAUGHT(ex);
-               }
-           }
-           else {
-               try {
-                   cerr << "INFO:" << "deleting pre snapshot" << endl;
-                   vector<unsigned int> nums{ pre_snapshot_num };
-                   bool verbose = false;
-                   command_delete_snapshots(dbus_conn, snapper_cfg, nums, verbose);
-                   cerr << "DEBUG:" << "deleted pre snapshot " << pre_snapshot_num << endl;
-               }
-               catch (const DBus::ErrorException& ex) {
-                   SN_CAUGHT(ex);
-                   cerr << "ERROR:" << error_description(ex) << endl;
-               }
-               catch (const Exception& ex) {
-                   SN_CAUGHT(ex);
-               }
-           }
-       }
-       return ack();
-    }
-
-private:
-
-    static const string cleanup_algorithm;
-
-    const string snapper_cfg;
-
-    DBus::Connection dbus_conn;
-    unsigned int pre_snapshot_num;
-    string snapshot_description;
-    map<string, string> userdata;
-
-    vector<SolvableMatcher> solvable_matchers;
-
-    map<string, string> get_userdata(const Message&);
-
-    enum class Phase { BEFORE, AFTER };
-
-    set<string> get_solvables(const Message&, Phase phase);
-
-    void match_solvables(const set<string>& solvables, bool& found, bool& important);
-
-};
-
-
-const string SnapperZyppPlugin::cleanup_algorithm = "number";
-
-
-map<string, string>
-SnapperZyppPlugin::get_userdata(const Message& msg)
-{
-    map<string, string> result;
-    auto it = msg.headers.find("userdata");
-    if (it != msg.headers.end()) {
-       const string& userdata_s = it->second;
-       vector<string> key_values;
-       boost::split(key_values, userdata_s, boost::is_any_of(","));
-       for (auto kv : key_values)
-       {
-           static const regex rx_keyval("([^=]*)=(.+)", regex::extended);
-           smatch match;
-
-           if (regex_match(kv, match, rx_keyval))
-           {
-               string key = boost::trim_copy(match[1].str());
-               string value = boost::trim_copy(match[2].str());
-               result[key] = value;
-           }
-           else
-           {
-               cerr << "ERROR:" << "invalid userdata: expecting comma separated key=value pairs" << endl;
-           }
-       }
-    }
-    return result;
-}
-
-
-static
-json_object*
-object_get(json_object* obj, const char* name)
-{
-    json_object * result;
-    if (!json_object_object_get_ex(obj, name, &result)) {
-       cerr << "ERROR:" << '"' << name << "\" not found" << endl;
-       return NULL;
-    }
-    return result;
-}
-
-
-class JsonTokener
-{
-public:
-
-    JsonTokener()
-       : p(json_tokener_new())
-    {
-       if (!p)
-           throw runtime_error("out of memory");
-    }
-
-    ~JsonTokener()
-    {
-       json_tokener_free(p);
-    }
-
-    json_tokener* get() { return p; }
-
-private:
-
-    json_tokener* p;
-
-};
-
-
-set<string>
-SnapperZyppPlugin::get_solvables(const Message& msg, Phase phase)
-{
-    set<string> result;
-
-    JsonTokener tokener;
-    json_object* zypp = json_tokener_parse_ex(tokener.get(), msg.body.c_str(), msg.body.size());
-    json_tokener_error jerr = json_tokener_get_error(tokener.get());
-    if (jerr != json_tokener_success) {
-       cerr << "ERROR:" << "parsing zypp JSON failed: "
-                        << json_tokener_error_desc(jerr) << endl;
-       return result;
-    }
-
-    // JSON structure:
-    // {"TransactionStepList":[{"type":"?","stage":"?","solvable":{"n":"mypackage"}}]}
-    // https://doc.opensuse.org/projects/libzypp/SLE12SP2/plugin-commit.html
-    json_object * steps = object_get(zypp, "TransactionStepList");
-    if (!steps)
-       return result;
-
-    if (json_object_get_type(steps) == json_type_array) {
-       size_t i, len = json_object_array_length(steps);
-       for (i = 0; i < len; ++i) {
-           json_object * step = json_object_array_get_idx(steps, i);
-           bool have_type = json_object_object_get_ex(step, "type", NULL);
-           bool have_stage = json_object_object_get_ex(step, "stage", NULL);
-           if (have_type && (phase == Phase::BEFORE || have_stage)) {
-               json_object * solvable = object_get(step, "solvable");
-               if (!solvable) {
-                   cerr << "ERROR:" << "in item #" << i << endl;
-                   continue;
-               }
-               json_object * name = object_get(solvable, "n");
-               if (!name) {
-                   cerr << "ERROR:" << "in item #" << i << endl;
-                   continue;
-               }
-               if (json_object_get_type(name) != json_type_string) {
-                   cerr << "ERROR:" << "\"n\" is not a string" << endl;
-                   cerr << "ERROR:" << "in item #" << i << endl;
-                   continue;
-               }
-               else {
-                   const char * prize = json_object_get_string(name);
-                   result.insert(prize);
-               }
-           }
-       }
-    }
-
-    return result;
-}
-
-
-void
-SnapperZyppPlugin::match_solvables(const set<string>& solvables, bool& found, bool& important)
-{
-    found = false;
-    important = false;
-
-    for (const string& solvable : solvables)
-    {
-       for (const SolvableMatcher& solvable_matcher : solvable_matchers)
-       {
-           if (solvable_matcher.match(solvable))
-           {
-               found = true;
-
-               if (solvable_matcher.is_important())
-               {
-                   important = true;
-                   return; // short circuit
-               }
-           }
-       }
-    }
-}
-
-
-int
-main()
-{
-    if (getenv("DISABLE_SNAPPER_ZYPP_PLUGIN") != nullptr) {
-       cerr << "INFO:" << "$DISABLE_SNAPPER_ZYPP_PLUGIN is set - disabling snapper-zypp-plugin" << endl;
-       ZyppCommitPlugin plugin;
-       return plugin.main();
-    }
-
-    ProgramOptions options;
-    SnapperZyppPlugin plugin(options);
-    return plugin.main();
-}
index 8b4b1569f15e3f2f8c01b551997faebd86bed127..aa4e09038c78e10d14c187d9ee01afeea9fa6083 100644 (file)
 #include "zypp-commit-plugin.h"
 
 
-ZyppPlugin::Message ZyppCommitPlugin::dispatch(const Message& msg)
+ZyppPlugin::Message
+ZyppCommitPlugin::dispatch(const Message& msg)
 {
     if (msg.command == "PLUGINBEGIN") {
        return plugin_begin(msg);
     }
+
     if (msg.command == "PLUGINEND") {
        return plugin_end(msg);
     }
+
     if (msg.command == "COMMITBEGIN") {
        return commit_begin(msg);
     }
+
     if (msg.command == "COMMITEND") {
        return commit_end(msg);
     }
index 8a399fdb889da4a510e7701643b226472a3674f2..1282e345305f893c689444d6b0c02bf3c5bd4cd6 100644 (file)
 
 #include "zypp-plugin.h"
 
+
 /// Dispatches begin+end of plugin+commit in dedicated methods.
 // The default implementations just ack.
-class ZyppCommitPlugin : public ZyppPlugin {
+class ZyppCommitPlugin : public ZyppPlugin
+{
 public:
+
     Message dispatch(const Message& msg) override;
 
-    virtual Message plugin_begin(const Message& m) {
+    virtual Message plugin_begin(const Message& msg) = 0;
+    virtual Message plugin_end(const Message& msg) = 0;
+
+    virtual Message commit_begin(const Message& msg) = 0;
+    virtual Message commit_end(const Message& msg) = 0;
+
+};
+
+
+class DummyZyppCommitPlugin : public ZyppCommitPlugin
+{
+public:
+
+    virtual Message plugin_begin(const Message& msg) override
+    {
        return ack();
     }
-    virtual Message plugin_end(const Message& m) {
+
+    virtual Message plugin_end(const Message& msg) override
+    {
        return ack();
     }
-    virtual Message commit_begin(const Message& m) {
+
+    virtual Message commit_begin(const Message& msg) override
+    {
        return ack();
     }
-    virtual Message commit_end(const Message& m) {
+
+    virtual Message commit_end(const Message& msg) override
+    {
        return ack();
     }
+
 };
 
-#endif //ZYPP_COMMIT_PLUGIN_H
+#endif
index 271f096e7966e341c1a8466175aa436d78f30965..0867930d90511b4fba08eed90bbe6349d51c0596 100644 (file)
@@ -33,7 +33,7 @@ using namespace std;
 int
 ZyppPlugin::main()
 {
-    while(true)
+    while (true)
     {
        Message msg = read_message(pin);
        if (pin.eof())
@@ -49,7 +49,7 @@ void
 ZyppPlugin::write_message(ostream& os, const Message& msg)
 {
     os << msg.command << endl;
-    for(auto it: msg.headers) {
+    for (auto it: msg.headers) {
        os << it.first << ':' << it.second << endl;
     }
     os << endl;
@@ -61,11 +61,7 @@ ZyppPlugin::write_message(ostream& os, const Message& msg)
 ZyppPlugin::Message
 ZyppPlugin::read_message(istream& is)
 {
-    enum class State {
-                     Start,
-                     Headers,
-                     Body
-    } state = State::Start;
+    enum class State { Start, Headers, Body } state = State::Start;
 
     Message msg;
 
@@ -76,7 +72,8 @@ ZyppPlugin::read_message(istream& is)
        getline(is, line);
        boost::trim_right(line);
 
-       if (state == State::Start) {
+       if (state == State::Start)
+       {
            if (is.eof())
                return msg; //empty
 
@@ -95,8 +92,10 @@ ZyppPlugin::read_message(istream& is)
                throw runtime_error("Plugin protocol error: expected a command. Got '" + line + "'");
            }
        }
-       else if (state == State::Headers) {
-           if (line.empty()) {
+       else if (state == State::Headers)
+       {
+           if (line.empty())
+           {
                state = State::Body;
                getline(is, msg.body, '\0');
 
@@ -128,9 +127,11 @@ ZyppPlugin::read_message(istream& is)
 ZyppPlugin::Message
 ZyppPlugin::dispatch(const Message& msg)
 {
-    if (msg.command == "_DISCONNECT") {
+    if (msg.command == "_DISCONNECT")
+    {
        return ack();
     }
+
     Message a;
     a.command = "_ENOMETHOD";
     a.headers["Command"] = msg.command;
index c5b01363f589c6bb8caa153828d7dd33590dd0b2..3b1e538e0ec43501ba923351ad0be87d5539a521 100644 (file)
 #include <map>
 #include <string>
 
-class ZyppPlugin {
+class ZyppPlugin
+{
 public:
+
     // Plugin message aka frame
     // https://doc.opensuse.org/projects/libzypp/SLE12SP2/zypp-plugins.html
-    struct Message {
+    struct Message
+    {
        std::string command;
        std::map<std::string, std::string> headers;
        std::string body;
@@ -42,31 +45,31 @@ public:
     std::ostream& pout;
     /// Where the plugin writes log messages to
     std::ostream& plog;
-    ZyppPlugin(std::istream& in = std::cin,
-              std::ostream& out = std::cout,
-              std::ostream& log = std::cerr)
-       : pin(in)
-       , pout(out)
-       , plog(log)
+
+    ZyppPlugin(std::istream& in = std::cin, std::ostream& out = std::cout, std::ostream& log = std::cerr)
+       : pin(in), pout(out), plog(log)
     {}
+
     virtual ~ZyppPlugin() {}
 
     virtual int main();
 
 protected:
+
     /// Handle a message and return a reply.
     // Derived classes should override it.
     // The base acks a _DISCONNECT and replies _ENOMETHOD to everything else.
-    virtual Message dispatch(const Message&);
+    virtual Message dispatch(const Message& msg);
 
     Message read_message(std::istream& is);
     void write_message(std::ostream& os, const Message& msg);
 
-    Message ack() {
+    Message ack()
+    {
        Message a;
        a.command = "ACK";
        return a;
     }
 };
 
-#endif //ZYPP_PLUGIN_H
+#endif