mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +02:00
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:
parent
8e8f5935b3
commit
6e4f60c4fe
4 changed files with 70 additions and 23 deletions
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
48
src/util.cpp
48
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 <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 ();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -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
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue