Enhancement - confirmation on big changes

- Implemented confirmation on big changes.  That means if the description is
  changed, or more than 2 tasks are modified in a single command.
- Implemented taskDiff to detect differences between two tasks.
- Implemented taskDifferences to describe differences between two tasks.
This commit is contained in:
Paul Beckingham 2009-06-27 17:09:29 -04:00
parent 8e8f5935b3
commit 6e4f60c4fe
4 changed files with 70 additions and 23 deletions

View file

@ -35,6 +35,7 @@
#include <pwd.h>
#include <time.h>
#include "Permission.h"
#include "text.h"
#include "util.h"
#include "main.h"
@ -794,6 +795,10 @@ std::string handleModify ()
std::vector <Task> all = tasks;
context.filter.applySequence (tasks, context.sequence);
Permission permission;
if (context.sequence.size () > (size_t) context.config.get ("bulk", 2))
permission.bigSequence ();
foreach (task, tasks)
{
// Perform some logical consistency checks.
@ -815,22 +820,33 @@ std::string handleModify ()
task->get ("parent") == other->get ("parent")) || // Sibling
other->get ("uuid") == task->get ("parent")) // Parent
{
Task before (*other);
// A non-zero value forces a file write.
int changes = 0;
// Apply other deltas.
changes += deltaDescription (*other);
if (deltaDescription (*other))
{
permission.bigChange ();
++changes;
}
changes += deltaTags (*other);
changes += deltaAttributes (*other);
changes += deltaSubstitutions (*other);
if (changes)
if (taskDiff (before, *other))
{
std::string question = taskDifferences (before, *other) + "Are you sure?";
if (changes && permission.confirmed (question))
context.tdb.update (*other);
++count;
}
}
}
}
context.tdb.commit ();
context.tdb.unlock ();

View file

@ -34,7 +34,7 @@ Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
UnitTest t (17);
UnitTest t (19);
// TODO bool confirm (const std::string&);
// TODO int confirm3 (const std::string&);
@ -80,14 +80,16 @@ int main (int argc, char** argv)
Task rightAgain (right);
std::string output = taskDiff (left, right);
t.ok (output.find ("zero was changed from '0' to '00'.\n") != std::string::npos, "Detected change zero:0 -> zero:00");
t.ok (output.find ("one was deleted.\n") != std::string::npos, "Detected deletion one:1 ->");
std::string output = taskDifferences (left, right);
t.ok (taskDiff (left, right), "Detected changes");
t.ok (output.find ("zero was changed from '0' to '00'.") != std::string::npos, "Detected change zero:0 -> zero:00");
t.ok (output.find ("one was deleted.") != std::string::npos, "Detected deletion one:1 ->");
t.ok (output.find ("two") == std::string::npos, "Detected no change two:2 -> two:2");
t.ok (output.find ("three was set to '3'.\n") != std::string::npos, "Detected addition -> three:3");
t.ok (output.find ("three was set to '3'.") != std::string::npos, "Detected addition -> three:3");
output = taskDiff (right, rightAgain);
t.ok (output.find ("No changes were made.\n") != std::string::npos, "No changes detected");
t.notok (taskDiff (right, rightAgain), "No changes detected");
output = taskDifferences (right, rightAgain);
t.ok (output.find ("No changes were made.") != std::string::npos, "No changes detected");
return 0;
}

View file

@ -427,7 +427,37 @@ void spit (const std::string& file, const std::string& contents)
}
////////////////////////////////////////////////////////////////////////////////
std::string taskDiff (const Task& before, const Task& after)
bool taskDiff (const Task& before, const Task& after)
{
// Attributes are all there is, so figure the different attribute names
// between before and after.
std::vector <std::string> beforeAtts;
foreach (att, before)
beforeAtts.push_back (att->first);
std::vector <std::string> afterAtts;
foreach (att, after)
afterAtts.push_back (att->first);
std::vector <std::string> beforeOnly;
std::vector <std::string> afterOnly;
listDiff (beforeAtts, afterAtts, beforeOnly, afterOnly);
if (beforeOnly.size () ||
afterOnly.size ())
return true;
foreach (name, beforeAtts)
if (*name != "uuid" &&
after.get (*name) != "" &&
before.get (*name) != after.get (*name))
return true;
return false;
}
////////////////////////////////////////////////////////////////////////////////
std::string taskDifferences (const Task& before, const Task& after)
{
// Attributes are all there is, so figure the different attribute names
// between before and after.
@ -447,15 +477,13 @@ std::string taskDiff (const Task& before, const Task& after)
std::stringstream out;
foreach (name, beforeOnly)
out << *name
<< " was deleted."
<< std::endl;
<< " was deleted. ";
foreach (name, afterOnly)
out << *name
<< " was set to '"
<< after.get (*name)
<< "'."
<< std::endl;
<< "'. ";
foreach (name, beforeAtts)
if (*name != "uuid" &&
@ -466,15 +494,15 @@ std::string taskDiff (const Task& before, const Task& after)
<< before.get (*name)
<< "' to '"
<< after.get (*name)
<< "'."
<< std::endl;
<< "'. ";
// Can't just say nothing.
if (out.str ().length () == 0)
out << "No changes were made."
<< std::endl;
out << "No changes were made. ";
return out.str ();
std::stringstream decorated;
decorated << "Task " << before.id << " was modified. " << out.str ();
return decorated.str ();
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -73,7 +73,8 @@ std::string expandPath (const std::string&);
bool slurp (const std::string&, std::vector <std::string>&, bool trimLines = false);
bool slurp (const std::string&, std::string&, bool trimLines = false);
void spit (const std::string&, const std::string&);
std::string taskDiff (const Task&, const Task&);
bool taskDiff (const Task&, const Task&);
std::string taskDifferences (const Task&, const Task&);
#endif
////////////////////////////////////////////////////////////////////////////////