# Makefile.am for snapper/tools/client
#
+SUBDIRS = utils
+
INCLUDES = -I$(top_srcdir) -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include
types.cc types.h \
commands.cc commands.h
-snapper_LDADD = ../snapper/libsnapper.la ../tools/utils/libutils.la ../dbus/libdbus.la -ldbus-1
+snapper_LDADD = ../snapper/libsnapper.la utils/libutils.la ../dbus/libdbus.la -ldbus-1
unsigned int
-command_create_xsnapshot(DBus::Connection& conn, const string& config_name, XSnapshotType type,
- unsigned int prenum, const string& description, const string& cleanup,
- const map<string, string>& userdata)
+command_create_single_xsnapshot(DBus::Connection& conn, const string& config_name,
+ const string& description, const string& cleanup,
+ const map<string, string>& userdata)
{
DBus::MessageMethodCall call("org.opensuse.snapper", "/org/opensuse/snapper",
- "org.opensuse.snapper", "CreateSnapshot");
+ "org.opensuse.snapper", "CreateSingleSnapshot");
DBus::Hoho hoho(call);
- hoho << config_name << type << prenum << description << cleanup << userdata;
+ hoho << config_name << description << cleanup << userdata;
DBus::Message reply = conn.send_and_reply_and_block(call);
unsigned int number;
-
+
+ DBus::Hihi hihi(reply);
+ hihi >> number;
+
+ return number;
+}
+
+
+unsigned int
+command_create_pre_xsnapshot(DBus::Connection& conn, const string& config_name,
+ const string& description, const string& cleanup,
+ const map<string, string>& userdata)
+{
+ DBus::MessageMethodCall call("org.opensuse.snapper", "/org/opensuse/snapper",
+ "org.opensuse.snapper", "CreatePreSnapshot");
+
+ DBus::Hoho hoho(call);
+ hoho << config_name << description << cleanup << userdata;
+
+ DBus::Message reply = conn.send_and_reply_and_block(call);
+
+ unsigned int number;
+
+ DBus::Hihi hihi(reply);
+ hihi >> number;
+
+ return number;
+}
+
+
+unsigned int
+command_create_post_xsnapshot(DBus::Connection& conn, const string& config_name,
+ unsigned int prenum, const string& description,
+ const string& cleanup, const map<string, string>& userdata)
+{
+ DBus::MessageMethodCall call("org.opensuse.snapper", "/org/opensuse/snapper",
+ "org.opensuse.snapper", "CreatePostSnapshot");
+
+ DBus::Hoho hoho(call);
+ hoho << config_name << prenum << description << cleanup << userdata;
+
+ DBus::Message reply = conn.send_and_reply_and_block(call);
+
+ unsigned int number;
+
DBus::Hihi hihi(reply);
hihi >> number;
return number;
}
+
+
+void
+command_create_xcomparison(DBus::Connection& conn, const string& config_name, unsigned int number1,
+ unsigned int number2)
+{
+ DBus::MessageMethodCall call("org.opensuse.snapper", "/org/opensuse/snapper",
+ "org.opensuse.snapper", "CreateComparison");
+
+ DBus::Hoho hoho(call);
+ hoho << config_name << number1 << number2;
+
+ DBus::Message reply = conn.send_and_reply_and_block(call);
+}
+
+
+list<XFile>
+command_get_xfiles(DBus::Connection& conn, const string& config_name, unsigned int number1,
+ unsigned int number2)
+{
+ DBus::MessageMethodCall call("org.opensuse.snapper", "/org/opensuse/snapper",
+ "org.opensuse.snapper", "GetFiles");
+
+ DBus::Hoho hoho(call);
+ hoho << config_name << number1 << number2;
+
+ DBus::Message reply = conn.send_and_reply_and_block(call);
+
+ DBus::Hihi hihi(reply);
+ list<XFile> files;
+ hihi >> files;
+
+ return files;
+}
+
+
+vector<string>
+command_get_xdiff(DBus::Connection& conn, const string& config_name, unsigned int number1,
+ unsigned int number2, const string& filename, const string& options)
+{
+ DBus::MessageMethodCall call("org.opensuse.snapper", "/org/opensuse/snapper",
+ "org.opensuse.snapper", "GetDiff");
+
+ DBus::Hoho hoho(call);
+ hoho << config_name << number1 << number2 << filename << options;
+
+ DBus::Message reply = conn.send_and_reply_and_block(call);
+
+ DBus::Hihi hihi(reply);
+ vector<string> files;
+ hihi >> files;
+
+ return files;
+}
#include <dbus/dbus.h>
#include <string>
+#include <vector>
#include <list>
#include <map>
using std::string;
+using std::vector;
using std::list;
using std::map;
command_list_xsnapshots(DBus::Connection& conn, const string& config_name);
unsigned int
-command_create_xsnapshot(DBus::Connection& conn, const string& config_name, XSnapshotType type,
- unsigned int prenum, const string& description, const string& cleanup,
- const map<string, string>& userdata);
+command_create_single_xsnapshot(DBus::Connection& conn, const string& config_name,
+ const string& description, const string& cleanup,
+ const map<string, string>& userdata);
+
+unsigned int
+command_create_pre_xsnapshot(DBus::Connection& conn, const string& config_name,
+ const string& description, const string& cleanup,
+ const map<string, string>& userdata);
+
+unsigned int
+command_create_post_xsnapshot(DBus::Connection& conn, const string& config_name,
+ unsigned int prenum, const string& description,
+ const string& cleanup, const map<string, string>& userdata);
+
+void
+command_create_xcomparison(DBus::Connection& conn, const string& config_name, unsigned int number1,
+ unsigned int number2);
+
+list<XFile>
+command_get_xfiles(DBus::Connection& conn, const string& config_name, unsigned int number1,
+ unsigned int number2);
+
+vector<string>
+command_get_xdiff(DBus::Connection& conn, const string& config_name, unsigned int number1,
+ unsigned int number2, const string& filename, const string& options);
#include <boost/algorithm/string.hpp>
#include "config.h"
-#include <snapper/Factory.h>
#include <snapper/Snapper.h>
-#include <snapper/Snapshot.h>
-#include <snapper/Comparison.h>
-#include <snapper/File.h>
#include <snapper/AppUtil.h>
#include <snapper/SnapperTmpl.h>
-#include <snapper/Compare.h>
#include <snapper/Enum.h>
#include <snapper/AsciiFile.h>
-#include "tools/utils/Table.h"
-#include "tools/utils/GetOpts.h"
+#include "utils/Table.h"
+#include "utils/GetOpts.h"
#include "commands.h"
string config_name = "root";
bool disable_filters = false;
-Snapper* sh = NULL;
-
-Snapshots::iterator
+unsigned int
read_num(const string& str)
{
- Snapshots& snapshots = sh->getSnapshots();
-
istringstream s(str);
unsigned int num = 0;
s >> num;
exit(EXIT_FAILURE);
}
- Snapshots::iterator snap = snapshots.find(num);
- if (snap == snapshots.end())
- {
- cerr << sformat(_("Snapshot '%u' not found."), num) << endl;
- exit(EXIT_FAILURE);
- }
-
- return snap;
+ return num;
}
-pair<Snapshots::iterator, Snapshots::iterator>
+pair<unsigned int, unsigned int>
read_nums(const string& str)
{
string::size_type pos = str.find("..");
exit(EXIT_FAILURE);
}
- Snapshots::iterator snap1 = read_num(str.substr(0, pos));
- Snapshots::iterator snap2 = read_num(str.substr(pos + 2));
+ unsigned int num1 = read_num(str.substr(0, pos));
+ unsigned int num2 = read_num(str.substr(pos + 2));
- if (snap1 == snap2)
+ if (num1 == num2)
{
cerr << _("Identical snapshots.") << endl;
exit(EXIT_FAILURE);
}
- return pair<Snapshots::iterator, Snapshots::iterator>(snap1, snap2);
+ return pair<unsigned int, unsigned int>(num1, num2);
}
void
-command_create_config()
+command_create_config(DBus::Connection& conn)
{
const struct option options[] = {
{ "fstype", required_argument, 0, 'f' },
void
-command_delete_config()
+command_delete_config(DBus::Connection& conn)
{
getopts.parse("delete-config", GetOpts::no_options);
if (getopts.hasArgs())
void
-command_list()
+command_list(DBus::Connection& conn)
{
const struct option options[] = {
{ "type", required_argument, 0, 't' },
header.add(_("Userdata"));
table.setHeader(header);
- const Snapshots& snapshots = sh->getSnapshots();
- for (Snapshots::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
+ list<XSnapshot> snapshots = command_list_xsnapshots(conn, config_name);
+ for (list<XSnapshot>::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
{
TableRow row;
- row.add(toString(it1->getType()));
- row.add(decString(it1->getNum()));
- // row.add(it1->getType() == POST ? decString(it1->getPreNum()) : "");
- row.add(it1->isCurrent() ? "" : datetime(it1->getDate(), false, false));
- row.add(it1->getCleanup());
- row.add(it1->getDescription());
- row.add(show_userdata(it1->getUserdata()));
+ row.add(/*toString(*/ decString((int)(it1->type)));
+ row.add(decString(it1->num));
+ row.add(it1->type == XPOST ? decString(it1->pre_num) : "");
+ row.add(it1->num == 0 ? "" : datetime(it1->date, false, false));
+ row.add(it1->cleanup);
+ row.add(it1->description);
+ row.add(show_userdata(it1->userdata));
table.add(row);
}
}
header.add(_("Userdata"));
table.setHeader(header);
- const Snapshots& snapshots = sh->getSnapshots();
- for (Snapshots::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
+ list<XSnapshot> snapshots = command_list_xsnapshots(conn, config_name);
+ for (list<XSnapshot>::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
{
- // if (it1->getType() != SINGLE)
- // continue;
+ if (it1->type != XSINGLE)
+ continue;
TableRow row;
- row.add(decString(it1->getNum()));
- row.add(it1->isCurrent() ? "" : datetime(it1->getDate(), false, false));
- row.add(it1->getDescription());
- row.add(show_userdata(it1->getUserdata()));
+ row.add(decString(it1->num));
+ row.add(it1->num == 0 ? "" : datetime(it1->date, false, false));
+ row.add(it1->description);
+ row.add(show_userdata(it1->userdata));
table.add(row);
}
}
header.add(_("Userdata"));
table.setHeader(header);
- const Snapshots& snapshots = sh->getSnapshots();
- for (Snapshots::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
+ list<XSnapshot> snapshots = command_list_xsnapshots(conn, config_name);
+ for (list<XSnapshot>::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
{
- // if (it1->getType() != PRE)
- // continue;
+ if (it1->type != XPRE)
+ continue;
+ list<XSnapshot>::const_iterator it2;
+ /*
Snapshots::const_iterator it2 = snapshots.findPost(it1);
if (it2 == snapshots.end())
continue;
+ */
TableRow row;
- row.add(decString(it1->getNum()));
- row.add(decString(it2->getNum()));
- row.add(datetime(it1->getDate(), false, false));
- row.add(datetime(it2->getDate(), false, false));
- row.add(it1->getDescription());
- row.add(show_userdata(it1->getUserdata()));
+ row.add(decString(it1->num));
+ row.add(decString(it2->num));
+ row.add(datetime(it1->date, false, false));
+ row.add(datetime(it2->date, false, false));
+ row.add(it1->description);
+ row.add(show_userdata(it1->userdata));
table.add(row);
}
}
void
-command_create()
+command_create(DBus::Connection& conn)
{
const struct option options[] = {
{ "type", required_argument, 0, 't' },
enum CreateType { CT_SINGLE, CT_PRE, CT_POST, CT_PRE_POST };
- const Snapshots& snapshots = sh->getSnapshots();
-
CreateType type = CT_SINGLE;
- Snapshots::const_iterator snap1 = snapshots.end();
+ unsigned int num1 = 0;
bool print_number = false;
string description;
string cleanup;
}
if ((opt = opts.find("pre-number")) != opts.end())
- snap1 = read_num(opt->second);
+ num1 = read_num(opt->second);
if ((opt = opts.find("print-number")) != opts.end())
print_number = true;
type = CT_PRE_POST;
}
- if (type == CT_POST && (snap1 == snapshots.end() || snap1->isCurrent()))
+ if (type == CT_POST && (num1 == 0))
{
cerr << _("Missing or invalid pre-number.") << endl;
exit(EXIT_FAILURE);
switch (type)
{
case CT_SINGLE: {
- Snapshots::iterator snap1 = sh->createSingleSnapshot(description);
- snap1->setCleanup(cleanup);
- snap1->setUserdata(userdata);
- snap1->flushInfo();
+ unsigned int num1 = command_create_single_xsnapshot(conn, config_name, description,
+ cleanup, userdata);
if (print_number)
- cout << snap1->getNum() << endl;
+ cout << num1 << endl;
} break;
case CT_PRE: {
- Snapshots::iterator snap1 = sh->createPreSnapshot(description);
- snap1->setCleanup(cleanup);
- snap1->setUserdata(userdata);
- snap1->flushInfo();
+ unsigned int num1 = command_create_pre_xsnapshot(conn, config_name, description,
+ cleanup, userdata);
if (print_number)
- cout << snap1->getNum() << endl;
+ cout << num1 << endl;
} break;
case CT_POST: {
- Snapshots::iterator snap2 = sh->createPostSnapshot(description, snap1);
- snap2->setCleanup(cleanup);
- snap2->setUserdata(userdata);
- snap2->flushInfo();
+ unsigned int num2 = command_create_post_xsnapshot(conn, config_name, num1, description,
+ cleanup, userdata);
if (print_number)
- cout << snap2->getNum() << endl;
- sh->startBackgroundComparsion(snap1, snap2);
+ cout << num2 << endl;
} break;
case CT_PRE_POST: {
- Snapshots::iterator snap1 = sh->createPreSnapshot(description);
- snap1->setCleanup(cleanup);
- snap1->setUserdata(userdata);
- snap1->flushInfo();
-
+ unsigned int num1 = command_create_pre_xsnapshot(conn, config_name, description,
+ cleanup, userdata);
system(command.c_str());
-
- Snapshots::iterator snap2 = sh->createPostSnapshot("", snap1);
- snap2->setCleanup(cleanup);
- snap2->setUserdata(userdata);
- snap2->flushInfo();
+ unsigned int num2 = command_create_post_xsnapshot(conn, config_name, num1, "",
+ cleanup, userdata);
if (print_number)
- cout << snap1->getNum() << ".." << snap2->getNum() << endl;
- sh->startBackgroundComparsion(snap1, snap2);
+ cout << num1 << ".." << num2 << endl;
} break;
}
}
void
-command_modify()
+command_modify(DBus::Connection& conn)
{
const struct option options[] = {
{ "description", required_argument, 0, 'd' },
{
while (getopts.hasArgs())
{
- Snapshots::iterator snapshot = read_num(getopts.popArg());
+ Snapshots::iterator snapshot; // = read_num(getopts.popArg());
GetOpts::parsed_opts::const_iterator opt;
void
-command_delete()
+command_delete(DBus::Connection& conn)
{
getopts.parse("delete", GetOpts::no_options);
if (!getopts.hasArgs())
{
while (getopts.hasArgs())
{
- Snapshots::iterator snapshot = read_num(getopts.popArg());
+ Snapshots::iterator snapshot; // = read_num(getopts.popArg());
- sh->deleteSnapshot(snapshot);
+ // sh->deleteSnapshot(snapshot);
}
}
catch (const IllegalSnapshotException& e)
void
-command_mount()
+command_mount(DBus::Connection& conn)
{
getopts.parse("mount", GetOpts::no_options);
if (!getopts.hasArgs())
{
while (getopts.hasArgs())
{
- Snapshots::iterator snapshot = read_num(getopts.popArg());
+ Snapshots::iterator snapshot; // = read_num(getopts.popArg());
snapshot->mountFilesystemSnapshot();
}
void
-command_umount()
+command_umount(DBus::Connection& conn)
{
getopts.parse("mount", GetOpts::no_options);
if (!getopts.hasArgs())
{
while (getopts.hasArgs())
{
- Snapshots::iterator snapshot = read_num(getopts.popArg());
+ Snapshots::iterator snapshot; // = read_num(getopts.popArg());
snapshot->umountFilesystemSnapshot();
}
void
-command_status()
+command_status(DBus::Connection& conn)
{
const struct option options[] = {
{ "output", required_argument, 0, 'o' },
GetOpts::parsed_opts::const_iterator opt;
- pair<Snapshots::const_iterator, Snapshots::const_iterator> snaps(read_nums(getopts.popArg()));
+ pair<unsigned int, unsigned int> snaps(read_nums(getopts.popArg()));
- Comparison comparison(sh, snaps.first, snaps.second);
+ command_create_xcomparison(conn, config_name, snaps.first, snaps.second);
- const Files& files = comparison.getFiles();
+ list<XFile> files = command_get_xfiles(conn, config_name, snaps.first, snaps.second);
FILE* file = stdout;
}
}
- for (Files::const_iterator it = files.begin(); it != files.end(); ++it)
- fprintf(file, "%s %s\n", statusToString(it->getPreToPostStatus()).c_str(),
- it->getAbsolutePath(LOC_SYSTEM).c_str());
+ for (list<XFile>::const_iterator it = files.begin(); it != files.end(); ++it)
+ fprintf(file, "%s %s\n", it->status.c_str(), it->filename.c_str()); // TODO abs filename
if (file != stdout)
fclose(file);
void
-command_diff()
+command_diff(DBus::Connection& conn)
{
GetOpts::parsed_opts opts = getopts.parse("diff", GetOpts::no_options);
GetOpts::parsed_opts::const_iterator opt;
- pair<Snapshots::const_iterator, Snapshots::const_iterator> snaps(read_nums(getopts.popArg()));
+ pair<unsigned int, unsigned int> snaps(read_nums(getopts.popArg()));
- Comparison comparison(sh, snaps.first, snaps.second);
+ command_create_xcomparison(conn, config_name, snaps.first, snaps.second);
- const Files& files = comparison.getFiles();
+ list<XFile> files = command_get_xfiles(conn, config_name, snaps.first, snaps.second);
if (getopts.numArgs() == 0)
{
- for (Files::const_iterator it1 = files.begin(); it1 != files.end(); ++it1)
+ for (list<XFile>::const_iterator it1 = files.begin(); it1 != files.end(); ++it1)
{
- vector<string> lines = it1->getDiff("--unified --new-file");
+ vector<string> lines = command_get_xdiff(conn, config_name, snaps.first, snaps.second,
+ it1->filename, "--unified --new-file");
for (vector<string>::const_iterator it2 = lines.begin(); it2 != lines.end(); ++it2)
- cout << it2->c_str() << endl;
+ cout << it2->c_str() << endl;
}
}
else
{
string name = getopts.popArg();
+ /*
Files::const_iterator tmp = files.findAbsolutePath(name);
if (tmp == files.end())
continue;
vector<string> lines = tmp->getDiff("--unified --new-file");
for (vector<string>::const_iterator it2 = lines.begin(); it2 != lines.end(); ++it2)
cout << it2->c_str() << endl;
+ */
}
}
}
void
-command_undo()
+command_undo(DBus::Connection& conn)
{
const struct option options[] = {
{ "input", required_argument, 0, 'i' },
exit(EXIT_FAILURE);
}
- pair<Snapshots::const_iterator, Snapshots::const_iterator> snaps(read_nums(getopts.popArg()));
+ pair<unsigned int, unsigned int> snaps(read_nums(getopts.popArg()));
FILE* file = NULL;
}
}
- if (snaps.first->isCurrent())
+ if (snaps.first == 0)
{
cerr << _("Invalid snapshots.") << endl;
exit(EXIT_FAILURE);
}
- Comparison comparison(sh, snaps.first, snaps.second);
+ command_create_xcomparison(conn, config_name, snaps.first, snaps.second);
- Files& files = comparison.getFiles();
+ list<XFile> files = command_get_xfiles(conn, config_name, snaps.first, snaps.second);
if (file)
{
name.erase(0, pos + 1);
}
+ /*
Files::iterator it = files.findAbsolutePath(name);
if (it == files.end())
{
}
it->setUndo(true);
+ */
}
}
else
{
if (getopts.numArgs() == 0)
{
+ /*
for (Files::iterator it = files.begin(); it != files.end(); ++it)
it->setUndo(true);
+ */
}
else
{
{
string name = getopts.popArg();
+ /*
Files::iterator tmp = files.findAbsolutePath(name);
if (tmp == files.end())
continue;
tmp->setUndo(true);
+ */
}
}
}
-
+ /*
UndoStatistic rs = comparison.getUndoStatistic();
if (rs.empty())
<< endl;
comparison.doUndo();
+ */
}
void
-command_cleanup()
+command_cleanup(DBus::Connection& conn)
{
const struct option options[] = {
{ 0, 0, 0, 0 }
if (cleanup == "number")
{
- sh->doCleanupNumber();
+ // sh->doCleanupNumber();
}
else if (cleanup == "timeline")
{
- sh->doCleanupTimeline();
+ // sh->doCleanupTimeline();
}
else if (cleanup == "empty-pre-post")
{
- sh->doCleanupEmptyPrePost();
+ // sh->doCleanupEmptyPrePost();
}
else
{
initDefaultLogger();
cmds["list-configs"] = command_list_configs;
- // cmds["create-config"] = command_create_config;
- // cmds["delete-config"] = command_delete_config;
- // cmds["list"] = command_list;
- // cmds["create"] = command_create;
- // cmds["modify"] = command_modify;
- // cmds["delete"] = command_delete;
- // cmds["mount"] = command_mount;
- // cmds["umount"] = command_umount;
- // cmds["status"] = command_status;
- // cmds["diff"] = command_diff;
- // cmds["undochange"] = command_undo;
- // cmds["cleanup"] = command_cleanup;
- // cmds["help"] = command_help;
+ cmds["create-config"] = command_create_config;
+ cmds["delete-config"] = command_delete_config;
+ cmds["list"] = command_list;
+ cmds["create"] = command_create;
+ cmds["modify"] = command_modify;
+ cmds["delete"] = command_delete;
+ cmds["mount"] = command_mount;
+ cmds["umount"] = command_umount;
+ cmds["status"] = command_status;
+ cmds["diff"] = command_diff;
+ cmds["undochange"] = command_undo;
+ cmds["cleanup"] = command_cleanup;
const struct option options[] = {
{ "quiet", no_argument, 0, 'q' },
exit(EXIT_FAILURE);
}
- DBus::Connection conn(DBUS_BUS_SYSTEM);
-
- if (cmd->first == "help" || cmd->first == "list-configs" ||
- cmd->first == "create-config" || cmd->first == "delete-config")
+ if (cmd->first == "help")
{
- (*cmd->second)(conn);
+ command_help();
}
else
{
- try
- {
- sh = createSnapper(config_name, disable_filters);
- }
- catch (const ConfigNotFoundException& e)
- {
- cerr << sformat(_("Config '%s' not found."), config_name.c_str()) << endl;
- exit(EXIT_FAILURE);
- }
- catch (const InvalidConfigException& e)
- {
- cerr << sformat(_("Config '%s' is invalid."), config_name.c_str()) << endl;
- exit(EXIT_FAILURE);
- }
+ DBus::Connection conn(DBUS_BUS_SYSTEM);
- if (!quiet)
- {
- sh->setCompareCallback(&compare_callback_impl);
- sh->setUndoCallback(&undo_callback_impl);
- }
-
- try
- {
- (*cmd->second)(conn);
- }
- catch (const SnapperException& e)
- {
- y2err("caught final exception");
- cerr << sformat(_("Command failed (%s). See log for more information."),
- e.what()) << endl;
- exit(EXIT_FAILURE);
- }
-
- deleteSnapper(sh);
+ (*cmd->second)(conn);
}
exit(EXIT_SUCCESS);
namespace DBus
{
const char* TypeInfo<XConfigInfo>::signature = "(ss)";
- const char* TypeInfo<XSnapshot>::signature = "(uqusa{ss})";
+ const char* TypeInfo<XSnapshot>::signature = "(uquusa{ss})";
const char* TypeInfo<XFile>::signature = "(ssb)";
const char* TypeInfo<XUndo>::signature = "(sb)";
operator>>(Hihi& hihi, XSnapshot& data)
{
hihi.open_recurse();
- hihi >> data.num >> data.type >> data.date >> data.description >> data.userdata;
+ hihi >> data.num >> data.type >> data.pre_num >> data.date >> data.description
+ >> data.userdata;
hihi.close_recurse();
return hihi;
}
}
}
-
};
-enum XSnapshotType { SINGLE, PRE, POST };
+enum XSnapshotType { XSINGLE, XPRE, XPOST };
struct XSnapshot
{
- unsigned int num;
XSnapshotType type;
- unsigned int date;
+ unsigned int num;
+ time_t date;
+ unsigned int pre_num;
string description;
+ string cleanup;
map<string, string> userdata;
};
#
-# Makefile.am for snapper/tools/utils
+# Makefile.am for snapper/client/utils
#
INCLUDES = -I$(top_srcdir)
bindings/Makefile
bindings/python/Makefile
tools/Makefile
- tools/utils/Makefile
dbus/Makefile
server/Makefile
client/Makefile
+ client/utils/Makefile
scripts/Makefile
data/Makefile
doc/Makefile
*/
+#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pwd.h>
dbus_interface='org.opensuse.snapper')
-print snapper.CreateSnapshot("root", 0, 0, "test", "", { "tid" : "456" })
+print snapper.CreateSingleSnapshot("root", "test", "", { "id" : "123" })
snapshots = snapper.ListSnapshots("root")
for snapshot in snapshots:
- print snapshot[0], snapshot[1], snapshot[2], snapshot[3],
- for k, v in snapshot[4].items():
+ print snapshot[0], snapshot[1], snapshot[2], snapshot[3], snapshot[4],
+ for k, v in snapshot[5].items():
print "%s=%s" % (k, v),
print
from os import readlink, getppid
from os.path import basename
-from subprocess import Popen, PIPE
+from dbus import SystemBus, Interface
from zypp_plugin import Plugin
class MyPlugin(Plugin):
exe = basename(readlink("/proc/%d/exe" % getppid()))
- args = ["snapper", "create", "--type=pre", "--print-number",
- "--cleanup-algorithm=number", "--description=zypp(%s)" % exe]
- self.o = Popen(args, stdout=PIPE).communicate()[0].strip()
+ num1 = snapper.CreatePreSnapshot("root", "zypp(%s)" % exe, "number")
self.ack()
def PLUGINEND(self, headers, body):
- args = ["snapper", "create", "--type=post", "--pre-number=%s" % self.o,
- "--cleanup-algorithm=number"]
- Popen(args)
+ num2 = snapper.CreatePostSnapshot("root", num1, "", "number")
self.ack()
+bus = SystemBus()
+
+snapper = Interface(get_object('org.opensuse.snapper', '/org/opensuse/snapper'),
+ dbus_interface='org.opensuse.snapper')
+
plugin = MyPlugin()
plugin.main()
return *it;
}
- return NULL;
+ throw NoComparison();
}
using namespace snapper;
+struct NoComparison : public std::exception
+{
+ explicit NoComparison() throw() {}
+ virtual const char* what() const throw() { return "no comparison"; }
+};
+
+
class Client
{
public:
namespace DBus
{
const char* TypeInfo<ConfigInfo>::signature = "(ss)";
- const char* TypeInfo<Snapshot>::signature = "(uqusa{ss})";
+ const char* TypeInfo<Snapshot>::signature = "(uquusa{ss})";
const char* TypeInfo<File>::signature = "(ssb)";
const char* TypeInfo<Undo>::signature = "(sb)";
operator<<(Hoho& hoho, const Snapshot& data)
{
hoho.open_struct();
- hoho << data.getNum() << data.getType() << data.getDate()
+ hoho << data.getNum() << data.getType() << data.getPreNum() << data.getDate()
<< data.getDescription() << data.getUserdata();
hoho.close_struct();
return hoho;
#include <dbus/dbus.h>
#include <string>
-#include <iostream>
#include <boost/algorithm/string.hpp>
#include <snapper/Snapper.h>
" <arg name='snapshots' type='v' direction='out'/>\n"
" </method>\n"
- " <method name='CreateSnapshot'>\n"
+ " <method name='CreateSingleSnapshot'>\n"
+ " <arg name='config-name' type='s' direction='in'/>\n"
+ " <arg name='description' type='s' direction='in'/>\n"
+ " <arg name='cleanup' type='s' direction='in'/>\n"
+ " <arg name='userdata' type='a{ss}' direction='in'/>\n"
+ " <arg name='number' type='u' direction='out'/>\n"
+ " </method>\n"
+
+ " <method name='CreatePreSnapshot'>\n"
+ " <arg name='config-name' type='s' direction='in'/>\n"
+ " <arg name='description' type='s' direction='in'/>\n"
+ " <arg name='cleanup' type='s' direction='in'/>\n"
+ " <arg name='userdata' type='a{ss}' direction='in'/>\n"
+ " <arg name='number' type='u' direction='out'/>\n"
+ " </method>\n"
+
+ " <method name='CreatePostSnapshot'>\n"
" <arg name='config-name' type='s' direction='in'/>\n"
- " <arg name='type' type='q' direction='in'/>\n"
" <arg name='pre-number' type='u' direction='in'/>\n"
" <arg name='description' type='s' direction='in'/>\n"
" <arg name='cleanup' type='s' direction='in'/>\n"
send_signal_config_created(DBus::Connection& conn, const string& config_name,
const string& subvolume)
{
- cout << "sending signal ConfigCreated" << endl;
-
DBus::MessageSignal msg("/org/opensuse/snapper", "org.opensuse.snapper", "ConfigCreated");
DBus::Hoho hoho(msg);
void
send_signal_snapshot_created(DBus::Connection& conn, const string& config_name,
- unsigned int number)
+ unsigned int num)
{
- cout << "sending signal SnapshotCreated" << endl;
-
DBus::MessageSignal msg("/org/opensuse/snapper", "org.opensuse.snapper", "SnapshotCreated");
DBus::Hoho hoho(msg);
- hoho << config_name << number;
+ hoho << config_name << num;
conn.send(msg);
}
void
send_signal_snapshot_deleted(DBus::Connection& conn, const string& config_name,
- unsigned int number)
+ unsigned int num)
{
- cout << "sending signal SnapshotDeleted" << endl;
-
DBus::MessageSignal msg("/org/opensuse/snapper", "org.opensuse.snapper", "SnapshotDeleted");
DBus::Hoho hoho(msg);
- hoho << config_name << number;
+ hoho << config_name << num;
conn.send(msg);
}
void
reply_to_command_list_configs(DBus::Connection& conn, DBus::Message& msg)
{
- cout << "command ListConfigs" << endl;
-
list<ConfigInfo> config_infos = Snapper::getConfigs();
DBus::MessageMethodReturn reply(msg);
void
reply_to_command_create_config(DBus::Connection& conn, DBus::Message& msg)
{
- cout << "command CreateConfigs" << endl;
-
- check_permission(conn, msg);
-
string config_name;
string subvolume;
DBus::Hihi hihi(msg);
hihi >> config_name >> subvolume;
+ y2mil("ListSnapshots config_name:" << config_name << " subvolume:" << subvolume);
+
+ check_permission(conn, msg);
+
DBus::MessageMethodReturn reply(msg);
conn.send(reply);
void
reply_to_command_lock_config(DBus::Connection& conn, DBus::Message& msg)
{
- cout << "command LockConfig" << endl;
-
string config_name;
DBus::Hihi hihi(msg);
hihi >> config_name;
- cout << "Method called with " << config_name << endl;
+ y2mil("LockConfig config_name:" << config_name);
check_permission(conn, msg, config_name);
void
reply_to_command_unlock_config(DBus::Connection& conn, DBus::Message& msg)
{
- cout << "command UnlockConfig" << endl;
-
string config_name;
DBus::Hihi hihi(msg);
hihi >> config_name;
- cout << "Method called with " << config_name << endl;
+ y2mil("UnlockConfig config_name:" << config_name);
check_permission(conn, msg, config_name);
void
reply_to_command_list_snapshots(DBus::Connection& conn, DBus::Message& msg)
{
- cout << "command ListSnapshots" << endl;
-
string config_name;
DBus::Hihi hihi(msg);
hihi >> config_name;
- cout << "Method called with " << config_name << endl;
+ y2mil("ListSnapshots config_name:" << config_name);
check_permission(conn, msg, config_name);
void
-reply_to_command_create_snapshot(DBus::Connection& conn, DBus::Message& msg)
+reply_to_command_create_single_snapshot(DBus::Connection& conn, DBus::Message& msg)
{
- cout << "command CreateSnapshots" << endl;
-
string config_name;
- SnapshotType type;
- unsigned int prenum;
string description;
string cleanup;
map<string, string> userdata;
DBus::Hihi hihi(msg);
- hihi >> config_name >> type >> prenum >> description >> cleanup >> userdata;
+ hihi >> config_name >> description >> cleanup >> userdata;
- cout << "Method called with " << config_name << endl;
+ y2mil("CreateSingleSnapshot config_name:" << config_name << " description:" << description <<
+ " cleanup:" << cleanup);
check_permission(conn, msg, config_name);
Snapper* snapper = getSnapper(config_name);
- // TODO type
Snapshots::iterator snap1 = snapper->createSingleSnapshot(description);
snap1->setCleanup(cleanup);
snap1->setUserdata(userdata);
void
-reply_to_command_delete_snapshot(DBus::Connection& conn, DBus::Message& msg)
+reply_to_command_create_pre_snapshot(DBus::Connection& conn, DBus::Message& msg)
{
- cout << "command DeleteSnapshots" << endl;
+ string config_name;
+ string description;
+ string cleanup;
+ map<string, string> userdata;
+
+ DBus::Hihi hihi(msg);
+ hihi >> config_name >> description >> cleanup >> userdata;
+
+ y2mil("CreatePreSnapshot config_name:" << config_name << " description:" << description <<
+ " cleanup:" << cleanup);
+
+ check_permission(conn, msg, config_name);
+
+ DBus::MessageMethodReturn reply(msg);
+
+ Snapper* snapper = getSnapper(config_name);
+
+ Snapshots::iterator snap1 = snapper->createPreSnapshot(description);
+ snap1->setCleanup(cleanup);
+ snap1->setUserdata(userdata);
+ snap1->flushInfo();
+
+ DBus::Hoho hoho(reply);
+ hoho << snap1->getNum();
+
+ conn.send(reply);
+
+ send_signal_snapshot_created(conn, config_name, snap1->getNum());
+}
+
+void
+reply_to_command_create_post_snapshot(DBus::Connection& conn, DBus::Message& msg)
+{
string config_name;
- unsigned int number;
+ unsigned int pre_num;
+ string description;
+ string cleanup;
+ map<string, string> userdata;
+
+ DBus::Hihi hihi(msg);
+ hihi >> config_name >> pre_num >> description >> cleanup >> userdata;
+
+ y2mil("CreatePostSnapshot config_name:" << config_name << " pre_num:" << pre_num <<
+ " description:" << description << " cleanup:" << cleanup);
+
+ check_permission(conn, msg, config_name);
+
+ DBus::MessageMethodReturn reply(msg);
+
+ Snapper* snapper = getSnapper(config_name);
+
+ Snapshots& snapshots = snapper->getSnapshots();
+
+ Snapshots::iterator snap1 = snapshots.find(pre_num);
+ if (snap1 == snapshots.end())
+ {
+ DBus::MessageError reply(msg, "error.invalid", DBUS_ERROR_FAILED);
+ conn.send(reply);
+ return;
+ }
+
+ Snapshots::iterator snap2 = snapper->createPostSnapshot(description, snap1);
+ snap2->setCleanup(cleanup);
+ snap2->setUserdata(userdata);
+ snap2->flushInfo();
+
+ DBus::Hoho hoho(reply);
+ hoho << snap2->getNum();
+
+ conn.send(reply);
+
+ send_signal_snapshot_created(conn, config_name, snap2->getNum());
+}
+
+
+
+void
+reply_to_command_delete_snapshot(DBus::Connection& conn, DBus::Message& msg)
+{
+ string config_name;
+ unsigned int num;
DBus::Hihi hihi(msg);
- hihi >> config_name >> number;
+ hihi >> config_name >> num;
- cout << "Method called with " << config_name << endl;
+ y2mil("DeleteSnapshot config_name:" << config_name << " num:" << num);
check_permission(conn, msg, config_name);
check_lock(conn, msg, config_name);
conn.send(reply);
- send_signal_snapshot_deleted(conn, config_name, number);
+ send_signal_snapshot_deleted(conn, config_name, num);
}
void
reply_to_command_create_comparison(DBus::Connection& conn, DBus::Message& msg)
{
- cout << "command CreateComparison" << endl;
-
string config_name;
- dbus_uint32_t number1, number2;
+ dbus_uint32_t num1, num2;
DBus::Hihi hihi(msg);
- hihi >> config_name >> number1 >> number2;
+ hihi >> config_name >> num1 >> num2;
- cout << "Method called with " << config_name << " " << number1 << " " << number2 << endl;
+ y2mil("CreateComparison config_name:" << config_name << " num1:" << num1 <<
+ " num2:" << num2);
check_permission(conn, msg, config_name);
Snapper* snapper = getSnapper(config_name);
Snapshots& snapshots = snapper->getSnapshots();
- Snapshots::const_iterator snapshot1 = snapshots.find(number1);
- Snapshots::const_iterator snapshot2 = snapshots.find(number2);
+ Snapshots::const_iterator snapshot1 = snapshots.find(num1);
+ Snapshots::const_iterator snapshot2 = snapshots.find(num2);
Comparison* comparison = new Comparison(snapper, snapshot1, snapshot2, true);
// TODO try, catch
void
Comparing::done()
{
- const Files& files = comparison->getFiles();
- cout << comparison->getFiles().size() << endl;
-
- for (Files::const_iterator it = files.begin(); it != files.end(); ++it)
- cout << statusToString(it->getPreToPostStatus()) << " "
- << it->getAbsolutePath(LOC_SYSTEM) << endl;
-
DBus::Hoho hoho(*reply);
- hoho << (dbus_uint32_t) comparison->getFiles().size();
conn->send(*reply);
delete reply;
void
reply_to_command_get_files(DBus::Connection& conn, DBus::Message& msg)
{
- cout << "command GetFiles" << endl;
-
string config_name;
- dbus_uint32_t number1, number2;
+ dbus_uint32_t num1, num2;
DBus::Hihi hihi(msg);
- hihi >> config_name >> number1 >> number2;
+ hihi >> config_name >> num1 >> num2;
- cout << "Method called with " << config_name << " " << number1 << " " << number2 << endl;
+ y2mil("GetFiles config_name:" << config_name << " num1:" << num1 << " num2:" <<
+ num2);
check_permission(conn, msg, config_name);
Clients::iterator it = clients.find(sender);
assert(it != clients.end());
- Comparison* comparison = it->find_comparison(config_name, number1, number2);
-
- if (!comparison || !comparison->isInitialized())
- {
- // error
- }
-
+ Comparison* comparison = it->find_comparison(config_name, num1, num2);
+
const Files& files = comparison->getFiles();
DBus::Hoho hoho(reply);
void
reply_to_command_set_undo(DBus::Connection& conn, DBus::Message& msg)
{
- cout << "command SetUndo" << endl;
-
string config_name;
- dbus_uint32_t number1, number2;
+ dbus_uint32_t num1, num2;
list<Undo> u;
DBus::Hihi hihi(msg);
- hihi >> config_name >> number1 >> number2 >> u;
+ hihi >> config_name >> num1 >> num2 >> u;
check_permission(conn, msg, config_name);
- cout << "Method called with " << config_name << " " << number1 << " " << number2 << endl;
+ y2mil("SetUndo config_name:" << config_name << " num1:" << num1 << " num2:" <<
+ num2);
string sender = msg.get_sender();
Clients::iterator it = clients.find(sender);
assert(it != clients.end());
- Comparison* comparison = it->find_comparison(config_name, number1, number2);
-
- if (!comparison || !comparison->isInitialized())
- {
- // error
- }
+ Comparison* comparison = it->find_comparison(config_name, num1, num2);
Files& files = comparison->getFiles();
void
reply_to_command_get_diff(DBus::Connection& conn, DBus::Message& msg)
{
- cout << "command GetDiff" << endl;
-
string config_name;
- dbus_uint32_t number1, number2;
+ dbus_uint32_t num1, num2;
string filename;
string options;
DBus::Hihi hihi(msg);
- hihi >> config_name >> number1 >> number2 >> filename >> options;
+ hihi >> config_name >> num1 >> num2 >> filename >> options;
- cout << "Method called with " << config_name << " " << number1 << " " << number2 << endl;
+ y2mil("GetDiff config_name:" << config_name << " num1:" << num1 << " num2:" <<
+ num2 << " filename:" << filename << " options:" << options);
check_permission(conn, msg, config_name);
Clients::iterator it = clients.find(sender);
assert(it != clients.end());
- Comparison* comparison = it->find_comparison(config_name, number1, number2);
-
- if (!comparison || !comparison->isInitialized())
- {
- // error
- }
+ Comparison* comparison = it->find_comparison(config_name, num1, num2);
Files& files = comparison->getFiles();
void
reply_to_command_debug(DBus::Connection& conn, DBus::Message& msg)
{
- cout << "command Debug" << endl;
-
// check_permission(conn, msg);
DBus::MessageMethodReturn reply(msg);
reply_to_command_unlock_config(conn, msg);
else if (msg.is_method_call("org.opensuse.snapper", "ListSnapshots"))
reply_to_command_list_snapshots(conn, msg);
- else if (msg.is_method_call("org.opensuse.snapper", "CreateSnapshot"))
- reply_to_command_create_snapshot(conn, msg);
+ else if (msg.is_method_call("org.opensuse.snapper", "CreateSingleSnapshot"))
+ reply_to_command_create_single_snapshot(conn, msg);
+ else if (msg.is_method_call("org.opensuse.snapper", "CreatePreSnapshot"))
+ reply_to_command_create_pre_snapshot(conn, msg);
+ else if (msg.is_method_call("org.opensuse.snapper", "CreatePostSnapshot"))
+ reply_to_command_create_post_snapshot(conn, msg);
else if (msg.is_method_call("org.opensuse.snapper", "DeleteSnapshot"))
reply_to_command_delete_snapshot(conn, msg);
else if (msg.is_method_call("org.opensuse.snapper", "CreateComparison"))
else if (msg.is_method_call("org.opensuse.snapper", "GetDiff"))
reply_to_command_get_diff(conn, msg);
}
- catch (DBus::MarshallingException)
+ catch (const DBus::MarshallingException& e)
{
DBus::MessageError reply(msg, "error.marshalling", DBUS_ERROR_FAILED);
conn.send(reply);
}
- catch (Permissions)
+ catch (const Permissions& e)
+ {
+ DBus::MessageError reply(msg, "error.no_permissions", DBUS_ERROR_FAILED);
+ conn.send(reply);
+ }
+ catch (const Lock& e)
+ {
+ DBus::MessageError reply(msg, "error.config_locked", DBUS_ERROR_FAILED);
+ conn.send(reply);
+ }
+ catch (const NoComparison& e)
{
- DBus::MessageError reply(msg, "error.permissions", DBUS_ERROR_FAILED);
+ DBus::MessageError reply(msg, "error.no_comparisons", DBUS_ERROR_FAILED);
conn.send(reply);
}
- catch (Lock)
+ catch (const IllegalSnapshotException& e)
{
- DBus::MessageError reply(msg, "error.locked", DBUS_ERROR_FAILED);
+ DBus::MessageError reply(msg, "error.illegal_snapshot", DBUS_ERROR_FAILED);
conn.send(reply);
}
}
compare-dirs.o
compare-dirs
-snapper.o
-snapper
# Makefile.am for snapper/tools
#
-SUBDIRS = utils
-
INCLUDES = -I$(top_srcdir)
compare_dirs_SOURCES = compare-dirs.cc
compare_dirs_LDADD = ../snapper/libsnapper.la
-
-bin_PROGRAMS = snapper
-
-snapper_SOURCES = snapper.cc
-snapper_LDADD = ../snapper/libsnapper.la utils/libutils.la
-
+++ /dev/null
-/*
- * Copyright (c) 2011-2012 Novell, Inc.
- *
- * 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 Novell, Inc.
- *
- * To contact Novell about this file by physical or electronic mail, you may
- * find current contact information at www.novell.com.
- */
-
-
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <iostream>
-#include <boost/algorithm/string.hpp>
-
-#include "config.h"
-#include <snapper/Factory.h>
-#include <snapper/Snapper.h>
-#include <snapper/Snapshot.h>
-#include <snapper/Comparison.h>
-#include <snapper/File.h>
-#include <snapper/AppUtil.h>
-#include <snapper/SnapperTmpl.h>
-#include <snapper/Compare.h>
-#include <snapper/Enum.h>
-#include <snapper/AsciiFile.h>
-
-#include "utils/Table.h"
-#include "utils/GetOpts.h"
-
-using namespace snapper;
-using namespace std;
-
-
-typedef void (*cmd_fnc)();
-map<string, cmd_fnc> cmds;
-
-GetOpts getopts;
-
-bool quiet = false;
-bool verbose = false;
-string config_name = "root";
-bool disable_filters = false;
-
-Snapper* sh = NULL;
-
-
-Snapshots::iterator
-read_num(const string& str)
-{
- Snapshots& snapshots = sh->getSnapshots();
-
- istringstream s(str);
- unsigned int num = 0;
- s >> num;
-
- if (s.fail() || !s.eof())
- {
- cerr << sformat(_("Invalid snapshot '%s'."), str.c_str()) << endl;
- exit(EXIT_FAILURE);
- }
-
- Snapshots::iterator snap = snapshots.find(num);
- if (snap == snapshots.end())
- {
- cerr << sformat(_("Snapshot '%u' not found."), num) << endl;
- exit(EXIT_FAILURE);
- }
-
- return snap;
-}
-
-
-pair<Snapshots::iterator, Snapshots::iterator>
-read_nums(const string& str)
-{
- string::size_type pos = str.find("..");
- if (pos == string::npos)
- {
- cerr << _("Invalid snapshots.") << endl;
- exit(EXIT_FAILURE);
- }
-
- Snapshots::iterator snap1 = read_num(str.substr(0, pos));
- Snapshots::iterator snap2 = read_num(str.substr(pos + 2));
-
- if (snap1 == snap2)
- {
- cerr << _("Identical snapshots.") << endl;
- exit(EXIT_FAILURE);
- }
-
- return pair<Snapshots::iterator, Snapshots::iterator>(snap1, snap2);
-}
-
-
-map<string, string>
-read_userdata(const string& s, const map<string, string>& old = map<string, string>())
-{
- map<string, string> userdata = old;
-
- list<string> tmp;
- boost::split(tmp, s, boost::is_any_of(","), boost::token_compress_on);
- if (tmp.empty())
- {
- cerr << _("Invalid userdata.") << endl;
- exit(EXIT_FAILURE);
- }
-
- for (list<string>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
- {
- string::size_type pos = it->find("=");
- if (pos == string::npos)
- {
- cerr << _("Invalid userdata.") << endl;
- exit(EXIT_FAILURE);
- }
-
- string key = boost::trim_copy(it->substr(0, pos));
- string value = boost::trim_copy(it->substr(pos + 1));
-
- if (key.empty())
- {
- cerr << _("Invalid userdata.") << endl;
- exit(EXIT_FAILURE);
- }
-
- if (value.empty())
- userdata.erase(key);
- else
- userdata[key] = value;
- }
-
- return userdata;
-}
-
-
-string
-show_userdata(const map<string, string>& userdata)
-{
- string s;
-
- for (map<string, string>::const_iterator it = userdata.begin(); it != userdata.end(); ++it)
- {
- if (!s.empty())
- s += ", ";
- s += it->first + "=" + it->second;
- }
-
- return s;
-}
-
-
-void
-help_list_configs()
-{
- cout << _(" List configs:") << endl
- << _("\tsnapper list-configs") << endl
- << endl;
-}
-
-
-void
-command_list_configs()
-{
- getopts.parse("list-configs", GetOpts::no_options);
- if (getopts.hasArgs())
- {
- cerr << _("Command 'list-configs' does not take arguments.") << endl;
- exit(EXIT_FAILURE);
- }
-
- Table table;
-
- TableHeader header;
- header.add(_("Config"));
- header.add(_("Subvolume"));
- table.setHeader(header);
-
- try
- {
- list<ConfigInfo> config_infos = Snapper::getConfigs();
- for (list<ConfigInfo>::const_iterator it = config_infos.begin(); it != config_infos.end(); ++it)
- {
- TableRow row;
- row.add(it->config_name);
- row.add(it->subvolume);
- table.add(row);
- }
- }
- catch (const ListConfigsFailedException& e)
- {
- cerr << sformat(_("Listing configs failed (%s)."), e.what()) << endl;
- exit(EXIT_FAILURE);
- }
-
- cout << table;
-}
-
-
-void
-help_create_config()
-{
- cout << _(" Create config:") << endl
- << _("\tsnapper create-config <subvolume>") << endl
- << endl
- << _(" Options for 'create-config' command:") << endl
- << _("\t--fstype, -f <fstype>\t\tManually set filesystem type.") << endl
- << _("\t--template, -t <name>\t\tName of config template to use.") << endl
- << endl;
-}
-
-
-void
-command_create_config()
-{
- const struct option options[] = {
- { "fstype", required_argument, 0, 'f' },
- { "template", required_argument, 0, 't' },
- { 0, 0, 0, 0 }
- };
-
- GetOpts::parsed_opts opts = getopts.parse("create-config", options);
- if (getopts.numArgs() != 1)
- {
- cerr << _("Command 'create-config' needs one argument.") << endl;
- exit(EXIT_FAILURE);
- }
-
- string subvolume = realpath(getopts.popArg());
- if (subvolume.empty())
- {
- cerr << _("Invalid subvolume.") << endl;
- exit(EXIT_FAILURE);
- }
-
- string fstype = "";
- string template_name = "default";
-
- GetOpts::parsed_opts::const_iterator opt;
-
- if ((opt = opts.find("fstype")) != opts.end())
- fstype = opt->second;
-
- if ((opt = opts.find("template")) != opts.end())
- template_name = opt->second;
-
- if (fstype.empty() && !Snapper::detectFstype(subvolume, fstype))
- {
- cerr << _("Detecting filesystem type failed.") << endl;
- exit(EXIT_FAILURE);
- }
-
- try
- {
- Snapper::createConfig(config_name, subvolume, fstype, template_name);
- }
- catch (const CreateConfigFailedException& e)
- {
- cerr << sformat(_("Creating config failed (%s)."), e.what()) << endl;
- exit(EXIT_FAILURE);
- }
-}
-
-
-void
-help_delete_config()
-{
- cout << _(" Delete config:") << endl
- << _("\tsnapper delete-config") << endl
- << endl;
-}
-
-
-void
-command_delete_config()
-{
- getopts.parse("delete-config", GetOpts::no_options);
- if (getopts.hasArgs())
- {
- cerr << _("Command 'delete-config' does not take arguments.") << endl;
- exit(EXIT_FAILURE);
- }
-
- try
- {
- Snapper::deleteConfig(config_name);
- }
- catch (const DeleteConfigFailedException& e)
- {
- cerr << sformat(_("Deleting config failed (%s)."), e.what()) << endl;
- exit(EXIT_FAILURE);
- }
-}
-
-
-void
-help_list()
-{
- cout << _(" List snapshots:") << endl
- << _("\tsnapper list") << endl
- << endl
- << _(" Options for 'list' command:") << endl
- << _("\t--type, -t <type>\t\tType of snapshots to list.") << endl
- << endl;
-}
-
-
-void
-command_list()
-{
- const struct option options[] = {
- { "type", required_argument, 0, 't' },
- { 0, 0, 0, 0 }
- };
-
- GetOpts::parsed_opts opts = getopts.parse("list", options);
- if (getopts.hasArgs())
- {
- cerr << _("Command 'list' does not take arguments.") << endl;
- exit(EXIT_FAILURE);
- }
-
- enum ListMode { LM_ALL, LM_SINGLE, LM_PRE_POST };
- ListMode list_mode = LM_ALL;
-
- GetOpts::parsed_opts::const_iterator opt;
-
- if ((opt = opts.find("type")) != opts.end())
- {
- if (opt->second == "all")
- list_mode = LM_ALL;
- else if (opt->second == "single")
- list_mode = LM_SINGLE;
- else if (opt->second == "pre-post")
- list_mode = LM_PRE_POST;
- else
- {
- cerr << _("Unknown type of snapshots.") << endl;
- exit(EXIT_FAILURE);
- }
- }
-
- Table table;
-
- switch (list_mode)
- {
- case LM_ALL:
- {
- TableHeader header;
- header.add(_("Type"));
- header.add(_("#"));
- header.add(_("Pre #"));
- header.add(_("Date"));
- header.add(_("Cleanup"));
- header.add(_("Description"));
- header.add(_("Userdata"));
- table.setHeader(header);
-
- const Snapshots& snapshots = sh->getSnapshots();
- for (Snapshots::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
- {
- TableRow row;
- row.add(toString(it1->getType()));
- row.add(decString(it1->getNum()));
- row.add(it1->getType() == POST ? decString(it1->getPreNum()) : "");
- row.add(it1->isCurrent() ? "" : datetime(it1->getDate(), false, false));
- row.add(it1->getCleanup());
- row.add(it1->getDescription());
- row.add(show_userdata(it1->getUserdata()));
- table.add(row);
- }
- }
- break;
-
- case LM_SINGLE:
- {
- TableHeader header;
- header.add(_("#"));
- header.add(_("Date"));
- header.add(_("Description"));
- header.add(_("Userdata"));
- table.setHeader(header);
-
- const Snapshots& snapshots = sh->getSnapshots();
- for (Snapshots::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
- {
- if (it1->getType() != SINGLE)
- continue;
-
- TableRow row;
- row.add(decString(it1->getNum()));
- row.add(it1->isCurrent() ? "" : datetime(it1->getDate(), false, false));
- row.add(it1->getDescription());
- row.add(show_userdata(it1->getUserdata()));
- table.add(row);
- }
- }
- break;
-
- case LM_PRE_POST:
- {
- TableHeader header;
- header.add(_("Pre #"));
- header.add(_("Post #"));
- header.add(_("Pre Date"));
- header.add(_("Post Date"));
- header.add(_("Description"));
- header.add(_("Userdata"));
- table.setHeader(header);
-
- const Snapshots& snapshots = sh->getSnapshots();
- for (Snapshots::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
- {
- if (it1->getType() != PRE)
- continue;
-
- Snapshots::const_iterator it2 = snapshots.findPost(it1);
- if (it2 == snapshots.end())
- continue;
-
- TableRow row;
- row.add(decString(it1->getNum()));
- row.add(decString(it2->getNum()));
- row.add(datetime(it1->getDate(), false, false));
- row.add(datetime(it2->getDate(), false, false));
- row.add(it1->getDescription());
- row.add(show_userdata(it1->getUserdata()));
- table.add(row);
- }
- }
- break;
- }
-
- cout << table;
-}
-
-
-void
-help_create()
-{
- cout << _(" Create snapshot:") << endl
- << _("\tsnapper create") << endl
- << endl
- << _(" Options for 'create' command:") << endl
- << _("\t--type, -t <type>\t\tType for snapshot.") << endl
- << _("\t--pre-number <number>\t\tNumber of corresponding pre snapshot.") << endl
- << _("\t--print-number, -p\t\tPrint number of created snapshot.") << endl
- << _("\t--description, -d <description>\tDescription for snapshot.") << endl
- << _("\t--cleanup-algorithm, -c <algo>\tCleanup algorithm for snapshot.") << endl
- << _("\t--userdata, -u <userdata>\tUserdata for snapshot.") << endl
- << _("\t--command <command>\tRun command and create pre and post snapshots.") << endl
- << endl;
-}
-
-
-void
-command_create()
-{
- const struct option options[] = {
- { "type", required_argument, 0, 't' },
- { "pre-number", required_argument, 0, 0 },
- { "print-number", no_argument, 0, 'p' },
- { "description", required_argument, 0, 'd' },
- { "cleanup-algorithm", required_argument, 0, 'c' },
- { "userdata", required_argument, 0, 'u' },
- { "command", required_argument, 0, 0 },
- { 0, 0, 0, 0 }
- };
-
- GetOpts::parsed_opts opts = getopts.parse("create", options);
- if (getopts.hasArgs())
- {
- cerr << _("Command 'create' does not take arguments.") << endl;
- exit(EXIT_FAILURE);
- }
-
- enum CreateType { CT_SINGLE, CT_PRE, CT_POST, CT_PRE_POST };
-
- const Snapshots& snapshots = sh->getSnapshots();
-
- CreateType type = CT_SINGLE;
- Snapshots::const_iterator snap1 = snapshots.end();
- bool print_number = false;
- string description;
- string cleanup;
- map<string, string> userdata;
- string command;
-
- GetOpts::parsed_opts::const_iterator opt;
-
- if ((opt = opts.find("type")) != opts.end())
- {
- if (opt->second == "single")
- type = CT_SINGLE;
- else if (opt->second == "pre")
- type = CT_PRE;
- else if (opt->second == "post")
- type = CT_POST;
- else if (opt->second == "pre-post")
- type = CT_PRE_POST;
- else
- {
- cerr << _("Unknown type of snapshot.") << endl;
- exit(EXIT_FAILURE);
- }
- }
-
- if ((opt = opts.find("pre-number")) != opts.end())
- snap1 = read_num(opt->second);
-
- if ((opt = opts.find("print-number")) != opts.end())
- print_number = true;
-
- if ((opt = opts.find("description")) != opts.end())
- description = opt->second;
-
- if ((opt = opts.find("cleanup-algorithm")) != opts.end())
- cleanup = opt->second;
-
- if ((opt = opts.find("userdata")) != opts.end())
- userdata = read_userdata(opt->second);
-
- if ((opt = opts.find("command")) != opts.end())
- {
- command = opt->second;
- type = CT_PRE_POST;
- }
-
- if (type == CT_POST && (snap1 == snapshots.end() || snap1->isCurrent()))
- {
- cerr << _("Missing or invalid pre-number.") << endl;
- exit(EXIT_FAILURE);
- }
-
- if (type == CT_PRE_POST && command.empty())
- {
- cerr << _("Missing command argument.") << endl;
- exit(EXIT_FAILURE);
- }
-
- try
- {
- switch (type)
- {
- case CT_SINGLE: {
- Snapshots::iterator snap1 = sh->createSingleSnapshot(description);
- snap1->setCleanup(cleanup);
- snap1->setUserdata(userdata);
- snap1->flushInfo();
- if (print_number)
- cout << snap1->getNum() << endl;
- } break;
-
- case CT_PRE: {
- Snapshots::iterator snap1 = sh->createPreSnapshot(description);
- snap1->setCleanup(cleanup);
- snap1->setUserdata(userdata);
- snap1->flushInfo();
- if (print_number)
- cout << snap1->getNum() << endl;
- } break;
-
- case CT_POST: {
- Snapshots::iterator snap2 = sh->createPostSnapshot(description, snap1);
- snap2->setCleanup(cleanup);
- snap2->setUserdata(userdata);
- snap2->flushInfo();
- if (print_number)
- cout << snap2->getNum() << endl;
- sh->startBackgroundComparsion(snap1, snap2);
- } break;
-
- case CT_PRE_POST: {
- Snapshots::iterator snap1 = sh->createPreSnapshot(description);
- snap1->setCleanup(cleanup);
- snap1->setUserdata(userdata);
- snap1->flushInfo();
-
- system(command.c_str());
-
- Snapshots::iterator snap2 = sh->createPostSnapshot("", snap1);
- snap2->setCleanup(cleanup);
- snap2->setUserdata(userdata);
- snap2->flushInfo();
- if (print_number)
- cout << snap1->getNum() << ".." << snap2->getNum() << endl;
- sh->startBackgroundComparsion(snap1, snap2);
- } break;
- }
- }
- catch (const InvalidUserdataException& e)
- {
- cerr << _("Invalid userdata.") << endl;
- exit(EXIT_FAILURE);
- }
-}
-
-
-void
-help_modify()
-{
- cout << _(" Modify snapshot:") << endl
- << _("\tsnapper modify <number>") << endl
- << endl
- << _(" Options for 'modify' command:") << endl
- << _("\t--description, -d <description>\tDescription for snapshot.") << endl
- << _("\t--cleanup-algorithm, -c <algo>\tCleanup algorithm for snapshot.") << endl
- << _("\t--userdata, -u <userdata>\tUserdata for snapshot.") << endl
- << endl;
-}
-
-
-void
-command_modify()
-{
- const struct option options[] = {
- { "description", required_argument, 0, 'd' },
- { "cleanup-algorithm", required_argument, 0, 'c' },
- { "userdata", required_argument, 0, 'u' },
- { 0, 0, 0, 0 }
- };
-
- GetOpts::parsed_opts opts = getopts.parse("modify", options);
-
- if (!getopts.hasArgs())
- {
- cerr << _("Command 'modify' needs at least one argument.") << endl;
- exit(EXIT_FAILURE);
- }
-
- try
- {
- while (getopts.hasArgs())
- {
- Snapshots::iterator snapshot = read_num(getopts.popArg());
-
- GetOpts::parsed_opts::const_iterator opt;
-
- if ((opt = opts.find("description")) != opts.end())
- snapshot->setDescription(opt->second);
-
- if ((opt = opts.find("cleanup-algorithm")) != opts.end())
- snapshot->setCleanup(opt->second);
-
- if ((opt = opts.find("userdata")) != opts.end())
- snapshot->setUserdata(read_userdata(opt->second, snapshot->getUserdata()));
-
- snapshot->flushInfo();
- }
- }
- catch (const IllegalSnapshotException& e)
- {
- cerr << _("Invalid snapshot.") << endl;
- exit(EXIT_FAILURE);
- }
- catch (const InvalidUserdataException& e)
- {
- cerr << _("Invalid userdata.") << endl;
- exit(EXIT_FAILURE);
- }
-}
-
-
-void
-help_delete()
-{
- cout << _(" Delete snapshot:") << endl
- << _("\tsnapper delete <number>") << endl
- << endl;
-}
-
-
-void
-command_delete()
-{
- getopts.parse("delete", GetOpts::no_options);
- if (!getopts.hasArgs())
- {
- cerr << _("Command 'delete' needs at least one argument.") << endl;
- exit(EXIT_FAILURE);
- }
-
- try
- {
- while (getopts.hasArgs())
- {
- Snapshots::iterator snapshot = read_num(getopts.popArg());
-
- sh->deleteSnapshot(snapshot);
- }
- }
- catch (const IllegalSnapshotException& e)
- {
- cerr << _("Invalid snapshot.") << endl;
- exit(EXIT_FAILURE);
- }
-}
-
-
-void
-help_mount()
-{
- cout << _(" Mount snapshot:") << endl
- << _("\tsnapper mount <number>") << endl
- << endl;
-}
-
-
-void
-command_mount()
-{
- getopts.parse("mount", GetOpts::no_options);
- if (!getopts.hasArgs())
- {
- cerr << _("Command 'mount' needs at least one argument.") << endl;
- exit(EXIT_FAILURE);
- }
-
- try
- {
- while (getopts.hasArgs())
- {
- Snapshots::iterator snapshot = read_num(getopts.popArg());
-
- snapshot->mountFilesystemSnapshot();
- }
- }
- catch (const IllegalSnapshotException& e)
- {
- cerr << _("Invalid snapshot.") << endl;
- exit(EXIT_FAILURE);
- }
-}
-
-
-void
-help_umount()
-{
- cout << _(" Umount snapshot:") << endl
- << _("\tsnapper umount <number>") << endl
- << endl;
-}
-
-
-void
-command_umount()
-{
- getopts.parse("mount", GetOpts::no_options);
- if (!getopts.hasArgs())
- {
- cerr << _("Command 'mount' needs at least one argument.") << endl;
- exit(EXIT_FAILURE);
- }
-
- try
- {
- while (getopts.hasArgs())
- {
- Snapshots::iterator snapshot = read_num(getopts.popArg());
-
- snapshot->umountFilesystemSnapshot();
- }
- }
- catch (const IllegalSnapshotException& e)
- {
- cerr << _("Invalid snapshot.") << endl;
- exit(EXIT_FAILURE);
- }
-}
-
-
-void
-help_status()
-{
- cout << _(" Comparing snapshots:") << endl
- << _("\tsnapper status <number1>..<number2>") << endl
- << endl
- << _(" Options for 'status' command:") << endl
- << _("\t--output, -o <file>\t\tSave status to file.") << endl
- << endl;
-}
-
-
-void
-command_status()
-{
- const struct option options[] = {
- { "output", required_argument, 0, 'o' },
- { 0, 0, 0, 0 }
- };
-
- GetOpts::parsed_opts opts = getopts.parse("status", options);
- if (getopts.numArgs() != 1)
- {
- cerr << _("Command 'status' needs one argument.") << endl;
- exit(EXIT_FAILURE);
- }
-
- GetOpts::parsed_opts::const_iterator opt;
-
- pair<Snapshots::const_iterator, Snapshots::const_iterator> snaps(read_nums(getopts.popArg()));
-
- Comparison comparison(sh, snaps.first, snaps.second);
-
- const Files& files = comparison.getFiles();
-
- FILE* file = stdout;
-
- if ((opt = opts.find("output")) != opts.end())
- {
- file = fopen(opt->second.c_str(), "w");
- if (!file)
- {
- cerr << sformat(_("Opening file '%s' failed."), opt->second.c_str()) << endl;
- exit(EXIT_FAILURE);
- }
- }
-
- for (Files::const_iterator it = files.begin(); it != files.end(); ++it)
- fprintf(file, "%s %s\n", statusToString(it->getPreToPostStatus()).c_str(),
- it->getAbsolutePath(LOC_SYSTEM).c_str());
-
- if (file != stdout)
- fclose(file);
-}
-
-
-void
-help_diff()
-{
- cout << _(" Comparing snapshots:") << endl
- << _("\tsnapper diff <number1>..<number2> [files]") << endl
- << endl;
-}
-
-
-void
-command_diff()
-{
- GetOpts::parsed_opts opts = getopts.parse("diff", GetOpts::no_options);
-
- GetOpts::parsed_opts::const_iterator opt;
-
- pair<Snapshots::const_iterator, Snapshots::const_iterator> snaps(read_nums(getopts.popArg()));
-
- Comparison comparison(sh, snaps.first, snaps.second);
-
- const Files& files = comparison.getFiles();
-
- if (getopts.numArgs() == 0)
- {
- for (Files::const_iterator it1 = files.begin(); it1 != files.end(); ++it1)
- {
- vector<string> lines = it1->getDiff("--unified --new-file");
- for (vector<string>::const_iterator it2 = lines.begin(); it2 != lines.end(); ++it2)
- cout << it2->c_str() << endl;
- }
- }
- else
- {
- while (getopts.numArgs() > 0)
- {
- string name = getopts.popArg();
-
- Files::const_iterator tmp = files.findAbsolutePath(name);
- if (tmp == files.end())
- continue;
-
- vector<string> lines = tmp->getDiff("--unified --new-file");
- for (vector<string>::const_iterator it2 = lines.begin(); it2 != lines.end(); ++it2)
- cout << it2->c_str() << endl;
- }
- }
-}
-
-
-void
-help_undo()
-{
- cout << _(" Undo changes:") << endl
- << _("\tsnapper undochange <number1>..<number2> [files]") << endl
- << endl
- << _(" Options for 'undochange' command:") << endl
- << _("\t--input, -i <file>\t\tRead files for which to undo changes from file.") << endl
- << endl;
-}
-
-
-void
-command_undo()
-{
- const struct option options[] = {
- { "input", required_argument, 0, 'i' },
- { 0, 0, 0, 0 }
- };
-
- GetOpts::parsed_opts opts = getopts.parse("undochange", options);
- if (getopts.numArgs() < 1)
- {
- cerr << _("Command 'undochange' needs at least one argument.") << endl;
- exit(EXIT_FAILURE);
- }
-
- pair<Snapshots::const_iterator, Snapshots::const_iterator> snaps(read_nums(getopts.popArg()));
-
- FILE* file = NULL;
-
- GetOpts::parsed_opts::const_iterator opt;
-
- if ((opt = opts.find("input")) != opts.end())
- {
- file = fopen(opt->second.c_str(), "r");
- if (!file)
- {
- cerr << sformat(_("Opening file '%s' failed."), opt->second.c_str()) << endl;
- exit(EXIT_FAILURE);
- }
- }
-
- if (snaps.first->isCurrent())
- {
- cerr << _("Invalid snapshots.") << endl;
- exit(EXIT_FAILURE);
- }
-
- Comparison comparison(sh, snaps.first, snaps.second);
-
- Files& files = comparison.getFiles();
-
- if (file)
- {
- AsciiFileReader asciifile(file);
-
- string line;
- while (asciifile.getline(line))
- {
- if (line.empty())
- continue;
-
- string name = line;
-
- // strip optional status
- if (name[0] != '/')
- {
- string::size_type pos = name.find(" ");
- if (pos == string::npos)
- continue;
-
- name.erase(0, pos + 1);
- }
-
- Files::iterator it = files.findAbsolutePath(name);
- if (it == files.end())
- {
- cerr << sformat(_("File '%s' not found."), name.c_str()) << endl;
- exit(EXIT_FAILURE);
- }
-
- it->setUndo(true);
- }
- }
- else
- {
- if (getopts.numArgs() == 0)
- {
- for (Files::iterator it = files.begin(); it != files.end(); ++it)
- it->setUndo(true);
- }
- else
- {
- while (getopts.numArgs() > 0)
- {
- string name = getopts.popArg();
-
- Files::iterator tmp = files.findAbsolutePath(name);
- if (tmp == files.end())
- continue;
-
- tmp->setUndo(true);
- }
- }
- }
-
- UndoStatistic rs = comparison.getUndoStatistic();
-
- if (rs.empty())
- {
- cout << "nothing to do" << endl;
- return;
- }
-
- cout << "create:" << rs.numCreate << " modify:" << rs.numModify << " delete:" << rs.numDelete
- << endl;
-
- comparison.doUndo();
-}
-
-
-void
-help_cleanup()
-{
- cout << _(" Cleanup snapshots:") << endl
- << _("\tsnapper cleanup <cleanup-algorithm>") << endl
- << endl;
-}
-
-
-void
-command_cleanup()
-{
- const struct option options[] = {
- { 0, 0, 0, 0 }
- };
-
- GetOpts::parsed_opts opts = getopts.parse("cleanup", options);
- if (getopts.numArgs() != 1)
- {
- cerr << _("Command 'cleanup' needs one arguments.") << endl;
- exit(EXIT_FAILURE);
- }
-
- string cleanup = getopts.popArg();
-
- if (cleanup == "number")
- {
- sh->doCleanupNumber();
- }
- else if (cleanup == "timeline")
- {
- sh->doCleanupTimeline();
- }
- else if (cleanup == "empty-pre-post")
- {
- sh->doCleanupEmptyPrePost();
- }
- else
- {
- cerr << sformat(_("Unknown cleanup algorithm '%s'."), cleanup.c_str()) << endl;
- exit(EXIT_FAILURE);
- }
-}
-
-
-void
-command_help()
-{
- getopts.parse("help", GetOpts::no_options);
- if (getopts.hasArgs())
- {
- cerr << _("Command 'help' does not take arguments.") << endl;
- exit(EXIT_FAILURE);
- }
-
- cout << _("usage: snapper [--global-options] <command> [--command-options] [command-arguments]") << endl
- << endl;
-
- cout << _(" Global options:") << endl
- << _("\t--quiet, -q\t\t\tSuppress normal output.") << endl
- << _("\t--verbose, -v\t\t\tIncrease verbosity.") << endl
- << _("\t--table-style, -t <style>\tTable style (integer).") << endl
- << _("\t--config, -c <name>\t\tSet name of config to use.") << endl
- << _("\t--disable-filters\t\tDisable filters.") << endl
- << _("\t--version\t\t\tPrint version and exit.") << endl
- << endl;
-
- help_list_configs();
- help_create_config();
- help_delete_config();
- help_list();
- help_create();
- help_modify();
- help_delete();
- help_mount();
- help_umount();
- help_status();
- help_diff();
- help_undo();
- help_cleanup();
-}
-
-
-struct CompareCallbackImpl : public CompareCallback
-{
- void start() { cout << _("comparing snapshots...") << flush; }
- void stop() { cout << " " << _("done") << endl; }
-};
-
-CompareCallbackImpl compare_callback_impl;
-
-
-struct UndoCallbackImpl : public UndoCallback
-{
- void start() { cout << _("undoing change...") << endl; }
- void stop() { cout << _("undoing change done") << endl; }
-
- void createInfo(const string& name)
- { if (verbose) cout << sformat(_("creating %s"), name.c_str()) << endl; }
- void modifyInfo(const string& name)
- { if (verbose) cout << sformat(_("modifying %s"), name.c_str()) << endl; }
- void deleteInfo(const string& name)
- { if (verbose) cout << sformat(_("deleting %s"), name.c_str()) << endl; }
-
- void createError(const string& name)
- { cerr << sformat(_("failed to create %s"), name.c_str()) << endl; }
- void modifyError(const string& name)
- { cerr << sformat(_("failed to modify %s"), name.c_str()) << endl; }
- void deleteError(const string& name)
- { cerr << sformat(_("failed to delete %s"), name.c_str()) << endl; }
-};
-
-UndoCallbackImpl undo_callback_impl;
-
-
-int
-main(int argc, char** argv)
-{
- umask(0027);
-
- setlocale(LC_ALL, "");
-
- initDefaultLogger();
-
- cmds["list-configs"] = command_list_configs;
- cmds["create-config"] = command_create_config;
- cmds["delete-config"] = command_delete_config;
- cmds["list"] = command_list;
- cmds["create"] = command_create;
- cmds["modify"] = command_modify;
- cmds["delete"] = command_delete;
- cmds["mount"] = command_mount;
- cmds["umount"] = command_umount;
- cmds["status"] = command_status;
- cmds["diff"] = command_diff;
- cmds["undochange"] = command_undo;
- cmds["cleanup"] = command_cleanup;
- cmds["help"] = command_help;
-
- const struct option options[] = {
- { "quiet", no_argument, 0, 'q' },
- { "verbose", no_argument, 0, 'v' },
- { "table-style", required_argument, 0, 't' },
- { "config", required_argument, 0, 'c' },
- { "disable-filters", no_argument, 0, 0 },
- { "version", no_argument, 0, 0 },
- { "help", no_argument, 0, 0 },
- { 0, 0, 0, 0 }
- };
-
- getopts.init(argc, argv);
-
- GetOpts::parsed_opts opts = getopts.parse(options);
-
- GetOpts::parsed_opts::const_iterator opt;
-
- if ((opt = opts.find("quiet")) != opts.end())
- quiet = true;
-
- if ((opt = opts.find("verbose")) != opts.end())
- verbose = true;
-
- if ((opt = opts.find("table-style")) != opts.end())
- {
- unsigned int s;
- opt->second >> s;
- if (s >= _End)
- {
- cerr << sformat(_("Invalid table style %d."), s) << " "
- << sformat(_("Use an integer number from %d to %d"), 0, _End - 1) << endl;
- exit(EXIT_FAILURE);
- }
- Table::defaultStyle = (TableLineStyle) s;
- }
-
- if ((opt = opts.find("config")) != opts.end())
- config_name = opt->second;
-
- if ((opt = opts.find("disable-filters")) != opts.end())
- disable_filters = true;
-
- if ((opt = opts.find("version")) != opts.end())
- {
- cout << "snapper " << VERSION << endl;
- exit(EXIT_SUCCESS);
- }
-
- if ((opt = opts.find("help")) != opts.end())
- {
- command_help();
- exit(EXIT_SUCCESS);
- }
-
- if (!getopts.hasArgs())
- {
- cerr << _("No command provided.") << endl
- << _("Try 'snapper help' for more information.") << endl;
- exit(EXIT_FAILURE);
- }
-
- const char* command = getopts.popArg();
- map<string, cmd_fnc>::const_iterator cmd = cmds.find(command);
- if (cmd == cmds.end())
- {
- cerr << sformat(_("Unknown command '%s'."), command) << endl
- << _("Try 'snapper help' for more information.") << endl;
- exit(EXIT_FAILURE);
- }
-
- if (cmd->first == "help" || cmd->first == "list-configs" ||
- cmd->first == "create-config" || cmd->first == "delete-config")
- {
- (*cmd->second)();
- }
- else
- {
- try
- {
- sh = createSnapper(config_name, disable_filters);
- }
- catch (const ConfigNotFoundException& e)
- {
- cerr << sformat(_("Config '%s' not found."), config_name.c_str()) << endl;
- exit(EXIT_FAILURE);
- }
- catch (const InvalidConfigException& e)
- {
- cerr << sformat(_("Config '%s' is invalid."), config_name.c_str()) << endl;
- exit(EXIT_FAILURE);
- }
-
- if (!quiet)
- {
- sh->setCompareCallback(&compare_callback_impl);
- sh->setUndoCallback(&undo_callback_impl);
- }
-
- try
- {
- (*cmd->second)();
- }
- catch (const SnapperException& e)
- {
- y2err("caught final exception");
- cerr << sformat(_("Command failed (%s). See log for more information."),
- e.what()) << endl;
- exit(EXIT_FAILURE);
- }
-
- deleteSnapper(sh);
- }
-
- exit(EXIT_SUCCESS);
-}