diff --git a/src/command.cpp b/src/command.cpp index 1d0e953a8..f61c17ea2 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -35,6 +35,7 @@ #include #include +#include "Permission.h" #include "text.h" #include "util.h" #include "main.h" @@ -794,6 +795,10 @@ std::string handleModify () std::vector 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,19 +820,30 @@ 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) - context.tdb.update (*other); + if (taskDiff (before, *other)) + { + std::string question = taskDifferences (before, *other) + "Are you sure?"; + if (changes && permission.confirmed (question)) + context.tdb.update (*other); - ++count; + ++count; + } } } } diff --git a/src/tests/util.t.cpp b/src/tests/util.t.cpp index 260116866..4cb9d43ea 100644 --- a/src/tests/util.t.cpp +++ b/src/tests/util.t.cpp @@ -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 ->"); - 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"); + 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'.") != 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; } diff --git a/src/util.cpp b/src/util.cpp index 260379d64..615553e65 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -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 beforeAtts; + foreach (att, before) + beforeAtts.push_back (att->first); + + std::vector afterAtts; + foreach (att, after) + afterAtts.push_back (att->first); + + std::vector beforeOnly; + std::vector 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 (); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/util.h b/src/util.h index 2d59cf22d..422f3bc21 100644 --- a/src/util.h +++ b/src/util.h @@ -73,7 +73,8 @@ std::string expandPath (const std::string&); bool slurp (const std::string&, std::vector &, 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 ////////////////////////////////////////////////////////////////////////////////