More work with notes; refactored actions; added tests

This commit is contained in:
Mike Dvorkin
2010-08-14 19:17:04 -07:00
parent 3086148a1b
commit 7ecace633f
15 changed files with 405 additions and 346 deletions

View File

@@ -5,11 +5,9 @@
static void action_list()
{
PPager ppager;
pit_db_load();
if (actions->number_of_records > 0) {
ppager = pit_pager_initialize(PAGER_ACTION, 0, actions->number_of_records);
PPager ppager = pit_pager_initialize(PAGER_ACTION, 0, actions->number_of_records);
for_each_action(pa) {
pit_pager_print(ppager, (char *)pa);
}
@@ -17,17 +15,14 @@ static void action_list()
}
}
void pit_action(int id, char *subject, char *message)
void pit_action(PAction pa)
{
static Action action = { 0 };
action.subject_id = id;
strncpy(action.subject, subject, sizeof(action.subject) - 1);
strncpy(action.username, current_user(), sizeof(action.username) - 1);
strncpy(action.message, message, sizeof(action.message) - 1);
pit_table_insert(actions, (char *)&action);
if (strcmp(subject, "pit")) puts(message);
if (pa) {
strncpy(pa->username, current_user(), sizeof(pa->username) - 1);
pit_table_insert(actions, (char *)pa);
if (pa->project_id || pa->task_id || pa->note_id)
puts(pa->message);
}
}
void pit_log(char *argv[])

View File

@@ -110,13 +110,15 @@ void pit_db_load() {
}
void pit_db_initialize() {
Action a = { 0 };
projects = pit_table_initialize(sizeof(Project), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
tasks = pit_table_initialize(sizeof(Task), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
notes = pit_table_initialize(sizeof(Note), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
actions = pit_table_initialize(sizeof(Action), TABLE_HAS_CREATED_AT);
pit_action(0, "pit", "Initialized pit");
strcpy(a.message, "Initialized pit");
pit_action(&a);
pit_db_save();
}

View File

@@ -3,85 +3,40 @@
#include <stdio.h>
#include "pit.h"
/*
** CREATING NOTES:
** pit note -c message
**
** EDITING NOTES:
** pit note -e [number] message
**
** DELETING NOTES:
** pit note -d [number]
**
** LISTING NOTES:
** pit note
*/
static int note_find_current(int id, PProject *ppp)
static int note_find_current(int id, PNote *ppn)
{
// if (id) {
// *ppp = (PProject)pit_table_find(notes, id);
// if (!*ppp) die("could not find note %d", id);
// } else {
// *ppp = (PProject)pit_table_current(notes);
// if (!*ppp) die("could not find current note");
// }
// return *ppp ? (*(PProject *)ppp)->id : 0;
return 0;
}
static void note_log_create(PNote pn, POptions po)
{
char str[256];
sprintf(str, "created note %d: %s (task %d)", pn->id, po->note.message, pn->task_id);
pit_action(pn->id, "note", str);
}
static void note_log_update(PNote pn, POptions po)
{
// char str[256];
// bool empty = TRUE;
//
// sprintf(str, "updated note %d:", pn->id);
// if (po->note.name) {
// sprintf(str + strlen(str), " (name: %s", po->note.name);
// empty = FALSE;
// } else {
// sprintf(str + strlen(str), " %s (", pn->name);
// }
// if (po->note.status) {
// sprintf(str + strlen(str), "%sstatus: %s)", (empty ? "" : ", "), po->note.status);
// }
// strcat(str, ")");
// pit_action(pn->id, "note", str);
}
static void note_log_delete(int id, char *name, int number_of_tasks)
{
// char str[256];
//
// sprintf(str, "deleted note %d: %s", id, name);
// if (number_of_tasks > 0) {
// sprintf(str + strlen(str), " with %d task%s", number_of_tasks, (number_of_tasks == 1 ? "" : "s"));
// }
// pit_action(id, "note", str);
}
void pit_note_list(PTask pt)
{
if (!notes) pit_db_load();
if (notes->number_of_records > 0) {
PPager ppager = pit_pager_initialize(PAGER_NOTE, pt ? 4 : 0, notes->number_of_records);
if (!pt) pt = (PTask)pit_table_current(tasks);
for_each_note(pn) {
if (pt && pn->task_id != pt->id)
continue;
pit_pager_print(ppager, (char *)pn);
}
pit_pager_flush(ppager);
if (id) {
*ppn = (PNote)pit_table_find(notes, id);
if (!*ppn) die("could not find note %d", id);
} else {
*ppn = (PNote)pit_table_current(notes);
if (!*ppn) die("could not find current note");
}
return *ppn ? (*(PNote *)ppn)->id : 0;
}
static void note_log_create(PTask pt, PNote pn, POptions po)
{
Action a = { pt->project_id, pt->id, pn->id, { 0 } };
sprintf(a.message, "created note %d: %s (task %d)", pn->id, po->note.message, pn->task_id);
pit_action(&a);
}
static void note_log_update(PTask pt, PNote pn, POptions po)
{
Action a = { pt->project_id, pt->id, pn->id, { 0 } };
sprintf(a.message, "updated note %d: (message: %s, task %d)", pn->id, pn->message, pn->task_id);
pit_action(&a);
}
static void note_log_delete(int project_id, int task_id, int id, char *message)
{
Action a = { project_id, task_id, id, { 0 } };
sprintf(a.message, "deleted note %d: %s (task %d)", id, message, task_id);
pit_action(&a);
}
static void note_create(POptions po)
@@ -101,62 +56,89 @@ static void note_create(POptions po)
pn = (PNote)pit_table_insert(notes, (char *)&n);
pit_table_mark(notes, pn->id);
pt->number_of_notes++;
note_log_create(pn, po);
note_log_create(pt, pn, po);
pit_db_save();
}
}
static void note_update(int id, POptions po)
{
puts("note_update");
// PProject pp;
//
// pit_db_load();
// id = note_find_current(id, &pp);
//
// if (po->note.name) strncpy(pp->name, po->note.name, sizeof(pp->name) - 1);
// if (po->note.status) strncpy(pp->status, po->note.status, sizeof(pp->status) - 1);
// pit_table_mark(notes, pp->id);
//
// note_log_update(pp, po);
// pit_db_save();
PNote pn;
pit_db_load();
id = note_find_current(id, &pn);
strncpy(pn->message, po->note.message, sizeof(pn->message) - 1);
strncpy(pn->username, current_user(), sizeof(pn->username) - 1);
pit_table_mark(notes, pn->id);
note_log_update((PTask)pit_table_find(tasks, pn->task_id), pn, po);
pit_db_save();
}
/*
** A note could be deleted as standalone entity or as part of cascading task
** or project delete.
*/
void pit_note_delete(int id, PTask pt)
{
puts("note_delete");
// PProject pp;
//
// pit_db_load();
// id = note_find_current(id, &pp);
// /*
// ** Delete note tasks.
// */
// if (pp->number_of_tasks > 0) {
// for_each_task(pt) {
// if (pt->note_id == id) {
// pit_task_delete(pt->id, pp);
// --pt; /* Make the task pointer stay since it now points to the next task. */
// }
// }
// }
// /*
// ** Ready to delete the note itself. But first preserve the
// ** name and number of tasks since we need these bits for logging.
// */
// char *deleted_name = str2str(pp->name);
// int deleted_number_of_tasks = pp->number_of_tasks;
//
// pp = (PProject)pit_table_delete(notes, id);
// if (pp) {
// pit_table_mark(notes, 0); /* TODO: find better current note candidate. */
// note_log_delete(id, deleted_name, deleted_number_of_tasks);
// pit_db_save();
// } else {
// die("could not delete the note");
// }
PNote pn;
bool standalone = (pt == NULL);
if (standalone) pit_db_load();
id = note_find_current(id, &pn);
if (standalone) pt = (PTask)pit_table_find(tasks, pn->task_id);
if (pt) {
char *deleted_message = str2str(pn->message);
pn = (PNote)pit_table_delete(notes, id);
if (pn) {
pit_table_mark(notes, 0); /* TODO: find better current note candidate. */
note_log_delete(pt->project_id, pt->id, id, deleted_message);
if (standalone) {
pt->number_of_notes--;
pit_db_save();
}
free(deleted_message);
} else {
free(deleted_message);
die("could not delete note %d", id);
}
} else {
die("could not find task for note %d", id);
}
}
void pit_note_list(PTask pt)
{
if (!notes) pit_db_load();
if (notes->number_of_records > 0) {
PPager ppager = pit_pager_initialize(PAGER_NOTE, pt ? 4 : 0, notes->number_of_records);
if (!pt) pt = (PTask)pit_table_current(tasks);
for_each_note(pn) {
if (pt && pn->task_id != pt->id)
continue;
pit_pager_print(ppager, (char *)pn);
}
pit_pager_flush(ppager);
}
}
/*
** CREATING NOTES:
** pit note -c message
**
** EDITING NOTES:
** pit note -e [number] message
**
** DELETING NOTES:
** pit note -d [number]
**
** LISTING NOTES:
** pit note
*/
void pit_note(char *argv[])
{
char **arg = &argv[1];
@@ -175,11 +157,7 @@ void pit_note(char *argv[])
number = pit_arg_number(++arg, NULL);
if (!number) --arg;
opt.note.message = pit_arg_string(++arg, "note message");
if (is_zero((char *)&opt.note, sizeof(opt.note))) {
die("nothing to update");
} else {
note_update(number, &opt);
}
note_update(number, &opt);
break;
case 'd': /* pit note -d [number] */
number = pit_arg_number(++arg, NULL);

View File

@@ -44,8 +44,9 @@ typedef struct _Note {
} Note, *PNote;
typedef struct _Action {
int subject_id; /* Reference to the specific Project, Task, or Note. */
char subject[16]; /* Project, Task, or Note. */
int project_id; /* Project id (always set). */
int task_id; /* Task id (set for task or note related actions). */
int note_id; /* Note id (set for note related actions only). */
char username[32]; /* Who added the log message? */
char message[255]; /* Log message. */
time_t created_at; /* When log message was added? */

View File

@@ -36,7 +36,7 @@ static void print_projects(PPager ppager)
char **pentry;
char format[64];
sprintf(format, "%%c %%%dd: (%%-%ds) [%%-%ds] %%-%ds (%%d task%%s)\n",
sprintf(format, "%%c %%%dd: (%%-%ds) |%%-%ds| %%-%ds (%%d task%%s)\n",
ppager->max.project.id, ppager->max.project.username, ppager->max.project.status, ppager->max.project.name
);
for_each_entry(ppager, pentry) {
@@ -79,7 +79,7 @@ static void print_tasks_with_date(PPager ppager)
char **pentry;
char format[64];
sprintf(format, "%%%dc %%%dd: (%%-%ds) [%%-%ds] [%%-%ds] %%-%ds %%-%ds (%%d note%%s)\n",
sprintf(format, "%%%dc %%%dd: (%%-%ds) |%%-%ds| |%%-%ds| %%-%ds %%-%ds (%%d note%%s)\n",
ppager->indent, ppager->max.task.id, ppager->max.task.username, ppager->max.task.status, ppager->max.task.priority, ppager->max.task.date, ppager->max.task.name
);
for_each_entry(ppager, pentry) {
@@ -102,7 +102,7 @@ static void print_tasks_with_time(PPager ppager)
char **pentry;
char format[64];
sprintf(format, "%%%dc %%%dd: (%%-%ds) [%%-%ds] [%%-%ds] %%%ds %%-%ds (%%d note%%s)\n",
sprintf(format, "%%%dc %%%dd: (%%-%ds) |%%-%ds| |%%-%ds| %%%ds %%-%ds (%%d note%%s)\n",
ppager->indent, ppager->max.task.id, ppager->max.task.username, ppager->max.task.status, ppager->max.task.priority, ppager->max.task.time, ppager->max.task.name
);
for_each_entry(ppager, pentry) {
@@ -125,7 +125,7 @@ static void print_tasks_with_date_and_time(PPager ppager)
char **pentry;
char format[64];
sprintf(format, "%%%dc %%%dd: (%%-%ds) [%%-%ds] [%%-%ds] %%-%ds %%%ds %%-%ds (%%d note%%s)\n",
sprintf(format, "%%%dc %%%dd: (%%-%ds) |%%-%ds| |%%-%ds| %%-%ds %%%ds %%-%ds (%%d note%%s)\n",
ppager->indent, ppager->max.task.id, ppager->max.task.username, ppager->max.task.status, ppager->max.task.priority, ppager->max.task.date, ppager->max.task.time, ppager->max.task.name
);
for_each_entry(ppager, pentry) {
@@ -165,6 +165,13 @@ void pit_pager_print(PPager ppager, char *entry)
for_each_entry(ppager, pentry) {
switch(ppager->type) {
case PAGER_PROJECT:
sprintf(str, "%d", PROJECT(id));
ppager->max.project.id = max(ppager->max.project.id, strlen(str));
ppager->max.project.username = max(ppager->max.project.username, strlen(PROJECT(username)));
ppager->max.project.name = max(ppager->max.project.name, strlen(PROJECT(name)));
ppager->max.project.status = max(ppager->max.project.status, strlen(PROJECT(status)));
break;
case PAGER_TASK:
sprintf(str, "%d", TASK(id));
ppager->max.task.id = max(ppager->max.task.id, strlen(str));
@@ -179,21 +186,14 @@ void pit_pager_print(PPager ppager, char *entry)
ppager->max.task.time = max(ppager->max.task.time, strlen(format_time(TASK(time))));
}
break;
case PAGER_PROJECT:
sprintf(str, "%d", ((PProject)*pentry)->id);
ppager->max.project.id = max(ppager->max.project.id, strlen(str));
ppager->max.project.username = max(ppager->max.project.username, strlen(((PProject)*pentry)->username));
ppager->max.project.name = max(ppager->max.project.name, strlen(((PProject)*pentry)->name));
ppager->max.project.status = max(ppager->max.project.status, strlen(((PProject)*pentry)->status));
break;
case PAGER_ACTION:
ppager->max.action.username = max(ppager->max.action.username, strlen(((PAction)*pentry)->username));
ppager->max.action.subject = max(ppager->max.action.subject, strlen(((PAction)*pentry)->subject));
break;
case PAGER_NOTE:
sprintf(str, "%d", NOTE(id));
ppager->max.note.id = max(ppager->max.note.id, strlen(str));
ppager->max.note.username = max(ppager->max.note.username, strlen(((PNote)*pentry)->username));
ppager->max.note.username = max(ppager->max.note.username, strlen(NOTE(username)));
break;
case PAGER_ACTION:
ppager->max.action.username = max(ppager->max.action.username, strlen(ACTION(username)));
ppager->max.action.message = max(ppager->max.action.message, strlen(ACTION(message)));
break;
default:
die("invalid pager type: %d\n", ppager->type);
@@ -246,3 +246,4 @@ void pit_pager_free(PPager ppager)
#undef TASK
#undef PROJECT
#undef ACTION
#undef NOTE

View File

@@ -29,7 +29,7 @@ typedef struct _Pager {
} task;
struct {
int username;
int subject;
int message;
} action;
struct {
int id;

View File

@@ -54,7 +54,7 @@ void pit_version();
void pit_db_load();
void pit_db_save();
void pit_db_initialize();
void pit_action(int id, char *subject, char *message);
void pit_action(PAction pa);
void pit_task_list(POptions po, PProject pp);
void pit_task_delete(int id, PProject pp);
void pit_note_list(PTask pt);

View File

@@ -3,23 +3,6 @@
#include <stdio.h>
#include "pit.h"
/*
** CREATING PROJECTS:
** pit project -c name [-s status]
**
** EDITING PROJECTS:
** pit project -e [number] [-n name] [-s status]
**
** DELETING PROJECTS:
** pit project -d [number]
**
** VIEWING PROJECT:
** pit project [[-q] number]
**
** LISTING PROJECTS:
** pit project -q [number | [-n name] [-s status]]
*/
static bool project_already_exist(char *name)
{
pit_db_load();
@@ -45,40 +28,40 @@ static int project_find_current(int id, PProject *ppp)
static void project_log_create(PProject pp, POptions po)
{
char str[256];
Action a = { pp->id, 0 };
sprintf(str, "created project %d: %s (status: %s)", pp->id, po->project.name, po->project.status);
pit_action(pp->id, "project", str);
sprintf(a.message, "created project %d: %s (status: %s)", pp->id, po->project.name, po->project.status);
pit_action(&a);
}
static void project_log_update(PProject pp, POptions po)
{
char str[256];
Action a = { pp->id, 0 };
bool empty = TRUE;
sprintf(str, "updated project %d:", pp->id);
sprintf(a.message, "updated project %d:", pp->id);
if (po->project.name) {
sprintf(str + strlen(str), " (name: %s", po->project.name);
sprintf(a.message + strlen(a.message), " (name: %s", po->project.name);
empty = FALSE;
} else {
sprintf(str + strlen(str), " %s (", pp->name);
sprintf(a.message + strlen(a.message), " %s (", pp->name);
}
if (po->project.status) {
sprintf(str + strlen(str), "%sstatus: %s)", (empty ? "" : ", "), po->project.status);
sprintf(a.message + strlen(a.message), "%sstatus: %s)", (empty ? "" : ", "), po->project.status);
}
strcat(str, ")");
pit_action(pp->id, "project", str);
strcat(a.message, ")");
pit_action(&a);
}
static void project_log_delete(int id, char *name, int number_of_tasks)
{
char str[256];
Action a = { id, 0 };
sprintf(str, "deleted project %d: %s", id, name);
sprintf(a.message, "deleted project %d: %s", id, name);
if (number_of_tasks > 0) {
sprintf(str + strlen(str), " with %d task%s", number_of_tasks, (number_of_tasks == 1 ? "" : "s"));
sprintf(a.message + strlen(a.message), " with %d task%s", number_of_tasks, (number_of_tasks == 1 ? "" : "s"));
}
pit_action(id, "project", str);
pit_action(&a);
}
static void project_list(POptions po)
@@ -147,6 +130,7 @@ static void project_update(int id, POptions po)
if (po->project.name) strncpy(pp->name, po->project.name, sizeof(pp->name) - 1);
if (po->project.status) strncpy(pp->status, po->project.status, sizeof(pp->status) - 1);
strncpy(pp->username, current_user(), sizeof(pp->username) - 1);
pit_table_mark(projects, pp->id);
project_log_update(pp, po);
@@ -203,6 +187,22 @@ static void project_parse_options(char **arg, POptions po)
}
}
/*
** CREATING PROJECTS:
** pit project -c name [-s status]
**
** EDITING PROJECTS:
** pit project -e [number] [-n name] [-s status]
**
** DELETING PROJECTS:
** pit project -d [number]
**
** VIEWING PROJECT:
** pit project [[-q] number]
**
** LISTING PROJECTS:
** pit project -q [number | [-n name] [-s status]]
*/
void pit_project(char *argv[])
{
char **arg = &argv[1];

View File

@@ -3,23 +3,6 @@
#include <stdio.h>
#include "pit.h"
/*
** CREATING TASKS:
** pit task -c name [-s status] [-p priority] [-d date] [-t time]
**
** EDITING TASKS:
** pit task -e [number] [-n name] [-s status] [-p priority] [-d date] [-t time]
**
** DELETING TASKS:
** pit task -d [number]
**
** VIEWING TASK:
** pit task [[-q] number]
**
** LISTING TASKS:
** pit task -q [number | [-n name] [-s status] [-p priority] [-d date] [-t time]]
*/
static int task_find_current(int id, PTask *ppt)
{
if (id) {
@@ -34,81 +17,65 @@ static int task_find_current(int id, PTask *ppt)
static void task_log_create(PTask pt, POptions po)
{
char str[256];
Action a = { pt->project_id, pt->id, 0 };
sprintf(str, "created task %d: %s (status: %s, priority: %s", pt->id, po->task.name, po->task.status, po->task.priority);
if (po->task.date > 0) sprintf(str + strlen(str), ", date: %s", format_date(po->task.date));
if (po->task.time > 0) sprintf(str + strlen(str), ", time: %s", format_time(po->task.time));
sprintf(str + strlen(str), ", project: %d)", pt->project_id);
pit_action(pt->id, "task", str);
sprintf(a.message, "created task %d: %s (status: %s, priority: %s", pt->id, po->task.name, po->task.status, po->task.priority);
if (po->task.date > 0) sprintf(a.message + strlen(a.message), ", date: %s", format_date(po->task.date));
if (po->task.time > 0) sprintf(a.message + strlen(a.message), ", time: %s", format_time(po->task.time));
sprintf(a.message + strlen(a.message), ", project: %d)", pt->project_id);
pit_action(&a);
}
static void task_log_update(PTask pt, POptions po)
{
char str[256];
Action a = { pt->project_id, pt->id, 0 };
bool empty = TRUE;
sprintf(str, "updated task %d:", pt->id);
sprintf(a.message, "updated task %d:", pt->id);
if (po->task.name) {
sprintf(str + strlen(str), " (name: %s", po->task.name);
sprintf(a.message + strlen(a.message), " (name: %s", po->task.name);
empty = FALSE;
} else {
sprintf(str + strlen(str), " %s (", pt->name);
sprintf(a.message + strlen(a.message), " %s (", pt->name);
}
if (po->task.status) {
sprintf(str + strlen(str), "%sstatus: %s", (empty ? "" : ", "), po->task.status);
sprintf(a.message + strlen(a.message), "%sstatus: %s", (empty ? "" : ", "), po->task.status);
empty = FALSE;
}
if (po->task.priority) {
sprintf(str + strlen(str), "%spriority: %s", (empty ? "" : ", "), po->task.priority);
sprintf(a.message + strlen(a.message), "%spriority: %s", (empty ? "" : ", "), po->task.priority);
empty = FALSE;
}
if (po->task.date) {
if (po->task.date < 0) {
sprintf(str + strlen(str), "%sdate: none", (empty ? "" : ", "));
sprintf(a.message + strlen(a.message), "%sdate: none", (empty ? "" : ", "));
} else {
sprintf(str + strlen(str), "%sdate: %s", (empty ? "" : ", "), format_date(po->task.date));
sprintf(a.message + strlen(a.message), "%sdate: %s", (empty ? "" : ", "), format_date(po->task.date));
}
empty = FALSE;
}
if (po->task.time) {
if (po->task.time < 0) {
sprintf(str + strlen(str), "%stime: none", (empty ? "" : ", "));
sprintf(a.message + strlen(a.message), "%stime: none", (empty ? "" : ", "));
} else {
sprintf(str + strlen(str), "%stime: %s", (empty ? "" : ", "), format_time(po->task.time));
sprintf(a.message + strlen(a.message), "%stime: %s", (empty ? "" : ", "), format_time(po->task.time));
}
empty = FALSE;
}
strcat(str, ")");
pit_action(pt->id, "task", str);
strcat(a.message, ")");
pit_action(&a);
}
static void task_log_delete(int id, char *name, int number_of_notes)
static void task_log_delete(int project_id, int id, char *name, int number_of_notes)
{
char str[256];
Action a = { project_id, id, 0 };
sprintf(str, "deleted task %d: %s", id, name);
sprintf(a.message, "deleted task %d: %s", id, name);
if (number_of_notes > 0) {
sprintf(str + strlen(str), " with %d note%s", number_of_notes, (number_of_notes == 1 ? "" : "s"));
}
pit_action(id, "task", str);
}
void pit_task_list(POptions po, PProject pp)
{
if (!tasks) pit_db_load();
if (tasks->number_of_records > 0) {
PPager ppager = pit_pager_initialize(PAGER_TASK, (pp ? 4 : 0), tasks->number_of_records);
if (!pp) pp = (PProject)pit_table_current(projects);
for_each_task(pt) {
if (pp && pt->project_id != pp->id)
continue;
pit_pager_print(ppager, (char *)pt);
}
pit_pager_flush(ppager);
sprintf(a.message + strlen(a.message), " with %d note%s", number_of_notes, (number_of_notes == 1 ? "" : "s"));
}
sprintf(a.message + strlen(a.message), " (project: %d)", project_id);
pit_action(&a);
}
static void task_show(int id)
@@ -173,62 +140,13 @@ static void task_update(int id, POptions po)
if (po->task.priority) strncpy(pt->priority, po->task.priority, sizeof(pt->priority) - 1);
if (po->task.date) pt->date = max(0, po->task.date);
if (po->task.time) pt->time = max(0, po->task.time);
strncpy(pt->username, current_user(), sizeof(pt->username) - 1);
pit_table_mark(tasks, pt->id);
task_log_update(pt, po);
pit_db_save();
}
/*
** A task could be deleted as standalone entity or as part of cascading project
** delete. In later case we're going to have 'pp' set and the database loaded.
*/
void pit_task_delete(int id, PProject pp)
{
PTask pt;
bool standalone = (pp == NULL);
if (standalone) pit_db_load();
id = task_find_current(id, &pt);
if (standalone) pp = (PProject)pit_table_find(projects, pt->project_id);
if (pp) {
/*
** First delete task notes if any.
*/
if (pt->number_of_notes > 0) {
for_each_note(pn) {
if (pn->task_id == id) {
pit_note_delete(pn->id, pt);
--pn; /* Make the note pointer stay since it now points to the next note. */
}
}
}
/*
** Preserve task name and number_of_notes before deleting the task since
** we need these for logging.
*/
char *deleted_name = str2str(pt->name);
int deleted_number_of_notes = pt->number_of_notes;
pt = (PTask)pit_table_delete(tasks, id);
if (pt) {
pit_table_mark(tasks, 0); /* TODO: find better current task candidate. */
task_log_delete(id, deleted_name, deleted_number_of_notes);
if (standalone) {
pp->number_of_tasks--;
pit_db_save();
}
free(deleted_name);
} else {
free(deleted_name);
die("could not delete task %d", id);
}
} else {
die("could not find project for task %d", id);
}
}
static void task_parse_options(char **arg, POptions po)
{
while(*++arg) {
@@ -254,6 +172,88 @@ static void task_parse_options(char **arg, POptions po)
}
}
void pit_task_list(POptions po, PProject pp)
{
if (!tasks) pit_db_load();
if (tasks->number_of_records > 0) {
PPager ppager = pit_pager_initialize(PAGER_TASK, (pp ? 4 : 0), tasks->number_of_records);
if (!pp) pp = (PProject)pit_table_current(projects);
for_each_task(pt) {
if (pp && pt->project_id != pp->id)
continue;
pit_pager_print(ppager, (char *)pt);
}
pit_pager_flush(ppager);
}
}
/*
** A task could be deleted as standalone entity or as part of cascading project
** delete. In later case we're going to have 'pp' set and the database loaded.
*/
void pit_task_delete(int id, PProject pp)
{
PTask pt;
bool standalone = (pp == NULL);
if (standalone) pit_db_load();
id = task_find_current(id, &pt);
if (standalone) pp = (PProject)pit_table_find(projects, pt->project_id);
if (pp) {
/*
** Preserve task name and number_of_notes before deleting the task since
** we need these for logging.
*/
char *deleted_name = str2str(pt->name);
int deleted_number_of_notes = pt->number_of_notes;
/*
** Delete task notes if any.
*/
if (pt->number_of_notes > 0) {
for_each_note(pn) {
if (pn->task_id == id) {
pit_note_delete(pn->id, pt);
--pn; /* Make the note pointer stay since it now points to the next note. */
}
}
}
pt = (PTask)pit_table_delete(tasks, id);
if (pt) {
pit_table_mark(tasks, 0); /* TODO: find better current task candidate. */
task_log_delete(pp->id, id, deleted_name, deleted_number_of_notes);
if (standalone) {
pp->number_of_tasks--;
pit_db_save();
}
free(deleted_name);
} else {
free(deleted_name);
die("could not delete task %d", id);
}
} else {
die("could not find project for task %d", id);
}
}
/*
** CREATING TASKS:
** pit task -c name [-s status] [-p priority] [-d date] [-t time]
**
** EDITING TASKS:
** pit task -e [number] [-n name] [-s status] [-p priority] [-d date] [-t time]
**
** DELETING TASKS:
** pit task -d [number]
**
** VIEWING TASK:
** pit task [[-q] number]
**
** LISTING TASKS:
** pit task -q [number | [-n name] [-s status] [-p priority] [-d date] [-t time]]
*/
void pit_task(char *argv[])
{
int number = 0;