diff --git a/src/action.c b/src/action.c index c400154..bdd6207 100644 --- a/src/action.c +++ b/src/action.c @@ -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[]) diff --git a/src/db.c b/src/db.c index c1def52..25c6b86 100644 --- a/src/db.c +++ b/src/db.c @@ -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(); } diff --git a/src/note.c b/src/note.c index b097996..a47aaf1 100644 --- a/src/note.c +++ b/src/note.c @@ -3,85 +3,40 @@ #include #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); diff --git a/src/object.h b/src/object.h index 4b9b03d..02f99cc 100644 --- a/src/object.h +++ b/src/object.h @@ -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? */ diff --git a/src/pager.c b/src/pager.c index 2b1e40d..58aab8c 100644 --- a/src/pager.c +++ b/src/pager.c @@ -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 diff --git a/src/pager.h b/src/pager.h index abeae2c..47c84b6 100644 --- a/src/pager.h +++ b/src/pager.h @@ -29,7 +29,7 @@ typedef struct _Pager { } task; struct { int username; - int subject; + int message; } action; struct { int id; diff --git a/src/pit.h b/src/pit.h index 6062c97..17346d2 100644 --- a/src/pit.h +++ b/src/pit.h @@ -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); diff --git a/src/project.c b/src/project.c index 7e196e5..0fd9e19 100644 --- a/src/project.c +++ b/src/project.c @@ -3,23 +3,6 @@ #include #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]; diff --git a/src/task.c b/src/task.c index ed46561..e92caa3 100644 --- a/src/task.c +++ b/src/task.c @@ -3,23 +3,6 @@ #include #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; diff --git a/test/pit_date.rb b/test/pit_date.rb new file mode 100644 index 0000000..8dc5083 --- /dev/null +++ b/test/pit_date.rb @@ -0,0 +1,54 @@ +module Pit + module Date + + def should_parse_alpha_dates + `#{@pit} project -c test` + `#{@pit} task -c test -d "dec 1, 2011 19:30"` + `#{@pit} task`.should.match /Dec 01, 2011 19:30/m + `#{@pit} task -c test -d "dec 1, 2012 1:15pm"` + `#{@pit} task`.should.match /Dec 01, 2012 13:15/m + `#{@pit} task -c test -d "dec 1, 2013 11"` + `#{@pit} task`.should.match /Dec 01, 2013 11:00/m + `#{@pit} task -c test -d "dec 1, 2013 7pm"` + `#{@pit} task`.should.match /Dec 01, 2013 19:00/m + `#{@pit} task -c test -d "dec 1, 2013"` + `#{@pit} task`.should.match /Dec 01, 2013 /m + `#{@pit} task -c test -d "dec 1 5:55"` + `#{@pit} task`.should.match /Dec 01, #{Time.now.year} 05:55/m + `#{@pit} task -c test -d "dec 1 2:40pm"` + `#{@pit} task`.should.match /Dec 01, #{Time.now.year} 14:40/m + # `#{@pit} task -c test -d "dec 1 5"` + # `#{@pit} task`.should.match /Dec 01, #{Time.now.year} 05:00/m + # `#{@pit} task -c test -d "dec 1 3pm"` + # `#{@pit} task`.should.match /Dec 01, #{Time.now.year} 15:00/m + `#{@pit} task -c test -d "dec 1"` + `#{@pit} task`.should.match /Dec 01, #{Time.now.year} /m + end + + def should_parse_slash_dates + `#{@pit} project -c test` + `#{@pit} task -c test -d "12/1/2011 19:30"` + `#{@pit} task`.should.match /Dec 01, 2011 19:30/m + `#{@pit} task -c test -d "12/1/2012 1:15pm"` + `#{@pit} task`.should.match /Dec 01, 2012 13:15/m + `#{@pit} task -c test -d "12/1/2013 11"` + `#{@pit} task`.should.match /Dec 01, 2013 11:00/m + `#{@pit} task -c test -d "12/1/2013 7pm"` + `#{@pit} task`.should.match /Dec 01, 2013 19:00/m + `#{@pit} task -c test -d "12/1/2013"` + `#{@pit} task`.should.match /Dec 01, 2013 /m + `#{@pit} task -c test -d "12/1 5:55"` + `#{@pit} task`.should.match /Dec 01, #{Time.now.year} 05:55/m + `#{@pit} task -c test -d "12/1 2:40pm"` + `#{@pit} task`.should.match /Dec 01, #{Time.now.year} 14:40/m + # `#{@pit} task -c test -d "12/1 5"` + # `#{@pit} task`.should.match /Dec 01, #{Time.now.year} 05:00/m + # `#{@pit} task -c test -d "12/1 3pm"` + # `#{@pit} task`.should.match /Dec 01, #{Time.now.year} 15:00/m + `#{@pit} task -c test -d "12/1"` + `#{@pit} task`.should.match /Dec 01, #{Time.now.year} /m + end + end +end + + \ No newline at end of file diff --git a/test/pit_note.rb b/test/pit_note.rb new file mode 100644 index 0000000..dfd46cc --- /dev/null +++ b/test/pit_note.rb @@ -0,0 +1,16 @@ +module Pit + module Note + def should_not_segfault + `#{@pit} p -c test` + `#{@pit} t -c test` + 10.times do |i| + `#{@pit} n -c note#{i+1}` + end + 5.times do |i| + `#{@pit} n -d #{i+1}` + end + `#{@pit} n -c note11` + `#{@pit} l`.should.match /created note 11/m + end + end +end diff --git a/test/pit_project.rb b/test/pit_project.rb new file mode 100644 index 0000000..79b34cb --- /dev/null +++ b/test/pit_project.rb @@ -0,0 +1,30 @@ +module Pit + module Project + + def should_create_project + `#{@pit} project -c test` + `#{@pit} project`.should.match /\* 1: \(.+\) \|active| test \(0 tasks\)/ + end + + def should_do_cascading_delete + def should_do_cascading_delete + 3.times do |p| + `#{@pit} project -c project#{p}` + 3.times do |t| + `#{@pit} task -c project#{p}_task#{t}` + 3.times do |n| + `#{@pit} note -c project#{p}_task#{t}_note#{n}` + end + end + end + `#{@pit} project`.should.match /\* 3:/m + `#{@pit} project -d` + `#{@pit} project`.should_not.match /[\s|\*] 3:/m + `#{@pit} project`.should.match /\s 2:/m + `#{@pit} project -d 2` + `#{@pit} project`.should_not.match /[\s|\*] 2:/m + `#{@pit} project`.should.match /\s 1:/m + end + end + end +end diff --git a/test/pit_task.rb b/test/pit_task.rb new file mode 100644 index 0000000..863c8d5 --- /dev/null +++ b/test/pit_task.rb @@ -0,0 +1,21 @@ +module Pit + module Task + + def should_do_cascading_delete + `#{@pit} project -c project` + 5.times do |t| + `#{@pit} task -c task#{t}` + 5.times do |n| + `#{@pit} note -c task#{t}_note#{n}` + end + end + `#{@pit} task`.should.match /\* 5:/m + `#{@pit} note -e 21 hello21` + `#{@pit} note -d 21` + `#{@pit} note -e 22 hello22` + `#{@pit} note -d 22` + `#{@pit} task -d` + `#{@pit} task`.should_not.match /[\s|\*] 5:/m + end + end +end diff --git a/test/pit_test.rb b/test/pit_test.rb index 95933f7..99a8bc8 100755 --- a/test/pit_test.rb +++ b/test/pit_test.rb @@ -2,6 +2,10 @@ # BASE = File.dirname(File.expand_path(__FILE__)) require "#{BASE}/pit_should" +require "#{BASE}/pit_date" +require "#{BASE}/pit_project" +require "#{BASE}/pit_task" +require "#{BASE}/pit_note" class PitTestRunner def self.run @@ -26,55 +30,12 @@ class PitTestRunner def before `#{@pit} init -f` - `#{@pit} project -c test` - end - - def should_parse_alpha_dates - `#{@pit} task -c test -d "dec 1, 2011 19:30"` - `#{@pit} task`.should.match /Dec 01, 2011 19:30/m - `#{@pit} task -c test -d "dec 1, 2012 1:15pm"` - `#{@pit} task`.should.match /Dec 01, 2012 13:15/m - `#{@pit} task -c test -d "dec 1, 2013 11"` - `#{@pit} task`.should.match /Dec 01, 2013 11:00/m - `#{@pit} task -c test -d "dec 1, 2013 7pm"` - `#{@pit} task`.should.match /Dec 01, 2013 19:00/m - `#{@pit} task -c test -d "dec 1, 2013"` - `#{@pit} task`.should.match /Dec 01, 2013 /m - `#{@pit} task -c test -d "dec 1 5:55"` - `#{@pit} task`.should.match /Dec 01, #{Time.now.year} 05:55/m - `#{@pit} task -c test -d "dec 1 2:40pm"` - `#{@pit} task`.should.match /Dec 01, #{Time.now.year} 14:40/m - # `#{@pit} task -c test -d "dec 1 5"` - # `#{@pit} task`.should.match /Dec 01, #{Time.now.year} 05:00/m - # `#{@pit} task -c test -d "dec 1 3pm"` - # `#{@pit} task`.should.match /Dec 01, #{Time.now.year} 15:00/m - `#{@pit} task -c test -d "dec 1"` - `#{@pit} task`.should.match /Dec 01, #{Time.now.year} /m - end - - def should_parse_slash_dates - `#{@pit} task -c test -d "12/1/2011 19:30"` - `#{@pit} task`.should.match /Dec 01, 2011 19:30/m - `#{@pit} task -c test -d "12/1/2012 1:15pm"` - `#{@pit} task`.should.match /Dec 01, 2012 13:15/m - `#{@pit} task -c test -d "12/1/2013 11"` - `#{@pit} task`.should.match /Dec 01, 2013 11:00/m - `#{@pit} task -c test -d "12/1/2013 7pm"` - `#{@pit} task`.should.match /Dec 01, 2013 19:00/m - `#{@pit} task -c test -d "12/1/2013"` - `#{@pit} task`.should.match /Dec 01, 2013 /m - `#{@pit} task -c test -d "12/1 5:55"` - `#{@pit} task`.should.match /Dec 01, #{Time.now.year} 05:55/m - `#{@pit} task -c test -d "12/1 2:40pm"` - `#{@pit} task`.should.match /Dec 01, #{Time.now.year} 14:40/m - # `#{@pit} task -c test -d "12/1 5"` - # `#{@pit} task`.should.match /Dec 01, #{Time.now.year} 05:00/m - # `#{@pit} task -c test -d "12/1 3pm"` - # `#{@pit} task`.should.match /Dec 01, #{Time.now.year} 15:00/m - `#{@pit} task -c test -d "12/1"` - `#{@pit} task`.should.match /Dec 01, #{Time.now.year} /m end + include Pit::Date + include Pit::Project + include Pit::Task + include Pit::Note end PitTestRunner.run diff --git a/test/test.pitfile b/test/test.pitfile deleted file mode 100644 index 50e686d..0000000 Binary files a/test/test.pitfile and /dev/null differ