From: Cheng-Ling Lai Date: Sat, 17 Jan 2026 16:46:34 +0000 (+0800) Subject: Unify snbk snapshot operation command implementation X-Git-Tag: v0.13.1~49^2 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=refs%2Fpull%2F1091%2Fhead;p=thirdparty%2Fsnapper.git Unify snbk snapshot operation command implementation --- diff --git a/client/snbk/cmd-delete.cc b/client/snbk/cmd-delete.cc index 64893e3b..e51ca7bb 100644 --- a/client/snbk/cmd-delete.cc +++ b/client/snbk/cmd-delete.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 SUSE LLC + * Copyright (c) [2024-2026] SUSE LLC * * All Rights Reserved. * @@ -21,102 +21,81 @@ #include -#include -#include - -#include "../proxy/errors.h" #include "../utils/text.h" -#include "BackupConfig.h" -#include "GlobalOptions.h" -#include "TheBigThing.h" #include "utils.h" namespace snapper { - - using namespace std; - - - void - help_delete() - { - cout << " " << _("Delete:") << '\n' - << "\t" << _("snbk delete [numbers]") << '\n' - << '\n'; - } - - - void - command_delete(const GlobalOptions& global_options, GetOpts& get_opts, BackupConfigs& backup_configs, - ProxySnappers* snappers) + namespace { - ParsedOpts opts = get_opts.parse("delete", GetOpts::no_options); + class SnapshotDelete : public SnapshotOperation + { + public: - vector nums = parse_nums(get_opts); + SnapshotDelete(const GlobalOptions& global_options, GetOpts& get_opts, + const BackupConfigs& backup_configs, ProxySnappers* snappers) + : SnapshotOperation(global_options, get_opts, backup_configs, snappers) + { + } - unsigned int errors = 0; + protected: - for (const BackupConfig& backup_config : backup_configs) - { - if (!global_options.quiet()) - cout << sformat(_("Running delete for backup config '%s'."), - backup_config.name.c_str()) << endl; + const char* command() const override { return "delete"; } - try + void run_all(TheBigThings& the_big_things, const BackupConfig& backup_config, + bool quiet, bool verbose) const override { - TheBigThings the_big_things(backup_config, snappers, global_options.verbose()); - - if (nums.empty()) - { - the_big_things.remove(backup_config, global_options.quiet(), global_options.quiet()); - } - else - { - for (unsigned int num : nums) - { - TheBigThings::iterator it = the_big_things.find(num); - if (it == the_big_things.end()) - { - string error = sformat(_("Snapshot number %d not found."), num); - SN_THROW(Exception(error)); - } - - it->remove(backup_config, global_options.quiet()); - } - } + the_big_things.remove(backup_config, quiet, verbose); } - catch (const DBus::ErrorException& e) + + void run_single(TheBigThing& the_big_thing, const BackupConfig& backup_config, + TheBigThings& the_big_things, bool quiet) const override { - SN_CAUGHT(e); + the_big_thing.remove(backup_config, quiet); + } - cerr << error_description(e) << endl; + const char* msg_running() const override + { + return _("Running delete for backup config '%s'."); + } - ++errors; + const char* msg_failed() const override + { + return _("Running delete for backup config '%s' failed."); } - catch (const Exception& e) + + const char* msg_error_summary() const override { - SN_CAUGHT(e); + return _("Running delete failed for %d of %ld backup config.", + "Running delete failed for %d of %ld backup configs.", + backup_configs.size()); + } + }; - cerr << e.what() << '\n'; + } // namespace - cerr << sformat(_("Running delete for backup config '%s' failed."), - backup_config.name.c_str()) << endl; + using namespace std; - ++errors; - } - } - if (errors != 0) - { - string error = sformat(_("Running delete failed for %d of %ld backup config.", - "Running delete failed for %d of %ld backup configs.", - backup_configs.size()), errors, backup_configs.size()); + void + help_delete() + { + cout << " " << _("Delete:") << '\n' + << "\t" << _("snbk delete [numbers]") << '\n' + << '\n'; + } - SN_THROW(Exception(error)); - } + + void + command_delete(const GlobalOptions& global_options, GetOpts& get_opts, BackupConfigs& backup_configs, + ProxySnappers* snappers) + { + SnapshotDelete snapshot_operation(global_options, get_opts, backup_configs, + snappers); + snapshot_operation(); } } diff --git a/client/snbk/cmd-restore.cc b/client/snbk/cmd-restore.cc index 8b041573..74452b77 100644 --- a/client/snbk/cmd-restore.cc +++ b/client/snbk/cmd-restore.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 SUSE LLC + * Copyright (c) [2024-2026] SUSE LLC * * All Rights Reserved. * @@ -21,21 +21,70 @@ #include -#include -#include - -#include "../proxy/errors.h" #include "../utils/text.h" -#include "BackupConfig.h" -#include "GlobalOptions.h" -#include "TheBigThing.h" #include "utils.h" namespace snapper { + namespace + { + class SnapshotRestore : public SnapshotOperation + { + public: + + SnapshotRestore(const GlobalOptions& global_options, GetOpts& get_opts, + const BackupConfigs& backup_configs, ProxySnappers* snappers) + : SnapshotOperation(global_options, get_opts, backup_configs, snappers) + { + } + + protected: + + const char* command() const override { return "restore"; } + + void prerequisite() const override + { + if (backup_configs.size() != 1) + { + SN_THROW(OptionsException( + _("A backup-config must be specified to run this command."))); + } + } + + void run_all(TheBigThings& the_big_things, const BackupConfig& backup_config, + bool quiet, bool verbose) const override + { + the_big_things.restore(backup_config, quiet, verbose); + } + + void run_single(TheBigThing& the_big_thing, const BackupConfig& backup_config, + TheBigThings& the_big_things, bool quiet) const override + { + the_big_thing.restore(backup_config, the_big_things, quiet); + } + + const char* msg_running() const override + { + return _("Running restore for backup config '%s'."); + } + + const char* msg_failed() const override + { + return _("Running restore for backup config '%s' failed."); + } + + const char* msg_error_summary() const override + { + return _("Running restore failed for %d of %ld backup config.", + "Running restore failed for %d of %ld backup configs.", + backup_configs.size()); + } + }; + + } // namespace using namespace std; @@ -59,82 +108,9 @@ namespace snapper command_restore(const GlobalOptions& global_options, GetOpts& get_opts, BackupConfigs& backup_configs, ProxySnappers* snappers) { - ParsedOpts opts = get_opts.parse("restore", GetOpts::no_options); - - if (backup_configs.size() != 1) - { - SN_THROW(OptionsException(_("A backup-config must be specified to run this " - "command."))); - } - - vector nums = parse_nums(get_opts); - - unsigned int errors = 0; - - for (const BackupConfig& backup_config : backup_configs) - { - if (!global_options.quiet()) - cout << sformat(_("Running restore for backup config '%s'."), - backup_config.name.c_str()) << endl; - - try - { - TheBigThings the_big_things(backup_config, snappers, - global_options.verbose()); - - if (nums.empty()) - { - the_big_things.restore(backup_config, global_options.quiet(), - global_options.quiet()); - } - else - { - for (unsigned int num : nums) - { - TheBigThings::iterator it = the_big_things.find(num); - if (it == the_big_things.end()) - { - string error = sformat(_("Snapshot number %d not found."), - num); - SN_THROW(Exception(error)); - } - - it->restore(backup_config, the_big_things, - global_options.quiet()); - } - } - } - catch (const DBus::ErrorException& e) - { - SN_CAUGHT(e); - - cerr << error_description(e) << endl; - - ++errors; - } - catch (const Exception& e) - { - SN_CAUGHT(e); - - cerr << e.what() << '\n'; - - cerr << sformat(_("Running restore for backup config '%s' failed."), - backup_config.name.c_str()) << endl; - - ++errors; - } - } - - if (errors != 0) - { - string error = sformat( - _("Running restore failed for %d of %ld backup config.", - "Running restore failed for %d of %ld backup configs.", - backup_configs.size()), errors, backup_configs.size() - ); - - SN_THROW(Exception(error)); - } + SnapshotRestore snapshot_operation(global_options, get_opts, backup_configs, + snappers); + snapshot_operation(); } } diff --git a/client/snbk/cmd-transfer-and-delete.cc b/client/snbk/cmd-transfer-and-delete.cc index e1e6ffb3..64927b9a 100644 --- a/client/snbk/cmd-transfer-and-delete.cc +++ b/client/snbk/cmd-transfer-and-delete.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 SUSE LLC + * Copyright (c) [2024-2026] SUSE LLC * * All Rights Reserved. * @@ -22,86 +22,96 @@ #include -#include - -#include "../proxy/errors.h" #include "../utils/text.h" -#include "BackupConfig.h" -#include "GlobalOptions.h" -#include "TheBigThing.h" +#include "utils.h" namespace snapper { - - using namespace std; - - - void - help_transfer_and_delete() + namespace { - cout << " " << _("Transfer and delete:") << '\n' - << "\t" << _("snbk transfer-and-delete") << '\n' - << '\n'; - } - - - void - command_transfer_and_delete(const GlobalOptions& global_options, GetOpts& get_opts, BackupConfigs& backup_configs, - ProxySnappers* snappers) - { - ParsedOpts opts = get_opts.parse("transfer-and-delete", GetOpts::no_options); - - if (get_opts.has_args()) + class SnapshotTransferAndDelete : public SnapshotOperation { - SN_THROW(OptionsException(_("Command 'transfer-and-delete' does not take arguments."))); - } + public: - unsigned int errors = 0; + SnapshotTransferAndDelete(const GlobalOptions& global_options, + GetOpts& get_opts, + const BackupConfigs& backup_configs, + ProxySnappers* snappers) + : SnapshotOperation(global_options, get_opts, backup_configs, snappers) + { + } - for (const BackupConfig& backup_config : backup_configs) - { - if (!global_options.quiet()) - cout << sformat(_("Running transfer and delete for backup config '%s'."), - backup_config.name.c_str()) << endl; + protected: - try + const char* command() const override { return "transfer-and-delete"; } + + void prerequisite() const override { - TheBigThings the_big_things(backup_config, snappers, global_options.verbose()); + if (get_opts.has_args()) + { + SN_THROW(OptionsException( + _("Command 'transfer-and-delete' does not take arguments."))); + } + } - the_big_things.transfer(backup_config, global_options.quiet(), global_options.quiet()); - the_big_things.remove(backup_config, global_options.quiet(), global_options.quiet()); + void run_all(TheBigThings& the_big_things, const BackupConfig& backup_config, + bool quiet, bool verbose) const override + { + the_big_things.transfer(backup_config, global_options.quiet(), + global_options.quiet()); + the_big_things.remove(backup_config, global_options.quiet(), + global_options.quiet()); } - catch (const DBus::ErrorException& e) + + void run_single(TheBigThing& the_big_thing, const BackupConfig& backup_config, + TheBigThings& the_big_things, bool quiet) const override { - SN_CAUGHT(e); + SN_THROW(Exception(_("Command 'transfer-and-delete' does not support " + "operating on a single snapshot."))); + } - cerr << error_description(e) << endl; + const char* msg_running() const override + { + return _("Running transfer and delete for backup config '%s'."); + } - ++errors; + const char* msg_failed() const override + { + return _("Running transfer and delete for backup config '%s' failed."); } - catch (const Exception& e) + + const char* msg_error_summary() const override { - SN_CAUGHT(e); + return _( + "Running transfer and delete failed for %d of %ld backup config.", + "Running transfer and delete failed for %d of %ld backup configs.", + backup_configs.size()); + } + }; - cerr << e.what() << '\n'; + } // namespace - cerr << sformat(_("Running transfer and delete for backup config '%s' failed."), - backup_config.name.c_str()) << endl; + using namespace std; - ++errors; - } - } - if (errors != 0) - { - string error = sformat(_("Running transfer and delete failed for %d of %ld backup config.", - "Running transfer and delete failed for %d of %ld backup configs.", - backup_configs.size()), errors, backup_configs.size()); + void + help_transfer_and_delete() + { + cout << " " << _("Transfer and delete:") << '\n' + << "\t" << _("snbk transfer-and-delete") << '\n' + << '\n'; + } - SN_THROW(Exception(error)); - } + + void + command_transfer_and_delete(const GlobalOptions& global_options, GetOpts& get_opts, BackupConfigs& backup_configs, + ProxySnappers* snappers) + { + SnapshotTransferAndDelete snapshot_operation(global_options, get_opts, + backup_configs, snappers); + snapshot_operation(); } } diff --git a/client/snbk/cmd-transfer.cc b/client/snbk/cmd-transfer.cc index 82e90e0b..facd8a67 100644 --- a/client/snbk/cmd-transfer.cc +++ b/client/snbk/cmd-transfer.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 SUSE LLC + * Copyright (c) [2024-2026] SUSE LLC * * All Rights Reserved. * @@ -21,102 +21,81 @@ #include -#include -#include - -#include "../proxy/errors.h" #include "../utils/text.h" -#include "BackupConfig.h" -#include "GlobalOptions.h" -#include "TheBigThing.h" #include "utils.h" namespace snapper { - - using namespace std; - - - void - help_transfer() - { - cout << " " << _("Transfer:") << '\n' - << "\t" << _("snbk transfer [numbers]") << '\n' - << '\n'; - } - - - void - command_transfer(const GlobalOptions& global_options, GetOpts& get_opts, BackupConfigs& backup_configs, - ProxySnappers* snappers) + namespace { - ParsedOpts opts = get_opts.parse("transfer", GetOpts::no_options); + class SnapshotTransfer : public SnapshotOperation + { + public: - vector nums = parse_nums(get_opts); + SnapshotTransfer(const GlobalOptions& global_options, GetOpts& get_opts, + const BackupConfigs& backup_configs, ProxySnappers* snappers) + : SnapshotOperation(global_options, get_opts, backup_configs, snappers) + { + } - unsigned int errors = 0; + protected: - for (const BackupConfig& backup_config : backup_configs) - { - if (!global_options.quiet()) - cout << sformat(_("Running transfer for backup config '%s'."), - backup_config.name.c_str()) << endl; + const char* command() const override { return "transfer"; } - try + void run_all(TheBigThings& the_big_things, const BackupConfig& backup_config, + bool quiet, bool verbose) const override { - TheBigThings the_big_things(backup_config, snappers, global_options.verbose()); - - if (nums.empty()) - { - the_big_things.transfer(backup_config, global_options.quiet(), global_options.quiet()); - } - else - { - for (unsigned int num : nums) - { - TheBigThings::iterator it = the_big_things.find(num); - if (it == the_big_things.end()) - { - string error = sformat(_("Snapshot number %d not found."), num); - SN_THROW(Exception(error)); - } - - it->transfer(backup_config, the_big_things, global_options.quiet()); - } - } + the_big_things.transfer(backup_config, quiet, verbose); } - catch (const DBus::ErrorException& e) + + void run_single(TheBigThing& the_big_thing, const BackupConfig& backup_config, + TheBigThings& the_big_things, bool quiet) const override { - SN_CAUGHT(e); + the_big_thing.transfer(backup_config, the_big_things, quiet); + } - cerr << error_description(e) << endl; + const char* msg_running() const override + { + return _("Running transfer for backup config '%s'."); + } - ++errors; + const char* msg_failed() const override + { + return _("Running transfer for backup config '%s' failed."); } - catch (const Exception& e) + + const char* msg_error_summary() const override { - SN_CAUGHT(e); + return _("Running transfer failed for %d of %ld backup config.", + "Running transfer failed for %d of %ld backup configs.", + backup_configs.size()); + } + }; - cerr << e.what() << '\n'; + } // namespace - cerr << sformat(_("Running transfer for backup config '%s' failed."), - backup_config.name.c_str()) << endl; + using namespace std; - ++errors; - } - } - if (errors != 0) - { - string error = sformat(_("Running transfer failed for %d of %ld backup config.", - "Running transfer failed for %d of %ld backup configs.", - backup_configs.size()), errors, backup_configs.size()); + void + help_transfer() + { + cout << " " << _("Transfer:") << '\n' + << "\t" << _("snbk transfer [numbers]") << '\n' + << '\n'; + } - SN_THROW(Exception(error)); - } + + void + command_transfer(const GlobalOptions& global_options, GetOpts& get_opts, BackupConfigs& backup_configs, + ProxySnappers* snappers) + { + SnapshotTransfer snapshot_operation(global_options, get_opts, backup_configs, + snappers); + snapshot_operation(); } } diff --git a/client/snbk/utils.cc b/client/snbk/utils.cc index b79eb00c..545587de 100644 --- a/client/snbk/utils.cc +++ b/client/snbk/utils.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) [2024-2025] SUSE LLC + * Copyright (c) [2024-2026] SUSE LLC * * All Rights Reserved. * @@ -22,15 +22,89 @@ #include +#include + +#include "../proxy/errors.h" #include "../utils/GetOpts.h" #include "../utils/text.h" +#include "utils.h" + namespace snapper { - vector - parse_nums(GetOpts& get_opts) + void SnapshotOperation::operator()() + { + ParsedOpts opts = get_opts.parse(command(), GetOpts::no_options); + + // Run prerequisite step + prerequisite(); + + // Run the snapshot operation + vector nums = parse_nums(); + + unsigned int errors = 0; + + for (const BackupConfig& backup_config : backup_configs) + { + if (!global_options.quiet()) + cout << sformat(msg_running(), backup_config.name.c_str()) << endl; + + try + { + TheBigThings the_big_things(backup_config, snappers, + global_options.verbose()); + + if (nums.empty()) + { + run_all(the_big_things, backup_config, global_options.quiet(), + global_options.quiet()); + } + else + { + for (unsigned int num : nums) + { + TheBigThings::iterator it = the_big_things.find(num); + if (it == the_big_things.end()) + { + string error = + sformat(_("Snapshot number %d not found."), num); + SN_THROW(Exception(error)); + } + + run_single(*it, backup_config, the_big_things, + global_options.quiet()); + } + } + } + catch (const DBus::ErrorException& e) + { + SN_CAUGHT(e); + + cerr << error_description(e) << endl; + + ++errors; + } + catch (const Exception& e) + { + SN_CAUGHT(e); + + cerr << e.what() << '\n'; + cerr << sformat(msg_failed(), backup_config.name.c_str()) << endl; + + ++errors; + } + } + + if (errors != 0) + { + string error = sformat(msg_error_summary(), errors, backup_configs.size()); + SN_THROW(Exception(error)); + } + } + + vector SnapshotOperation::parse_nums() const { static const regex num_regex("[0-9]+", regex::extended); @@ -49,4 +123,4 @@ namespace snapper return nums; } -} +} // namespace snapper diff --git a/client/snbk/utils.h b/client/snbk/utils.h index a50e28b4..8cc5b74a 100644 --- a/client/snbk/utils.h +++ b/client/snbk/utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2024-2025] SUSE LLC + * Copyright (c) [2024-2026] SUSE LLC * * All Rights Reserved. * @@ -20,13 +20,58 @@ */ -#include "../utils/GetOpts.h" +#include "BackupConfig.h" +#include "GlobalOptions.h" +#include "TheBigThing.h" namespace snapper { - vector - parse_nums(GetOpts& get_opts); + class SnapshotOperation + { + public: -} + SnapshotOperation(const GlobalOptions& global_options, GetOpts& get_opts, + const BackupConfigs& backup_configs, ProxySnappers* snappers) + : global_options(global_options), get_opts(get_opts), + backup_configs(backup_configs), snappers(snappers) + { + } + + virtual ~SnapshotOperation() = default; + + void operator()(); + + protected: + + /** Command name of the snapshot operation. */ + virtual const char* command() const = 0; + + /** Run the optional prerequisite procedures for the snapshot operation. */ + virtual void prerequisite() const {} + + /** Run the snapshot operation for the entire backup config. */ + virtual void run_all(TheBigThings& the_big_things, + const BackupConfig& backup_config, bool quiet, + bool verbose) const = 0; + + /** Run the operation for a specific snapshot. */ + virtual void run_single(TheBigThing& the_big_thing, + const BackupConfig& backup_config, + TheBigThings& the_big_things, bool quiet) const = 0; + + /** Messages related to the snapshot operation. */ + virtual const char* msg_running() const = 0; + virtual const char* msg_failed() const = 0; + virtual const char* msg_error_summary() const = 0; + + vector parse_nums() const; + + const GlobalOptions& global_options; + GetOpts& get_opts; + const BackupConfigs& backup_configs; + ProxySnappers* snappers; + }; + +} // namespace snapper