}
-vector<string>
-command_get_xdiff(DBus::Connection& conn, const string& config_name, unsigned int number1,
- unsigned int number2, const string& name, const string& options)
-{
- DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "GetDiff");
-
- DBus::Hoho hoho(call);
- hoho << config_name << number1 << number2 << name << options;
-
- DBus::Message reply = conn.send_with_reply_and_block(call);
-
- vector<string> files;
-
- DBus::Hihi hihi(reply);
- hihi >> files;
-
- return files;
-}
-
-
-void
-command_set_xundo(DBus::Connection& conn, const string& config_name, unsigned int number1,
- unsigned int number2, const list<XUndo>& undos)
-{
- DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "SetUndo");
-
- DBus::Hoho hoho(call);
- hoho << config_name << number1 << number2 << undos;
-
- conn.send_with_reply_and_block(call);
-}
-
-
-void
-command_set_xundo_all(DBus::Connection& conn, const string& config_name, unsigned int number1,
- unsigned int number2, bool undo)
-{
- DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "SetUndoAll");
-
- DBus::Hoho hoho(call);
- hoho << config_name << number1 << number2 << undo;
-
- conn.send_with_reply_and_block(call);
-}
-
-
-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, "GetUndoSteps");
-
- DBus::Hoho hoho(call);
- hoho << config_name << number1 << number2;
-
- DBus::Message reply = conn.send_with_reply_and_block(call);
-
- vector<XUndoStep> undo_steps;
-
- DBus::Hihi hihi(reply);
- hihi >> undo_steps;
-
- return undo_steps;
-}
-
-
-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, "DoUndoStep");
-
- DBus::Hoho hoho(call);
- hoho << config_name << number1 << number2 << undo_step;
-
- DBus::Message reply = conn.send_with_reply_and_block(call);
-
- bool ret;
-
- DBus::Hihi hihi(reply);
- hihi >> ret;
-
- return ret;
-}
-
-
vector<string>
command_xdebug(DBus::Connection& conn)
{
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& name, const string& options);
-
-void
-command_set_xundo(DBus::Connection& conn, const string& config_name, unsigned int number1,
- unsigned int number2, const list<XUndo>& undos);
-
-void
-command_set_xundo_all(DBus::Connection& conn, const string& config_name, unsigned int number1,
- unsigned int number2, bool undo);
-
-vector<XUndoStep>
-command_get_xundo_steps(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);
-
vector<string>
command_xdebug(DBus::Connection& conn);
#include <snapper/SnapperTmpl.h>
#include <snapper/Enum.h>
#include <snapper/AsciiFile.h>
+#include <snapper/SystemCmd.h>
+#include <snapper/SnapperDefines.h>
#include "utils/text.h"
#include "utils/Table.h"
}
-string
-add_subvolume(const string& subvolume, const string& name)
+struct MyFiles : public Files
{
- return subvolume == "/" ? name : subvolume + name;
-}
+ friend class MyComparison;
+ MyFiles(const FilePaths* file_paths)
+ : Files(file_paths) {}
-string
-remove_subvolume(const string& subvolume, const string& name)
+};
+
+
+struct MyComparison
{
- if (!boost::starts_with(name, subvolume))
- throw;
+ MyComparison(DBus::Connection& conn, pair<unsigned int, unsigned int> nums, bool mount)
+ : files(&file_paths)
+ {
+ command_create_xcomparison(conn, config_name, nums.first, nums.second);
- if (subvolume == "/")
- return name;
- else
- return string(name, subvolume.size());
-}
+ file_paths.system_path = command_get_xmount_point(conn, config_name, 0);
+
+ if (mount)
+ {
+ if (nums.first != 0)
+ file_paths.pre_path = command_mount_xsnapshots(conn, config_name, nums.first);
+ else
+ file_paths.pre_path = file_paths.system_path;
+
+ if (nums.second != 0)
+ file_paths.post_path = command_mount_xsnapshots(conn, config_name, nums.second);
+ else
+ file_paths.post_path = file_paths.system_path;
+ }
+
+ list<XFile> tmp = command_get_xfiles(conn, config_name, nums.first, nums.second);
+ for (list<XFile>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
+ files.push_back(File(&file_paths, it->name, it->status));
+ }
+
+ FilePaths file_paths;
+
+ MyFiles files;
+
+};
void
pair<unsigned int, unsigned int> nums(read_nums(getopts.popArg()));
- command_create_xcomparison(conn, config_name, nums.first, nums.second);
-
- list<XFile> files = command_get_xfiles(conn, config_name, nums.first, nums.second);
+ MyComparison comparison(conn, nums, false);
+ MyFiles& files = comparison.files;
FILE* file = stdout;
}
}
- XConfigInfo ci = command_get_xconfig(conn, config_name);
-
- for (list<XFile>::const_iterator it = files.begin(); it != files.end(); ++it)
- fprintf(file, "%s %s\n", it->status.c_str(), add_subvolume(ci.subvolume, it->name).c_str());
+ 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);
pair<unsigned int, unsigned int> nums(read_nums(getopts.popArg()));
- command_create_xcomparison(conn, config_name, nums.first, nums.second);
+ MyComparison comparison(conn, nums, true);
+ MyFiles& files = comparison.files;
if (getopts.numArgs() == 0)
{
- list<XFile> files = command_get_xfiles(conn, config_name, nums.first, nums.second);
-
- for (list<XFile>::const_iterator it1 = files.begin(); it1 != files.end(); ++it1)
+ for (Files::const_iterator it1 = files.begin(); it1 != files.end(); ++it1)
{
- vector<string> lines = command_get_xdiff(conn, config_name, nums.first, nums.second,
- it1->name, "--unified --new-file");
+ SystemCmd cmd(DIFFBIN " --unified --new-file " + quote(it1->getAbsolutePath(LOC_PRE)) +
+ " " + quote(it1->getAbsolutePath(LOC_POST)), false);
+
+ const vector<string> lines = cmd.stdout();
for (vector<string>::const_iterator it2 = lines.begin(); it2 != lines.end(); ++it2)
cout << it2->c_str() << endl;
}
}
else
{
- XConfigInfo ci = command_get_xconfig(conn, config_name);
-
while (getopts.numArgs() > 0)
{
- string name = remove_subvolume(ci.subvolume, getopts.popArg());
+ string name = getopts.popArg();
+
+ Files::const_iterator it1 = files.findAbsolutePath(name);
+ if (it1 == files.end())
+ continue;
+
+ SystemCmd cmd(DIFFBIN " --unified --new-file " + quote(it1->getAbsolutePath(LOC_PRE)) +
+ " " + quote(it1->getAbsolutePath(LOC_POST)), false);
- vector<string> lines = command_get_xdiff(conn, config_name, nums.first, nums.second,
- name, "--unified --new-file");
+ const vector<string> lines = cmd.stdout();
for (vector<string>::const_iterator it2 = lines.begin(); it2 != lines.end(); ++it2)
cout << it2->c_str() << endl;
}
exit(EXIT_FAILURE);
}
- command_create_xcomparison(conn, config_name, nums.first, nums.second);
-
- list<XFile> files = command_get_xfiles(conn, config_name, nums.first, nums.second);
+ MyComparison comparison(conn, nums, true);
+ MyFiles& files = comparison.files;
if (file)
{
- XConfigInfo ci = command_get_xconfig(conn, config_name);
-
- list<XUndo> undos;
-
AsciiFileReader asciifile(file);
string line;
name.erase(0, pos + 1);
}
- XUndo undo;
- undo.undo = true;
- undo.name = remove_subvolume(ci.subvolume, name);
- undos.push_back(undo);
- }
+ Files::iterator it = files.findAbsolutePath(name);
+ if (it == files.end())
+ {
+ cerr << sformat(_("File '%s' not found."), name.c_str()) << endl;
+ exit(EXIT_FAILURE);
+ }
- command_set_xundo(conn, config_name, nums.first, nums.second, undos);
+ it->setUndo(true);
+ }
}
else
{
if (getopts.numArgs() == 0)
{
- command_set_xundo_all(conn, config_name, nums.first, nums.second, true);
+ for (Files::iterator it = files.begin(); it != files.end(); ++it)
+ it->setUndo(true);
}
else
{
- XConfigInfo ci = command_get_xconfig(conn, config_name);
-
- list<XUndo> undos;
-
while (getopts.numArgs() > 0)
{
- XUndo undo;
- undo.undo = true;
- undo.name = remove_subvolume(ci.subvolume, getopts.popArg());
- undos.push_back(undo);
- }
+ Files::iterator it = files.findAbsolutePath(getopts.popArg());
+ if (it == files.end())
+ continue;
- command_set_xundo(conn, config_name, nums.first, nums.second, undos);
+ it->setUndo(true);
+ }
}
}
- vector<XUndoStep> undo_steps = command_get_xundo_steps(conn, config_name, nums.first, nums.second);
+ UndoStatistic undo_statistic = files.getUndoStatistic();
- 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)
+ if (undo_statistic.empty())
{
cout << _("nothing to do") << endl;
return;
}
- cout << sformat(_("create:%d modify:%d delete:%d"), numCreate, numModify, numDelete) << endl;
+ cout << sformat(_("create:%d modify:%d delete:%d"), undo_statistic.numCreate,
+ undo_statistic.numModify, undo_statistic.numDelete) << endl;
- XConfigInfo ci = command_get_xconfig(conn, config_name);
+ vector<UndoStep> undo_steps = files.getUndoSteps();
- for (vector<XUndoStep>::const_iterator it = undo_steps.begin(); it != undo_steps.end(); ++it)
+ for (vector<UndoStep>::const_iterator it1 = undo_steps.begin(); it1 != undo_steps.end(); ++it1)
{
+ vector<File>::const_iterator it2 = files.find(it1->name);
+ if (it2 == files.end())
+ {
+ cerr << "internal error" << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ if (it1->action != it2->getAction())
+ {
+ cerr << "internal error" << endl;
+ exit(EXIT_FAILURE);
+ }
+
if (verbose)
{
- switch (it->action)
+ switch (it1->action)
{
case CREATE:
- cout << sformat(_("creating %s"), add_subvolume(ci.subvolume, it->name).c_str()) << endl;
+ cout << sformat(_("creating %s"), it2->getAbsolutePath(LOC_SYSTEM).c_str()) << endl;
break;
case MODIFY:
- cout << sformat(_("modifying %s"), add_subvolume(ci.subvolume, it->name).c_str()) << endl;
+ cout << sformat(_("modifying %s"), it2->getAbsolutePath(LOC_SYSTEM).c_str()) << endl;
break;
case DELETE:
- cout << sformat(_("deleting %s"), add_subvolume(ci.subvolume, it->name).c_str()) << endl;
+ cout << sformat(_("deleting %s"), it2->getAbsolutePath(LOC_SYSTEM).c_str()) << endl;
break;
}
}
- if (!command_do_xundo_step(conn, config_name, nums.first, nums.second, *it))
+ if (!it2->doUndo())
{
- switch (it->action)
+ switch (it1->action)
{
case CREATE:
- cout << sformat(_("failed to create %s"), add_subvolume(ci.subvolume, it->name).c_str()) << endl;
+ cerr << sformat(_("failed to create %s"), it2->getAbsolutePath(LOC_SYSTEM).c_str()) << endl;
break;
case MODIFY:
- cout << sformat(_("failed to modify %s"), add_subvolume(ci.subvolume, it->name).c_str()) << endl;
+ cerr << sformat(_("failed to modify %s"), it2->getAbsolutePath(LOC_SYSTEM).c_str()) << endl;
break;
case DELETE:
- cout << sformat(_("failed to delete %s"), add_subvolume(ci.subvolume, it->name).c_str()) << endl;
+ cerr << sformat(_("failed to delete %s"), it2->getAbsolutePath(LOC_SYSTEM).c_str()) << endl;
break;
}
}
{
const char* TypeInfo<XConfigInfo>::signature = "(ssa{ss})";
const char* TypeInfo<XSnapshot>::signature = "(uqutssa{ss})";
- const char* TypeInfo<XFile>::signature = "(ssb)";
- const char* TypeInfo<XUndo>::signature = "(sb)";
- const char* TypeInfo<XUndoStep>::signature = "(sq)";
+ const char* TypeInfo<XFile>::signature = "(su)";
Hihi&
operator>>(Hihi& hihi, XFile& data)
{
hihi.open_recurse();
- hihi >> data.name >> data.status >> data.undo;
+ hihi >> data.name >> data.status;
hihi.close_recurse();
return hihi;
}
return hoho;
}
-
- Hoho&
- operator<<(Hoho& hoho, const XUndo& data)
- {
- hoho.open_struct();
- hoho << data.name << data.undo;
- hoho.close_struct();
- 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;
- }
}
struct XFile
{
- string status;
string name;
- bool undo;
-};
-
-
-struct XUndo
-{
- string name;
- bool undo;
-};
-
-
-struct XUndoStep
-{
- string name;
- Action action;
+ unsigned int status;
};
template <> struct TypeInfo<XSnapshot> { static const char* signature; };
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);
Hihi& operator>>(Hihi& hihi, XFile& data);
- Hoho& operator<<(Hoho& hoho, const XUndo& data);
-
- Hihi& operator>>(Hihi& hihi, XUndoStep& data);
- Hoho& operator<<(Hoho& hoho, const XUndoStep& data);
-
};
namespace DBus
{
- class Connection : boost::noncopyable
+ class Connection : private boost::noncopyable
{
public:
method CreateComparison config-name number1 number2
method DeleteComparison config-name number1 number2
-The following commands require a successful CreateComparison in advance.
+The following command require a successful CreateComparison in advance.
-method GetFiles config-name number1 number2 -> list(filename status undo)
+method GetFiles config-name number1 number2 -> list(filename status)
-method GetStatus config-name number1 number2 filename which -> string
-method GetDiff config-name number1 number2 filename which -> list(string)
-
-method SetUndo config-name number1 number2 list(filename undo)
-method SetUndoAll config-name number1 number2 bool
-method GetUndoSteps config-name number1 number2
-method DoUndoStep config-name number1 number2 undo_step
Filenames do not include the subvolume.
cout << f->getAbsolutePath(LOC_SYSTEM) << " "
<< f->getAbsolutePath(LOC_PRE) << " "
<< f->getAbsolutePath(LOC_POST) << endl;
- vector<string> const& sv = f->getDiff("-u");
- for( vector<string>::const_iterator s=sv.begin(); s!=sv.end(); ++s )
- cout << *s << endl;
}
}
Files& flist = cmp.getFiles();
Files::iterator fi=flist.begin();
if( fi!=flist.end() )
+ {
cout << boolalpha << fi->getUndo() << endl;
fi->setUndo(true);
cout << boolalpha << fi->getUndo() << endl;
cout << boolalpha << fi->getUndo() << endl;
fi->setUndo(true);
cout << boolalpha << fi->getUndo() << endl;
+ }
// testing doUndo
if( fi!=flist.end() )
" <arg name='files' type='v' direction='out'/>\n"
" </method>\n"
- " <method name='GetDiff'>\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='filename' type='s' direction='in'/>\n"
- " <arg name='options' type='s' direction='in'/>\n"
- " <arg name='diff' type='v' direction='out'/>\n"
- " </method>\n"
-
- " <method name='SetUndo'>\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='files' type='a(sb)' direction='in'/>\n"
- " </method>\n"
-
- " <method name='SetUndoAll'>\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' type='b' direction='in'/>\n"
- " </method>\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='undo-steps' type='a(sq)' direction='out'/>\n"
- " </method>\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"
"</node>\n";
}
-void
-Client::get_diff(DBus::Connection& conn, DBus::Message& msg)
-{
- string config_name;
- dbus_uint32_t num1, num2;
- string filename;
- string options;
-
- DBus::Hihi hihi(msg);
- hihi >> config_name >> num1 >> num2 >> filename >> options;
-
- y2deb("GetDiff config_name:" << config_name << " num1:" << num1 << " num2:" << num2 <<
- " filename:" << filename << " options:" << options);
-
- boost::unique_lock<boost::shared_mutex> lock(big_mutex);
-
- MetaSnappers::iterator it = meta_snappers.find(config_name);
-
- check_permission(conn, msg, *it);
-
- list<Comparison*>::iterator it2 = find_comparison(it->getSnapper(), num1, num2);
-
- Files& files = (*it2)->getFiles();
-
- Files::iterator it3 = files.find(filename);
- if (it3 == files.end())
- throw UnknownFile();
-
- lock.unlock();
-
- vector<string> d = it3->getDiff(options);
-
- lock.lock();
-
- DBus::MessageMethodReturn reply(msg);
-
- DBus::Hoho hoho(reply);
- hoho << d;
-
- conn.send(reply);
-}
-
-
-void
-Client::set_undo(DBus::Connection& conn, DBus::Message& msg)
-{
- string config_name;
- dbus_uint32_t num1, num2;
- list<Undo> undos;
-
- DBus::Hihi hihi(msg);
- hihi >> config_name >> num1 >> num2 >> undos;
-
- y2deb("SetUndo config_name:" << config_name << " num1:" << num1 << " num2:" << num2);
-
- boost::unique_lock<boost::shared_mutex> lock(big_mutex);
-
- MetaSnappers::iterator it = meta_snappers.find(config_name);
-
- check_permission(conn, msg, *it);
-
- list<Comparison*>::iterator it2 = find_comparison(it->getSnapper(), num1, num2);
-
- Files& files = (*it2)->getFiles();
-
- for (list<Undo>::const_iterator it2 = undos.begin(); it2 != undos.end(); ++it2)
- {
- Files::iterator it3 = files.find(it2->filename);
- if (it3 == files.end())
- throw UnknownFile();
-
- it3->setUndo(it2->undo);
- }
-
- DBus::MessageMethodReturn reply(msg);
-
- conn.send(reply);
-}
-
-
-void
-Client::set_undo_all(DBus::Connection& conn, DBus::Message& msg)
-{
- string config_name;
- dbus_uint32_t num1, num2;
- bool undo;
-
- DBus::Hihi hihi(msg);
- hihi >> config_name >> num1 >> num2 >> undo;
-
- y2deb("SetUndoAll config_name:" << config_name << " num1:" << num1 << " num2:" << num2);
-
- boost::unique_lock<boost::shared_mutex> lock(big_mutex);
-
- MetaSnappers::iterator it = meta_snappers.find(config_name);
-
- check_permission(conn, msg, *it);
-
- list<Comparison*>::iterator it3 = find_comparison(it->getSnapper(), num1, num2);
-
- Files& files = (*it3)->getFiles();
-
- for (Files::iterator it2 = files.begin(); it2 != files.end(); ++it2)
- {
- it2->setUndo(undo);
- }
-
- DBus::MessageMethodReturn reply(msg);
-
- conn.send(reply);
-}
-
-
-void
-Client::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;
-
- y2deb("GetUndoSteps config_name:" << config_name << " num1:" << num1 << " num2:" << num2);
-
- boost::unique_lock<boost::shared_mutex> lock(big_mutex);
-
- MetaSnappers::iterator it = meta_snappers.find(config_name);
-
- check_permission(conn, msg, *it);
-
- list<Comparison*>::iterator it2 = find_comparison(it->getSnapper(), num1, num2);
-
- vector<UndoStep> undo_steps = (*it2)->getUndoSteps();
-
- DBus::MessageMethodReturn reply(msg);
-
- DBus::Hoho hoho(reply);
- hoho << undo_steps;
-
- conn.send(reply);
-}
-
-
-void
-Client::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 >> undo_step;
-
- y2deb("DoUndoStep config_name:" << config_name << " num1:" << num1 << " num2:" << num2);
-
- boost::unique_lock<boost::shared_mutex> lock(big_mutex);
-
- MetaSnappers::iterator it = meta_snappers.find(config_name);
-
- check_permission(conn, msg, *it);
-
- list<Comparison*>::iterator it2 = find_comparison(it->getSnapper(), num1, num2);
-
- lock.unlock();
-
- bool ret = (*it2)->doUndoStep(undo_step);
-
- lock.lock();
-
- DBus::MessageMethodReturn reply(msg);
-
- DBus::Hoho hoho(reply);
- hoho << ret;
-
- conn.send(reply);
-}
-
-
void
Client::debug(DBus::Connection& conn, DBus::Message& msg) const
{
delete_comparison(conn, msg);
else if (msg.is_method_call(INTERFACE, "GetFiles"))
get_files(conn, msg);
- else if (msg.is_method_call(INTERFACE, "GetDiff"))
- get_diff(conn, msg);
- else if (msg.is_method_call(INTERFACE, "SetUndo"))
- set_undo(conn, msg);
- else if (msg.is_method_call(INTERFACE, "SetUndoAll"))
- set_undo_all(conn, msg);
- else if (msg.is_method_call(INTERFACE, "GetUndoSteps"))
- get_undo_steps(conn, msg);
- else if (msg.is_method_call(INTERFACE, "DoUndoStep"))
- do_undo_step(conn, msg);
else if (msg.is_method_call(INTERFACE, "Debug"))
debug(conn, msg);
else
};
-class Client : boost::noncopyable
+class Client : private boost::noncopyable
{
public:
void create_comparison(DBus::Connection& conn, DBus::Message& msg);
void delete_comparison(DBus::Connection& conn, DBus::Message& msg);
void get_files(DBus::Connection& conn, DBus::Message& msg);
- void get_diff(DBus::Connection& conn, DBus::Message& msg);
- void set_undo(DBus::Connection& conn, DBus::Message& msg);
- void set_undo_all(DBus::Connection& conn, DBus::Message& msg);
- void get_undo_steps(DBus::Connection& conn, DBus::Message& msg);
- void do_undo_step(DBus::Connection& conn, DBus::Message& msg);
void debug(DBus::Connection& conn, DBus::Message& msg) const;
void dispatch(DBus::Connection& conn, DBus::Message& msg);
using namespace snapper;
-class RefCounter : boost::noncopyable
+class RefCounter : private boost::noncopyable
{
public:
{
const char* TypeInfo<ConfigInfo>::signature = "(ssa{ss})";
const char* TypeInfo<Snapshot>::signature = "(uqutssa{ss})";
- const char* TypeInfo<File>::signature = "(ssb)";
- const char* TypeInfo<Undo>::signature = "(sb)";
- const char* TypeInfo<UndoStep>::signature = "(sq)";
+ const char* TypeInfo<File>::signature = "(su)";
Hoho&
operator<<(Hoho& hoho, const File& data)
{
hoho.open_struct();
- hoho << data.getName() << statusToString(data.getPreToPostStatus()) << data.getUndo();
+ hoho << data.getName() << data.getPreToPostStatus();
hoho.close_struct();
return hoho;
}
return hoho;
}
-
- Hihi&
- operator>>(Hihi& hihi, Undo& data)
- {
- hihi.open_recurse();
- hihi >> data.filename >> data.undo;
- hihi.close_recurse();
- return hihi;
- }
-
-
- Hoho&
- operator<<(Hoho& hoho, const Undo& data)
- {
- hoho.open_struct();
- hoho << data.filename << data.undo;
- hoho.close_struct();
- 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;
- }
-
}
-
using namespace snapper;
-struct Undo
-{
- Undo() {}
- Undo(const string& filename, bool undo) : filename(filename), undo(undo) {}
-
- string filename;
- bool undo;
-};
-
-
namespace DBus
{
template <> struct TypeInfo<ConfigInfo> { static const char* signature; };
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);
Hoho& operator<<(Hoho& hoho, const Files& 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);
-
};
dirfd = ::open(base_path.c_str(), O_RDONLY | O_NOATIME);
if (dirfd < 0)
{
- cerr << "open failed path:" << base_path << " error:" << strerror(errno) << endl;
+ y2err("open failed path:" << base_path << " error:" << strerror(errno));
throw IOErrorException();
}
}
dirfd = ::openat(dir.dirfd, name.c_str(), O_RDONLY | O_NOFOLLOW | O_NOATIME);
if (dirfd < 0)
{
- cerr << "open failed path:" << dir.fullname(name) << " (" << strerror(errno) << ")" << endl;
+ y2err("open failed path:" << dir.fullname(name) << " (" << strerror(errno) << ")");
throw IOErrorException();
}
}
int fd = dup(dirfd);
if (fd == -1)
{
- cerr << "dup failed" << " error:" << strerror(errno) << endl;
+ y2err("dup failed" << " error:" << strerror(errno));
throw IOErrorException();
}
DIR* dp = fdopendir(fd);
if (dp == NULL)
{
- cerr << "fdopendir failed path:" << fullname() << " error:" << strerror(errno) << endl;
+ y2err("fdopendir failed path:" << fullname() << " error:" << strerror(errno));
::close(fd);
throw IOErrorException();
}
using std::vector;
- class SDir : boost::noncopyable
+ class SDir : private boost::noncopyable
{
public:
};
- class SFile : boost::noncopyable
+ class SFile : private boost::noncopyable
{
public:
*/
+#include <string.h>
+
#include "snapper/Comparison.h"
#include "snapper/Snapper.h"
#include "snapper/Log.h"
#include "snapper/File.h"
#include "snapper/Exception.h"
+#include "snapper/Compare.h"
+#include "snapper/SnapperTmpl.h"
+#include "snapper/AsciiFile.h"
namespace snapper
Comparison::Comparison(const Snapper* snapper, Snapshots::const_iterator snapshot1,
Snapshots::const_iterator snapshot2)
- : snapper(snapper), snapshot1(snapshot1), snapshot2(snapshot2), files(this)
+ : snapper(snapper), snapshot1(snapshot1), snapshot2(snapshot2), files(&file_paths)
{
if (snapshot1 == snapper->getSnapshots().end() ||
snapshot2 == snapper->getSnapshots().end() ||
y2mil("num1:" << snapshot1->getNum() << " num2:" << snapshot2->getNum());
- files.initialize();
+ file_paths.system_path = snapper->subvolumeDir();
+ file_paths.pre_path = snapshot1->snapshotDir();
+ file_paths.post_path = snapshot2->snapshotDir();
+
+ initialize();
+ }
+
+
+ void
+ Comparison::initialize()
+ {
+ if (getSnapshot1()->isCurrent() || getSnapshot2()->isCurrent())
+ {
+ create();
+ }
+ else
+ {
+ if (!load())
+ {
+ create();
+ save();
+ }
+ }
+
+ filter();
+ }
+
+
+ struct Comparison::AppendHelper
+ {
+ AppendHelper(const FilePaths* file_paths, Files& files)
+ : file_paths(file_paths), files(files) {}
+ void operator()(const string& name, unsigned int status)
+ { files.push_back(File(file_paths, name, status)); }
+ const FilePaths* file_paths;
+ Files& files;
+ };
+
+
+ void
+ Comparison::create()
+ {
+ y2mil("num1:" << getSnapshot1()->getNum() << " num2:" << getSnapshot2()->getNum());
+
+ if (!getSnapshot1()->isCurrent())
+ getSnapshot1()->mountFilesystemSnapshot();
+ if (!getSnapshot2()->isCurrent())
+ getSnapshot2()->mountFilesystemSnapshot();
+
+#if 1
+ cmpdirs_cb_t cb = AppendHelper(&file_paths, files);
+#else
+ cmpdirs_cb_t cb = [&file_paths, &files](const string& name, unsigned int status) {
+ files.push_back(File(&file_paths, name, status));
+ };
+#endif
+
+ SDir dir1(getSnapshot1()->snapshotDir());
+ SDir dir2(getSnapshot2()->snapshotDir());
+ cmpDirs(dir1, dir2, cb);
+
+ files.sort();
+
+ y2mil("found " << files.size() << " lines");
+ }
+
+
+ bool
+ Comparison::load()
+ {
+ y2mil("num1:" << getSnapshot1()->getNum() << " num2:" << getSnapshot2()->getNum());
+
+ if (getSnapshot1()->isCurrent() || getSnapshot2()->isCurrent())
+ throw IllegalSnapshotException();
+
+ unsigned int num1 = getSnapshot1()->getNum();
+ unsigned int num2 = getSnapshot2()->getNum();
+
+ bool invert = num1 > num2;
+
+ if (invert)
+ swap(num1, num2);
+
+ string input = getSnapper()->infosDir() + "/" + decString(num2) + "/filelist-" +
+ decString(num1) + ".txt";
+
+ try
+ {
+ AsciiFileReader asciifile(input);
+
+ string line;
+ while (asciifile.getline(line))
+ {
+ string::size_type pos = line.find(" ");
+ if (pos == string::npos)
+ continue;
+
+ unsigned int status = stringToStatus(string(line, 0, pos));
+ string name = string(line, pos + 1);
+
+ if (invert)
+ status = invertStatus(status);
+
+ File file(&file_paths, name, status);
+ files.push_back(file);
+ }
+ }
+ catch (const FileNotFoundException& e)
+ {
+ return false;
+ }
+
+ files.sort();
+
+ y2mil("read " << files.size() << " lines");
+
+ return true;
}
- Files&
- Comparison::getFiles()
+ bool
+ Comparison::save()
{
- return files;
+ y2mil("num1:" << getSnapshot1()->getNum() << " num2:" << getSnapshot2()->getNum());
+
+ if (getSnapshot1()->isCurrent() || getSnapshot2()->isCurrent())
+ throw IllegalSnapshotException();
+
+ unsigned int num1 = getSnapshot1()->getNum();
+ unsigned int num2 = getSnapshot2()->getNum();
+
+ bool invert = num1 > num2;
+
+ if (invert)
+ swap(num1, num2);
+
+ string output = getSnapper()->infosDir() + "/" + decString(num2) + "/filelist-" +
+ decString(num1) + ".txt";
+
+ string tmp_name = output + ".tmp-XXXXXX";
+
+ FILE* file = mkstemp(tmp_name);
+ if (!file)
+ {
+ y2err("mkstemp failed errno:" << errno << " (" << strerror(errno) << ")");
+ throw IOErrorException();
+ }
+
+ for (Files::const_iterator it = files.begin(); it != files.end(); ++it)
+ {
+ unsigned int status = it->getPreToPostStatus();
+
+ if (invert)
+ status = invertStatus(status);
+
+ fprintf(file, "%s %s\n", statusToString(status).c_str(), it->getName().c_str());
+ }
+
+ fclose(file);
+
+ rename(tmp_name.c_str(), output.c_str());
+
+ return true;
}
- const Files&
- Comparison::getFiles() const
+ void
+ Comparison::filter()
{
- return files;
+ const vector<string>& ignore_patterns = getSnapper()->getIgnorePatterns();
+ files.filter(ignore_patterns);
}
UndoStatistic
Comparison::getUndoStatistic() const
{
+ if (getSnapshot1()->isCurrent())
+ throw IllegalSnapshotException();
+
return files.getUndoStatistic();
}
vector<UndoStep>
Comparison::getUndoSteps() const
{
+ if (getSnapshot1()->isCurrent())
+ throw IllegalSnapshotException();
+
return files.getUndoSteps();
}
bool
Comparison::doUndoStep(const UndoStep& undo_step)
{
+ if (getSnapshot1()->isCurrent())
+ throw IllegalSnapshotException();
+
return files.doUndoStep(undo_step);
}
Snapshots::const_iterator getSnapshot1() const { return snapshot1; }
Snapshots::const_iterator getSnapshot2() const { return snapshot2; }
- Files& getFiles();
- const Files& getFiles() const;
+ Files& getFiles() { return files; }
+ const Files& getFiles() const { return files; }
UndoStatistic getUndoStatistic() const;
private:
+ void initialize();
+ void create();
+ bool load();
+ bool save();
+ void filter();
+
const Snapper* snapper;
Snapshots::const_iterator snapshot1;
Snapshots::const_iterator snapshot2;
+ FilePaths file_paths;
+
Files files;
+ struct AppendHelper;
+
};
}
#include "snapper/File.h"
#include "snapper/Snapper.h"
-#include "snapper/Comparison.h"
#include "snapper/AppUtil.h"
#include "snapper/Enum.h"
#include "snapper/SnapperTmpl.h"
#include "snapper/SystemCmd.h"
#include "snapper/SnapperDefines.h"
#include "snapper/Compare.h"
-#include "snapper/AsciiFile.h"
#include "snapper/Exception.h"
}
- const Snapper*
- File::getSnapper() const
- {
- return comparison->getSnapper();
- }
-
-
- const Snapper*
- Files::getSnapper() const
- {
- return comparison->getSnapper();
- }
-
-
-#if 1
- struct AppendHelper
- {
- AppendHelper(const Comparison* comparison, vector<File>& entries)
- : comparison(comparison), entries(entries) {}
- void operator()(const string& name, unsigned int status)
- { entries.push_back(File(comparison, name, status)); }
- const Comparison* comparison;
- vector<File>& entries;
- };
-#endif
-
-
- void
- Files::create()
- {
- y2mil("num1:" << comparison->getSnapshot1()->getNum() << " num2:" <<
- comparison->getSnapshot2()->getNum());
-
- if (!comparison->getSnapshot1()->isCurrent())
- comparison->getSnapshot1()->mountFilesystemSnapshot();
- if (!comparison->getSnapshot2()->isCurrent())
- comparison->getSnapshot2()->mountFilesystemSnapshot();
-
-#if 1
- cmpdirs_cb_t cb = AppendHelper(comparison, entries);
-#else
- cmpdirs_cb_t cb = [&comparison, &entries](const string& name, unsigned int status) {
- entries.push_back(File(comparison, name, status));
- };
-#endif
-
- SDir dir1(comparison->getSnapshot1()->snapshotDir());
- SDir dir2(comparison->getSnapshot2()->snapshotDir());
- cmpDirs(dir1, dir2, cb);
-
- sort(entries.begin(), entries.end());
-
- y2mil("found " << entries.size() << " lines");
- }
-
-
- bool
- Files::load()
- {
- y2mil("num1:" << comparison->getSnapshot1()->getNum() << " num2:" <<
- comparison->getSnapshot2()->getNum());
-
- if (comparison->getSnapshot1()->isCurrent() || comparison->getSnapshot2()->isCurrent())
- throw IllegalSnapshotException();
-
- unsigned int num1 = comparison->getSnapshot1()->getNum();
- unsigned int num2 = comparison->getSnapshot2()->getNum();
-
- bool invert = num1 > num2;
-
- if (invert)
- swap(num1, num2);
-
- string input = getSnapper()->infosDir() + "/" + decString(num2) + "/filelist-" +
- decString(num1) + ".txt";
-
- try
- {
- AsciiFileReader asciifile(input);
-
- string line;
- while (asciifile.getline(line))
- {
- string::size_type pos = line.find(" ");
- if (pos == string::npos)
- continue;
-
- unsigned int status = stringToStatus(string(line, 0, pos));
- string name = string(line, pos + 1);
-
- if (invert)
- status = invertStatus(status);
-
- File file(comparison, name, status);
- entries.push_back(file);
- }
- }
- catch (const FileNotFoundException& e)
- {
- return false;
- }
-
- sort(entries.begin(), entries.end());
-
- y2mil("read " << entries.size() << " lines");
-
- return true;
- }
-
-
- bool
- Files::save()
- {
- y2mil("num1:" << comparison->getSnapshot1()->getNum() << " num2:" << comparison->getSnapshot2()->getNum());
-
- if (comparison->getSnapshot1()->isCurrent() || comparison->getSnapshot2()->isCurrent())
- throw IllegalSnapshotException();
-
- unsigned int num1 = comparison->getSnapshot1()->getNum();
- unsigned int num2 = comparison->getSnapshot2()->getNum();
-
- bool invert = num1 > num2;
-
- if (invert)
- swap(num1, num2);
-
- string output = getSnapper()->infosDir() + "/" + decString(num2) + "/filelist-" +
- decString(num1) + ".txt";
-
- string tmp_name = output + ".tmp-XXXXXX";
-
- FILE* file = mkstemp(tmp_name);
- if (!file)
- {
- y2err("mkstemp failed errno:" << errno << " (" << strerror(errno) << ")");
- throw IOErrorException();
- }
-
- for (const_iterator it = entries.begin(); it != entries.end(); ++it)
- {
- unsigned int status = it->getPreToPostStatus();
-
- if (invert)
- status = invertStatus(status);
-
- fprintf(file, "%s %s\n", statusToString(status).c_str(), it->getName().c_str());
- }
-
- fclose(file);
-
- rename(tmp_name.c_str(), output.c_str());
-
- return true;
- }
-
-
struct FilterHelper
{
FilterHelper(const vector<string>& patterns)
void
- Files::filter()
+ Files::filter(const vector<string>& ignore_patterns)
{
- const vector<string>& ignore_patterns = getSnapper()->getIgnorePatterns();
entries.erase(remove_if(entries.begin(), entries.end(), FilterHelper(ignore_patterns)),
entries.end());
}
- void
- Files::initialize()
+ int
+ operator<(const File& a, const File& b)
{
- entries.clear();
+ return a.getName() < b.getName();
+ }
- if (comparison->getSnapshot1()->isCurrent() || comparison->getSnapshot2()->isCurrent())
- {
- create();
- }
- else
- {
- if (!load())
- {
- create();
- save();
- }
- }
- filter();
+ void
+ Files::sort()
+ {
+ std::sort(entries.begin(), entries.end());
}
- inline bool
+ bool
file_name_less(const File& file, const string& name)
{
return file.getName() < name;
Files::iterator
Files::findAbsolutePath(const string& filename)
{
- string subvolume = getSnapper()->subvolumeDir();
+ string subvolume = file_paths->system_path;
if (!boost::starts_with(filename, subvolume))
return end();
Files::const_iterator
Files::findAbsolutePath(const string& filename) const
{
- string subvolume = getSnapper()->subvolumeDir();
+ string subvolume = file_paths->system_path;
if (!boost::starts_with(filename, subvolume))
return end();
File::getPreToSystemStatus()
{
if (pre_to_system_status == (unsigned int)(-1))
- pre_to_system_status = cmpFiles(comparison->getSnapshot1()->snapshotDir(),
- getSnapper()->subvolumeDir(), name);
+ pre_to_system_status = cmpFiles(file_paths->pre_path, file_paths->system_path, name);
return pre_to_system_status;
}
File::getPostToSystemStatus()
{
if (post_to_system_status == (unsigned int)(-1))
- post_to_system_status = cmpFiles(comparison->getSnapshot2()->snapshotDir(),
- getSnapper()->subvolumeDir(), name);
+ post_to_system_status = cmpFiles(file_paths->post_path, file_paths->system_path, name);
return post_to_system_status;
}
switch (loc)
{
case LOC_PRE:
- prefix = comparison->getSnapshot1()->snapshotDir();
+ prefix = file_paths->pre_path;
break;
case LOC_POST:
- prefix = comparison->getSnapshot2()->snapshotDir();
+ prefix = file_paths->post_path;
break;
case LOC_SYSTEM:
- prefix = getSnapper()->subvolumeDir();
+ prefix = file_paths->system_path;
break;
}
}
- vector<string>
- File::getDiff(const string& options) const
- {
- SystemCmd cmd(DIFFBIN " " + options + " " + quote(getAbsolutePath(LOC_PRE)) + " " +
- quote(getAbsolutePath(LOC_POST)), false);
- return cmd.stdout();
- }
-
-
bool
File::createParentDirectories(const string& path) const
{
bool
- File::doUndo()
+ File::doUndo() const
{
- if (comparison->getSnapshot1()->isCurrent())
- throw IllegalSnapshotException();
-
bool error = false;
if (getPreToPostStatus() & CREATED || getPreToPostStatus() & TYPE)
UndoStatistic
Files::getUndoStatistic() const
{
- if (comparison->getSnapshot1()->isCurrent())
- throw IllegalSnapshotException();
-
UndoStatistic rs;
for (vector<File>::const_iterator it = entries.begin(); it != entries.end(); ++it)
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)
bool
- Files::doUndoStep(const UndoStep& undo_step)
+ Files::doUndoStep(const UndoStep& undo_step) const
{
- if (comparison->getSnapshot1()->isCurrent())
- throw IllegalSnapshotException();
-
- vector<File>::iterator it = find(undo_step.name);
+ vector<File>::const_iterator it = find(undo_step.name);
if (it == end())
return false;
/*
- * Copyright (c) 2011 Novell, Inc.
+ * Copyright (c) [2011-2012] Novell, Inc.
*
* All Rights Reserved.
*
using std::vector;
- class Snapper;
- class Comparison;
-
-
enum StatusFlags
{
CREATED = 1, DELETED = 2, TYPE = 4, CONTENT = 8, PERMISSIONS = 16, USER = 32,
};
+ struct FilePaths
+ {
+ string system_path;
+ string pre_path;
+ string post_path;
+ };
+
+
class File
{
public:
- File(const Comparison* comparison, const string& name,
- unsigned int pre_to_post_status)
- : comparison(comparison), name(name), pre_to_post_status(pre_to_post_status),
+ File(const FilePaths* file_paths, const string& name, unsigned int pre_to_post_status)
+ : file_paths(file_paths), name(name), pre_to_post_status(pre_to_post_status),
pre_to_system_status(-1), post_to_system_status(-1), undo(false)
{}
string getAbsolutePath(Location loc) const;
- vector<string> getDiff(const string& options) const;
-
bool getUndo() const { return undo; }
void setUndo(bool value) { undo = value; }
- bool doUndo();
+ bool doUndo() const;
Action getAction() const;
private:
- const Snapper* getSnapper() const;
-
bool createParentDirectories(const string& path) const;
bool createAllTypes() const;
bool modifyAllTypes() const;
- const Comparison* comparison;
+ const FilePaths* file_paths;
string name;
};
- inline int operator<(const File& a, const File& b)
- {
- return a.getName() < b.getName();
- }
-
-
class Files
{
public:
friend class Comparison;
- Files(const Comparison* comparison)
- : comparison(comparison) {}
-
- const Snapper* getSnapper() const;
+ Files(const FilePaths* file_paths)
+ : file_paths(file_paths) {}
typedef vector<File>::iterator iterator;
typedef vector<File>::const_iterator const_iterator;
iterator findAbsolutePath(const string& name);
const_iterator findAbsolutePath(const string& name) const;
- private:
+ UndoStatistic getUndoStatistic() const;
- void initialize();
+ vector<UndoStep> getUndoSteps() const;
- void create();
- bool load();
- bool save();
- void filter();
+ bool doUndoStep(const UndoStep& undo_step) const;
- UndoStatistic getUndoStatistic() const;
+ protected:
- vector<UndoStep> getUndoSteps() const;
+ void clear() { entries.clear(); }
+ void push_back(File file) { entries.push_back(file); }
- bool doUndoStep(const UndoStep& undo_step);
+ void filter(const vector<string>& ignore_patterns);
+ void sort();
- const Comparison* comparison;
+ const FilePaths* file_paths;
+
+ private:
vector<File> entries;
/*
- * Copyright (c) [2004-2011] Novell, Inc.
+ * Copyright (c) [2004-2012] Novell, Inc.
*
* All Rights Reserved.
*
using std::string;
-class Regex : boost::noncopyable
+class Regex : private boost::noncopyable
{
public:
};
- class Snapper : boost::noncopyable
+ class Snapper : private boost::noncopyable
{
public:
/*
- * Copyright (c) [2004-2011] Novell, Inc.
+ * Copyright (c) [2004-2012] Novell, Inc.
*
* All Rights Reserved.
*
using std::vector;
-class SystemCmd : boost::noncopyable
+ class SystemCmd : private boost::noncopyable
{
public:
/*
- * Copyright (c) [2010-2011] Novell, Inc.
+ * Copyright (c) [2010-2012] Novell, Inc.
*
* All Rights Reserved.
*
using namespace std;
- class XmlFile : boost::noncopyable
+ class XmlFile : private boost::noncopyable
{
public: