_options_parser(options_parser), _global_options(global_options), _snappers(snappers)
{}
-
- bool Command::has_errors() const
- {
- return !errors().empty();
- }
-
-
- Command::~Command()
- {}
-
}
}
return _snappers;
}
- virtual bool has_errors() const;
-
- virtual std::vector<std::string> errors() const = 0;
-
virtual void run() = 0;
- virtual ~Command();
+ virtual ~Command() {}
protected:
/*
- * Copyright (c) [2019] SUSE LLC
+ * Copyright (c) [2019-2020] SUSE LLC
*
* All Rights Reserved.
*
* find current contact information at www.novell.com.
*/
-#include <algorithm>
-
#include <boost/algorithm/string.hpp>
#include "client/Command/ColumnsOption.h"
namespace cli
{
- vector<string> Command::ColumnsOption::selected_columns() const
+ vector<string>
+ Command::ColumnsOption::selected_columns() const
{
- if (_raw_columns.empty())
- return {};
-
vector<string> columns;
boost::split(columns, _raw_columns, boost::is_any_of(","), boost::token_compress_on);
- return columns;
- }
-
-
- string Command::ColumnsOption::error() const
- {
- if (wrong_columns().empty())
- return "";
-
- return _("Unknown columns: ") + boost::algorithm::join(wrong_columns(), ", ");
- }
-
-
- vector<string> Command::ColumnsOption::wrong_columns() const
- {
- vector<string> wrong;
-
- for (auto column : selected_columns())
+ vector<string> unknowns;
+ for (const string& column : columns)
{
- if (wrong_column(column))
- wrong.push_back(column);
+ if (find(_all_columns.begin(), _all_columns.end(), column) == _all_columns.end())
+ unknowns.push_back(column);
}
- return wrong;
- }
+ if (!unknowns.empty())
+ {
+ string error = _("Unknown column:", "Unknown columns:", unknowns.size()) + string(" ") +
+ boost::algorithm::join(unknowns, ", ") + '\n' +
+ _("Allowed columns are:") + string(" ") + boost::join(_all_columns, ", ");
+ SN_THROW(OptionsException(error));
+ }
- bool Command::ColumnsOption::wrong_column(const std::string& column) const
- {
- return find(_all_columns.begin(), _all_columns.end(), column) == _all_columns.end();
+ return columns;
}
}
std::vector<std::string> selected_columns() const;
- std::string error() const;
-
- std::vector<std::string> wrong_columns() const;
-
private:
- bool wrong_column(const std::string& column) const;
-
const std::vector<std::string>& _all_columns;
std::string _raw_columns;
}
- vector<string> Command::GetConfig::errors() const
- {
- return options().errors();
- }
-
-
void Command::GetConfig::run()
{
if (_options_parser.hasArgs())
exit(EXIT_FAILURE);
}
- if (options().has_errors())
- {
- cerr << options().errors().front() << endl;
- exit(EXIT_FAILURE);
- }
-
string output;
switch (global_options().output_format())
const Options& options() const;
- virtual std::vector<std::string> errors() const override;
-
virtual void run() override;
virtual ~GetConfig();
}
- vector<string> Command::GetConfig::Options::errors() const
- {
- vector<string> detected_errors;
-
- if (!_columns_option.wrong_columns().empty())
- detected_errors.push_back(_columns_option.error());
-
- return detected_errors;
- }
-
-
string Command::GetConfig::Options::columns_raw() const
{
- return has_option("columns") ? get_option("columns")->second : "";
+ return has_option("columns") ? get_argument("columns") : "";
}
}
std::vector<std::string> columns() const;
- virtual std::vector<std::string> errors() const override;
-
private:
void parse_options();
}
- vector<string> Command::ListConfigs::errors() const
- {
- return options().errors();
- }
-
-
void Command::ListConfigs::run()
{
if (_options_parser.hasArgs())
exit(EXIT_FAILURE);
}
- if (options().has_errors())
- {
- cerr << options().errors().front() << endl;
- exit(EXIT_FAILURE);
- }
-
string output;
switch (global_options().output_format())
const Options& options() const;
- virtual std::vector<std::string> errors() const override;
-
virtual void run() override;
virtual ~ListConfigs();
}
- vector<string> Command::ListConfigs::Options::errors() const
- {
- vector<string> detected_errors;
-
- if (!_columns_option.wrong_columns().empty())
- detected_errors.push_back(_columns_option.error());
-
- return detected_errors;
- }
-
-
string Command::ListConfigs::Options::columns_raw() const
{
- return has_option("columns") ? get_option("columns")->second : "";
+ return has_option("columns") ? get_argument("columns") : "";
}
}
std::vector<std::string> columns() const;
- virtual std::vector<std::string> errors() const override;
-
private:
void parse_options();
}
- vector<string> Command::ListSnapshots::errors() const
- {
- return options().errors();
- }
-
-
void Command::ListSnapshots::run()
{
if (_options_parser.hasArgs())
exit(EXIT_FAILURE);
}
- if (options().has_errors())
- {
- cerr << options().errors().front() << endl;
- exit(EXIT_FAILURE);
- }
-
string output;
switch (global_options().output_format())
const Options& options() const;
- virtual std::vector<std::string> errors() const override;
-
virtual void run() override;
virtual ~ListSnapshots();
/*
- * Copyright (c) [2019] SUSE LLC
+ * Copyright (c) [2019-2020] SUSE LLC
*
* All Rights Reserved.
*
* find current contact information at www.novell.com.
*/
-#include <stdexcept>
-
#include <boost/algorithm/string.hpp>
+#include <snapper/AppUtil.h>
+
#include "client/Command/ListSnapshots/Options.h"
#include "client/utils/text.h"
}
- vector<string> Command::ListSnapshots::Options::errors() const
- {
- vector<string> detected_errors;
-
- if (wrong_type())
- detected_errors.push_back(type_error());
-
- if (wrong_columns())
- detected_errors.push_back(columns_error());
-
- return detected_errors;
- }
-
-
Command::ListSnapshots::Options::ListMode
Command::ListSnapshots::Options::list_mode_value() const
{
- string type = has_option("type") ? get_option("type")->second : "";
+ if (!has_option("type"))
+ return ListMode::ALL;
- if (type == "all")
- return LM_ALL;
+ string str = get_argument("type");
- if (type == "single")
- return LM_SINGLE;
+ ListMode list_mode;
+ if (!toValue(str, list_mode, false))
+ {
+ string error = sformat(_("Unknown snapshots type %s."), str.c_str()) + '\n' +
+ sformat(_("Use %s, %s or %s."), toString(ListMode::ALL).c_str(),
+ toString(ListMode::SINGLE).c_str(), toString(ListMode::PRE_POST).c_str());
- if (type == "pre-post")
- return LM_PRE_POST;
+ SN_THROW(OptionsException(error));
+ }
- return LM_ALL;
+ return list_mode;
}
string Command::ListSnapshots::Options::columns_raw() const
{
- return has_option("columns") ? get_option("columns")->second : "";
+ return has_option("columns") ? get_argument("columns") : "";
}
switch (list_mode())
{
- case LM_ALL:
+ case ListMode::ALL:
columns = all_mode_columns(format);
break;
- case LM_SINGLE:
+ case ListMode::SINGLE:
columns = single_mode_columns(format);
break;
- case LM_PRE_POST:
+ case ListMode::PRE_POST:
columns = pre_post_mode_columns(format);
break;
}
throw logic_error("unknown output format");
}
+ }
- bool Command::ListSnapshots::Options::wrong_type() const
- {
- if (!has_option("type"))
- return false;
-
- string type = get_option("type")->second;
-
- return type != "all" && type != "single" && type != "pre-post";
- }
-
-
- bool Command::ListSnapshots::Options::wrong_columns() const
- {
- return !_columns_option.wrong_columns().empty();
- }
-
-
- string Command::ListSnapshots::Options::type_error() const
- {
- return _("Unknown type of snapshots.");
- }
-
+ const vector<string> EnumInfo<cli::Command::ListSnapshots::Options::ListMode>::names({ "all", "single", "pre-post" });
- string Command::ListSnapshots::Options::columns_error() const
- {
- return _columns_option.error();
- }
-
- }
}
/*
- * Copyright (c) [2019] SUSE LLC
+ * Copyright (c) [2019-2020] SUSE LLC
*
* All Rights Reserved.
*
static const std::vector<std::string> ALL_COLUMNS;
- enum ListMode { LM_ALL, LM_SINGLE, LM_PRE_POST };
+ enum class ListMode { ALL, SINGLE, PRE_POST };
static std::string help_text();
Options(GetOpts& parser);
- ListMode list_mode() const
- {
- return _list_mode;
- }
-
- bool disable_used_space() const
- {
- return _disable_used_space;
- }
-
- bool all_configs() const
- {
- return _all_configs;
- }
+ ListMode list_mode() const { return _list_mode; }
+ bool disable_used_space() const { return _disable_used_space; }
+ bool all_configs() const { return _all_configs; }
std::vector<std::string> columns(GlobalOptions::OutputFormat format) const;
- virtual std::vector<std::string> errors() const override;
-
private:
void parse_options();
std::vector<std::string> pre_post_mode_columns(GlobalOptions::OutputFormat format) const;
- bool wrong_type() const;
-
- bool wrong_columns() const;
-
- std::string type_error() const;
-
- std::string columns_error() const;
-
ListMode _list_mode;
bool _disable_used_space;
};
}
+
+ template <> struct EnumInfo<cli::Command::ListSnapshots::Options::ListMode> { static const vector<string> names; };
+
}
#endif
{
switch (command().options().list_mode())
{
- case Options::ListMode::LM_ALL:
+ case Options::ListMode::ALL:
{
selected.push_back(&snapshot);
}
break;
- case Options::ListMode::LM_SINGLE:
+ case Options::ListMode::SINGLE:
{
if (snapshot.getType() == SINGLE)
selected.push_back(&snapshot);
}
break;
- case Options::ListMode::LM_PRE_POST:
+ case Options::ListMode::PRE_POST:
{
ProxySnapshots::const_iterator post_it = find_post(snapshot, snapshots);
string
Command::ListSnapshots::SnappersData::date_value(const ProxySnapshot& snapshot) const
{
- if (command().options().list_mode() == Options::ListMode::LM_PRE_POST)
+ if (command().options().list_mode() == Options::ListMode::PRE_POST)
return snapshot_date(snapshot);
return snapshot.isCurrent() ? "" : snapshot_date(snapshot);
return _("Subvolume");
if (column == Options::Columns::NUMBER)
- return list_mode == Options::LM_PRE_POST ? _("Pre #") : _("#");
+ return list_mode == Options::ListMode::PRE_POST ? _("Pre #") : _("#");
if (column == Options::Columns::DEFAULT)
return _("Default");
return _("Type");
if (column == Options::Columns::DATE)
- return list_mode == Options::LM_PRE_POST ? _("Pre Date") : _("Date");
+ return list_mode == Options::ListMode::PRE_POST ? _("Pre Date") : _("Date");
if (column == Options::Columns::USER)
return _("User");
/*
- * Copyright (c) [2019] SUSE LLC
+ * Copyright (c) [2019-2020] SUSE LLC
*
* All Rights Reserved.
*
namespace
{
- const string CSV_OPTION = "csv";
-
- const string JSON_OPTION = "json";
-
const string DEFAULT_CONFIG = "root";
const string DEFAULT_ROOT = "/";
- const option OPTIONS[15] = {
+ const option OPTIONS[] = {
{ "quiet", no_argument, 0, 'q' },
{ "verbose", no_argument, 0, 'v' },
{ "utc", no_argument, 0, 0 },
{ "iso", no_argument, 0, 0 },
{ "table-style", required_argument, 0, 't' },
- { "machine-readable", required_argument, 0, 0},
- { "csvout", no_argument, 0, 0},
- { "jsonout", no_argument, 0, 0},
- { "separator", required_argument, 0, 0},
+ { "machine-readable", required_argument, 0, 0 },
+ { "csvout", no_argument, 0, 0 },
+ { "jsonout", no_argument, 0, 0 },
+ { "separator", required_argument, 0, 0 },
{ "config", required_argument, 0, 'c' },
{ "no-dbus", no_argument, 0, 0 },
{ "root", required_argument, 0, 'r' },
+ { "ambit", required_argument, 0, 'a' },
{ "version", no_argument, 0, 0 },
{ "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }
+ _("\t--config, -c <name>\t\tSet name of config to use.") + '\n'
+ _("\t--no-dbus\t\t\tOperate without DBus.") + '\n'
+ _("\t--root, -r <path>\t\tOperate on target root (works only without DBus).") + '\n'
+ + _("\t--ambit, -a ambit\t\tOperate in the specified ambit.") + '\n'
+ _("\t--version\t\t\tPrint version and exit.") + '\n';
}
- GlobalOptions::GlobalOptions(GetOpts& parser) :
- Options(parser)
+ GlobalOptions::GlobalOptions(GetOpts& parser)
+ : Options(parser), _ambit(Ambit::AUTO)
{
parse_options();
+ check_options();
_quiet = has_option("quiet");
_verbose = has_option("verbose");
_separator = separator_value();
_config = config_value();
_root = root_value();
+ _ambit = ambit_value();
}
}
- vector<string> GlobalOptions::errors() const
+ void
+ GlobalOptions::check_options() const
{
- vector<string> detected_errors;
+ if (has_option("root") && !has_option("no-dbus"))
+ {
+ string error =_("root argument can be used only together with no-dbus.\n"
+ "Try 'snapper --help' for more information.");
- if (wrong_table_style())
- detected_errors.push_back(table_style_error());
+ SN_THROW(OptionsException(error));
+ }
+ }
- if (wrong_machine_readable())
- detected_errors.push_back(machine_readable_error());
- if (missing_no_dbus())
- detected_errors.push_back(missing_no_dbus_error());
+ TableLineStyle
+ GlobalOptions::table_style_value() const
+ {
+ if (!has_option("table-style"))
+ return TableFormatter::default_style();
- return detected_errors;
- }
+ string str = get_argument("table-style");
+ unsigned long value = stoul(str);
+ if (value >= Table::numStyles)
+ {
+ string error = sformat(_("Invalid table style %s."), str.c_str()) + '\n' +
+ sformat(_("Use an integer number from %d to %d."), 0, Table::numStyles - 1);
- TableLineStyle GlobalOptions::table_style_value() const
- {
- if (has_option("table-style") && !wrong_table_style())
- return (TableLineStyle) table_style_raw();
+ SN_THROW(OptionsException(error));
+ }
- return TableFormatter::default_style();
+ return (TableLineStyle)(value);
}
- GlobalOptions::OutputFormat GlobalOptions::output_format_value() const
+ GlobalOptions::OutputFormat
+ GlobalOptions::output_format_value() const
{
- if (has_option("csvout") || machine_readable_value() == CSV_OPTION)
+ if (has_option("csvout"))
return OutputFormat::CSV;
- if (has_option("jsonout") || machine_readable_value() == JSON_OPTION)
+ if (has_option("jsonout"))
return OutputFormat::JSON;
- return OutputFormat::TABLE;
- }
+ if (!has_option("machine-readable"))
+ return OutputFormat::TABLE;
+ string str = get_argument("machine-readable");
- string GlobalOptions::machine_readable_value() const
- {
- if (has_option("machine-readable"))
- return get_option("machine-readable")->second;
+ OutputFormat output_format;
+ if (!toValue(str, output_format, false))
+ {
+ string error = sformat(_("Invalid machine readable format %s."), str.c_str()) + '\n' +
+ sformat(_("Use %s, %s or %s."), toString(OutputFormat::TABLE).c_str(),
+ toString(OutputFormat::CSV).c_str(), toString(OutputFormat::JSON).c_str());
- return "";
+ SN_THROW(OptionsException(error));
+ }
+
+ return output_format;
}
- string GlobalOptions::separator_value() const
+ string
+ GlobalOptions::separator_value() const
{
if (has_option("separator"))
- return get_option("separator")->second;
+ return get_argument("separator");
return CsvFormatter::default_separator();
}
- string GlobalOptions::config_value() const
+ string
+ GlobalOptions::config_value() const
{
if (has_option("config"))
- return get_option("config")->second;
+ return get_argument("config");
return DEFAULT_CONFIG;
}
- string GlobalOptions::root_value() const
+ string
+ GlobalOptions::root_value() const
{
if (has_option("root"))
- return get_option("root")->second;
+ return get_argument("root");
return DEFAULT_ROOT;
}
- unsigned int GlobalOptions::table_style_raw() const
- {
- return stoul(get_option("table-style")->second);
- }
-
-
- bool GlobalOptions::wrong_table_style() const
- {
- if (!has_option("table-style"))
- return false;
-
- if (table_style_raw() >= Table::numStyles)
- return true;
-
- return false;
- }
-
-
- bool GlobalOptions::wrong_machine_readable() const
+ GlobalOptions::Ambit
+ GlobalOptions::ambit_value() const
{
- if (!has_option("machine-readable"))
- return false;
-
- string value = machine_readable_value();
+ if (!has_option("ambit"))
+ return Ambit::AUTO;
- if (value != CSV_OPTION && value != JSON_OPTION)
- return true;
+ string str = get_argument("ambit");
- return false;
- }
+ Ambit ambit;
+ if (!toValue(str, ambit, false))
+ {
+ string error = sformat(_("Invalid ambit %s."), str.c_str()) + '\n' +
+ sformat(_("Use %s, %s or %s."), toString(Ambit::AUTO).c_str(),
+ toString(Ambit::CLASSIC).c_str(), toString(Ambit::TRANSACTIONAL).c_str());
+ SN_THROW(OptionsException(error));
+ }
- bool GlobalOptions::missing_no_dbus() const
- {
- return has_option("root") && !has_option("no-dbus");
+ return ambit;
}
+ }
- string GlobalOptions::table_style_error() const
- {
- return sformat(_("Invalid table style %d."), table_style_raw()) + " " +
- sformat(_("Use an integer number from %d to %d."), 0, Table::numStyles - 1);
- }
-
-
- string GlobalOptions::machine_readable_error() const
- {
- string format = machine_readable_value();
-
- return sformat(_("Invalid machine readable format %s."), format.c_str()) + " " +
- sformat(_("Use %s or %s."), CSV_OPTION.c_str(), JSON_OPTION.c_str());
- }
-
+ const vector<string> EnumInfo<cli::GlobalOptions::OutputFormat>::names({ "table", "csv", "json" });
- string GlobalOptions::missing_no_dbus_error() const
- {
- return _("root argument can be used only together with no-dbus.\n"
- "Try 'snapper --help' for more information.");
- }
+ const vector<string> EnumInfo<cli::GlobalOptions::Ambit>::names({ "auto", "classic", "transactional" });
- }
}
/*
- * Copyright (c) [2019] SUSE LLC
+ * Copyright (c) [2019-2020] SUSE LLC
*
* All Rights Reserved.
*
#include <string>
+#include <snapper/Enum.h>
+
#include "client/Options.h"
#include "client/utils/GetOpts.h"
#include "client/utils/Table.h"
public:
- enum OutputFormat { TABLE, CSV, JSON };
+ enum class OutputFormat { TABLE, CSV, JSON };
+ enum class Ambit { AUTO, CLASSIC, TRANSACTIONAL };
- static std::string help_text();
+ static string help_text();
GlobalOptions(GetOpts& parser);
- virtual std::vector<std::string> errors() const override;
-
- bool quiet() const
- {
- return _quiet;
- }
-
- bool verbose() const
- {
- return _verbose;
- }
-
- bool utc() const
- {
- return _utc;
- }
-
- bool iso() const
- {
- return _iso;
- }
-
- bool no_dbus() const
- {
- return _no_dbus;
- }
-
- bool version() const
- {
- return _version;
- }
-
- bool help() const
- {
- return _help;
- }
-
- TableLineStyle table_style() const
- {
- return _table_style;
- }
-
- OutputFormat output_format() const
- {
- return _output_format;
- }
-
- string separator() const
- {
- return _separator;
- }
-
- string config() const
- {
- return _config;
- }
-
-
- string root() const
- {
- return _root;
- }
+ bool quiet() const { return _quiet; }
+ bool verbose() const { return _verbose; }
+ bool utc() const { return _utc; }
+ bool iso() const { return _iso; }
+ bool no_dbus() const { return _no_dbus; }
+ bool version() const { return _version; }
+ bool help() const { return _help; }
+ TableLineStyle table_style() const { return _table_style; }
+ OutputFormat output_format() const { return _output_format; }
+ string separator() const { return _separator; }
+ string config() const { return _config; }
+ string root() const { return _root; }
+ Ambit ambit() { return _ambit; }
+
+ void set_ambit(Ambit ambit) { _ambit = ambit; }
private:
void parse_options();
+ void check_options() const;
TableLineStyle table_style_value() const;
-
OutputFormat output_format_value() const;
-
- std::string machine_readable_value() const;
-
- std::string separator_value() const;
-
- std::string config_value() const;
-
- std::string root_value() const;
-
- unsigned int table_style_raw() const;
-
- bool wrong_table_style() const;
-
- bool wrong_machine_readable() const;
-
- bool missing_no_dbus() const;
-
- std::string table_style_error() const;
-
- std::string machine_readable_error() const;
-
- std::string missing_no_dbus_error() const;
+ string separator_value() const;
+ string config_value() const;
+ string root_value() const;
+ Ambit ambit_value() const;
bool _quiet;
-
bool _verbose;
-
bool _utc;
-
bool _iso;
-
bool _no_dbus;
-
bool _version;
-
bool _help;
-
TableLineStyle _table_style;
-
OutputFormat _output_format;
-
string _separator;
-
string _config;
-
string _root;
+ Ambit _ambit;
};
}
+
+
+ template <> struct EnumInfo<cli::GlobalOptions::OutputFormat> { static const vector<string> names; };
+
+ template <> struct EnumInfo<cli::GlobalOptions::Ambit> { static const vector<string> names; };
+
}
-#endif
\ No newline at end of file
+#endif
namespace cli
{
- Options::Options(GetOpts& parser) :
- _parser(parser), _options()
+ Options::Options(GetOpts& parser)
+ : _parser(parser), _options()
{}
- Options::~Options()
- {}
-
-
- bool Options::has_option(const string option_name) const
- {
- GetOpts::parsed_opts::const_iterator option = get_option(option_name);
-
- return option != _options.end();
- }
-
-
- GetOpts::parsed_opts::const_iterator
- Options::get_option(const string option_name) const
+ bool
+ Options::has_option(const string& name) const
{
- return _options.find(option_name);
+ return _options.find(name) != _options.end();
}
- bool Options::has_errors() const
+ const string&
+ Options::get_argument(const string& name) const
{
- return !errors().empty();
+ return _options.find(name)->second;
}
}
/*
- * Copyright (c) [2019] SUSE LLC
+ * Copyright (c) [2019-2020] SUSE LLC
*
* All Rights Reserved.
*
#include <string>
#include <vector>
+#include <snapper/Exception.h>
+
#include "client/utils/GetOpts.h"
namespace snapper
{
+ using std::string;
+ using std::vector;
+
+
+ struct OptionsException : public Exception
+ {
+ explicit OptionsException(const string& msg) : Exception(msg) {}
+ };
+
+
namespace cli
{
Options(GetOpts& parser);
- virtual bool has_errors() const;
-
- virtual std::vector<std::string> errors() const = 0;
-
- virtual ~Options();
+ virtual ~Options() {}
protected:
- bool has_option(const std::string option_name) const;
+ bool has_option(const string& name) const;
- GetOpts::parsed_opts::const_iterator
- get_option(const std::string option_name) const;
+ const string& get_argument(const string& name) const;
GetOpts& _parser;
}
}
-#endif
\ No newline at end of file
+#endif
/*
- * Copyright (c) [2016-2019] SUSE LLC
+ * Copyright (c) [2016-2020] SUSE LLC
*
* All Rights Reserved.
*
}
+ProxySnapshots::iterator
+ProxySnapshotsDbus::getActive()
+{
+ pair<bool, unsigned int> tmp = command_get_active_snapshot(conn(), configName());
+
+ return tmp.first ? find(tmp.second) : end();
+}
+
+
ProxySnapshots::const_iterator
ProxySnapshotsDbus::getActive() const
{
/*
- * Copyright (c) [2016-2019] SUSE LLC
+ * Copyright (c) [2016-2020] SUSE LLC
*
* All Rights Reserved.
*
virtual iterator getDefault() override;
virtual const_iterator getDefault() const override;
+ virtual iterator getActive() override;
virtual const_iterator getActive() const override;
DBus::Connection& conn() const;
/*
- * Copyright (c) [2016-2019] SUSE LLC
+ * Copyright (c) [2016-2020] SUSE LLC
*
* All Rights Reserved.
*
}
+ProxySnapshots::iterator
+ProxySnapshotsLib::getActive()
+{
+ Snapshots& snapshots = backref->snapper->getSnapshots();
+
+ Snapshots::const_iterator tmp = snapshots.getActive();
+
+ return tmp != snapshots.end() ? find(tmp->getNum()) : end();
+}
+
+
ProxySnapshots::const_iterator
ProxySnapshotsLib::getActive() const
{
/*
- * Copyright (c) [2016-2019] SUSE LLC
+ * Copyright (c) [2016-2020] SUSE LLC
*
* All Rights Reserved.
*
virtual iterator getDefault() override;
virtual const_iterator getDefault() const override;
+ virtual iterator getActive() override;
virtual const_iterator getActive() const override;
ProxySnapshotsLib(ProxySnapperLib* backref);
/*
- * Copyright (c) [2016-2019] SUSE LLC
+ * Copyright (c) [2016-2020] SUSE LLC
*
* All Rights Reserved.
*
virtual iterator getDefault() = 0;
virtual const_iterator getDefault() const = 0;
+ virtual iterator getActive() = 0;
virtual const_iterator getActive() const = 0;
iterator find(unsigned int i);
/*
* Copyright (c) [2011-2015] Novell, Inc.
- * Copyright (c) [2016-2019] SUSE LLC
+ * Copyright (c) [2016-2020] SUSE LLC
*
* All Rights Reserved.
*
struct Cmd
{
- typedef void (*cmd_func_t)(cli::GlobalOptions* global_options, ProxySnappers* snappers,
+ typedef void (*cmd_func_t)(cli::GlobalOptions& global_options, ProxySnappers* snappers,
ProxySnapper* snapper);
typedef void (*help_func_t)();
void
-command_list_configs(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper*)
+command_list_configs(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper*)
{
- cli::Command::ListConfigs command(*global_options, getopts, *snappers);
+ cli::Command::ListConfigs command(global_options, getopts, *snappers);
command.run();
}
void
-command_create_config(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper*)
+command_create_config(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper*)
{
const struct option options[] = {
{ "fstype", required_argument, 0, 'f' },
exit(EXIT_FAILURE);
}
- snappers->createConfig(global_options->config(), subvolume, fstype, template_name);
+ snappers->createConfig(global_options.config(), subvolume, fstype, template_name);
}
void
-command_delete_config(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper*)
+command_delete_config(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper*)
{
getopts.parse("delete-config", GetOpts::no_options);
if (getopts.hasArgs())
exit(EXIT_FAILURE);
}
- snappers->deleteConfig(global_options->config());
+ snappers->deleteConfig(global_options.config());
}
void
-command_get_config(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper*)
+command_get_config(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper*)
{
- cli::Command::GetConfig command(*global_options, getopts, *snappers);
+ cli::Command::GetConfig command(global_options, getopts, *snappers);
command.run();
}
void
-command_set_config(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper* snapper)
+command_set_config(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper* snapper)
{
getopts.parse("set-config", GetOpts::no_options);
if (!getopts.hasArgs())
void
-command_list(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper*)
+command_list(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper*)
{
- cli::Command::ListSnapshots command(*global_options, getopts, *snappers);
+ cli::Command::ListSnapshots command(global_options, getopts, *snappers);
command.run();
}
void
-command_create(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper* snapper)
+command_create(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper* snapper)
{
const struct option options[] = {
{ "type", required_argument, 0, 't' },
exit(EXIT_FAILURE);
}
- enum CreateType { CT_SINGLE, CT_PRE, CT_POST, CT_PRE_POST };
+ enum class CreateType { SINGLE, PRE, POST, PRE_POST };
const ProxySnapshots& snapshots = snapper->getSnapshots();
- CreateType type = CT_SINGLE;
+ CreateType type = CreateType::SINGLE;
ProxySnapshots::const_iterator snapshot1 = snapshots.end();
ProxySnapshots::const_iterator snapshot2 = snapshots.end();
bool print_number = false;
if ((opt = opts.find("type")) != opts.end())
{
if (opt->second == "single")
- type = CT_SINGLE;
+ type = CreateType::SINGLE;
else if (opt->second == "pre")
- type = CT_PRE;
+ type = CreateType::PRE;
else if (opt->second == "post")
- type = CT_POST;
+ type = CreateType::POST;
else if (opt->second == "pre-post")
- type = CT_PRE_POST;
+ type = CreateType::PRE_POST;
else
{
cerr << _("Unknown type of snapshot.") << endl;
if ((opt = opts.find("command")) != opts.end())
{
command = opt->second;
- type = CT_PRE_POST;
+ type = CreateType::PRE_POST;
}
if ((opt = opts.find("read-only")) != opts.end())
if ((opt = opts.find("from")) != opts.end())
parent = snapshots.findNum(opt->second);
- if (type == CT_POST && snapshot1 == snapshots.end())
+ if (type == CreateType::POST && snapshot1 == snapshots.end())
{
cerr << _("Missing or invalid pre-number.") << endl;
exit(EXIT_FAILURE);
}
- if (type == CT_PRE_POST && command.empty())
+ if (type == CreateType::PRE_POST && command.empty())
{
cerr << _("Missing command argument.") << endl;
exit(EXIT_FAILURE);
}
- if (type != CT_SINGLE && !scd.read_only)
+ if (type != CreateType::SINGLE && !scd.read_only)
{
cerr << _("Option --read-write only supported for snapshots of type single.") << endl;
exit(EXIT_FAILURE);
}
- if (type != CT_SINGLE && parent != snapshots.getCurrent())
+ if (type != CreateType::SINGLE && parent != snapshots.getCurrent())
{
cerr << _("Option --from only supported for snapshots of type single.") << endl;
exit(EXIT_FAILURE);
switch (type)
{
- case CT_SINGLE: {
+ case CreateType::SINGLE: {
snapshot1 = snapper->createSingleSnapshot(parent, scd);
if (print_number)
cout << snapshot1->getNum() << endl;
} break;
- case CT_PRE: {
+ case CreateType::PRE: {
snapshot1 = snapper->createPreSnapshot(scd);
if (print_number)
cout << snapshot1->getNum() << endl;
} break;
- case CT_POST: {
+ case CreateType::POST: {
snapshot2 = snapper->createPostSnapshot(snapshot1, scd);
if (print_number)
cout << snapshot2->getNum() << endl;
} break;
- case CT_PRE_POST: {
+ case CreateType::PRE_POST: {
snapshot1 = snapper->createPreSnapshot(scd);
system(command.c_str());
snapshot2 = snapper->createPostSnapshot(snapshot1, scd);
void
-command_modify(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper* snapper)
+command_modify(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper* snapper)
{
const struct option options[] = {
{ "description", required_argument, 0, 'd' },
void
-command_delete(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper* snapper)
+command_delete(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper* snapper)
{
const struct option options[] = {
{ "sync", no_argument, 0, 's' },
filter_undeletables(snapshots, nums);
- snapper->deleteSnapshots(nums, global_options->verbose());
+ snapper->deleteSnapshots(nums, global_options.verbose());
if (sync)
snapper->syncFilesystem();
void
-command_mount(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper* snapper)
+command_mount(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper* snapper)
{
getopts.parse("mount", GetOpts::no_options);
if (!getopts.hasArgs())
void
-command_umount(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper* snapper)
+command_umount(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper* snapper)
{
getopts.parse("umount", GetOpts::no_options);
if (!getopts.hasArgs())
void
-command_status(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper* snapper)
+command_status(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper* snapper)
{
const struct option options[] = {
{ "output", required_argument, 0, 'o' },
void
-command_diff(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper* snapper)
+command_diff(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper* snapper)
{
const struct option options[] = {
{ "input", required_argument, 0, 'i' },
void
-command_undo(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper* snapper)
+command_undo(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper* snapper)
{
const struct option options[] = {
{ "input", required_argument, 0, 'i' },
exit(EXIT_FAILURE);
}
- if (global_options->verbose())
+ if (global_options.verbose())
{
switch (it1->action)
{
void
-command_rollback(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper* snapper)
+command_rollback(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper* snapper)
{
const struct option options[] = {
{ "print-number", no_argument, 0, 'p' },
ProxyConfig config = snapper->getConfig();
- const Filesystem* filesystem = getFilesystem(config, global_options->root());
+ const Filesystem* filesystem = getFilesystem(config, global_options.root());
if (filesystem->fstype() != "btrfs")
{
cerr << _("Command 'rollback' only available for btrfs.") << endl;
ProxySnapshots::iterator previous_default = snapshots.getDefault();
+ if (global_options.ambit() == cli::GlobalOptions::Ambit::AUTO)
+ {
+ if (filesystem->isSnapshotReadOnly(previous_default->getNum()))
+ global_options.set_ambit(cli::GlobalOptions::Ambit::TRANSACTIONAL);
+ else
+ global_options.set_ambit(cli::GlobalOptions::Ambit::CLASSIC);
+ }
+
+ if (!global_options.quiet())
+ cout << sformat(_("Ambit is %s."), toString(global_options.ambit()).c_str()) << endl;
+
if (previous_default != snapshots.end() && scd1.description == default_description1)
scd1.description += sformat(" of #%d", previous_default->getNum());
- ProxySnapshots::const_iterator snapshot1 = snapshots.end();
- ProxySnapshots::const_iterator snapshot2 = snapshots.end();
-
- if (getopts.numArgs() == 0)
+ switch (global_options.ambit())
{
- if (!global_options->quiet())
- cout << _("Creating read-only snapshot of default subvolume.") << flush;
+ case cli::GlobalOptions::Ambit::CLASSIC:
+ {
+ ProxySnapshots::const_iterator snapshot1 = snapshots.end();
+ ProxySnapshots::const_iterator snapshot2 = snapshots.end();
- scd1.read_only = true;
- snapshot1 = snapper->createSingleSnapshotOfDefault(scd1);
+ if (getopts.numArgs() == 0)
+ {
+ if (!global_options.quiet())
+ cout << _("Creating read-only snapshot of default subvolume.") << flush;
- if (!global_options->quiet())
- cout << " " << sformat(_("(Snapshot %d.)"), snapshot1->getNum()) << endl;
+ scd1.read_only = true;
+ snapshot1 = snapper->createSingleSnapshotOfDefault(scd1);
- if (!global_options->quiet())
- cout << _("Creating read-write snapshot of current subvolume.") << flush;
+ if (!global_options.quiet())
+ cout << " " << sformat(_("(Snapshot %d.)"), snapshot1->getNum()) << endl;
- ProxySnapshots::const_iterator active = snapshots.getActive();
- if (active != snapshots.end() && scd2.description == default_description2)
- scd2.description += sformat(" of #%d", active->getNum());
+ if (!global_options.quiet())
+ cout << _("Creating read-write snapshot of current subvolume.") << flush;
- scd2.read_only = false;
- snapshot2 = snapper->createSingleSnapshot(snapshots.getCurrent(), scd2);
+ ProxySnapshots::const_iterator active = snapshots.getActive();
+ if (active != snapshots.end() && scd2.description == default_description2)
+ scd2.description += sformat(" of #%d", active->getNum());
- if (!global_options->quiet())
- cout << " " << sformat(_("(Snapshot %d.)"), snapshot2->getNum()) << endl;
- }
- else
- {
- ProxySnapshots::const_iterator tmp = snapshots.findNum(getopts.popArg());
+ scd2.read_only = false;
+ snapshot2 = snapper->createSingleSnapshot(snapshots.getCurrent(), scd2);
- if (!global_options->quiet())
- cout << _("Creating read-only snapshot of current system.") << flush;
+ if (!global_options.quiet())
+ cout << " " << sformat(_("(Snapshot %d.)"), snapshot2->getNum()) << endl;
+ }
+ else
+ {
+ ProxySnapshots::const_iterator tmp = snapshots.findNum(getopts.popArg());
- snapshot1 = snapper->createSingleSnapshot(scd1);
+ if (!global_options.quiet())
+ cout << _("Creating read-only snapshot of current system.") << flush;
- if (!global_options->quiet())
- cout << " " << sformat(_("(Snapshot %d.)"), snapshot1->getNum()) << endl;
+ snapshot1 = snapper->createSingleSnapshot(scd1);
- if (!global_options->quiet())
- cout << sformat(_("Creating read-write snapshot of snapshot %d."), tmp->getNum()) << flush;
+ if (!global_options.quiet())
+ cout << " " << sformat(_("(Snapshot %d.)"), snapshot1->getNum()) << endl;
- if (tmp != snapshots.end() && scd2.description == default_description2)
- scd2.description += sformat(" of #%d", tmp->getNum());
+ if (!global_options.quiet())
+ cout << sformat(_("Creating read-write snapshot of snapshot %d."), tmp->getNum()) << flush;
- scd2.read_only = false;
- snapshot2 = snapper->createSingleSnapshot(tmp, scd2);
+ if (tmp != snapshots.end() && scd2.description == default_description2)
+ scd2.description += sformat(" of #%d", tmp->getNum());
- if (!global_options->quiet())
- cout << " " << sformat(_("(Snapshot %d.)"), snapshot2->getNum()) << endl;
- }
+ scd2.read_only = false;
+ snapshot2 = snapper->createSingleSnapshot(tmp, scd2);
- if (previous_default != snapshots.end() && previous_default->getCleanup().empty())
- {
- SMD smd = previous_default->getSmd();
- smd.cleanup = "number";
- snapper->modifySnapshot(previous_default, smd);
- }
+ if (!global_options.quiet())
+ cout << " " << sformat(_("(Snapshot %d.)"), snapshot2->getNum()) << endl;
+ }
+
+ if (previous_default != snapshots.end() && previous_default->getCleanup().empty())
+ {
+ SMD smd = previous_default->getSmd();
+ smd.cleanup = "number";
+ snapper->modifySnapshot(previous_default, smd);
+ }
- if (!global_options->quiet())
- cout << sformat(_("Setting default subvolume to snapshot %d."), snapshot2->getNum()) << endl;
+ if (!global_options.quiet())
+ cout << sformat(_("Setting default subvolume to snapshot %d."), snapshot2->getNum()) << endl;
- filesystem->setDefault(snapshot2->getNum());
+ filesystem->setDefault(snapshot2->getNum());
- Hooks::rollback(filesystem->snapshotDir(snapshot1->getNum()),
- filesystem->snapshotDir(snapshot2->getNum()));
+ Hooks::rollback(filesystem->snapshotDir(snapshot1->getNum()),
+ filesystem->snapshotDir(snapshot2->getNum()));
- if (print_number)
- cout << snapshot2->getNum() << endl;
+ if (print_number)
+ cout << snapshot2->getNum() << endl;
+ }
+ break;
+
+ case cli::GlobalOptions::Ambit::TRANSACTIONAL:
+ {
+ // see bsc #1172273
+
+ ProxySnapshots::iterator snapshot = snapshots.end();
+
+ if (getopts.numArgs() == 0)
+ {
+ snapshot = snapshots.getActive();
+ }
+ else
+ {
+ snapshot = snapshots.findNum(getopts.popArg());
+ }
+
+ if (previous_default == snapshot)
+ {
+ cerr << _("Active snapshot is already default snapshot.") << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ SMD smd = snapshot->getSmd();
+ smd.cleanup = "";
+ snapper->modifySnapshot(snapshot, smd);
+
+ if (!global_options.quiet())
+ cout << sformat(_("Setting default subvolume to snapshot %d."), snapshot->getNum()) << endl;
+
+ filesystem->setDefault(snapshot->getNum());
+
+ Hooks::rollback(filesystem->snapshotDir(previous_default->getNum()),
+ filesystem->snapshotDir(snapshot->getNum()));
+ }
+ break;
+
+ case cli::GlobalOptions::Ambit::AUTO:
+ {
+ cerr << "internal error: ambit is auto" << endl;
+ exit(EXIT_FAILURE);
+ }
+ break;
+ }
}
#endif
void
-command_setup_quota(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper* snapper)
+command_setup_quota(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper* snapper)
{
GetOpts::parsed_opts opts = getopts.parse("setup-quota", GetOpts::no_options);
if (getopts.numArgs() != 0)
void
-command_cleanup(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper* snapper)
+command_cleanup(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper* snapper)
{
GetOpts::parsed_opts opts = getopts.parse("cleanup", GetOpts::no_options);
if (getopts.numArgs() != 1)
if (cleanup == "number")
{
- do_cleanup_number(snapper, global_options->verbose());
+ do_cleanup_number(snapper, global_options.verbose());
}
else if (cleanup == "timeline")
{
- do_cleanup_timeline(snapper, global_options->verbose());
+ do_cleanup_timeline(snapper, global_options.verbose());
}
else if (cleanup == "empty-pre-post")
{
- do_cleanup_empty_pre_post(snapper, global_options->verbose());
+ do_cleanup_empty_pre_post(snapper, global_options.verbose());
}
else
{
void
-command_debug(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper*)
+command_debug(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper*)
{
getopts.parse("debug", GetOpts::no_options);
if (getopts.hasArgs())
}
void
-command_xa_diff(cli::GlobalOptions* global_options, ProxySnappers* snappers, ProxySnapper* snapper)
+command_xa_diff(cli::GlobalOptions& global_options, ProxySnappers* snappers, ProxySnapper* snapper)
{
GetOpts::parsed_opts opts = getopts.parse("xadiff", GetOpts::no_options);
if (getopts.numArgs() < 1)
Cmd("debug", command_debug, help_debug, false)
};
- getopts.init(argc, argv);
-
- cli::GlobalOptions global_options(getopts);
-
- if (global_options.has_errors())
+ try
{
- cerr << global_options.errors().front() << endl;
+ getopts.init(argc, argv);
- exit(EXIT_FAILURE);
- }
+ cli::GlobalOptions global_options(getopts);
- if (global_options.version())
- {
- cout << "snapper " << Snapper::compileVersion() << endl;
- cout << "flags " << Snapper::compileFlags() << endl;
- exit(EXIT_SUCCESS);
- }
+ if (global_options.version())
+ {
+ cout << "snapper " << Snapper::compileVersion() << endl;
+ cout << "flags " << Snapper::compileFlags() << endl;
+ exit(EXIT_SUCCESS);
+ }
- if (global_options.help())
- {
- help(cmds);
- }
+ if (global_options.help())
+ {
+ help(cmds);
+ }
- if (!getopts.hasArgs())
- {
- cerr << _("No command provided.") << endl
- << _("Try 'snapper --help' for more information.") << endl;
- exit(EXIT_FAILURE);
- }
+ if (!getopts.hasArgs())
+ {
+ cerr << _("No command provided.") << endl
+ << _("Try 'snapper --help' for more information.") << endl;
+ exit(EXIT_FAILURE);
+ }
- const char* command = getopts.popArg();
+ const char* command = getopts.popArg();
- list<Cmd>::const_iterator cmd = cmds.begin();
- while (cmd != cmds.end() && (cmd->name != command && !contains(cmd->aliases, command)))
- ++cmd;
+ list<Cmd>::const_iterator cmd = cmds.begin();
+ while (cmd != cmds.end() && (cmd->name != command && !contains(cmd->aliases, command)))
+ ++cmd;
- if (cmd == cmds.end())
- {
- cerr << sformat(_("Unknown command '%s'."), command) << endl
- << _("Try 'snapper --help' for more information.") << endl;
- exit(EXIT_FAILURE);
- }
+ if (cmd == cmds.end())
+ {
+ cerr << sformat(_("Unknown command '%s'."), command) << endl
+ << _("Try 'snapper --help' for more information.") << endl;
+ exit(EXIT_FAILURE);
+ }
- try
- {
- ProxySnappers snappers(global_options.no_dbus() ? ProxySnappers::createLib(global_options.root()) :
- ProxySnappers::createDbus());
+ try
+ {
+ ProxySnappers snappers(global_options.no_dbus() ? ProxySnappers::createLib(global_options.root()) :
+ ProxySnappers::createDbus());
- if (cmd->needs_snapper)
- (*cmd->cmd_func)(&global_options, &snappers, snappers.getSnapper(global_options.config()));
- else
- (*cmd->cmd_func)(&global_options, &snappers, nullptr);
- }
- catch (const DBus::ErrorException& e)
- {
- SN_CAUGHT(e);
+ if (cmd->needs_snapper)
+ (*cmd->cmd_func)(global_options, &snappers, snappers.getSnapper(global_options.config()));
+ else
+ (*cmd->cmd_func)(global_options, &snappers, nullptr);
+ }
+ catch (const DBus::ErrorException& e)
+ {
+ SN_CAUGHT(e);
+
+ if (strcmp(e.name(), "error.unknown_config") == 0 && global_options.config() == "root")
+ {
+ cerr << _("The config 'root' does not exist. Likely snapper is not configured.") << endl
+ << _("See 'man snapper' for further instructions.") << endl;
+ exit(EXIT_FAILURE);
+ }
- if (strcmp(e.name(), "error.unknown_config") == 0 && global_options.config() == "root")
+ cerr << error_description(e) << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const DBus::FatalException& e)
{
- cerr << _("The config 'root' does not exist. Likely snapper is not configured.") << endl
- << _("See 'man snapper' for further instructions.") << endl;
+ SN_CAUGHT(e);
+ cerr << _("Failure") << " (" << e.what() << ")." << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const IllegalSnapshotException& e)
+ {
+ SN_CAUGHT(e);
+ cerr << _("Illegal snapshot.") << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const ConfigNotFoundException& e)
+ {
+ SN_CAUGHT(e);
+ cerr << sformat(_("Config '%s' not found."), global_options.config().c_str()) << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const InvalidConfigException& e)
+ {
+ SN_CAUGHT(e);
+ cerr << sformat(_("Config '%s' is invalid."), global_options.config().c_str()) << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const ListConfigsFailedException& e)
+ {
+ SN_CAUGHT(e);
+ cerr << sformat(_("Listing configs failed (%s)."), e.what()) << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const CreateConfigFailedException& e)
+ {
+ SN_CAUGHT(e);
+ cerr << sformat(_("Creating config failed (%s)."), e.what()) << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const DeleteConfigFailedException& e)
+ {
+ SN_CAUGHT(e);
+ cerr << sformat(_("Deleting config failed (%s)."), e.what()) << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const InvalidConfigdataException& e)
+ {
+ SN_CAUGHT(e);
+ cerr << _("Invalid configdata.") << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const AclException& e)
+ {
+ SN_CAUGHT(e);
+ cerr << _("ACL error.") << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const IOErrorException& e)
+ {
+ SN_CAUGHT(e);
+ cerr << sformat(_("IO error (%s)."), e.what()) << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const InvalidUserException& e)
+ {
+ SN_CAUGHT(e);
+ cerr << _("Invalid user.") << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const InvalidGroupException& e)
+ {
+ SN_CAUGHT(e);
+ cerr << _("Invalid group.") << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const QuotaException& e)
+ {
+ SN_CAUGHT(e);
+ cerr << sformat(_("Quota error (%s)."), e.what()) << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const FreeSpaceException& e)
+ {
+ SN_CAUGHT(e);
+ cerr << sformat(_("Free space error (%s)."), e.what()) << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const OptionsException& e)
+ {
+ SN_CAUGHT(e);
+ cerr << e.what() << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const Exception& e)
+ {
+ SN_CAUGHT(e);
+ cerr << sformat(_("Error (%s)."), e.what()) << endl;
exit(EXIT_FAILURE);
}
-
- cerr << error_description(e) << endl;
- exit(EXIT_FAILURE);
- }
- catch (const DBus::FatalException& e)
- {
- SN_CAUGHT(e);
- cerr << _("Failure") << " (" << e.what() << ")." << endl;
- exit(EXIT_FAILURE);
- }
- catch (const IllegalSnapshotException& e)
- {
- SN_CAUGHT(e);
- cerr << _("Illegal snapshot.") << endl;
- exit(EXIT_FAILURE);
- }
- catch (const ConfigNotFoundException& e)
- {
- SN_CAUGHT(e);
- cerr << sformat(_("Config '%s' not found."), global_options.config().c_str()) << endl;
- exit(EXIT_FAILURE);
- }
- catch (const InvalidConfigException& e)
- {
- SN_CAUGHT(e);
- cerr << sformat(_("Config '%s' is invalid."), global_options.config().c_str()) << endl;
- exit(EXIT_FAILURE);
- }
- catch (const ListConfigsFailedException& e)
- {
- SN_CAUGHT(e);
- cerr << sformat(_("Listing configs failed (%s)."), e.what()) << endl;
- exit(EXIT_FAILURE);
- }
- catch (const CreateConfigFailedException& e)
- {
- SN_CAUGHT(e);
- cerr << sformat(_("Creating config failed (%s)."), e.what()) << endl;
- exit(EXIT_FAILURE);
- }
- catch (const DeleteConfigFailedException& e)
- {
- SN_CAUGHT(e);
- cerr << sformat(_("Deleting config failed (%s)."), e.what()) << endl;
- exit(EXIT_FAILURE);
- }
- catch (const InvalidConfigdataException& e)
- {
- SN_CAUGHT(e);
- cerr << _("Invalid configdata.") << endl;
- exit(EXIT_FAILURE);
- }
- catch (const AclException& e)
- {
- SN_CAUGHT(e);
- cerr << _("ACL error.") << endl;
- exit(EXIT_FAILURE);
- }
- catch (const IOErrorException& e)
- {
- SN_CAUGHT(e);
- cerr << sformat(_("IO error (%s)."), e.what()) << endl;
- exit(EXIT_FAILURE);
- }
- catch (const InvalidUserException& e)
- {
- SN_CAUGHT(e);
- cerr << _("Invalid user.") << endl;
- exit(EXIT_FAILURE);
- }
- catch (const InvalidGroupException& e)
- {
- SN_CAUGHT(e);
- cerr << _("Invalid group.") << endl;
- exit(EXIT_FAILURE);
- }
- catch (const QuotaException& e)
- {
- SN_CAUGHT(e);
- cerr << sformat(_("Quota error (%s)."), e.what()) << endl;
- exit(EXIT_FAILURE);
- }
- catch (const FreeSpaceException& e)
- {
- SN_CAUGHT(e);
- cerr << sformat(_("Free space error (%s)."), e.what()) << endl;
- exit(EXIT_FAILURE);
}
- catch (const Exception& e)
+ catch (const OptionsException& e)
{
SN_CAUGHT(e);
- cerr << sformat(_("Error (%s)."), e.what()) << endl;
+ cerr << e.what() << endl;
exit(EXIT_FAILURE);
}
<refentry id='snapper8' xmlns:xlink="http://www.w3.org/1999/xlink">
<refentryinfo>
- <date>2019-10-14</date>
+ <date>2020-06-15</date>
</refentryinfo>
<refmeta>
<refentrytitle>snapper</refentrytitle>
<manvolnum>8</manvolnum>
- <refmiscinfo class='date'>2019-10-14</refmiscinfo>
+ <refmiscinfo class='date'>2020-06-15</refmiscinfo>
<refmiscinfo class='version'>@VERSION@</refmiscinfo>
<refmiscinfo class='manual'>Filesystem Snapshot Management</refmiscinfo>
</refmeta>
<para>Operate on target root. Only works together with no-dbus and only for some commands.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>-a, --ambit <replaceable>ambit</replaceable></option></term>
+ <listitem>
+ <para>Operate in the specified ambit. Can be used to override the ambit detection.
+ Allowed ambits are auto, classic and transactional.</para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><option>--version</option></term>
<listitem>
<para>The rollback command also sets the description, the cleanup
algorithm and some userdata unless the values are specified on the command
line. This will automate cleanup of snapshots created by rollbacks.</para>
+ <para>In other ambits than classic the rollback command does what is required
+ to do a rollback. Anyway it is recommended to use specific programs in that
+ case.</para>
</listitem>
</varlistentry>
+-------------------------------------------------------------------
+Tue Jun 16 18:31:47 CEST 2020 - aschnell@suse.com
+
+- special rollback for transactional server (bsc#1172273)
+- version 0.8.10
+
-------------------------------------------------------------------
Mon Apr 06 16:22:29 CEST 2020 - aschnell@suse.com
if ((size_t)(value) >= names.size())
throw OutOfRangeException();
- return names[value];
+ return names[(size_t)(value)];
}