]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
- work on dbus interface
authorArvin Schnell <aschnell@suse.de>
Fri, 27 Apr 2012 10:08:18 +0000 (12:08 +0200)
committerArvin Schnell <aschnell@suse.de>
Fri, 27 Apr 2012 10:08:18 +0000 (12:08 +0200)
28 files changed:
client/Makefile.am
client/commands.cc
client/commands.h
client/snapper.cc
client/types.cc
client/types.h
client/utils/.gitignore [moved from tools/utils/.gitignore with 100% similarity]
client/utils/GetOpts.cc [moved from tools/utils/GetOpts.cc with 100% similarity]
client/utils/GetOpts.h [moved from tools/utils/GetOpts.h with 100% similarity]
client/utils/Makefile.am [moved from tools/utils/Makefile.am with 82% similarity]
client/utils/Table.cc [moved from tools/utils/Table.cc with 100% similarity]
client/utils/Table.h [moved from tools/utils/Table.h with 100% similarity]
client/utils/console.cc [moved from tools/utils/console.cc with 100% similarity]
client/utils/console.h [moved from tools/utils/console.h with 100% similarity]
client/utils/text.cc [moved from tools/utils/text.cc with 100% similarity]
client/utils/text.h [moved from tools/utils/text.h with 100% similarity]
configure.in
dbus/DBusConnection.cc
examples/python/create.py
examples/python/list.py
scripts/zypp-plugin.py
server/Client.cc
server/Client.h
server/Types.cc
server/snapperd.cc
tools/.gitignore
tools/Makefile.am
tools/snapper.cc [deleted file]

index 8341a6f97d091305dbb6fdf7d77add0392312792..1ea75e60efe3932bb0bd55859122f14ccfe5e33c 100644 (file)
@@ -2,6 +2,8 @@
 # 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
 
 
@@ -12,5 +14,5 @@ snapper_SOURCES =                     \
        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
 
index e1a688ff57f1c31a3bf412a15017e865a46f748a..d08836a4dbe68371d1e7ee44b8e3ac424f15184d 100644 (file)
@@ -67,22 +67,120 @@ 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)
 {
     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;
+}
index dbb16cc876bb1dbd301064d77d099cea09b262f3..43d4a3728a3b8945c18565cfd37f3b9f6b271e1d 100644 (file)
 #include <dbus/dbus.h>
 
 #include <string>
+#include <vector>
 #include <list>
 #include <map>
 
 using std::string;
+using std::vector;
 using std::list;
 using std::map;
 
@@ -44,7 +46,29 @@ list<XSnapshot>
 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);
 
index a50e5cf40bb5890dc15af87d688a78a58c78b979..c15b02e8b5831f2668ab738b8da8d98b21436629 100644 (file)
 #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"
 
@@ -58,14 +53,10 @@ bool verbose = false;
 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;
@@ -76,18 +67,11 @@ read_num(const string& str)
        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("..");
@@ -97,16 +81,16 @@ read_nums(const string& str)
        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);
 }
 
 
@@ -228,7 +212,7 @@ help_create_config()
 
 
 void
-command_create_config()
+command_create_config(DBus::Connection& conn)
 {
     const struct option options[] = {
        { "fstype",             required_argument,      0,      'f' },
@@ -289,7 +273,7 @@ help_delete_config()
 
 
 void
-command_delete_config()
+command_delete_config(DBus::Connection& conn)
 {
     getopts.parse("delete-config", GetOpts::no_options);
     if (getopts.hasArgs())
@@ -323,7 +307,7 @@ help_list()
 
 
 void
-command_list()
+command_list(DBus::Connection& conn)
 {
     const struct option options[] = {
        { "type",               required_argument,      0,      't' },
@@ -373,17 +357,17 @@ command_list()
            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);
            }
        }
@@ -398,17 +382,17 @@ command_list()
            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);
            }
        }
@@ -425,23 +409,26 @@ command_list()
            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);
            }
        }
@@ -471,7 +458,7 @@ help_create()
 
 
 void
-command_create()
+command_create(DBus::Connection& conn)
 {
     const struct option options[] = {
        { "type",               required_argument,      0,      't' },
@@ -493,10 +480,8 @@ command_create()
 
     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;
@@ -523,7 +508,7 @@ command_create()
     }
 
     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;
@@ -543,7 +528,7 @@ command_create()
        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);
@@ -560,48 +545,34 @@ command_create()
        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;
        }
     }
@@ -628,7 +599,7 @@ help_modify()
 
 
 void
-command_modify()
+command_modify(DBus::Connection& conn)
 {
     const struct option options[] = {
        { "description",        required_argument,      0,      'd' },
@@ -649,7 +620,7 @@ command_modify()
     {
        while (getopts.hasArgs())
        {
-           Snapshots::iterator snapshot = read_num(getopts.popArg());
+           Snapshots::iterator snapshot; // = read_num(getopts.popArg());
 
            GetOpts::parsed_opts::const_iterator opt;
 
@@ -688,7 +659,7 @@ help_delete()
 
 
 void
-command_delete()
+command_delete(DBus::Connection& conn)
 {
     getopts.parse("delete", GetOpts::no_options);
     if (!getopts.hasArgs())
@@ -701,9 +672,9 @@ command_delete()
     {
        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)
@@ -724,7 +695,7 @@ help_mount()
 
 
 void
-command_mount()
+command_mount(DBus::Connection& conn)
 {
     getopts.parse("mount", GetOpts::no_options);
     if (!getopts.hasArgs())
@@ -737,7 +708,7 @@ command_mount()
     {
        while (getopts.hasArgs())
        {
-           Snapshots::iterator snapshot = read_num(getopts.popArg());
+           Snapshots::iterator snapshot; // = read_num(getopts.popArg());
 
            snapshot->mountFilesystemSnapshot();
        }
@@ -760,7 +731,7 @@ help_umount()
 
 
 void
-command_umount()
+command_umount(DBus::Connection& conn)
 {
     getopts.parse("mount", GetOpts::no_options);
     if (!getopts.hasArgs())
@@ -773,7 +744,7 @@ command_umount()
     {
        while (getopts.hasArgs())
        {
-           Snapshots::iterator snapshot = read_num(getopts.popArg());
+           Snapshots::iterator snapshot; // = read_num(getopts.popArg());
 
            snapshot->umountFilesystemSnapshot();
        }
@@ -799,7 +770,7 @@ help_status()
 
 
 void
-command_status()
+command_status(DBus::Connection& conn)
 {
     const struct option options[] = {
        { "output",             required_argument,      0,      'o' },
@@ -815,11 +786,11 @@ command_status()
 
     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;
 
@@ -833,9 +804,8 @@ command_status()
        }
     }
 
-    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);
@@ -852,25 +822,26 @@ help_diff()
 
 
 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
@@ -879,6 +850,7 @@ command_diff()
        {
            string name = getopts.popArg();
 
+           /*
            Files::const_iterator tmp = files.findAbsolutePath(name);
            if (tmp == files.end())
                continue;
@@ -886,6 +858,7 @@ command_diff()
            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;
+           */
        }
     }
 }
@@ -904,7 +877,7 @@ help_undo()
 
 
 void
-command_undo()
+command_undo(DBus::Connection& conn)
 {
     const struct option options[] = {
        { "input",              required_argument,      0,      'i' },
@@ -918,7 +891,7 @@ command_undo()
        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;
 
@@ -934,15 +907,15 @@ command_undo()
        }
     }
 
-    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)
     {
@@ -966,6 +939,7 @@ command_undo()
                name.erase(0, pos + 1);
            }
 
+           /*
            Files::iterator it = files.findAbsolutePath(name);
            if (it == files.end())
            {
@@ -974,14 +948,17 @@ command_undo()
            }
 
            it->setUndo(true);
+           */
        }
     }
     else
     {
        if (getopts.numArgs() == 0)
        {
+           /*
            for (Files::iterator it = files.begin(); it != files.end(); ++it)
                it->setUndo(true);
+           */
        }
        else
        {
@@ -989,15 +966,17 @@ command_undo()
            {
                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())
@@ -1010,6 +989,7 @@ command_undo()
         << endl;
 
     comparison.doUndo();
+    */
 }
 
 
@@ -1023,7 +1003,7 @@ help_cleanup()
 
 
 void
-command_cleanup()
+command_cleanup(DBus::Connection& conn)
 {
     const struct option options[] = {
        { 0, 0, 0, 0 }
@@ -1040,15 +1020,15 @@ command_cleanup()
 
     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
     {
@@ -1138,19 +1118,18 @@ main(int argc, char** argv)
     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' },
@@ -1222,49 +1201,15 @@ main(int argc, char** argv)
        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);
index 66f344088a52978094ee431ca3f148f1d6c6a232..2234db6f38675d7ccd2fd19c4b94f31039da4acc 100644 (file)
@@ -32,7 +32,7 @@
 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)";
     
@@ -61,7 +61,8 @@ namespace DBus
     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;
     }
@@ -95,4 +96,3 @@ namespace DBus
     }
     
 }
-
index 92f2497fd5755db8be52d220bb6921213a051247..9c821a2b82320e4512b806470ec945ccf679fe3e 100644 (file)
@@ -45,15 +45,17 @@ struct XConfigInfo
 };
 
 
-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;
 };
 
similarity index 100%
rename from tools/utils/GetOpts.h
rename to client/utils/GetOpts.h
similarity index 82%
rename from tools/utils/Makefile.am
rename to client/utils/Makefile.am
index 96ab5075aa9f090537ce53ca929403e2a6324c2f..2bba631746ebdb45d342af6988a8cf8aba909289 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Makefile.am for snapper/tools/utils
+# Makefile.am for snapper/client/utils
 #
 
 INCLUDES = -I$(top_srcdir)
similarity index 100%
rename from tools/utils/Table.cc
rename to client/utils/Table.cc
similarity index 100%
rename from tools/utils/Table.h
rename to client/utils/Table.h
similarity index 100%
rename from tools/utils/console.h
rename to client/utils/console.h
similarity index 100%
rename from tools/utils/text.cc
rename to client/utils/text.cc
similarity index 100%
rename from tools/utils/text.h
rename to client/utils/text.h
index e997df6f76b382989a72ce784ea13c68ecbd1232..cb1f6263a309fc475cfb557cc8879670bc077bc0 100644 (file)
@@ -54,10 +54,10 @@ AC_OUTPUT(
        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
index ed860fed129029625b1da7f03516694f4336736d..bcf4359aa8da1d34b1f0d1257496c837940355fc 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 
+#include <unistd.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <pwd.h>
index 9360dfc015ba3835fc783042ec197b5709dba1a6..36505950e833cef1fdcad4053c17bd76379f5438 100755 (executable)
@@ -8,5 +8,5 @@ snapper = dbus.Interface(bus.get_object('org.opensuse.snapper', '/org/opensuse/s
                          dbus_interface='org.opensuse.snapper')
 
 
-print snapper.CreateSnapshot("root", 0, 0, "test", "", { "tid" : "456" })
+print snapper.CreateSingleSnapshot("root", "test", "", { "id" : "123" })
 
index 71d9b12790a3c6e3c7a411ea129350dd95ed128c..eab9f54be1c6df2917b4895b766bd1942a26d7e9 100755 (executable)
@@ -11,8 +11,8 @@ snapper = dbus.Interface(bus.get_object('org.opensuse.snapper', '/org/opensuse/s
 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
 
index 19d7a5da54fd2f706c103775e53815f2ca8031a9..a663bfe6ab4cbfe6cfb8c22da666471c1d0ef003 100755 (executable)
@@ -2,7 +2,7 @@
 
 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):
@@ -11,19 +11,20 @@ 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()
index 8cd2e252476e7dadf8fc1a3c592272ddd43cf379..2ec50d8191551f7886bdc4589ba2bc9a4c30b5be 100644 (file)
@@ -57,7 +57,7 @@ Client::find_comparison(Snapper* snapper, Snapshots::const_iterator snapshot1,
            return *it;
     }
 
-    return NULL;
+    throw NoComparison();
 }
 
 
index 73e904a226d84de3fc6c6cac2965a99dc6329ddc..b1ba3dfb6b02c76fc7ffe9dbf194bf3ede873d7d 100644 (file)
@@ -38,6 +38,13 @@ using namespace std;
 using namespace snapper;
 
 
+struct NoComparison : public std::exception
+{
+    explicit NoComparison() throw() {}
+    virtual const char* what() const throw() { return "no comparison"; }
+};
+
+
 class Client
 {
 public:
index 798b4e6cf1e8a7ef673b75ae30e505b86ab6ff95..e5be7bfeab6e246ba272020915e976282642c385 100644 (file)
@@ -26,7 +26,7 @@
 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)";
 
@@ -63,7 +63,7 @@ namespace DBus
     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;
index 6db57da7bf7717bde457fe956ba4cb34fb53dc8b..36042ac6e6925460ec33aab887c0b32f2e7b5934 100644 (file)
@@ -27,7 +27,6 @@
 #include <dbus/dbus.h>
 
 #include <string>
-#include <iostream>
 #include <boost/algorithm/string.hpp>
 
 #include <snapper/Snapper.h>
@@ -92,9 +91,24 @@ reply_to_introspect(DBus::Connection& conn, DBus::Message& msg)
        "      <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"
@@ -218,8 +232,6 @@ void
 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);
@@ -231,14 +243,12 @@ send_signal_config_created(DBus::Connection& conn, const string& config_name,
 
 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);
 }
@@ -246,14 +256,12 @@ send_signal_snapshot_created(DBus::Connection& conn, const string& config_name,
 
 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);
 }
@@ -262,8 +270,6 @@ send_signal_snapshot_deleted(DBus::Connection& conn, const string& config_name,
 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);
@@ -278,16 +284,16 @@ reply_to_command_list_configs(DBus::Connection& conn, DBus::Message& 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);
@@ -299,14 +305,12 @@ reply_to_command_create_config(DBus::Connection& conn, DBus::Message& msg)
 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);
 
@@ -323,14 +327,12 @@ reply_to_command_lock_config(DBus::Connection& conn, DBus::Message& msg)
 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);
 
@@ -347,14 +349,12 @@ reply_to_command_unlock_config(DBus::Connection& conn, DBus::Message& msg)
 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);
 
@@ -370,21 +370,18 @@ reply_to_command_list_snapshots(DBus::Connection& conn, DBus::Message& msg)
 
 
 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);
 
@@ -392,7 +389,6 @@ reply_to_command_create_snapshot(DBus::Connection& conn, DBus::Message& msg)
 
     Snapper* snapper = getSnapper(config_name);
 
-    // TODO type
     Snapshots::iterator snap1 = snapper->createSingleSnapshot(description);
     snap1->setCleanup(cleanup);
     snap1->setUserdata(userdata);
@@ -408,17 +404,95 @@ reply_to_command_create_snapshot(DBus::Connection& conn, DBus::Message& msg)
 
 
 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);
@@ -431,7 +505,7 @@ reply_to_command_delete_snapshot(DBus::Connection& conn, DBus::Message& msg)
 
     conn.send(reply);
 
-    send_signal_snapshot_deleted(conn, config_name, number);
+    send_signal_snapshot_deleted(conn, config_name, num);
 }
 
 
@@ -454,22 +528,21 @@ protected:
 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
@@ -501,15 +574,7 @@ Comparing::operator()()
 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;
@@ -519,15 +584,14 @@ Comparing::done()
 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);
 
@@ -538,13 +602,8 @@ reply_to_command_get_files(DBus::Connection& conn, DBus::Message& msg)
     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);
@@ -557,18 +616,17 @@ reply_to_command_get_files(DBus::Connection& conn, DBus::Message& msg)
 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();
 
@@ -577,12 +635,7 @@ reply_to_command_set_undo(DBus::Connection& conn, DBus::Message& msg)
     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();
 
@@ -600,17 +653,16 @@ reply_to_command_set_undo(DBus::Connection& conn, DBus::Message& msg)
 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);
 
@@ -619,12 +671,7 @@ reply_to_command_get_diff(DBus::Connection& conn, DBus::Message& msg)
     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();
 
@@ -644,8 +691,6 @@ reply_to_command_get_diff(DBus::Connection& conn, DBus::Message& msg)
 void
 reply_to_command_debug(DBus::Connection& conn, DBus::Message& msg)
 {
-    cout << "command Debug" << endl;
-
     // check_permission(conn, msg);
 
     DBus::MessageMethodReturn reply(msg);
@@ -721,8 +766,12 @@ dispatch(DBus::Connection& conn, DBus::Message& 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"))
@@ -734,19 +783,29 @@ dispatch(DBus::Connection& conn, DBus::Message& msg)
        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);
     }
 }
index 311988651f6307147ffb07a54599b78d11e7bd3f..bbbb2da8c4cf4b388aecc1972bc803786caab281 100644 (file)
@@ -1,4 +1,2 @@
 compare-dirs.o
 compare-dirs
-snapper.o
-snapper
index 0db42e8edb4860f2510c9e6a497433c8c65eb4be..3950e46b50aea2bca54b2705ff2f7b22a005096e 100644 (file)
@@ -2,8 +2,6 @@
 # Makefile.am for snapper/tools
 #
 
-SUBDIRS = utils
-
 INCLUDES = -I$(top_srcdir)
 
 
@@ -14,9 +12,3 @@ toolsbin_PROGRAMS = compare-dirs
 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
-
diff --git a/tools/snapper.cc b/tools/snapper.cc
deleted file mode 100644 (file)
index 47a275f..0000000
+++ /dev/null
@@ -1,1267 +0,0 @@
-/*
- * 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);
-}