mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
Bug #493
- Not a fix for the bug, but improved task consistency checking. The real fix can only be made when the Task::waiting status is abolished.
This commit is contained in:
parent
9e4786e4fe
commit
5d4cafb7a6
3 changed files with 52 additions and 32 deletions
32
src/Task.cpp
32
src/Task.cpp
|
@ -634,21 +634,21 @@ void Task::validate () const
|
|||
if (!has ("uuid") ||
|
||||
!has ("entry") ||
|
||||
!has ("description"))
|
||||
throw std::string ("A task must have a description in order to be valid."); // TODO i18n
|
||||
throw std::string ("A task must have a description in order to be valid.");
|
||||
|
||||
if (get ("description") == "") // No i18n
|
||||
throw std::string ("Cannot add a task that is blank, or contains <CR> or <LF> characters."); // TODO i18n
|
||||
throw std::string ("Cannot add a task that is blank, or contains <CR> or <LF> characters.");
|
||||
|
||||
if (has ("due"))
|
||||
{
|
||||
Date due (::atoi (get ("due").c_str ()));
|
||||
|
||||
// Verify until > due
|
||||
if (has ("until"))
|
||||
// Verify wait < due
|
||||
if (has ("wait"))
|
||||
{
|
||||
Date until (::atoi (get ("until").c_str ()));
|
||||
if (due > until)
|
||||
throw std::string ("An 'until' date must be after a 'due' date."); // TODO i18n
|
||||
Date wait (::atoi (get ("wait").c_str ()));
|
||||
if (wait > due)
|
||||
throw std::string ("A 'wait' date must be after a 'due' date.");
|
||||
}
|
||||
|
||||
Date entry (::atoi (get ("entry").c_str ()));
|
||||
|
@ -657,24 +657,36 @@ void Task::validate () const
|
|||
{
|
||||
Date start (::atoi (get ("start").c_str ()));
|
||||
if (entry > start)
|
||||
throw std::string ("A 'start' date must be after an 'entry' date."); // TODO i18n
|
||||
throw std::string ("A 'start' date must be after an 'entry' date.");
|
||||
}
|
||||
|
||||
if (has ("end"))
|
||||
{
|
||||
Date end (::atoi (get ("end").c_str ()));
|
||||
if (entry > end)
|
||||
throw std::string ("An 'end' date must be after an 'entry' date."); // TODO i18n
|
||||
throw std::string ("An 'end' date must be after an 'entry' date.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (has ("recur"))
|
||||
throw std::string ("You cannot specify a recurring task without a due date.");
|
||||
}
|
||||
|
||||
if (has ("until") && !has ("recur"))
|
||||
throw std::string ("You cannot specify an until date for a non-recurring task.");
|
||||
|
||||
// Recur durations must be valid.
|
||||
if (has ("recur"))
|
||||
{
|
||||
Duration d;
|
||||
if (! d.valid (get ("recur")))
|
||||
throw std::string ("A recurrence value must be valid."); // TODO i18n
|
||||
throw std::string ("A recurrence value must be valid.");
|
||||
}
|
||||
|
||||
if (has ("wait") &&
|
||||
getStatus () == Task::recurring)
|
||||
throw std::string ("You cannot create a task that is both waiting and recurring.");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -95,20 +95,6 @@ int handleAdd (std::string &outs)
|
|||
foreach (tag, context.tagAdditions)
|
||||
context.task.addTag (*tag);
|
||||
|
||||
// Perform some logical consistency checks.
|
||||
if (context.task.has ("wait") &&
|
||||
context.task.has ("due") &&
|
||||
Date (context.task.get ("due")) < Date (context.task.get ("wait")))
|
||||
context.footnote ("Warning: the wait date falls after the due date.");
|
||||
|
||||
if (context.task.has ("recur") &&
|
||||
!context.task.has ("due"))
|
||||
throw std::string ("You cannot specify a recurring task without a due date.");
|
||||
|
||||
if (context.task.has ("until") &&
|
||||
!context.task.has ("recur"))
|
||||
throw std::string ("You cannot specify an until date for a non-recurring task.");
|
||||
|
||||
// Must load pending to resolve dependencies, and to provide a new ID.
|
||||
context.tdb.lock (context.config.getBoolean ("locking"));
|
||||
|
||||
|
@ -648,6 +634,7 @@ void handleMerge (std::string& outs)
|
|||
|
||||
std::string autopush = context.config.get ("merge.autopush");
|
||||
|
||||
// TODO Task accepts many different values for "yes". Try Config::getBoolean.
|
||||
if ( ((autopush == "ask") && (confirm ("Do you want to push the changes to the database you merged from?")) )
|
||||
|| (autopush == "yes") )
|
||||
{
|
||||
|
@ -893,7 +880,7 @@ int handleShow (std::string &outs)
|
|||
"complete.all.projects complete.all.tags search.case.sensitive hooks "
|
||||
"active.indicator tag.indicator recurrence.indicator recurrence.limit "
|
||||
"list.all.projects list.all.tags undo.style verbose rule.precedence.color "
|
||||
"merge.autopush "
|
||||
"merge.autopush merge.default.uri pull.default.uri "
|
||||
#ifdef FEATURE_SHELL
|
||||
"shell.prompt "
|
||||
#endif
|
||||
|
@ -1542,6 +1529,9 @@ int handleDone (std::string &outs)
|
|||
// Change status.
|
||||
task->setStatus (Task::completed);
|
||||
|
||||
// Only allow valid tasks.
|
||||
task->validate ();
|
||||
|
||||
if (taskDiff (before, *task))
|
||||
{
|
||||
if (context.hooks.trigger ("pre-completed", *task))
|
||||
|
@ -1696,6 +1686,9 @@ int handleModify (std::string &outs)
|
|||
|
||||
if (taskDiff (before, *other))
|
||||
{
|
||||
// Only allow valid tasks.
|
||||
other->validate ();
|
||||
|
||||
if (changes && permission.confirmed (before, taskDifferences (before, *other) + "Proceed with change?"))
|
||||
{
|
||||
// TODO Are dependencies being explicitly removed?
|
||||
|
@ -1773,6 +1766,9 @@ int handleAppend (std::string &outs)
|
|||
|
||||
if (taskDiff (before, *other))
|
||||
{
|
||||
// Only allow valid tasks.
|
||||
other->validate ();
|
||||
|
||||
if (changes && permission.confirmed (before, taskDifferences (before, *other) + "Proceed with change?"))
|
||||
{
|
||||
context.tdb.update (*other);
|
||||
|
@ -1852,6 +1848,9 @@ int handlePrepend (std::string &outs)
|
|||
|
||||
if (taskDiff (before, *other))
|
||||
{
|
||||
// Only allow valid tasks.
|
||||
other->validate ();
|
||||
|
||||
if (changes && permission.confirmed (before, taskDifferences (before, *other) + "Are you sure?"))
|
||||
{
|
||||
context.tdb.update (*other);
|
||||
|
@ -1937,6 +1936,9 @@ int handleDuplicate (std::string &outs)
|
|||
sprintf (entryTime, "%u", (unsigned int) time (NULL));
|
||||
dup.set ("entry", entryTime);
|
||||
|
||||
// Only allow valid tasks.
|
||||
dup.validate ();
|
||||
|
||||
context.tdb.add (dup);
|
||||
|
||||
if (context.config.getBoolean ("echo.command"))
|
||||
|
@ -2298,6 +2300,9 @@ int handleAnnotate (std::string &outs)
|
|||
|
||||
if (taskDiff (before, *task))
|
||||
{
|
||||
// Only allow valid tasks.
|
||||
task->validate ();
|
||||
|
||||
if (permission.confirmed (before, taskDifferences (before, *task) + "Proceed with change?"))
|
||||
{
|
||||
context.tdb.update (*task);
|
||||
|
@ -2393,6 +2398,9 @@ int handleDenotate (std::string &outs)
|
|||
|
||||
if (taskDiff (before, *task))
|
||||
{
|
||||
// Only allow valid tasks.
|
||||
task->validate ();
|
||||
|
||||
if (permission.confirmed (before, taskDifferences (before, *task) + "Proceed with change?"))
|
||||
{
|
||||
context.tdb.update (*task);
|
||||
|
|
|
@ -76,7 +76,7 @@ like ($output, qr/tomorrow/ms, 'waiting task visible when specifically queried')
|
|||
|
||||
# Message is 'Warning: the wait date falls after the due date.'
|
||||
$output = qx{../task rc:wait.rc add Complain due:today wait:tomorrow};
|
||||
like ($output, qr/wait\sdate\sfalls/ms, 'warning on wait after due');
|
||||
like ($output, qr/A 'wait' date must be after a 'due' date\./, 'error on wait after due');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue