DBus::Hoho hoho(call);
hoho << config_name << subvolume << fstype << template_name;
- DBus::Message reply = conn.send_and_reply_and_block(call);
+ conn.send_and_reply_and_block(call);
}
DBus::Hoho hoho(call);
hoho << config_name;
- DBus::Message reply = conn.send_and_reply_and_block(call);
+ conn.send_and_reply_and_block(call);
}
DBus::Hoho hoho(call);
hoho << config_name << num << data.description << data.cleanup << data.userdata;
- DBus::Message reply = conn.send_and_reply_and_block(call);
+ conn.send_and_reply_and_block(call);
}
DBus::Hoho hoho(call);
hoho << config_name << nums;
- DBus::Message reply = conn.send_and_reply_and_block(call);
+ conn.send_and_reply_and_block(call);
}
DBus::Hoho hoho(call);
hoho << config_name << num;
- DBus::Message reply = conn.send_and_reply_and_block(call);
+ conn.send_and_reply_and_block(call);
}
DBus::Hoho hoho(call);
hoho << config_name << num;
- DBus::Message reply = conn.send_and_reply_and_block(call);
+ conn.send_and_reply_and_block(call);
}
DBus::Hoho hoho(call);
hoho << config_name << number1 << number2;
- DBus::Message reply = conn.send_and_reply_and_block(call);
+ conn.send_and_reply_and_block(call);
}
DBus::Hoho hoho(call);
hoho << config_name << number1 << number2 << undos;
- DBus::Message reply = conn.send_and_reply_and_block(call);
+ conn.send_and_reply_and_block(call);
}
DBus::Hoho hoho(call);
hoho << config_name << number1 << number2 << undo;
- DBus::Message reply = conn.send_and_reply_and_block(call);
+ conn.send_and_reply_and_block(call);
}
-XUndoStatistic
-command_get_xundostatistic(DBus::Connection& conn, const string& config_name, unsigned int number1,
- unsigned int number2)
+vector<XUndoStep>
+command_get_xundo_steps(DBus::Connection& conn, const string& config_name, unsigned int number1,
+ unsigned int number2)
{
- DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "GetUndoStatistic");
+ DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "GetUndoSteps");
DBus::Hoho hoho(call);
hoho << config_name << number1 << number2;
DBus::Message reply = conn.send_and_reply_and_block(call);
- XUndoStatistic ret;
+ vector<XUndoStep> undo_steps;
DBus::Hihi hihi(reply);
- hihi >> ret.numCreate >> ret.numModify >> ret.numDelete;
+ hihi >> undo_steps;
- return ret;
+ return undo_steps;
}
-void
-command_xundo_changes(DBus::Connection& conn, const string& config_name, unsigned int number1,
- unsigned int number2)
+bool
+command_do_xundo_step(DBus::Connection& conn, const string& config_name, unsigned int number1,
+ unsigned int number2, const XUndoStep& undo_step)
{
- DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "UndoChanges");
+ DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "DoUndoStep");
DBus::Hoho hoho(call);
- hoho << config_name << number1 << number2;
+ hoho << config_name << number1 << number2 << undo_step;
DBus::Message reply = conn.send_and_reply_and_block(call);
+
+ bool ret;
+
+ DBus::Hihi hihi(reply);
+ hihi >> ret;
+
+ return ret;
}
command_set_xundo_all(DBus::Connection& conn, const string& config_name, unsigned int number1,
unsigned int number2, bool undo);
-XUndoStatistic
-command_get_xundostatistic(DBus::Connection& conn, const string& config_name, unsigned int number1,
- unsigned int number2);
+vector<XUndoStep>
+command_get_xundo_steps(DBus::Connection& conn, const string& config_name, unsigned int number1,
+ unsigned int number2);
-void
-command_xundo_changes(DBus::Connection& conn, const string& config_name, unsigned int number1,
- unsigned int number2);
+bool
+command_do_xundo_step(DBus::Connection& conn, const string& config_name, unsigned int number1,
+ unsigned int number2, const XUndoStep& undo_step);
}
}
- XUndoStatistic s = command_get_xundostatistic(conn, config_name, nums.first, nums.second);
+ vector<XUndoStep> undo_steps = command_get_xundo_steps(conn, config_name, nums.first, nums.second);
- if (s.empty())
+ int numCreate = 0;
+ int numModify = 0;
+ int numDelete = 0;
+
+ for (vector<XUndoStep>::const_iterator it = undo_steps.begin(); it != undo_steps.end(); ++it)
+ {
+ switch (it->action)
+ {
+ case CREATE: numCreate++; break;
+ case MODIFY: numModify++; break;
+ case DELETE: numDelete++; break;
+ }
+ }
+
+ if (numCreate == 0 && numModify == 0 && numDelete == 0)
{
cout << _("nothing to do") << endl;
return;
}
- cout << sformat(_("create:%d modify:%d delete:%d"), s.numCreate, s.numModify, s.numDelete) << endl;
+ cout << sformat(_("create:%d modify:%d delete:%d"), numCreate, numModify, numDelete) << endl;
+
+ XConfigInfo ci = command_get_xconfig(conn, config_name);
- command_xundo_changes(conn, config_name, nums.first, nums.second);
+ for (vector<XUndoStep>::const_iterator it = undo_steps.begin(); it != undo_steps.end(); ++it)
+ {
+ if (verbose)
+ {
+ switch (it->action)
+ {
+ case CREATE:
+ cout << sformat(_("creating %s"), add_subvolume(ci.subvolume, it->name).c_str()) << endl;
+ break;
+ case MODIFY:
+ cout << sformat(_("modifying %s"), add_subvolume(ci.subvolume, it->name).c_str()) << endl;
+ break;
+ case DELETE:
+ cout << sformat(_("deleting %s"), add_subvolume(ci.subvolume, it->name).c_str()) << endl;
+ break;
+ }
+ }
+
+ if (!command_do_xundo_step(conn, config_name, nums.first, nums.second, *it))
+ {
+ switch (it->action)
+ {
+ case CREATE:
+ cout << sformat(_("failed to create %s"), add_subvolume(ci.subvolume, it->name).c_str()) << endl;
+ break;
+ case MODIFY:
+ cout << sformat(_("failed to modify %s"), add_subvolume(ci.subvolume, it->name).c_str()) << endl;
+ break;
+ case DELETE:
+ cout << sformat(_("failed to delete %s"), add_subvolume(ci.subvolume, it->name).c_str()) << endl;
+ break;
+ }
+ }
+ }
}
}
-bool
-XUndoStatistic::empty() const
-{
- return numCreate == 0 && numModify == 0 && numDelete == 0;
-}
-
-
namespace DBus
{
const char* TypeInfo<XConfigInfo>::signature = "(ssa{ss})";
const char* TypeInfo<XSnapshot>::signature = "(uquussa{ss})";
const char* TypeInfo<XFile>::signature = "(ssb)";
const char* TypeInfo<XUndo>::signature = "(sb)";
+ const char* TypeInfo<XUndoStep>::signature = "(sq)";
Hihi&
return hoho;
}
+
+ Hihi&
+ operator>>(Hihi& hihi, XUndoStep& data)
+ {
+ hihi.open_recurse();
+ dbus_uint16_t tmp;
+ hihi >> data.name >> tmp;
+ data.action = static_cast<Action>(tmp);
+ hihi.close_recurse();
+ return hihi;
+ }
+
+
+ Hoho&
+ operator<<(Hoho& hoho, const XUndoStep& data)
+ {
+ hoho.open_struct();
+ hoho << data.name << static_cast<dbus_uint16_t>(data.action);
+ hoho.close_struct();
+ return hoho;
+ }
}
#include "dbus/DBusConnection.h"
#include "dbus/DBusMessage.h"
#include "snapper/Snapshot.h"
+#include "snapper/File.h"
using namespace snapper;
};
-struct XUndoStatistic
+struct XUndoStep
{
- bool empty() const;
-
- unsigned int numCreate;
- unsigned int numModify;
- unsigned int numDelete;
+ string name;
+ Action action;
};
template <> struct TypeInfo<XConfigInfo> { static const char* signature; };
template <> struct TypeInfo<XFile> { static const char* signature; };
template <> struct TypeInfo<XUndo> { static const char* signature; };
+ template <> struct TypeInfo<XUndoStep> { static const char* signature; };
Hihi& operator>>(Hihi& hihi, XConfigInfo& data);
Hoho& operator<<(Hoho& hoho, const XUndo& data);
+ Hihi& operator>>(Hihi& hihi, XUndoStep& data);
+ Hoho& operator<<(Hoho& hoho, const XUndoStep& data);
+
};
const char* TypeInfo<Snapshot>::signature = "(uquussa{ss})";
const char* TypeInfo<File>::signature = "(ssb)";
const char* TypeInfo<Undo>::signature = "(sb)";
+ const char* TypeInfo<UndoStep>::signature = "(sq)";
Hoho&
return hoho;
}
+
+ Hihi&
+ operator>>(Hihi& hihi, UndoStep& data)
+ {
+ hihi.open_recurse();
+ dbus_uint16_t tmp;
+ hihi >> data.name >> tmp;
+ data.action = static_cast<Action>(tmp);
+ hihi.close_recurse();
+ return hihi;
+ }
+
+
+ Hoho&
+ operator<<(Hoho& hoho, const UndoStep& data)
+ {
+ hoho.open_struct();
+ hoho << data.name << static_cast<dbus_uint16_t>(data.action);
+ hoho.close_struct();
+ return hoho;
+ }
+
}
template <> struct TypeInfo<Snapshot> { static const char* signature; };
template <> struct TypeInfo<File> { static const char* signature; };
template <> struct TypeInfo<Undo> { static const char* signature; };
+ template <> struct TypeInfo<UndoStep> { static const char* signature; };
Hoho& operator<<(Hoho& hoho, const ConfigInfo& data);
Hihi& operator>>(Hihi& hihi, Undo& data);
Hoho& operator<<(Hoho& hoho, const Undo& data);
+ Hihi& operator>>(Hihi& hihi, UndoStep& data);
+ Hoho& operator<<(Hoho& hoho, const UndoStep& data);
+
};
" <arg name='undo' type='b' direction='in'/>\n"
" </method>\n"
- " <method name='GetUndoStatistic'>\n"
+ " <method name='GetUndoSteps'>\n"
" <arg name='config-name' type='s' direction='in'/>\n"
" <arg name='number1' type='u' direction='in'/>\n"
" <arg name='number2' type='u' direction='in'/>\n"
- " <arg name='number-create' type='u' direction='out'/>\n"
- " <arg name='number-modify' type='u' direction='out'/>\n"
- " <arg name='number-delete' type='u' direction='out'/>\n"
+ " <arg name='undo-steps' type='a(sq)' direction='out'/>\n"
" </method>\n"
- " <method name='UndoChanges'>\n"
+ " <method name='DoUndoStep'>\n"
" <arg name='config-name' type='s' direction='in'/>\n"
" <arg name='number1' type='u' direction='in'/>\n"
" <arg name='number2' type='u' direction='in'/>\n"
+ " <arg name='undo-step' type='(sq)' direction='in'/>\n"
" </method>\n"
" </interface>\n"
struct Comparing : public Job
{
+ Comparing(Comparison* comparison)
+ : comparison(comparison) {}
+
DBus::Connection* conn;
DBus::MessageMethodReturn* reply;
assert(it != clients.end());
it->comparisons.push_back(comparison);
- Comparing* job = new Comparing;
+ Comparing* job = new Comparing(comparison);
job->conn = &conn;
job->reply = new DBus::MessageMethodReturn(msg);
- job->comparison = comparison;
jobs.add(job);
}
void
Comparing::done()
{
- DBus::Hoho hoho(*reply);
conn->send(*reply);
delete reply;
void
-reply_to_command_get_undo_statistics(DBus::Connection& conn, DBus::Message& msg)
+reply_to_command_get_undo_steps(DBus::Connection& conn, DBus::Message& msg)
{
string config_name;
dbus_uint32_t num1, num2;
DBus::Hihi hihi(msg);
hihi >> config_name >> num1 >> num2;
- y2mil("GetUndoStatistic config_name:" << config_name << " num1:" << num1 << " num2:" <<
+ y2mil("GetUndoSteps config_name:" << config_name << " num1:" << num1 << " num2:" <<
num2);
check_permission(conn, msg, config_name);
Comparison* comparison = it->find_comparison(config_name, num1, num2);
- UndoStatistic statistic = comparison->getUndoStatistic();
+ vector<UndoStep> undo_steps = comparison->getUndoSteps();
DBus::MessageMethodReturn reply(msg);
DBus::Hoho hoho(reply);
- hoho << statistic.numCreate << statistic.numModify << statistic.numDelete;
+ hoho << undo_steps;
conn.send(reply);
}
struct Undoing : public Job
{
+ Undoing(Comparison* comparison, const UndoStep& undo_step)
+ : comparison(comparison), undo_step(undo_step) {}
+
DBus::Connection* conn;
DBus::MessageMethodReturn* reply;
Comparison* comparison;
+ UndoStep undo_step;
void done();
void
-reply_to_command_undo_changes(DBus::Connection& conn, DBus::Message& msg)
+reply_to_command_do_undo_step(DBus::Connection& conn, DBus::Message& msg)
{
string config_name;
dbus_uint32_t num1, num2;
+ UndoStep undo_step("", MODIFY);
DBus::Hihi hihi(msg);
- hihi >> config_name >> num1 >> num2;
+ hihi >> config_name >> num1 >> num2 >> undo_step;
- y2mil("UndoChanges config_name:" << config_name << " num1:" << num1 << " num2:" <<
+ y2mil("GetUndoSteps config_name:" << config_name << " num1:" << num1 << " num2:" <<
num2);
check_permission(conn, msg, config_name);
Comparison* comparison = it->find_comparison(config_name, num1, num2);
- Undoing* job = new Undoing;
+ Undoing* job = new Undoing(comparison, undo_step);
job->conn = &conn;
job->reply = new DBus::MessageMethodReturn(msg);
- job->comparison = comparison;
jobs.add(job);
}
{
boost::this_thread::sleep(seconds(2));
- comparison->doUndo();
+ bool ret = comparison->doUndoStep(undo_step);
+
+ DBus::Hoho hoho(*reply);
+ hoho << ret;
boost::this_thread::sleep(seconds(2));
}
void
Undoing::done()
{
- DBus::Hoho hoho(*reply);
conn->send(*reply);
delete reply;
reply_to_command_set_undo(conn, msg);
else if (msg.is_method_call(INTERFACE, "SetUndoAll"))
reply_to_command_set_undo_all(conn, msg);
- else if (msg.is_method_call(INTERFACE, "GetUndoStatistic"))
- reply_to_command_get_undo_statistics(conn, msg);
- else if (msg.is_method_call(INTERFACE, "UndoChanges"))
- reply_to_command_undo_changes(conn, msg);
+ else if (msg.is_method_call(INTERFACE, "GetUndoSteps"))
+ reply_to_command_get_undo_steps(conn, msg);
+ else if (msg.is_method_call(INTERFACE, "DoUndoStep"))
+ reply_to_command_do_undo_step(conn, msg);
else if (msg.is_method_call(INTERFACE, "Debug"))
reply_to_command_debug(conn, msg);
else
}
+ vector<UndoStep>
+ Comparison::getUndoSteps() const
+ {
+ if (!initialized)
+ throw;
+
+ return files.getUndoSteps();
+ }
+
+
+ bool
+ Comparison::doUndoStep(const UndoStep& undo_step)
+ {
+ if (!initialized)
+ throw;
+
+ return files.doUndoStep(undo_step);
+ }
+
+
bool
Comparison::doUndo()
{
UndoStatistic getUndoStatistic() const;
+ vector<UndoStep> getUndoSteps() const;
+
+ bool doUndoStep(const UndoStep& undo_step);
+
bool doUndo();
private:
}
- File::Action
+ Action
File::getAction() const
{
if (getPreToPostStatus() == CREATED)
{
switch (it->getAction())
{
- case File::CREATE: rs.numCreate++; break;
- case File::MODIFY: rs.numModify++; break;
- case File::DELETE: rs.numDelete++; break;
+ case CREATE: rs.numCreate++; break;
+ case MODIFY: rs.numModify++; break;
+ case DELETE: rs.numDelete++; break;
}
}
}
}
+ vector<UndoStep>
+ Files::getUndoSteps() const
+ {
+ if (comparison->getSnapshot1()->isCurrent())
+ throw IllegalSnapshotException();
+
+ vector<UndoStep> undo_steps;
+
+ for (vector<File>::const_reverse_iterator it = entries.rbegin(); it != entries.rend(); ++it)
+ {
+ if (it->getUndo())
+ {
+ if (it->getPreToPostStatus() == CREATED)
+ undo_steps.push_back(UndoStep(it->getName(), it->getAction()));
+ }
+ }
+
+ for (vector<File>::const_iterator it = entries.begin(); it != entries.end(); ++it)
+ {
+ if (it->getUndo())
+ {
+ if (it->getPreToPostStatus() != CREATED)
+ undo_steps.push_back(UndoStep(it->getName(), it->getAction()));
+ }
+ }
+
+ return undo_steps;
+ }
+
+
+ bool
+ Files::doUndoStep(const UndoStep& undo_step)
+ {
+ if (comparison->getSnapshot1()->isCurrent())
+ throw IllegalSnapshotException();
+
+ vector<File>::iterator it = find(undo_step.name);
+ if (it == end())
+ return false;
+
+ return it->doUndo();
+ }
+
+
bool
Files::doUndo()
{
if (it->getUndo())
{
if (it->getPreToPostStatus() == CREATED)
- {
it->doUndo();
- }
}
}
if (it->getUndo())
{
if (it->getPreToPostStatus() != CREATED)
- {
it->doUndo();
- }
}
}
LOC_PRE, LOC_POST, LOC_SYSTEM
};
+ enum Action
+ {
+ CREATE, MODIFY, DELETE
+ };
+
struct UndoStatistic
{
};
+ struct UndoStep
+ {
+ UndoStep(const string& name, Action action)
+ : name(name), action(action) {}
+
+ string name;
+ Action action;
+ };
+
+
class File
{
public:
void setUndo(bool value) { undo = value; }
bool doUndo();
- enum Action { CREATE, MODIFY, DELETE };
-
Action getAction() const;
friend std::ostream& operator<<(std::ostream& s, const File& file);
UndoStatistic getUndoStatistic() const;
+ vector<UndoStep> getUndoSteps() const;
+
+ bool doUndoStep(const UndoStep& undo_step);
+
bool doUndo();
const Comparison* comparison;