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

View file

@ -34,7 +34,7 @@ Context context;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv) int main (int argc, char** argv)
{ {
UnitTest t (17); UnitTest t (19);
// TODO bool confirm (const std::string&); // TODO bool confirm (const std::string&);
// TODO int confirm3 (const std::string&); // TODO int confirm3 (const std::string&);
@ -80,14 +80,16 @@ int main (int argc, char** argv)
Task rightAgain (right); Task rightAgain (right);
std::string output = taskDiff (left, right); std::string output = taskDifferences (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 (taskDiff (left, right), "Detected changes");
t.ok (output.find ("one was deleted.\n") != std::string::npos, "Detected deletion one:1 ->"); t.ok (output.find ("zero was changed from '0' to '00'.") != std::string::npos, "Detected change zero:0 -> zero:00");
t.ok (output.find ("two") == std::string::npos, "Detected no change two:2 -> two:2"); t.ok (output.find ("one was deleted.") != std::string::npos, "Detected deletion one:1 ->");
t.ok (output.find ("three was set to '3'.\n") != std::string::npos, "Detected addition -> three:3"); t.ok (output.find ("two") == std::string::npos, "Detected no change two:2 -> two:2");
t.ok (output.find ("three was set to '3'.") != std::string::npos, "Detected addition -> three:3");
output = taskDiff (right, rightAgain); t.notok (taskDiff (right, rightAgain), "No changes detected");
t.ok (output.find ("No changes were made.\n") != std::string::npos, "No changes detected"); output = taskDifferences (right, rightAgain);
t.ok (output.find ("No changes were made.") != std::string::npos, "No changes detected");
return 0; 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 // Attributes are all there is, so figure the different attribute names
// between before and after. // between before and after.
@ -447,15 +477,13 @@ std::string taskDiff (const Task& before, const Task& after)
std::stringstream out; std::stringstream out;
foreach (name, beforeOnly) foreach (name, beforeOnly)
out << *name out << *name
<< " was deleted." << " was deleted. ";
<< std::endl;
foreach (name, afterOnly) foreach (name, afterOnly)
out << *name out << *name
<< " was set to '" << " was set to '"
<< after.get (*name) << after.get (*name)
<< "'." << "'. ";
<< std::endl;
foreach (name, beforeAtts) foreach (name, beforeAtts)
if (*name != "uuid" && if (*name != "uuid" &&
@ -466,15 +494,15 @@ std::string taskDiff (const Task& before, const Task& after)
<< before.get (*name) << before.get (*name)
<< "' to '" << "' to '"
<< after.get (*name) << after.get (*name)
<< "'." << "'. ";
<< std::endl;
// Can't just say nothing. // Can't just say nothing.
if (out.str ().length () == 0) if (out.str ().length () == 0)
out << "No changes were made." out << "No changes were made. ";
<< std::endl;
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::vector <std::string>&, bool trimLines = false);
bool slurp (const std::string&, std::string&, bool trimLines = false); bool slurp (const std::string&, std::string&, bool trimLines = false);
void spit (const std::string&, const std::string&); 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 #endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////