mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +02:00
Shadow File Rewrite
- No longer writes shadow files based on TDB onChange trigger. - Addressed bug whereby adding a recurring task trigger a shadow file rewrite, which in turn performs trigger another rewrite...
This commit is contained in:
parent
6e956b45ad
commit
1e70400143
5 changed files with 72 additions and 108 deletions
20
src/TDB.cpp
20
src/TDB.cpp
|
@ -308,7 +308,6 @@ bool TDB::overwritePending (std::vector <T>& all)
|
||||||
fputs (it->compose ().c_str (), out);
|
fputs (it->compose ().c_str (), out);
|
||||||
|
|
||||||
fclose (out);
|
fclose (out);
|
||||||
dbChanged ();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,7 +328,6 @@ bool TDB::writePending (const T& t)
|
||||||
fputs (t.compose ().c_str (), out);
|
fputs (t.compose ().c_str (), out);
|
||||||
|
|
||||||
fclose (out);
|
fclose (out);
|
||||||
dbChanged ();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,8 +348,6 @@ bool TDB::writeCompleted (const T& t)
|
||||||
fputs (t.compose ().c_str (), out);
|
fputs (t.compose ().c_str (), out);
|
||||||
|
|
||||||
fclose (out);
|
fclose (out);
|
||||||
// Note: No call to dbChanged here because this call never occurs by itself.
|
|
||||||
// It is always accompanied by an overwritePending call.
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,20 +432,4 @@ int TDB::nextId ()
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void TDB::onChange (void (*callback)())
|
|
||||||
{
|
|
||||||
if (callback)
|
|
||||||
mOnChange.push_back (callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Iterate over callbacks.
|
|
||||||
void TDB::dbChanged ()
|
|
||||||
{
|
|
||||||
foreach (i, mOnChange)
|
|
||||||
if (*i)
|
|
||||||
(**i) ();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
|
@ -51,21 +51,17 @@ public:
|
||||||
int gc ();
|
int gc ();
|
||||||
int nextId ();
|
int nextId ();
|
||||||
|
|
||||||
void onChange (void (*)());
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool lock (FILE*) const;
|
bool lock (FILE*) const;
|
||||||
bool overwritePending (std::vector <T>&);
|
bool overwritePending (std::vector <T>&);
|
||||||
bool writePending (const T&);
|
bool writePending (const T&);
|
||||||
bool writeCompleted (const T&);
|
bool writeCompleted (const T&);
|
||||||
bool readLockedFile (const std::string&, std::vector <std::string>&) const;
|
bool readLockedFile (const std::string&, std::vector <std::string>&) const;
|
||||||
void dbChanged ();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string mPendingFile;
|
std::string mPendingFile;
|
||||||
std::string mCompletedFile;
|
std::string mCompletedFile;
|
||||||
int mId;
|
int mId;
|
||||||
std::vector <void (*)()> mOnChange;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2260,6 +2260,7 @@ std::string handleCustomReport (
|
||||||
// Load all pending tasks.
|
// Load all pending tasks.
|
||||||
std::vector <T> tasks;
|
std::vector <T> tasks;
|
||||||
tdb.allPendingT (tasks);
|
tdb.allPendingT (tasks);
|
||||||
|
handleRecurrence (tdb, tasks);
|
||||||
|
|
||||||
// Apply filters.
|
// Apply filters.
|
||||||
{
|
{
|
||||||
|
|
151
src/task.cpp
151
src/task.cpp
|
@ -46,11 +46,6 @@
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Globals for exclusive use by callback function.
|
|
||||||
static TDB* gTdb = NULL;
|
|
||||||
static Config* gConf = NULL;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
static void shortUsage (Config& conf)
|
static void shortUsage (Config& conf)
|
||||||
{
|
{
|
||||||
|
@ -289,7 +284,6 @@ int main (int argc, char** argv)
|
||||||
// Load the config file from the home directory. If the file cannot be
|
// Load the config file from the home directory. If the file cannot be
|
||||||
// found, offer to create a sample one.
|
// found, offer to create a sample one.
|
||||||
Config conf;
|
Config conf;
|
||||||
gConf = &conf;
|
|
||||||
loadConfFile (argc, argv, conf);
|
loadConfFile (argc, argv, conf);
|
||||||
|
|
||||||
// When redirecting output to a file, do not use color, curses.
|
// When redirecting output to a file, do not use color, curses.
|
||||||
|
@ -300,11 +294,10 @@ int main (int argc, char** argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
TDB tdb;
|
TDB tdb;
|
||||||
gTdb = &tdb;
|
|
||||||
std::string dataLocation = expandPath (conf.get ("data.location"));
|
std::string dataLocation = expandPath (conf.get ("data.location"));
|
||||||
tdb.dataDirectory (dataLocation);
|
tdb.dataDirectory (dataLocation);
|
||||||
|
|
||||||
// Set up TDB callback.
|
// Check for silly shadow file settings.
|
||||||
std::string shadowFile = expandPath (conf.get ("shadow.file"));
|
std::string shadowFile = expandPath (conf.get ("shadow.file"));
|
||||||
if (shadowFile != "")
|
if (shadowFile != "")
|
||||||
{
|
{
|
||||||
|
@ -315,8 +308,6 @@ int main (int argc, char** argv)
|
||||||
if (shadowFile == dataLocation + "/completed.data")
|
if (shadowFile == dataLocation + "/completed.data")
|
||||||
throw std::string ("Configuration variable 'shadow.file' is set to "
|
throw std::string ("Configuration variable 'shadow.file' is set to "
|
||||||
"overwrite your completed tasks. Please change it.");
|
"overwrite your completed tasks. Please change it.");
|
||||||
|
|
||||||
tdb.onChange (&onChangeCallback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << runTaskCommand (argc, argv, tdb, conf);
|
std::cout << runTaskCommand (argc, argv, tdb, conf);
|
||||||
|
@ -383,12 +374,12 @@ void nag (TDB& tdb, T& task, Config& conf)
|
||||||
pri = priority[0];
|
pri = priority[0];
|
||||||
|
|
||||||
// General form is "if there are no more deserving tasks", suppress the nag.
|
// General form is "if there are no more deserving tasks", suppress the nag.
|
||||||
std::cout << "# isOverdue = " << (isOverdue ? "true" : "false") << std::endl;
|
std::cout << "# task.isOverdue = " << (isOverdue ? "true" : "false") << std::endl;
|
||||||
std::cout << "# pri = " << pri << std::endl;
|
std::cout << "# task.pri = " << pri << std::endl;
|
||||||
std::cout << "# overdue = " << overdue << std::endl;
|
std::cout << "# task.overdue = " << overdue << std::endl;
|
||||||
std::cout << "# high = " << high << std::endl;
|
std::cout << "# pending.high = " << high << std::endl;
|
||||||
std::cout << "# medium = " << medium << std::endl;
|
std::cout << "# pending.medium = " << medium << std::endl;
|
||||||
std::cout << "# low = " << low << std::endl;
|
std::cout << "# pending.low = " << low << std::endl;
|
||||||
|
|
||||||
if (isOverdue ) return;
|
if (isOverdue ) return;
|
||||||
if (pri == 'H' && !overdue ) return;
|
if (pri == 'H' && !overdue ) return;
|
||||||
|
@ -711,51 +702,45 @@ void updateRecurrenceMask (
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Using gTdb and gConf, generate a report.
|
void updateShadowFile (TDB& tdb, Config& conf)
|
||||||
void onChangeCallback ()
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (gConf && gTdb)
|
// Determine if shadow file is enabled.
|
||||||
|
std::string shadowFile = expandPath (conf.get ("shadow.file"));
|
||||||
|
if (shadowFile != "")
|
||||||
{
|
{
|
||||||
// Determine if shadow file is enabled.
|
std::string oldCurses = conf.get ("curses");
|
||||||
std::string shadowFile = expandPath (gConf->get ("shadow.file"));
|
std::string oldColor = conf.get ("color");
|
||||||
if (shadowFile != "")
|
conf.set ("curses", "off");
|
||||||
|
conf.set ("color", "off");
|
||||||
|
|
||||||
|
// Run report. Use shadow.command, using default.command as a fallback
|
||||||
|
// with "list" as a default.
|
||||||
|
std::string command = conf.get ("shadow.command",
|
||||||
|
conf.get ("default.command", "list"));
|
||||||
|
std::vector <std::string> args;
|
||||||
|
split (args, command, ' ');
|
||||||
|
std::string result = runTaskCommand (args, tdb, conf);
|
||||||
|
|
||||||
|
std::ofstream out (shadowFile.c_str ());
|
||||||
|
if (out.good ())
|
||||||
{
|
{
|
||||||
std::string oldCurses = gConf->get ("curses");
|
out << result;
|
||||||
std::string oldColor = gConf->get ("color");
|
out.close ();
|
||||||
gConf->set ("curses", "off");
|
|
||||||
gConf->set ("color", "off");
|
|
||||||
|
|
||||||
// Run report. Use shadow.command, using default.command as a fallback
|
|
||||||
// with "list" as a default.
|
|
||||||
std::string command = gConf->get ("shadow.command",
|
|
||||||
gConf->get ("default.command", "list"));
|
|
||||||
std::vector <std::string> args;
|
|
||||||
split (args, command, ' ');
|
|
||||||
std::string result = runTaskCommand (args, *gTdb, *gConf);
|
|
||||||
|
|
||||||
std::ofstream out (shadowFile.c_str ());
|
|
||||||
if (out.good ())
|
|
||||||
{
|
|
||||||
out << result;
|
|
||||||
out.close ();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw std::string ("Could not write file '") + shadowFile + "'";
|
|
||||||
|
|
||||||
gConf->set ("curses", oldCurses);
|
|
||||||
gConf->set ("color", oldColor);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw std::string ("No specified shadow file '") + shadowFile + "'.";
|
throw std::string ("Could not write file '") + shadowFile + "'";
|
||||||
|
|
||||||
// Optionally display a notification that the shadow file was updated.
|
conf.set ("curses", oldCurses);
|
||||||
if (gConf->get (std::string ("shadow.notify"), false))
|
conf.set ("color", oldColor);
|
||||||
std::cout << "[Shadow file '" << shadowFile << "' updated]" << std::endl;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw std::string ("Internal error (TDB/Config).");
|
throw std::string ("No specified shadow file '") + shadowFile + "'.";
|
||||||
|
|
||||||
|
// Optionally display a notification that the shadow file was updated.
|
||||||
|
if (conf.get (std::string ("shadow.notify"), false))
|
||||||
|
std::cout << "[Shadow file '" << shadowFile << "' updated]" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (std::string& error)
|
catch (std::string& error)
|
||||||
|
@ -775,13 +760,14 @@ std::string runTaskCommand (
|
||||||
char** argv,
|
char** argv,
|
||||||
TDB& tdb,
|
TDB& tdb,
|
||||||
Config& conf,
|
Config& conf,
|
||||||
bool gc /* = true */)
|
bool gc /* = true */,
|
||||||
|
bool shadow /* = true */)
|
||||||
{
|
{
|
||||||
std::vector <std::string> args;
|
std::vector <std::string> args;
|
||||||
for (int i = 1; i < argc; ++i)
|
for (int i = 1; i < argc; ++i)
|
||||||
args.push_back (argv[i]);
|
args.push_back (argv[i]);
|
||||||
|
|
||||||
return runTaskCommand (args, tdb, conf, gc);
|
return runTaskCommand (args, tdb, conf, gc, shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -789,7 +775,8 @@ std::string runTaskCommand (
|
||||||
std::vector <std::string>& args,
|
std::vector <std::string>& args,
|
||||||
TDB& tdb,
|
TDB& tdb,
|
||||||
Config& conf,
|
Config& conf,
|
||||||
bool gc /* = false */)
|
bool gc /* = false */,
|
||||||
|
bool shadow /* = false */)
|
||||||
{
|
{
|
||||||
// If argc == 1 and the default.command configuration variable is set,
|
// If argc == 1 and the default.command configuration variable is set,
|
||||||
// then use that, otherwise stick with argc/argv.
|
// then use that, otherwise stick with argc/argv.
|
||||||
|
@ -810,34 +797,34 @@ std::string runTaskCommand (
|
||||||
|
|
||||||
std::string out = "";
|
std::string out = "";
|
||||||
|
|
||||||
if (command == "" && task.getId ()) { handleModify (tdb, task, conf ); }
|
if (command == "" && task.getId ()) { handleModify (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); }
|
||||||
else if (command == "add") { handleAdd (tdb, task, conf ); }
|
else if (command == "add") { handleAdd (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); }
|
||||||
else if (command == "done") { handleDone (tdb, task, conf ); }
|
else if (command == "done") { handleDone (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); }
|
||||||
else if (command == "export") { handleExport (tdb, task, conf ); }
|
else if (command == "export") { handleExport (tdb, task, conf ); }
|
||||||
else if (command == "projects") { out = handleProjects (tdb, task, conf ); }
|
else if (command == "projects") { out = handleProjects (tdb, task, conf ); }
|
||||||
else if (command == "tags") { out = handleTags (tdb, task, conf ); }
|
else if (command == "tags") { out = handleTags (tdb, task, conf ); }
|
||||||
else if (command == "info") { out = handleInfo (tdb, task, conf ); }
|
else if (command == "info") { out = handleInfo (tdb, task, conf ); }
|
||||||
else if (command == "undelete") { out = handleUndelete (tdb, task, conf ); }
|
else if (command == "undelete") { out = handleUndelete (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); }
|
||||||
else if (command == "delete") { out = handleDelete (tdb, task, conf ); }
|
else if (command == "delete") { out = handleDelete (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); }
|
||||||
else if (command == "start") { out = handleStart (tdb, task, conf ); }
|
else if (command == "start") { out = handleStart (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); }
|
||||||
else if (command == "stop") { out = handleStop (tdb, task, conf ); }
|
else if (command == "stop") { out = handleStop (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); }
|
||||||
else if (command == "undo") { out = handleUndo (tdb, task, conf ); }
|
else if (command == "undo") { out = handleUndo (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); }
|
||||||
else if (command == "stats") { out = handleReportStats (tdb, task, conf ); }
|
else if (command == "stats") { out = handleReportStats (tdb, task, conf ); }
|
||||||
else if (command == "completed") { if (gc) tdb.gc (); out = handleCompleted (tdb, task, conf ); } // TODO replace with Custom
|
else if (command == "completed") { if (gc) tdb.gc (); out = handleCompleted (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); } // TODO replace with Custom
|
||||||
else if (command == "summary") { if (gc) tdb.gc (); out = handleReportSummary (tdb, task, conf ); }
|
else if (command == "summary") { if (gc) tdb.gc (); out = handleReportSummary (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); }
|
||||||
else if (command == "next") { if (gc) tdb.gc (); out = handleReportNext (tdb, task, conf ); } // TODO replace with Custom
|
else if (command == "next") { if (gc) tdb.gc (); out = handleReportNext (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); } // TODO replace with Custom
|
||||||
else if (command == "history") { if (gc) tdb.gc (); out = handleReportHistory (tdb, task, conf ); }
|
else if (command == "history") { if (gc) tdb.gc (); out = handleReportHistory (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); }
|
||||||
else if (command == "ghistory") { if (gc) tdb.gc (); out = handleReportGHistory (tdb, task, conf ); }
|
else if (command == "ghistory") { if (gc) tdb.gc (); out = handleReportGHistory (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); }
|
||||||
else if (command == "calendar") { if (gc) tdb.gc (); out = handleReportCalendar (tdb, task, conf ); }
|
else if (command == "calendar") { if (gc) tdb.gc (); out = handleReportCalendar (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); }
|
||||||
else if (command == "active") { if (gc) tdb.gc (); out = handleReportActive (tdb, task, conf ); } // TODO replace with Custom
|
else if (command == "active") { if (gc) tdb.gc (); out = handleReportActive (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); } // TODO replace with Custom
|
||||||
else if (command == "overdue") { if (gc) tdb.gc (); out = handleReportOverdue (tdb, task, conf ); } // TODO replace with Custom
|
else if (command == "overdue") { if (gc) tdb.gc (); out = handleReportOverdue (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); } // TODO replace with Custom
|
||||||
else if (command == "oldest") { if (gc) tdb.gc (); out = handleReportOldest (tdb, task, conf ); } // TODO replace with Custom
|
else if (command == "oldest") { if (gc) tdb.gc (); out = handleReportOldest (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); } // TODO replace with Custom
|
||||||
else if (command == "newest") { if (gc) tdb.gc (); out = handleReportNewest (tdb, task, conf ); } // TODO replace with Custom
|
else if (command == "newest") { if (gc) tdb.gc (); out = handleReportNewest (tdb, task, conf ); if (shadow) updateShadowFile (tdb, conf); } // TODO replace with Custom
|
||||||
else if (command == "colors") { out = handleColor ( conf ); }
|
else if (command == "colors") { out = handleColor ( conf ); }
|
||||||
else if (command == "version") { out = handleVersion ( conf ); }
|
else if (command == "version") { out = handleVersion ( conf ); }
|
||||||
else if (command == "help") { longUsage ( conf ); }
|
else if (command == "help") { longUsage ( conf ); }
|
||||||
else if (isCustomReport (command)) { if (gc) tdb.gc (); out = handleCustomReport (tdb, task, conf, command); } // New Custom reports
|
else if (isCustomReport (command)) { if (gc) tdb.gc (); out = handleCustomReport (tdb, task, conf, command); if (shadow) updateShadowFile (tdb, conf); } // New Custom reports
|
||||||
else { shortUsage ( conf ); }
|
else { shortUsage ( conf ); }
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,8 +69,8 @@ bool generateDueDates (T&, std::vector <Date>&);
|
||||||
Date getNextRecurrence (Date&, std::string&);
|
Date getNextRecurrence (Date&, std::string&);
|
||||||
void updateRecurrenceMask (TDB&, std::vector <T>&, T&);
|
void updateRecurrenceMask (TDB&, std::vector <T>&, T&);
|
||||||
void onChangeCallback ();
|
void onChangeCallback ();
|
||||||
std::string runTaskCommand (int, char**, TDB&, Config&, bool gc = true);
|
std::string runTaskCommand (int, char**, TDB&, Config&, bool gc = true, bool shadow = true);
|
||||||
std::string runTaskCommand (std::vector <std::string>&, TDB&, Config&, bool gc = false);
|
std::string runTaskCommand (std::vector <std::string>&, TDB&, Config&, bool gc = false, bool shadow = false);
|
||||||
|
|
||||||
// command.cpp
|
// command.cpp
|
||||||
void handleAdd (TDB&, T&, Config&);
|
void handleAdd (TDB&, T&, Config&);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue