Dependencies
- Supports new "depends" attribute. - Supports "task <id> depends:1,2". - Supports "task <id> depends:-1,-2". - Supports id <--> uuid mapping in TDB.
This commit is contained in:
@@ -63,6 +63,7 @@ static const char* modifiableNames[] =
|
|||||||
"recur",
|
"recur",
|
||||||
"until",
|
"until",
|
||||||
"wait",
|
"wait",
|
||||||
|
"depends",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Synonyms on the same line.
|
// Synonyms on the same line.
|
||||||
|
|||||||
26
src/TDB.cpp
26
src/TDB.cpp
@@ -304,6 +304,10 @@ int TDB::loadPending (std::vector <Task>& tasks, Filter& filter)
|
|||||||
task.id = mId++;
|
task.id = mId++;
|
||||||
|
|
||||||
mPending.push_back (task);
|
mPending.push_back (task);
|
||||||
|
|
||||||
|
// Maintain mapping for ease of link/dependency resolution.
|
||||||
|
mI2U[task.id] = task.get ("uuid");
|
||||||
|
mU2I[task.get ("uuid")] = task.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
++line_number;
|
++line_number;
|
||||||
@@ -425,6 +429,8 @@ int TDB::loadCompleted (std::vector <Task>& tasks, Filter& filter)
|
|||||||
void TDB::add (const Task& task)
|
void TDB::add (const Task& task)
|
||||||
{
|
{
|
||||||
mNew.push_back (task);
|
mNew.push_back (task);
|
||||||
|
mI2U[task.id] = task.get ("uuid");
|
||||||
|
mU2I[task.get ("uuid")] = task.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -1425,6 +1431,26 @@ void TDB::merge (const std::string& mergeFile)
|
|||||||
mods.clear();
|
mods.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::string TDB::uuid (int id) const
|
||||||
|
{
|
||||||
|
std::map <int, std::string>::const_iterator i;
|
||||||
|
if ((i = mI2U.find (id)) != mI2U.end ())
|
||||||
|
return i->second;
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int TDB::id (const std::string& uuid) const
|
||||||
|
{
|
||||||
|
std::map <std::string, int>::const_iterator i;
|
||||||
|
if ((i = mU2I.find (uuid)) != mU2I.end ())
|
||||||
|
return i->second;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
FILE* TDB::openAndLock (const std::string& file)
|
FILE* TDB::openAndLock (const std::string& file)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ public:
|
|||||||
void undo ();
|
void undo ();
|
||||||
void merge (const std::string&);
|
void merge (const std::string&);
|
||||||
|
|
||||||
|
std::string uuid (int) const;
|
||||||
|
int id (const std::string&) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FILE* openAndLock (const std::string&);
|
FILE* openAndLock (const std::string&);
|
||||||
void writeUndo (const Task&, FILE*);
|
void writeUndo (const Task&, FILE*);
|
||||||
@@ -79,6 +82,9 @@ private:
|
|||||||
std::vector <Task> mCompleted; // Contents of pending.data
|
std::vector <Task> mCompleted; // Contents of pending.data
|
||||||
std::vector <Task> mNew; // Uncommitted new tasks
|
std::vector <Task> mNew; // Uncommitted new tasks
|
||||||
std::vector <Task> mModified; // Uncommitted modified tasks
|
std::vector <Task> mModified; // Uncommitted modified tasks
|
||||||
|
|
||||||
|
std::map <int, std::string> mI2U; // ID -> UUID map
|
||||||
|
std::map <std::string, int> mU2I; // UUID -> ID map
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
66
src/Task.cpp
66
src/Task.cpp
@@ -467,6 +467,72 @@ void Task::removeAnnotations ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Task::addDependency (int id)
|
||||||
|
{
|
||||||
|
std::string uuid = context.tdb.uuid (id);
|
||||||
|
if (uuid == "")
|
||||||
|
{
|
||||||
|
std::stringstream s;
|
||||||
|
s << "Could not create a dependency on task " << id << " - not found.";
|
||||||
|
throw s.str ();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string depends = get ("depends");
|
||||||
|
if (depends.length ())
|
||||||
|
{
|
||||||
|
if (depends.find (uuid) == std::string::npos)
|
||||||
|
set ("depends", depends + "," + uuid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
set ("depends", uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Task::removeDependency (int id)
|
||||||
|
{
|
||||||
|
std::string uuid = context.tdb.uuid (id);
|
||||||
|
if (uuid == "")
|
||||||
|
{
|
||||||
|
std::stringstream s;
|
||||||
|
s << "Could not find a UUID for id " << id << ".";
|
||||||
|
throw s.str ();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector <std::string> deps;
|
||||||
|
split (deps, get ("depends"), ',');
|
||||||
|
|
||||||
|
std::vector <std::string>::iterator i;
|
||||||
|
i = std::find (deps.begin (), deps.end (), uuid);
|
||||||
|
if (i != deps.end ())
|
||||||
|
{
|
||||||
|
deps.erase (i);
|
||||||
|
std::string combined;
|
||||||
|
join (combined, ",", deps);
|
||||||
|
set ("depends", combined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Task::getDependencies (std::vector <int>& all) const
|
||||||
|
{
|
||||||
|
std::vector <std::string> deps;
|
||||||
|
split (deps, get ("depends"), ',');
|
||||||
|
|
||||||
|
all.clear ();
|
||||||
|
|
||||||
|
std::vector <std::string>::iterator i;
|
||||||
|
for (i = deps.begin (); i != deps.end (); ++i)
|
||||||
|
all.push_back (context.tdb.id (*i));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Task::getDependencies (std::vector <std::string>& all) const
|
||||||
|
{
|
||||||
|
all.clear ();
|
||||||
|
split (all, get ("depends"), ',');
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
int Task::getTagCount ()
|
int Task::getTagCount ()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -73,6 +73,11 @@ public:
|
|||||||
void addAnnotation (const std::string&);
|
void addAnnotation (const std::string&);
|
||||||
void removeAnnotations ();
|
void removeAnnotations ();
|
||||||
|
|
||||||
|
void addDependency (int);
|
||||||
|
void removeDependency (int);
|
||||||
|
void getDependencies (std::vector <int>&) const;
|
||||||
|
void getDependencies (std::vector <std::string>&) const;
|
||||||
|
|
||||||
void validate () const;
|
void validate () const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -99,6 +99,8 @@ int handleAdd (std::string &outs)
|
|||||||
!context.task.has ("recur"))
|
!context.task.has ("recur"))
|
||||||
throw std::string ("You cannot specify an until date for a non-recurring task.");
|
throw std::string ("You cannot specify an until date for a non-recurring task.");
|
||||||
|
|
||||||
|
// TODO Resolve dependencies.
|
||||||
|
|
||||||
// Only valid tasks can be added.
|
// Only valid tasks can be added.
|
||||||
context.task.validate ();
|
context.task.validate ();
|
||||||
|
|
||||||
@@ -164,6 +166,8 @@ int handleLog (std::string &outs)
|
|||||||
foreach (tag, context.tagAdditions)
|
foreach (tag, context.tagAdditions)
|
||||||
context.task.addTag (*tag);
|
context.task.addTag (*tag);
|
||||||
|
|
||||||
|
// TODO Resolve dependencies.
|
||||||
|
|
||||||
// Only valid tasks can be added.
|
// Only valid tasks can be added.
|
||||||
context.task.validate ();
|
context.task.validate ();
|
||||||
|
|
||||||
@@ -2231,7 +2235,25 @@ int deltaAttributes (Task& task)
|
|||||||
task.setStatus (Task::waiting);
|
task.setStatus (Task::waiting);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (att->second.value () == "")
|
// Modifying dependencies requires adding/removing uuids.
|
||||||
|
else if (att->second.name () == "depends")
|
||||||
|
{
|
||||||
|
std::vector <std::string> deps;
|
||||||
|
split (deps, att->second.value (), ',');
|
||||||
|
|
||||||
|
std::vector <std::string>::iterator i;
|
||||||
|
for (i = deps.begin (); i != deps.end (); i++)
|
||||||
|
{
|
||||||
|
int id = atoi (i->c_str ());
|
||||||
|
if (id < 0)
|
||||||
|
task.removeDependency (-id);
|
||||||
|
else
|
||||||
|
task.addDependency (id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now the generalized handling.
|
||||||
|
else if (att->second.value () == "")
|
||||||
task.remove (att->second.name ());
|
task.remove (att->second.name ());
|
||||||
else
|
else
|
||||||
// One of the few places where the compound attribute name is used.
|
// One of the few places where the compound attribute name is used.
|
||||||
|
|||||||
Reference in New Issue
Block a user