X-Git-Url: https://git.wpitchoune.net/gitweb/?a=blobdiff_plain;f=src%2Ftw.c;h=89343a45ea8c67504dc1930f9b7059682f3993de;hb=db9c7f7e2a7bebd83de857029942ddb5497140ec;hp=6c256977c6e607613a1ee6f32abf366be3629982;hpb=1ff664c141ac890095ba33d96d28aca87f8b2ff7;p=ptask.git diff --git a/src/tw.c b/src/tw.c index 6c25697..89343a4 100644 --- a/src/tw.c +++ b/src/tw.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2013 jeanfi@gmail.com + * Copyright (C) 2012-2016 jeanfi@gmail.com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -16,20 +16,35 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA */ +#define _GNU_SOURCE #include #include #include #include +#include -#include +#include -#include #include #include "note.h" #include #include "tw.h" +/* Whether ptask check that the taskwarrior version is supported. */ +static int check_version_enabled = 1; + +struct tm *parse_time(const char *t) +{ + struct tm *tm; + + tm = malloc(sizeof(struct tm)); + memset(tm, 0, sizeof(struct tm)); + strptime(t, "%Y%m%dT%H%M%S%Z", tm); + + return tm; +} + static char *task_exec(char *opts) { FILE *f; @@ -37,6 +52,8 @@ static char *task_exec(char *opts) size_t s; char *str, *tmp, *cmd, buf[1024]; + log_fct_enter(); + cmd = malloc(strlen("task ") + strlen(opts) + 1); strcpy(cmd, "task "); strcat(cmd, opts); @@ -67,6 +84,8 @@ static char *task_exec(char *opts) if (ret == -1) log_err("pclose fails"); + log_fct_exit(); + return str; } @@ -92,7 +111,12 @@ static int task_check_version() log_debug("task version: %s", ver); - if (!strcmp(ver, "2.2.0") || !strcmp(ver, "2.0.0")) + if (!strcmp(ver, "2.2.0") + || !strcmp(ver, "2.0.0") + || !strcmp(ver, "2.3.0") + || !strcmp(ver, "2.4.0") + || !strcmp(ver, "2.4.1") + || !strcmp(ver, "2.5.0")) return 1; else return 0; @@ -102,9 +126,11 @@ static char *tw_exec(char *opts) { char *opts2; - if (!task_check_version()) { - log_err("ptask is not compatible with the installed version of" - " taskwarrior."); + if (check_version_enabled && !task_check_version()) { + log_err("ptask is not compatible with the installed version of " + "taskwarrior. The command line option -f can force " + "the usage of an unsupported version of taskwarrior " + "(risk of malfunction like damaging data)."); return NULL; } @@ -140,10 +166,107 @@ static struct json_object *task_exec_json(const char *opts) return o; } +char **json_to_tags(struct json_object *jtask) +{ + struct json_object *jtags, *jtag; + char **tags; + int n, i; + + jtags = json_object_object_get(jtask, "tags"); + + if (!jtags) + return NULL; + + + n = json_object_array_length(jtags); + + tags = malloc((n + 1) * sizeof(char *)); + + for (i = 0; i < n; i++) { + jtag = json_object_array_get_idx(jtags, i); + tags[i] = strdup(json_object_get_string(jtag)); + } + + tags[n] = NULL; + + return tags; +} + +struct task *json_to_task(struct json_object *jtask) +{ + struct task *task; + const char *urg; + struct json_object *json; + + task = malloc(sizeof(struct task)); + + json = json_object_object_get(jtask, "id"); + task->id = json_object_get_int(json); + + json = json_object_object_get(jtask, "description"); + task->description = strdup(json_object_get_string(json)); + + json = json_object_object_get(jtask, "status"); + task->status = strdup(json_object_get_string(json)); + + json = json_object_object_get(jtask, "project"); + if (json) + task->project + = strdup(json_object_get_string(json)); + else + task->project = strdup(""); + + json = json_object_object_get(jtask, "priority"); + if (json) + task->priority + = strdup(json_object_get_string(json)); + else + task->priority = strdup(""); + + json = json_object_object_get(jtask, "uuid"); + task->uuid = strdup(json_object_get_string(json)); + + json = json_object_object_get(jtask, "urgency"); + urg = json_object_get_string(json); + if (urg) + task->urgency = strdup(urg); + else + task->urgency = NULL; + + task->note = note_get(task->uuid); + + json = json_object_object_get(jtask, "entry"); + task->entry = parse_time(json_object_get_string(json)); + + json = json_object_object_get(jtask, "due"); + if (json) + task->due + = parse_time(json_object_get_string(json)); + else + task->due = NULL; + + json = json_object_object_get(jtask, "start"); + if (json) + task->start + = parse_time(json_object_get_string(json)); + else + task->start = NULL; + + json = json_object_object_get(jtask, "recur"); + if (json) + task->recur = strdup(json_object_get_string(json)); + else + task->recur = NULL; + + task->tags = json_to_tags(jtask); + + return task; +} + struct task **tw_get_all_tasks(const char *status) { int i, n; - struct json_object *jtasks, *jtask, *json; + struct json_object *jtasks, *jtask; struct task **tasks; char *opts; @@ -165,35 +288,7 @@ struct task **tw_get_all_tasks(const char *status) for (i = 0; i < n; i++) { jtask = json_object_array_get_idx(jtasks, i); - tasks[i] = malloc(sizeof(struct task)); - - json = json_object_object_get(jtask, "id"); - tasks[i]->id = json_object_get_int(json); - - json = json_object_object_get(jtask, "description"); - tasks[i]->description = strdup(json_object_get_string(json)); - - json = json_object_object_get(jtask, "status"); - tasks[i]->status = strdup(json_object_get_string(json)); - - json = json_object_object_get(jtask, "project"); - if (json) - tasks[i]->project - = strdup(json_object_get_string(json)); - else - tasks[i]->project = strdup(""); - - json = json_object_object_get(jtask, "priority"); - if (json) - tasks[i]->priority - = strdup(json_object_get_string(json)); - else - tasks[i]->priority = strdup(""); - - json = json_object_object_get(jtask, "uuid"); - tasks[i]->uuid = strdup(json_object_get_string(json)); - - tasks[i]->note = note_get(tasks[i]->uuid); + tasks[i] = json_to_task(jtask); } tasks[n] = NULL; @@ -276,6 +371,8 @@ void tw_modify_priority(const char *uuid, const char *priority) char *str; char *opts; + log_fct_enter(); + str = escape(priority); opts = malloc(1 @@ -290,15 +387,19 @@ void tw_modify_priority(const char *uuid, const char *priority) free(str); free(opts); + + log_fct_exit(); } void tw_add(const char *newdesc, const char *prj, const char *prio) { char *opts, *eprj; + log_fct_enter(); + eprj = escape(prj); - opts = malloc(strlen(" add") + opts = malloc(strlen("add") + strlen(" priority:") + 1 + strlen(" project:\\\"") @@ -309,7 +410,7 @@ void tw_add(const char *newdesc, const char *prj, const char *prio) + strlen("\"") + 1); - strcpy(opts, " add"); + strcpy(opts, "add"); if (prio && strlen(prio) == 1) { strcat(opts, " priority:"); @@ -324,15 +425,17 @@ void tw_add(const char *newdesc, const char *prj, const char *prio) strcat(opts, " \""); strcat(opts, newdesc); - strcat(opts, " \""); + strcat(opts, "\""); tw_exec(opts); free(opts); free(eprj); + + log_fct_exit(); } -void tw_done(const char *uuid) +void tw_task_done(const char *uuid) { char *opts; @@ -347,8 +450,55 @@ void tw_done(const char *uuid) free(opts); } +void tw_task_start(const char *uuid) +{ + char *opts; + + opts = malloc(1 + + strlen(uuid) + + strlen(" start") + + 1); + sprintf(opts, " %s start", uuid); + + tw_exec(opts); + + free(opts); +} + +void tw_task_stop(const char *uuid) +{ + char *opts; + + opts = malloc(1 + + strlen(uuid) + + strlen(" stop") + + 1); + sprintf(opts, " %s stop", uuid); + + tw_exec(opts); + + free(opts); +} + +void tw_task_remove(const char *uuid) +{ + char *opts; + + opts = malloc(1 + + strlen(uuid) + + strlen(" delete") + + 1); + sprintf(opts, " %s delete", uuid); + + tw_exec(opts); + + free(opts); +} + static void task_free(struct task *task) { + char **tags; + if (!task) return ; @@ -358,6 +508,20 @@ static void task_free(struct task *task) free(task->note); free(task->project); free(task->priority); + free(task->urgency); + free(task->entry); + free(task->due); + free(task->start); + free(task->recur); + + tags = task->tags; + if (tags) { + while (*tags) { + free(*tags); + tags++; + } + free(task->tags); + } free(task); } @@ -375,13 +539,36 @@ void tw_task_list_free(struct task **tasks) free(tasks); } -static struct project *project_list_get(struct project **prj, const char *name) +static void project_free(struct project *p) { - while (*prj) - if (!strcmp((*prj)->name, name)) - return *prj; - else - prj++; + if (!p) + return ; + + free(p->name); + free(p); +} + +void tw_project_list_free(struct project **prjs) +{ + struct project **cur; + + if (!prjs) + return ; + + for (cur = prjs; *cur; cur++) + project_free(*cur); + + free(prjs); +} + +static struct project *project_list_get(struct project **prjs, const char *name) +{ + struct project **cur; + + for (cur = prjs; *cur; cur++) + if (!strcmp((*cur)->name, name)) + return *cur; + return NULL; } @@ -397,16 +584,52 @@ static struct project *project_new(const char *name, int count) return prj; } +static int projects_length(struct project **list) +{ + int n; + + if (!list) + return 0; + + n = 0; + while (*list) { + n++; + list++; + } + + return n; +} + +static struct project **projects_add(struct project **list, void *item) +{ + int n; + struct project **result; + + n = projects_length(list); + + result = (struct project **)malloc + ((n + 1 + 1) * sizeof(struct project *)); + + if (list) + memcpy(result, list, n * sizeof(struct project *)); + + result[n] = item; + result[n + 1] = NULL; + + return result; +} + struct project **tw_get_projects(struct task **tasks) { struct task **t_cur; struct project **prjs, **tmp, *prj; const char *prj_name; - log_debug("tw_get_projects()"); + log_fct_enter(); - prjs = malloc(sizeof(struct project *)); - *prjs = NULL; + prjs = malloc(2 * sizeof(struct project *)); + prjs[0] = project_new("ALL", 0); + prjs[1] = NULL; for (t_cur = tasks; *t_cur; t_cur++) { prj_name = (*t_cur)->project; @@ -415,13 +638,21 @@ struct project **tw_get_projects(struct task **tasks) prj->count++; } else { prj = project_new(prj_name, 1); - - tmp = (struct project **)list_add((void **)prjs, prj); - - list_free((void **)prjs); + + tmp = projects_add(prjs, prj); + + free(prjs); prjs = tmp; } + prjs[0]->count++; } + log_fct_exit(); + return prjs; } + +void tw_enable_check_version(int e) +{ + check_version_enabled = e; +}