/*
- * Copyright (c) 2024 SUSE LLC
+ * Copyright (c) [2024-2026] SUSE LLC
*
* All Rights Reserved.
*
#include <iostream>
-#include <regex>
-#include <snapper/AppUtil.h>
-
-#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<unsigned int> 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();
}
}
/*
- * Copyright (c) 2024 SUSE LLC
+ * Copyright (c) [2024-2026] SUSE LLC
*
* All Rights Reserved.
*
#include <iostream>
-#include <regex>
-#include <snapper/AppUtil.h>
-
-#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;
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<unsigned int> 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();
}
}
/*
- * Copyright (c) 2024 SUSE LLC
+ * Copyright (c) [2024-2026] SUSE LLC
*
* All Rights Reserved.
*
#include <iostream>
-#include <snapper/AppUtil.h>
-
-#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();
}
}
/*
- * Copyright (c) 2024 SUSE LLC
+ * Copyright (c) [2024-2026] SUSE LLC
*
* All Rights Reserved.
*
#include <iostream>
-#include <regex>
-#include <snapper/AppUtil.h>
-
-#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<unsigned int> 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();
}
}
/*
- * Copyright (c) [2024-2025] SUSE LLC
+ * Copyright (c) [2024-2026] SUSE LLC
*
* All Rights Reserved.
*
#include <regex>
+#include <snapper/AppUtil.h>
+
+#include "../proxy/errors.h"
#include "../utils/GetOpts.h"
#include "../utils/text.h"
+#include "utils.h"
+
namespace snapper
{
- vector<unsigned int>
- 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<unsigned int> 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<unsigned int> SnapshotOperation::parse_nums() const
{
static const regex num_regex("[0-9]+", regex::extended);
return nums;
}
-}
+} // namespace snapper
/*
- * Copyright (c) [2024-2025] SUSE LLC
+ * Copyright (c) [2024-2026] SUSE LLC
*
* All Rights Reserved.
*
*/
-#include "../utils/GetOpts.h"
+#include "BackupConfig.h"
+#include "GlobalOptions.h"
+#include "TheBigThing.h"
namespace snapper
{
- vector<unsigned int>
- 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<unsigned int> parse_nums() const;
+
+ const GlobalOptions& global_options;
+ GetOpts& get_opts;
+ const BackupConfigs& backup_configs;
+ ProxySnappers* snappers;
+ };
+
+} // namespace snapper