From: Arvin Schnell Date: Wed, 25 Jan 2023 10:11:21 +0000 (+0100) Subject: - coding style X-Git-Tag: v0.10.5~62^2 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=e71a05a2b99fbbe899d13253a7c8cb871b0c94ac;p=thirdparty%2Fsnapper.git - coding style --- diff --git a/zypp-plugin/Makefile.am b/zypp-plugin/Makefile.am index 5970cb0b..a293a5d2 100644 --- a/zypp-plugin/Makefile.am +++ b/zypp-plugin/Makefile.am @@ -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 index 00000000..103f847b --- /dev/null +++ b/zypp-plugin/snapper-zypp-commit-plugin.cc @@ -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 +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +// 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& 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 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 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 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 +SnapperZyppCommitPlugin::get_userdata(const Message& msg) +{ + map result; + auto it = msg.headers.find("userdata"); + if (it != msg.headers.end()) + { + const string& userdata_s = it->second; + vector 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 +SnapperZyppCommitPlugin::get_solvables(const Message& msg, Phase phase) const +{ + set 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& 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 index 00000000..cb519cd1 --- /dev/null +++ b/zypp-plugin/snapper-zypp-commit-plugin.h @@ -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 userdata; + + vector solvable_matchers; + + map get_userdata(const Message& msg); + + enum class Phase { BEFORE, AFTER }; + + std::set get_solvables(const Message& msg, Phase phase) const; + + void match_solvables(const std::set& 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 index 7c044e88..00000000 --- a/zypp-plugin/snapper-zypp-plugin.cc +++ /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 -#include -#include - -#include -#include -#include -#include -#include -#include - -using namespace std; - -#include -// 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& 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 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 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 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 userdata; - - vector solvable_matchers; - - map get_userdata(const Message&); - - enum class Phase { BEFORE, AFTER }; - - set get_solvables(const Message&, Phase phase); - - void match_solvables(const set& solvables, bool& found, bool& important); - -}; - - -const string SnapperZyppPlugin::cleanup_algorithm = "number"; - - -map -SnapperZyppPlugin::get_userdata(const Message& msg) -{ - map result; - auto it = msg.headers.find("userdata"); - if (it != msg.headers.end()) { - const string& userdata_s = it->second; - vector 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 -SnapperZyppPlugin::get_solvables(const Message& msg, Phase phase) -{ - set 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& 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(); -} diff --git a/zypp-plugin/zypp-commit-plugin.cc b/zypp-plugin/zypp-commit-plugin.cc index 8b4b1569..aa4e0903 100644 --- a/zypp-plugin/zypp-commit-plugin.cc +++ b/zypp-plugin/zypp-commit-plugin.cc @@ -23,17 +23,21 @@ #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); } diff --git a/zypp-plugin/zypp-commit-plugin.h b/zypp-plugin/zypp-commit-plugin.h index 8a399fdb..1282e345 100644 --- a/zypp-plugin/zypp-commit-plugin.h +++ b/zypp-plugin/zypp-commit-plugin.h @@ -24,24 +24,48 @@ #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 diff --git a/zypp-plugin/zypp-plugin.cc b/zypp-plugin/zypp-plugin.cc index 271f096e..0867930d 100644 --- a/zypp-plugin/zypp-plugin.cc +++ b/zypp-plugin/zypp-plugin.cc @@ -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; diff --git a/zypp-plugin/zypp-plugin.h b/zypp-plugin/zypp-plugin.h index c5b01363..3b1e538e 100644 --- a/zypp-plugin/zypp-plugin.h +++ b/zypp-plugin/zypp-plugin.h @@ -26,11 +26,14 @@ #include #include -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 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